Bug 1427987 - Fix browser_navigateEvents.js on e10s. r=pbro
authorAlexandre Poirot <poirot.alex@gmail.com>
Mon, 08 Jan 2018 01:24:25 -0800
changeset 398587 9b49df8dc9b9
parent 398586 9c586454144b
child 398588 4f065bc82a46
push id33224
push userdluca@mozilla.com
push dateWed, 10 Jan 2018 21:59:28 +0000
treeherdermozilla-central@57386b58c057 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1427987
milestone59.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 1427987 - Fix browser_navigateEvents.js on e10s. r=pbro MozReview-Commit-ID: F5IP4Pa0P9N
devtools/server/tests/browser/browser_navigateEvents.js
--- a/devtools/server/tests/browser/browser_navigateEvents.js
+++ b/devtools/server/tests/browser/browser_navigateEvents.js
@@ -2,22 +2,26 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const URL1 = MAIN_DOMAIN + "navigate-first.html";
 const URL2 = MAIN_DOMAIN + "navigate-second.html";
 
-var EventEmitter = require("devtools/shared/event-emitter");
-var client;
+var isE10s = Services.appinfo.browserTabsRemoteAutostart;
 
 SpecialPowers.pushPrefEnv(
   {"set": [["dom.require_user_interaction_for_beforeunload", false]]});
 
+var signalAllEventsReceived;
+var onAllEventsReceived = new Promise(resolve => {
+  signalAllEventsReceived = resolve;
+});
+
 // State machine to check events order
 var i = 0;
 function assertEvent(event, data) {
   switch (i++) {
     case 0:
       is(event, "request", "Get first page load");
       is(data, URL1);
       break;
@@ -26,137 +30,147 @@ function assertEvent(event, data) {
       break;
     case 2:
       is(event, "unload-dialog", "We get the dialog on first page unload");
       break;
     case 3:
       is(event, "will-navigate", "The very first event is will-navigate on server side");
       is(data.newURI, URL2, "newURI property is correct");
       break;
-    case 4:
-      is(event, "request",
-        "RDP is async with messageManager, the request happens after will-navigate");
-      is(data, URL2);
-      break;
-    case 5:
+    case isE10s ? 4 : 5: // When e10s is disabled tabNavigated/request order is swapped
       is(event, "tabNavigated", "After the request, the client receive tabNavigated");
       is(data.state, "start", "state is start");
       is(data.url, URL2, "url property is correct");
       is(data.nativeConsoleAPI, true, "nativeConsoleAPI is correct");
       break;
+    case isE10s ? 5 : 4:
+      is(event, "request",
+        "RDP is async with messageManager, the request happens after will-navigate");
+      is(data, URL2);
+      break;
     case 6:
       is(event, "DOMContentLoaded");
-      // eslint-disable-next-line mozilla/no-cpows-in-tests
-      is(content.document.readyState, "interactive");
+      is(data.readyState, "interactive");
       break;
     case 7:
       is(event, "load");
-      // eslint-disable-next-line mozilla/no-cpows-in-tests
-      is(content.document.readyState, "complete");
+      is(data.readyState, "complete");
       break;
     case 8:
       is(event, "navigate",
         "Then once the second doc is loaded, we get the navigate event");
-      // eslint-disable-next-line mozilla/no-cpows-in-tests
-      is(content.document.readyState, "complete",
+      is(data.readyState, "complete",
         "navigate is emitted only once the document is fully loaded");
       break;
     case 9:
       is(event, "tabNavigated", "Finally, the receive the client event");
       is(data.state, "stop", "state is stop");
       is(data.url, URL2, "url property is correct");
       is(data.nativeConsoleAPI, true, "nativeConsoleAPI is correct");
 
-      // End of test!
-      cleanup();
+      signalAllEventsReceived();
       break;
   }
 }
 
 function waitForOnBeforeUnloadDialog(browser, callback) {
-  browser.addEventListener("DOMWillOpenModalDialog", function () {
-    executeSoon(() => {
-      let stack = browser.parentNode;
-      let dialogs = stack.getElementsByTagName("tabmodalprompt");
-      let {button0, button1} = dialogs[0].ui;
-      callback(button0, button1);
-    });
+  browser.addEventListener("DOMWillOpenModalDialog", async function (event) {
+    let stack = browser.parentNode;
+    let dialogs = stack.getElementsByTagName("tabmodalprompt");
+    await waitUntil(() => dialogs[0]);
+    let {button0, button1} = dialogs[0].ui;
+    callback(button0, button1);
   }, {capture: true, once: true});
 }
 
 var httpObserver = function (subject, topic, state) {
   let channel = subject.QueryInterface(Ci.nsIHttpChannel);
   let url = channel.URI.spec;
   // Only listen for our document request, as many other requests can happen
   if (url == URL1 || url == URL2) {
     assertEvent("request", url);
   }
 };
 Services.obs.addObserver(httpObserver, "http-on-modify-request");
 
-function onDOMContentLoaded() {
-  assertEvent("DOMContentLoaded");
-}
-function onLoad() {
-  assertEvent("load");
+function onMessage({ data }) {
+  assertEvent(data.event, data.data);
 }
 
-function getServerTabActor(callback) {
+async function connectAndAttachTab() {
   // Ensure having a minimal server
   initDebuggerServer();
 
   // Connect to this tab
   let transport = DebuggerServer.connectPipe();
-  client = new DebuggerClient(transport);
-  connectDebuggerClient(client).then(form => {
-    let actorID = form.actor;
-    client.attachTab(actorID, function (response, tabClient) {
-      // !Hack! Retrieve a server side object, the BrowserTabActor instance
-      let tabActor = DebuggerServer.searchAllConnectionsForActor(actorID);
-      callback(tabActor);
-    });
-  });
-
+  let client = new DebuggerClient(transport);
   client.addListener("tabNavigated", function (event, packet) {
     assertEvent("tabNavigated", packet);
   });
+  let form = await connectDebuggerClient(client);
+  let actorID = form.actor;
+  await client.attachTab(actorID);
+  return { client, actorID };
 }
 
-function test() {
+add_task(async function () {
   // Open a test tab
-  addTab(URL1).then(function (browser) {
-    getServerTabActor(function (tabActor) {
-      // In order to listen to internal will-navigate/navigate events
-      EventEmitter.on(tabActor, "will-navigate", function (data) {
-        assertEvent("will-navigate", data);
-      });
-      EventEmitter.on(tabActor, "navigate", function (data) {
-        assertEvent("navigate", data);
-      });
+  let browser = await addTab(URL1);
+
+  // Listen for alert() call being made in navigate-first during unload
+  waitForOnBeforeUnloadDialog(browser, function (btnLeave, btnStay) {
+    assertEvent("unload-dialog");
+    // accept to quit this page to another
+    btnLeave.click();
+  });
 
-      // Start listening for page load events
-      browser.addEventListener("DOMContentLoaded", onDOMContentLoaded, true);
-      browser.addEventListener("load", onLoad, true);
+  // Listen for messages sent by the content task
+  browser.messageManager.addMessageListener("devtools-test:event", onMessage);
+
+  let { client, actorID } = await connectAndAttachTab();
+  await ContentTask.spawn(browser, [actorID], async function (actorId) {
+    const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+    const { DebuggerServer } = require("devtools/server/main");
+    const EventEmitter = require("devtools/shared/event-emitter");
 
-      // Listen for alert() call being made in navigate-first during unload
-      waitForOnBeforeUnloadDialog(browser, function (btnLeave, btnStay) {
-        assertEvent("unload-dialog");
-        // accept to quit this page to another
-        btnLeave.click();
+    // !Hack! Retrieve a server side object, the BrowserTabActor instance
+    let tabActor = DebuggerServer.searchAllConnectionsForActor(actorId);
+    // In order to listen to internal will-navigate/navigate events
+    EventEmitter.on(tabActor, "will-navigate", function (data) {
+      sendSyncMessage("devtools-test:event", {
+        event: "will-navigate",
+        data: { newURI: data.newURI }
+      });
+    });
+    EventEmitter.on(tabActor, "navigate", function (data) {
+      sendSyncMessage("devtools-test:event", {
+        event: "navigate",
+        data: { readyState: content.document.readyState }
       });
-
-      // Load another document in this doc to dispatch these events
-      assertEvent("load-new-document");
-      BrowserTestUtils.loadURI(gBrowser.selectedBrowser, URL2);
     });
+    // Forward DOMContentLoaded and load events
+    addEventListener("DOMContentLoaded", function () {
+      sendSyncMessage("devtools-test:event", {
+        event: "DOMContentLoaded",
+        data: { readyState: content.document.readyState }
+      });
+    }, { capture: true });
+    addEventListener("load", function () {
+      sendSyncMessage("devtools-test:event", {
+        event: "load",
+        data: { readyState: content.document.readyState }
+      });
+    }, { capture: true });
   });
-}
+
+  // Load another document in this doc to dispatch these events
+  assertEvent("load-new-document");
+  BrowserTestUtils.loadURI(browser, URL2);
 
-function cleanup() {
-  let browser = gBrowser.selectedBrowser;
-  browser.removeEventListener("DOMContentLoaded", onDOMContentLoaded);
-  browser.removeEventListener("load", onLoad);
-  client.close().then(function () {
-    Services.obs.addObserver(httpObserver, "http-on-modify-request");
-    DebuggerServer.destroy();
-    finish();
-  });
-}
+  // Wait for all events to be received
+  await onAllEventsReceived;
+
+  // Cleanup
+  browser.messageManager.removeMessageListener("devtools-test:event", onMessage);
+  await client.close();
+  Services.obs.addObserver(httpObserver, "http-on-modify-request");
+  DebuggerServer.destroy();
+});