Bug 1515646 - Test BrowsingContext::FindWithName. r=peterv
authorAndreas Farre <farre@mozilla.com>
Fri, 15 Feb 2019 11:17:50 +0000
changeset 459518 996e8765c85a16605c098144e8e95f97e89b70ea
parent 459517 15158d921194d94000045378b00d8944d6dbb0e3
child 459519 502cc11396cef7a59a1a291f9fdb4e2546ce728b
push id111964
push usercsabou@mozilla.com
push dateFri, 15 Feb 2019 18:54:44 +0000
treeherdermozilla-inbound@db3c4f905082 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1515646
milestone67.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 1515646 - Test BrowsingContext::FindWithName. r=peterv Test that BrowsingContext::FindWithName finds the expected BrowsingContexts and also that BrowsingContext::FindWithName finds the same browsing contexts as if nsIDocShellTreeItem::FindItemWithName had been used. Differential Revision: https://phabricator.services.mozilla.com/D15191
docshell/test/browser/browser.ini
docshell/test/browser/browser_browsingContext-01.js
docshell/test/browser/browser_browsingContext-02.js
docshell/test/browser/browser_browsingContext-03.js
docshell/test/browser/browser_browsingContext.js
--- a/docshell/test/browser/browser.ini
+++ b/docshell/test/browser/browser.ini
@@ -111,9 +111,11 @@ skip-if = os == 'win' && !debug # bug 13
 [browser_timelineMarkers-02.js]
 skip-if = true # Bug 1220415
 [browser_timelineMarkers-03.js]
 [browser_timelineMarkers-04.js]
 [browser_timelineMarkers-05.js]
 [browser_ua_emulation.js]
 [browser_history_triggeringprincipal_viewsource.js]
 [browser_click_link_within_view_source.js]
-[browser_browsingContext.js]
+[browser_browsingContext-01.js]
+[browser_browsingContext-02.js]
+[browser_browsingContext-03.js]
rename from docshell/test/browser/browser_browsingContext.js
rename to docshell/test/browser/browser_browsingContext-01.js
new file mode 100644
--- /dev/null
+++ b/docshell/test/browser/browser_browsingContext-02.js
@@ -0,0 +1,119 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function() {
+  await BrowserTestUtils.withNewTab(
+    {gBrowser, url: "about:blank"}, async function(browser) {
+      const BASE1 = getRootDirectory(gTestPath)
+            .replace("chrome://mochitests/content", "http://example.com");
+      const BASE2 = getRootDirectory(gTestPath)
+            .replace("chrome://mochitests/content", "http://test1.example.com");
+      const URL = BASE1 + "onload_message.html";
+      let sixth = BrowserTestUtils.waitForNewTab(gBrowser, URL + "#sixth", true, true);
+      let seventh = BrowserTestUtils.waitForNewTab(gBrowser, URL + "#seventh", true, true);
+      await ContentTask.spawn(browser, {base1: BASE1, base2: BASE2},
+                              async function({base1, base2}) {
+        let top = content.window;
+        top.name = 'top';
+        top.location.href += "#top";
+
+        let contexts = {
+          top: top.location.href,
+          first: base1 + "dummy_page.html#first",
+          third: base2 + "dummy_page.html#third",
+          second: base1 + "dummy_page.html#second",
+          fourth: base2 + "dummy_page.html#fourth",
+          fifth: base1 + "dummy_page.html#fifth",
+          sixth: base1 + "onload_message.html#sixth",
+          seventh: base1 + "onload_message.html#seventh"
+        };
+
+        function addFrame(target, name) {
+          let doc = (target.contentWindow || target).document;
+          let frame = doc.createElement('iframe');
+          let p = new Promise(resolve => (frame.onload = () =>resolve(frame)));
+          doc.body.appendChild(frame);
+          frame.name = name;
+          frame.src = contexts[name];
+          return p;
+        }
+
+        function addWindow(target, name, {options, resolve}) {
+          var win = target.contentWindow.open(contexts[name], name, options);
+
+          if (resolve) {
+            return new Promise(
+                resolve => target.contentWindow.addEventListener(
+                    'message', () => resolve(win)));
+          } else {
+            return Promise.resolve({name: name});
+          }
+        }
+
+        // We're going to create a tree that looks like the
+        // following.
+        //
+        //           top          sixth    seventh
+        //          /   \
+        //         /     \        /
+        //      first  second
+        //      /   \           /
+        //     /     \
+        //  third  fourth - - -
+        //          /
+        //         /
+        //      fifth
+        //
+        // The idea is to have one top level non-auxiliary browsing
+        // context, five nested, one top level auxiliary with an
+        // opener, and one top level without an opener. Given that
+        // set of related and one unrelated browsing contexts we
+        // wish to confirm that targeting is able to find
+        // appropriate browsing contexts.
+
+
+        function bc(frame) {
+          return (frame.contentWindow || frame).docShell.browsingContext;
+        }
+
+        function reachable(start, targets) {
+          for (let target of targets) {
+            is(bc(start).findWithName(target.name), bc(target),
+               [bc(start).name, 'can reach', target.name].join(' '));
+          }
+        }
+
+        function unreachable(start, target) {
+          is(bc(start).findWithName(target.name), null,
+             [bc(start).name, "can't reach", target.name].join(' '));
+        }
+
+        let first = await addFrame(top, 'first');
+        info('first');
+        let second = await addFrame(top, 'second');
+        info('second');
+        let third = await addFrame(first, 'third');
+        info('third');
+        let fourth = await addFrame(first, 'fourth');
+        info('fourth');
+        let fifth = await addFrame(fourth, 'fifth');
+        info('fifth');
+        let sixth = await addWindow(fourth, 'sixth', { resolve: true });
+        info('sixth');
+        let seventh = await addWindow(fourth, 'seventh', { options: ['noopener'] });
+        info('seventh');
+
+        let frames = [top, first, second, third, fourth, fifth, sixth];
+        for (let start of frames) {
+          reachable(start, frames);
+          unreachable(start, seventh);
+        }
+      });
+
+      for (let tab of await Promise.all([sixth, seventh])) {
+        BrowserTestUtils.removeTab(tab);
+      }
+    });
+});
new file mode 100644
--- /dev/null
+++ b/docshell/test/browser/browser_browsingContext-03.js
@@ -0,0 +1,136 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function() {
+  await BrowserTestUtils.withNewTab(
+    {gBrowser, url: "about:blank"}, async function(browser) {
+      const BASE1 = getRootDirectory(gTestPath)
+            .replace("chrome://mochitests/content", "http://example.com");
+      const BASE2 = getRootDirectory(gTestPath)
+            .replace("chrome://mochitests/content", "http://test1.example.com");
+      const URL = BASE1 + "onload_message.html";
+      let sixth = BrowserTestUtils.waitForNewTab(gBrowser, URL + "#sixth", true, true);
+      await ContentTask.spawn(browser, {base1: BASE1, base2: BASE2},
+                              async function({base1, base2}) {
+        let top = content.window;
+        top.name = 'top';
+        top.location.href += "#top";
+
+        let contexts = {
+          top: top.location.href,
+          first: base1 + "dummy_page.html#first",
+          third: base2 + "dummy_page.html#third",
+          second: base1 + "dummy_page.html#second",
+          fourth: base2 + "dummy_page.html#fourth",
+          fifth: base1 + "dummy_page.html#fifth",
+          sixth: base1 + "onload_message.html#sixth",
+        };
+
+        function addFrame(target, name) {
+          let doc = (target.contentWindow || target).document;
+          let frame = doc.createElement('iframe');
+          let p = new Promise(resolve => (frame.onload = () =>resolve(frame)));
+          doc.body.appendChild(frame);
+          frame.name = name;
+          frame.src = contexts[name];
+          return p;
+        }
+
+        function addWindow(target, name) {
+          var win = target.contentWindow.open(contexts[name], name);
+
+          return new Promise(
+              resolve => target.contentWindow.addEventListener(
+                  'message', () => resolve(win)));
+        }
+
+        // Generate all lists of length length with every combination of
+        // values in input
+        function* generate(input, length) {
+          let list = new Array(length);
+
+          function* values(pos) {
+            if (pos >= list.length) {
+              yield list;
+            } else {
+              for (let v of input) {
+                list[pos] = v;
+                yield* values(pos + 1);
+              }
+            }
+          }
+          yield* values(0);
+        }
+
+        // We're going to create a tree that looks like the
+        // follwing.
+        //
+        //           top          sixth
+        //          /   \
+        //         /     \        /
+        //      first  second
+        //      /   \           /
+        //     /     \
+        //  third  fourth - - -
+        //          /
+        //         /
+        //      fifth
+        //
+        // The idea is to have one top level non-auxiliary browsing
+        // context, five nested, one top level auxiliary with an
+        // opener. Given that set of related browsing contexts we
+        // wish to confirm that targeting is semantically equivalent
+        // with how nsIDocShellTreeItem.findItemWithName works. The
+        // trick to ensure that is to give all frames the same name!
+        // and ensure that the find algorithms return the same nodes
+        // in the same order.
+
+        function bc(frame) {
+          return (frame.contentWindow || frame).docShell.browsingContext;
+        }
+
+        let first = await addFrame(top, 'first');
+        let second = await addFrame(top, 'second');
+        let third = await addFrame(first, 'third');
+        let fourth = await addFrame(first, 'fourth');
+        let fifth = await addFrame(fourth, 'fifth');
+        let sixth = await addWindow(fourth, 'sixth');
+
+        let frames = [top, first, second, third, fourth, fifth, sixth];
+        let browsingContexts = frames.map(bc);
+        let docShells = browsingContexts.map(context => context.docShell);
+
+        ok(top.docShell instanceof Ci.nsIDocShellTreeItem,
+           "When we remove nsIDocShellTreeItem this test should be removed");
+
+        // For every browsing context we generate all possible
+        // combinations of names for these browsing contexts using
+        // "dummy" and "target" as possible name.
+        for (let names of generate(["dummy", "target"], docShells.length)) {
+          for (let i = names.length - 1; i >= 0; --i) {
+            docShells[i].name = names[i];
+          }
+
+          for (let i = 0; i < docShells.length; ++i) {
+            let docShell = docShells[i].findItemWithName('target', null, null, false);
+            let browsingContext = browsingContexts[i].findWithName('target');
+            is (docShell ? docShell.browsingContext : null, browsingContext,
+                "findItemWithName should find same browsing context as findWithName");
+          }
+        }
+
+        for (let target of ["_self", "_top", "_parent", "_blank"]) {
+          for (let i = 0; i < docShells.length; ++i) {
+            let docShell = docShells[i].findItemWithName(target, null, null, false);
+            let browsingContext = browsingContexts[i].findWithName(target);
+            is (docShell ? docShell.browsingContext : null, browsingContext,
+                "findItemWithName should find same browsing context as findWithName for " + target);
+          }
+        }
+      });
+
+      BrowserTestUtils.removeTab(await sixth);
+    });
+});