Bug 1239122 - Make docshell browser-chrome tests e10s compatible. r=billm
authorBlake Kaplan <mrbkap@gmail.com>
Wed, 20 Jan 2016 14:14:00 +0100
changeset 280839 f405663b5570ba4462a7703ba3f0b4f1d9dcc143
parent 280838 55f1fc505b88998fb91ca144d97a7fef2a14ba86
child 280840 1ba31786ecfd539f6fd681a4f897d788027bbb77
push id70610
push usercbook@mozilla.com
push dateThu, 21 Jan 2016 08:25:59 +0000
treeherdermozilla-inbound@1ba31786ecfd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1239122
milestone46.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 1239122 - Make docshell browser-chrome tests e10s compatible. r=billm
docshell/test/browser/browser.ini
docshell/test/browser/browser_bug349769.js
docshell/test/browser/browser_bug388121-1.js
docshell/test/browser/browser_bug422543.js
docshell/test/browser/browser_bug670318.js
docshell/test/browser/file_bug422543_script.js
docshell/test/browser/file_bug670318.html
docshell/test/navigation/browser.ini
docshell/test/navigation/browser_bug343515.js
--- a/docshell/test/browser/browser.ini
+++ b/docshell/test/browser/browser.ini
@@ -22,16 +22,17 @@ support-files =
   file_bug234628-7-child.html
   file_bug234628-7-child.html^headers^
   file_bug234628-7.html
   file_bug234628-8-child.html
   file_bug234628-8.html
   file_bug234628-9-child.html
   file_bug234628-9.html
   file_bug420605.html
+  file_bug422543_script.js
   file_bug503832.html
   file_bug655270.html
   file_bug670318.html
   file_bug852909.pdf
   file_bug852909.png
   file_bug1046022.html
   file_bug1206879.html
   file_multiple_pushState.html
@@ -54,32 +55,28 @@ support-files =
 [browser_bug234628-3.js]
 [browser_bug234628-4.js]
 [browser_bug234628-5.js]
 [browser_bug234628-6.js]
 [browser_bug234628-7.js]
 [browser_bug234628-8.js]
 [browser_bug234628-9.js]
 [browser_bug349769.js]
-skip-if = e10s # Bug ?????? - test touches content (newBrowser.contentDocument.nodePrincipal)
 [browser_bug388121-1.js]
-skip-if = e10s # Bug ?????? - test touches content (newBrowser.contentDocument.nodePrincipal)
 [browser_bug388121-2.js]
 [browser_bug420605.js]
 [browser_bug422543.js]
-skip-if = e10s # Bug 1220927 - Test tries to do addSHistoryListener on content.
 [browser_bug441169.js]
 skip-if = buildapp == 'mulet'
 [browser_bug503832.js]
 skip-if = buildapp == 'mulet'
 [browser_bug554155.js]
 [browser_bug655270.js]
 [browser_bug655273.js]
 [browser_bug670318.js]
-skip-if = e10s # Bug 1220927 - Test tries to do addSHistoryListener on content.
 [browser_bug673467.js]
 [browser_bug852909.js]
 [browser_bug92473.js]
 [browser_uriFixupIntegration.js]
 [browser_loadDisallowInherit.js]
 [browser_loadURI.js]
 [browser_multiple_pushState.js]
 [browser_onbeforeunload_navigation.js]
--- a/docshell/test/browser/browser_bug349769.js
+++ b/docshell/test/browser/browser_bug349769.js
@@ -1,44 +1,47 @@
-function test() {
-  waitForExplicitFinish(); 
-
-  var newTab;
-  var newBrowser;
+add_task(function* test() {
   const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
-  var iteration = 1;
   const uris = [undefined, "about:blank"];
-  var uri;
 
-  function testLoad(event) {
-    newBrowser.removeEventListener("load", testLoad, true);
-    is (event.target, newBrowser.contentDocument, "Unexpected target");
-    var prin = newBrowser.contentDocument.nodePrincipal;
-    isnot(prin, null, "Loaded principal must not be null when adding " + uri);
-    isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
-    is(secMan.isSystemPrincipal(prin), false,
-       "Loaded principal must not be system when loading " + uri);
-    gBrowser.removeTab(newTab);
+  function checkContentProcess(uri) {
+    yield ContentTask.spawn(newBrowser, uri, function* (uri) {
+      var prin = content.document.nodePrincipal;
+      isnot(prin, null, "Loaded principal must not be null when adding " + uri);
+      isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
 
-    if (iteration == uris.length) {
-      finish();
-    } else {
-      ++iteration;
-      doTest();
-    }
+      const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+                       .getService(Ci.nsIScriptSecurityManager);
+      is(secMan.isSystemPrincipal(prin), false,
+         "Loaded principal must not be system when loading " + uri);
+    });
   }
 
-  function doTest() {
-    uri = uris[iteration - 1];
-    newTab = gBrowser.addTab(uri);
-    newBrowser = gBrowser.getBrowserForTab(newTab);
-    newBrowser.addEventListener("load", testLoad, true);
-    var prin = newBrowser.contentDocument.nodePrincipal;
-    isnot(prin, null, "Forced principal must not be null when loading " + uri);
-    isnot(prin, undefined,
-          "Forced principal must not be undefined when loading " + uri);
-    is(secMan.isSystemPrincipal(prin), false,
-       "Forced principal must not be system when loading " + uri);
-   }
+  for (var uri of uris) {
+    yield BrowserTestUtils.withNewTab({ gBrowser }, function* (newBrowser) {
+      yield BrowserTestUtils.loadURI(newBrowser, uri);
+
+      var prin = newBrowser.contentPrincipal;
+      isnot(prin, null, "Forced principal must not be null when loading " + uri);
+      isnot(prin, undefined,
+            "Forced principal must not be undefined when loading " + uri);
+      is(secMan.isSystemPrincipal(prin), false,
+         "Forced principal must not be system when loading " + uri);
+
+      // Belt-and-suspenders e10s check: make sure that the same checks hold
+      // true in the content process.
+      checkContentProcess(uri);
 
-   doTest();
-}
+      yield BrowserTestUtils.browserLoaded(newBrowser);
+
+      prin = newBrowser.contentPrincipal;
+      isnot(prin, null, "Loaded principal must not be null when adding " + uri);
+      isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+      is(secMan.isSystemPrincipal(prin), false,
+         "Loaded principal must not be system when loading " + uri);
 
+      // Belt-and-suspenders e10s check: make sure that the same checks hold
+      // true in the content process.
+      checkContentProcess(uri);
+    });
+  }
+});
+
--- a/docshell/test/browser/browser_bug388121-1.js
+++ b/docshell/test/browser/browser_bug388121-1.js
@@ -1,26 +1,15 @@
-function test() {
-  waitForExplicitFinish(); 
-
-  var newTab;
-  var newBrowser;
-  const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
+add_task(function* test() {
+  yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (newBrowser) {
+    yield ContentTask.spawn(newBrowser, null, function* () {
+      var prin = content.document.nodePrincipal;
+      isnot(prin, null, "Loaded principal must not be null");
+      isnot(prin, undefined, "Loaded principal must not be undefined");
 
-  function testLoad(event) {
-    newBrowser.removeEventListener("load", testLoad, true);
-    is (event.target, newBrowser.contentDocument, "Unexpected target");
-    var prin = newBrowser.contentDocument.nodePrincipal;
-    isnot(prin, null, "Loaded principal must not be null");
-    isnot(prin, undefined, "Loaded principal must not be undefined");
-    is(secMan.isSystemPrincipal(prin), false,
-       "Loaded principal must not be system");
-    gBrowser.removeTab(newTab);
+      const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+                       .getService(Ci.nsIScriptSecurityManager);
+      is(secMan.isSystemPrincipal(prin), false,
+         "Loaded principal must not be system");
+    });
+  });
+});
 
-    finish();
-  }
-
-  newTab = gBrowser.addTab();
-  newBrowser = gBrowser.getBrowserForTab(newTab);
-  newBrowser.contentWindow.location.href = "about:blank"
-  newBrowser.addEventListener("load", testLoad, true);
-}
-
--- a/docshell/test/browser/browser_bug422543.js
+++ b/docshell/test/browser/browser_bug422543.js
@@ -1,174 +1,116 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function SHistoryListener() {
-}
-
-SHistoryListener.prototype = {
-  retval: true,
-  last: "initial",
-
-  OnHistoryNewEntry: function (aNewURI) {
-    this.last = "newentry";
-  },
-
-  OnHistoryGoBack: function (aBackURI) {
-    this.last = "goback";
-    return this.retval;
-  },
-
-  OnHistoryGoForward: function (aForwardURI) {
-    this.last = "goforward";
-    return this.retval;
-  },
-
-  OnHistoryGotoIndex: function (aIndex, aGotoURI) {
-    this.last = "gotoindex";
-    return this.retval;
-  },
-
-  OnHistoryPurge: function (aNumEntries) {
-    this.last = "purge";
-    return this.retval;
-  },
-
-  OnHistoryReload: function (aReloadURI, aReloadFlags) {
-    this.last = "reload";
-    return this.retval;
-  },
-
-  OnHistoryReplaceEntry: function (aIndex) {},
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
-                                         Ci.nsISupportsWeakReference])
-};
-
-var gFirstListener = new SHistoryListener();
-var gSecondListener = new SHistoryListener();
-
-function test() {
-  TestRunner.run();
-}
-
-function runTests() {
+add_task(function* runTests() {
   yield setup();
   let browser = gBrowser.selectedBrowser;
-  checkListeners("initial", "listeners initialized");
+  // Now that we're set up, initialize our frame script.
+  yield checkListeners("initial", "listeners initialized");
 
   // Check if all history listeners are always notified.
   info("# part 1");
-  browser.loadURI("http://www.example.com/");
-  yield whenPageShown(browser);
-  checkListeners("newentry", "shistory has a new entry");
+  yield whenPageShown(browser, () => browser.loadURI("http://www.example.com/"));
+  yield checkListeners("newentry", "shistory has a new entry");
   ok(browser.canGoBack, "we can go back");
 
-  browser.goBack();
-  yield whenPageShown(browser);
-  checkListeners("goback", "back to the first shentry");
+  yield whenPageShown(browser, () => browser.goBack());
+  yield checkListeners("goback", "back to the first shentry");
   ok(browser.canGoForward, "we can go forward");
 
-  browser.goForward();
-  yield whenPageShown(browser);
-  checkListeners("goforward", "forward to the second shentry");
+  yield whenPageShown(browser, () => browser.goForward());
+  yield checkListeners("goforward", "forward to the second shentry");
 
-  browser.reload();
-  yield whenPageShown(browser);
-  checkListeners("reload", "current shentry reloaded");
+  yield whenPageShown(browser, () => browser.reload());
+  yield checkListeners("reload", "current shentry reloaded");
 
-  browser.gotoIndex(0);
-  yield whenPageShown(browser);
-  checkListeners("gotoindex", "back to the first index");
+  yield whenPageShown(browser, () => browser.gotoIndex(0));
+  yield checkListeners("gotoindex", "back to the first index");
 
   // Check nsISHistoryInternal.notifyOnHistoryReload
   info("# part 2");
-  ok(notifyReload(), "reloading has not been canceled");
-  checkListeners("reload", "saw the reload notification");
+  ok((yield notifyReload()), "reloading has not been canceled");
+  yield checkListeners("reload", "saw the reload notification");
 
   // Let the first listener cancel the reload action.
   info("# part 3");
-  resetListeners();
-  gFirstListener.retval = false;
-  ok(!notifyReload(), "reloading has been canceled");
-  checkListeners("reload", "saw the reload notification");
+  yield resetListeners();
+  yield setListenerRetval(0, false);
+  ok(!(yield notifyReload()), "reloading has been canceled");
+  yield checkListeners("reload", "saw the reload notification");
 
   // Let both listeners cancel the reload action.
   info("# part 4");
-  resetListeners();
-  gSecondListener.retval = false;
-  ok(!notifyReload(), "reloading has been canceled");
-  checkListeners("reload", "saw the reload notification");
+  yield resetListeners();
+  yield setListenerRetval(1, false);
+  ok(!(yield notifyReload()), "reloading has been canceled");
+  yield checkListeners("reload", "saw the reload notification");
 
   // Let the second listener cancel the reload action.
   info("# part 5");
-  resetListeners();
-  gFirstListener.retval = true;
-  ok(!notifyReload(), "reloading has been canceled");
-  checkListeners("reload", "saw the reload notification");
+  yield resetListeners();
+  yield setListenerRetval(0, true);
+  ok(!(yield notifyReload()), "reloading has been canceled");
+  yield checkListeners("reload", "saw the reload notification");
+});
+
+function listenOnce(message, arg = {}) {
+  return new Promise(resolve => {
+    let mm = gBrowser.selectedBrowser.messageManager;
+    mm.addMessageListener(message + ":return", function listener(msg) {
+      mm.removeMessageListener(message + ":return", listener);
+      resolve(msg.data);
+    });
+
+    mm.sendAsyncMessage(message, arg);
+  });
 }
 
 function checkListeners(aLast, aMessage) {
-  is(gFirstListener.last, aLast, aMessage);
-  is(gSecondListener.last, aLast, aMessage);
+  return listenOnce("bug422543:getListenerStatus").then((listenerStatuses) => {
+    is(listenerStatuses[0], aLast, aMessage);
+    is(listenerStatuses[1], aLast, aMessage);
+  });
 }
 
 function resetListeners() {
-  gFirstListener.last = gSecondListener.last = "initial";
+  return listenOnce("bug422543:resetListeners");
 }
 
 function notifyReload() {
-  let browser = gBrowser.selectedBrowser;
-  let shistory = browser.docShell.sessionHistory;
-  shistory.QueryInterface(Ci.nsISHistoryInternal);
-  return shistory.notifyOnHistoryReload(browser.currentURI, 0);
-}
-
-function setup(aCallback) {
-  let tab = gBrowser.selectedTab = gBrowser.addTab("about:mozilla");
-  let browser = tab.linkedBrowser;
-  registerCleanupFunction(function () { gBrowser.removeTab(tab); });
-
-  whenPageShown(browser, function () {
-    gFirstListener = new SHistoryListener();
-    gSecondListener = new SHistoryListener();
-
-    let shistory = browser.docShell.sessionHistory;
-    shistory.addSHistoryListener(gFirstListener);
-    shistory.addSHistoryListener(gSecondListener);
-
-    registerCleanupFunction(function () {
-      shistory.removeSHistoryListener(gFirstListener);
-      shistory.removeSHistoryListener(gSecondListener);
-    });
-
-    (aCallback || TestRunner.next)();
+  return listenOnce("bug422543:notifyReload").then(({ rval }) => {
+    return rval;
   });
 }
 
-function whenPageShown(aBrowser, aCallback) {
-  aBrowser.addEventListener("pageshow", function onLoad() {
-    aBrowser.removeEventListener("pageshow", onLoad, true);
-    executeSoon(aCallback || TestRunner.next);
-  }, true);
+function setListenerRetval(num, val) {
+  return listenOnce("bug422543:setRetval", { num, val });
 }
 
-var TestRunner = {
-  run: function () {
-    waitForExplicitFinish();
-    this._iter = runTests();
-    this.next();
-  },
+function setup() {
+  return BrowserTestUtils.openNewForegroundTab(gBrowser,
+                                               "http://mochi.test:8888")
+                         .then(function (tab) {
+    let browser = tab.linkedBrowser;
+    registerCleanupFunction(function* () {
+      yield listenOnce("bug422543:cleanup");
+      gBrowser.removeTab(tab);
+    });
 
-  next: function () {
-    try {
-      TestRunner._iter.next();
-    } catch (e if e instanceof StopIteration) {
-      TestRunner.finish();
-    }
-  },
+    browser.messageManager
+           .loadFrameScript(getRootDirectory(gTestPath) + "file_bug422543_script.js", false);
+  });
+}
 
-  finish: function () {
-    finish();
-  }
-};
+function whenPageShown(aBrowser, aNavigation) {
+  let listener = ContentTask.spawn(aBrowser, null, function () {
+    return new Promise(resolve => {
+      addEventListener("pageshow", function onLoad() {
+        removeEventListener("pageshow", onLoad, true);
+        resolve();
+      }, true);
+    });
+  });
+
+  aNavigation();
+  return listener;
+}
--- a/docshell/test/browser/browser_bug670318.js
+++ b/docshell/test/browser/browser_bug670318.js
@@ -5,56 +5,58 @@
  * Test for Bug 670318
  *
  * When LoadEntry() is called on a browser that has multiple duplicate history
  * entries, history.index can end up out of range (>= history.count).
  */
 
 const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
 
-function test() {
-  waitForExplicitFinish();
-
-  let count = 0, historyListenerRemoved = false;
+add_task(function* test() {
+  yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
+                                    function* (browser) {
+    yield ContentTask.spawn(browser, URL, function* (URL) {
+      let history = docShell.sessionHistory;
+      let count = 0;
 
-  let listener = {
-    OnHistoryNewEntry: function (aNewURI) {
-      if (aNewURI.spec == URL && 5 == ++count) {
-        browser.addEventListener("load", function onLoad() {
-          browser.removeEventListener("load", onLoad, true);
+      let testDone = {};
+      testDone.promise = new Promise(resolve => { testDone.resolve = resolve; });
 
-          ok(history.index < history.count, "history.index is valid");
-          finish();
-        }, true);
+      let listener = {
+        OnHistoryNewEntry: function (aNewURI) {
+          if (aNewURI.spec == URL && 5 == ++count) {
+            addEventListener("load", function onLoad() {
+              removeEventListener("load", onLoad, true);
 
-        history.removeSHistoryListener(listener);
-        historyListenerRemoved = true;
+              ok(history.index < history.count, "history.index is valid");
+              testDone.resolve();
+            }, true);
 
-        executeSoon(function () { BrowserReload(); });
-      }
-
-      return true;
-    },
+            history.removeSHistoryListener(listener);
+            content.setTimeout(() => { content.location.reload(); }, 0);
+          }
 
-    OnHistoryReload: () => true,
-    OnHistoryGoBack: () => true,
-    OnHistoryGoForward: () => true,
-    OnHistoryGotoIndex: () => true,
-    OnHistoryPurge: () => true,
-    OnHistoryReplaceEntry: () => true,
-
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
-                                           Ci.nsISupportsWeakReference])
-  };
+          return true;
+        },
 
-  let tab = gBrowser.loadOneTab(URL, {inBackground: false});
-  let browser = tab.linkedBrowser;
-  let history = browser.sessionHistory;
-
-  history.addSHistoryListener(listener);
+        OnHistoryReload: () => true,
+        OnHistoryGoBack: () => true,
+        OnHistoryGoForward: () => true,
+        OnHistoryGotoIndex: () => true,
+        OnHistoryPurge: () => true,
+        OnHistoryReplaceEntry: () => {
+          // The initial load of about:blank causes a transient entry to be
+          // created, so our first navigation to a real page is a replace
+          // instead of a new entry.
+          ++count;
+          return true;
+        },
 
-  registerCleanupFunction(function () {
-    gBrowser.removeTab(tab);
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
+                                               Ci.nsISupportsWeakReference])
+      };
 
-    if (!historyListenerRemoved)
-      history.removeSHistoryListener(listener);
+      history.addSHistoryListener(listener);
+      content.location = URL;
+      yield testDone.promise;
+    });
   });
-}
+});
new file mode 100644
--- /dev/null
+++ b/docshell/test/browser/file_bug422543_script.js
@@ -0,0 +1,98 @@
+const { utils: Cu, interfaces: Ci } = Components;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function SHistoryListener() {
+}
+
+SHistoryListener.prototype = {
+  retval: true,
+  last: "initial",
+
+  OnHistoryNewEntry: function (aNewURI) {
+    this.last = "newentry";
+  },
+
+  OnHistoryGoBack: function (aBackURI) {
+    this.last = "goback";
+    return this.retval;
+  },
+
+  OnHistoryGoForward: function (aForwardURI) {
+    this.last = "goforward";
+    return this.retval;
+  },
+
+  OnHistoryGotoIndex: function (aIndex, aGotoURI) {
+    this.last = "gotoindex";
+    return this.retval;
+  },
+
+  OnHistoryPurge: function (aNumEntries) {
+    this.last = "purge";
+    return this.retval;
+  },
+
+  OnHistoryReload: function (aReloadURI, aReloadFlags) {
+    this.last = "reload";
+    return this.retval;
+  },
+
+  OnHistoryReplaceEntry: function (aIndex) {},
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
+                                         Ci.nsISupportsWeakReference])
+};
+
+let testAPI = {
+  shistory: null,
+  listeners: [ new SHistoryListener(),
+               new SHistoryListener() ],
+
+  init() {
+    this.shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
+    for (let listener of this.listeners) {
+      this.shistory.addSHistoryListener(listener);
+    }
+  },
+
+  cleanup() {
+    for (let listener of this.listeners) {
+      this.shistory.removeSHistoryListener(listener);
+    }
+    this.shistory = null;
+    sendAsyncMessage("bug422543:cleanup:return", {});
+  },
+
+  getListenerStatus() {
+    sendAsyncMessage("bug422543:getListenerStatus:return",
+                     this.listeners.map(l => l.last));
+  },
+
+  resetListeners() {
+    for (let listener of this.listeners) {
+      listener.last = "initial";
+    }
+
+    sendAsyncMessage("bug422543:resetListeners:return", {});
+  },
+
+  notifyReload() {
+    let internal = this.shistory.QueryInterface(Ci.nsISHistoryInternal);
+    let rval =
+      internal.notifyOnHistoryReload(content.document.documentURIObject, 0);
+    sendAsyncMessage("bug422543:notifyReload:return", { rval });
+  },
+
+  setRetval({ num, val }) {
+    this.listeners[num].retval = val;
+    sendAsyncMessage("bug422543:setRetval:return", {});
+  },
+};
+
+addMessageListener("bug422543:cleanup", () => { testAPI.cleanup(); });
+addMessageListener("bug422543:getListenerStatus", () => { testAPI.getListenerStatus(); });
+addMessageListener("bug422543:notifyReload", () => { testAPI.notifyReload(); });
+addMessageListener("bug422543:resetListeners", () => { testAPI.resetListeners(); });
+addMessageListener("bug422543:setRetval", (msg) => { testAPI.setRetval(msg.data); });
+
+testAPI.init();
--- a/docshell/test/browser/file_bug670318.html
+++ b/docshell/test/browser/file_bug670318.html
@@ -1,15 +1,15 @@
 <html><head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 <script>
 function load() {
   function next() {
     if (count < 5)
-      iframe.src = 'data:text/html,iframe ' + (++count);
+      iframe.src = 'data:text/html;charset=utf-8,iframe ' + (++count);
   }
 
   var count = 0;
   var iframe = document.createElement('iframe');
   iframe.onload = function () { setTimeout(next, 0) };
   document.body.appendChild(iframe);
 
   setTimeout(next, 0);
--- a/docshell/test/navigation/browser.ini
+++ b/docshell/test/navigation/browser.ini
@@ -3,10 +3,9 @@ support-files =
   bug343515_pg1.html
   bug343515_pg2.html
   bug343515_pg3.html
   bug343515_pg3_1.html
   bug343515_pg3_1_1.html
   bug343515_pg3_2.html
 
 [browser_bug343515.js]
-skip-if = e10s # Bug ?????? - test directly touches content (tries to QI the content window)
 [browser_test-content-chromeflags.js]
--- a/docshell/test/navigation/browser_bug343515.js
+++ b/docshell/test/navigation/browser_bug343515.js
@@ -1,22 +1,14 @@
 // Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden
 
 // Globals
 var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
 var ctx = {};
 
-// Helper function to check if a window is active
-function isActive(aWindow) {
-  var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIWebNavigation)
-                        .QueryInterface(Ci.nsIDocShell);
-  return docshell.isActive;
-}
-
 // We need to wait until the page from each testcase is fully loaded,
 // including all of its descendant iframes. To do that we manually count
 // how many load events should happen on that page (one for the toplevel doc
 // and one for each subframe) and wait until we receive the expected number
 // of events.
 function nShotsListener(aElem, aType, aCallback, aCount) {
   let count = aCount;
   aElem.addEventListener(aType, function listenerCallback() {
@@ -29,182 +21,239 @@ function nShotsListener(aElem, aType, aC
     }
   }, true);
 }
 
 function oneShotListener(aElem, aType, aCallback) {
   nShotsListener(aElem, aType, aCallback, 1);
 }
 
+function waitForPageshow(aBrowser, callback) {
+  return ContentTask.spawn(aBrowser, null, function* () {
+    yield ContentTaskUtils.waitForEvent(this, "pageshow");
+  }).then(callback);
+}
+
 // Entry point from Mochikit
 function test() {
 
   // Lots of callbacks going on here
   waitForExplicitFinish();
 
   // Begin the test
   step1();
 }
 
 function step1() {
 
   // Get a handle on the initial tab
   ctx.tab0 = gBrowser.selectedTab;
   ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
-  ctx.tab0Window = ctx.tab0Browser.contentWindow;
 
   // Our current tab should be active
-  ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start");
+  ok(ctx.tab0Browser.docShellIsActive, "Tab 0 should be active at test start");
 
   // Open a New Tab
   ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
   ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
-  ctx.tab1Window = ctx.tab1Browser.contentWindow;
   oneShotListener(ctx.tab1Browser, "load", step2);
 }
 
 function step2() {
   is(testPath + "bug343515_pg1.html", ctx.tab1Browser.currentURI.spec,
      "Got expected tab 1 url in step 2");
 
   // Our current tab should still be active
-  ok(isActive(ctx.tab0Window), "Tab 0 should still be active");
-  ok(!isActive(ctx.tab1Window), "Tab 1 should not be active");
+  ok(ctx.tab0Browser.docShellIsActive, "Tab 0 should still be active");
+  ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should not be active");
 
   // Switch to tab 1
-  gBrowser.selectedTab = ctx.tab1;
-
-  // Tab 1 should now be active
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(isActive(ctx.tab1Window), "Tab 1 should be active");
+  BrowserTestUtils.switchTab(gBrowser, ctx.tab1).then(() => {
+    // Tab 1 should now be active
+    ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+    ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
 
-  // Open another tab
-  ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
-  ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
-  ctx.tab2Window = ctx.tab2Browser.contentWindow;
+    // Open another tab
+    ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
+    ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
 
-  // bug343515_pg2.html consists of a page with two iframes,
-  // which will therefore generate 3 load events.
-  nShotsListener(ctx.tab2Browser, "load", step3, 3);
+    // bug343515_pg2.html consists of a page with two iframes,
+    // which will therefore generate 3 load events.
+    nShotsListener(ctx.tab2Browser, "load", step3, 3);
+  });
 }
 
 function step3() {
   is(testPath + "bug343515_pg2.html", ctx.tab2Browser.currentURI.spec,
      "Got expected tab 2 url in step 3");
 
   // Tab 0 should be inactive, Tab 1 should be active
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(isActive(ctx.tab1Window), "Tab 1 should be active");
+  ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+  ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
 
   // Tab 2's window _and_ its iframes should be inactive
-  ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
-  is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
-  for (var i = 0; i < ctx.tab2Window.frames.length; i++)
-    info("step 3, frame " + i + " info: " + ctx.tab2Window.frames[i].location);
-  ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
+  ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
+  ContentTask.spawn(ctx.tab2Browser, null, function* () {
+    is(content.frames.length, 2, "Tab 2 should have 2 iframes");
+    for (var i = 0; i < content.frames.length; i++) {
+      info("step 3, frame " + i + " info: " + content.frames[i].location);
+      let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
+                                      .getInterface(Ci.nsIWebNavigation)
+                                      .QueryInterface(Ci.nsIDocShell);
 
-  // Navigate tab 2 to a different page
-  ctx.tab2Window.location = testPath + "bug343515_pg3.html";
+      ok(!docShell.isActive, `Tab2 iframe ${i} should be inactive`);
+    }
+  }).then(() => {
+    // Navigate tab 2 to a different page
+    ctx.tab2Browser.loadURI(testPath + "bug343515_pg3.html");
 
-  // bug343515_pg3.html consists of a page with two iframes, one of which
-  // contains another iframe, so there'll be a total of 4 load events
-  nShotsListener(ctx.tab2Browser, "load", step4, 4);
+    // bug343515_pg3.html consists of a page with two iframes, one of which
+    // contains another iframe, so there'll be a total of 4 load events
+    nShotsListener(ctx.tab2Browser, "load", step4, 4);
+  });
 }
 
 function step4() {
+  function checkTab2Active(expected) {
+    return ContentTask.spawn(ctx.tab2Browser, expected, function* (expected) {
+      function isActive(aWindow) {
+        var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIWebNavigation)
+                              .QueryInterface(Ci.nsIDocShell);
+        return docshell.isActive;
+      }
+
+      let active = expected ? "active" : "inactive";
+      is(content.frames.length, 2, "Tab 2 should have 2 iframes");
+      for (var i = 0; i < content.frames.length; i++)
+        info("step 4, frame " + i + " info: " + content.frames[i].location);
+      is(content.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
+      is(isActive(content.frames[0]), expected, `Tab2 iframe 0 should be ${active}`);
+      is(isActive(content.frames[0].frames[0]), expected,
+         `Tab2 iframe 0 subiframe 0 should be ${active}`);
+      is(isActive(content.frames[1]), expected, `Tab2 iframe 1 should be ${active}`);
+    });
+  }
+
   is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec,
      "Got expected tab 2 url in step 4");
 
   // Tab 0 should be inactive, Tab 1 should be active
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(isActive(ctx.tab1Window), "Tab 1 should be active");
+  ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+  ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
 
   // Tab2 and all descendants should be inactive
-  ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
-  is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
-  for (var i = 0; i < ctx.tab2Window.frames.length; i++)
-    info("step 4, frame " + i + " info: " + ctx.tab2Window.frames[i].location);
-  is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
-  ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
-
-  // Switch to Tab 2
-  gBrowser.selectedTab = ctx.tab2;
+  checkTab2Active(false).then(() => {
+    // Switch to Tab 2
+    return BrowserTestUtils.switchTab(gBrowser, ctx.tab2);
+  }).then(() => {
+    // Check everything
+    ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+    ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should be inactive");
+    ok(ctx.tab2Browser.docShellIsActive, "Tab 2 should be active");
 
-  // Check everything
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
-  ok(isActive(ctx.tab2Window), "Tab 2 should be active");
-  ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
-  ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active");
-  ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
-
-  // Go back
-  oneShotListener(ctx.tab2Browser, "pageshow", step5);
-  ctx.tab2Browser.goBack();
-
+    return checkTab2Active(true);
+  }).then(() => {
+    // Go back
+    waitForPageshow(ctx.tab2Browser, step5);
+    ctx.tab2Browser.goBack();
+  });
 }
 
 function step5() {
   // Check everything
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
-  ok(isActive(ctx.tab2Window), "Tab 2 should be active");
-  ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
-  ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
+  ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+  ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should be inactive");
+  ok(ctx.tab2Browser.docShellIsActive, "Tab 2 should be active");
+  ContentTask.spawn(ctx.tab2Browser, null, function* () {
+    for (var i = 0; i < content.frames.length; i++) {
+      let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
+                                      .getInterface(Ci.nsIWebNavigation)
+                                      .QueryInterface(Ci.nsIDocShell);
 
-  // Switch to tab 1
-  gBrowser.selectedTab = ctx.tab1;
+      ok(docShell.isActive, `Tab2 iframe ${i} should be active`);
+    }
+  }).then(() => {
+    // Switch to tab 1
+    return BrowserTestUtils.switchTab(gBrowser, ctx.tab1);
+  }).then(() => {
+    // Navigate to page 3
+    ctx.tab1Browser.loadURI(testPath + "bug343515_pg3.html");
 
-  // Navigate to page 3
-  ctx.tab1Window.location = testPath + "bug343515_pg3.html";
-
-  // bug343515_pg3.html consists of a page with two iframes, one of which
-  // contains another iframe, so there'll be a total of 4 load events
-  nShotsListener(ctx.tab1Browser, "load", step6, 4);
+    // bug343515_pg3.html consists of a page with two iframes, one of which
+    // contains another iframe, so there'll be a total of 4 load events
+    nShotsListener(ctx.tab1Browser, "load", step6, 4);
+  });
 }
 
 function step6() {
 
   // Check everything
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(isActive(ctx.tab1Window), "Tab 1 should be active");
-  ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
-  ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
-  ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
-  ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
+  ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+  ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+  ContentTask.spawn(ctx.tab1Browser, null, function* () {
+    function isActive(aWindow) {
+      var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIWebNavigation)
+                            .QueryInterface(Ci.nsIDocShell);
+      return docshell.isActive;
+    }
 
-  // Go forward on tab 2
-  oneShotListener(ctx.tab2Browser, "pageshow", step7);
-  var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIWebNavigation);
-  tab2docshell.goForward();
+    ok(isActive(content.frames[0]), "Tab1 iframe 0 should be active");
+    ok(isActive(content.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
+    ok(isActive(content.frames[1]), "Tab1 iframe 1 should be active");
+  }).then(() => {
+    ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
+    return ContentTask.spawn(ctx.tab2Browser, null, function* () {
+      for (var i = 0; i < content.frames.length; i++) {
+        let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
+                                        .getInterface(Ci.nsIWebNavigation)
+                                        .QueryInterface(Ci.nsIDocShell);
+
+        ok(!docShell.isActive, `Tab2 iframe ${i} should be inactive`);
+      }
+    });
+  }).then(() => {
+    // Go forward on tab 2
+    waitForPageshow(ctx.tab2Browser, step7);
+    ctx.tab2Browser.goForward();
+  });
 }
 
 function step7() {
+  function checkBrowser(browser, tabNum, active) {
+    return ContentTask.spawn(browser, { tabNum, active },
+                             function* ({ tabNum, active }) {
+             function isActive(aWindow) {
+               var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                     .getInterface(Ci.nsIWebNavigation)
+                                     .QueryInterface(Ci.nsIDocShell);
+               return docshell.isActive;
+             }
 
-  ctx.tab2Window = ctx.tab2Browser.contentWindow;
+             let activestr = active ? "active" : "inactive";
+             is(isActive(content.frames[0]), active,
+                `Tab${tabNum} iframe 0 should be ${activestr}`);
+             is(isActive(content.frames[0].frames[0]), active,
+                `Tab${tabNum} iframe 0 subiframe 0 should be ${activestr}`);
+             is(isActive(content.frames[1]), active,
+                `Tab${tabNum} iframe 1 should be ${activestr}`);
+           });
+  }
 
   // Check everything
-  ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
-  ok(isActive(ctx.tab1Window), "Tab 1 should be active");
-  ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
-  ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
-  ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
-  ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
-  ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
-
-  // That's probably enough
-  allDone();
+  ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
+  ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
+  checkBrowser(ctx.tab1Browser, 1, true).then(() => {
+    ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
+    return checkBrowser(ctx.tab2Browser, 2, false);
+  }).then(() => {
+    // That's probably enough
+    allDone();
+  });
 }
 
 function allDone() {
 
   // Close the tabs we made
   gBrowser.removeTab(ctx.tab1);
   gBrowser.removeTab(ctx.tab2);