summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_unregister_during_loadContentScript.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_contentscript_unregister_during_loadContentScript.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_contentscript_unregister_during_loadContentScript.js91
1 files changed, 91 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_unregister_during_loadContentScript.js b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_unregister_during_loadContentScript.js
new file mode 100644
index 0000000000..9191f7633e
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_unregister_during_loadContentScript.js
@@ -0,0 +1,91 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const server = createHttpServer();
+server.registerDirectory("/data/", do_get_file("data"));
+
+const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
+
+add_task(async function content_script_unregistered_during_loadContentScript() {
+ let content_scripts = [];
+
+ for (let i = 0; i < 10; i++) {
+ content_scripts.push({
+ matches: ["<all_urls>"],
+ js: ["dummy.js"],
+ run_at: "document_start",
+ });
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ content_scripts,
+ },
+ files: {
+ "dummy.js": function () {
+ browser.test.sendMessage("content-script-executed");
+ },
+ },
+ });
+
+ await extension.startup();
+
+ let contentPage = await ExtensionTestUtils.loadContentPage(
+ `${BASE_URL}/file_sample.html`
+ );
+ info("Wait for all the content scripts to be executed");
+ await Promise.all(
+ content_scripts.map(() => extension.awaitMessage("content-script-executed"))
+ );
+
+ const promiseDone = contentPage.legacySpawn([extension.id], extensionId => {
+ const { ExtensionProcessScript } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionProcessScript.sys.mjs"
+ );
+
+ return new Promise(resolve => {
+ // This recreates a scenario similar to Bug 1593240 and ensures that the
+ // related fix doesn't regress. Replacing loadContentScript with a
+ // function that unregisters all the content scripts make us sure that
+ // mutating the policy contentScripts doesn't trigger a crash due to
+ // the invalidation of the contentScripts iterator being used by the
+ // caller (ExtensionPolicyService::CheckContentScripts).
+ const { loadContentScript } = ExtensionProcessScript;
+ ExtensionProcessScript.loadContentScript = async (...args) => {
+ const policy = WebExtensionPolicy.getByID(extensionId);
+ let initial = policy.contentScripts.length;
+ let i = initial;
+ while (i) {
+ policy.unregisterContentScript(policy.contentScripts[--i]);
+ }
+ Services.tm.dispatchToMainThread(() =>
+ resolve({
+ initial,
+ final: policy.contentScripts.length,
+ })
+ );
+ // Call the real loadContentScript method.
+ return loadContentScript(...args);
+ };
+ });
+ });
+
+ info("Reload the webpage");
+ await contentPage.loadURL(`${BASE_URL}/file_sample.html`);
+ info("Wait for all the content scripts to be executed again");
+ await Promise.all(
+ content_scripts.map(() => extension.awaitMessage("content-script-executed"))
+ );
+ info("No crash triggered as expected");
+
+ Assert.deepEqual(
+ await promiseDone,
+ { initial: content_scripts.length, final: 0 },
+ "All content scripts unregistered as expected"
+ );
+
+ await contentPage.close();
+ await extension.unload();
+});