зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1546432 - Migrate DocumentL10n to use dom::l10n::Mutations. r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D28981 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
fbc6e0304a
Коммит
2ee19983ae
|
@ -7885,10 +7885,6 @@ void Document::Destroy() {
|
||||||
|
|
||||||
mIsGoingAway = true;
|
mIsGoingAway = true;
|
||||||
|
|
||||||
if (mDocumentL10n) {
|
|
||||||
mDocumentL10n->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptLoader()->Destroy();
|
ScriptLoader()->Destroy();
|
||||||
SetScriptGlobalObject(nullptr);
|
SetScriptGlobalObject(nullptr);
|
||||||
RemovedFromDocShell();
|
RemovedFromDocShell();
|
||||||
|
|
|
@ -224,10 +224,6 @@ DOMInterfaces = {
|
||||||
'headerFile': 'mozilla/dom/DeviceMotionEvent.h',
|
'headerFile': 'mozilla/dom/DeviceMotionEvent.h',
|
||||||
},
|
},
|
||||||
|
|
||||||
'DocumentL10n': {
|
|
||||||
'implicitJSContext': ['translateFragment'],
|
|
||||||
},
|
|
||||||
|
|
||||||
'DominatorTree': {
|
'DominatorTree': {
|
||||||
'nativeType': 'mozilla::devtools::DominatorTree'
|
'nativeType': 'mozilla::devtools::DominatorTree'
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
#include "js/JSON.h" // JS_ParseJSON
|
#include "js/JSON.h" // JS_ParseJSON
|
||||||
#include "mozilla/dom/DocumentL10n.h"
|
#include "mozilla/dom/DocumentL10n.h"
|
||||||
#include "mozilla/dom/DocumentL10nBinding.h"
|
#include "mozilla/dom/DocumentL10nBinding.h"
|
||||||
#include "mozilla/dom/Element.h"
|
|
||||||
#include "mozilla/dom/L10nUtilsBinding.h"
|
#include "mozilla/dom/L10nUtilsBinding.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/dom/l10n/DOMOverlays.h"
|
#include "mozilla/dom/l10n/DOMOverlays.h"
|
||||||
|
#include "mozilla/intl/LocaleService.h"
|
||||||
#include "nsQueryObject.h"
|
#include "nsQueryObject.h"
|
||||||
|
#include "nsIScriptError.h"
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
#include "nsImportModule.h"
|
#include "nsImportModule.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
@ -27,6 +29,8 @@
|
||||||
static const char* kObservedPrefs[] = {L10N_PSEUDO_PREF, INTL_UI_DIRECTION_PREF,
|
static const char* kObservedPrefs[] = {L10N_PSEUDO_PREF, INTL_UI_DIRECTION_PREF,
|
||||||
nullptr};
|
nullptr};
|
||||||
|
|
||||||
|
using namespace mozilla::intl;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
@ -51,8 +55,24 @@ void PromiseResolver::RejectedCallback(JSContext* aCx,
|
||||||
|
|
||||||
PromiseResolver::~PromiseResolver() { mPromise = nullptr; }
|
PromiseResolver::~PromiseResolver() { mPromise = nullptr; }
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DocumentL10n, mDocument, mDOMLocalization,
|
NS_IMPL_CYCLE_COLLECTION_CLASS(DocumentL10n)
|
||||||
mContentSink, mReady)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DocumentL10n)
|
||||||
|
tmp->DisconnectMutations();
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMutations)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMLocalization)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContentSink)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReady)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DocumentL10n)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMutations)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMLocalization)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentSink)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReady)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DocumentL10n)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DocumentL10n)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(DocumentL10n)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DocumentL10n)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(DocumentL10n)
|
||||||
|
@ -66,6 +86,7 @@ NS_INTERFACE_MAP_END
|
||||||
DocumentL10n::DocumentL10n(Document* aDocument)
|
DocumentL10n::DocumentL10n(Document* aDocument)
|
||||||
: mDocument(aDocument), mState(DocumentL10nState::Initialized) {
|
: mDocument(aDocument), mState(DocumentL10nState::Initialized) {
|
||||||
mContentSink = do_QueryInterface(aDocument->GetCurrentContentSink());
|
mContentSink = do_QueryInterface(aDocument->GetCurrentContentSink());
|
||||||
|
mMutations = new mozilla::dom::l10n::Mutations(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentL10n::~DocumentL10n() {
|
DocumentL10n::~DocumentL10n() {
|
||||||
|
@ -75,6 +96,15 @@ DocumentL10n::~DocumentL10n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Preferences::RemoveObservers(this, kObservedPrefs);
|
Preferences::RemoveObservers(this, kObservedPrefs);
|
||||||
|
|
||||||
|
DisconnectMutations();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentL10n::DisconnectMutations() {
|
||||||
|
if (mMutations) {
|
||||||
|
mDocument->RemoveMutationObserver(mMutations);
|
||||||
|
mMutations->Disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DocumentL10n::Init(nsTArray<nsString>& aResourceIds) {
|
bool DocumentL10n::Init(nsTArray<nsString>& aResourceIds) {
|
||||||
|
@ -128,32 +158,19 @@ NS_IMETHODIMP
|
||||||
DocumentL10n::Observe(nsISupports* aSubject, const char* aTopic,
|
DocumentL10n::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
const char16_t* aData) {
|
const char16_t* aData) {
|
||||||
if (!strcmp(aTopic, INTL_APP_LOCALES_CHANGED)) {
|
if (!strcmp(aTopic, INTL_APP_LOCALES_CHANGED)) {
|
||||||
if (mDOMLocalization) {
|
OnChange();
|
||||||
mDOMLocalization->OnChange();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(!strcmp("nsPref:changed", aTopic));
|
MOZ_ASSERT(!strcmp("nsPref:changed", aTopic));
|
||||||
nsDependentString pref(aData);
|
nsDependentString pref(aData);
|
||||||
if (pref.EqualsLiteral(L10N_PSEUDO_PREF) ||
|
if (pref.EqualsLiteral(L10N_PSEUDO_PREF) ||
|
||||||
pref.EqualsLiteral(INTL_UI_DIRECTION_PREF)) {
|
pref.EqualsLiteral(INTL_UI_DIRECTION_PREF)) {
|
||||||
if (mDOMLocalization) {
|
OnChange();
|
||||||
mDOMLocalization->OnChange();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentL10n::Destroy() {
|
|
||||||
if (mDOMLocalization) {
|
|
||||||
Element* elem = mDocument->GetDocumentElement();
|
|
||||||
if (elem) {
|
|
||||||
mDOMLocalization->DisconnectRoot(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JSObject* DocumentL10n::WrapObject(JSContext* aCx,
|
JSObject* DocumentL10n::WrapObject(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) {
|
JS::Handle<JSObject*> aGivenProto) {
|
||||||
return DocumentL10n_Binding::Wrap(aCx, this, aGivenProto);
|
return DocumentL10n_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
|
@ -316,7 +333,9 @@ void DocumentL10n::GetAttributes(JSContext* aCx, Element& aElement,
|
||||||
|
|
||||||
class LocalizationHandler : public PromiseNativeHandler {
|
class LocalizationHandler : public PromiseNativeHandler {
|
||||||
public:
|
public:
|
||||||
explicit LocalizationHandler(nsINode* aNode) { mNode = aNode; };
|
explicit LocalizationHandler(DocumentL10n* aDocumentL10n) {
|
||||||
|
mDocumentL10n = aDocumentL10n;
|
||||||
|
};
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS(LocalizationHandler)
|
NS_DECL_CYCLE_COLLECTION_CLASS(LocalizationHandler)
|
||||||
|
@ -331,8 +350,6 @@ class LocalizationHandler : public PromiseNativeHandler {
|
||||||
JS::Handle<JS::Value> aValue) override {
|
JS::Handle<JS::Value> aValue) override {
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
|
|
||||||
RefPtr<DocumentL10n> docL10n = mNode->OwnerDoc()->GetL10n();
|
|
||||||
|
|
||||||
nsTArray<L10nValue> l10nData;
|
nsTArray<L10nValue> l10nData;
|
||||||
if (aValue.isObject()) {
|
if (aValue.isObject()) {
|
||||||
JS::ForOfIterator iter(aCx);
|
JS::ForOfIterator iter(aCx);
|
||||||
|
@ -375,12 +392,10 @@ class LocalizationHandler : public PromiseNativeHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (docL10n) {
|
mDocumentL10n->PauseObserving(rv);
|
||||||
docL10n->PauseObserving(rv);
|
if (NS_WARN_IF(rv.Failed())) {
|
||||||
if (NS_WARN_IF(rv.Failed())) {
|
mReturnValuePromise->MaybeRejectWithUndefined();
|
||||||
mReturnValuePromise->MaybeRejectWithUndefined();
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<DOMOverlaysError> errors;
|
nsTArray<DOMOverlaysError> errors;
|
||||||
|
@ -394,26 +409,15 @@ class LocalizationHandler : public PromiseNativeHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (docL10n) {
|
mDocumentL10n->ResumeObserving(rv);
|
||||||
docL10n->ResumeObserving(rv);
|
if (NS_WARN_IF(rv.Failed())) {
|
||||||
if (NS_WARN_IF(rv.Failed())) {
|
mReturnValuePromise->MaybeRejectWithUndefined();
|
||||||
mReturnValuePromise->MaybeRejectWithUndefined();
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<JS::Value> jsErrors;
|
DocumentL10n::ReportDOMOverlaysErrors(mDocumentL10n->GetDocument(), errors);
|
||||||
SequenceRooter<JS::Value> rooter(aCx, &jsErrors);
|
|
||||||
for (auto& error : errors) {
|
|
||||||
JS::RootedValue jsError(aCx);
|
|
||||||
if (!ToJSValue(aCx, error, &jsError)) {
|
|
||||||
mReturnValuePromise->MaybeRejectWithUndefined();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jsErrors.AppendElement(jsError);
|
|
||||||
}
|
|
||||||
|
|
||||||
mReturnValuePromise->MaybeResolve(jsErrors);
|
mReturnValuePromise->MaybeResolveWithUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void RejectedCallback(JSContext* aCx,
|
virtual void RejectedCallback(JSContext* aCx,
|
||||||
|
@ -425,7 +429,7 @@ class LocalizationHandler : public PromiseNativeHandler {
|
||||||
~LocalizationHandler() = default;
|
~LocalizationHandler() = default;
|
||||||
|
|
||||||
nsTArray<nsCOMPtr<Element>> mElements;
|
nsTArray<nsCOMPtr<Element>> mElements;
|
||||||
RefPtr<nsINode> mNode;
|
RefPtr<DocumentL10n> mDocumentL10n;
|
||||||
RefPtr<Promise> mReturnValuePromise;
|
RefPtr<Promise> mReturnValuePromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -440,23 +444,28 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(LocalizationHandler)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LocalizationHandler)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LocalizationHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNode)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentL10n)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValuePromise)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValuePromise)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LocalizationHandler)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LocalizationHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentL10n)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValuePromise)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValuePromise)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
already_AddRefed<Promise> DocumentL10n::TranslateFragment(JSContext* aCx,
|
already_AddRefed<Promise> DocumentL10n::TranslateFragment(nsINode& aNode,
|
||||||
nsINode& aNode,
|
|
||||||
ErrorResult& aRv) {
|
ErrorResult& aRv) {
|
||||||
Sequence<L10nKey> l10nKeys;
|
Sequence<OwningNonNull<Element>> elements;
|
||||||
SequenceRooter<L10nKey> rooter(aCx, &l10nKeys);
|
|
||||||
RefPtr<LocalizationHandler> nativeHandler = new LocalizationHandler(&aNode);
|
GetTranslatables(aNode, elements, aRv);
|
||||||
nsTArray<nsCOMPtr<Element>>& domElements = nativeHandler->Elements();
|
|
||||||
|
return TranslateElements(elements, aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentL10n::GetTranslatables(nsINode& aNode,
|
||||||
|
Sequence<OwningNonNull<Element>>& aElements,
|
||||||
|
ErrorResult& aRv) {
|
||||||
nsIContent* node =
|
nsIContent* node =
|
||||||
aNode.IsContent() ? aNode.AsContent() : aNode.GetFirstChild();
|
aNode.IsContent() ? aNode.AsContent() : aNode.GetFirstChild();
|
||||||
for (; node; node = node->GetNextNode(&aNode)) {
|
for (; node; node = node->GetNextNode(&aNode)) {
|
||||||
|
@ -470,13 +479,42 @@ already_AddRefed<Promise> DocumentL10n::TranslateFragment(JSContext* aCx,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!aElements.AppendElement(*domElement, fallible)) {
|
||||||
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<Promise> DocumentL10n::TranslateElements(
|
||||||
|
const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv) {
|
||||||
|
JS::RootingContext* rcx = RootingCx();
|
||||||
|
Sequence<L10nKey> l10nKeys;
|
||||||
|
SequenceRooter<L10nKey> rooter(rcx, &l10nKeys);
|
||||||
|
RefPtr<LocalizationHandler> nativeHandler = new LocalizationHandler(this);
|
||||||
|
nsTArray<nsCOMPtr<Element>>& domElements = nativeHandler->Elements();
|
||||||
|
domElements.SetCapacity(aElements.Length());
|
||||||
|
|
||||||
|
nsIGlobalObject* global = mDocument->GetScopeObject();
|
||||||
|
if (!global) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoEntryScript aes(global, "DocumentL10n GetAttributes");
|
||||||
|
JSContext* cx = aes.cx();
|
||||||
|
|
||||||
|
for (auto& domElement : aElements) {
|
||||||
|
if (!domElement->HasAttr(kNameSpaceID_None, nsGkAtoms::datal10nid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
L10nKey* key = l10nKeys.AppendElement(fallible);
|
L10nKey* key = l10nKeys.AppendElement(fallible);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetAttributes(aCx, *domElement, *key, aRv);
|
GetAttributes(cx, *domElement, *key, aRv);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -488,17 +526,12 @@ already_AddRefed<Promise> DocumentL10n::TranslateFragment(JSContext* aCx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIGlobalObject* global = mDocument->GetScopeObject();
|
|
||||||
if (!global) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Promise> callbackResult = FormatMessages(aCx, l10nKeys, aRv);
|
RefPtr<Promise> callbackResult = FormatMessages(cx, l10nKeys, aRv);
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -509,27 +542,56 @@ already_AddRefed<Promise> DocumentL10n::TranslateFragment(JSContext* aCx,
|
||||||
return MaybeWrapPromise(promise);
|
return MaybeWrapPromise(promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise> DocumentL10n::TranslateElements(
|
|
||||||
const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv) {
|
|
||||||
AutoTArray<RefPtr<Element>, 10> elements;
|
|
||||||
elements.SetCapacity(aElements.Length());
|
|
||||||
for (auto& element : aElements) {
|
|
||||||
elements.AppendElement(element);
|
|
||||||
}
|
|
||||||
RefPtr<Promise> promise;
|
|
||||||
aRv = mDOMLocalization->TranslateElements(elements, getter_AddRefs(promise));
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return MaybeWrapPromise(promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DocumentL10n::PauseObserving(ErrorResult& aRv) {
|
void DocumentL10n::PauseObserving(ErrorResult& aRv) {
|
||||||
aRv = mDOMLocalization->PauseObserving();
|
mMutations->PauseObserving();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentL10n::ResumeObserving(ErrorResult& aRv) {
|
void DocumentL10n::ResumeObserving(ErrorResult& aRv) {
|
||||||
aRv = mDOMLocalization->ResumeObserving();
|
mMutations->ResumeObserving();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void DocumentL10n::ReportDOMOverlaysErrors(
|
||||||
|
Document* aDocument, nsTArray<mozilla::dom::DOMOverlaysError>& aErrors) {
|
||||||
|
nsAutoString msg;
|
||||||
|
|
||||||
|
for (auto& error : aErrors) {
|
||||||
|
if (error.mCode.WasPassed()) {
|
||||||
|
msg = NS_LITERAL_STRING("[fluent-dom] ");
|
||||||
|
switch (error.mCode.Value()) {
|
||||||
|
case DOMOverlays_Binding::ERROR_FORBIDDEN_TYPE:
|
||||||
|
msg += NS_LITERAL_STRING("An element of forbidden type \"") +
|
||||||
|
error.mTranslatedElementName.Value() +
|
||||||
|
NS_LITERAL_STRING(
|
||||||
|
"\" was found in the translation. Only safe text-level "
|
||||||
|
"elements and elements with data-l10n-name are allowed.");
|
||||||
|
break;
|
||||||
|
case DOMOverlays_Binding::ERROR_NAMED_ELEMENT_MISSING:
|
||||||
|
msg += NS_LITERAL_STRING("An element named \"") +
|
||||||
|
error.mL10nName.Value() +
|
||||||
|
NS_LITERAL_STRING("\" wasn't found in the source.");
|
||||||
|
break;
|
||||||
|
case DOMOverlays_Binding::ERROR_NAMED_ELEMENT_TYPE_MISMATCH:
|
||||||
|
msg += NS_LITERAL_STRING("An element named \"") +
|
||||||
|
error.mL10nName.Value() +
|
||||||
|
NS_LITERAL_STRING(
|
||||||
|
"\" was found in the translation but its type ") +
|
||||||
|
error.mTranslatedElementName.Value() +
|
||||||
|
NS_LITERAL_STRING(
|
||||||
|
" didn't match the element found in the source ") +
|
||||||
|
error.mSourceElementName.Value() + NS_LITERAL_STRING(".");
|
||||||
|
break;
|
||||||
|
case DOMOverlays_Binding::ERROR_UNKNOWN:
|
||||||
|
default:
|
||||||
|
msg += NS_LITERAL_STRING(
|
||||||
|
"Unknown error happened while translation of an element.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nsContentUtils::ReportToConsoleNonLocalized(
|
||||||
|
msg, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"),
|
||||||
|
aDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class L10nReadyHandler final : public PromiseNativeHandler {
|
class L10nReadyHandler final : public PromiseNativeHandler {
|
||||||
|
@ -542,12 +604,12 @@ class L10nReadyHandler final : public PromiseNativeHandler {
|
||||||
|
|
||||||
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
|
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
|
||||||
mDocumentL10n->InitialDocumentTranslationCompleted();
|
mDocumentL10n->InitialDocumentTranslationCompleted();
|
||||||
mPromise->MaybeResolveWithClone(aCx, aValue);
|
mPromise->MaybeResolveWithUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
|
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
|
||||||
mDocumentL10n->InitialDocumentTranslationCompleted();
|
mDocumentL10n->InitialDocumentTranslationCompleted();
|
||||||
mPromise->MaybeRejectWithClone(aCx, aValue);
|
mPromise->MaybeRejectWithUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -574,12 +636,18 @@ void DocumentL10n::TriggerInitialDocumentTranslation() {
|
||||||
mState = DocumentL10nState::InitialTranslationTriggered;
|
mState = DocumentL10nState::InitialTranslationTriggered;
|
||||||
|
|
||||||
Element* elem = mDocument->GetDocumentElement();
|
Element* elem = mDocument->GetDocumentElement();
|
||||||
if (elem) {
|
if (!elem) {
|
||||||
mDOMLocalization->ConnectRoot(elem);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Promise> promise;
|
Sequence<OwningNonNull<Element>> elements;
|
||||||
mDOMLocalization->TranslateRoots(getter_AddRefs(promise));
|
ErrorResult rv;
|
||||||
|
|
||||||
|
GetTranslatables(*elem, elements, rv);
|
||||||
|
|
||||||
|
mMutations->ConnectRoot(elem);
|
||||||
|
|
||||||
|
RefPtr<Promise> promise = TranslateElements(elements, rv);
|
||||||
if (!promise) {
|
if (!promise) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -594,6 +662,11 @@ void DocumentL10n::InitialDocumentTranslationCompleted() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Element* documentElement = mDocument->GetDocumentElement();
|
||||||
|
if (documentElement) {
|
||||||
|
SetRootInfo(documentElement);
|
||||||
|
}
|
||||||
|
|
||||||
mState = DocumentL10nState::InitialTranslationCompleted;
|
mState = DocumentL10nState::InitialTranslationCompleted;
|
||||||
|
|
||||||
mDocument->InitialDocumentTranslationCompleted();
|
mDocument->InitialDocumentTranslationCompleted();
|
||||||
|
@ -603,9 +676,36 @@ void DocumentL10n::InitialDocumentTranslationCompleted() {
|
||||||
mContentSink->InitialDocumentTranslationCompleted();
|
mContentSink->InitialDocumentTranslationCompleted();
|
||||||
mContentSink = nullptr;
|
mContentSink = nullptr;
|
||||||
}
|
}
|
||||||
|
mDocument->AddMutationObserverUnlessExists(mMutations);
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise* DocumentL10n::Ready() { return mReady; }
|
Promise* DocumentL10n::Ready() { return mReady; }
|
||||||
|
|
||||||
|
void DocumentL10n::OnChange() {
|
||||||
|
if (mDOMLocalization) {
|
||||||
|
mDOMLocalization->OnChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentL10n::SetRootInfo(Element* aElement) {
|
||||||
|
nsAutoCString primaryLocale;
|
||||||
|
LocaleService::GetInstance()->GetAppLocaleAsBCP47(primaryLocale);
|
||||||
|
aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::lang,
|
||||||
|
NS_ConvertUTF8toUTF16(primaryLocale), true);
|
||||||
|
|
||||||
|
nsAutoString dir;
|
||||||
|
if (LocaleService::GetInstance()->IsAppLocaleRTL()) {
|
||||||
|
nsGkAtoms::rtl->ToString(dir);
|
||||||
|
} else {
|
||||||
|
nsGkAtoms::ltr->ToString(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nameSpace = aElement->GetNameSpaceID();
|
||||||
|
nsAtom* dirAtom =
|
||||||
|
nameSpace == kNameSpaceID_XUL ? nsGkAtoms::localedir : nsGkAtoms::dir;
|
||||||
|
|
||||||
|
aElement->SetAttr(kNameSpaceID_None, dirAtom, dir, true);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -19,14 +19,18 @@
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||||
|
#include "mozilla/dom/l10n/Mutations.h"
|
||||||
|
#include "mozilla/dom/DOMOverlaysBinding.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class Document;
|
namespace l10n {
|
||||||
class Element;
|
class Mutations;
|
||||||
|
}
|
||||||
struct L10nKey;
|
struct L10nKey;
|
||||||
|
|
||||||
class PromiseResolver final : public PromiseNativeHandler {
|
class PromiseResolver final : public PromiseNativeHandler {
|
||||||
|
@ -71,7 +75,6 @@ class DocumentL10n final : public nsIObserver,
|
||||||
public:
|
public:
|
||||||
explicit DocumentL10n(Document* aDocument);
|
explicit DocumentL10n(Document* aDocument);
|
||||||
bool Init(nsTArray<nsString>& aResourceIds);
|
bool Init(nsTArray<nsString>& aResourceIds);
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~DocumentL10n();
|
virtual ~DocumentL10n();
|
||||||
|
@ -81,9 +84,11 @@ class DocumentL10n final : public nsIObserver,
|
||||||
DocumentL10nState mState;
|
DocumentL10nState mState;
|
||||||
nsCOMPtr<mozIDOMLocalization> mDOMLocalization;
|
nsCOMPtr<mozIDOMLocalization> mDOMLocalization;
|
||||||
nsCOMPtr<nsIContentSink> mContentSink;
|
nsCOMPtr<nsIContentSink> mContentSink;
|
||||||
|
RefPtr<l10n::Mutations> mMutations;
|
||||||
|
|
||||||
already_AddRefed<Promise> MaybeWrapPromise(Promise* aPromise);
|
already_AddRefed<Promise> MaybeWrapPromise(Promise* aPromise);
|
||||||
void RegisterObservers();
|
void RegisterObservers();
|
||||||
|
void DisconnectMutations();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Document* GetParentObject() const { return mDocument; };
|
Document* GetParentObject() const { return mDocument; };
|
||||||
|
@ -121,13 +126,19 @@ class DocumentL10n final : public nsIObserver,
|
||||||
void GetAttributes(JSContext* aCx, Element& aElement, L10nKey& aResult,
|
void GetAttributes(JSContext* aCx, Element& aElement, L10nKey& aResult,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
already_AddRefed<Promise> TranslateFragment(JSContext* aCx, nsINode& aNode,
|
already_AddRefed<Promise> TranslateFragment(nsINode& aNode, ErrorResult& aRv);
|
||||||
ErrorResult& aRv);
|
|
||||||
|
void GetTranslatables(nsINode& aNode,
|
||||||
|
Sequence<OwningNonNull<Element>>& aElements,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
already_AddRefed<Promise> TranslateElements(
|
already_AddRefed<Promise> TranslateElements(
|
||||||
const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv);
|
const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv);
|
||||||
|
|
||||||
void PauseObserving(ErrorResult& aRv);
|
void PauseObserving(ErrorResult& aRv);
|
||||||
void ResumeObserving(ErrorResult& aRv);
|
void ResumeObserving(ErrorResult& aRv);
|
||||||
|
static void ReportDOMOverlaysErrors(
|
||||||
|
Document* aDocument, nsTArray<mozilla::dom::DOMOverlaysError>& aErrors);
|
||||||
|
|
||||||
Promise* Ready();
|
Promise* Ready();
|
||||||
|
|
||||||
|
@ -136,6 +147,9 @@ class DocumentL10n final : public nsIObserver,
|
||||||
void InitialDocumentTranslationCompleted();
|
void InitialDocumentTranslationCompleted();
|
||||||
|
|
||||||
Document* GetDocument() { return mDocument; };
|
Document* GetDocument() { return mDocument; };
|
||||||
|
|
||||||
|
void OnChange();
|
||||||
|
protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
Загрузка…
Ссылка в новой задаче