Bug 1347482 - Change various DOM tests to run the navigator checks in sub-iframes. r=mystor
authorMark Banner <standard8@mozilla.com>
Tue, 04 Apr 2017 21:53:27 +0100
changeset 399590 3c68d659c2b715f811708f043a1e7169d77be2ba
parent 399589 c8097447026154023fff870735a13b3a99099e7d
child 399659 950612071c4e5cbd61af6c0f66ed0bc40c35e39c
child 399663 9a38eee8322fc4782bf042b1bde37ccb6af21c26
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1347482
milestone55.0a1
first release with
nightly linux32
3c68d659c2b7 / 55.0a1 / 20170406100208 / files
nightly linux64
3c68d659c2b7 / 55.0a1 / 20170406100208 / files
nightly mac
3c68d659c2b7 / 55.0a1 / 20170406030206 / files
nightly win32
3c68d659c2b7 / 55.0a1 / 20170406030206 / files
nightly win64
3c68d659c2b7 / 55.0a1 / 20170406030206 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1347482 - Change various DOM tests to run the navigator checks in sub-iframes. r=mystor We have to run the navigator checks in sub-iframes as we need to set preferences which affect navigator's API which may or may not be already initialised with the current settings. The sub-iframes will have a navigator object set up with the expected preferences for the test. The iframes all call into the parent to publish the test results, this is because the SimpleTest infrastructure doesn't cope with results being published from sub-iframes. MozReview-Commit-ID: GFVQHMVkbMP
dom/power/test/mochitest.ini
dom/power/test/test_bug957899.html
dom/power/test/test_bug957899_iframe.html
dom/presentation/tests/mochitest/mochitest.ini
dom/presentation/tests/mochitest/test_presentation_availability.html
dom/presentation/tests/mochitest/test_presentation_availability_iframe.html
dom/tests/mochitest/gamepad/mochitest.ini
dom/tests/mochitest/gamepad/mock_gamepad.js
dom/tests/mochitest/gamepad/test_check_timestamp.html
dom/tests/mochitest/gamepad/test_check_timestamp_iframe.html
dom/tests/mochitest/gamepad/test_gamepad.html
dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
dom/tests/mochitest/gamepad/test_gamepad_connect_events_iframe.html
dom/tests/mochitest/gamepad/test_gamepad_extensions.html
dom/tests/mochitest/gamepad/test_gamepad_extensions_iframe.html
dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync.html
dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync_iframe.html
dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
dom/tests/mochitest/gamepad/test_gamepad_hidden_frame_iframe.html
dom/tests/mochitest/gamepad/test_gamepad_iframe.html
dom/tests/mochitest/gamepad/test_navigator_gamepads.html
dom/tests/mochitest/gamepad/test_navigator_gamepads_iframe.html
dom/tests/mochitest/geolocation/mochitest.ini
dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off.html
dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off_iframe.html
dom/workers/test/mochitest.ini
dom/workers/test/test_navigator.js
dom/workers/test/test_navigator_iframe.html
dom/workers/test/test_navigator_iframe.js
--- a/dom/power/test/mochitest.ini
+++ b/dom/power/test/mochitest.ini
@@ -1,3 +1,4 @@
 [test_bug957893.html]
 [test_bug957899.html]
+support-files = test_bug957899_iframe.html
 [test_wakelock_not_exposed.html]
--- a/dom/power/test/test_bug957899.html
+++ b/dom/power/test/test_bug957899.html
@@ -3,18 +3,19 @@
 <head>
   <title>Test bug 957899 - Crash in WakeLock</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
  <script type="application/javascript">
   SimpleTest.waitForExplicitFinish();
-  function test() {
-    var wl = navigator.requestWakeLock('a');
-    ok(wl, "WakeLock created!");
-    ok(!(wl instanceof XPathEvaluator), "Crashing?");
-    SimpleTest.finish();
-  }
-  SpecialPowers.pushPrefEnv({"set": [["dom.wakelock.enabled", true]]}, test);
+  // This test loads in an iframe, to ensure that the navigator instance is
+  // loaded with the correct value of the preference.
+  SpecialPowers.pushPrefEnv({"set": [["dom.wakelock.enabled", true]]}, () => {
+    let iframe = document.createElement("iframe");
+    iframe.id = "f1";
+    iframe.src = "test_bug957899_iframe.html";
+    document.body.appendChild(iframe);
+  });
  </script>
 </body>
 </html>
copy from dom/power/test/test_bug957899.html
copy to dom/power/test/test_bug957899_iframe.html
--- a/dom/power/test/test_bug957899.html
+++ b/dom/power/test/test_bug957899_iframe.html
@@ -2,19 +2,15 @@
 <html>
 <head>
   <title>Test bug 957899 - Crash in WakeLock</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
  <script type="application/javascript">
-  SimpleTest.waitForExplicitFinish();
-  function test() {
-    var wl = navigator.requestWakeLock('a');
-    ok(wl, "WakeLock created!");
-    ok(!(wl instanceof XPathEvaluator), "Crashing?");
-    SimpleTest.finish();
-  }
-  SpecialPowers.pushPrefEnv({"set": [["dom.wakelock.enabled", true]]}, test);
+  var wl = navigator.requestWakeLock('a');
+  window.parent.ok(wl, "WakeLock created!");
+  window.parent.ok(!(wl instanceof XPathEvaluator), "Crashing?");
+  window.parent.SimpleTest.finish();
  </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/mochitest.ini
+++ b/dom/presentation/tests/mochitest/mochitest.ini
@@ -71,8 +71,9 @@ skip-if = (e10s || toolkit == 'android')
 [test_presentation_sender_on_terminate_request.html]
 skip-if = toolkit == 'android'
 [test_presentation_sandboxed_presentation.html]
 skip-if = true # bug 1315867
 [test_presentation_reconnect.html]
 [test_presentation_mixed_security_contexts.html]
 skip-if = toolkit == 'android' # bug 1304934
 [test_presentation_availability.html]
+support-files = test_presentation_availability_iframe.html
--- a/dom/presentation/tests/mochitest/test_presentation_availability.html
+++ b/dom/presentation/tests/mochitest/test_presentation_availability.html
@@ -6,231 +6,30 @@
   <meta charset="utf-8">
   <title>Test for PresentationAvailability</title>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1228508">Test PresentationAvailability</a>
 <script type="application/javascript">
-
-"use strict";
-
-var testDevice = {
-  id: 'id',
-  name: 'name',
-  type: 'type',
-};
-
-var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationDeviceInfoChromeScript.js'));
-var request;
-var availability;
-
-function testSetup() {
-  return new Promise(function(aResolve, aReject) {
-    gScript.addMessageListener('setup-complete', function() {
-      aResolve();
-    });
-    gScript.sendAsyncMessage('setup');
-  });
-}
-
-function testInitialUnavailable() {
-  request = new PresentationRequest("https://example.com");
-
-  return request.getAvailability().then(function(aAvailability) {
-    is(aAvailability.value, false, "Should have no available device after setup");
-    aAvailability.onchange = function() {
-      aAvailability.onchange = null;
-      ok(aAvailability.value, "Device should be available.");
-    }
-    availability = aAvailability;
-    gScript.sendAsyncMessage('trigger-device-add', testDevice);
-  }).catch(function(aError) {
-    ok(false, "Error occurred when getting availability: " + aError);
-    teardown();
-  });
-}
-
-function testInitialAvailable() {
-  let anotherRequest = new PresentationRequest("https://example.net");
-  return anotherRequest.getAvailability().then(function(aAvailability) {
-    is(aAvailability.value, true, "Should have available device initially");
-    isnot(aAvailability, availability, "Should get different availability object for different request URL");
-  }).catch(function(aError) {
-    ok(false, "Error occurred when getting availability: " + aError);
-    teardown();
-  });
-}
-
-function testSameObject() {
-  let sameUrlRequest = new PresentationRequest("https://example.com");
-  return sameUrlRequest.getAvailability().then(function(aAvailability) {
-    is(aAvailability, availability, "Should get same availability object for same request URL");
-  }).catch(function(aError) {
-    ok(false, "Error occurred when getting availability: " + aError);
-    teardown();
-  });
-}
-
-function testOnChangeEvent() {
-  return new Promise(function(aResolve, aReject) {
-    availability.onchange = function() {
-      availability.onchange = null;
-      is(availability.value, false, "Should have no available device after device removed");
-      aResolve();
-    }
-    gScript.sendAsyncMessage('trigger-device-remove');
-  });
-}
-
-function testConsecutiveGetAvailability() {
-  let request = new PresentationRequest("https://example.org");
-  let firstAvailabilityResolved = false;
-  return Promise.all([
-    request.getAvailability().then(function() {
-      firstAvailabilityResolved = true;
-    }),
-    request.getAvailability().then(function() {
-      ok(firstAvailabilityResolved, "getAvailability() should be resolved in sequence");
-    })
-  ]).catch(function(aError) {
-    ok(false, "Error occurred when getting availability: " + aError);
-    teardown();
-  });
-}
-
-function testUnsupportedDeviceAvailability() {
-  return Promise.race([
-    new Promise(function(aResolve, aReject) {
-      let request = new PresentationRequest("https://test.com");
-      request.getAvailability().then(function(aAvailability) {
-        availability = aAvailability;
-        aAvailability.onchange = function() {
-          availability.onchange = null;
-          ok(false, "Should not get onchange event.");
-          teardown();
-        }
-      });
-      gScript.sendAsyncMessage('trigger-add-unsupport-url-device');
-    }),
-    new Promise(function(aResolve, aReject) {
-      setTimeout(function() {
-        ok(true, "Should not get onchange event.");
-        availability.onchange = null;
-        gScript.sendAsyncMessage('trigger-remove-unsupported-device');
-        aResolve();
-      }, 3000);
-    }),
-  ]);
-}
-
-function testMultipleAvailabilityURLs() {
-  let request1 = new PresentationRequest(["https://example.com",
-                                         "https://example1.com"]);
-  let request2 = new PresentationRequest(["https://example1.com",
-                                         "https://example2.com"]);
-  return Promise.all([
-    request1.getAvailability().then(function(aAvailability) {
-      return new Promise(function(aResolve) {
-        aAvailability.onchange = function() {
-          aAvailability.onchange = null;
-          ok(true, "Should get onchange event.");
-          aResolve();
-        };
-      });
-    }),
-    request2.getAvailability().then(function(aAvailability) {
-      return new Promise(function(aResolve) {
-        aAvailability.onchange = function() {
-          aAvailability.onchange = null;
-          ok(true, "Should get onchange event.");
-          aResolve();
-        };
-      });
-    }),
-    new Promise(function(aResolve) {
-      gScript.sendAsyncMessage('trigger-add-multiple-devices');
-      aResolve();
-    }),
-  ]).then(new Promise(function(aResolve) {
-    gScript.sendAsyncMessage('trigger-remove-multiple-devices');
-    aResolve();
-  }));
-}
-
-function testPartialSupportedDeviceAvailability() {
-  let request1 = new PresentationRequest(["https://supportedUrl.com"]);
-  let request2 = new PresentationRequest(["http://notSupportedUrl.com"]);
-
-  return Promise.all([
-    request1.getAvailability().then(function(aAvailability) {
-      return new Promise(function(aResolve) {
-        aAvailability.onchange = function() {
-          aAvailability.onchange = null;
-          ok(true, "Should get onchange event.");
-          aResolve();
-        };
-      });
-    }),
-    Promise.race([
-      request2.getAvailability().then(function(aAvailability) {
-        return new Promise(function(aResolve) {
-          aAvailability.onchange = function() {
-            aAvailability.onchange = null;
-            ok(false, "Should get onchange event.");
-            aResolve();
-          };
-        });
-      }),
-      new Promise(function(aResolve) {
-        setTimeout(function() {
-          ok(true, "Should not get onchange event.");
-          availability.onchange = null;
-          aResolve();
-        }, 3000);
-      }),
-    ]),
-    new Promise(function(aResolve) {
-      gScript.sendAsyncMessage('trigger-add-https-devices');
-      aResolve();
-    }),
-  ]).then(new Promise(function(aResolve) {
-    gScript.sendAsyncMessage('trigger-remove-https-devices');
-    aResolve();
-  }));
-}
-
-function teardown() {
-  request = null;
-  availability = null;
-  gScript.sendAsyncMessage('teardown');
-  gScript.destroy();
-  SimpleTest.finish();
-}
-
-function runTests() {
-  ok(navigator.presentation, "navigator.presentation should be available.");
-  testSetup().then(testInitialUnavailable)
-             .then(testInitialAvailable)
-             .then(testSameObject)
-             .then(testOnChangeEvent)
-             .then(testConsecutiveGetAvailability)
-             .then(testMultipleAvailabilityURLs)
-             .then(testUnsupportedDeviceAvailability)
-             .then(testPartialSupportedDeviceAvailability)
-             .then(teardown);
-}
-
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout('Test for guarantee not firing async event');
 SpecialPowers.pushPermissions([
   {type: "presentation-device-manage", allow: false, context: document},
 ], function() {
-  SpecialPowers.pushPrefEnv({ "set": [["dom.presentation.enabled", true],
-                                      ["dom.presentation.controller.enabled", true],
-                                      ["dom.presentation.session_transport.data_channel.enable", false]]},
-                            runTests);
+  SpecialPowers.pushPrefEnv({
+    "set": [["dom.presentation.enabled", true],
+            ["dom.presentation.controller.enabled", true],
+            ["dom.presentation.session_transport.data_channel.enable", false]]},
+    () => {
+      let iframe = document.createElement("iframe");
+      iframe.src = "test_presentation_availability_iframe.html";
+      document.body.appendChild(iframe);
+    }
+  );
 });
 
 </script>
 </body>
 </html>
copy from dom/presentation/tests/mochitest/test_presentation_availability.html
copy to dom/presentation/tests/mochitest/test_presentation_availability_iframe.html
--- a/dom/presentation/tests/mochitest/test_presentation_availability.html
+++ b/dom/presentation/tests/mochitest/test_presentation_availability_iframe.html
@@ -1,21 +1,25 @@
 <!DOCTYPE HTML>
 <html>
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <head>
   <meta charset="utf-8">
   <title>Test for PresentationAvailability</title>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1228508">Test PresentationAvailability</a>
 <script type="application/javascript">
+let ok = window.parent.ok;
+let is = window.parent.is;
+let isnot = window.parent.isnot;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
 
 "use strict";
 
 var testDevice = {
   id: 'id',
   name: 'name',
   type: 'type',
 };
@@ -202,35 +206,22 @@ function testPartialSupportedDeviceAvail
 function teardown() {
   request = null;
   availability = null;
   gScript.sendAsyncMessage('teardown');
   gScript.destroy();
   SimpleTest.finish();
 }
 
-function runTests() {
-  ok(navigator.presentation, "navigator.presentation should be available.");
-  testSetup().then(testInitialUnavailable)
-             .then(testInitialAvailable)
-             .then(testSameObject)
-             .then(testOnChangeEvent)
-             .then(testConsecutiveGetAvailability)
-             .then(testMultipleAvailabilityURLs)
-             .then(testUnsupportedDeviceAvailability)
-             .then(testPartialSupportedDeviceAvailability)
-             .then(teardown);
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout('Test for guarantee not firing async event');
-SpecialPowers.pushPermissions([
-  {type: "presentation-device-manage", allow: false, context: document},
-], function() {
-  SpecialPowers.pushPrefEnv({ "set": [["dom.presentation.enabled", true],
-                                      ["dom.presentation.controller.enabled", true],
-                                      ["dom.presentation.session_transport.data_channel.enable", false]]},
-                            runTests);
-});
+ok(navigator.presentation, "navigator.presentation should be available.");
+testSetup().then(testInitialUnavailable)
+           .then(testInitialAvailable)
+           .then(testSameObject)
+           .then(testOnChangeEvent)
+           .then(testConsecutiveGetAvailability)
+           .then(testMultipleAvailabilityURLs)
+           .then(testUnsupportedDeviceAvailability)
+           .then(testPartialSupportedDeviceAvailability)
+           .then(teardown);
 
 </script>
 </body>
 </html>
--- a/dom/tests/mochitest/gamepad/mochitest.ini
+++ b/dom/tests/mochitest/gamepad/mochitest.ini
@@ -1,13 +1,20 @@
 [DEFAULT]
 support-files =
   gamepad_frame.html
   gamepad_frame_state.html
   mock_gamepad.js
 
 [test_check_timestamp.html]
+support-files = test_check_timestamp_iframe.html
 [test_gamepad.html]
+support-files = test_gamepad_iframe.html
 [test_gamepad_connect_events.html]
+support-files = test_gamepad_connect_events_iframe.html
 [test_gamepad_extensions.html]
+support-files = test_gamepad_extensions_iframe.html
 [test_gamepad_frame_state_sync.html]
+support-files = test_gamepad_frame_state_sync_iframe.html
 [test_gamepad_hidden_frame.html]
+support-files = test_gamepad_hidden_frame_iframe.html
 [test_navigator_gamepads.html]
+support-files = test_navigator_gamepads_iframe.html
--- a/dom/tests/mochitest/gamepad/mock_gamepad.js
+++ b/dom/tests/mochitest/gamepad/mock_gamepad.js
@@ -1,12 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 var GamepadService;
 
+function setGamepadPreferenceAndCreateIframe(iframeSrc) {
+  SpecialPowers.pushPrefEnv({"set" : [["dom.gamepad.test.enabled", true]]}, () => {
+    let iframe = document.createElement("iframe");
+    iframe.src = iframeSrc;
+    document.body.appendChild(iframe);
+  });
+}
+
 function runGamepadTest (callback) {
-  SpecialPowers.pushPrefEnv({"set" : [["dom.gamepad.test.enabled", true]]},
-                      () => {
-                        GamepadService = navigator.requestGamepadServiceTest();
-                        callback();
-                      });
-}
\ No newline at end of file
+  GamepadService = navigator.requestGamepadServiceTest();
+  callback();
+}
--- a/dom/tests/mochitest/gamepad/test_check_timestamp.html
+++ b/dom/tests/mochitest/gamepad/test_check_timestamp.html
@@ -5,63 +5,16 @@
 <head>
   <title>Test Gamepad.timestamp</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-
-window.addEventListener("gamepadbuttondown", buttonpresshandler);
-
-var index;
-var timea=0;
-var firstPress = true;
-var testOver = false;
-
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
-runGamepadTest(checkTimestamp);
-
-function checkTimestamp(){
-  GamepadService.addGamepad("test gamepad 1",
-                            GamepadService.standardMapping,
-                            GamepadService.noHand,
-                            4,
-                            2,
-                            0).then(function(i) {
-                              index = i;
-                              // Press a button to make the gamepad visible
-                              // to the page.
-                              GamepadService.newButtonEvent(index, 0, true);
-                              GamepadService.newButtonEvent(index, 0, true);
-                              ok(true, "test");
-                            });
-}
-
-function cleanup(){
-  SpecialPowers.executeSoon(function() {
-    GamepadService.removeGamepad(index);
-    SimpleTest.finish();
-  });
-}
-
-function buttonpresshandler(e) {
-  if (testOver) {
-    return;
-  }
-  if (timea == 0){
-    timea = e.gamepad.timestamp;
-  } else {
-    ok(timea <= e.gamepad.timestamp, "Timestamp less than last timestamp");
-  }
-  GamepadService.newButtonEvent(index, 0, false);
-  if (!firstPress) {
-    testOver = true;
-    SpecialPowers.executeSoon(cleanup);
-  } else {
-    firstPress = false;
-  }
-}
+setGamepadPreferenceAndCreateIframe("test_check_timestamp_iframe.html");
 
 </script>
 </body>
 </html>
copy from dom/tests/mochitest/gamepad/test_check_timestamp.html
copy to dom/tests/mochitest/gamepad/test_check_timestamp_iframe.html
--- a/dom/tests/mochitest/gamepad/test_check_timestamp.html
+++ b/dom/tests/mochitest/gamepad/test_check_timestamp_iframe.html
@@ -1,29 +1,32 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test Gamepad.timestamp</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
 
+let ok = window.parent.ok;
+let is = window.parent.is;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
+
 window.addEventListener("gamepadbuttondown", buttonpresshandler);
 
 var index;
 var timea=0;
 var firstPress = true;
 var testOver = false;
 
-SimpleTest.waitForExplicitFinish();
 runGamepadTest(checkTimestamp);
 
 function checkTimestamp(){
   GamepadService.addGamepad("test gamepad 1",
                             GamepadService.standardMapping,
                             GamepadService.noHand,
                             4,
                             2,
--- a/dom/tests/mochitest/gamepad/test_gamepad.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad.html
@@ -5,69 +5,16 @@
 <head>
   <title>Test gamepad</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
-// Due to gamepad being a polling API instead of event driven, test ordering
-// ends up being a little weird in order to deal with e10s. Calls to
-// GamepadService are async across processes, so we'll need to make sure
-// we account for timing before checking values.
-window.addEventListener("gamepadconnected", connecthandler);
-var index;
-var testNum = 0;
-
-window.addEventListener("gamepadbuttondown", () => {
-  SpecialPowers.executeSoon(buttontest1);
-});
-
-window.addEventListener("gamepadbuttonup", () => {
-  SpecialPowers.executeSoon(buttontest2);
-});
-
-runGamepadTest(startTest);
-
-function startTest() {
-  // Add a gamepad
-  GamepadService.addGamepad("test gamepad", // id
-                     GamepadService.standardMapping,
-                     GamepadService.noHand,
-                     4,
-                     2,
-                     0).then(function(i) {
-                       index = i;
-                       // Simulate button events on the gamepad we added
-                       GamepadService.newButtonEvent(index, 0, true);
-                     });
-}
-
-function connecthandler(e) {
-  ok(e.gamepad.timestamp <= performance.now(),
-     "gamepad.timestamp should less than or equal to performance.now()");
-  is(e.gamepad.index, 0, "correct gamepad index");
-  is(e.gamepad.id, "test gamepad", "correct gamepad name");
-  is(e.gamepad.mapping, "standard", "standard mapping");
-  is(e.gamepad.buttons.length, 4, "correct number of buttons");
-  is(e.gamepad.axes.length, 2, "correct number of axes");
-}
-
-function buttontest1() {
-  var gamepads = navigator.getGamepads();
-  is(gamepads[0].buttons[0].pressed, true, "gamepad button should register as pressed");
-  GamepadService.newButtonValueEvent(index, 1, true, 0.5);
-}
-
-function buttontest2() {
-  var gamepads = navigator.getGamepads();
-  is(gamepads[0].buttons[1].pressed, true, "gamepad button should register as pressed");
-  is(gamepads[0].buttons[1].value, 0.5, "gamepad button value should be 0.5");
-  GamepadService.removeGamepad(index);
-  SimpleTest.finish();
-}
+setGamepadPreferenceAndCreateIframe("test_gamepad_iframe.html");
 
 </script>
 </body>
 </html>
-
--- a/dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
@@ -8,71 +8,15 @@
 <head>
   <title>Test hidden frames</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
-
-var gamepad_index;
-
-function pressButton() {
-  GamepadService.newButtonEvent(gamepad_index, 0, true);
-  GamepadService.newButtonEvent(gamepad_index, 0, false);
-}
-
- // Add a gamepad
-function startTests() {
-  window.addEventListener("gamepadbuttondown", function() {
-    // Wait to ensure that all frames received the button press as well.
-    SpecialPowers.executeSoon(tests[testNum++]);
-  });
-
-  GamepadService.addGamepad("test gamepad", // id
-                            GamepadService.standardMapping,
-                            GamepadService.noHand,
-                            4, // buttons
-                            2,
-                            0).then(function(i) {
-                              gamepad_index = i;
-                              gamepad_connected()
-                            });
-}
-
-var f1, f2;
-function gamepad_connected() {
-  f1 = document.getElementById('f1');
-  pressButton();
-}
-
-var testNum = 0;
-var tests = [
-  test1,
-  test2,
-];
-
-function test1() {
-  is(f1.contentWindow.connectedEvents, 1, "right number of connection events in frame 1");
-
-  // Now add another frame.
-  f2 = document.createElement("iframe");
-  f2.addEventListener("load", function() {
-    // When the frame is loaded, press a button again.
-    pressButton();
-  });
-  f2.src = "gamepad_frame.html";
-  document.body.appendChild(f2);
-}
-
-function test2() {
-  is(f1.contentWindow.connectedEvents, 1, "right number of connection events in frame 1");
-  is(f2.contentWindow.connectedEvents, 1, "right number of connection events in frame 2");
-  GamepadService.removeGamepad(gamepad_index);
-  SimpleTest.finish();
-}
-
+setGamepadPreferenceAndCreateIframe("test_check_timestamp_iframe.html");
 </script>
-<iframe id="f1" src="gamepad_frame.html" onload="runGamepadTest(startTests)"></iframe>
 </body>
 </html>
copy from dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
copy to dom/tests/mochitest/gamepad/test_gamepad_connect_events_iframe.html
--- a/dom/tests/mochitest/gamepad/test_gamepad_connect_events.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_connect_events_iframe.html
@@ -8,17 +8,20 @@
 <head>
   <title>Test hidden frames</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
+let ok = window.parent.ok;
+let is = window.parent.is;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
 
 var gamepad_index;
 
 function pressButton() {
   GamepadService.newButtonEvent(gamepad_index, 0, true);
   GamepadService.newButtonEvent(gamepad_index, 0, false);
 }
 
--- a/dom/tests/mochitest/gamepad/test_gamepad_extensions.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_extensions.html
@@ -5,130 +5,15 @@
 <head>
   <title>Test gamepad</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
-
-var tests = [
-  poseadd,
-  posecheck,
-  haptictest
-];
-var gamepad_index = 0;
-var testNum = 0;
-var poseOrient = new Float32Array([-0.203, -0.235, 0.740, -0.596]);
-var posePos = new Float32Array([-0.0233, -0.707, -0.763]);
-var poseAngVel = new Float32Array([-0.0008, 0.00147, 0.001]);
-var poseAngAcc = new Float32Array([-0.494, 0.476, -0.241]);
-var poseLinVel = new Float32Array([0.003,0.024,-0.068]);
-var poseLinAcc = new Float32Array([-1.211,21.427,-2.348]);
-
-window.addEventListener("gamepadconnected", connecthandler);
-window.addEventListener("gamepadbuttondown", function() {
-  // Wait to ensure that all frames received the button press as well.
-  SpecialPowers.executeSoon(tests[testNum++]);
-});
-
-function pressButton() {
-  GamepadService.newButtonEvent(gamepad_index, 0, true);
-  GamepadService.newButtonEvent(gamepad_index, 0, false);
-}
-
-function startTest() {
-  SpecialPowers.pushPrefEnv({ "set": [["dom.gamepad.extensions.enabled", true]] });
-  // Add a gamepad
-  GamepadService.addGamepad("test gamepad", // id
-                     GamepadService.standardMapping,
-                     GamepadService.leftHand,
-                     4,
-                     2,
-                     1).then(function(i) {
-                      gamepad_index = i;
-                       // Simulate button events on the gamepad we added
-                      pressButton();
-                     });
-}
-
-function connecthandler(e) {
-  ok(e.gamepad.timestamp <= performance.now(),
-     "gamepad.timestamp should less than or equal to performance.now()");
-  is(e.gamepad.index, 0, "correct gamepad index");
-  is(e.gamepad.id, "test gamepad", "correct gamepad name");
-  is(e.gamepad.mapping, "standard", "standard mapping");
-  is(e.gamepad.hand, "left", "left hand");
-  is(e.gamepad.buttons.length, 4, "correct number of buttons");
-  is(e.gamepad.axes.length, 2, "correct number of axes");
-  is(e.gamepad.hapticActuators.length, 1, "correct number of haptics");
-}
-
-function checkValueInFloat32Array(array1, array2) {
-  if (array1.length != array2.length) {
-    return false;
-  }
-  var index = 0;
-  while (index < array2.length) {
-    if (array1[index] != array2[index]) {
-      return false;
-    }
-    ++index;
-  }
-  return true;
-}
-
-function poseadd() {
-  GamepadService.newPoseMove(gamepad_index, poseOrient,
-                             posePos, poseAngVel, poseAngAcc,
-                             poseLinVel, poseLinAcc);
-  pressButton();
-}
-
-function posecheck() {
-  var gamepads = navigator.getGamepads();
-  var pose = gamepads[0].pose;
-  is(gamepads[0].pose.hasOrientation, true,
-     "correct gamepadPose hasOrientation");
-  is(gamepads[0].pose.hasPosition, true,
-     "correct gamepadPose hasPosition");
-  is(checkValueInFloat32Array(pose.orientation, poseOrient), true,
-     "correct gamepadPose orientation");
-  is(checkValueInFloat32Array(pose.position, posePos), true,
-     "correct gamepadPose position");
-  is(checkValueInFloat32Array(pose.angularVelocity, poseAngVel), true,
-     "correct gamepadPose angularVelocity");
-  is(checkValueInFloat32Array(pose.angularAcceleration, poseAngAcc), true,
-     "correct gamepadPose angularAcceleration");
-  is(checkValueInFloat32Array(pose.linearVelocity, poseLinVel), true,
-     "correct gamepadPose linearVelocity");
-  is(checkValueInFloat32Array(pose.linearAcceleration, poseLinAcc), true,
-     "correct gamepadPose linearAcceleration");
-  pressButton();
-}
-
-function setFrameVisible(f, visible) {
-  var Ci = SpecialPowers.Ci;
-  var docshell = SpecialPowers.wrap(f.contentWindow).QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
-  docshell.isActive = visible;
-}
-
-function haptictest() {
-  var gamepads = navigator.getGamepads();
-  var hapticActuators = gamepads[0].hapticActuators[0];
-  hapticActuators.pulse(1, 100).then(function(result) {
-    is(result, true, "gamepad hapticActuators test success.");
-    GamepadService.removeGamepad(gamepad_index);
-    SimpleTest.finish();
-  });
-  // When page is background, we should stop our haptics and still
-  // can get the promise.
-  var f1 = document.getElementById('f1');
-  setFrameVisible(f1, false);
-}
-
+setGamepadPreferenceAndCreateIframe("test_gamepad_extensions_iframe.html");
 </script>
-<iframe id="f1" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
 </body>
 </html>
-
copy from dom/tests/mochitest/gamepad/test_gamepad_extensions.html
copy to dom/tests/mochitest/gamepad/test_gamepad_extensions_iframe.html
--- a/dom/tests/mochitest/gamepad/test_gamepad_extensions.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_extensions_iframe.html
@@ -1,21 +1,23 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test gamepad</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
+let ok = window.parent.ok;
+let is = window.parent.is;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
 
 var tests = [
   poseadd,
   posecheck,
   haptictest
 ];
 var gamepad_index = 0;
 var testNum = 0;
@@ -126,9 +128,8 @@ function haptictest() {
   var f1 = document.getElementById('f1');
   setFrameVisible(f1, false);
 }
 
 </script>
 <iframe id="f1" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
 </body>
 </html>
-
--- a/dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync.html
@@ -5,100 +5,15 @@
 <head>
   <title>Test hidden frames</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
- // Add a gamepad
-var index;
-
-function setFrameVisible(f, visible) {
-  var Ci = SpecialPowers.Ci;
-  var docshell = SpecialPowers.wrap(f.contentWindow).QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
-  docshell.isActive = visible;
-}
-
-var frames_loaded = 0;
-function startTest() {
-  frames_loaded++;
-  if (frames_loaded == 2) {
-    GamepadService.addGamepad("test gamepad", // id
-                              GamepadService.standardMapping,
-                              GamepadService.noHand,
-                              4, // buttons
-                              2,
-                              0).then(function(i) {
-                                index = i;
-                                gamepad_loaded();
-                              });
-  }
-}
-var f1, f2;
-function gamepad_loaded() {
-  f1 = document.getElementById('f1');
-  f2 = document.getElementById('f2');
-  let w1 = f1.contentWindow;
-  let w2 = f2.contentWindow;
-  w1.addEventListener("gamepadbuttonup", () => {
-                       ok(!f1.contentWindow.gamepad.buttons[0].pressed,
-                          "frame 1 no button pressed");
-                      });
-  w2.addEventListener("gamepadbuttonup", () => {
-                      ok(!f2.contentWindow.gamepad.buttons[0].pressed,
-                         "frame 2 no button pressed");
-                      setFrameVisible(f2, false);
-                      SpecialPowers.executeSoon(function() {
-                        GamepadService.newButtonEvent(index, 0, true);
-                        });
-                      })
-  // Now press the button, but don't release it.
-  GamepadService.newButtonEvent(index, 0, true);
-}
-
-window.addEventListener("gamepadbuttondown", function() {
-  // Wait to ensure that all frames received the button press as well.
- SpecialPowers.executeSoon(tests[testNum++]);
-});
-
-var testNum = 0;
-var tests = [
-  check_button_pressed,
-  check_second_frame_no_button_press,
-];
-
-function check_button_pressed() {
-  // At this point the both frames should see the button as pressed.
-  ok(f1.contentWindow.gamepad.buttons[0].pressed, "frame 1 sees button pressed");
-  ok(f2.contentWindow.gamepad.buttons[0].pressed, "frame 2 sees button pressed");
-
-  // Now release the button, then hide the second frame.
-  GamepadService.newButtonEvent(index, 0, false);
-}
-
-function check_second_frame_no_button_press () {
-  /*
-   * At this point the first frame should see the button as pressed,
-   * but the second frame should not, since it's hidden.
-   */
-  ok(f1.contentWindow.gamepad.buttons[0].pressed, "frame 1 sees button pressed");
-  ok(!f2.contentWindow.gamepad.buttons[0].pressed, "frame 2 should not see button pressed");
-
-  // Now unhide the second frame.
-  setFrameVisible(f2, true);
-  SpecialPowers.executeSoon(function() {
-    // Now that the frame is visible again, it should see the button
-    // that was pressed.
-    ok(f2.contentWindow.gamepad.buttons[0].pressed, "frame 2 sees button pressed");
-    // cleanup
-    GamepadService.removeGamepad(index);
-    SimpleTest.finish();
-  });
-}
-
+setGamepadPreferenceAndCreateIframe("test_gamepad_frame_state_sync_iframe.html");
 </script>
-<iframe id="f1" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
-<iframe id="f2" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
 </body>
 </html>
copy from dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync.html
copy to dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync_iframe.html
--- a/dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_frame_state_sync_iframe.html
@@ -1,21 +1,24 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test hidden frames</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
+let ok = window.parent.ok;
+let is = window.parent.is;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
+
  // Add a gamepad
 var index;
 
 function setFrameVisible(f, visible) {
   var Ci = SpecialPowers.Ci;
   var docshell = SpecialPowers.wrap(f.contentWindow).QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
   docshell.isActive = visible;
 }
--- a/dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
@@ -5,77 +5,15 @@
 <head>
   <title>Test hidden frames</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
-
-window.addEventListener("gamepadbuttondown", function() {
-  // Wait to ensure that all frames received the button press as well.
- SpecialPowers.executeSoon(tests[testNum++]);
-});
-
-function pressButton() {
-  GamepadService.newButtonEvent(index, 0, true);
-  GamepadService.newButtonEvent(index, 0, false);
-}
-
-function setFrameVisible(f, visible) {
-  var Ci = SpecialPowers.Ci;
-  var docshell = SpecialPowers.wrap(f.contentWindow).QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
-  docshell.isActive = visible;
-}
-
-var frames_loaded = 0;
-function startTest() {
-  frames_loaded++;
-  if (frames_loaded == 2) {
-    GamepadService.addGamepad("test gamepad", // id
-                              GamepadService.standardMapping,
-                              GamepadService.noHand,
-                              4, // buttons
-                              2,
-                              0).then(function(i) {
-                                index = i;
-                                gamepad_loaded();
-                              });
-  }
-}
-var f1, f2;
-function gamepad_loaded() {
-  f1 = document.getElementById('f1');
-  f2 = document.getElementById('f2');
-  pressButton();
-}
-
-
-
-var testNum = 0;
-var tests = [
-  test1,
-  test2,
-];
-
-function test1() {
-  is(f1.contentWindow.buttonPresses, 1, "right number of button presses in frame 1");
-  is(f2.contentWindow.buttonPresses, 1, "right number of button presses in frame 2");
-
-  // Now hide the second frame and send another button press.
-  setFrameVisible(f2, false);
-  SpecialPowers.executeSoon( () => { pressButton(); });
-}
-
-function test2() {
-  is(f1.contentWindow.buttonPresses, 2, "right number of button presses in frame 1");
-  is(f2.contentWindow.buttonPresses, 1, "right number of button presses in frame 2");
-  GamepadService.removeGamepad(index);
-  SimpleTest.finish();
-}
-
+setGamepadPreferenceAndCreateIframe("test_gamepad_hidden_frame_iframe.html");
 </script>
-<iframe id="f1" src="gamepad_frame.html" onload="runGamepadTest(startTest)"></iframe>
-<iframe id="f2" src="gamepad_frame.html" onload="runGamepadTest(startTest)"></iframe>
 </body>
 </html>
copy from dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
copy to dom/tests/mochitest/gamepad/test_gamepad_hidden_frame_iframe.html
--- a/dom/tests/mochitest/gamepad/test_gamepad_hidden_frame.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_hidden_frame_iframe.html
@@ -1,21 +1,23 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test hidden frames</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
+let ok = window.parent.ok;
+let is = window.parent.is;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
 
 window.addEventListener("gamepadbuttondown", function() {
   // Wait to ensure that all frames received the button press as well.
  SpecialPowers.executeSoon(tests[testNum++]);
 });
 
 function pressButton() {
   GamepadService.newButtonEvent(index, 0, true);
copy from dom/tests/mochitest/gamepad/test_gamepad.html
copy to dom/tests/mochitest/gamepad/test_gamepad_iframe.html
--- a/dom/tests/mochitest/gamepad/test_gamepad.html
+++ b/dom/tests/mochitest/gamepad/test_gamepad_iframe.html
@@ -1,21 +1,24 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test gamepad</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
+let ok = window.parent.ok;
+let is = window.parent.is;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
+
 // Due to gamepad being a polling API instead of event driven, test ordering
 // ends up being a little weird in order to deal with e10s. Calls to
 // GamepadService are async across processes, so we'll need to make sure
 // we account for timing before checking values.
 window.addEventListener("gamepadconnected", connecthandler);
 var index;
 var testNum = 0;
 
@@ -65,9 +68,8 @@ function buttontest2() {
   is(gamepads[0].buttons[1].value, 0.5, "gamepad button value should be 0.5");
   GamepadService.removeGamepad(index);
   SimpleTest.finish();
 }
 
 </script>
 </body>
 </html>
-
--- a/dom/tests/mochitest/gamepad/test_navigator_gamepads.html
+++ b/dom/tests/mochitest/gamepad/test_navigator_gamepads.html
@@ -5,111 +5,15 @@
 <head>
   <title>Test gamepad</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
-
-var testNum = 0;
-var tests = [
-  check_first_gamepad,
-  check_second_gamepad,
-  check_gamepad_hole,
-  check_no_gamepads,
-];
-
-function run_next_test(event) {
-  SpecialPowers.executeSoon(function() { tests[testNum++](event); });
-}
-
-function buttonhandler(e) {
- run_next_test(e);
-}
-
-function disconnecthandler(e) {
-  run_next_test(e);
-}
-window.addEventListener("gamepadbuttondown", buttonhandler);
-window.addEventListener("gamepaddisconnected", disconnecthandler);
-
-runGamepadTest(startTest)
-
-function startTest() {
-  // gamepads should be empty first
-  is(navigator.getGamepads().length, 0, "should be zero gamepads exposed");
-  // Add a gamepad
-  GamepadService.addGamepad("test gamepad 1", // id
-                     GamepadService.standardMapping,
-                     GamepadService.noHand,
-                     4, // buttons
-                     2,
-                     0).then(function(index) {
-                       internal_index1 = index;
-                       // Press a button to make the gamepad visible to the page.
-                       GamepadService.newButtonEvent(internal_index1, 0, true);
-                     });
-}
-
-var content_index1 = 0;
-var internal_index2;
-var content_index2 = 1;
-
-function check_first_gamepad(e) {
-  ok(true, "Checking first gamepad");
-  // First gamepad gets added.
-  is(e.gamepad.id, "test gamepad 1", "correct gamepad name");
-  var gamepads = navigator.getGamepads();
-  is(gamepads.length, 1, "should have one gamepad exposed");
-  is(gamepads[e.gamepad.index], e.gamepad, "right gamepad exposed at index");
-  is(gamepads[content_index1], e.gamepad, "gamepad counter working correctly");
-  // Add a second gamepad, should automatically show up.
-  GamepadService.addGamepad("test gamepad 2", // id
-                     GamepadService.standardMapping,
-                     GamepadService.noHand,
-                     4, // buttons
-                     2,
-                     0).then(function(index) {
-                       internal_index2 = index;
-                       GamepadService.newButtonEvent(internal_index2, 0, true);
-                     });
-  ok(true, "Done checking first gamepad");
-}
-
-function check_second_gamepad(e) {
-  ok(true, "Checking second gamepad");
-  // Second gamepad gets added.
-  is(e.gamepad.index, 1, "gamepad index should be 1")
-  is(e.gamepad.id, "test gamepad 2", "correct gamepad name");
-  var gamepads = navigator.getGamepads();
-  is(gamepads.length, 2, "should have two gamepads exposed");
-  is(gamepads[e.gamepad.index], e.gamepad, "right gamepad exposed at index");
-  is(gamepads[content_index2], e.gamepad, "gamepad counter working correctly");
-  // Now remove the first one.
-  GamepadService.removeGamepad(internal_index1);
-  ok(true, "Done checking second gamepad");
-}
-
-function check_gamepad_hole(e) {
-  ok(true, "Checking gamepad hole");
-  // First gamepad gets removed.
-  var gamepads = navigator.getGamepads();
-  is(gamepads.length, 2, "gamepads should have two entries");
-  is(gamepads[content_index1], null, "should be a hole in the gamepad list");
-  isnot(gamepads[content_index2], null, "second gamepad should exist");
-  // Now remove the second one.
-  GamepadService.removeGamepad(internal_index2);
-  ok(true, "Done checking gamepad hole");
-}
-
-function check_no_gamepads(e) {
-  ok(true, "Checking no gamepads");
-  // Second gamepad gets removed.
-  var gamepads = navigator.getGamepads();
-  is(gamepads.length, 0, "gamepads should be empty");
-  SimpleTest.finish();
-}
+setGamepadPreferenceAndCreateIframe("test_navigator_gamepads_iframe.html");
 </script>
 </body>
 </html>
copy from dom/tests/mochitest/gamepad/test_navigator_gamepads.html
copy to dom/tests/mochitest/gamepad/test_navigator_gamepads_iframe.html
--- a/dom/tests/mochitest/gamepad/test_navigator_gamepads.html
+++ b/dom/tests/mochitest/gamepad/test_navigator_gamepads_iframe.html
@@ -1,21 +1,24 @@
 <!-- Any copyright is dedicated to the Public Domain.
    - http://creativecommons.org/publicdomain/zero/1.0/ -->
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test gamepad</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script type="text/javascript" src="mock_gamepad.js"></script>
 <script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
+let ok = window.parent.ok;
+let is = window.parent.is;
+let isnot = window.parent.isnot;
+let SimpleTest = window.parent.SimpleTest;
+let SpecialPowers = window.parent.SpecialPowers;
 
 var testNum = 0;
 var tests = [
   check_first_gamepad,
   check_second_gamepad,
   check_gamepad_hole,
   check_no_gamepads,
 ];
--- a/dom/tests/mochitest/geolocation/mochitest.ini
+++ b/dom/tests/mochitest/geolocation/mochitest.ini
@@ -12,16 +12,17 @@ support-files =
 [test_cachedPosition.html]
 [test_cancelCurrent.html]
 [test_cancelWatch.html]
 [test_clearWatch.html]
 [test_clearWatchBeforeAllowing.html]
 [test_clearWatch_invalid.html]
 [test_errorcheck.html]
 [test_geolocation_is_undefined_when_pref_is_off.html]
+support-files = test_geolocation_is_undefined_when_pref_is_off_iframe.html
 [test_manyCurrentConcurrent.html]
 [test_manyCurrentSerial.html]
 [test_manyWatchConcurrent.html]
 [test_manyWatchSerial.html]
 [test_manyWindows.html]
 [test_optional_api_params.html]
 [test_shutdown.html]
 [test_timeoutCurrent.html]
--- a/dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off.html
+++ b/dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off.html
@@ -14,22 +14,23 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank"
 href="https://bugzilla.mozilla.org/show_bug.cgi?id=884921">Mozilla Bug 884921</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
 SimpleTest.waitForExplicitFinish();
 
 SpecialPowers.pushPrefEnv({set: [["geo.enabled", false]]}, function() {
-  is(navigator.geolocation, undefined);
-  is("geolocation" in navigator, false);
-  SimpleTest.finish();
+  let iframe = document.createElement("iframe");
+  iframe.id = "f1";
+  iframe.src = "test_geolocation_is_undefined_when_pref_is_off_iframe.html";
+  document.body.appendChild(iframe);
 });
 
 </script>
 </pre>
 </body>
 </html>
-
copy from dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off.html
copy to dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off_iframe.html
--- a/dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off.html
+++ b/dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off_iframe.html
@@ -14,22 +14,15 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank"
 href="https://bugzilla.mozilla.org/show_bug.cgi?id=884921">Mozilla Bug 884921</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-SpecialPowers.pushPrefEnv({set: [["geo.enabled", false]]}, function() {
-  is(navigator.geolocation, undefined);
-  is("geolocation" in navigator, false);
-  SimpleTest.finish();
-});
-
+  window.parent.is(navigator.geolocation, undefined);
+  window.parent.is("geolocation" in navigator, false);
+  window.parent.SimpleTest.finish();
 </script>
 </pre>
 </body>
 </html>
-
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -56,17 +56,16 @@ support-files =
   sharedWorker_console.js
   sharedWorker_sharedWorker.js
   simpleThread_worker.js
   suspend_iframe.html
   suspend_worker.js
   terminate_worker.js
   test_csp.html^headers^
   test_csp.js
-  test_navigator.js
   referrer_worker.html
   threadErrors_worker1.js
   threadErrors_worker2.js
   threadErrors_worker3.js
   threadErrors_worker4.js
   threadTimeouts_worker.js
   throwingOnerror_worker.js
   timeoutTracing_worker.js
@@ -166,18 +165,26 @@ tags = mcb
 [test_json.html]
 [test_loadEncoding.html]
 [test_loadError.html]
 [test_location.html]
 [test_longThread.html]
 [test_multi_sharedWorker.html]
 [test_multi_sharedWorker_lifetimes.html]
 [test_navigator.html]
+support-files =
+  test_navigator.js
+  test_navigator_iframe.html
+  test_navigator_iframe.js
 [test_navigator_secureContext.html]
 scheme=https
+support-files =
+  test_navigator.js
+  test_navigator_iframe.html
+  test_navigator_iframe.js
 [test_navigator_languages.html]
 [test_newError.html]
 [test_notification.html]
 [test_notification_child.html]
 [test_notification_permission.html]
 [test_onLine.html]
 [test_promise.html]
 [test_promise_resolved_with_string.html]
--- a/dom/workers/test/test_navigator.js
+++ b/dom/workers/test/test_navigator.js
@@ -1,49 +1,10 @@
-function runTest() {
-  var worker = new Worker("navigator_worker.js");
-
-  worker.onmessage = function(event) {
-    var args = JSON.parse(event.data);
-
-    if (args.name == "testFinished") {
-      SimpleTest.finish();
-      return;
-    }
-
-    if (typeof navigator[args.name] == "undefined") {
-      ok(false, "Navigator has no '" + args.name + "' property!");
-      return;
-    }
-
-    if (args.name === "languages") {
-      is(navigator.languages.toString(), args.value.toString(), "languages matches");
-      return;
-    }
+SimpleTest.waitForExplicitFinish();
 
-    if (args.name === "storage") {
-      is(typeof navigator.storage, typeof args.value, "storage type matches");
-      return;
-    }
-
-    if (args.name === "connection") {
-      is(typeof navigator.connection, typeof args.value, "connection type matches");
-      return;
-    }
-
-    is(navigator[args.name], args.value,
-       "Mismatched navigator string for " + args.name + "!");
-  };
-
-  worker.onerror = function(event) {
-    ok(false, "Worker had an error: " + event.message);
-    SimpleTest.finish();
-  }
-
-  var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
-  var isNightly = version.endsWith("a1");
-  var isRelease = !version.includes("a");
-
-  worker.postMessage({ isNightly, isRelease });
-}
-
-SpecialPowers.pushPrefEnv({"set": [["dom.netinfo.enabled", true]]}, runTest);
-SimpleTest.waitForExplicitFinish();
+// This test loads in an iframe, to ensure that the navigator instance is
+// loaded with the correct value of the preference.
+SpecialPowers.pushPrefEnv({"set": [["dom.netinfo.enabled", true]]}, () => {
+  let iframe = document.createElement("iframe");
+  iframe.id = "f1";
+  iframe.src = "test_navigator_iframe.html";
+  document.body.appendChild(iframe);
+});
copy from dom/workers/test/test_navigator.html
copy to dom/workers/test/test_navigator_iframe.html
--- a/dom/workers/test/test_navigator.html
+++ b/dom/workers/test/test_navigator_iframe.html
@@ -1,27 +1,24 @@
 <!--
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <!DOCTYPE HTML>
 <html>
 <!--
-Tests of DOM Worker Navigator
+Sub-tests of DOM Worker Navigator tests.
 -->
 <head>
   <title>Test for DOM Worker Navigator</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">
-<script>
-  ok(!self.isSecureContext, "This test should not be running in a secure context");
-</script>
-<script type="text/javascript" src="test_navigator.js"></script>
+<script type="text/javascript" src="test_navigator_iframe.js"></script>
 </pre>
 </body>
 </html>
copy from dom/workers/test/test_navigator.js
copy to dom/workers/test/test_navigator_iframe.js
--- a/dom/workers/test/test_navigator.js
+++ b/dom/workers/test/test_navigator_iframe.js
@@ -1,49 +1,48 @@
-function runTest() {
-  var worker = new Worker("navigator_worker.js");
-
-  worker.onmessage = function(event) {
-    var args = JSON.parse(event.data);
+var worker = new Worker("navigator_worker.js");
 
-    if (args.name == "testFinished") {
-      SimpleTest.finish();
-      return;
-    }
+var is = window.parent.is;
+var ok = window.parent.ok;
+var SimpleTest = window.parent.SimpleTest;
 
-    if (typeof navigator[args.name] == "undefined") {
-      ok(false, "Navigator has no '" + args.name + "' property!");
-      return;
-    }
+worker.onmessage = function(event) {
+  var args = JSON.parse(event.data);
 
-    if (args.name === "languages") {
-      is(navigator.languages.toString(), args.value.toString(), "languages matches");
-      return;
-    }
-
-    if (args.name === "storage") {
-      is(typeof navigator.storage, typeof args.value, "storage type matches");
-      return;
-    }
+  if (args.name == "testFinished") {
+    SimpleTest.finish();
+    return;
+  }
 
-    if (args.name === "connection") {
-      is(typeof navigator.connection, typeof args.value, "connection type matches");
-      return;
-    }
+  if (typeof navigator[args.name] == "undefined") {
+    ok(false, "Navigator has no '" + args.name + "' property!");
+    return;
+  }
 
-    is(navigator[args.name], args.value,
-       "Mismatched navigator string for " + args.name + "!");
-  };
-
-  worker.onerror = function(event) {
-    ok(false, "Worker had an error: " + event.message);
-    SimpleTest.finish();
+  if (args.name === "languages") {
+    is(navigator.languages.toString(), args.value.toString(), "languages matches");
+    return;
   }
 
-  var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
-  var isNightly = version.endsWith("a1");
-  var isRelease = !version.includes("a");
+  if (args.name === "storage") {
+    is(typeof navigator.storage, typeof args.value, "storage type matches");
+    return;
+  }
 
-  worker.postMessage({ isNightly, isRelease });
+  if (args.name === "connection") {
+    is(typeof navigator.connection, typeof args.value, "connection type matches");
+    return;
+  }
+
+  is(navigator[args.name], args.value,
+     "Mismatched navigator string for " + args.name + "!");
+};
+
+worker.onerror = function(event) {
+  ok(false, "Worker had an error: " + event.message);
+  SimpleTest.finish();
 }
 
-SpecialPowers.pushPrefEnv({"set": [["dom.netinfo.enabled", true]]}, runTest);
-SimpleTest.waitForExplicitFinish();
+var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
+var isNightly = version.endsWith("a1");
+var isRelease = !version.includes("a");
+
+worker.postMessage({ isNightly, isRelease });