summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test')
-rw-r--r--toolkit/components/extensions/test/browser/browser_ext_themes_getCurrent_differentExt.js4
-rw-r--r--toolkit/components/extensions/test/browser/browser_ext_themes_sidebars.js8
-rw-r--r--toolkit/components/extensions/test/marionette/manifest-serviceworker.toml1
-rw-r--r--toolkit/components/extensions/test/mochitest/mochitest-common.toml10
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_all_apis.js2
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_contentscript_activeTab.html5
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_extension_getViews.html108
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_runtime_getContexts.html126
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_scripting_executeScript_activeTab.html5
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_subframes_privileges.html67
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_contentscript_errors.js32
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_contentscript_permissions_change.js1
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js118
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_dnr_dynamic_rules.js33
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_dnr_regexFilter_limits.js44
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_dnr_session_rules.js33
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_dnr_static_rules.js22
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_downloads_urlencoded.js2
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_manifest_incognito.js39
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_permission_warnings.js2
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_permissions.js144
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_runtime_getContexts.js180
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_service_worker_messaging.js128
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_storage_telemetry.js45
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_webRequest_eventPage_StreamFilter.js6
-rw-r--r--toolkit/components/extensions/test/xpcshell/xpcshell-common.toml2
-rw-r--r--toolkit/components/extensions/test/xpcshell/xpcshell-serviceworker.toml2
27 files changed, 1003 insertions, 166 deletions
diff --git a/toolkit/components/extensions/test/browser/browser_ext_themes_getCurrent_differentExt.js b/toolkit/components/extensions/test/browser/browser_ext_themes_getCurrent_differentExt.js
index 587c5d4efe..86d794669d 100644
--- a/toolkit/components/extensions/test/browser/browser_ext_themes_getCurrent_differentExt.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_getCurrent_differentExt.js
@@ -139,7 +139,9 @@ add_task(async function test_getcurrent_privateBrowsing() {
"resource://gre/modules/ExtensionCommon.sys.mjs"
);
const { makeWidgetId } = ExtensionCommon;
- privateWin.SidebarUI.show(`${makeWidgetId(extension.id)}-sidebar-action`);
+ privateWin.SidebarController.show(
+ `${makeWidgetId(extension.id)}-sidebar-action`
+ );
let imageLoaded = extension.awaitMessage("theme-image");
Assert.deepEqual(await imageLoaded, { success: true }, "theme image loaded");
diff --git a/toolkit/components/extensions/test/browser/browser_ext_themes_sidebars.js b/toolkit/components/extensions/test/browser/browser_ext_themes_sidebars.js
index 0d2e69716d..492fe3a263 100644
--- a/toolkit/components/extensions/test/browser/browser_ext_themes_sidebars.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_sidebars.js
@@ -17,7 +17,7 @@ async function test_sidebar_theme(theme, isBrightText) {
const sidebarBox = document.getElementById("sidebar-box");
const browserRoot = document.documentElement;
- const content = SidebarUI.browser.contentWindow;
+ const content = SidebarController.browser.contentWindow;
const root = content.document.documentElement;
ok(
@@ -184,7 +184,7 @@ add_task(async function test_support_sidebar_colors() {
for (let command of ["viewBookmarksSidebar", "viewHistorySidebar"]) {
info("Executing command: " + command);
- await SidebarUI.show(command);
+ await SidebarController.show(command);
await test_sidebar_theme(
{
@@ -263,7 +263,7 @@ add_task(async function test_support_sidebar_border_color() {
"Sidebar splitter should be colored properly"
);
- SidebarUI.reversePosition();
+ SidebarController.reversePosition();
is(
sidebarSplitterCS.borderInlineStartColor,
@@ -271,7 +271,7 @@ add_task(async function test_support_sidebar_border_color() {
"Sidebar splitter should be colored properly after switching sides"
);
- SidebarUI.reversePosition();
+ SidebarController.reversePosition();
}
await extension.unload();
diff --git a/toolkit/components/extensions/test/marionette/manifest-serviceworker.toml b/toolkit/components/extensions/test/marionette/manifest-serviceworker.toml
index c8035f80c2..04bdc4e17e 100644
--- a/toolkit/components/extensions/test/marionette/manifest-serviceworker.toml
+++ b/toolkit/components/extensions/test/marionette/manifest-serviceworker.toml
@@ -1,4 +1,5 @@
[DEFAULT]
+skip-if = ["!nightly_build"] # MOZ_WEBEXT_WEBIDL_ENABLED is only defined on nightly
["test_extension_serviceworkers_purged_on_pref_disabled.py"]
["test_temporary_extension_serviceworkers_not_persisted.py"]
diff --git a/toolkit/components/extensions/test/mochitest/mochitest-common.toml b/toolkit/components/extensions/test/mochitest/mochitest-common.toml
index 782069a79c..f49fb131c5 100644
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.toml
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.toml
@@ -268,6 +268,8 @@ skip-if = [
"http2",
]
+["test_ext_extension_getViews.html"]
+
["test_ext_extension_iframe_messaging.html"]
skip-if = [
"http3",
@@ -350,6 +352,8 @@ skip-if = [
"http2",
]
+["test_ext_runtime_getContexts.html"]
+
["test_ext_script_filenames.html"]
["test_ext_scripting_contentScripts.html"]
@@ -443,12 +447,6 @@ skip-if = [
]
["test_ext_subframes_privileges.html"]
-skip-if = [
- "os == 'android'", # Bug 1845918
- "verify", # Bug 1489771
- "http3",
- "http2",
-]
["test_ext_tabs_captureTab.html"]
skip-if = [
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js b/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js
index 95ac9af50d..8dec0c6ae5 100644
--- a/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js
+++ b/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js
@@ -89,8 +89,10 @@ let expectedBackgroundApis = [
"permissions.remove",
"permissions.onAdded",
"permissions.onRemoved",
+ "runtime.ContextType",
"runtime.getBackgroundPage",
"runtime.getBrowserInfo",
+ "runtime.getContexts",
"runtime.getPlatformInfo",
"runtime.onConnectExternal",
"runtime.onInstalled",
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_activeTab.html b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_activeTab.html
index 076c177dfa..28bbe3b253 100644
--- a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_activeTab.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_activeTab.html
@@ -14,7 +14,10 @@
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
- set: [["extensions.manifestV3.enabled", true]],
+ set: [
+ ["extensions.manifestV3.enabled", true],
+ ["extensions.originControls.grantByDefault", false],
+ ],
});
});
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_extension_getViews.html b/toolkit/components/extensions/test/mochitest/test_ext_extension_getViews.html
new file mode 100644
index 0000000000..9309d45cdf
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_extension_getViews.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>extension.getViews Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <script type="text/javascript" src="head.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+function genericChecker() {
+ const params = new URLSearchParams(window.location.search);
+ const kind = params.get("kind");
+ const createdTabIds = [];
+
+ browser.test.onMessage.addListener(async msg => {
+ if (msg == `${kind}-test-get-views`) {
+ try {
+ let result = browser.extension.getViews({});
+ browser.test.assertEq(3, result.length, "Expect 3 extension views to be found");
+
+ result = browser.extension.getViews({ type: "tab" });
+ browser.test.assertEq(1, result.length, "Expect 1 tab extension view to be found");
+
+ result = browser.extension.getViews({ type: "popup" });
+ browser.test.assertEq(1, result.length, "Expect 1 popup extension view to be found");
+
+ browser.test.sendMessage(`${msg}:done`);
+ } catch (err) {
+ browser.test.fail(`browser.extension.getViews exception: ${err}`);
+ browser.test.sendMessage(`${msg}:done`);
+ }
+ } else if (msg == `${kind}-open-tab`) {
+ const tab = await browser.tabs.create({ url: "/page.html?kind=tab" });
+ createdTabIds.push(tab.id);
+ } else if (msg == `${kind}-close-tabs`) {
+ await browser.tabs.remove(createdTabIds);
+ browser.test.sendMessage(`${msg}:done`);
+ }
+ });
+
+ browser.test.log(`${kind} extension page loaded`);
+ browser.test.sendMessage(`${kind}-loaded`);
+}
+
+add_task(async function test_runtime_getContexts() {
+ const EXT_ID = "runtime-getContexts@mochitest";
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary", // To automatically show sidebar on load.
+ incognitoOverride: "spanning",
+ manifest: {
+ manifest_version: 3,
+ browser_specific_settings: { gecko: { id: EXT_ID } },
+
+ action: {
+ default_popup: "page.html?kind=action",
+ default_area: "navbar",
+ },
+
+ background: {
+ page: "page.html?kind=background",
+ },
+ },
+
+ files: {
+ "page.html": `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"><\/head>
+ <body>
+ <script src="page.js"><\/script>
+ <\/body>
+ <\/html>
+ `,
+
+ "page.js": genericChecker,
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("background-loaded");
+
+ extension.sendMessage("background-open-tab");
+ await extension.awaitMessage("tab-loaded");
+
+ await AppTestDelegate.clickBrowserAction(window, extension);
+ await extension.awaitMessage("action-loaded");
+
+ extension.sendMessage("background-test-get-views");
+ await extension.awaitMessage("background-test-get-views:done");
+
+ // Close popup window.
+ await AppTestDelegate.closeBrowserAction(window, extension);
+
+ // Close extension page tabs.
+ extension.sendMessage("background-close-tabs");
+ await extension.awaitMessage("background-close-tabs:done");
+
+ await extension.unload();
+});
+
+</script>
+</body>
+</html>
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_runtime_getContexts.html b/toolkit/components/extensions/test/mochitest/test_ext_runtime_getContexts.html
new file mode 100644
index 0000000000..fa3b7385da
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_runtime_getContexts.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>runtime.getContexts Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <script type="text/javascript" src="head.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+function genericChecker() {
+ const params = new URLSearchParams(window.location.search);
+ const kind = params.get("kind");
+ const createdTabIds = [];
+
+ browser.test.onMessage.addListener(async msg => {
+ if (msg == `${kind}-test-get-contexts`) {
+ try {
+ const result = await browser.runtime.getContexts({});
+ browser.test.assertEq(3, result.length, "Expect 3 extension contexts to be found");
+
+ const bgContext = result.find(it => it.contextType === browser.runtime.ContextType.BACKGROUND);
+ const tabContext = result.find(it => it.documentUrl.endsWith("kind=tab"));
+ const popupContext = result.find(it => it.documentUrl.endsWith("kind=action"));
+
+ browser.test.assertEq(window.location.href, bgContext.documentUrl, "background context has the expected documentUrl");
+ browser.test.assertEq(-1, bgContext.windowId, "background context has the expected windowId");
+ browser.test.assertEq(-1, bgContext.tabId, "background context has the expected tabId");
+ browser.test.assertEq("TAB", tabContext.contextType, "Got expected tab context type");
+ browser.test.assertTrue(
+ typeof tabContext.windowId === "number" && tabContext.windowId > 0,
+ "Got expected windowId on tab context"
+ );
+ browser.test.assertTrue(
+ typeof tabContext.windowId === "number" && tabContext.tabId > 0,
+ "Got expected tabId on tab context"
+ );
+ browser.test.assertEq(
+ tabContext.windowId,
+ popupContext.windowId,
+ "Poup and tab expected to have the same windowId"
+ );
+ browser.test.assertEq(-1, popupContext.tabId, "popup context has the expected tabId");
+ browser.test.assertEq("POPUP", popupContext.contextType, "Got expected popup context type");
+
+ browser.test.sendMessage(`${msg}:done`);
+ } catch (err) {
+ browser.test.fail(`broser.runtime.getContexts call rejected: ${err}`);
+ browser.test.sendMessage(`${msg}:done`);
+ }
+ } else if (msg == `${kind}-open-tab`) {
+ const tab = await browser.tabs.create({ url: "/page.html?kind=tab" });
+ createdTabIds.push(tab.id);
+ } else if (msg == `${kind}-close-tabs`) {
+ await browser.tabs.remove(createdTabIds);
+ browser.test.sendMessage(`${msg}:done`);
+ }
+ });
+
+ browser.test.log(`${kind} extension page loaded`);
+ browser.test.sendMessage(`${kind}-loaded`);
+}
+
+add_task(async function test_runtime_getContexts() {
+ const EXT_ID = "runtime-getContexts@mochitest";
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary", // To automatically show sidebar on load.
+ incognitoOverride: "spanning",
+ manifest: {
+ manifest_version: 3,
+ browser_specific_settings: { gecko: { id: EXT_ID } },
+
+ action: {
+ default_popup: "page.html?kind=action",
+ default_area: "navbar",
+ },
+
+ background: {
+ page: "page.html?kind=background",
+ },
+ },
+
+ files: {
+ "page.html": `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"><\/head>
+ <body>
+ <script src="page.js"><\/script>
+ <\/body>
+ <\/html>
+ `,
+
+ "page.js": genericChecker,
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("background-loaded");
+
+ extension.sendMessage("background-open-tab");
+ await extension.awaitMessage("tab-loaded");
+
+ await AppTestDelegate.clickBrowserAction(window, extension);
+ await extension.awaitMessage("action-loaded");
+
+ extension.sendMessage("background-test-get-contexts");
+ await extension.awaitMessage("background-test-get-contexts:done");
+
+ // Close popup window.
+ await AppTestDelegate.closeBrowserAction(window, extension);
+
+ // Close extension page tabs.
+ extension.sendMessage("background-close-tabs");
+ await extension.awaitMessage("background-close-tabs:done");
+
+ await extension.unload();
+});
+
+</script>
+</body>
+</html>
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_scripting_executeScript_activeTab.html b/toolkit/components/extensions/test/mochitest/test_ext_scripting_executeScript_activeTab.html
index 5eb2193409..a0ceed72d5 100644
--- a/toolkit/components/extensions/test/mochitest/test_ext_scripting_executeScript_activeTab.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_scripting_executeScript_activeTab.html
@@ -27,7 +27,10 @@ const makeExtension = ({ manifest: manifestProps, ...otherProps }) => {
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
- set: [["extensions.manifestV3.enabled", true]],
+ set: [
+ ["extensions.manifestV3.enabled", true],
+ ["extensions.originControls.grantByDefault", false],
+ ],
});
});
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_subframes_privileges.html b/toolkit/components/extensions/test/mochitest/test_ext_subframes_privileges.html
index f791d08602..0586275808 100644
--- a/toolkit/components/extensions/test/mochitest/test_ext_subframes_privileges.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_subframes_privileges.html
@@ -14,6 +14,32 @@
"use strict";
/* eslint-disable mozilla/balanced-listeners */
+const {
+ WebExtensionPolicy,
+} = SpecialPowers.Cu.getGlobalForObject(SpecialPowers.Services);
+
+
+// Some tests load non-moz-extension:-URLs in their extension document. When
+// extensions run in-process (extensions.webextensions.remote set to false),
+// that fails.
+// For details, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1724099 and
+// the same function in toolkit/components/extensions/test/xpcshell/head.js
+async function allow_unsafe_parent_loads_when_extensions_not_remote() {
+ if (!WebExtensionPolicy.useRemoteWebExtensions) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["security.allow_unsafe_parent_loads", true]],
+ });
+ }
+}
+
+async function revert_allow_unsafe_parent_loads_when_extensions_not_remote() {
+ if (!WebExtensionPolicy.useRemoteWebExtensions) {
+ // Assume that the previous call to pushPrefEnv was from
+ // allow_unsafe_parent_loads_when_extensions_not_remote.
+ await SpecialPowers.popPrefEnv();
+ }
+}
+
add_task(async function test_webext_tab_subframe_privileges() {
function background() {
browser.runtime.onMessage.addListener(async ({msg, success, tabId, error}) => {
@@ -198,19 +224,25 @@ add_task(async function test_webext_contentscript_iframe_subframe_privileges() {
});
add_task(async function test_webext_background_remote_subframe_privileges() {
- function backgroundSubframeScript() {
+ // file_remote_frame.html is opened at the same origin as this test page.
+ document.cookie = "cookie=monster";
+
+ function backgroundScript() {
window.addEventListener("message", evt => {
- browser.test.assertEq("http://mochi.test:8888", evt.origin, "postmessage origin ok");
+ browser.test.assertTrue(
+ evt.origin === "http://mochi.test:8888" ||
+ evt.origin === "https://mochi.test:8888", // using https-first, http2/http3 server.
+ `postmessage origin ok: ${evt.origin}`
+ );
browser.test.assertFalse(evt.data.tabs, "remote frame cannot access webextension APIs");
browser.test.assertEq("cookie=monster", evt.data.cookie, "Expected cookie value");
browser.test.notifyPass("webext-background-subframe-privileges");
}, {once: true});
- browser.cookies.set({url: "http://mochi.test:8888", name: "cookie", "value": "monster"});
}
let extensionData = {
manifest: {
- permissions: ["cookies", "*://mochi.test/*", "tabs"],
+ permissions: ["*://mochi.test/*", "tabs"],
background: {
page: "background.html",
},
@@ -219,32 +251,32 @@ add_task(async function test_webext_background_remote_subframe_privileges() {
"background.html": `<!DOCTYPE>
<head>
<meta charset="utf-8">
- <script src="background-subframe.js"><\/script>
+ <script src="background.js"><\/script>
</head>
<body>
<iframe src='${SimpleTest.getTestFileURL("file_remote_frame.html")}'></iframe>
</body>
</html>`,
- "background-subframe.js": backgroundSubframeScript,
+ "background.js": backgroundScript,
},
};
// Need remote webextensions to be able to load remote content from a background page.
- if (!SpecialPowers.getBoolPref("extensions.webextensions.remote", true)) {
- return;
- }
+ await allow_unsafe_parent_loads_when_extensions_not_remote();
let extension = ExtensionTestUtils.loadExtension(extensionData);
await extension.startup();
await extension.awaitFinish("webext-background-subframe-privileges");
await extension.unload();
+ await revert_allow_unsafe_parent_loads_when_extensions_not_remote();
});
// Test a moz-extension:// iframe inside a content iframe in an extension page.
add_task(async function test_sub_subframe_conduit_verified_env() {
let manifest = {
content_scripts: [{
- matches: ["http://mochi.test/*/file_sample.html"],
+ // Note: no :8888 because of bug 1468162.
+ matches: ["*://mochi.test/*/file_sample.html"],
all_frames: true,
js: ["cs.js"],
}],
@@ -311,19 +343,20 @@ add_task(async function test_sub_subframe_conduit_verified_env() {
is(err, "Unknown sender or wrong actor for recvCreateProxyContext");
}
- let remote = SpecialPowers.getBoolPref("extensions.webextensions.remote");
-
let badProcess = { message: /Bad {[\w-]+} process: web/ };
let badPrincipal = { message: /Bad {[\w-]+} principal: http/ };
- consoleMonitor.start(remote ? [badPrincipal, badProcess] : [badProcess]);
+ consoleMonitor.start([badPrincipal, badProcess]);
let extension = ExtensionTestUtils.loadExtension({ manifest, files });
+
+
+ // Need OOP to spoof from a web iframe inside background page.
+ await allow_unsafe_parent_loads_when_extensions_not_remote();
await extension.startup();
- if (remote) {
- info("Need OOP to spoof from a web iframe inside background page.");
- await expectErrors(extension);
- }
+ info("Spoof from a web iframe inside background page.");
+ await expectErrors(extension);
+ await revert_allow_unsafe_parent_loads_when_extensions_not_remote();
info("Try spoofing from the web process.");
let win = window.open("./file_sample.html");
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_errors.js b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_errors.js
index 6fae3b838a..c4f504c219 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_errors.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_errors.js
@@ -18,6 +18,11 @@ add_task(async function test_cached_contentscript_on_document_start() {
// Use distinct content scripts as some will throw and would prevent executing the next script
{
matches: ["http://*/*/file_content_script_errors.html"],
+ js: ["script_does_not_exist.js"],
+ run_at: "document_start",
+ },
+ {
+ matches: ["http://*/*/file_content_script_errors.html"],
js: ["script1.js"],
run_at: "document_start",
},
@@ -41,6 +46,16 @@ add_task(async function test_cached_contentscript_on_document_start() {
js: ["script5.js"],
run_at: "document_start",
},
+ {
+ matches: ["http://*/*/file_content_script_errors.html"],
+ js: ["script6.js"],
+ run_at: "document_start",
+ },
+ {
+ matches: ["http://*/*/file_content_script_errors.html"],
+ js: ["script7.js"],
+ run_at: "document_start",
+ },
],
},
@@ -58,6 +73,12 @@ add_task(async function test_cached_contentscript_on_document_start() {
)
`,
"script5.js": `
+ throw null;
+ `,
+ "script6.js": `
+ throw Symbol("MySymbol");
+ `,
+ "script7.js": `
Promise.reject("rejected promise");
(async () => {
@@ -78,19 +99,22 @@ add_task(async function test_cached_contentscript_on_document_start() {
},
});
+ await extension.startup();
+
// Error messages, in roughly the order they appear above.
let expectedMessages = [
+ `Unable to load script: moz-extension://${extension.uuid}/script_does_not_exist.js`,
"Error: Object exception",
"uncaught exception: String exception",
"ReferenceError: undefinedSymbol is not defined",
"SyntaxError: expected expression, got ')'",
+ "uncaught exception: null",
+ "uncaught exception: Symbol(MySymbol)",
"uncaught exception: rejected promise",
"Error: async function exception",
"ReferenceError: asyncUndefinedSymbol is not defined",
];
- await extension.startup();
-
// Load a first page in order to be able to register a console listener in the content process.
// This has to be done in the same domain of the second page to stay in the same process.
let contentPage = await ExtensionTestUtils.loadContentPage(TEST_URL_1);
@@ -110,7 +134,7 @@ add_task(async function test_cached_contentscript_on_document_start() {
innerWindowID: error.innerWindowID,
message: error.errorMessage,
});
- if (this.collectedErrors.length == 7) {
+ if (this.collectedErrors.length == 10) {
Services.console.unregisterListener(this);
resolve(this.collectedErrors);
}
@@ -128,7 +152,7 @@ add_task(async function test_cached_contentscript_on_document_start() {
await extension.awaitMessage("content-script-loaded");
- equal(errors.length, 7);
+ equal(errors.length, 10);
let messages = [];
for (const { innerWindowID, message } of errors) {
equal(
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_permissions_change.js b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_permissions_change.js
index 842994858e..dbaa01fa86 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_permissions_change.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_permissions_change.js
@@ -1,6 +1,7 @@
"use strict";
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
+Services.prefs.setBoolPref("extensions.originControls.grantByDefault", false);
const server = createHttpServer({ hosts: ["example.com", "example.net"] });
server.registerDirectory("/data/", do_get_file("data"));
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js b/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js
index e7dd1e99c6..b8fa021a1c 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_cookieBehaviors.js
@@ -61,17 +61,34 @@ function assertCookiesForHost(url, cookiesCount, message) {
// Test that the indexedDB and localStorage are allowed in an extension page
// and that the indexedDB is allowed in a extension worker.
add_task(async function test_ext_page_allowed_storage() {
- function testWebStorages() {
+ async function testWebStorages() {
const url = window.location.href;
try {
// In a webpage accessing indexedDB throws on cookiesBehavior reject,
// here we verify that doesn't happen for an extension page.
+
+ await new Promise((resolve, reject) => {
+ const begin = indexedDB.open("door");
+ begin.onsuccess = resolve;
+ begin.onerror = err => reject(err.target);
+ });
+
+ const dbs = await indexedDB.databases();
browser.test.assertTrue(
- indexedDB,
- "IndexedDB global should be accessible"
+ dbs.some(elem => elem.name === "door"),
+ "Just created database should be found"
);
+ await new Promise((resolve, reject) => {
+ const end = indexedDB.deleteDatabase("door");
+ end.onsuccess = () => {
+ browser.test.log(`IndexedDB is accessible`);
+ resolve();
+ };
+ end.onerror = reject;
+ });
+
// In a webpage localStorage is undefined on cookiesBehavior reject,
// here we verify that doesn't happen for an extension page.
browser.test.assertTrue(
@@ -97,9 +114,23 @@ add_task(async function test_ext_page_allowed_storage() {
}
function testWorker() {
- this.onmessage = () => {
+ this.onmessage = async () => {
try {
void indexedDB;
+ await new Promise((resolve, reject) => {
+ const begin = indexedDB.open("door");
+ begin.onerror = err => reject(err.target);
+ begin.onsuccess = () => {
+ indexedDB
+ .databases()
+ .then(() => {
+ const end = indexedDB.deleteDatabase("door");
+ end.onerror = err => reject(err.target);
+ end.onsuccess = resolve;
+ })
+ .catch(reject);
+ };
+ });
postMessage({ pass: true });
} catch (err) {
postMessage({ pass: false });
@@ -448,9 +479,43 @@ add_task(
let extFrame = this.content.document.querySelector("iframe#ext");
let webFrame = this.content.document.querySelector("iframe#web");
- function testIDB(win) {
+ async function testIDB(win) {
try {
- void win.indexedDB;
+ if (!win.indexedDB) {
+ Assert.ok(false, "IndexedDB global should be accessible");
+ return;
+ }
+
+ await new Promise((resolve, reject) => {
+ const req = win.indexedDB.open("door");
+ req.onerror = err => {
+ reject(err.target);
+ Assert.ok(
+ false,
+ "IDB open should be accessible: " + err.target.message
+ );
+ };
+ req.onsuccess = resolve;
+ });
+
+ const dbs = await win.indexedDB.databases();
+ Assert.ok(
+ dbs.some(elem => elem.name === "door"),
+ "Just created database should be found"
+ );
+
+ await new Promise((resolve, reject) => {
+ const req = win.indexedDB.deleteDatabase("door");
+ req.onerror = err => {
+ reject(err.target);
+ Assert.ok(
+ false,
+ "IDB deleteDatabase should be accessible: " + err.target.message
+ );
+ };
+ req.onsuccess = resolve;
+ });
+
return { success: true };
} catch (err) {
return { error: `${err}` };
@@ -467,10 +532,10 @@ add_task(
}
return {
- extTopLevel: testIDB(this.content),
+ extTopLevel: await testIDB(this.content),
// TODO bug 1762638: Execute the following in their own tasks.
- extSubFrame: testIDB(extFrame.contentWindow),
- webSubFrame: testIDB(webFrame.contentWindow),
+ extSubFrame: await testIDB(extFrame.contentWindow),
+ webSubFrame: await testIDB(webFrame.contentWindow),
webServiceWorker: await testServiceWorker(webFrame.contentWindow),
};
});
@@ -485,9 +550,30 @@ add_task(
return new Promise(resolve => {
let frame = this.content.document.createElement("iframe");
frame.setAttribute("src", `moz-extension://${uuid}/subframe.html`);
- frame.onload = () => {
+ frame.onload = async () => {
try {
- void frame.contentWindow.indexedDB;
+ if (!frame.contentWindow.indexedDB) {
+ throw Error("IndexedDB global should be accessible");
+ }
+ const indexedDB = frame.contentWindow.indexedDB;
+
+ await new Promise((success, failure) => {
+ const begin = indexedDB.open("door");
+ begin.onsuccess = success;
+ begin.onerror = err => failure(err.target);
+ });
+
+ const dbs = await indexedDB.databases();
+ if (!dbs.some(elem => elem.name === "door")) {
+ throw Error("Just created database should be found");
+ }
+
+ await new Promise((success, failure) => {
+ const end = indexedDB.deleteDatabase("door");
+ end.onsuccess = success;
+ end.onerror = err => failure(err.target);
+ });
+
resolve({ success: true });
} catch (err) {
resolve({ error: `${err}` });
@@ -512,7 +598,7 @@ add_task(
Assert.deepEqual(
results.webSubFrame,
- { error: "SecurityError: The operation is insecure." },
+ { error: "SecurityError: IDBFactory.open: The operation is insecure" },
"IndexedDB not allowed in a subframe webpage with a top level extension page"
);
Assert.deepEqual(
@@ -544,8 +630,14 @@ add_task(async function test_content_script_on_cookieBehaviorReject() {
function contentScript() {
// Ensure that when the current cookieBehavior doesn't allow a webpage to use indexedDB
// or localStorage, then a WebExtension content script is not allowed to use it as well.
+ browser.test.assertTrue(indexedDB, "IndexedDB handle should be accessible");
+
browser.test.assertThrows(
- () => indexedDB,
+ () => {
+ indexedDB.open("door").onsuccess = () => {
+ browser.test.fail(`Unreached function`);
+ };
+ },
/The operation is insecure/,
"a content script can't use indexedDB from a page where it is disallowed"
);
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_dynamic_rules.js b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_dynamic_rules.js
index 4ba120852f..ff87da1dde 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_dynamic_rules.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_dynamic_rules.js
@@ -414,10 +414,10 @@ add_task(async function test_save_and_load_dynamic_rules() {
browser.test.onMessage.addListener(async (msg, ...args) => {
switch (msg) {
case "assertGetDynamicRules": {
- const [{ expectedRules }] = args;
+ const [{ expectedRules, filter }] = args;
browser.test.assertDeepEq(
expectedRules,
- await dnr.getDynamicRules(),
+ await dnr.getDynamicRules(filter),
"getDynamicRules() resolves to the expected dynamic rules"
);
break;
@@ -503,6 +503,35 @@ add_task(async function test_save_and_load_dynamic_rules() {
expectedRules: getSchemaNormalizedRules(extension, rules),
});
+ info("Verify getDynamicRules with some filters");
+ // An empty list of rule IDs should return no rule.
+ await callTestMessageHandler(extension, "assertGetDynamicRules", {
+ expectedRules: [],
+ filter: { ruleIds: [] },
+ });
+ // Non-existent rule ID.
+ await callTestMessageHandler(extension, "assertGetDynamicRules", {
+ expectedRules: [],
+ filter: { ruleIds: [456] },
+ });
+ await callTestMessageHandler(extension, "assertGetDynamicRules", {
+ expectedRules: getSchemaNormalizedRules(extension, [rules[0]]),
+ filter: { ruleIds: [rules[0].id] },
+ });
+ await callTestMessageHandler(extension, "assertGetDynamicRules", {
+ expectedRules: getSchemaNormalizedRules(extension, [rules[1]]),
+ filter: { ruleIds: [rules[1].id] },
+ });
+ await callTestMessageHandler(extension, "assertGetDynamicRules", {
+ expectedRules: getSchemaNormalizedRules(extension, rules),
+ filter: { ruleIds: rules.map(rule => rule.id) },
+ });
+ // When `ruleIds` isn't defined, we return all the rules.
+ await callTestMessageHandler(extension, "assertGetDynamicRules", {
+ expectedRules: getSchemaNormalizedRules(extension, rules),
+ filter: {},
+ });
+
const extUUID = extension.uuid;
const dnrStore = ExtensionDNRStore._getStoreForTesting();
await dnrStore._savePromises.get(extUUID);
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_regexFilter_limits.js b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_regexFilter_limits.js
index 443f69c2d1..69635e4c80 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_regexFilter_limits.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_regexFilter_limits.js
@@ -26,33 +26,6 @@ add_setup(async () => {
await ExtensionTestUtils.startAddonManager();
});
-const _origDescs = {};
-function restoreDefaultDnrLimit(key) {
- info(`Restoring original value of ExtensionDNRLimits.${key}`);
- Object.defineProperty(ExtensionDNRLimits, key, _origDescs[key]);
-}
-function overrideDefaultDnrLimit(key, value) {
- // Until DNR limits can be customized through prefs (bug 1803370), we need to
- // overwrite the internals here in the parent process. That is sufficient to
- // control the limits. Notably, this does NOT affect the values of the
- // constants exposed through the declarativeNetRequest keyspace, because
- // their values are directly read from the extension (child) process.
- if (!_origDescs[key]) {
- _origDescs[key] = Object.getOwnPropertyDescriptor(ExtensionDNRLimits, key);
- registerCleanupFunction(() => restoreDefaultDnrLimit(key));
- }
- Assert.ok(
- typeof value === "number" && Number.isInteger(value),
- `Setting ExtensionDNRLimits.${key} = ${value} (was: ${ExtensionDNRLimits[key]})`
- );
- Object.defineProperty(ExtensionDNRLimits, key, {
- configurable: true,
- writable: true,
- enumerable: true,
- value,
- });
-}
-
// Create an extension composed of the given test cases, and start or reload
// the extension before each test case.
//
@@ -302,7 +275,10 @@ add_task(async function session_and_dynamic_regexFilter_limit() {
setup() {
// Artificially decrease the max number of allowed regexFilter rules,
// so that whatever that was stored on disk is no longer within quota.
- overrideDefaultDnrLimit("MAX_NUMBER_OF_REGEX_RULES", 1);
+ Services.prefs.setIntPref(
+ "extensions.dnr.max_number_of_regex_rules",
+ 1
+ );
},
backgroundFn: testPart3_too_many_regexFilters_stored_after_lowering_quota,
checkConsoleMessages: expectError,
@@ -311,7 +287,9 @@ add_task(async function session_and_dynamic_regexFilter_limit() {
name: "testPart4_reload_after_quota_back",
setup() {
// Restore the original quota after it was lowered in testPart3.
- restoreDefaultDnrLimit("MAX_NUMBER_OF_REGEX_RULES");
+ Services.prefs.clearUserPref(
+ "extensions.dnr.max_number_of_regex_rules"
+ );
},
backgroundFn: testPart4_reload_after_quota_back,
checkConsoleMessages: noErrors,
@@ -525,8 +503,8 @@ add_task(async function static_regexFilter_limit() {
{
name: "testPart5_after_doubling_quota",
setup() {
- overrideDefaultDnrLimit(
- "MAX_NUMBER_OF_REGEX_RULES",
+ Services.prefs.setIntPref(
+ "extensions.dnr.max_number_of_regex_rules",
2 * MAX_NUMBER_OF_REGEX_RULES
);
},
@@ -537,7 +515,9 @@ add_task(async function static_regexFilter_limit() {
name: "testPart6_after_restoring_original_quota_half",
setup() {
// Restore the original quota after it was raised in testPart5.
- restoreDefaultDnrLimit("MAX_NUMBER_OF_REGEX_RULES");
+ Services.prefs.clearUserPref(
+ "extensions.dnr.max_number_of_regex_rules"
+ );
},
backgroundFn: testPart6_after_restoring_original_quota_half,
checkConsoleMessages: (n, m) =>
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_session_rules.js b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_session_rules.js
index 5f0b0d72a2..6ac80a4ee7 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_session_rules.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_session_rules.js
@@ -218,6 +218,39 @@ add_task(async function register_and_retrieve_session_rules() {
"getSessionRules() returns all registered session rules"
);
+ browser.test.assertDeepEq(
+ [],
+ await dnr.getSessionRules({ ruleIds: [] }),
+ "getSessionRules() returns no rule because ruleIds is an empty array"
+ );
+ browser.test.assertDeepEq(
+ [],
+ await dnr.getSessionRules({ ruleIds: [1234567890] }),
+ "getSessionRules() returns no rule because rule ID is non-existent"
+ );
+ browser.test.assertDeepEq(
+ [RULE_4321_OUT],
+ await dnr.getSessionRules({ ruleIds: [4321] }),
+ "getSessionRules() returns a rule"
+ );
+ browser.test.assertDeepEq(
+ [RULE_1234_OUT],
+ await dnr.getSessionRules({ ruleIds: [1234] }),
+ "getSessionRules() returns a rule"
+ );
+ // The order is the same as the original input above, not the order of
+ // the IDs in `ruleIds`.
+ browser.test.assertDeepEq(
+ [RULE_4321_OUT, RULE_1234_OUT],
+ await dnr.getSessionRules({ ruleIds: [1234, 4321] }),
+ "getSessionRules() returns two rules"
+ );
+ browser.test.assertDeepEq(
+ [RULE_4321_OUT, RULE_1234_OUT],
+ await dnr.getSessionRules({}),
+ "getSessionRules() returns all the rules because there is no ruleIds"
+ );
+
await browser.test.assertRejects(
dnr.updateSessionRules({
addRules: [RULE_9001_IN, RULE_1234_IN],
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_static_rules.js b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_static_rules.js
index 4d20bd330e..7d5befef2e 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_static_rules.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_static_rules.js
@@ -1269,13 +1269,13 @@ add_task(async function test_static_rulesets_limits() {
},
{
message:
- /declarative_net_request: Enabled static rulesets are exceeding the MAX_NUMBER_OF_ENABLED_STATIC_RULESETS limit .* "ruleset_10"/,
+ /declarative_net_request: Enabled static rulesets are exceeding the MAX_NUMBER_OF_ENABLED_STATIC_RULESETS limit .* "ruleset_20"/,
},
// Error reported on the browser console as part of loading enabled rulesets)
// on enabled rulesets being ignored because exceeding the limit.
{
message:
- /Ignoring enabled static ruleset exceeding the MAX_NUMBER_OF_ENABLED_STATIC_RULESETS .* "ruleset_10"/,
+ /Ignoring enabled static ruleset exceeding the MAX_NUMBER_OF_ENABLED_STATIC_RULESETS .* "ruleset_20"/,
},
],
});
@@ -1285,7 +1285,7 @@ add_task(async function test_static_rulesets_limits() {
);
extension.sendMessage("updateEnabledRulesets", {
disableRulesetIds: ["ruleset_0"],
- enableRulesetIds: ["ruleset_10", "ruleset_11"],
+ enableRulesetIds: ["ruleset_20", "ruleset_21"],
});
await Assert.rejects(
@@ -1313,19 +1313,19 @@ add_task(async function test_static_rulesets_limits() {
"updateEnabledRulesets",
{
disableRulesetIds: ["ruleset_0"],
- enableRulesetIds: ["ruleset_10"],
+ enableRulesetIds: ["ruleset_20"],
},
{
- disableRulesetIds: ["ruleset_10"],
- enableRulesetIds: ["ruleset_11"],
+ disableRulesetIds: ["ruleset_20"],
+ enableRulesetIds: ["ruleset_21"],
}
);
await extension.awaitMessage("updateEnabledRulesets:done");
- // Expect ruleset_0 disabled, ruleset_10 to be enabled but then disabled by the
- // second update queued after the first one, and ruleset_11 to be enabled.
+ // Expect ruleset_0 disabled, ruleset_20 to be enabled but then disabled by the
+ // second update queued after the first one, and ruleset_21 to be enabled.
delete expectedEnabledRulesets.ruleset_0;
- expectedEnabledRulesets.ruleset_11 = getSchemaNormalizedRules(
+ expectedEnabledRulesets.ruleset_21 = getSchemaNormalizedRules(
extension,
rules
);
@@ -1356,10 +1356,10 @@ add_task(async function test_static_rulesets_limits() {
await assertDNRStoreData(dnrStore, extension, expectedEnabledRulesets);
extension.sendMessage("updateEnabledRulesets", {
- disableRulesetIds: ["ruleset_11"],
+ disableRulesetIds: ["ruleset_21"],
});
await extension.awaitMessage("updateEnabledRulesets:done");
- delete expectedEnabledRulesets.ruleset_11;
+ delete expectedEnabledRulesets.ruleset_21;
await assertDNRGetEnabledRulesets(
extension,
Array.from(Object.keys(expectedEnabledRulesets))
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_downloads_urlencoded.js b/toolkit/components/extensions/test/xpcshell/test_ext_downloads_urlencoded.js
index ae40faf909..8532ce4a99 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_downloads_urlencoded.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_downloads_urlencoded.js
@@ -83,7 +83,7 @@ add_task(async function test_decoded_filename_download() {
const FILE_NAME_DECODED_2 = "file\u{0001F6B2}encoded.txt";
const FILE_NAME_ENCODED_URL_2 = BASE + "/" + FILE_NAME_ENCODED_2;
const FILE_NAME_ENCODED_3 = "file%X%20encode.txt";
- const FILE_NAME_DECODED_3 = "file%X encode.txt";
+ const FILE_NAME_DECODED_3 = "file_X encode.txt";
const FILE_NAME_ENCODED_URL_3 = BASE + "/" + FILE_NAME_ENCODED_3;
const FILE_NAME_ENCODED_4 = "file%E3%80%82encode.txt";
const FILE_NAME_DECODED_4 = "file\u3002encode.txt";
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_manifest_incognito.js b/toolkit/components/extensions/test/xpcshell/test_ext_manifest_incognito.js
index 4330e1b681..6c2c0f65f9 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_manifest_incognito.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_manifest_incognito.js
@@ -27,19 +27,48 @@ add_task(async function test_manifest_incognito() {
"Should have the expected incognito string"
);
+ ExtensionTestUtils.failOnSchemaWarnings(false);
normalized = await ExtensionTestUtils.normalizeManifest({
- incognito: "split",
+ incognito: "whatisthis",
});
+ ExtensionTestUtils.failOnSchemaWarnings(true);
equal(
normalized.error,
- 'Error processing incognito: Invalid enumeration value "split"',
+ 'Error processing incognito: Invalid enumeration value "whatisthis"',
"Should have an error"
);
Assert.deepEqual(normalized.errors, [], "Should not have a warning");
+
+ // Sanity check: Default value of "incognito" is "spanning".
+ normalized = await ExtensionTestUtils.normalizeManifest({});
+ equal(normalized.error, undefined, "Should not have an error");
+ equal(normalized.errors.length, 0, "Should not have warnings");
+ equal(
+ normalized.value.incognito,
+ "spanning",
+ "Should have the expected default value for incognito when unspecified"
+ );
+});
+
+add_task(async function test_manifest_incognito_split_fallback_not_allowed() {
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ let normalized = await ExtensionTestUtils.normalizeManifest({
+ incognito: "split",
+ });
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+
+ equal(normalized.error, undefined, "Should not have an error");
+ Assert.deepEqual(
+ normalized.errors,
+ [
+ `Warning processing incognito: incognito "split" is unsupported. Falling back to incognito "not_allowed".`,
+ ],
+ "Should have a warning"
+ );
equal(
- normalized.value,
- undefined,
- "Invalid incognito string should be undefined"
+ normalized.value.incognito,
+ "not_allowed",
+ "incognito:split should fall back to not_allowed by default"
);
});
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_permission_warnings.js b/toolkit/components/extensions/test/xpcshell/test_ext_permission_warnings.js
index ab3f20f12e..925f8f9dfe 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_permission_warnings.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_permission_warnings.js
@@ -41,7 +41,7 @@ async function getManifestPermissions(extensionData) {
ExtensionTestUtils.failOnSchemaWarnings(false);
await extension.loadManifest();
ExtensionTestUtils.failOnSchemaWarnings(true);
- let result = extension.manifestPermissions;
+ let result = extension.getRequiredPermissions();
if (extension.manifest.manifest_version >= 3) {
// In MV3, host permissions are optional by default.
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js b/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
index ae6ce3d27e..a0bebc3f77 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
@@ -10,6 +10,11 @@ const { ExtensionPermissions } = ChromeUtils.importESModule(
"resource://gre/modules/ExtensionPermissions.sys.mjs"
);
+const WITH_INSTALL_PROMPT = [
+ ["extensions.originControls.grantByDefault", true],
+];
+const NO_INSTALL_PROMPT = [["extensions.originControls.grantByDefault", false]];
+
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
// ExtensionParent.sys.mjs is being imported lazily because when it is imported Services.appinfo will be
@@ -427,12 +432,24 @@ add_task(function test_normal_mv2() {
});
});
+add_task(function test_normal_mv3_noInstallPrompt() {
+ return runWithPrefs(NO_INSTALL_PROMPT, () =>
+ test_permissions({
+ manifest_version: 3,
+ useAddonManager: "permanent",
+ expectAllGranted: false,
+ })
+ );
+});
+
add_task(function test_normal_mv3() {
- return test_permissions({
- manifest_version: 3,
- useAddonManager: "permanent",
- expectAllGranted: false,
- });
+ return runWithPrefs(WITH_INSTALL_PROMPT, () =>
+ test_permissions({
+ manifest_version: 3,
+ useAddonManager: "permanent",
+ expectAllGranted: true,
+ })
+ );
});
add_task(function test_granted_for_temporary_mv3() {
@@ -444,28 +461,30 @@ add_task(function test_granted_for_temporary_mv3() {
});
});
-add_task(async function test_granted_only_for_privileged_mv3() {
- try {
- // For permanent non-privileged, granted_host_permissions does nothing.
- await test_permissions({
- manifest_version: 3,
- granted_host_permissions: true,
- useAddonManager: "permanent",
- expectAllGranted: false,
- });
+add_task(function test_granted_only_for_privileged_mv3() {
+ return runWithPrefs(NO_INSTALL_PROMPT, async () => {
+ try {
+ // For permanent non-privileged, granted_host_permissions does nothing.
+ await test_permissions({
+ manifest_version: 3,
+ granted_host_permissions: true,
+ useAddonManager: "permanent",
+ expectAllGranted: false,
+ });
- // Make extensions loaded with addon manager privileged.
- AddonTestUtils.usePrivilegedSignatures = true;
+ // Make extensions loaded with addon manager privileged.
+ AddonTestUtils.usePrivilegedSignatures = true;
- await test_permissions({
- manifest_version: 3,
- granted_host_permissions: true,
- useAddonManager: "permanent",
- expectAllGranted: true,
- });
- } finally {
- AddonTestUtils.usePrivilegedSignatures = false;
- }
+ await test_permissions({
+ manifest_version: 3,
+ granted_host_permissions: true,
+ useAddonManager: "permanent",
+ expectAllGranted: true,
+ });
+ } finally {
+ AddonTestUtils.usePrivilegedSignatures = false;
+ }
+ });
});
add_task(async function test_startup() {
@@ -540,7 +559,7 @@ add_task(async function test_startup() {
});
// Test that we don't prompt for permissions an extension already has.
-async function test_alreadyGranted(manifest_version) {
+async function test_alreadyGranted({ manifest_version }) {
const REQUIRED_PERMISSIONS = ["geolocation"];
const REQUIRED_ORIGINS = [
"*://required-host.com/",
@@ -671,10 +690,17 @@ async function test_alreadyGranted(manifest_version) {
await extension.unload();
}
add_task(async function test_alreadyGranted_mv2() {
- return test_alreadyGranted(2);
+ return test_alreadyGranted({ manifest_version: 2 });
});
-add_task(async function test_alreadyGranted_mv3() {
- return test_alreadyGranted(3);
+add_task(function test_alreadyGranted_mv3_noInstallPrompt() {
+ return runWithPrefs(NO_INSTALL_PROMPT, () =>
+ test_alreadyGranted({ manifest_version: 3 })
+ );
+});
+add_task(function test_alreadyGranted_mv3() {
+ return runWithPrefs(WITH_INSTALL_PROMPT, () =>
+ test_alreadyGranted({ manifest_version: 3 })
+ );
});
// IMPORTANT: Do not change this list without review from a Web Extensions peer!
@@ -779,7 +805,10 @@ add_task(async function test_optional_all_urls() {
});
// Check when content_script match patterns are treated as optional origins.
-async function test_content_script_is_optional(manifest_version) {
+async function test_content_script_is_optional({
+ manifest_version,
+ expectGranted,
+}) {
function background() {
browser.test.onMessage.addListener(async (msg, arg) => {
if (msg == "request") {
@@ -816,7 +845,11 @@ async function test_content_script_is_optional(manifest_version) {
extension.sendMessage("getAll");
let initial = await extension.awaitMessage("granted");
- deepEqual(initial.origins, [], "Nothing granted on install.");
+ if (manifest_version < 3 || !expectGranted) {
+ deepEqual(initial.origins, [], "Nothing granted on install.");
+ } else {
+ deepEqual(initial.origins, [CS_ORIGIN], "CS origin granted on install.");
+ }
await withHandlingUserInput(extension, async () => {
extension.sendMessage("request", {
@@ -845,11 +878,32 @@ async function test_content_script_is_optional(manifest_version) {
await extension.unload();
}
-add_task(() => test_content_script_is_optional(2));
-add_task(() => test_content_script_is_optional(3));
+
+add_task(async function test_content_script_is_optional_mv2() {
+ await test_content_script_is_optional({ manifest_version: 2 });
+});
+add_task(function test_content_script_is_optional_mv3_noInstallPrompt() {
+ return runWithPrefs(NO_INSTALL_PROMPT, () =>
+ test_content_script_is_optional({
+ manifest_version: 3,
+ expectGranted: false,
+ })
+ );
+});
+add_task(function test_content_script_is_optional_mv3() {
+ return runWithPrefs(WITH_INSTALL_PROMPT, () =>
+ test_content_script_is_optional({
+ manifest_version: 3,
+ expectGranted: true,
+ })
+ );
+});
// Check that optional permissions are not included in update prompts
-async function test_permissions_prompt(manifest_version) {
+async function test_permissions_prompt({
+ manifest_version,
+ expectInitialGranted,
+}) {
function background() {
browser.test.onMessage.addListener(async (msg, arg) => {
if (msg == "request") {
@@ -896,7 +950,7 @@ async function test_permissions_prompt(manifest_version) {
equal(result, true, "request() for optional permissions succeeded");
});
- if (manifest_version >= 3) {
+ if (!expectInitialGranted) {
await withHandlingUserInput(extension, async () => {
extension.sendMessage("request", {
origins: ["https://test1.example.com/*"],
@@ -964,10 +1018,26 @@ async function test_permissions_prompt(manifest_version) {
await extension.unload();
}
add_task(async function test_permissions_prompt_mv2() {
- return test_permissions_prompt(2);
+ return test_permissions_prompt({
+ manifest_version: 2,
+ expectInitialGranted: true,
+ });
+});
+add_task(function test_permissions_prompt_mv3_noInstallPrompt() {
+ return runWithPrefs(NO_INSTALL_PROMPT, () =>
+ test_permissions_prompt({
+ manifest_version: 3,
+ expectInitialGranted: false,
+ })
+ );
});
add_task(async function test_permissions_prompt_mv3() {
- return test_permissions_prompt(3);
+ return runWithPrefs(WITH_INSTALL_PROMPT, () =>
+ test_permissions_prompt({
+ manifest_version: 3,
+ expectInitialGranted: true,
+ })
+ );
});
// Check that internal permissions can not be set and are not returned by the API.
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_runtime_getContexts.js b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_getContexts.js
new file mode 100644
index 0000000000..efef355f74
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_getContexts.js
@@ -0,0 +1,180 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_runtime_getContexts() {
+ function background() {
+ browser.test.onMessage.addListener(async (msg, ...args) => {
+ if (msg === "runtime.getContexts") {
+ try {
+ const filter = args[0];
+ if (!filter) {
+ // Expected to be rejected.
+ await browser.runtime.getContexts();
+ } else {
+ // Expected to be resolved.
+ const result = await browser.runtime.getContexts(filter);
+ browser.test.sendMessage(`${msg}:result`, result);
+ }
+ } catch (err) {
+ browser.test.log(`runtime.getContexts error: ${err}\n`);
+ browser.test.sendMessage(`${msg}:error`, String(err));
+ }
+ }
+ });
+ browser.test.sendMessage("bgpage:loaded");
+ }
+
+ const extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ manifest_version: 3,
+ },
+ background,
+ files: {
+ "tab.html": `<!DOCTYPE html><html></html>`,
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("bgpage:loaded");
+
+ const documentOrigin = extension.extension.baseURI.spec.slice(0, -1);
+ const tabDocumentUrl = extension.extension.baseURI.resolve("tab.html");
+ const bgDocumentUrl = extension.extension.baseURI.resolve(
+ "_generated_background_page.html"
+ );
+
+ let expectedBackground = {
+ contextType: "BACKGROUND",
+ documentOrigin,
+ documentUrl: bgDocumentUrl,
+ incognito: false,
+ frameId: 0,
+ tabId: -1,
+ windowId: -1,
+ };
+
+ let expectedTab = {
+ contextType: "TAB",
+ documentOrigin,
+ documentUrl: `${tabDocumentUrl}?fistOpenedTab=true`,
+ incognito: false,
+ frameId: 0,
+ // tabId and windowId are expected to be -1 in xpcshell test
+ // (these are also covered by browser_ext_getContexts.js).
+ tabId: -1,
+ windowId: -1,
+ };
+
+ const assertValidContextId = contextId => {
+ Assert.equal(
+ typeof contextId,
+ "string",
+ "contextId should be set to a string"
+ );
+ Assert.notEqual(
+ contextId.length,
+ 0,
+ "contextId should be set to a non-zero length string"
+ );
+ };
+ const assertGetContextsResult = (
+ actual,
+ expected,
+ msg,
+ { assertContextId = false } = {}
+ ) => {
+ const actualCopy = assertContextId ? actual : actual.map(it => ({ ...it }));
+ if (!assertContextId) {
+ actualCopy.forEach(it => delete it.contextId);
+ }
+ Assert.deepEqual(actualCopy, expected, msg);
+ };
+
+ info(
+ "Test runtime.getContexts rejects when called without any filter parameter"
+ );
+ extension.sendMessage("runtime.getContexts", undefined);
+ let resError = await extension.awaitMessage("runtime.getContexts:error");
+ Assert.equal(
+ resError,
+ "Error: Incorrect argument types for runtime.getContexts.",
+ "Got the expected error message"
+ );
+
+ info(
+ "Test runtime.getContext resolved when called with an empty filter parameter"
+ );
+
+ extension.sendMessage("runtime.getContexts", {});
+ let res = await extension.awaitMessage("runtime.getContexts:result");
+
+ assertGetContextsResult(
+ res,
+ [expectedBackground],
+ "Got the expected properties for the background context"
+ );
+
+ let actualBackground = res[0];
+ assertValidContextId(actualBackground.contextId);
+
+ const page = await ExtensionTestUtils.loadContentPage(
+ `${tabDocumentUrl}?fistOpenedTab=true`
+ );
+
+ res = await page.spawn([], () =>
+ this.content.wrappedJSObject.browser.runtime.getContexts({})
+ );
+
+ const bgItem = res.find(it => it.contextType === "BACKGROUND");
+ const tabItem = res.find(it => it.contextType === "TAB");
+
+ assertValidContextId(tabItem.contextId);
+
+ assertGetContextsResult(
+ res,
+ [expectedBackground, expectedTab],
+ "Got expected properties for backgrond and tab contexts"
+ );
+ assertGetContextsResult(
+ [bgItem],
+ [actualBackground],
+ "Expect the expected properties for the background context (included same contextId)",
+ { assertContextId: true }
+ );
+
+ info("Test runtime.getContexts with a contextType filter");
+ res = await page.spawn([], () =>
+ this.content.wrappedJSObject.browser.runtime.getContexts({
+ contextTypes: ["BACKGROUND"],
+ })
+ );
+ assertGetContextsResult(
+ res,
+ [actualBackground],
+ "Expect only the backgrund context to be included in the results",
+ { assertContextId: true }
+ );
+
+ info("Test runtime.ContextType enum");
+ const contextTypeEnum = await page.spawn([], () => {
+ return this.content.wrappedJSObject.browser.runtime.ContextType;
+ });
+
+ const expectedTypesMap = ["BACKGROUND", "POPUP", "SIDE_PANEL", "TAB"].reduce(
+ (acc, item) => {
+ acc[item] = item;
+ return acc;
+ },
+ {}
+ );
+
+ Assert.deepEqual(
+ contextTypeEnum,
+ expectedTypesMap,
+ "Got the expected values in the ContextType enum"
+ );
+
+ await extension.unload();
+});
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_service_worker_messaging.js b/toolkit/components/extensions/test/xpcshell/test_ext_service_worker_messaging.js
new file mode 100644
index 0000000000..b064da259b
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_service_worker_messaging.js
@@ -0,0 +1,128 @@
+/* Any copyright is dedicated to the Public Domain.
+https://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_runtime_sendMessage() {
+ const extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ background: {
+ service_worker: "sw.js",
+ },
+ browser_specific_settings: {
+ gecko: { id: "@test-messaging" },
+ },
+ },
+ files: {
+ "sw.js": async function () {
+ browser.test.onMessage.addListener(msg => {
+ browser.test.assertEq("send", msg, "expected correct message");
+ browser.runtime.sendMessage("hello-from-sw");
+ });
+
+ browser.test.sendMessage("background-ready");
+ },
+ "page.html": '<!DOCTYPE html><script src="page.js"></script>',
+ "page.js"() {
+ browser.runtime.onMessage.addListener((msg, sender) => {
+ browser.test.assertEq(
+ "hello-from-sw",
+ msg,
+ "expected message from service worker"
+ );
+
+ const { contextId, ...otherProps } = sender;
+ browser.test.assertTrue(!!contextId, "expected a truthy contextId");
+ browser.test.assertDeepEq(
+ {
+ envType: "addon_child",
+ id: "@test-messaging",
+ origin: self.origin,
+ url: browser.runtime.getURL("sw.js"),
+ },
+ otherProps,
+ "expected correct sender props"
+ );
+
+ browser.test.sendMessage("page-done");
+ });
+
+ browser.test.sendMessage("page-ready");
+ },
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("background-ready");
+
+ const page = await ExtensionTestUtils.loadContentPage(
+ `moz-extension://${extension.uuid}/page.html`,
+ { extension }
+ );
+ await extension.awaitMessage("page-ready");
+
+ extension.sendMessage("send");
+ await extension.awaitMessage("page-done");
+
+ await page.close();
+ await extension.unload();
+});
+
+add_task(async function test_runtime_connect() {
+ const extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ background: {
+ service_worker: "sw.js",
+ },
+ browser_specific_settings: {
+ gecko: { id: "@test-messaging" },
+ },
+ },
+ files: {
+ "sw.js": async function () {
+ browser.test.onMessage.addListener(msg => {
+ browser.test.assertEq("connect", msg, "expected correct message");
+ browser.runtime.connect();
+ });
+
+ browser.test.sendMessage("background-ready");
+ },
+ "page.html": '<!DOCTYPE html><script src="page.js"></script>',
+ "page.js"() {
+ browser.runtime.onConnect.addListener(port => {
+ const { contextId, ...otherProps } = port.sender;
+ browser.test.assertTrue(!!contextId, "expected a truthy contextId");
+ browser.test.assertDeepEq(
+ {
+ envType: "addon_child",
+ id: "@test-messaging",
+ origin: self.origin,
+ url: browser.runtime.getURL("sw.js"),
+ },
+ otherProps,
+ "expected correct sender props"
+ );
+
+ browser.test.sendMessage("page-done");
+ });
+
+ browser.test.sendMessage("page-ready");
+ },
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("background-ready");
+
+ const page = await ExtensionTestUtils.loadContentPage(
+ `moz-extension://${extension.uuid}/page.html`,
+ { extension }
+ );
+ await extension.awaitMessage("page-ready");
+
+ extension.sendMessage("connect");
+ await extension.awaitMessage("page-done");
+
+ await page.close();
+ await extension.unload();
+});
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_storage_telemetry.js b/toolkit/components/extensions/test/xpcshell/test_ext_storage_telemetry.js
index d0448b7b2e..4b98597b11 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_storage_telemetry.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_storage_telemetry.js
@@ -15,55 +15,42 @@ const { TelemetryTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TelemetryTestUtils.sys.mjs"
);
-const HISTOGRAM_JSON_IDS = [
- "WEBEXT_STORAGE_LOCAL_SET_MS",
- "WEBEXT_STORAGE_LOCAL_GET_MS",
-];
-const KEYED_HISTOGRAM_JSON_IDS = [
- "WEBEXT_STORAGE_LOCAL_SET_MS_BY_ADDONID",
- "WEBEXT_STORAGE_LOCAL_GET_MS_BY_ADDONID",
-];
-
-const HISTOGRAM_IDB_IDS = [
+const HISTOGRAM_IDS = [
"WEBEXT_STORAGE_LOCAL_IDB_SET_MS",
"WEBEXT_STORAGE_LOCAL_IDB_GET_MS",
];
-const KEYED_HISTOGRAM_IDB_IDS = [
+const KEYED_HISTOGRAM_IDS = [
"WEBEXT_STORAGE_LOCAL_IDB_SET_MS_BY_ADDONID",
"WEBEXT_STORAGE_LOCAL_IDB_GET_MS_BY_ADDONID",
];
-const HISTOGRAM_IDS = [].concat(HISTOGRAM_JSON_IDS, HISTOGRAM_IDB_IDS);
-const KEYED_HISTOGRAM_IDS = [].concat(
- KEYED_HISTOGRAM_JSON_IDS,
- KEYED_HISTOGRAM_IDB_IDS
-);
-
const EXTENSION_ID1 = "@test-extension1";
const EXTENSION_ID2 = "@test-extension2";
async function test_telemetry_background() {
const { GleanTimingDistribution } = globalThis;
+
+ // NOTE: we do not collect telemetry for the legacy JSON backend anymore
+ // and so if the IDB backend is not enabled we expect the related telemetry
+ // histograms and timing distributions to be empty.
const expectedEmptyGleanMetrics = ExtensionStorageIDB.isBackendEnabled
- ? ["storageLocalGetJson", "storageLocalSetJson"]
+ ? []
: ["storageLocalGetIdb", "storageLocalSetIdb"];
const expectedNonEmptyGleanMetrics = ExtensionStorageIDB.isBackendEnabled
? ["storageLocalGetIdb", "storageLocalSetIdb"]
- : ["storageLocalGetJson", "storageLocalSetJson"];
-
+ : [];
const expectedEmptyHistograms = ExtensionStorageIDB.isBackendEnabled
- ? HISTOGRAM_JSON_IDS
- : HISTOGRAM_IDB_IDS;
+ ? []
+ : HISTOGRAM_IDS;
const expectedEmptyKeyedHistograms = ExtensionStorageIDB.isBackendEnabled
- ? KEYED_HISTOGRAM_JSON_IDS
- : KEYED_HISTOGRAM_IDB_IDS;
-
+ ? []
+ : KEYED_HISTOGRAM_IDS;
const expectedNonEmptyHistograms = ExtensionStorageIDB.isBackendEnabled
- ? HISTOGRAM_IDB_IDS
- : HISTOGRAM_JSON_IDS;
+ ? HISTOGRAM_IDS
+ : [];
const expectedNonEmptyKeyedHistograms = ExtensionStorageIDB.isBackendEnabled
- ? KEYED_HISTOGRAM_IDB_IDS
- : KEYED_HISTOGRAM_JSON_IDS;
+ ? KEYED_HISTOGRAM_IDS
+ : [];
const server = createHttpServer();
server.registerDirectory("/data/", do_get_file("data"));
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_eventPage_StreamFilter.js b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_eventPage_StreamFilter.js
index 23c29aa155..820e04956e 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_eventPage_StreamFilter.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_eventPage_StreamFilter.js
@@ -105,7 +105,11 @@ async function test_idletimeout_on_streamfilter({
).catch(err => {
// This request is expected to be aborted when cleared after the test is exiting,
// otherwise rethrow the error to trigger an explicit failure.
- if (/The operation was aborted/.test(err.message)) {
+ if (
+ /Content-Length header of network response exceeds response Body/.test(
+ err.message
+ )
+ ) {
info(`Test webRequest fetching "${testURL}" aborted`);
} else {
ok(
diff --git a/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml b/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
index 6d47012eca..fd0b2d50d2 100644
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
@@ -432,6 +432,8 @@ skip-if = ["os == 'android' && debug"]
["test_ext_runtime_getBrowserInfo.js"]
+["test_ext_runtime_getContexts.js"]
+
["test_ext_runtime_getPlatformInfo.js"]
["test_ext_runtime_id.js"]
diff --git a/toolkit/components/extensions/test/xpcshell/xpcshell-serviceworker.toml b/toolkit/components/extensions/test/xpcshell/xpcshell-serviceworker.toml
index b300959970..83ca99bc2f 100644
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-serviceworker.toml
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-serviceworker.toml
@@ -49,3 +49,5 @@ run-sequentially = "very high failure rate in parallel"
["test_ext_scripting_contentScripts_file.js"]
["test_ext_scripting_updateContentScripts.js"]
+
+["test_ext_service_worker_messaging.js"]