diff --git a/intl/l10n/DocumentL10n.cpp b/intl/l10n/DocumentL10n.cpp index a98928719536..7832963bc1b4 100644 --- a/intl/l10n/DocumentL10n.cpp +++ b/intl/l10n/DocumentL10n.cpp @@ -16,6 +16,12 @@ #include "nsContentUtils.h" #include "xpcprivate.h" +#define INTL_APP_LOCALES_CHANGED "intl:app-locales-changed" + +#define L10N_PSEUDO_PREF "intl.l10n.pseudo" + +static const char* kObservedPrefs[] = {L10N_PSEUDO_PREF, nullptr}; + namespace mozilla { namespace dom { @@ -63,15 +69,28 @@ PromiseResolver::~PromiseResolver() { mPromise = nullptr; } NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DocumentL10n, mDocument, mDOMLocalization, mContentSink, mReady) -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DocumentL10n, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DocumentL10n, Release) +NS_IMPL_CYCLE_COLLECTING_ADDREF(DocumentL10n) +NS_IMPL_CYCLE_COLLECTING_RELEASE(DocumentL10n) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DocumentL10n) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +NS_INTERFACE_MAP_END DocumentL10n::DocumentL10n(Document* aDocument) : mDocument(aDocument), mState(DocumentL10nState::Initialized) { mContentSink = do_QueryInterface(aDocument->GetCurrentContentSink()); } -DocumentL10n::~DocumentL10n() {} +DocumentL10n::~DocumentL10n() { + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, INTL_APP_LOCALES_CHANGED); + } + + Preferences::RemoveObservers(this, kObservedPrefs); +} bool DocumentL10n::Init(nsTArray& aResourceIds) { nsCOMPtr jsm = @@ -105,13 +124,41 @@ bool DocumentL10n::Init(nsTArray& aResourceIds) { // DOMLocalization to allow it to retranslate // the document when locale changes or pseudolocalization // gets turned on. - if (NS_FAILED(mDOMLocalization->RegisterObservers())) { - return false; - } + RegisterObservers(); return true; } +void DocumentL10n::RegisterObservers() { + DebugOnly rv = Preferences::AddWeakObservers(this, kObservedPrefs); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Adding observers failed."); + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->AddObserver(this, INTL_APP_LOCALES_CHANGED, true); + } +} + +NS_IMETHODIMP +DocumentL10n::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + if (!strcmp(aTopic, INTL_APP_LOCALES_CHANGED)) { + if (mDOMLocalization) { + mDOMLocalization->OnChange(); + } + } else { + MOZ_ASSERT(!strcmp("nsPref:changed", aTopic)); + nsDependentString pref(aData); + if (pref.EqualsLiteral(L10N_PSEUDO_PREF)) { + if (mDOMLocalization) { + mDOMLocalization->OnChange(); + } + } + } + + return NS_OK; +} + void DocumentL10n::Destroy() { if (mDOMLocalization) { Element* elem = mDocument->GetDocumentElement(); diff --git a/intl/l10n/DocumentL10n.h b/intl/l10n/DocumentL10n.h index 707b273952fd..a4ae3e9f39e7 100644 --- a/intl/l10n/DocumentL10n.h +++ b/intl/l10n/DocumentL10n.h @@ -7,16 +7,18 @@ #ifndef mozilla_dom_DocumentL10n_h #define mozilla_dom_DocumentL10n_h +#include "mozIDOMLocalization.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIContentSink.h" +#include "nsINode.h" +#include "nsIObserver.h" +#include "nsWrapperCache.h" +#include "nsWeakReference.h" #include "js/TypeDecls.h" #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/BindingDeclarations.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" #include "mozilla/dom/Document.h" -#include "nsIContentSink.h" -#include "nsINode.h" -#include "mozIDOMLocalization.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/PromiseNativeHandler.h" @@ -57,10 +59,14 @@ enum class DocumentL10nState { * instance of mozIDOMLocalization and maintains a single promise * which gets resolved the first time the document gets translated. */ -class DocumentL10n final : public nsWrapperCache { +class DocumentL10n final : public nsIObserver, + public nsSupportsWeakReference, + public nsWrapperCache { public: - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DocumentL10n) - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DocumentL10n) + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(DocumentL10n, + nsIObserver) + NS_DECL_NSIOBSERVER public: explicit DocumentL10n(Document* aDocument); @@ -77,6 +83,7 @@ class DocumentL10n final : public nsWrapperCache { nsCOMPtr mContentSink; already_AddRefed MaybeWrapPromise(Promise* aPromise); + void RegisterObservers(); public: Document* GetParentObject() const { return mDocument; }; diff --git a/intl/l10n/mozIDOMLocalization.idl b/intl/l10n/mozIDOMLocalization.idl index 5823391efde0..536b45835135 100644 --- a/intl/l10n/mozIDOMLocalization.idl +++ b/intl/l10n/mozIDOMLocalization.idl @@ -14,7 +14,7 @@ interface mozIDOMLocalization : nsISupports { unsigned long addResourceIds(in Array resourceIds, in bool aEager); unsigned long removeResourceIds(in Array resourceIds); - void registerObservers(); + void onChange(); Promise formatMessages(in Array aKeys); Promise formatValues(in Array aKeys);