Bug 1356273: Part 2 - Add tests that document.open()/write() only loads content scripts once. r?aswan
The combination of "match_about_blank": true and "run_at": "document_start"
can potentially cause content scripts to run twice for the same document, once
for the intermediate about:blank document created by the document.open() call,
and again for the same document with its final URL after it's been fully
setup.
This test ensures that that behavior doesn't regress.
MozReview-Commit-ID: 9XSfW3rEL4f
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/data/file_document_open.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+
+ <iframe id="iframe"></iframe>
+
+ <script type="text/javascript">
+ "use strict";
+ addEventListener("load", () => {
+ let iframe = document.getElementById("iframe");
+ let doc = iframe.contentDocument;
+ doc.open("text/html");
+ doc.write("Hello.");
+ doc.close();
+ }, {once: true});
+ </script>
+</body>
+</html>
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript.js
@@ -109,8 +109,64 @@ add_task(async function test_contentscri
await contentPage.close();
equal(loadingCount, 1, "document_start script ran exactly once");
equal(interactiveCount, 1, "document_end script ran exactly once");
equal(completeCount, 2, "document_idle script ran exactly twice");
await extension.unload();
});
+
+add_task(async function test_contentscript_window_open() {
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ applications: {gecko: {id: "contentscript@tests.mozilla.org"}},
+ content_scripts: [
+ {
+ "matches": ["<all_urls>"],
+ "js": ["content_script.js"],
+ "run_at": "document_start",
+ "match_about_blank": true,
+ "all_frames": true,
+ },
+ ],
+ },
+
+ files: {
+ "content_script.js": `
+ var x = (x || 0) + 1;
+ (${async () => {
+ /* globals x */
+ browser.test.assertEq(1, x, "Should only run once");
+
+ if (top !== window) {
+ await new Promise(resolve => setTimeout(resolve, 0));
+ }
+
+ browser.test.sendMessage("content-script", [location.href, top === window]);
+ }})();
+ `,
+ },
+ });
+
+ await extension.startup();
+
+ let url = `${BASE_URL}/file_document_open.html`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(url);
+
+ Assert.deepEqual(await extension.awaitMessage("content-script"),
+ [url, true]);
+
+ let [frameURL, isTop] = await extension.awaitMessage("content-script");
+ // Sometimes we get a content script load for the initial about:blank
+ // iframe here, sometimes we don't. Either way is fine, as long as we
+ // don't get two loads into the same document.open() document.
+ if (frameURL === "about:blank") {
+ equal(isTop, false);
+
+ [frameURL, isTop] = await extension.awaitMessage("content-script");
+ }
+
+ Assert.deepEqual([frameURL, isTop], [url, false]);
+
+ await contentPage.close();
+ await extension.unload();
+});