Bug 1379148 - Part 4: Add tests for document.write() with document_start content script present. r=mixedpuppy, a=sledru
authorKris Maglione <maglione.k@gmail.com>
Wed, 20 Sep 2017 17:01:33 -0700
changeset 434230 de68fff98d0c5f6c6cc5bd230af92a5a9ecaa61f
parent 434229 e9235f4e44ee49812d2d07e14619d4927b88f75c
child 434231 d81018c999467e67455aec94bbafcfaff7976ca9
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy, sledru
bugs1379148
milestone57.0
Bug 1379148 - Part 4: Add tests for document.write() with document_start content script present. r=mixedpuppy, a=sledru MozReview-Commit-ID: 5yxgpur1tvf
toolkit/components/extensions/ExtensionXPCShellUtils.jsm
toolkit/components/extensions/test/xpcshell/data/file_document_write.html
toolkit/components/extensions/test/xpcshell/test_ext_contentscript_scriptCreated.js
toolkit/components/extensions/test/xpcshell/xpcshell-content.ini
--- a/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
+++ b/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
@@ -54,16 +54,21 @@ let BASE_MANIFEST = Object.freeze({
   "version": "0",
 });
 
 
 function frameScript() {
   Components.utils.import("resource://gre/modules/Services.jsm");
 
   Services.obs.notifyObservers(this, "tab-content-frameloader-created");
+
+  // eslint-disable-next-line mozilla/balanced-listeners
+  addEventListener("MozHeapMinimize", () => {
+    Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");
+  }, true, true);
 }
 
 const FRAME_SCRIPT = `data:text/javascript,(${encodeURI(frameScript)}).call(this)`;
 
 let kungFuDeathGrip = new Set();
 function promiseBrowserLoaded(browser, url, redirectUrl) {
   return new Promise(resolve => {
     const listener = {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/data/file_document_write.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+  <iframe id="iframe"></iframe>
+
+  <script type="text/javascript">
+    "use strict";
+    addEventListener("load", () => {
+      // Send a heap-minimize observer notification so our script cache is
+      // cleared, and our content script isn't available for synchronous
+      // insertion.
+      window.dispatchEvent(new CustomEvent("MozHeapMinimize"));
+
+      let iframe = document.getElementById("iframe");
+      let doc = iframe.contentDocument;
+      doc.open("text/html");
+      // We need to do two writes here. The first creates the document element,
+      // which normally triggers parser blocking. The second triggers the
+      // creation of the element we're about to query for, which would normally
+      // happen asynchronously if the parser were blocked.
+      doc.write("<div id=meh>");
+      doc.write("<div id=beer></div>");
+
+      let elem = doc.getElementById("beer");
+      top.postMessage(elem instanceof HTMLDivElement ? "ok" : "fail",
+                      "*");
+
+      doc.close();
+    }, {once: true});
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_scriptCreated.js
@@ -0,0 +1,49 @@
+"use strict";
+
+const server = createHttpServer();
+server.registerDirectory("/data/", do_get_file("data"));
+
+const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
+
+// 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();
+
+// Test that document_start content scripts don't block script-created
+// parsers.
+add_task(async function test_contentscript_scriptCreated() {
+  let extensionData = {
+    manifest: {
+      content_scripts: [{
+        "matches": ["http://*/*/file_document_write.html"],
+        "js": ["content_script.js"],
+        "run_at": "document_start",
+        "match_about_blank": true,
+        "all_frames": true,
+      }],
+    },
+
+    files: {
+      "content_script.js": function() {
+        if (window === top) {
+          addEventListener("message", msg => {
+            browser.test.assertEq("ok", msg.data, "document.write() succeeded");
+            browser.test.sendMessage("content-script-done");
+          }, {once: true});
+        }
+      },
+    },
+  };
+
+  let extension = ExtensionTestUtils.loadExtension(extensionData);
+
+  await extension.startup();
+
+  let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_document_write.html`);
+
+  await extension.awaitMessage("content-script-done");
+
+  await contentPage.close();
+
+  await extension.unload();
+});
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-content.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-content.ini
@@ -1,5 +1,6 @@
 [test_ext_i18n.js]
 skip-if = os == "android" || (os == "win" && debug)
 [test_ext_i18n_css.js]
 [test_ext_contentscript.js]
+[test_ext_contentscript_scriptCreated.js]
 [test_ext_contentscript_xrays.js]