Bug 1432856 - Added tests for window open and focus in fullscreen. r=smaug
☠☠ backed out by d94afce0c18b ☠ ☠
authorpbz <pbz@mozilla.com>
Mon, 16 Dec 2019 21:08:29 +0000
changeset 507299 49d03dd89b1759bdf28f50ad5330d5a2f9651803
parent 507298 62fc84c8ce9978f4df6d65ac6e8d8e4939b0bb65
child 507300 3d08c3cce53325d6623178e60d1ca5d38b4721c5
push id103347
push userpzuhlcke@mozilla.com
push dateMon, 16 Dec 2019 21:26:02 +0000
treeherderautoland@3d08c3cce533 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1432856
milestone73.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 1432856 - Added tests for window open and focus in fullscreen. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D56391
browser/base/content/test/fullscreen/browser.ini
browser/base/content/test/fullscreen/browser_fullscreen_window_focus.js
browser/base/content/test/fullscreen/browser_fullscreen_window_open.js
browser/base/content/test/fullscreen/head.js
browser/base/content/test/fullscreen/open_and_focus_helper.html
--- a/browser/base/content/test/fullscreen/browser.ini
+++ b/browser/base/content/test/fullscreen/browser.ini
@@ -1,9 +1,14 @@
 [DEFAULT]
 support-files =
   head.js
+  open_and_focus_helper.html
 [browser_bug1557041.js]
 skip-if = os == 'linux' # Bug 1561973
 [browser_fullscreen_permissions_prompt.js]
 skip-if = debug && os == 'mac' # Bug 1568570
 [browser_fullscreen_cross_origin.js]
 support-files = fullscreen.html fullscreen_frame.html
+[browser_fullscreen_window_open.js]
+skip-if = debug && os == 'mac' # Bug 1568570
+[browser_fullscreen_window_focus.js]
+skip-if = debug && os == 'mac' # Bug 1568570
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/fullscreen/browser_fullscreen_window_focus.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// This test tends to trigger a race in the fullscreen time telemetry,
+// where the fullscreen enter and fullscreen exit events (which use the
+// same histogram ID) overlap. That causes TelemetryStopwatch to log an
+// error.
+SimpleTest.ignoreAllUncaughtExceptions(true);
+
+const TEST_URL =
+  "http://example.com/browser/browser/base/content/test/fullscreen/open_and_focus_helper.html";
+const IFRAME_ID = "testIframe";
+
+async function testWindowFocus(iframeID) {
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+
+  info("Calling window.open()");
+  let popup = await jsWindowOpen(tab.linkedBrowser, iframeID);
+  info("re-focusing main window");
+  await waitForFocus();
+
+  info("Entering full-screen");
+  await changeFullscreen(tab.linkedBrowser, true);
+
+  await testExpectFullScreenExit(tab.linkedBrowser, true, async () => {
+    info("Calling window.focus()");
+    await jsWindowFocus(tab.linkedBrowser, iframeID);
+  });
+
+  // Cleanup
+  popup.close();
+  BrowserTestUtils.removeTab(tab);
+}
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ["dom.disable_open_during_load", false], // Allow window.focus calls without user interaction
+    ],
+  });
+});
+
+add_task(function test_parentWindowFocus() {
+  return testWindowFocus();
+});
+
+add_task(function test_iframeWindowFocus() {
+  return testWindowFocus(IFRAME_ID);
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/fullscreen/browser_fullscreen_window_open.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// This test tends to trigger a race in the fullscreen time telemetry,
+// where the fullscreen enter and fullscreen exit events (which use the
+// same histogram ID) overlap. That causes TelemetryStopwatch to log an
+// error.
+SimpleTest.ignoreAllUncaughtExceptions(true);
+
+const TEST_URL =
+  "http://example.com/browser/browser/base/content/test/fullscreen/open_and_focus_helper.html";
+const IFRAME_ID = "testIframe";
+
+async function testWindowOpen(iframeID) {
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+  info("Entering full-screen");
+  await changeFullscreen(tab.linkedBrowser, true);
+
+  let popup;
+  await testExpectFullScreenExit(tab.linkedBrowser, true, async () => {
+    info("Calling window.open()");
+    popup = await jsWindowOpen(tab.linkedBrowser, iframeID);
+  });
+
+  // Cleanup
+  await BrowserTestUtils.closeWindow(popup);
+  BrowserTestUtils.removeTab(tab);
+}
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ["dom.disable_open_during_load", false], // Allow window.open calls without user interaction
+    ],
+  });
+});
+
+add_task(function test_parentWindowOpen() {
+  return testWindowOpen();
+});
+
+add_task(function test_iframeWindowOpen() {
+  return testWindowOpen(IFRAME_ID);
+});
--- a/browser/base/content/test/fullscreen/head.js
+++ b/browser/base/content/test/fullscreen/head.js
@@ -1,26 +1,25 @@
 const { ContentTaskUtils } = ChromeUtils.import(
   "resource://testing-common/ContentTaskUtils.jsm"
 );
 function waitForFullScreenState(browser, state) {
-  info("inside waitforfullscreenstate");
   return new Promise(resolve => {
     let eventReceived = false;
 
     let observe = (subject, topic, data) => {
       if (!eventReceived) {
         return;
       }
       Services.obs.removeObserver(observe, "fullscreen-painted");
       resolve();
     };
     Services.obs.addObserver(observe, "fullscreen-painted");
 
-    window.addEventListener(
+    browser.ownerGlobal.addEventListener(
       `MozDOMFullscreen:${state ? "Entered" : "Exited"}`,
       () => {
         eventReceived = true;
       },
       { once: true }
     );
   });
 }
@@ -45,8 +44,83 @@ async function changeFullscreen(browser,
     if (state) {
       content.document.body.requestFullscreen();
     } else {
       content.document.exitFullscreen();
     }
   });
   return fullScreenChange;
 }
+
+async function testExpectFullScreenExit(browser, leaveFS, action) {
+  let fsPromise = waitForFullScreenState(browser, !leaveFS);
+  if (leaveFS) {
+    if (action) {
+      await action();
+    }
+    await fsPromise;
+    ok(true, "Should leave full-screen");
+  } else {
+    if (action) {
+      await action();
+    }
+    let result = await Promise.race([
+      fsPromise,
+      new Promise(resolve => {
+        SimpleTest.requestFlakyTimeout("Wait for failure condition");
+        // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+        setTimeout(() => resolve(true), 2500);
+      }),
+    ]);
+    ok(result, "Should not leave full-screen");
+  }
+}
+
+function jsWindowFocus(browser, iframeId) {
+  return ContentTask.spawn(browser, { iframeId }, async args => {
+    let destWin = content;
+    if (args.iframeId) {
+      let iframe = content.document.getElementById(args.iframeId);
+      if (!iframe) {
+        throw new Error("iframe not set");
+      }
+      destWin = iframe.contentWindow;
+    }
+    await content.wrappedJSObject.sendMessage(destWin, "focus");
+  });
+}
+
+async function jsWindowOpen(browser, iframeId) {
+  let windowOpened = BrowserTestUtils.waitForNewWindow();
+  ContentTask.spawn(browser, { iframeId }, async args => {
+    let destWin = content;
+    if (args.iframeId) {
+      // Create a cross origin iframe
+      destWin = (await content.wrappedJSObject.createIframe(
+        args.iframeId,
+        true
+      )).contentWindow;
+    }
+    // Send message to either the iframe or the current page to open a popup
+    await content.wrappedJSObject.sendMessage(destWin, "open");
+  });
+  return windowOpened;
+}
+
+function waitForFocus(...args) {
+  return new Promise(resolve => SimpleTest.waitForFocus(resolve, ...args));
+}
+
+function waitForBrowserWindowActive(win) {
+  return new Promise(resolve => {
+    if (Services.focus.activeWindow == win) {
+      resolve();
+    } else {
+      win.addEventListener(
+        "activate",
+        () => {
+          resolve();
+        },
+        { once: true }
+      );
+    }
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/fullscreen/open_and_focus_helper.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset='utf-8'>
+</head>
+<body>
+  <script>
+    const MY_ORIGIN = window.location.origin;
+    const CROSS_ORIGIN = "https://example.org";
+
+    // Creates an iframe with message channel to trigger window open and focus
+    window.createIframe = function(id, crossOrigin = false) {
+      return new Promise(resolve => {
+        const origin = crossOrigin ? CROSS_ORIGIN : MY_ORIGIN;
+        let iframe = document.createElement("iframe");
+        iframe.id = id;
+        iframe.src = origin + window.location.pathname;
+        iframe.onload = () => resolve(iframe);
+        document.body.appendChild(iframe);
+      });
+    }
+
+    window.sendMessage = function(destWin, msg) {
+      return new Promise(resolve => {
+        let channel = new MessageChannel();
+        channel.port1.onmessage = resolve;
+        destWin.postMessage(msg, "*", [channel.port2]);
+      });
+    }
+
+    window.onMessage = function(event) {
+      let canReply = event.ports && event.ports.length > 0;
+      if(event.data === "open") {
+        window.popup = window.open('https://example.com', '', 'top=0,height=1, width=300');
+        if (canReply) event.ports[0].postMessage('opened');
+      } else if(event.data === "focus") {
+        window.popup.focus();
+        if (canReply) event.ports[0].postMessage('focused');
+      }
+    }
+    window.addEventListener('message', window.onMessage);
+  </script>
+</body>
+</html>