mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-11 05:39:41 +02:00
***
Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8
This changes the behavior of ChromeUtils.import() to return an exports object,
rather than a module global, in all cases except when `null` is passed as a
second argument, and changes the default behavior not to pollute the global
scope with the module's exports. Thus, the following code written for the old
model:
ChromeUtils.import("resource://gre/modules/Services.jsm");
is approximately the same as the following, in the new model:
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Since the two behaviors are mutually incompatible, this patch will land with a
scripted rewrite to update all existing callers to use the new model rather
than the old.
***
Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs
This was done using the followng script:
https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm
***
Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D16747
***
Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16748
***
Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16749
***
Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs
***
Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16750
--HG--
extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895
extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
507 lines
15 KiB
JavaScript
507 lines
15 KiB
JavaScript
"use strict";
|
||
|
||
const {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm");
|
||
|
||
// ExtensionContent.jsm needs to know when it's running from xpcshell,
|
||
// to use the right timeout for content scripts executed at document_idle.
|
||
ExtensionTestUtils.mockAppInfo();
|
||
|
||
const server = createHttpServer();
|
||
server.registerDirectory("/data/", do_get_file("data"));
|
||
|
||
const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
|
||
|
||
var originalReqLocales = Services.locale.requestedLocales;
|
||
|
||
registerCleanupFunction(() => {
|
||
Preferences.reset("intl.accept_languages");
|
||
Services.locale.requestedLocales = originalReqLocales;
|
||
});
|
||
|
||
|
||
add_task(async function test_i18n() {
|
||
function runTests(assertEq) {
|
||
let _ = browser.i18n.getMessage.bind(browser.i18n);
|
||
|
||
let url = browser.runtime.getURL("/");
|
||
assertEq(url, `moz-extension://${_("@@extension_id")}/`, "@@extension_id builtin message");
|
||
|
||
assertEq("Foo.", _("Foo"), "Simple message in selected locale.");
|
||
|
||
assertEq("(bar)", _("bar"), "Simple message fallback in default locale.");
|
||
|
||
assertEq("", _("some-unknown-locale-string"), "Unknown locale string.");
|
||
|
||
assertEq("", _("@@unknown_builtin_string"), "Unknown built-in string.");
|
||
assertEq("", _("@@bidi_unknown_builtin_string"), "Unknown built-in bidi string.");
|
||
|
||
assertEq("Føo.", _("Föo"), "Multi-byte message in selected locale.");
|
||
|
||
let substitutions = [];
|
||
substitutions[4] = "5";
|
||
substitutions[13] = "14";
|
||
|
||
assertEq("'$0' '14' '' '5' '$$$$' '$'.", _("basic_substitutions", substitutions),
|
||
"Basic numeric substitutions");
|
||
|
||
assertEq("'$0' '' 'just a string' '' '$$$$' '$'.", _("basic_substitutions", "just a string"),
|
||
"Basic numeric substitutions, with non-array value");
|
||
|
||
let values = _("named_placeholder_substitutions", ["(subst $1 $2)", "(2 $1 $2)"]).split("\n");
|
||
|
||
assertEq("_foo_ (subst $1 $2) _bar_", values[0], "Named and numeric substitution");
|
||
|
||
assertEq("(2 $1 $2)", values[1], "Numeric substitution amid named placeholders");
|
||
|
||
assertEq("$bad name$", values[2], "Named placeholder with invalid key");
|
||
|
||
assertEq("", values[3], "Named placeholder with an invalid value");
|
||
|
||
assertEq("Accepted, but shouldn't break.", values[4], "Named placeholder with a strange content value");
|
||
|
||
assertEq("$foo", values[5], "Non-placeholder token that should be ignored");
|
||
}
|
||
|
||
let extension = ExtensionTestUtils.loadExtension({
|
||
manifest: {
|
||
"default_locale": "jp",
|
||
|
||
content_scripts: [
|
||
{"matches": ["http://*/*/file_sample.html"],
|
||
"js": ["content.js"]},
|
||
],
|
||
},
|
||
|
||
|
||
files: {
|
||
"_locales/en_US/messages.json": {
|
||
"foo": {
|
||
"message": "Foo.",
|
||
"description": "foo",
|
||
},
|
||
|
||
"föo": {
|
||
"message": "Føo.",
|
||
"description": "foo",
|
||
},
|
||
|
||
"basic_substitutions": {
|
||
"message": "'$0' '$14' '$1' '$5' '$$$$$' '$$'.",
|
||
"description": "foo",
|
||
},
|
||
|
||
"Named_placeholder_substitutions": {
|
||
"message": "$Foo$\n$2\n$bad name$\n$bad_value$\n$bad_content_value$\n$foo",
|
||
"description": "foo",
|
||
"placeholders": {
|
||
"foO": {
|
||
"content": "_foo_ $1 _bar_",
|
||
"description": "foo",
|
||
},
|
||
|
||
"bad name": {
|
||
"content": "Nope.",
|
||
"description": "bad name",
|
||
},
|
||
|
||
"bad_value": "Nope.",
|
||
|
||
"bad_content_value": {
|
||
"content": ["Accepted, but shouldn't break."],
|
||
"description": "bad value",
|
||
},
|
||
},
|
||
},
|
||
|
||
"broken_placeholders": {
|
||
"message": "$broken$",
|
||
"description": "broken placeholders",
|
||
"placeholders": "foo.",
|
||
},
|
||
},
|
||
|
||
"_locales/jp/messages.json": {
|
||
"foo": {
|
||
"message": "(foo)",
|
||
"description": "foo",
|
||
},
|
||
|
||
"bar": {
|
||
"message": "(bar)",
|
||
"description": "bar",
|
||
},
|
||
},
|
||
|
||
"content.js": "new " + function(runTestsFn) {
|
||
runTestsFn((...args) => {
|
||
browser.runtime.sendMessage(["assertEq", ...args]);
|
||
});
|
||
|
||
browser.runtime.sendMessage(["content-script-finished"]);
|
||
} + `(${runTests})`,
|
||
},
|
||
|
||
background: "new " + function(runTestsFn) {
|
||
browser.runtime.onMessage.addListener(([msg, ...args]) => {
|
||
if (msg == "assertEq") {
|
||
browser.test.assertEq(...args);
|
||
} else {
|
||
browser.test.sendMessage(msg, ...args);
|
||
}
|
||
});
|
||
|
||
runTestsFn(browser.test.assertEq.bind(browser.test));
|
||
} + `(${runTests})`,
|
||
});
|
||
|
||
await extension.startup();
|
||
|
||
let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
|
||
await extension.awaitMessage("content-script-finished");
|
||
await contentPage.close();
|
||
|
||
await extension.unload();
|
||
});
|
||
|
||
add_task(async function test_i18n_negotiation() {
|
||
function runTests(expected) {
|
||
let _ = browser.i18n.getMessage.bind(browser.i18n);
|
||
|
||
browser.test.assertEq(expected, _("foo"), "Got expected message");
|
||
}
|
||
|
||
let extensionData = {
|
||
manifest: {
|
||
"default_locale": "en_US",
|
||
|
||
content_scripts: [
|
||
{"matches": ["http://*/*/file_sample.html"],
|
||
"js": ["content.js"]},
|
||
],
|
||
},
|
||
|
||
|
||
files: {
|
||
"_locales/en_US/messages.json": {
|
||
"foo": {
|
||
"message": "English.",
|
||
"description": "foo",
|
||
},
|
||
},
|
||
|
||
"_locales/jp/messages.json": {
|
||
"foo": {
|
||
"message": "\u65e5\u672c\u8a9e",
|
||
"description": "foo",
|
||
},
|
||
},
|
||
|
||
"content.js": "new " + function(runTestsFn) {
|
||
browser.test.onMessage.addListener(expected => {
|
||
runTestsFn(expected);
|
||
|
||
browser.test.sendMessage("content-script-finished");
|
||
});
|
||
browser.test.sendMessage("content-ready");
|
||
} + `(${runTests})`,
|
||
},
|
||
|
||
background: "new " + function(runTestsFn) {
|
||
browser.test.onMessage.addListener(expected => {
|
||
runTestsFn(expected);
|
||
|
||
browser.test.sendMessage("background-script-finished");
|
||
});
|
||
} + `(${runTests})`,
|
||
};
|
||
|
||
// At the moment extension language negotiation is tied to Firefox language
|
||
// negotiation result. That means that to test an extension in `fr`, we need
|
||
// to mock `fr` being available in Firefox and then request it.
|
||
//
|
||
// In the future, we should provide some way for tests to decouple their
|
||
// language selection from that of Firefox.
|
||
Services.locale.availableLocales = ["en-US", "fr", "jp"];
|
||
|
||
let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
|
||
|
||
for (let [lang, msg] of [["en-US", "English."], ["jp", "\u65e5\u672c\u8a9e"]]) {
|
||
Services.locale.requestedLocales = [lang];
|
||
|
||
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||
await extension.startup();
|
||
await extension.awaitMessage("content-ready");
|
||
|
||
extension.sendMessage(msg);
|
||
await extension.awaitMessage("background-script-finished");
|
||
await extension.awaitMessage("content-script-finished");
|
||
|
||
await extension.unload();
|
||
}
|
||
Services.locale.requestedLocales = originalReqLocales;
|
||
|
||
await contentPage.close();
|
||
});
|
||
|
||
|
||
add_task(async function test_get_accept_languages() {
|
||
function checkResults(source, results, expected) {
|
||
browser.test.assertEq(
|
||
expected.length,
|
||
results.length,
|
||
`got expected number of languages in ${source}`);
|
||
results.forEach((lang, index) => {
|
||
browser.test.assertEq(
|
||
expected[index],
|
||
lang,
|
||
`got expected language in ${source}`);
|
||
});
|
||
}
|
||
|
||
function background(checkResultsFn) {
|
||
browser.test.onMessage.addListener(([msg, expected]) => {
|
||
browser.i18n.getAcceptLanguages().then(results => {
|
||
checkResultsFn("background", results, expected);
|
||
|
||
browser.test.sendMessage("background-done");
|
||
});
|
||
});
|
||
}
|
||
|
||
function content(checkResultsFn) {
|
||
browser.test.onMessage.addListener(([msg, expected]) => {
|
||
browser.i18n.getAcceptLanguages().then(results => {
|
||
checkResultsFn("contentScript", results, expected);
|
||
|
||
browser.test.sendMessage("content-done");
|
||
});
|
||
});
|
||
browser.test.sendMessage("content-loaded");
|
||
}
|
||
|
||
let extension = ExtensionTestUtils.loadExtension({
|
||
manifest: {
|
||
"content_scripts": [{
|
||
"matches": ["http://*/*/file_sample.html"],
|
||
"run_at": "document_start",
|
||
"js": ["content_script.js"],
|
||
}],
|
||
},
|
||
|
||
background: `(${background})(${checkResults})`,
|
||
|
||
files: {
|
||
"content_script.js": `(${content})(${checkResults})`,
|
||
},
|
||
});
|
||
|
||
let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
|
||
|
||
await extension.startup();
|
||
await extension.awaitMessage("content-loaded");
|
||
|
||
let expectedLangs = ["en-US", "en"];
|
||
extension.sendMessage(["expect-results", expectedLangs]);
|
||
await extension.awaitMessage("background-done");
|
||
await extension.awaitMessage("content-done");
|
||
|
||
expectedLangs = ["en-US", "en", "fr-CA", "fr"];
|
||
Preferences.set("intl.accept_languages", expectedLangs.toString());
|
||
extension.sendMessage(["expect-results", expectedLangs]);
|
||
await extension.awaitMessage("background-done");
|
||
await extension.awaitMessage("content-done");
|
||
Preferences.reset("intl.accept_languages");
|
||
|
||
await contentPage.close();
|
||
|
||
await extension.unload();
|
||
});
|
||
|
||
add_task(async function test_get_ui_language() {
|
||
function getResults() {
|
||
return {
|
||
getUILanguage: browser.i18n.getUILanguage(),
|
||
getMessage: browser.i18n.getMessage("@@ui_locale"),
|
||
};
|
||
}
|
||
|
||
function checkResults(source, results, expected) {
|
||
browser.test.assertEq(
|
||
expected,
|
||
results.getUILanguage,
|
||
`Got expected getUILanguage result in ${source}`
|
||
);
|
||
browser.test.assertEq(
|
||
expected,
|
||
results.getMessage,
|
||
`Got expected getMessage result in ${source}`
|
||
);
|
||
}
|
||
|
||
function background(getResultsFn, checkResultsFn) {
|
||
browser.test.onMessage.addListener(([msg, expected]) => {
|
||
checkResultsFn("background", getResultsFn(), expected);
|
||
|
||
browser.test.sendMessage("background-done");
|
||
});
|
||
}
|
||
|
||
function content(getResultsFn, checkResultsFn) {
|
||
browser.test.onMessage.addListener(([msg, expected]) => {
|
||
checkResultsFn("contentScript", getResultsFn(), expected);
|
||
|
||
browser.test.sendMessage("content-done");
|
||
});
|
||
browser.test.sendMessage("content-loaded");
|
||
}
|
||
|
||
let extension = ExtensionTestUtils.loadExtension({
|
||
manifest: {
|
||
"content_scripts": [{
|
||
"matches": ["http://*/*/file_sample.html"],
|
||
"run_at": "document_start",
|
||
"js": ["content_script.js"],
|
||
}],
|
||
},
|
||
|
||
background: `(${background})(${getResults}, ${checkResults})`,
|
||
|
||
files: {
|
||
"content_script.js": `(${content})(${getResults}, ${checkResults})`,
|
||
},
|
||
});
|
||
|
||
let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
|
||
|
||
await extension.startup();
|
||
await extension.awaitMessage("content-loaded");
|
||
|
||
extension.sendMessage(["expect-results", "en-US"]);
|
||
|
||
await extension.awaitMessage("background-done");
|
||
await extension.awaitMessage("content-done");
|
||
|
||
// We don't currently have a good way to mock this.
|
||
if (false) {
|
||
Services.locale.requestedLocales = ["he"];
|
||
|
||
extension.sendMessage(["expect-results", "he"]);
|
||
|
||
await extension.awaitMessage("background-done");
|
||
await extension.awaitMessage("content-done");
|
||
}
|
||
|
||
await contentPage.close();
|
||
|
||
await extension.unload();
|
||
});
|
||
|
||
|
||
add_task(async function test_detect_language() {
|
||
if (AppConstants.MOZ_BUILD_APP !== "browser") {
|
||
// This is not supported on Android.
|
||
return;
|
||
}
|
||
|
||
const af_string = " aam skukuza die naam beteken hy wat skoonvee of hy wat alles onderstebo keer wysig " +
|
||
"bosveldkampe boskampe is kleiner afgeleë ruskampe wat oor min fasiliteite beskik daar is geen restaurante " +
|
||
"of winkels nie en slegs oornagbesoekers word toegelaat bateleur";
|
||
// String with intermixed French/English text
|
||
const fr_en_string = "France is the largest country in Western Europe and the third-largest in Europe as a whole. " +
|
||
"A accès aux chiens et aux frontaux qui lui ont été il peut consulter et modifier ses collections et exporter " +
|
||
"Cet article concerne le pays européen aujourd’hui appelé République française. Pour d’autres usages du nom France, " +
|
||
"Pour une aide rapide et effective, veuiller trouver votre aide dans le menu ci-dessus." +
|
||
"Motoring events began soon after the construction of the first successful gasoline-fueled automobiles. The quick brown fox jumped over the lazy dog";
|
||
|
||
function checkResult(source, result, expected) {
|
||
browser.test.assertEq(expected.isReliable, result.isReliable, "result.confident is true");
|
||
browser.test.assertEq(
|
||
expected.languages.length,
|
||
result.languages.length,
|
||
`result.languages contains the expected number of languages in ${source}`);
|
||
expected.languages.forEach((lang, index) => {
|
||
browser.test.assertEq(
|
||
lang.percentage,
|
||
result.languages[index].percentage,
|
||
`element ${index} of result.languages array has the expected percentage in ${source}`);
|
||
browser.test.assertEq(
|
||
lang.language,
|
||
result.languages[index].language,
|
||
`element ${index} of result.languages array has the expected language in ${source}`);
|
||
});
|
||
}
|
||
|
||
function backgroundScript(checkResultFn) {
|
||
browser.test.onMessage.addListener(([msg, expected]) => {
|
||
browser.i18n.detectLanguage(msg).then(result => {
|
||
checkResultFn("background", result, expected);
|
||
browser.test.sendMessage("background-done");
|
||
});
|
||
});
|
||
}
|
||
|
||
function content(checkResultFn) {
|
||
browser.test.onMessage.addListener(([msg, expected]) => {
|
||
browser.i18n.detectLanguage(msg).then(result => {
|
||
checkResultFn("contentScript", result, expected);
|
||
browser.test.sendMessage("content-done");
|
||
});
|
||
});
|
||
browser.test.sendMessage("content-loaded");
|
||
}
|
||
|
||
let extension = ExtensionTestUtils.loadExtension({
|
||
manifest: {
|
||
"content_scripts": [{
|
||
"matches": ["http://*/*/file_sample.html"],
|
||
"run_at": "document_start",
|
||
"js": ["content_script.js"],
|
||
}],
|
||
},
|
||
|
||
background: `(${backgroundScript})(${checkResult})`,
|
||
|
||
files: {
|
||
"content_script.js": `(${content})(${checkResult})`,
|
||
},
|
||
});
|
||
|
||
let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`);
|
||
|
||
await extension.startup();
|
||
await extension.awaitMessage("content-loaded");
|
||
|
||
let expected = {
|
||
isReliable: true,
|
||
languages: [
|
||
{
|
||
language: "fr",
|
||
percentage: 67,
|
||
},
|
||
{
|
||
language: "en",
|
||
percentage: 32,
|
||
},
|
||
],
|
||
};
|
||
extension.sendMessage([fr_en_string, expected]);
|
||
await extension.awaitMessage("background-done");
|
||
await extension.awaitMessage("content-done");
|
||
|
||
expected = {
|
||
isReliable: true,
|
||
languages: [
|
||
{
|
||
language: "af",
|
||
percentage: 99,
|
||
},
|
||
],
|
||
};
|
||
extension.sendMessage([af_string, expected]);
|
||
await extension.awaitMessage("background-done");
|
||
await extension.awaitMessage("content-done");
|
||
|
||
await contentPage.close();
|
||
|
||
await extension.unload();
|
||
});
|