Bug 1485727 [wpt PR 12645] - HTML: more tests for document.open bailout order, a=testonly
authorTimothy Gu <timothygu99@gmail.com>
Fri, 24 Aug 2018 13:05:26 +0000
changeset 491633 0585d2064f4944eb21522699451509fb4e682ca5
parent 491632 f65fe110acd5e5b9fbc77f1bd823adf88abcf2e1
child 491634 11990807b74a1e2029f2827dc5580985c8aaf119
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1485727, 12645, 12240
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1485727 [wpt PR 12645] - HTML: more tests for document.open bailout order, a=testonly Automatic update from web-platform-testsHTML: more tests for document.open bailout order (#12645) A continuation of https://github.com/web-platform-tests/wpt/pull/12240, but this treats cases when two bailout criteria compete against each other. See https://github.com/whatwg/html/issues/3818. -- wpt-commits: 45d82ab6c8893eab5a8f50aedfc20af81679cb10 wpt-pr: 12645
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.js
testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.js
testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-custom-element-with-domain-frame.sub.html
testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-synchronous-script-with-domain-frame.sub.html
testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-domain-frame.sub.xhtml
testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-synchronous-script-frame.xhtml
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -289030,21 +289030,41 @@
      {}
     ]
    ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/aborted-parser-frame.html": [
     [
      {}
     ]
    ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-custom-element-with-domain-frame.sub.html": [
+    [
+     {}
+    ]
+   ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-synchronous-script-frame.html": [
     [
      {}
     ]
    ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-synchronous-script-with-domain-frame.sub.html": [
+    [
+     {}
+    ]
+   ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-domain-frame.sub.xhtml": [
+    [
+     {}
+    ]
+   ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-synchronous-script-frame.xhtml": [
+    [
+     {}
+    ]
+   ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/document-open-side-effects.js": [
     [
      {}
     ]
    ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/encoding-frame.html": [
     [
      {}
@@ -365515,16 +365535,28 @@
     ]
    ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.js": [
     [
      "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.html",
      {}
     ]
    ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.js": [
+    [
+     "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.html",
+     {}
+    ]
+   ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.js": [
+    [
+     "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.html",
+     {}
+    ]
+   ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js": [
     [
      "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.html",
      {}
     ]
    ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-same-origin-domain.sub.window.js": [
     [
@@ -606610,16 +606642,24 @@
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/016.html": [
    "1c70fce591a38dd7917e1fffbd1d9ebab46e8b7f",
    "testharness"
   ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.js": [
    "1d94de8a7c9f28dfab32111deb664d9921437e46",
    "testharness"
   ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.js": [
+   "0e1c54b683257aea8fd58c893957acd794cc1ab1",
+   "testharness"
+  ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.js": [
+   "3558397410edea6eaa9e73fa6d0293cc7e4d48ba",
+   "testharness"
+  ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js": [
    "6b80ecacf8f640ff94209dbd915049e261214eac",
    "testharness"
   ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-same-origin-domain.sub.window.js": [
    "ef35452e330e80ab8b4acebf4f1f9ef7a523dc90",
    "testharness"
   ],
@@ -606686,20 +606726,36 @@
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/aborted-parser-async-frame.html": [
    "d5535630be05ddb466814c503ab086d7176ecbda",
    "support"
   ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/aborted-parser-frame.html": [
    "d9ec23590bf98a86d75661536dc03dfae7abbc3e",
    "support"
   ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-custom-element-with-domain-frame.sub.html": [
+   "4de97e8ed1bb99fd6eb2efa6dbe43bb1eb05edea",
+   "support"
+  ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-synchronous-script-frame.html": [
    "632b2934ac16be0f5b9cca3fd80ee26c315a5d9c",
    "support"
   ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-synchronous-script-with-domain-frame.sub.html": [
+   "7ca7b5f44c518d7251c4cc47bb9d41976dd8bfc7",
+   "support"
+  ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-domain-frame.sub.xhtml": [
+   "b054c0fe3a1e6b34127c83561140c06963f2dbfc",
+   "support"
+  ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-synchronous-script-frame.xhtml": [
+   "00fc71eccfb5e967f006d217f59577f086ac42ef",
+   "support"
+  ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/document-open-side-effects.js": [
    "7cb86dcba0236d1e161989e95de172ebbf7852e0",
    "support"
   ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/encoding-frame.html": [
    "843c3a2c7988be0b9595bc69887fc75a5a7b304c",
    "support"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.js
@@ -0,0 +1,97 @@
+document.domain = "{{host}}";
+
+// In many cases in this test, we want to delay execution of a piece of code so
+// that the entry settings object would be the top-level page. A microtask is
+// perfect for this purpose as it is executed in the "clean up after running
+// script" algorithm, which is generally called right after the callback.
+function setEntryToTopLevel(cb) {
+  Promise.resolve().then(cb);
+}
+
+async_test(t => {
+  const iframe = document.body.appendChild(document.createElement("iframe"));
+  t.add_cleanup(() => { iframe.remove(); });
+  iframe.onload = t.step_func_done(() => {
+    // Since this is called as an event handler on an element of this window,
+    // the entry settings object is that of this browsing context.
+    assert_throws("InvalidStateError", () => {
+      iframe.contentDocument.open();
+    }, "opening an XML document should throw an InvalidStateError");
+  });
+  const frameURL = new URL("resources/bailout-order-xml-with-domain-frame.sub.xhtml", document.URL);
+  frameURL.port = "{{ports[http][1]}}";
+  iframe.src = frameURL.href;
+}, "document.open should throw an InvalidStateError with XML document even if it is cross-origin");
+
+async_test(t => {
+  const iframe = document.body.appendChild(document.createElement("iframe"));
+  t.add_cleanup(() => { iframe.remove(); });
+  window.onCustomElementReady = t.step_func(() => {
+    window.onCustomElementReady = t.unreached_func("onCustomElementReady called again");
+    // Here, the entry settings object is still the iframe's, as the function
+    // is called from a custom element constructor in the iframe document.
+    // Delay execution in such a way that makes the entry settings object the
+    // top-level page's, but without delaying too much that the
+    // throw-on-dynamic-markup-insertion counter gets decremented (which is
+    // what this test tries to pit against the cross-origin document check).
+    //
+    // "Clean up after running script" is executed through the "construct" Web
+    // IDL algorithm in "create an element", called by "create an element for a
+    // token" in the parser.
+    setEntryToTopLevel(t.step_func_done(() => {
+      assert_throws("InvalidStateError", () => {
+        iframe.contentDocument.open();
+      }, "opening a document when the throw-on-dynamic-markup-insertion counter is incremented should throw an InvalidStateError");
+    }));
+  });
+  const frameURL = new URL("resources/bailout-order-custom-element-with-domain-frame.sub.html", document.URL);
+  frameURL.port = "{{ports[http][1]}}";
+  iframe.src = frameURL.href;
+}, "document.open should throw an InvalidStateError when the throw-on-dynamic-markup-insertion counter is incremented even if the document is cross-origin");
+
+async_test(t => {
+  const iframe = document.body.appendChild(document.createElement("iframe"));
+  t.add_cleanup(() => { iframe.remove(); });
+  self.testSynchronousScript = t.step_func(() => {
+    // Here, the entry settings object is still the iframe's, as the function
+    // is synchronously called from a <script> element in the iframe's
+    // document.
+    //
+    // "Clean up after running script" is executed when the </script> tag is
+    // seen by the HTML parser.
+    setEntryToTopLevel(t.step_func_done(() => {
+      assert_throws("SecurityError", () => {
+        iframe.contentDocument.open();
+      }, "opening a same origin-domain (but not same origin) document should throw a SecurityError");
+    }));
+  });
+  const frameURL = new URL("resources/bailout-order-synchronous-script-with-domain-frame.sub.html", document.URL);
+  frameURL.port = "{{ports[http][1]}}";
+  iframe.src = frameURL.href;
+}, "document.open should throw a SecurityError with cross-origin document even when there is an active parser executing script");
+
+for (const ev of ["beforeunload", "pagehide", "unload"]) {
+  async_test(t => {
+    const iframe = document.body.appendChild(document.createElement("iframe"));
+    t.add_cleanup(() => { iframe.remove(); });
+    iframe.addEventListener("load", t.step_func(() => {
+      iframe.contentWindow.addEventListener(ev, t.step_func(() => {
+        // Here, the entry settings object should be the top-level page's, as
+        // the callback context of this event listener is the incumbent
+        // settings object, which is the this page. However, due to a Chrome
+        // bug (https://crbug.com/606900), the entry settings object may be
+        // mis-set to the iframe's.
+        //
+        // "Clean up after running script" is called in the task that
+        // navigates.
+        setEntryToTopLevel(t.step_func_done(() => {
+          assert_throws("SecurityError", () => {
+            iframe.contentDocument.open();
+          }, "opening a same origin-domain (but not same origin) document should throw a SecurityError");
+        }));
+      }));
+      iframe.src = "about:blank";
+    }), { once: true });
+    iframe.src = "http://{{host}}:{{ports[http][1]}}/common/domain-setter.sub.html";
+  }, `document.open should throw a SecurityError with cross-origin document even when the ignore-opens-during-unload counter is greater than 0 (during ${ev} event)`);
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.js
@@ -0,0 +1,26 @@
+async_test(t => {
+  const iframe = document.body.appendChild(document.createElement("iframe"));
+  t.add_cleanup(() => { iframe.remove(); });
+  self.testSynchronousScript = t.step_func_done(() => {
+    assert_throws("InvalidStateError", () => {
+      iframe.contentDocument.open();
+    }, "opening an XML document should throw");
+  });
+  iframe.src = "resources/bailout-order-xml-with-synchronous-script-frame.xhtml";
+}, "document.open should throw an InvalidStateError with XML document even when there is an active parser executing script");
+
+for (const ev of ["beforeunload", "pagehide", "unload"]) {
+  async_test(t => {
+    const iframe = document.body.appendChild(document.createElement("iframe"));
+    t.add_cleanup(() => { iframe.remove(); });
+    iframe.addEventListener("load", t.step_func(() => {
+      iframe.contentWindow.addEventListener(ev, t.step_func_done(() => {
+        assert_throws("InvalidStateError", () => {
+          iframe.contentDocument.open();
+        }, "opening an XML document should throw");
+      }));
+      iframe.src = "about:blank";
+    }), { once: true });
+    iframe.src = "/common/dummy.xhtml";
+  }, `document.open should throw an InvalidStateError with XML document even when the ignore-opens-during-unload counter is greater than 0 (during ${ev} event)`);
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-custom-element-with-domain-frame.sub.html
@@ -0,0 +1,13 @@
+<p>Text</p>
+<script>
+document.domain = "{{host}}";
+
+class CustomElement extends HTMLElement {
+  constructor() {
+    super();
+    parent.onCustomElementReady();
+  }
+}
+customElements.define("custom-element", CustomElement);
+</script>
+<custom-element></custom-element>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-synchronous-script-with-domain-frame.sub.html
@@ -0,0 +1,5 @@
+<p>Text</p>
+<script>
+document.domain = "{{host}}";
+parent.testSynchronousScript();
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-domain-frame.sub.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><title>XHTML document with domain set</title></head>
+  <body>
+    <p>Text</p>
+    <script>
+      document.domain = "{{host}}";
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/bailout-order-xml-with-synchronous-script-frame.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><title>XHTML document with hook to run script from a script tag</title></head>
+  <body>
+    <p>Text</p>
+    <script>
+      parent.testSynchronousScript();
+    </script>
+  </body>
+</html>