зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1455649 - DocumentL10n, part 3 - Plug DocumentL10n life cycle into DOM hooks. r=smaug
--HG-- extra : rebase_source : d071878d22b5fd204db8367780ee22be22196773
This commit is contained in:
Родитель
d105ed85e4
Коммит
e78d123097
|
@ -8911,6 +8911,10 @@ nsIDocument::SetReadyStateInternal(ReadyState rs)
|
|||
mLoadingTimeStamp = mozilla::TimeStamp::Now();
|
||||
}
|
||||
|
||||
if (READYSTATE_INTERACTIVE == rs) {
|
||||
TriggerInitialDocumentTranslation();
|
||||
}
|
||||
|
||||
RecordNavigationTiming(rs);
|
||||
|
||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
|
|
|
@ -144,6 +144,10 @@ HTMLLinkElement::BindToTree(nsIDocument* aDocument,
|
|||
nsContentUtils::AddScriptRunner(
|
||||
NewRunnableMethod("dom::HTMLLinkElement::BindToTree", this, update));
|
||||
|
||||
if (aDocument && this->AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization, eIgnoreCase)) {
|
||||
aDocument->LocalizationLinkAdded(this);
|
||||
}
|
||||
|
||||
CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));
|
||||
|
||||
return rv;
|
||||
|
@ -180,6 +184,10 @@ HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
|||
nsIDocument* oldDoc = GetUncomposedDoc();
|
||||
ShadowRoot* oldShadowRoot = GetContainingShadow();
|
||||
|
||||
if (oldDoc && this->AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization, eIgnoreCase)) {
|
||||
oldDoc->LocalizationLinkRemoved(this);
|
||||
}
|
||||
|
||||
CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved"));
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
||||
|
@ -292,6 +300,36 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||
aSubjectPrincipal);
|
||||
}
|
||||
|
||||
// If a link's `rel` attribute was changed from or to `localization`,
|
||||
// update the list of localization links.
|
||||
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::rel) {
|
||||
nsIDocument* doc = GetComposedDoc();
|
||||
if (doc) {
|
||||
if ((aValue && aValue->Equals(nsGkAtoms::localization, eIgnoreCase)) &&
|
||||
(!aOldValue || !aOldValue->Equals(nsGkAtoms::localization, eIgnoreCase))) {
|
||||
doc->LocalizationLinkAdded(this);
|
||||
} else if ((aOldValue && aOldValue->Equals(nsGkAtoms::localization, eIgnoreCase)) &&
|
||||
(!aValue || !aValue->Equals(nsGkAtoms::localization, eIgnoreCase))) {
|
||||
doc->LocalizationLinkRemoved(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the link has `rel=localization` and its `href` attribute is changed,
|
||||
// update the list of localization links.
|
||||
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::href &&
|
||||
AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization, eIgnoreCase)) {
|
||||
nsIDocument* doc = GetComposedDoc();
|
||||
if (doc) {
|
||||
if (aOldValue) {
|
||||
doc->LocalizationLinkRemoved(this);
|
||||
}
|
||||
if (aValue) {
|
||||
doc->LocalizationLinkAdded(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aValue) {
|
||||
if (aNameSpaceID == kNameSpaceID_None &&
|
||||
(aName == nsGkAtoms::href ||
|
||||
|
|
|
@ -61,6 +61,11 @@ void
|
|||
HTMLSharedElement::DoneAddingChildren(bool aHaveNotified)
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::head)) {
|
||||
nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
|
||||
if (doc) {
|
||||
doc->OnL10nResourceContainerParsed();
|
||||
}
|
||||
|
||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this,
|
||||
NS_LITERAL_STRING("DOMHeadElementParsed"),
|
||||
|
|
|
@ -577,6 +577,7 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
|
|||
nodeInfo->NameAtom() == nsGkAtoms::textarea ||
|
||||
nodeInfo->NameAtom() == nsGkAtoms::video ||
|
||||
nodeInfo->NameAtom() == nsGkAtoms::audio ||
|
||||
nodeInfo->NameAtom() == nsGkAtoms::head ||
|
||||
nodeInfo->NameAtom() == nsGkAtoms::object))
|
||||
|| nodeInfo->NameAtom() == nsGkAtoms::title
|
||||
) {
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsURILoader.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/dom/DocumentL10n.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/NodeInfoInlines.h"
|
||||
#include "mozilla/dom/ProcessingInstruction.h"
|
||||
|
@ -1045,6 +1046,10 @@ XULDocument::AddElementToDocumentPost(Element* aElement)
|
|||
if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
|
||||
// Create our XUL key listener and hook it up.
|
||||
nsXBLService::AttachGlobalKeyHandler(aElement);
|
||||
} else if (aElement->IsXULElement(nsGkAtoms::link)) {
|
||||
LocalizationLinkAdded(aElement);
|
||||
} else if (aElement->IsXULElement(nsGkAtoms::linkset)) {
|
||||
OnL10nResourceContainerParsed();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1833,6 +1838,11 @@ XULDocument::DoneWalking()
|
|||
|
||||
NotifyPossibleTitleChange(false);
|
||||
|
||||
// For performance reasons, we want to trigger the DocumentL10n's `TriggerInitialDocumentTranslation` within the same
|
||||
// microtask that will be created for a `MozBeforeInitialXULLayout`
|
||||
// event listener.
|
||||
AddEventListener(NS_LITERAL_STRING("MozBeforeInitialXULLayout"), mDocumentL10n, true, false);
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(
|
||||
this,
|
||||
static_cast<nsIDocument*>(this),
|
||||
|
@ -1840,6 +1850,8 @@ XULDocument::DoneWalking()
|
|||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
|
||||
RemoveEventListener(NS_LITERAL_STRING("MozBeforeInitialXULLayout"), mDocumentL10n, true);
|
||||
|
||||
// Before starting layout, check whether we're a toplevel chrome
|
||||
// window. If we are, setup some state so that we don't have to restyle
|
||||
// the whole tree after StartLayout.
|
||||
|
|
|
@ -36,6 +36,7 @@ LOCAL_INCLUDES += [
|
|||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
|
||||
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
|
|
@ -18,3 +18,8 @@
|
|||
[dom/test_mozdom_translateElements.html]
|
||||
[dom/test_mozdom_translateFragment.html]
|
||||
[dom/test_mozdom_translateRoots.html]
|
||||
|
||||
[dom/test_docl10n.xul]
|
||||
[dom/test_docl10n.xhtml]
|
||||
[dom/test_docl10n.html]
|
||||
[dom/test_docl10n_ready_rejected.html]
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test DocumentL10n in HTML environment</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<link rel="localization" href="crashreporter/aboutcrashes.ftl"/>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
await document.l10n.ready;
|
||||
|
||||
let desc = document.getElementById("main-desc");
|
||||
is(desc.textContent.length > 0, true);
|
||||
|
||||
// Test for manual value formatting
|
||||
let msg = await document.l10n.formatValue("id-heading");
|
||||
is(msg.length > 0, true);
|
||||
|
||||
let label = document.getElementById("label1");
|
||||
document.l10n.setAttributes(
|
||||
label,
|
||||
"date-crashed-heading",
|
||||
{
|
||||
name: "John"
|
||||
}
|
||||
);
|
||||
|
||||
// Test for l10n.getAttributes
|
||||
let l10nArgs = document.l10n.getAttributes(label);
|
||||
is(l10nArgs.id, "date-crashed-heading");
|
||||
is(l10nArgs.args.name, "John");
|
||||
|
||||
let verifyL10n = () => {
|
||||
if (label.textContent.length > 0) {
|
||||
window.removeEventListener("MozAfterPaint", verifyL10n);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
window.addEventListener("MozAfterPaint", verifyL10n);
|
||||
}, { once: true});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="main-desc" data-l10n-id="crash-reports-title"></h1>
|
||||
|
||||
<p id="label1"></p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf-8"></meta>
|
||||
<title>Test DocumentL10n in HTML environment</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"></link>
|
||||
<link rel="localization" href="crashreporter/aboutcrashes.ftl"/>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
await document.l10n.ready;
|
||||
|
||||
let desc = document.getElementById("main-desc");
|
||||
is(desc.textContent.length > 0, true);
|
||||
|
||||
// Test for manual value formatting
|
||||
let msg = await document.l10n.formatValue("id-heading");
|
||||
is(msg.length > 0, true);
|
||||
|
||||
let label = document.getElementById("label1");
|
||||
document.l10n.setAttributes(
|
||||
label,
|
||||
"date-crashed-heading",
|
||||
{
|
||||
name: "John"
|
||||
}
|
||||
);
|
||||
|
||||
// Test for l10n.getAttributes
|
||||
let l10nArgs = document.l10n.getAttributes(label);
|
||||
is(l10nArgs.id, "date-crashed-heading");
|
||||
is(l10nArgs.args.name, "John");
|
||||
|
||||
let verifyL10n = () => {
|
||||
if (label.textContent.length > 0) {
|
||||
window.removeEventListener("MozAfterPaint", verifyL10n);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
window.addEventListener("MozAfterPaint", verifyL10n);
|
||||
}, { once: true});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="main-desc" data-l10n-id="crash-reports-title"></h1>
|
||||
|
||||
<p id="label1" />
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
title="Testing DocumentL10n in XUL environment">
|
||||
|
||||
<linkset>
|
||||
<link rel="localization" href="crashreporter/aboutcrashes.ftl"/>
|
||||
</linkset>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
await document.l10n.ready;
|
||||
|
||||
let desc = document.getElementById("main-desc");
|
||||
is(desc.textContent.length > 0, true);
|
||||
|
||||
// Test for manual value formatting
|
||||
let msg = await document.l10n.formatValue("id-heading");
|
||||
is(msg.length > 0, true);
|
||||
|
||||
let label = document.getElementById("label1");
|
||||
document.l10n.setAttributes(
|
||||
label,
|
||||
"date-crashed-heading",
|
||||
{
|
||||
name: "John"
|
||||
}
|
||||
);
|
||||
|
||||
// Test for l10n.getAttributes
|
||||
let l10nArgs = document.l10n.getAttributes(label);
|
||||
is(l10nArgs.id, "date-crashed-heading");
|
||||
is(l10nArgs.args.name, "John");
|
||||
|
||||
let verifyL10n = () => {
|
||||
if (label.textContent.length > 0) {
|
||||
window.removeEventListener("MozAfterPaint", verifyL10n);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
window.addEventListener("MozAfterPaint", verifyL10n);
|
||||
}, { once: true});
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<description id="main-desc" data-l10n-id="crash-reports-title"/>
|
||||
|
||||
<label id="label1" />
|
||||
</window>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test mozIDOMLocalization.ready rejected state</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<link rel="localization" href="path/to_non_existing.ftl"/>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
document.l10n.ready.then(() => {
|
||||
is(1, 2, "the ready should not resolve");
|
||||
SimpleTest.finish();
|
||||
}, (err) => {
|
||||
is(1, 1, "the ready should reject");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 data-l10n-id="non-existing-id"></h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Ensure unprivilaged document cannot access document.l10n in an iframe</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
let frame = document.getElementById("frame");
|
||||
let frame2 = document.getElementById("frame2");
|
||||
|
||||
is("l10n" in frame.contentDocument, false);
|
||||
is("l10n" in frame2.contentDocument, false);
|
||||
});
|
||||
addLoadEvent(SimpleTest.finish);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="frame" src="about:blank"></iframe>
|
||||
<iframe id="frame2" src="about:crashes"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
[dom/test_docl10n_unpriv_iframe.html]
|
|
@ -73,7 +73,7 @@ add_task(async function test_format_messages() {
|
|||
});
|
||||
|
||||
add_task(async function test_format_values() {
|
||||
let msgs = await domLocalization.formatValues([{"id": "key"}], 1);
|
||||
let msgs = await domLocalization.formatValues([{"id": "key"}]);
|
||||
equal(msgs.length, 1);
|
||||
equal(msgs[0], "[en] Value");
|
||||
});
|
||||
|
|
|
@ -546,6 +546,7 @@ STATIC_ATOMS = [
|
|||
Atom("li", "li"),
|
||||
Atom("line", "line"),
|
||||
Atom("link", "link"),
|
||||
Atom("linkset", "linkset"),
|
||||
# Atom("list", "list"), # "list" is present below
|
||||
Atom("listbox", "listbox"),
|
||||
Atom("listener", "listener"),
|
||||
|
@ -556,6 +557,7 @@ STATIC_ATOMS = [
|
|||
Atom("triggeringprincipal", "triggeringprincipal"),
|
||||
Atom("localedir", "localedir"),
|
||||
Atom("localName", "local-name"),
|
||||
Atom("localization", "localization"),
|
||||
Atom("longdesc", "longdesc"),
|
||||
Atom("loop", "loop"),
|
||||
Atom("low", "low"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче