diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 92ceb20cb3e4..b8c2dc773518 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -3858,7 +3858,12 @@ bool Document::GetAllowPlugins() { void Document::EnsureL10n() { if (!mDocumentL10n) { - mDocumentL10n = DocumentL10n::Create(this); + Element* elem = GetDocumentElement(); + if (NS_WARN_IF(!elem)) { + return; + } + bool isSync = elem->HasAttr(kNameSpaceID_None, nsGkAtoms::datal10nsync); + mDocumentL10n = DocumentL10n::Create(this, isSync); MOZ_ASSERT(mDocumentL10n); } } diff --git a/dom/l10n/DOMLocalization.cpp b/dom/l10n/DOMLocalization.cpp index 68993788df34..bcd048c2b7ef 100644 --- a/dom/l10n/DOMLocalization.cpp +++ b/dom/l10n/DOMLocalization.cpp @@ -32,8 +32,21 @@ NS_IMPL_RELEASE_INHERITED(DOMLocalization, Localization) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMLocalization) NS_INTERFACE_MAP_END_INHERITING(Localization) -DOMLocalization::DOMLocalization(nsIGlobalObject* aGlobal) - : Localization(aGlobal) { +/* static */ +already_AddRefed DOMLocalization::Create( + nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator) { + RefPtr domLoc = + new DOMLocalization(aGlobal, aSync, aBundleGenerator); + + domLoc->Init(); + + return domLoc.forget(); +} + +DOMLocalization::DOMLocalization(nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator) + : Localization(aGlobal, aSync, aBundleGenerator) { mMutations = new L10nMutations(this); } @@ -47,13 +60,14 @@ already_AddRefed DOMLocalization::Constructor( return nullptr; } - RefPtr domLoc = new DOMLocalization(global); + RefPtr domLoc = + DOMLocalization::Create(global, aSync, aBundleGenerator); if (aResourceIds.Length()) { domLoc->AddResourceIds(aResourceIds); } - domLoc->Activate(aSync, true, aBundleGenerator); + domLoc->Activate(true); return domLoc.forget(); } diff --git a/dom/l10n/DOMLocalization.h b/dom/l10n/DOMLocalization.h index 3cceecb3439c..3f0a5ffc4d10 100644 --- a/dom/l10n/DOMLocalization.h +++ b/dom/l10n/DOMLocalization.h @@ -23,7 +23,9 @@ class DOMLocalization : public intl::Localization { NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMLocalization, Localization) - explicit DOMLocalization(nsIGlobalObject* aGlobal); + static already_AddRefed Create( + nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator); void Destroy(); @@ -104,6 +106,8 @@ class DOMLocalization : public intl::Localization { } protected: + explicit DOMLocalization(nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator); virtual ~DOMLocalization(); void OnChange() override; void DisconnectMutations(); diff --git a/dom/l10n/DocumentL10n.cpp b/dom/l10n/DocumentL10n.cpp index 442729b0e14d..0781e40e560c 100644 --- a/dom/l10n/DocumentL10n.cpp +++ b/dom/l10n/DocumentL10n.cpp @@ -30,8 +30,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DocumentL10n) NS_INTERFACE_MAP_END_INHERITING(DOMLocalization) /* static */ -RefPtr DocumentL10n::Create(Document* aDocument) { - RefPtr l10n = new DocumentL10n(aDocument); +RefPtr DocumentL10n::Create(Document* aDocument, + const bool aSync) { + RefPtr l10n = new DocumentL10n(aDocument, aSync); if (!l10n->Init()) { return nullptr; @@ -39,14 +40,15 @@ RefPtr DocumentL10n::Create(Document* aDocument) { return l10n.forget(); } -DocumentL10n::DocumentL10n(Document* aDocument) - : DOMLocalization(aDocument->GetScopeObject()), +DocumentL10n::DocumentL10n(Document* aDocument, const bool aSync) + : DOMLocalization(aDocument->GetScopeObject(), aSync, {}), mDocument(aDocument), - mState(DocumentL10nState::Uninitialized) { + mState(DocumentL10nState::Constructed) { mContentSink = do_QueryInterface(aDocument->GetCurrentContentSink()); } bool DocumentL10n::Init() { + DOMLocalization::Init(); ErrorResult rv; mReady = Promise::Create(mGlobal, rv); if (NS_WARN_IF(rv.Failed())) { @@ -55,30 +57,6 @@ bool DocumentL10n::Init() { return true; } -void DocumentL10n::Activate(const bool aLazy) { - if (mState > DocumentL10nState::Uninitialized) { - return; - } - - Element* elem = mDocument->GetDocumentElement(); - if (NS_WARN_IF(!elem)) { - return; - } - bool isSync = elem->HasAttr(kNameSpaceID_None, nsGkAtoms::datal10nsync); - - if (aLazy) { - if (isSync) { - NS_WARNING( - "Document localization initialized lazy, data-l10n-sync attribute " - "has no effect."); - } - DOMLocalization::Activate(false, true, {}); - } else { - DOMLocalization::Activate(isSync, true, {}); - } - mState = DocumentL10nState::Activated; -} - JSObject* DocumentL10n::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { return DocumentL10n_Binding::Wrap(aCx, this, aGivenProto); @@ -165,8 +143,8 @@ void DocumentL10n::TriggerInitialTranslation() { } already_AddRefed DocumentL10n::TranslateDocument(ErrorResult& aRv) { - MOZ_ASSERT(mState == DocumentL10nState::Activated, - "This method should be called only from Activated state."); + MOZ_ASSERT(mState == DocumentL10nState::Constructed, + "This method should be called only from Constructed state."); RefPtr promise = Promise::Create(mGlobal, aRv); Element* elem = mDocument->GetDocumentElement(); diff --git a/dom/l10n/DocumentL10n.h b/dom/l10n/DocumentL10n.h index 8dafd86be94f..f80b799e41ec 100644 --- a/dom/l10n/DocumentL10n.h +++ b/dom/l10n/DocumentL10n.h @@ -15,10 +15,7 @@ namespace dom { enum class DocumentL10nState { // State set when the DocumentL10n gets constructed. - Uninitialized = 0, - - // State set when the DocumentL10n is activated and ready to be used. - Activated, + Constructed = 0, // State set when the initial translation got triggered. This happens // if DocumentL10n was constructed during parsing of the document. @@ -47,13 +44,11 @@ class DocumentL10n final : public DOMLocalization { NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentL10n, DOMLocalization) - static RefPtr Create(Document* aDocument); - - void Activate(const bool aLazy); + static RefPtr Create(Document* aDocument, const bool aSync); protected: - explicit DocumentL10n(Document* aDocument); - bool Init(); + explicit DocumentL10n(Document* aDocument, const bool aSync); + bool Init() override; virtual ~DocumentL10n() = default; diff --git a/intl/l10n/Localization.cpp b/intl/l10n/Localization.cpp index acf06e6d2095..c3eec67b0074 100644 --- a/intl/l10n/Localization.cpp +++ b/intl/l10n/Localization.cpp @@ -50,20 +50,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Localization) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_END -Localization::Localization(nsIGlobalObject* aGlobal) - : mGlobal(aGlobal), mIsSync(false) { - nsCOMPtr jsm = - do_ImportModule("resource://gre/modules/Localization.jsm"); - MOZ_RELEASE_ASSERT(jsm); +/* static */ +already_AddRefed Localization::Create( + nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator) { + RefPtr loc = new Localization(aGlobal, aSync, aBundleGenerator); - Unused << jsm->GetLocalization(getter_AddRefs(mLocalization)); - MOZ_RELEASE_ASSERT(mLocalization); + loc->Init(); + + return loc.forget(); } -void Localization::Activate(const bool aSync, const bool aEager, - const BundleGenerator& aBundleGenerator) { - AutoJSContext cx; - +Localization::Localization(nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator) + : mGlobal(aGlobal), mIsSync(aSync) { if (aBundleGenerator.mGenerateBundles.WasPassed()) { GenerateBundles& generateBundles = aBundleGenerator.mGenerateBundles.Value(); @@ -75,6 +75,23 @@ void Localization::Activate(const bool aSync, const bool aEager, mGenerateBundlesSync.setObject(*generateBundlesSync.CallbackOrNull()); } mIsSync = aSync; +} + +bool Localization::Init() { + RegisterObservers(); + + return true; +} + +void Localization::Activate(const bool aEager) { + nsCOMPtr jsm = + do_ImportModule("resource://gre/modules/Localization.jsm"); + MOZ_RELEASE_ASSERT(jsm); + + Unused << jsm->GetLocalization(getter_AddRefs(mLocalization)); + MOZ_RELEASE_ASSERT(mLocalization); + + AutoJSContext cx; JS::Rooted generateBundlesJS(cx, mGenerateBundles); JS::Rooted generateBundlesSyncJS(cx, mGenerateBundlesSync); @@ -84,7 +101,6 @@ void Localization::Activate(const bool aSync, const bool aEager, &bundlesJS); mBundles.set(bundlesJS); - RegisterObservers(); mozilla::HoldJSObjects(this); } @@ -98,13 +114,14 @@ already_AddRefed Localization::Constructor( return nullptr; } - RefPtr loc = new Localization(global); + RefPtr loc = + Localization::Create(global, aSync, aBundleGenerator); if (aResourceIds.Length()) { loc->AddResourceIds(aResourceIds); } - loc->Activate(aSync, true, aBundleGenerator); + loc->Activate(true); return loc.forget(); } @@ -228,6 +245,9 @@ uint32_t Localization::RemoveResourceIds( already_AddRefed Localization::FormatValue( JSContext* aCx, const nsACString& aId, const Optional& aArgs, ErrorResult& aRv) { + if (!mLocalization) { + Activate(false); + } JS::Rooted args(aCx); if (aArgs.WasPassed()) { @@ -254,6 +274,9 @@ void Localization::SetIsSync(const bool aIsSync) { mIsSync = aIsSync; } already_AddRefed Localization::FormatValues( JSContext* aCx, const Sequence& aKeys, ErrorResult& aRv) { + if (!mLocalization) { + Activate(false); + } nsTArray jsKeys; SequenceRooter rooter(aCx, &jsKeys); for (auto& key : aKeys) { @@ -278,6 +301,9 @@ already_AddRefed Localization::FormatValues( already_AddRefed Localization::FormatMessages( JSContext* aCx, const Sequence& aKeys, ErrorResult& aRv) { + if (!mLocalization) { + Activate(false); + } nsTArray jsKeys; SequenceRooter rooter(aCx, &jsKeys); for (auto& key : aKeys) { @@ -308,6 +334,9 @@ void Localization::FormatValueSync(JSContext* aCx, const nsACString& aId, "Can't use formatValueSync when state is async."); return; } + if (!mLocalization) { + Activate(false); + } JS::Rooted args(aCx); if (aArgs.WasPassed()) { @@ -333,6 +362,9 @@ void Localization::FormatValuesSync(JSContext* aCx, "Can't use formatValuesSync when state is async."); return; } + if (!mLocalization) { + Activate(false); + } nsTArray jsKeys; SequenceRooter rooter(aCx, &jsKeys); for (auto& key : aKeys) { @@ -358,6 +390,9 @@ void Localization::FormatMessagesSync(JSContext* aCx, "Can't use formatMessagesSync when state is async."); return; } + if (!mLocalization) { + Activate(false); + } nsTArray jsKeys; SequenceRooter rooter(aCx, &jsKeys); for (auto& key : aKeys) { diff --git a/intl/l10n/Localization.h b/intl/l10n/Localization.h index 8e00813ced26..47519b727349 100644 --- a/intl/l10n/Localization.h +++ b/intl/l10n/Localization.h @@ -32,9 +32,11 @@ class Localization : public nsIObserver, nsIObserver) NS_DECL_NSIOBSERVER - explicit Localization(nsIGlobalObject* aGlobal); - void Activate(const bool aSync, const bool aEager, - const BundleGenerator& aBundleGenerator); + static already_AddRefed Create( + nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator); + + void Activate(const bool aEager); void Destroy(); @@ -84,6 +86,10 @@ class Localization : public nsIObserver, ErrorResult& aRv); protected: + Localization(nsIGlobalObject* aGlobal, const bool aSync, + const BundleGenerator& aBundleGenerator); + virtual bool Init(); + virtual ~Localization(); void RegisterObservers(); virtual void OnChange();