Bug 1364364 - Part 5.2: Remove browser.sessionhistory.cache_subframes and fix test cases relying on it. r?smaug draft
authorSamael Wang <freesamael@gmail.com>
Tue, 05 Sep 2017 16:02:04 +0800
changeset 664561 dad6ed482e3d9cc6f1ebef0b16c4825220febe43
parent 664560 44447908b47f0a7f89381411f5567c57344a2d88
child 664562 c5cb09249cb071b9ca2024d42660311aa942f481
push id79723
push userbmo:sawang@mozilla.com
push dateThu, 14 Sep 2017 03:01:27 +0000
reviewerssmaug
bugs1364364
milestone57.0a1
Bug 1364364 - Part 5.2: Remove browser.sessionhistory.cache_subframes and fix test cases relying on it. r?smaug browser.sessionhistory.cache_subframes has been disabled for 12yrs. It's not actually maintained and it leaks content viewers. Using this unreliable feature in test cases is a bad practice, so remove the pref completely and fix existing test cases. MozReview-Commit-ID: 3tQLpsqmmaq
docshell/base/nsDocShell.cpp
docshell/test/chrome/bug608669.xul
docshell/test/chrome/test_bug608669.xul
dom/indexedDB/test/bfcache_page1.html
dom/indexedDB/test/bfcache_page2.html
dom/indexedDB/test/test_bfcache.html
dom/media/webspeech/synth/test/file_bfcache_page1.html
dom/media/webspeech/synth/test/file_bfcache_page2.html
dom/media/webspeech/synth/test/test_bfcache.html
dom/workers/test/WorkerDebugger_frozen_window1.html
dom/workers/test/WorkerDebugger_frozen_window2.html
dom/workers/test/blank.html
dom/workers/test/mochitest.ini
dom/workers/test/multi_sharedWorker_frame.html
dom/workers/test/test_WorkerDebugger_frozen.xul
dom/workers/test/test_multi_sharedWorker_lifetimes.html
dom/workers/test/test_onLine.html
dom/workers/test/test_suspend.html
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -8307,26 +8307,21 @@ nsDocShell::CanSavePresentation(uint32_t
   }
 
   // Avoid doing the work of saving the presentation state in the case where
   // the content viewer cache is disabled.
   if (nsSHistory::GetMaxTotalViewers() == 0) {
     return false;
   }
 
-  // Don't cache the content viewer if we're in a subframe and the subframe
-  // pref is disabled.
-  bool cacheFrames =
-    Preferences::GetBool("browser.sessionhistory.cache_subframes", false);
-  if (!cacheFrames) {
-    nsCOMPtr<nsIDocShellTreeItem> root;
-    GetSameTypeParent(getter_AddRefs(root));
-    if (root && root != this) {
-      return false;  // this is a subframe load
-    }
+  // Don't cache the content viewer if we're in a subframe.
+  nsCOMPtr<nsIDocShellTreeItem> root;
+  GetSameTypeParent(getter_AddRefs(root));
+  if (root && root != this) {
+    return false;  // this is a subframe load
   }
 
   // If the document does not want its presentation cached, then don't.
   nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc();
   return doc && doc->CanSavePresentation(aNewRequest);
 }
 
 void
--- a/docshell/test/chrome/bug608669.xul
+++ b/docshell/test/chrome/bug608669.xul
@@ -1,6 +1,14 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <window title="Mozilla Bug 608669 - Blank page"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+  onload="notifyOpener();">
   <description flex="1" value="This window is intentionally left blank"/>
+  <script type="application/javascript">
+  function notifyOpener() {
+    if (opener) {
+      opener.postMessage("load", "*");
+    }
+  }
+  </script>
 </window>
--- a/docshell/test/chrome/test_bug608669.xul
+++ b/docshell/test/chrome/test_bug608669.xul
@@ -13,53 +13,28 @@ https://bugzilla.mozilla.org/show_bug.cg
   <body xmlns="http://www.w3.org/1999/xhtml">
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=608669"
      target="_blank">Mozilla Bug 608669</a>
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
-var gOrigMaxTotalViewers = undefined;
-function setCachePref(enabled) {
-  var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
-                             .getService(Components.interfaces.nsIPrefBranch);
-  if (enabled) {
-    is(typeof gOrigMaxTotalViewers, "undefined", "don't double-enable bfcache");
-    prefBranch.setBoolPref("browser.sessionhistory.cache_subframes", true);
-    gOrigMaxTotalViewers = prefBranch.getIntPref("browser.sessionhistory.max_total_viewers");
-    prefBranch.setIntPref("browser.sessionhistory.max_total_viewers", 10);
-  }
-  else {
-    is(typeof gOrigMaxTotalViewers, "number", "don't double-disable bfcache");
-    prefBranch.setIntPref("browser.sessionhistory.max_total_viewers", gOrigMaxTotalViewers);
-    gOrigMaxTotalViewers = undefined;
-    try {
-      prefBranch.clearUserPref("browser.sessionhistory.cache_subframes");
-    } catch (e) { /* Pref didn't exist, meh */ }
-  }
-}
-
-
 /** Test for Bug 608669 **/
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(nextTest);
 
 gen = doTest();
 
 function nextTest() {
   gen.next();
 }
 
 function* doTest() {
-  var container = document.getElementById('container');
-
-  setCachePref(true);
-
   var notificationCount = 0;
   var observer = {
     observe: function(aSubject, aTopic, aData) {
       is(aTopic, "chrome-document-global-created",
          "correct topic");
       is(aData, "null",
          "correct data");
       notificationCount++;
@@ -68,49 +43,36 @@ function* doTest() {
 
   var os = Components.classes["@mozilla.org/observer-service;1"].
     getService(Components.interfaces.nsIObserverService);
   os.addObserver(observer, "chrome-document-global-created");
   os.addObserver(observer, "content-document-global-created");
 
   is(notificationCount, 0, "initial count");
 
-  // create a new iframe
-  var iframe = document.createElement("iframe");
-  container.appendChild(iframe);
-  iframe.contentWindow.x = "y";
-  is(notificationCount, 1, "after created iframe");
-  
-  // Try loading in an iframe
-  iframe.setAttribute("src", "bug608669.xul");
-  iframe.onload = nextTest;
+  // create a new window
+  var testWin = window.open("", "bug 608669", "chrome,width=600,height=600");
+  testWin.x = "y";
+  is(notificationCount, 1, "after created window");
+
+  // Try loading in the window
+  testWin.location = "bug608669.xul";
+  window.onmessage = nextTest;
   yield undefined;
   is(notificationCount, 1, "after first load");
-  is(iframe.contentWindow.x, "y", "reused window");
+  is(testWin.x, "y", "reused window");
 
-  // Try loading again in an iframe
-  iframe.setAttribute("src", "bug608669.xul?x");
-  iframe.onload = nextTest;
+  // Try loading again in the window
+  testWin.location = "bug608669.xul?x";
+  window.onmessage = nextTest;
   yield undefined;
   is(notificationCount, 2, "after second load");
-  is("x" in iframe.contentWindow, false, "didn't reuse window");
+  is("x" in testWin, false, "didn't reuse window");
 
-  // Open a new window using window.open
-  popup = window.open("bug608669.xul", "bug 608669",
-                      "chrome,width=600,height=600");
-  popup.onload = nextTest;
-  yield undefined;
-  is(notificationCount, 3, "after window.open load");
-  popup.close();
+  testWin.close();
 
-  setCachePref(false);
   os.removeObserver(observer, "chrome-document-global-created");
   os.removeObserver(observer, "content-document-global-created");
   SimpleTest.finish();
 }
 
-
-
   ]]></script>
-  <vbox id="container" flex="1">
-    <description>Below will an iframe be added</description>
-  </vbox>
 </window>
--- a/dom/indexedDB/test/bfcache_page1.html
+++ b/dom/indexedDB/test/bfcache_page1.html
@@ -1,27 +1,27 @@
 <!DOCTYPE html>
 <html>
 <head>
   <script>
-  var request = indexedDB.open(parent.location, 1);
+  var request = indexedDB.open(opener.location, 1);
   request.onupgradeneeded = function(e) {
     var db = e.target.result;
     // This should never be called
     db.onversionchange = function(e) {
       db.transaction(["mystore"]).objectStore("mystore").put({ hello: "fail" }, 42);
     }
     var trans = e.target.transaction;
     if (db.objectStoreNames.contains("mystore")) {
       db.deleteObjectStore("mystore");
     }
     var store = db.createObjectStore("mystore");
     store.add({ hello: "world" }, 42);
     trans.oncomplete = function() {
-      parent.postMessage("go", "http://mochi.test:8888");
+      opener.postMessage("go", "http://mochi.test:8888");
     }
   };
   </script>
 </head>
 <body>
   This is page one.
 </body>
 </html>
--- a/dom/indexedDB/test/bfcache_page2.html
+++ b/dom/indexedDB/test/bfcache_page2.html
@@ -1,28 +1,28 @@
 <!DOCTYPE html>
 <html>
 <head>
   <script>
   var res = {};
-  var request = indexedDB.open(parent.location, 2);
+  var request = indexedDB.open(opener.location, 2);
   request.onblocked = function() {
     res.blockedFired = true;
   }
   request.onupgradeneeded  = function(e) {
     var db = e.target.result;
     res.version = db.version;
     res.storeCount = db.objectStoreNames.length;
 
     var trans = request.transaction;
     trans.objectStore("mystore").get(42).onsuccess = function(e) {
       res.value = JSON.stringify(e.target.result);
     }
     trans.oncomplete = function() {
-      parent.postMessage(JSON.stringify(res), "http://mochi.test:8888");
+      opener.postMessage(JSON.stringify(res), "http://mochi.test:8888");
     }
   };
 
   </script>
 </head>
 <body>
   This is page two.
 </body>
--- a/dom/indexedDB/test/test_bfcache.html
+++ b/dom/indexedDB/test/test_bfcache.html
@@ -5,63 +5,37 @@
 <html>
 <head>
   <title>Indexed Database Property Test</title>
 
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="text/javascript">
     /* import-globals-from helpers.js */
-    var gOrigMaxTotalViewers = undefined;
-    function setCachePref(enabled) {
-      if (enabled) {
-        is(typeof gOrigMaxTotalViewers, "undefined",
-           "don't double-enable bfcache");
-        SpecialPowers.setBoolPref("browser.sessionhistory.cache_subframes",
-                                  true);
-        gOrigMaxTotalViewers =
-          SpecialPowers.getIntPref("browser.sessionhistory.max_total_viewers");
-        SpecialPowers.setIntPref("browser.sessionhistory.max_total_viewers",
-                                 10);
-      }
-      else {
-        is(typeof gOrigMaxTotalViewers, "number",
-           "don't double-disable bfcache");
-        SpecialPowers.setIntPref("browser.sessionhistory.max_total_viewers",
-                                 gOrigMaxTotalViewers);
-        gOrigMaxTotalViewers = undefined;
-        try {
-          SpecialPowers.clearUserPref("browser.sessionhistory.cache_subframes");
-        } catch (e) { /* Pref didn't exist, meh */ }
-      }
-    }
 
     function* testSteps()
     {
-      var iframe = $("iframe");
-      setCachePref(true);
       window.onmessage = grabEventAndContinueHandler;
 
-      iframe.src = "bfcache_iframe1.html";
+      let testWin = window.open("bfcache_page1.html", "testWin");
       var event = yield undefined;
       is(event.data, "go", "set up database successfully");
 
-      iframe.src = "bfcache_iframe2.html";
+      testWin.location = "bfcache_page2.html";
       let res = JSON.parse((yield).data);
       is(res.version, 2, "version was set correctly");
       is(res.storeCount, 1, "correct set of stores");
       ok(!("blockedFired" in res), "blocked shouldn't fire");
       is(res.value, JSON.stringify({ hello: "world" }),
          "correct value found in store");
 
-      setCachePref(false);
+      testWin.close();
       finishTest();
     }
   </script>
   <script type="text/javascript" src="helpers.js"></script>
 
 </head>
 
 <body onload="runTest();">
-  <iframe id="iframe"></iframe>
 </body>
 
 </html>
--- a/dom/media/webspeech/synth/test/file_bfcache_page1.html
+++ b/dom/media/webspeech/synth/test/file_bfcache_page1.html
@@ -2,17 +2,17 @@
 <html>
 <head>
   <meta charset="utf-8">
   <script type="application/javascript">
     addEventListener('pageshow', function onshow(evt) {
       var u = new SpeechSynthesisUtterance('hello');
       u.lang = 'it-IT-noend';
       u.addEventListener('start', function() {
-        location = "file_bfcache_frame2.html";
+        location = "file_bfcache_page2.html";
       });
       speechSynthesis.speak(u);
     });
   </script>
 </head>
 <body>
 </body>
 </html>
--- a/dom/media/webspeech/synth/test/file_bfcache_page2.html
+++ b/dom/media/webspeech/synth/test/file_bfcache_page2.html
@@ -1,14 +1,14 @@
 <html>
 <script>
 var frameUnloaded = function() {
   var u = new SpeechSynthesisUtterance('hi');
   u.addEventListener('end', function () {
-    parent.ok(true, 'Successfully spoke utterance from new frame.');
-    parent.onDone();
+    opener.ok(true, 'Successfully spoke utterance from new frame.');
+    opener.onDone();
   });
   speechSynthesis.speak(u);
 };
 </script>
 
 <body onpageshow="frameUnloaded()"></body></html>
 
--- a/dom/media/webspeech/synth/test/test_bfcache.html
+++ b/dom/media/webspeech/synth/test/test_bfcache.html
@@ -8,38 +8,39 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 1230533: Test speech is stopped from a window when unloaded</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230533">Mozilla Bug 1230533</a>
 <p id="display"></p>
-<iframe id="testFrame"></iframe>
 <div id="content" style="display: none">
-  
+
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 525444 **/
 
 SimpleTest.waitForExplicitFinish();
-
-var iframe;
+let testWin;
 
 function onDone() {
+  testWin.close();
   SimpleTest.finish();
 }
 
 SpecialPowers.pushPrefEnv({ set: [
   ['media.webspeech.synth.enabled', true],
-  ['media.webspeech.synth.force_global_queue', true],
-  ['browser.sessionhistory.cache_subframes', true],
-  ['browser.sessionhistory.max_total_viewers', 10]] },
+  ['media.webspeech.synth.force_global_queue', true]] },
   function() {
-    loadSpeechTest("file_bfcache_frame.html");
+    testWin = window.open("about:blank", "testWin");
+    testWin.onload = function(e) {
+      waitForVoices(testWin)
+        .then(() => testWin.location = "file_bfcache_page1.html")
+    };
   });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/WorkerDebugger_frozen_window1.html
+++ b/dom/workers/test/WorkerDebugger_frozen_window1.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <script>
       var worker = new Worker("WorkerDebugger_frozen_worker1.js");
       worker.onmessage = function () {
-        parent.postMessage("ready", "*");
+        opener.postMessage("ready", "*");
       };
     </script>
   </head>
   <body>
     This is page 1.
   </body>
 <html>
--- a/dom/workers/test/WorkerDebugger_frozen_window2.html
+++ b/dom/workers/test/WorkerDebugger_frozen_window2.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <script>
       var worker = new Worker("WorkerDebugger_frozen_worker2.js");
       worker.onmessage = function () {
-        parent.postMessage("ready", "*");
+        opener.postMessage("ready", "*");
       };
     </script>
   </head>
   <body>
     This is page 2.
   </body>
 <html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/blank.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>Blank</title>
+  </head>
+  <body onload="notifyOnload();">
+    <script type="application/javascript">
+    function notifyOnload() {
+      opener.postMessage({event: 'load'}, '*');
+    }
+    </script>
+  </body>
+</html>
+
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -1,12 +1,13 @@
 [DEFAULT]
 support-files =
   WorkerTest_badworker.js
   atob_worker.js
+  blank.html
   bug978260_worker.js
   bug1014466_data1.txt
   bug1014466_data2.txt
   bug1014466_worker.js
   bug1020226_worker.js
   bug1020226_frame.html
   bug998474_worker.js
   bug1063538_worker.js
--- a/dom/workers/test/multi_sharedWorker_frame.html
+++ b/dom/workers/test/multi_sharedWorker_frame.html
@@ -2,25 +2,41 @@
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <!DOCTYPE HTML>
 <html>
   <head>
     <title>Test for SharedWorker</title>
   </head>
-  <body>
+  <body onload="notifyOpenerLoadEvent();">
     <script type="text/javascript">
       "use strict";
 
+      function postMessageToParentOrOpener(message) {
+        if (parent != window) {
+          parent.postMessage(message, "*");
+        }
+        if (opener) {
+          opener.postMessage(message, "*");
+        }
+      }
+
+      // Used by test_multi_sharedWorker_lifetimes.html
+      function notifyOpenerLoadEvent() {
+        if (opener) {
+          opener.postMessage({event: "load"}, "*");
+        }
+      }
+
       function debug(message) {
         if (typeof(message) != "string") {
           throw new Error("debug() only accepts strings!");
         }
-        parent.postMessage(message, "*");
+        postMessageToParentOrOpener(message);
       }
 
       let worker;
 
       window.addEventListener("message", function(event) {
         if (!worker) {
           worker = new SharedWorker("multi_sharedWorker_sharedWorker.js",
                                     "FrameWorker");
@@ -30,22 +46,22 @@
 
             let data = {
               type: "error",
               message: event.message,
               filename: event.filename,
               lineno: event.lineno,
               isErrorEvent: event instanceof ErrorEvent
             };
-            parent.postMessage(data, "*");
+            postMessageToParentOrOpener(data);
           };
 
           worker.port.onmessage = function(event) {
             debug("Worker message: " + JSON.stringify(event.data));
-            parent.postMessage(event.data, "*");
+            postMessageToParentOrOpener(event.data);
           };
         }
 
         debug("Posting message: " + JSON.stringify(event.data));
         worker.port.postMessage(event.data);
       });
     </script>
   </body>
--- a/dom/workers/test/test_WorkerDebugger_frozen.xul
+++ b/dom/workers/test/test_WorkerDebugger_frozen.xul
@@ -11,80 +11,69 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
   <script type="application/javascript" src="dom_worker_helper.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
-    const CACHE_SUBFRAMES = "browser.sessionhistory.cache_subframes";
-    const MAX_TOTAL_VIEWERS = "browser.sessionhistory.max_total_viewers";
-
-    const IFRAME1_URL = "WorkerDebugger_frozen_iframe1.html";
-    const IFRAME2_URL = "WorkerDebugger_frozen_iframe2.html";
+    const WINDOW1_URL = "WorkerDebugger_frozen_window1.html";
+    const WINDOW2_URL = "WorkerDebugger_frozen_window2.html";
 
     const WORKER1_URL = "WorkerDebugger_frozen_worker1.js";
     const WORKER2_URL = "WorkerDebugger_frozen_worker2.js";
 
     function test() {
       (async function() {
         SimpleTest.waitForExplicitFinish();
 
-        var oldMaxTotalViewers = SpecialPowers.getIntPref(MAX_TOTAL_VIEWERS);
-
-        SpecialPowers.setBoolPref(CACHE_SUBFRAMES, true);
-        SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, 10);
-
-        let iframe = $("iframe");
+        SpecialPowers.pushPrefEnv({set:
+          [["browser.sessionhistory.max_total_viewers", 10]]});
 
         let promise = waitForMultiple([
           waitForRegister(WORKER1_URL),
           waitForWindowMessage(window, "ready"),
         ]);
-        iframe.src = IFRAME1_URL;
+        let testWin = window.open(WINDOW1_URL, "testWin");;
         let [dbg1] = await promise;
         is(dbg1.isClosed, false,
            "debugger for worker on page 1 should not be closed");
 
         promise = waitForMultiple([
           waitForUnregister(WORKER1_URL),
           waitForDebuggerClose(dbg1),
           waitForRegister(WORKER2_URL),
           waitForWindowMessage(window, "ready"),
         ]);
-        iframe.src = IFRAME2_URL;
+        testWin.location = WINDOW2_URL;
         let [,, dbg2] = await promise;
         is(dbg1.isClosed, true,
            "debugger for worker on page 1 should be closed");
         is(dbg2.isClosed, false,
            "debugger for worker on page 2 should not be closed");
 
         promise = Promise.all([
           waitForUnregister(WORKER2_URL),
           waitForDebuggerClose(dbg2),
           waitForRegister(WORKER1_URL)
         ]);
-        iframe.contentWindow.history.back();
+        testWin.history.back();
         [,, dbg1] = await promise;
         is(dbg1.isClosed, false,
            "debugger for worker on page 1 should not be closed");
         is(dbg2.isClosed, true,
            "debugger for worker on page 2 should be closed");
 
-        SpecialPowers.clearUserPref(CACHE_SUBFRAMES);
-        SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, oldMaxTotalViewers);
-
         SimpleTest.finish();
       })();
     }
 
   ]]>
   </script>
 
   <body xmlns="http://www.w3.org/1999/xhtml">
     <p id="display"></p>
     <div id="content" style="display:none;"></div>
     <pre id="test"></pre>
-    <iframe id="iframe"></iframe>
   </body>
   <label id="test-result"/>
 </window>
--- a/dom/workers/test/test_multi_sharedWorker_lifetimes.html
+++ b/dom/workers/test/test_multi_sharedWorker_lifetimes.html
@@ -7,149 +7,134 @@
   <head>
     <title>Test for SharedWorker</title>
     <script src="/tests/SimpleTest/SimpleTest.js"></script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
       <script class="testbody" type="text/javascript">
         "use strict";
 
         const scrollbarPref = "layout.testing.overlay-scrollbars.always-visible";
-        const bfCacheEnabledPref = "browser.sessionhistory.cache_subframes";
-        const bfCacheDepthPref = "browser.sessionhistory.max_total_viewers";
-        const bfCacheDepth = 10;
+        const viewersPref = "browser.sessionhistory.max_total_viewers";
 
-        const frameRelativeURL = "multi_sharedWorker_frame.html";
+        const windowRelativeURL = "multi_sharedWorker_frame.html";
         const storedData = "0123456789abcdefghijklmnopqrstuvwxyz";
 
         let testGenerator = (function*() {
           SimpleTest.waitForExplicitFinish();
 
-	  // Force scrollbar to always be shown.  The scrollbar setting is
-	  // necessary to avoid the fade-in/fade-out from evicting our document
-	  // from the BF cache below.  If bug 1049277 is fixed, then we can
-	  // stop setting the scrollbar pref here.
-          SpecialPowers.pushPrefEnv({ set: [[scrollbarPref, true]] },
+          // Force scrollbar to always be shown.  The scrollbar setting is
+          // necessary to avoid the fade-in/fade-out from evicting our document
+          // from the BF cache below.  If bug 1049277 is fixed, then we can
+          // stop setting the scrollbar pref here.
+          SpecialPowers.pushPrefEnv({ set: [[scrollbarPref, true],
+                                            [viewersPref, 10]] },
                                     sendToGenerator);
           yield undefined;
 
           window.addEventListener("message", function(event) {
             if (typeof(event.data) == "string") {
               info(event.data);
             } else {
               sendToGenerator(event);
             }
           });
 
-          let frame = document.getElementById("frame");
-          frame.src = frameRelativeURL;
-          frame.onload = sendToGenerator;
-
+          let testWin = window.open(windowRelativeURL, "testWin");
           yield undefined;
 
-          frame = frame.contentWindow;
-          frame.postMessage({ command: "retrieve" }, "*");
+          testWin.postMessage({ command: "retrieve" }, "*");
 
           let event = yield undefined;
           ok(event instanceof MessageEvent, "Got a MessageEvent");
-          is(event.source, frame, "Correct window got the event");
+          is(event.source, testWin, "Correct window got the event");
           is(event.data.type, "result", "Got a result message");
           is(event.data.data, undefined, "No data stored yet");
 
-          frame.postMessage({ command: "store", data: storedData }, "*");
-          frame.postMessage({ command: "retrieve" }, "*");
+          testWin.postMessage({ command: "store", data: storedData }, "*");
+          testWin.postMessage({ command: "retrieve" }, "*");
 
           event = yield undefined;
           ok(event instanceof MessageEvent, "Got a MessageEvent");
-          is(event.source, frame, "Correct window got the event");
+          is(event.source, testWin, "Correct window got the event");
           is(event.data.type, "result", "Got a result message");
           is(event.data.data, storedData, "Got stored data");
 
           // Navigate when the bfcache is disabled.
-          info("Navigating to about:blank");
-          frame = document.getElementById("frame");
-          frame.onload = sendToGenerator;
-          frame.src = "about:blank";
-          frame.contentWindow.document.body.offsetTop;
+          info("Navigating to a blank page");
+          testWin.onunload = function(){};;
+          testWin.location = "blank.html";
+          testWin.document.body.offsetTop;
 
           yield undefined;
 
-          info("Navigating to " + frameRelativeURL);
-          frame.src = frameRelativeURL;
-          frame.contentWindow.document.body.offsetTop;
+          info("Navigating to " + windowRelativeURL);
+          testWin.onunload = function(){};
+          testWin.location = windowRelativeURL;
+          testWin.document.body.offsetTop;
 
           yield undefined;
 
-          frame = frame.contentWindow;
-          frame.postMessage({ command: "retrieve" }, "*");
+          testWin.postMessage({ command: "retrieve" }, "*");
 
           event = yield undefined;
           ok(event instanceof MessageEvent, "Got a MessageEvent");
-          is(event.source, frame, "Correct window got the event");
+          is(event.source, testWin, "Correct window got the event");
           is(event.data.type, "result", "Got a result message");
           is(event.data.data, undefined, "No data stored");
 
-          frame.postMessage({ command: "store", data: storedData }, "*");
-          frame.postMessage({ command: "retrieve" }, "*");
+          testWin.postMessage({ command: "store", data: storedData }, "*");
+          testWin.postMessage({ command: "retrieve" }, "*");
 
           event = yield undefined;
           ok(event instanceof MessageEvent, "Got a MessageEvent");
-          is(event.source, frame, "Correct window got the event");
+          is(event.source, testWin, "Correct window got the event");
           is(event.data.type, "result", "Got a result message");
           is(event.data.data, storedData, "Got stored data");
 
-          info("Enabling '" + bfCacheEnabledPref + "' pref");
-          SpecialPowers.pushPrefEnv({ set: [[bfCacheEnabledPref, true],
-                                            [bfCacheDepthPref, bfCacheDepth]] },
-                                    sendToGenerator);
-          yield undefined;
-
           // Navigate when the bfcache is enabled.
-          frame = document.getElementById("frame");
-          frame.onload = sendToGenerator;
-
-          info("Navigating to about:blank");
-          frame.src = "about:blank";
-          frame.contentWindow.document.body.offsetTop;
+          info("Navigating to a blank page");
+          testWin.location = "blank.html";
+          testWin.document.body.offsetTop;
 
           yield undefined;
 
           for (let i = 0; i < 3; i++) {
             info("Running GC");
             SpecialPowers.exactGC(sendToGenerator);
             yield undefined;
 
+            // It seems using SpecialPowers.executeSoon() would make the
+            // entryGlobal being the TabChildGlobal (and that would make the
+            // baseURI in the location assignment below being incorrect);
+            // setTimeout on the otherhand ensures the entryGlobal is this
+            // window.
             info("Waiting the event queue to clear");
-            SpecialPowers.executeSoon(sendToGenerator);
+            setTimeout(sendToGenerator, 0);
             yield undefined;
           }
 
-          info("Navigating to " + frameRelativeURL);
-          frame.src = frameRelativeURL;
-          frame.contentWindow.document.body.offsetTop;
+          info("Navigating to " + windowRelativeURL);
+          testWin.location = windowRelativeURL;
+          testWin.document.body.offsetTop;
 
           yield undefined;
 
-          frame = frame.contentWindow;
-          frame.postMessage({ command: "retrieve" }, "*");
+          testWin.postMessage({ command: "retrieve" }, "*");
 
           event = yield undefined;
           ok(event instanceof MessageEvent, "Got a MessageEvent");
-          is(event.source, frame, "Correct window got the event");
+          is(event.source, testWin, "Correct window got the event");
           is(event.data.type, "result", "Got a result message");
           is(event.data.data, storedData, "Still have data stored");
 
-          info("Resetting '" + bfCacheEnabledPref + "' pref");
-          SpecialPowers.popPrefEnv(sendToGenerator);
-          yield undefined;
-
           window.removeEventListener("message", sendToGenerator);
 
+          testWin.close();
           SimpleTest.finish();
         })();
 
         let sendToGenerator = testGenerator.next.bind(testGenerator);
 
       </script>
   </head>
   <body onload="testGenerator.next();">
-    <iframe id="frame"></iframe>
   </body>
 </html>
--- a/dom/workers/test/test_onLine.html
+++ b/dom/workers/test/test_onLine.html
@@ -21,17 +21,26 @@ http://creativecommons.org/licenses/publ
 
 <script class="testbody" type="text/javascript">
 
 addLoadEvent(function() {
   var w = new Worker("onLine_worker.js");
 
   w.onmessage = function(e) {
     if (e.data.type === 'ready') {
-      doTest();
+      // XXX Important trick here.
+      //
+      // Setting iosvc.offline would trigger a sync notifyObservers call, and if
+      // there exists a preloaded about:newtab (see tabbrowser._handleNewTab),
+      // that tab will be notified.
+      //
+      // This implies a sync call across different tabGroups, and will hit the
+      // assertion in SchedulerGroup::ValidateAccess(). So use executeSoon to
+      // re-dispatch an unlabeled runnable to the event queue.
+      SpecialPowers.executeSoon(doTest);
     } else if (e.data.type === 'ok') {
       ok(e.data.test, e.data.message);
     } else if (e.data.type === 'finished') {
       SimpleTest.finish();
     }
   }
 
   function doTest() {
--- a/dom/workers/test/test_suspend.html
+++ b/dom/workers/test/test_suspend.html
@@ -9,130 +9,126 @@
   <title>Test for DOM Worker Threads</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none"></div>
 <pre id="test">
-<iframe id="workerFrame" src="suspend_iframe.html" onload="subframeLoaded();">
-</iframe>
 <script class="testbody" type="text/javascript">
 
   SimpleTest.waitForExplicitFinish();
 
-  var iframe;
+  const BLANK_URI = location.href.replace("test_suspend.html", "blank.html");
+
   var lastCount;
 
   var suspended = false;
   var resumed = false;
   var finished = false;
 
   var interval;
   var oldMessageCount;
   var waitCount = 0;
 
+  var testWin = window.open("suspend_window.html", "testWin");
+  testWin.onload = testWinLoaded;
+
+  window.addEventListener("message", msg => {
+    if (suspended) {
+      badOnloadCallback();
+    } else {
+      suspendCallback();
+    }
+  })
+
   function finishTest() {
     if (finished) {
       return;
     }
     finished = true;
-    SpecialPowers.flushPrefEnv(function () {
-      iframe.terminateWorker();
-      SimpleTest.finish();
-    });
+    testWin.terminateWorker();
+    testWin.close();
+    SimpleTest.finish();
   }
 
   function waitInterval() {
     if (finished) {
       return;
     }
-    is(String(iframe.location), "about:blank", "Wrong url!");
+    is(testWin.location.href, BLANK_URI, "Wrong url!");
     is(suspended, true, "Not suspended?");
     is(resumed, false, "Already resumed?!");
     is(lastCount, oldMessageCount, "Received a message while suspended!");
     if (++waitCount == 5) {
       clearInterval(interval);
       resumed = true;
-      iframe.history.back();
+      testWin.history.back();
     }
   }
 
   function badOnloadCallback() {
     if (finished) {
       return;
     }
-    ok(false, "We don't want suspend_iframe.html to fire a new load event, we want it to come out of the bfcache!");
+    ok(false, "We don't want suspend_window.html to fire a new load event, we want it to come out of the bfcache!");
     finishTest();
   }
 
   function suspendCallback() {
     if (finished) {
       return;
     }
-    is(String(iframe.location), "about:blank", "Wrong url!");
+    is(testWin.location.href, BLANK_URI, "Wrong url!");
     is(suspended, false, "Already suspended?");
     is(resumed, false, "Already resumed?");
-    SpecialPowers.popPrefEnv(function () {
-      suspended = true;
-      var iframeElement = document.getElementById("workerFrame");
-      iframeElement.onload = badOnloadCallback;
-      oldMessageCount = lastCount;
-      interval = setInterval(waitInterval, 1000);
-    });
+    suspended = true;
+    oldMessageCount = lastCount;
+    interval = setInterval(waitInterval, 1000);
   }
 
   function messageCallback(data) {
     if (finished) {
       return;
     }
 
     if (!suspended) {
       ok(lastCount === undefined || lastCount == data - 1,
          "Got good data, lastCount = " + lastCount + ", data = " + data);
       lastCount = data;
       if (lastCount == 25) {
-        SpecialPowers.pushPrefEnv({"set": [["browser.sessionhistory.cache_subframes", true]]}, function () {
-          iframe.location = "about:blank";
-          // We want suspend_iframe.html to go into bfcache, so we need to flush
-          // out all pending notifications. Otherwise, if they're flushed too
-          // late, they could kick us out of the bfcache again.
-          iframe.document.body.offsetTop;
-        });
+        testWin.location = "blank.html";
+        // We want suspend_window.html to go into bfcache, so we need to flush
+        // out all pending notifications. Otherwise, if they're flushed too
+        // late, they could kick us out of the bfcache again.
+        testWin.document.body.offsetTop;
       }
       return;
     }
 
-    var newLocation =
-      window.location.toString().replace("test_suspend.html",
-                                         "suspend_iframe.html");
-    is(newLocation.indexOf(iframe.location.toString()), 0, "Wrong url!");
+    var newLocation = location.href.replace("test_suspend.html",
+                                            "suspend_window.html");
+    is(testWin.location.href, newLocation, "Wrong url!");
     is(resumed, true, "Got message before resumed!");
     is(lastCount, data - 1, "Missed a message, suspend failed!");
     finishTest();
   }
 
   function errorCallback(data) {
     if (finished) {
       return;
     }
-    ok(false, "Iframe had an error: '" + data + "'");
+    ok(false, "testWin had an error: '" + data + "'");
     finishTest();
   }
 
-  function subframeLoaded() {
+  function testWinLoaded() {
     if (finished) {
       return;
     }
-    var iframeElement = document.getElementById("workerFrame");
-    iframeElement.onload = suspendCallback;
-
-    iframe = iframeElement.contentWindow;
-    ok(iframe, "No iframe?!");
-
-    iframe.startWorker(messageCallback, errorCallback);
+    testWin.startWorker(messageCallback, errorCallback);
   }
 
 </script>
 </pre>
 </body>
 </html>