mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
307d0160a7
Differential Revision: https://phabricator.services.mozilla.com/D33739 --HG-- rename : dom/chrome-webidl/DOMOverlays.webidl => dom/chrome-webidl/L10nOverlays.webidl rename : dom/l10n/Mutations.cpp => dom/l10n/L10nMutations.cpp rename : dom/l10n/Mutations.h => dom/l10n/L10nMutations.h rename : dom/l10n/DOMOverlays.cpp => dom/l10n/L10nOverlays.cpp rename : dom/l10n/DOMOverlays.h => dom/l10n/L10nOverlays.h rename : dom/l10n/tests/gtest/TestDOMOverlays.cpp => dom/l10n/tests/gtest/TestL10nOverlays.cpp rename : dom/l10n/tests/mochitest/dom_localization/test_mutations.html => dom/l10n/tests/mochitest/dom_localization/test_l10n_mutations.html rename : dom/l10n/tests/mochitest/mutations/test_append_content_post_dcl.html => dom/l10n/tests/mochitest/l10n_mutations/test_append_content_post_dcl.html rename : dom/l10n/tests/mochitest/mutations/test_append_content_pre_dcl.html => dom/l10n/tests/mochitest/l10n_mutations/test_append_content_pre_dcl.html rename : dom/l10n/tests/mochitest/mutations/test_append_fragment_post_dcl.html => dom/l10n/tests/mochitest/l10n_mutations/test_append_fragment_post_dcl.html rename : dom/l10n/tests/mochitest/mutations/test_pause_observing.html => dom/l10n/tests/mochitest/l10n_mutations/test_pause_observing.html rename : dom/l10n/tests/mochitest/mutations/test_set_attributes.html => dom/l10n/tests/mochitest/l10n_mutations/test_set_attributes.html rename : dom/l10n/tests/mochitest/domoverlays/test_attributes.html => dom/l10n/tests/mochitest/l10n_overlays/test_attributes.html rename : dom/l10n/tests/mochitest/domoverlays/test_extra_text_markup.html => dom/l10n/tests/mochitest/l10n_overlays/test_extra_text_markup.html rename : dom/l10n/tests/mochitest/domoverlays/test_functional_children.html => dom/l10n/tests/mochitest/l10n_overlays/test_functional_children.html rename : dom/l10n/tests/mochitest/domoverlays/test_domoverlays.xul => dom/l10n/tests/mochitest/l10n_overlays/test_l10n_overlays.xul rename : dom/l10n/tests/mochitest/domoverlays/test_same_id.html => dom/l10n/tests/mochitest/l10n_overlays/test_same_id.html rename : dom/l10n/tests/mochitest/domoverlays/test_same_id_args.html => dom/l10n/tests/mochitest/l10n_overlays/test_same_id_args.html rename : dom/l10n/tests/mochitest/domoverlays/test_text_children.html => dom/l10n/tests/mochitest/l10n_overlays/test_text_children.html extra : moz-landing-system : lando
189 lines
4.7 KiB
C++
189 lines
4.7 KiB
C++
#include "L10nMutations.h"
|
|
#include "mozilla/dom/DocumentInlines.h"
|
|
|
|
using namespace mozilla::dom;
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(L10nMutations)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(L10nMutations)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingElements)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingElementsHash)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(L10nMutations)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingElements)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingElementsHash)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(L10nMutations)
|
|
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(L10nMutations)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(L10nMutations)
|
|
|
|
L10nMutations::L10nMutations(DOMLocalization* aDOMLocalization)
|
|
: mDOMLocalization(aDOMLocalization) {
|
|
mObserving = true;
|
|
}
|
|
|
|
void L10nMutations::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
|
|
nsAtom* aAttribute, int32_t aModType,
|
|
const nsAttrValue* aOldValue) {
|
|
if (!mObserving) {
|
|
return;
|
|
}
|
|
Document* uncomposedDoc = aElement->GetUncomposedDoc();
|
|
if (uncomposedDoc) {
|
|
if (aNameSpaceID == kNameSpaceID_None &&
|
|
(aAttribute == nsGkAtoms::datal10nid ||
|
|
aAttribute == nsGkAtoms::datal10nargs)) {
|
|
L10nElementChanged(aElement);
|
|
}
|
|
}
|
|
}
|
|
|
|
void L10nMutations::ContentAppended(nsIContent* aChild) {
|
|
if (!mObserving) {
|
|
return;
|
|
}
|
|
ErrorResult rv;
|
|
Sequence<OwningNonNull<Element>> elements;
|
|
|
|
nsINode* node = aChild;
|
|
while (node) {
|
|
if (node->IsElement()) {
|
|
Element* elem = node->AsElement();
|
|
|
|
Document* uncomposedDoc = elem->GetUncomposedDoc();
|
|
if (uncomposedDoc) {
|
|
DOMLocalization::GetTranslatables(*node, elements, rv);
|
|
}
|
|
}
|
|
|
|
node = node->GetNextSibling();
|
|
}
|
|
|
|
for (auto& elem : elements) {
|
|
L10nElementChanged(elem);
|
|
}
|
|
}
|
|
|
|
void L10nMutations::ContentInserted(nsIContent* aChild) {
|
|
if (!mObserving) {
|
|
return;
|
|
}
|
|
ErrorResult rv;
|
|
Sequence<OwningNonNull<Element>> elements;
|
|
|
|
if (!aChild->IsElement()) {
|
|
return;
|
|
}
|
|
Element* elem = aChild->AsElement();
|
|
|
|
Document* uncomposedDoc = elem->GetUncomposedDoc();
|
|
if (!uncomposedDoc) {
|
|
return;
|
|
}
|
|
DOMLocalization::GetTranslatables(*aChild, elements, rv);
|
|
|
|
for (auto& elem : elements) {
|
|
L10nElementChanged(elem);
|
|
}
|
|
}
|
|
|
|
void L10nMutations::L10nElementChanged(Element* aElement) {
|
|
if (!mPendingElementsHash.Contains(aElement)) {
|
|
mPendingElements.AppendElement(aElement);
|
|
mPendingElementsHash.PutEntry(aElement);
|
|
}
|
|
|
|
if (!mRefreshObserver) {
|
|
StartRefreshObserver();
|
|
}
|
|
}
|
|
|
|
void L10nMutations::PauseObserving() { mObserving = false; }
|
|
|
|
void L10nMutations::ResumeObserving() { mObserving = true; }
|
|
|
|
void L10nMutations::WillRefresh(mozilla::TimeStamp aTime) {
|
|
StopRefreshObserver();
|
|
FlushPendingTranslations();
|
|
}
|
|
|
|
void L10nMutations::FlushPendingTranslations() {
|
|
if (!mDOMLocalization) {
|
|
return;
|
|
}
|
|
|
|
ErrorResult rv;
|
|
|
|
Sequence<OwningNonNull<Element>> elements;
|
|
|
|
for (auto& elem : mPendingElements) {
|
|
if (!elem->HasAttr(kNameSpaceID_None, nsGkAtoms::datal10nid)) {
|
|
continue;
|
|
}
|
|
|
|
elements.AppendElement(*elem, fallible);
|
|
}
|
|
|
|
mPendingElementsHash.Clear();
|
|
mPendingElements.Clear();
|
|
|
|
RefPtr<Promise> promise = mDOMLocalization->TranslateElements(elements, rv);
|
|
}
|
|
|
|
void L10nMutations::Disconnect() {
|
|
StopRefreshObserver();
|
|
mDOMLocalization = nullptr;
|
|
}
|
|
|
|
void L10nMutations::StartRefreshObserver() {
|
|
if (!mDOMLocalization || mRefreshObserver) {
|
|
return;
|
|
}
|
|
|
|
if (!mRefreshDriver) {
|
|
nsPIDOMWindowInner* innerWindow =
|
|
mDOMLocalization->GetParentObject()->AsInnerWindow();
|
|
Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
|
|
if (doc) {
|
|
nsPresContext* ctx = doc->GetPresContext();
|
|
if (ctx) {
|
|
mRefreshDriver = ctx->RefreshDriver();
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we can't start the refresh driver, it means
|
|
// that the presContext is not available yet.
|
|
// In that case, we'll trigger the flush of pending
|
|
// elements in Document::CreatePresShell.
|
|
if (mRefreshDriver) {
|
|
mRefreshDriver->AddRefreshObserver(this, FlushType::Style);
|
|
mRefreshObserver = true;
|
|
} else {
|
|
NS_WARNING("[l10n][mutations] Failed to start a refresh observer.");
|
|
}
|
|
}
|
|
|
|
void L10nMutations::StopRefreshObserver() {
|
|
if (!mDOMLocalization) {
|
|
return;
|
|
}
|
|
|
|
if (mRefreshDriver) {
|
|
mRefreshDriver->RemoveRefreshObserver(this, FlushType::Style);
|
|
mRefreshObserver = false;
|
|
}
|
|
}
|
|
|
|
void L10nMutations::OnCreatePresShell() {
|
|
if (!mPendingElements.IsEmpty()) {
|
|
StartRefreshObserver();
|
|
}
|
|
}
|