Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Mon, 18 Jun 2018 12:07:01 +0300
changeset 422828 4e6031a71ca31be8bd3a8e0241735233e297df58
parent 422827 f3a4d5ac04be4e04b658c839e06f3c047bc346c5 (current diff)
parent 422817 f804cc575bba9c6dcb4e3770f7dafe4d8934e73c (diff)
child 422829 705644bd3788e039c147373182fa7fd19fec0e6d
push id34153
push usercsabou@mozilla.com
push dateMon, 18 Jun 2018 15:53:06 +0000
treeherdermozilla-central@9b74b9f2939a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
--- a/accessible/tests/mochitest/elm/test_nsApplicationAcc.html
+++ b/accessible/tests/mochitest/elm/test_nsApplicationAcc.html
@@ -8,17 +8,16 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
 
   <script type="application/javascript">
-    /* import-globals-from ../common.js */
     function doTest() {
       var accessible = getApplicationAccessible();
       if (!accessible) {
         SimpleTest.finish();
         return;
       }
 
       var brandBundle =
--- a/accessible/tests/mochitest/textcaret/test_general.html
+++ b/accessible/tests/mochitest/textcaret/test_general.html
@@ -10,17 +10,16 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
-    /* import-globals-from ../common.js */
     /**
      * Turn on/off the caret browsing mode.
      */
     function turnCaretBrowsing(aIsOn) {
       Services.prefs.setBoolPref("accessibility.browsewithcaret", aIsOn);
     }
 
     /**
--- a/browser/components/payments/test/mochitest/test_PaymentStateSubscriberMixin.html
+++ b/browser/components/payments/test/mochitest/test_PaymentStateSubscriberMixin.html
@@ -22,17 +22,16 @@ Test the PaymentStateSubscriberMixin
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the PaymentStateSubscriberMixin **/
 
 /* global sinon */
-/* import-globals-from payments_common.js */
 
 import PaymentStateSubscriberMixin from "../../res/mixins/PaymentStateSubscriberMixin.js";
 
 class TestElement extends PaymentStateSubscriberMixin(HTMLElement) {
   render(state) {
     this.textContent = JSON.stringify(state);
   }
 }
--- a/browser/components/payments/test/mochitest/test_address_form.html
+++ b/browser/components/payments/test/mochitest/test_address_form.html
@@ -26,17 +26,16 @@ Test the address-form element
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the address-form element **/
 
 /* global sinon */
-/* import-globals-from payments_common.js */
 
 import AddressForm from "../../res/containers/address-form.js";
 
 let display = document.getElementById("display");
 
 function checkAddressForm(customEl, expectedAddress) {
   const ADDRESS_PROPERTY_NAMES = [
     "given-name",
--- a/browser/components/payments/test/mochitest/test_address_picker.html
+++ b/browser/components/payments/test/mochitest/test_address_picker.html
@@ -25,17 +25,16 @@ Test the address-picker component
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the address-picker component **/
 
-/* import-globals-from payments_common.js */
 import "../../res/containers/address-picker.js";
 
 let picker1 = document.getElementById("picker1");
 
 add_task(async function test_empty() {
   ok(picker1, "Check picker1 exists");
   let {savedAddresses} = picker1.requestStore.getState();
   is(Object.keys(savedAddresses).length, 0, "Check empty initial state");
--- a/browser/components/payments/test/mochitest/test_basic_card_form.html
+++ b/browser/components/payments/test/mochitest/test_basic_card_form.html
@@ -25,17 +25,16 @@ Test the basic-card-form element
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the basic-card-form element **/
 
 /* global sinon */
-/* import-globals-from payments_common.js */
 
 import BasicCardForm from "../../res/containers/basic-card-form.js";
 
 let display = document.getElementById("display");
 
 function checkCCForm(customEl, expectedCard) {
   const CC_PROPERTY_NAMES = [
     "billingAddressGUID",
--- a/browser/components/payments/test/mochitest/test_currency_amount.html
+++ b/browser/components/payments/test/mochitest/test_currency_amount.html
@@ -22,18 +22,16 @@ Test the currency-amount component
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the currency-amount component **/
 
 import "../../res/components/currency-amount.js";
 
-/* import-globals-from payments_common.js */
-
 let amount1 = document.getElementById("amount1");
 
 add_task(async function test_no_value() {
   ok(amount1, "amount1 exists");
   is(amount1.textContent, "", "Initially empty");
 
   amount1.currency = "USD";
   await asyncElementRendered();
--- a/browser/components/payments/test/mochitest/test_labelled_checkbox.html
+++ b/browser/components/payments/test/mochitest/test_labelled_checkbox.html
@@ -21,17 +21,16 @@ Test the labelled-checkbox component
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the labelled-checkbox component **/
 
-/* import-globals-from payments_common.js */
 import "../../res/components/labelled-checkbox.js";
 
 let box0 = document.getElementById("box0");
 let box1 = document.getElementById("box1");
 
 add_task(async function test_no_values() {
   ok(box0, "box0 exists");
   is(box0.label, null, "Initially un-labelled");
--- a/browser/components/payments/test/mochitest/test_order_details.html
+++ b/browser/components/payments/test/mochitest/test_order_details.html
@@ -32,18 +32,16 @@
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the order-details component **/
 
-/* import-globals-from payments_common.js */
-
 import OrderDetails from "../../res/containers/order-details.js";
 import {requestStore} from "../../res/mixins/PaymentStateSubscriberMixin.js";
 
 let orderDetails = document.querySelector("order-details");
 let emptyState = requestStore.getState();
 
 function setup() {
   let initialState = deepClone(emptyState);
--- a/browser/components/payments/test/mochitest/test_payer_address_picker.html
+++ b/browser/components/payments/test/mochitest/test_payer_address_picker.html
@@ -25,18 +25,16 @@ Test the paymentOptions address-picker
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the payer requested details functionality **/
 
-/* import-globals-from payments_common.js */
-
 import PaymentDialog from "../../res/containers/payment-dialog.js";
 
 function getVisiblePickerOptions(picker) {
   let select = picker.querySelector(":scope > rich-select");
   let options = select.querySelectorAll("address-option");
   let visibleOptions = Array.from(options).filter(isVisible);
   return visibleOptions;
 }
--- a/browser/components/payments/test/mochitest/test_payment_details_item.html
+++ b/browser/components/payments/test/mochitest/test_payment_details_item.html
@@ -21,17 +21,16 @@ Test the payment-details-item component
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the payment-details-item component **/
 
-/* import-globals-from payments_common.js */
 import "../../res/components/payment-details-item.js";
 
 let item1 = document.getElementById("item1");
 let item2 = document.getElementById("item2");
 
 add_task(async function test_no_value() {
   ok(item1, "item1 exists");
   is(item1.textContent, "", "Initially empty");
--- a/browser/components/payments/test/mochitest/test_payment_dialog.html
+++ b/browser/components/payments/test/mochitest/test_payment_dialog.html
@@ -24,17 +24,16 @@ Test the payment-dialog custom element
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the payment-dialog element **/
 
 /* global sinon */
-/* import-globals-from payments_common.js */
 
 import PaymentDialog from "../../res/containers/payment-dialog.js";
 
 let el1;
 
 let completionStates = [
     ["processing", "Processing"],
     ["success", "Done"],
--- a/browser/components/payments/test/mochitest/test_payment_method_picker.html
+++ b/browser/components/payments/test/mochitest/test_payment_method_picker.html
@@ -25,17 +25,16 @@ Test the payment-method-picker component
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the payment-method-picker component **/
 
-/* import-globals-from payments_common.js */
 import "../../res/components/basic-card-option.js";
 import "../../res/containers/payment-method-picker.js";
 
 let picker1 = document.getElementById("picker1");
 
 add_task(async function test_empty() {
   ok(picker1, "Check picker1 exists");
   let {savedBasicCards} = picker1.requestStore.getState();
--- a/browser/components/payments/test/mochitest/test_rich_select.html
+++ b/browser/components/payments/test/mochitest/test_rich_select.html
@@ -76,18 +76,16 @@ Test the rich-select component
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the rich-select address-option component **/
 
-/* import-globals-from payments_common.js */
-
 import AddressOption from "../../res/components/address-option.js";
 import BasicCardOption from "../../res/components/basic-card-option.js";
 import RichSelect from "../../res/components/rich-select.js";
 
 let select1 = document.getElementById("select1");
 let option1 = document.getElementById("option1");
 let option2 = document.getElementById("option2");
 let option3 = document.getElementById("option3");
--- a/browser/components/payments/test/mochitest/test_shipping_option_picker.html
+++ b/browser/components/payments/test/mochitest/test_shipping_option_picker.html
@@ -24,18 +24,16 @@ Test the shipping-option-picker componen
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 </pre>
 <script type="module">
 /** Test the shipping-option-picker component **/
 
-/* import-globals-from payments_common.js */
-
 import "../../res/containers/shipping-option-picker.js";
 
 let picker1 = document.getElementById("picker1");
 
 add_task(async function test_empty() {
   ok(picker1, "Check picker1 exists");
   let state = picker1.requestStore.getState();
   let {shippingOptions} = state && state.request && state.request.paymentDetails;
--- a/browser/extensions/formautofill/test/mochitest/test_address_level_1_submission.html
+++ b/browser/extensions/formautofill/test/mochitest/test_address_level_1_submission.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: Test autofill submission for a country without address-level1
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 const TEST_ADDRESSES = [{
   organization: "Mozilla",
   "street-address": "123 Sesame Street",
   "address-level1": "AL",
   country: "DE",
--- a/browser/extensions/formautofill/test/mochitest/test_autofocus_form.html
+++ b/browser/extensions/formautofill/test/mochitest/test_autofocus_form.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: autocomplete on an autofocus form
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 let MOCK_STORAGE = [{
   organization: "Sesame Street",
   "street-address": "123 Sesame Street.",
   tel: "1-345-345-3456",
 }, {
--- a/browser/extensions/formautofill/test/mochitest/test_basic_autocomplete_form.html
+++ b/browser/extensions/formautofill/test/mochitest/test_basic_autocomplete_form.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: simple form address autofill
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 let MOCK_STORAGE = [{
   organization: "Sesame Street",
   "street-address": "123 Sesame Street.\n2-line\n3-line",
   tel: "+13453453456",
   country: "US",
--- a/browser/extensions/formautofill/test/mochitest/test_basic_creditcard_autocomplete_form.html
+++ b/browser/extensions/formautofill/test/mochitest/test_basic_creditcard_autocomplete_form.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: simple form credit card autofill
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 const MOCK_STORAGE = [{
   "cc-name": "John Doe",
   "cc-number": "4929001587121045",
   "cc-exp-month": 4,
   "cc-exp-year": 2017,
--- a/browser/extensions/formautofill/test/mochitest/test_clear_form.html
+++ b/browser/extensions/formautofill/test/mochitest/test_clear_form.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: clear form button
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 const MOCK_ADDR_STORAGE = [{
   organization: "Sesame Street",
   "street-address": "2 Harrison St\nline2\nline3",
   tel: "+13453453456",
 }, {
--- a/browser/extensions/formautofill/test/mochitest/test_creditcard_autocomplete_off.html
+++ b/browser/extensions/formautofill/test/mochitest/test_creditcard_autocomplete_off.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: simple form credit card autofill
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 const MOCK_STORAGE = [{
   "cc-name": "John Doe",
   "cc-number": "4929001587121045",
   "cc-exp-month": 4,
   "cc-exp-year": 2017,
--- a/browser/extensions/formautofill/test/mochitest/test_form_changes.html
+++ b/browser/extensions/formautofill/test/mochitest/test_form_changes.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: autocomplete on an autofocus form
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 let MOCK_STORAGE = [{
   name: "John Doe",
   organization: "Sesame Street",
   "address-level2": "Austin",
   tel: "+13453453456",
--- a/browser/extensions/formautofill/test/mochitest/test_formautofill_preview_highlight.html
+++ b/browser/extensions/formautofill/test/mochitest/test_formautofill_preview_highlight.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: preview and highlight
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 const MOCK_STORAGE = [{
   organization: "Sesame Street",
   "street-address": "123 Sesame Street.",
   tel: "+13453453456",
 }, {
--- a/browser/extensions/formautofill/test/mochitest/test_multi_locale_CA_address_form.html
+++ b/browser/extensions/formautofill/test/mochitest/test_multi_locale_CA_address_form.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: simple form address autofill
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 let MOCK_STORAGE = [{
   organization: "Mozilla Vancouver",
   "street-address": "163 W Hastings St.\n#209\n3-line",
   tel: "+17787851540",
   country: "CA",
--- a/browser/extensions/formautofill/test/mochitest/test_multiple_forms.html
+++ b/browser/extensions/formautofill/test/mochitest/test_multiple_forms.html
@@ -8,19 +8,17 @@
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 let MOCK_STORAGE = [{
   "given-name": "John",
   "additional-name": "R",
   "family-name": "Smith",
 }];
--- a/browser/extensions/formautofill/test/mochitest/test_on_address_submission.html
+++ b/browser/extensions/formautofill/test/mochitest/test_on_address_submission.html
@@ -9,19 +9,17 @@
   <script type="text/javascript" src="formautofill_common.js"></script>
   <script type="text/javascript" src="satchel_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Form autofill test: check if address is saved/updated correctly
 
 <script>
-/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 /* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
-/* import-globals-from formautofill_common.js */
 
 "use strict";
 
 let TEST_ADDRESSES = [{
   organization: "Sesame Street",
   "street-address": "123 Sesame Street.",
   tel: "+13453453456",
 }, {
--- a/devtools/client/aboutdebugging/test/browser_service_workers_push_service.js
+++ b/devtools/client/aboutdebugging/test/browser_service_workers_push_service.js
@@ -14,18 +14,16 @@ const TAB_URL = URL_ROOT + "service-work
 const FAKE_ENDPOINT = "https://fake/endpoint";
 
 const PushService = Cc["@mozilla.org/push/Service;1"]
   .getService(Ci.nsIPushService).wrappedJSObject;
 
 add_task(async function() {
   info("Turn on workers via mochitest http.");
   await enableServiceWorkerDebugging();
-  // Enable the push service.
-  await pushPref("dom.push.connection.enabled", true);
 
   info("Mock the push service");
   PushService.service = {
     _registrations: new Map(),
     _notify(scope) {
       Services.obs.notifyObservers(
         null,
         PushService.subscriptionModifiedTopic,
--- a/devtools/client/shared/components/test/mochitest/test_searchbox-with-autocomplete.html
+++ b/devtools/client/shared/components/test/mochitest/test_searchbox-with-autocomplete.html
@@ -12,17 +12,16 @@ Test the searchbox and autocomplete-popu
   <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
   <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <script src="head.js"></script>
 <script>
-/* import-globals-from head.js */
 "use strict";
 window.onload = async function () {
   /**
    * Takes a DOMNode with its children as list items,
    * Typically UL > LI and each item's text value is
    * compared with the reference item's value as a test
    *
    * @params {Node} - Node to be compared
--- a/devtools/client/shared/components/test/mochitest/test_searchbox.html
+++ b/devtools/client/shared/components/test/mochitest/test_searchbox.html
@@ -12,17 +12,16 @@ Test the searchbox component
   <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
   <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <script src="head.js"></script>
 <script>
-/* import-globals-from head.js */
 "use strict";
 window.onload = function () {
   let React = browserRequire("devtools/client/shared/vendor/react");
   let SearchBox = React.createFactory(
     browserRequire("devtools/client/shared/components/SearchBox")
   );
   ok(SearchBox, "Got the SearchBox factory");
 
--- a/devtools/client/shared/components/test/mochitest/test_stack-trace-source-maps.html
+++ b/devtools/client/shared/components/test/mochitest/test_stack-trace-source-maps.html
@@ -11,17 +11,16 @@ Test the rendering of a stack trace with
   <title>StackTrace component test</title>
   <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <script src="head.js"></script>
 <script>
-/* import-globals-from head.js */
 "use strict";
 
 window.onload = function () {
   let ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
   let React = browserRequire("devtools/client/shared/vendor/react");
   let StackTrace = React.createFactory(
     browserRequire("devtools/client/shared/components/StackTrace")
   );
--- a/devtools/client/shared/components/test/mochitest/test_stack-trace.html
+++ b/devtools/client/shared/components/test/mochitest/test_stack-trace.html
@@ -11,17 +11,16 @@ Test the rendering of a stack trace
   <title>StackTrace component test</title>
   <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script src="chrome://mochikit/content/tests/SimpleTest/AddTask.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
 <script src="head.js"></script>
 <script>
-/* import-globals-from head.js */
 "use strict";
 
 window.onload = function() {
   const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
   const React = browserRequire("devtools/client/shared/vendor/react");
   const StackTrace = React.createFactory(
     browserRequire("devtools/client/shared/components/StackTrace")
   );
--- a/devtools/client/webide/test/test_device_preferences.html
+++ b/devtools/client/webide/test/test_device_preferences.html
@@ -10,17 +10,16 @@
     <script type="application/javascript" src="head.js"></script>
     <script type="application/javascript" src="device_front_shared.js"></script>
     <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   </head>
 
   <body>
 
     <script type="application/javascript">
-      /* import-globals-from device_front_shared.js */
       window.onload = function() {
         SimpleTest.waitForExplicitFinish();
 
         (async function() {
           DebuggerServer.init();
           DebuggerServer.registerAllActors();
 
           const win = await openWebIDE();
--- a/dom/indexedDB/test/browser_forgetThisSiteAdd.html
+++ b/dom/indexedDB/test/browser_forgetThisSiteAdd.html
@@ -2,17 +2,16 @@
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
   <head>
     <title>Indexed Database Test</title>
 
     <script type="text/javascript">
-      /* import-globals-from browserHelpers.js */
       function* testSteps()
       {
         let request = indexedDB.open("browser_forgetThisSite.js", 11);
         request.onerror = grabEventAndContinueHandler;
         request.onupgradeneeded = grabEventAndContinueHandler;
         let event = yield undefined;
 
         if (event.type == "error") {
--- a/dom/indexedDB/test/browser_forgetThisSiteGet.html
+++ b/dom/indexedDB/test/browser_forgetThisSiteGet.html
@@ -2,17 +2,16 @@
   Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
   <head>
     <title>Indexed Database Test</title>
 
     <script type="text/javascript">
-      /* import-globals-from browserHelpers.js */
       function* testSteps()
       {
         let request = indexedDB.open("browser_forgetThisSite.js");
         request.onerror = grabEventAndContinueHandler;
         request.onsuccess = grabEventAndContinueHandler;
         let event = yield undefined;
 
         if (event.type == "error") {
--- a/dom/indexedDB/test/browser_permissionsPrompt.html
+++ b/dom/indexedDB/test/browser_permissionsPrompt.html
@@ -3,17 +3,16 @@
   http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html>
   <head>
     <meta charset=UTF-8>
     <title>Indexed Database Test</title>
 
     <script type="text/javascript">
-      /* import-globals-from browserHelpers.js */
       function* testSteps()
       {
         const name = window.location.pathname;
 
         let request = indexedDB.open(name, { version: 1,
                                              storage: "persistent" });
         request.onerror = grabEventAndContinueHandler;
         request.onsuccess = grabEventAndContinueHandler;
--- a/dom/indexedDB/test/test_bfcache.html
+++ b/dom/indexedDB/test/test_bfcache.html
@@ -4,18 +4,16 @@
 -->
 <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 */
-
     function* testSteps()
     {
       window.onmessage = grabEventAndContinueHandler;
 
       let testWin = window.open("bfcache_page1.html", "testWin");
       var event = yield undefined;
       is(event.data, "go", "set up database successfully");
 
--- a/dom/indexedDB/test/test_blob_simple.html
+++ b/dom/indexedDB/test/test_blob_simple.html
@@ -5,17 +5,16 @@
 <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 */
   function* testSteps()
   {
     info("Setting up test fixtures: create an IndexedDB database and object store.");
 
     let request = indexedDB.open(window.location.pathname, 1);
     request.onerror = errorHandler;
     request.onupgradeneeded = grabEventAndContinueHandler;
     request.onsuccess = unexpectedSuccessHandler;
--- a/dom/indexedDB/test/test_blob_worker_xhr_post.html
+++ b/dom/indexedDB/test/test_blob_worker_xhr_post.html
@@ -5,17 +5,16 @@
 <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 */
   function* testSteps()
   {
     const BLOB_DATA = ["fun ", "times ", "all ", "around!"];
     const BLOB_TYPE = "text/plain";
     const BLOB_SIZE = BLOB_DATA.join("").length;
 
     info("Setting up");
 
--- a/dom/indexedDB/test/test_blob_worker_xhr_post_multifile.html
+++ b/dom/indexedDB/test/test_blob_worker_xhr_post_multifile.html
@@ -5,17 +5,16 @@
 <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 */
   /**
    * Create a composite/multi-file Blob on the worker, then post it as an XHR
    * payload and ensure that we don't hang/generate an assertion/etc. but
    * instead generate the expected 404.  This test is basically the same as
    * test_blob_worker_xhr_post.html except for the composite Blob.
    */
   function* testSteps()
   {
--- a/dom/indexedDB/test/test_blob_worker_xhr_read.html
+++ b/dom/indexedDB/test/test_blob_worker_xhr_read.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>Indexed Database Blob Read From Worker</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 */
   /**
    * Create an IndexedDB-backed Blob, send it to the worker, try and read the
    * contents of the Blob from the worker using an XHR.  Ideally, we don't
    * deadlock the main thread.
    */
   function* testSteps()
   {
     const BLOB_DATA = ["Green"];
--- a/dom/indexedDB/test/test_blob_worker_xhr_read_slice.html
+++ b/dom/indexedDB/test/test_blob_worker_xhr_read_slice.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>Indexed Database Blob Read From Worker</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 */
   /**
    * Create an IndexedDB-backed Blob, send it to the worker, try and read the
    * *SLICED* contents of the Blob from the worker using an XHR.  This is
    * (as of the time of writing this) basically the same as
    * test_blob_worker_xhr_read.html but with slicing added.
    */
   function* testSteps()
   {
--- a/dom/indexedDB/test/test_file_array.html
+++ b/dom/indexedDB/test/test_file_array.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
     const b1 = getRandomBlob(10000);
 
--- a/dom/indexedDB/test/test_file_cross_database_copying.html
+++ b/dom/indexedDB/test/test_file_cross_database_copying.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const databaseInfo = [
       { name: window.location.pathname + "1" },
       { name: window.location.pathname + "2" }
     ];
--- a/dom/indexedDB/test/test_file_delete.html
+++ b/dom/indexedDB/test/test_file_delete.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_file_os_delete.html
+++ b/dom/indexedDB/test/test_file_os_delete.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_file_put_deleted.html
+++ b/dom/indexedDB/test/test_file_put_deleted.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   /**
    * Test that a put of a file-backed Blob/File whose backing file has been
    * deleted results in a failure of that put failure.
    *
    * In order to create a file-backed Blob and ensure that we actually try and
    * copy its contents (rather than triggering a reference-count increment), we
    * use two separate databases.  This test is derived from
    * test_file_cross_database_copying.html.
--- a/dom/indexedDB/test/test_file_put_get_object.html
+++ b/dom/indexedDB/test/test_file_put_get_object.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
     const blob = getRandomBlob(1000);
     const file = getRandomFile("random.bin", 100000);
--- a/dom/indexedDB/test/test_file_put_get_values.html
+++ b/dom/indexedDB/test/test_file_put_get_values.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_file_replace.html
+++ b/dom/indexedDB/test/test_file_replace.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
     const blobData = { key: 42, blobs: [] };
 
--- a/dom/indexedDB/test/test_file_resurrection_delete.html
+++ b/dom/indexedDB/test/test_file_resurrection_delete.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_file_resurrection_transaction_abort.html
+++ b/dom/indexedDB/test/test_file_resurrection_transaction_abort.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_file_sharing.html
+++ b/dom/indexedDB/test/test_file_sharing.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreInfo = [
       { name: "Blobs", options: { } },
--- a/dom/indexedDB/test/test_file_transaction_abort.html
+++ b/dom/indexedDB/test/test_file_transaction_abort.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_filehandle_compat.html
+++ b/dom/indexedDB/test/test_filehandle_compat.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_disabled_pref.html
+++ b/dom/indexedDB/test/test_filehandle_disabled_pref.html
@@ -8,18 +8,16 @@
 
     <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 file.js */
-      /* import-globals-from helpers.js */
       function* testSteps()
       {
         const databaseName = window.location.pathname;
         const databaseVersion = 1;
         const objectStoreName = "foo";
         const mutableFileName = "bar";
         const mutableFileKey = 42;
 
--- a/dom/indexedDB/test/test_filehandle_getFile.html
+++ b/dom/indexedDB/test/test_filehandle_getFile.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_iteration.html
+++ b/dom/indexedDB/test/test_filehandle_iteration.html
@@ -5,17 +5,16 @@
 <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 */
   function* testSteps()
   {
     const dbName = window.location.pathname;
     const dbVersion = 1;
     const objectStoreName = "foo";
     const entryCount = 10;
 
     let request = indexedDB.open(dbName, dbVersion);
--- a/dom/indexedDB/test/test_filehandle_lifetimes.html
+++ b/dom/indexedDB/test/test_filehandle_lifetimes.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_lifetimes_nested.html
+++ b/dom/indexedDB/test/test_filehandle_lifetimes_nested.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_location.html
+++ b/dom/indexedDB/test/test_filehandle_location.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_ordering.html
+++ b/dom/indexedDB/test/test_filehandle_ordering.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_overlapping.html
+++ b/dom/indexedDB/test/test_filehandle_overlapping.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_progress_events.html
+++ b/dom/indexedDB/test/test_filehandle_progress_events.html
@@ -5,18 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     var testBuffer = getRandomBuffer(100000);
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_filehandle_readonly_exceptions.html
+++ b/dom/indexedDB/test/test_filehandle_readonly_exceptions.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_request_readyState.html
+++ b/dom/indexedDB/test/test_filehandle_request_readyState.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     is(request.readyState, "pending", "Correct readyState");
 
     request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_filehandle_serialization.html
+++ b/dom/indexedDB/test/test_filehandle_serialization.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const databaseInfo = [
       { name: window.location.pathname + "1" },
       { name: window.location.pathname + "2" }
     ];
--- a/dom/indexedDB/test/test_filehandle_store_snapshot.html
+++ b/dom/indexedDB/test/test_filehandle_store_snapshot.html
@@ -5,18 +5,16 @@
 <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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
--- a/dom/indexedDB/test/test_filehandle_stream_tracking.html
+++ b/dom/indexedDB/test/test_filehandle_stream_tracking.html
@@ -5,18 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     var testBuffer = getRandomBuffer(100000);
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_filehandle_success_events_after_abort.html
+++ b/dom/indexedDB/test/test_filehandle_success_events_after_abort.html
@@ -5,17 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
--- a/dom/indexedDB/test/test_filehandle_truncate.html
+++ b/dom/indexedDB/test/test_filehandle_truncate.html
@@ -5,18 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     var testBuffer = getRandomBuffer(100000);
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_filehandle_workers.html
+++ b/dom/indexedDB/test/test_filehandle_workers.html
@@ -5,18 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     let testBuffer = getRandomBuffer(100000);
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_filehandle_write_read_data.html
+++ b/dom/indexedDB/test/test_filehandle_write_read_data.html
@@ -5,18 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     var testString = "Lorem ipsum his ponderum delicatissimi ne, at noster dolores urbanitas pro, cibo elaboraret no his. Ea dicunt maiorum usu. Ad appareat facilisis mediocritatem eos. Tale graeci mentitum in eos, hinc insolens at nam. Graecis nominavi aliquyam eu vix. Id solet assentior sadipscing pro. Et per atqui graecis, usu quot viris repudiandae ei, mollis evertitur an nam. At nam dolor ignota, liber labore omnesque ea mei, has movet voluptaria in. Vel an impetus omittantur. Vim movet option salutandi ex, ne mei ignota corrumpit. Mucius comprehensam id per. Est ea putant maiestatis.";
     for (let i = 0; i < 5; i++) {
       testString += testString;
     }
--- a/dom/indexedDB/test/test_getFileId.html
+++ b/dom/indexedDB/test/test_getFileId.html
@@ -5,18 +5,16 @@
 <html>
 <head>
   <title>File Handle 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 file.js */
-  /* import-globals-from helpers.js */
   function* testSteps()
   {
     let id = getFileId(null);
     ok(id == -1, "Correct id");
 
     id = getFileId(getRandomBlob(100));
     ok(id == -1, "Correct id");
 
--- a/dom/indexedDB/test/test_globalObjects_content.html
+++ b/dom/indexedDB/test/test_globalObjects_content.html
@@ -5,17 +5,16 @@
 <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 */
   function* testSteps()
   {
     const name = window.location.pathname;
 
     // Test for IDBKeyRange and indexedDB availability in content windows.
     let keyRange = IDBKeyRange.only(42);
     ok(keyRange, "Got keyRange");
 
--- a/dom/indexedDB/test/test_leaving_page.html
+++ b/dom/indexedDB/test/test_leaving_page.html
@@ -10,17 +10,16 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 
 <body onload="runTest();">
   <iframe id="inner"></iframe>
   <a id="a" href="leaving_page_iframe.html"></a>
 
   <script type="text/javascript">
-    /* import-globals-from helpers.js */
     window.addEventListener("message", function(e) {
       ok(false, "gotmessage: " + e.data);
     });
 
     function* testSteps()
     {
       var iframe = $("inner");
       iframe.src = "leaving_page_iframe.html";
--- a/dom/indexedDB/test/test_open_for_principal.html
+++ b/dom/indexedDB/test/test_open_for_principal.html
@@ -5,17 +5,16 @@
 <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 */
   function* testSteps()
   {
     is("open" in indexedDB, true, "open() defined");
     is("openForPrincipal" in indexedDB, false, "openForPrincipal() not defined");
 
     is("deleteDatabase" in indexedDB, true, "deleteDatabase() defined");
     is("deleteForPrincipal" in indexedDB, false, "deleteForPrincipal() not defined");
 
--- a/dom/indexedDB/test/test_persistenceType.html
+++ b/dom/indexedDB/test/test_persistenceType.html
@@ -5,17 +5,16 @@
 <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 */
     function* testSteps()
     {
       const name = window.location.pathname;
       const version = 1;
       const storages = ["persistent", "temporary", "default"];
 
       const objectStoreName = "Foo";
       const data = { key: 1, value: "bar" };
new file mode 100644
--- /dev/null
+++ b/dom/push/PushBroadcastService.jsm
@@ -0,0 +1,216 @@
+/* jshint moz: true, esnext: true */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/osfile.jsm");
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "JSONFile", "resource://gre/modules/JSONFile.jsm");
+
+var EXPORTED_SYMBOLS = ["pushBroadcastService"];
+
+// We are supposed to ignore any updates with this version.
+// FIXME: what is the actual "dummy" version?
+// See bug 1467550.
+const DUMMY_VERSION_STRING = "dummy";
+
+XPCOMUtils.defineLazyGetter(this, "console", () => {
+  let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
+  return new ConsoleAPI({
+    maxLogLevelPref: "dom.push.loglevel",
+    prefix: "BroadcastService",
+  });
+});
+ChromeUtils.defineModuleGetter(this, "PushService", "resource://gre/modules/PushService.jsm");
+
+class InvalidSourceInfo extends Error {
+  constructor(message) {
+    super(message);
+    this.name = 'InvalidSourceInfo';
+  }
+}
+
+const BROADCAST_SERVICE_VERSION = 1;
+
+var BroadcastService = class {
+  constructor(pushService, path) {
+    this.pushService = pushService;
+    this.jsonFile = new JSONFile({
+      path,
+      dataPostProcessor: this._initializeJSONFile,
+    });
+    this.initializePromise = this.jsonFile.load();
+  }
+
+  /**
+   * Convert the listeners from our on-disk format to the format
+   * needed by a hello message.
+   */
+  async getListeners() {
+    await this.initializePromise;
+    return Object.entries(this.jsonFile.data.listeners).reduce((acc, [k, v]) => {
+      acc[k] = v.version;
+      return acc;
+    }, {});
+  }
+
+  _initializeJSONFile(data) {
+    if (!data.version) {
+      data.version = BROADCAST_SERVICE_VERSION;
+    }
+    if (!data.hasOwnProperty("listeners")) {
+      data.listeners = {};
+    }
+    return data;
+  }
+
+  /**
+   * Reset to a state akin to what you would get in a new profile.
+   * In particular, wipe anything from storage.
+   *
+   * Used mainly for testing.
+   */
+  async _resetListeners() {
+    await this.initializePromise;
+    this.jsonFile.data = this._initializeJSONFile({});
+    this.initializePromise = Promise.resolve();
+  }
+
+  /**
+   * Ensure that a sourceInfo is correct (has the expected fields).
+   */
+  _validateSourceInfo(sourceInfo) {
+    const {moduleURI, symbolName} = sourceInfo;
+    if (typeof moduleURI !== "string") {
+      throw new InvalidSourceInfo(`moduleURI must be a string (got ${typeof moduleURI})`);
+    }
+    if (typeof symbolName !== "string") {
+      throw new InvalidSourceInfo(`symbolName must be a string (got ${typeof symbolName})`);
+    }
+  }
+
+  /**
+   * Add an entry for a given listener if it isn't present, or update
+   * one if it is already present.
+   *
+   * Note that this means only a single listener can be set for a
+   * given subscription. This is a limitation in the current API that
+   * stems from the fact that there can only be one source of truth
+   * for the subscriber's version. As a workaround, you can define a
+   * listener which calls multiple other listeners.
+   *
+   * @param {string} broadcastId The broadcastID to listen for
+   * @param {string} version The most recent version we have for
+   *   updates from this broadcastID
+   * @param {Object} sourceInfo A description of the handler for
+   *   updates on this broadcastID
+   */
+  async addListener(broadcastId, version, sourceInfo) {
+    console.info("addListener: adding listener", broadcastId, version, sourceInfo);
+    await this.initializePromise;
+    this._validateSourceInfo(sourceInfo);
+    if (typeof version !== "string") {
+      throw new TypeError("version should be a string");
+    }
+    const isNew = !this.jsonFile.data.listeners.hasOwnProperty(broadcastId);
+
+    // Update listeners before telling the pushService to subscribe,
+    // in case it would disregard the update in the small window
+    // between getting listeners and setting state to RUNNING.
+    this.jsonFile.data.listeners[broadcastId] = {version, sourceInfo};
+    this.jsonFile.saveSoon();
+
+    if (isNew) {
+      await this.pushService.subscribeBroadcast(broadcastId, version);
+    }
+  }
+
+  async receivedBroadcastMessage(broadcasts) {
+    console.info("receivedBroadcastMessage:", broadcasts);
+    await this.initializePromise;
+    for (const broadcastId in broadcasts) {
+      const version = broadcasts[broadcastId];
+      if (version === DUMMY_VERSION_STRING) {
+        console.info("Ignoring", version, "because it's the dummy version");
+        continue;
+      }
+      // We don't know this broadcastID. This is probably a bug?
+      if (!this.jsonFile.data.listeners.hasOwnProperty(broadcastId)) {
+        console.warn("receivedBroadcastMessage: unknown broadcastId", broadcastId);
+        continue;
+      }
+
+      const {sourceInfo} = this.jsonFile.data.listeners[broadcastId];
+      try {
+        this._validateSourceInfo(sourceInfo);
+      } catch (e) {
+        console.error("receivedBroadcastMessage: malformed sourceInfo", sourceInfo, e);
+        continue;
+      }
+
+      const {moduleURI, symbolName} = sourceInfo;
+
+      const module = {};
+      try {
+        ChromeUtils.import(moduleURI, module);
+      } catch (e) {
+        console.error("receivedBroadcastMessage: couldn't invoke", broadcastId,
+                      "because import of module", moduleURI,
+                      "failed", e);
+        continue;
+      }
+
+      if (!module[symbolName]) {
+        console.error("receivedBroadcastMessage: couldn't invoke", broadcastId,
+                      "because module", moduleName, "missing attribute", symbolName);
+        continue;
+      }
+
+      const handler = module[symbolName];
+
+      if (!handler.receivedBroadcastMessage) {
+        console.error("receivedBroadcastMessage: couldn't invoke", broadcastId,
+                      "because handler returned by", `${moduleURI}.${symbolName}`,
+                      "has no receivedBroadcastMessage method");
+        continue;
+      }
+
+      try {
+        await handler.receivedBroadcastMessage(version, broadcastId);
+      } catch (e) {
+        console.error("receivedBroadcastMessage: handler for", broadcastId,
+                      "threw error:", e);
+        continue;
+      }
+
+      // Broadcast message applied successfully. Update the version we
+      // received if it's different than the one we had.  We don't
+      // enforce an ordering here (i.e. we use != instead of <)
+      // because we don't know what the ordering of the service's
+      // versions is going to be.
+      if (this.jsonFile.data.listeners[broadcastId].version != version) {
+        this.jsonFile.data.listeners[broadcastId].version = version;
+        this.jsonFile.saveSoon();
+      }
+    }
+  }
+
+  // For test only.
+  _saveImmediately() {
+    return this.jsonFile._save();
+  }
+}
+
+function initializeBroadcastService() {
+  // Fallback path for xpcshell tests.
+  let path = "broadcast-listeners.json";
+  if (OS.Constants.Path.profileDir) {
+    // Real path for use in a real profile.
+    path = OS.Path.join(OS.Constants.Path.profileDir, path);
+  }
+  return new BroadcastService(PushService, path);
+};
+
+var pushBroadcastService = initializeBroadcastService();
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -30,16 +30,17 @@ const CONNECTION_PROTOCOLS = (function()
 })();
 
 XPCOMUtils.defineLazyServiceGetter(this, "gPushNotifier",
                                    "@mozilla.org/push/Notifier;1",
                                    "nsIPushNotifier");
 XPCOMUtils.defineLazyServiceGetter(this, "eTLDService",
                                    "@mozilla.org/network/effective-tld-service;1",
                                    "nsIEffectiveTLDService");
+ChromeUtils.defineModuleGetter(this, "pushBroadcastService", "resource://gre/modules/PushBroadcastService.jsm");
 
 var EXPORTED_SYMBOLS = ["PushService"];
 
 XPCOMUtils.defineLazyGetter(this, "console", () => {
   let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
   return new ConsoleAPI({
     maxLogLevelPref: "dom.push.loglevel",
     prefix: "PushService",
@@ -211,23 +212,34 @@ var PushService = {
     if (this._state == PUSH_SERVICE_RUNNING) {
       // PushService was not in the offline state, but got notification to
       // go online (a offline notification has not been sent).
       // Disconnect first.
       this._service.disconnect();
     }
 
     let records = await this.getAllUnexpired();
+    let broadcastListeners = await pushBroadcastService.getListeners();
 
+    // In principle, a listener could be added to the
+    // pushBroadcastService here, after we have gotten listeners and
+    // before we're RUNNING, but this can't happen in practice because
+    // the only caller that can add listeners is PushBroadcastService,
+    // and it waits on the same promise we are before it can add
+    // listeners. If PushBroadcastService gets woken first, it will
+    // update the value that is eventually returned from
+    // getListeners.
     this._setState(PUSH_SERVICE_RUNNING);
 
     if (records.length > 0 || prefs.get("alwaysConnect")) {
       // Connect if we have existing subscriptions, or if the always-on pref
-      // is set.
-      this._service.connect(records);
+      // is set. We gate on the pref to let us do load testing before
+      // turning it on for everyone, but if the user has push
+      // subscriptions, we need to connect them anyhow.
+      this._service.connect(records, broadcastListeners);
     }
   },
 
   _changeStateConnectionEnabledEvent: function(enabled) {
     console.debug("changeStateConnectionEnabledEvent()", enabled);
 
     if (this._state < PUSH_SERVICE_CONNECTION_DISABLE &&
         this._state != PUSH_SERVICE_ACTIVATING) {
@@ -457,23 +469,23 @@ var PushService = {
     this._setState(PUSH_SERVICE_ACTIVATING);
 
     prefs.observe("serverURL", this);
     Services.obs.addObserver(this, "quit-application");
 
     if (options.serverURI) {
       // this is use for xpcshell test.
 
-      this._stateChangeProcessEnqueue(_ =>
+      return this._stateChangeProcessEnqueue(_ =>
         this._changeServerURL(options.serverURI, STARTING_SERVICE_EVENT, options));
 
     } else {
       // This is only used for testing. Different tests require connecting to
       // slightly different URLs.
-      this._stateChangeProcessEnqueue(_ =>
+      return this._stateChangeProcessEnqueue(_ =>
         this._changeServerURL(prefs.get("serverURL"), STARTING_SERVICE_EVENT));
     }
   },
 
   _startObservers: function() {
     console.debug("startObservers()");
 
     if (this._state != PUSH_SERVICE_ACTIVATING) {
@@ -736,16 +748,26 @@ var PushService = {
       return this._decryptAndNotifyApp(record, messageID, headers, data);
     }).catch(error => {
       console.error("receivedPushMessage: Error notifying app", error);
       return Ci.nsIPushErrorReporter.ACK_NOT_DELIVERED;
     });
   },
 
   /**
+   * Dispatches a broadcast notification to the BroadcastService.
+   */
+  receivedBroadcastMessage(message) {
+    pushBroadcastService.receivedBroadcastMessage(message.broadcasts)
+      .catch(e => {
+        console.error(e);
+      });;
+  },
+
+  /**
    * Updates a registration record after receiving a push message.
    *
    * @param {String} keyID The push registration ID.
    * @param {Function} updateFunc The function passed to `receivedPushMessage`.
    * @returns {Promise} Resolves with the updated record, or rejects if the
    *  record was not updated.
    */
   _updateRecordAfterPush(keyID, updateFunc) {
@@ -1053,16 +1075,31 @@ var PushService = {
           }
           throw new Error("Push subscription expired");
         }).then(_ => this._lookupOrPutPendingRequest(aPageRecord));
       }
       return record.toSubscription();
     });
   },
 
+  /*
+   * Called only by the PushBroadcastService on the receipt of a new
+   * subscription. Don't call this directly. Go through PushBroadcastService.
+   */
+  async subscribeBroadcast(broadcastId, version) {
+    if (this._state != PUSH_SERVICE_RUNNING) {
+      // Ignore any request to subscribe before we send a hello.
+      // We'll send all the broadcast listeners as part of the hello
+      // anyhow.
+      return;
+    }
+
+    await this._service.sendSubscribeBroadcast(broadcastId, version);
+  },
+
   /**
    * Called on message from the child process.
    *
    * Why is the record being deleted from the local database before the server
    * is told?
    *
    * Unregistration is for the benefit of the app and the AppServer
    * so that the AppServer does not keep pinging a channel the UserAgent isn't
--- a/dom/push/PushServiceAndroidGCM.jsm
+++ b/dom/push/PushServiceAndroidGCM.jsm
@@ -162,17 +162,17 @@ var PushServiceAndroidGCM = {
     Services.obs.removeObserver(this, "PushServiceAndroidGCM:ReceivedPushMessage");
     prefs.ignore("debug", this);
   },
 
   onAlarmFired: function() {
     // No action required.
   },
 
-  connect: function(records) {
+  connect: function(records, broadcastListeners) {
     console.debug("connect:", records);
     // It's possible for the registration or subscriptions backing the
     // PushService to not be registered with the underlying AndroidPushService.
     // Expire those that are unrecognized.
     return EventDispatcher.instance.sendRequestForResult({
       type: "PushServiceAndroidGCM:DumpSubscriptions",
     })
     .then(subscriptions => {
@@ -189,16 +189,20 @@ var PushServiceAndroidGCM = {
         return this._mainPushService.dropRegistrationAndNotifyApp(record.keyID)
           .catch(error => {
             console.error("connect: Error dropping registration", record.keyID, error);
           });
       }));
     });
   },
 
+  sendSubscribeBroadcast: async function(serviceId, version) {
+    // Not implemented yet
+  },
+
   isConnected: function() {
     return this._mainPushService != null;
   },
 
   disconnect: function() {
     console.debug("disconnect");
   },
 
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -421,20 +421,24 @@ var PushServiceHttp2 = {
 
   validServerURI: function(serverURI) {
     if (serverURI.scheme == "http") {
       return !!prefs.getBoolPref("testing.allowInsecureServerURL", false);
     }
     return serverURI.scheme == "https";
   },
 
-  connect: function(subscriptions) {
+  connect: function(subscriptions, broadcastListeners) {
     this.startConnections(subscriptions);
   },
 
+  sendSubscribeBroadcast: async function(serviceId, version) {
+    // Not implemented yet
+  },
+
   isConnected: function() {
     return this._mainPushService != null;
   },
 
   disconnect: function() {
     this._shutdownConnections(false);
   },
 
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -309,16 +309,18 @@ var PushServiceWebSocket = {
     this._ws.sendMsg(msg);
   },
 
   init: function(options, mainPushService, serverURI) {
     console.debug("init()");
 
     this._mainPushService = mainPushService;
     this._serverURI = serverURI;
+    // Filled in at connect() time
+    this._broadcastListeners = null;
 
     // Override the default WebSocket factory function. The returned object
     // must be null or satisfy the nsIWebSocketChannel interface. Used by
     // the tests to provide a mock WebSocket implementation.
     if (options.makeWebSocket) {
       this._makeWebSocket = options.makeWebSocket;
     }
 
@@ -507,18 +509,19 @@ var PushServiceWebSocket = {
       this._currentState = STATE_WAITING_FOR_WS_START;
     } catch(e) {
       console.error("beginWSSetup: Error opening websocket.",
         "asyncOpen failed", e);
       this._reconnect();
     }
   },
 
-  connect: function(records) {
-    console.debug("connect()");
+  connect: function(records, broadcastListeners) {
+    console.debug("connect()", broadcastListeners);
+    this._broadcastListeners = broadcastListeners;
     this._beginWSSetup();
   },
 
   isConnected: function() {
     return !!this._ws;
   },
 
   /**
@@ -561,16 +564,23 @@ var PushServiceWebSocket = {
       this._sendPendingRequests();
     };
 
     function finishHandshake() {
       this._UAID = reply.uaid;
       this._currentState = STATE_READY;
       prefs.observe("userAgentID", this);
 
+      // Handle broadcasts received in response to the "hello" message.
+      if (reply.broadcasts) {
+        // The reply isn't technically a broadcast message, but it has
+        // the shape of a broadcast message (it has a broadcasts field).
+        this._mainPushService.receivedBroadcastMessage(reply);
+      }
+
       this._dataEnabled = !!reply.use_webpush;
       if (this._dataEnabled) {
         this._mainPushService.getAllUnexpired().then(records =>
           Promise.all(records.map(record =>
             this._mainPushService.ensureCrypto(record).catch(error => {
               console.error("finishHandshake: Error updating record",
                 record.keyID, error);
             })
@@ -742,16 +752,20 @@ var PushServiceWebSocket = {
       if (typeof version === "number" && version >= 0) {
         // FIXME(nsm): this relies on app update notification being infallible!
         // eventually fix this
         this._receivedUpdate(update.channelID, version);
       }
     }
   },
 
+  _handleBroadcastReply: function(reply) {
+    this._mainPushService.receivedBroadcastMessage(reply);
+  },
+
   reportDeliveryError(messageID, reason) {
     console.debug("reportDeliveryError()");
     let code = kDELIVERY_REASON_TO_CODE[reason];
     if (!code) {
       throw new Error('Invalid delivery error reason');
     }
     let data = {messageType: 'nack',
                 version: messageID,
@@ -940,16 +954,17 @@ var PushServiceWebSocket = {
     if (this._currentState != STATE_WAITING_FOR_WS_START) {
       console.error("wsOnStart: NOT in STATE_WAITING_FOR_WS_START. Current",
         "state", this._currentState, "Skipping");
       return;
     }
 
     let data = {
       messageType: "hello",
+      broadcasts: this._broadcastListeners,
       use_webpush: true,
     };
 
     if (this._UAID) {
       data.uaid = this._UAID;
     }
 
     this._wsSendMessage(data);
@@ -1008,17 +1023,17 @@ var PushServiceWebSocket = {
 
     // If it is a ping, do not handle the message.
     if (doNotHandle) {
       return;
     }
 
     // A whitelist of protocol handlers. Add to these if new messages are added
     // in the protocol.
-    let handlers = ["Hello", "Register", "Unregister", "Notification"];
+    let handlers = ["Hello", "Register", "Unregister", "Notification", "Broadcast"];
 
     // Build up the handler name to call from messageType.
     // e.g. messageType == "register" -> _handleRegisterReply.
     let handlerName = reply.messageType[0].toUpperCase() +
                       reply.messageType.slice(1).toLowerCase();
 
     if (!handlers.includes(handlerName)) {
       console.warn("wsOnMessageAvailable: No whitelisted handler", handlerName,
@@ -1107,16 +1122,27 @@ var PushServiceWebSocket = {
       return null;
     }
     this._pendingRequests.delete(key);
     if (!this._hasPendingRequests()) {
       this._requestTimeoutTimer.cancel();
     }
     return request;
   },
+
+  sendSubscribeBroadcast(serviceId, version) {
+    let data = {
+      messageType: "broadcast_subscribe",
+      broadcasts: {
+        [serviceId]: version
+      },
+    };
+
+    this._queueRequest(data);
+  },
 };
 
 function PushRecordWebSocket(record) {
   PushRecord.call(this, record);
   this.channelID = record.channelID;
   this.version = record.version;
 }
 
--- a/dom/push/moz.build
+++ b/dom/push/moz.build
@@ -8,16 +8,17 @@ with Files("**"):
 
 EXTRA_COMPONENTS += [
     'Push.js',
     'Push.manifest',
     'PushComponents.js',
 ]
 
 EXTRA_JS_MODULES += [
+    'PushBroadcastService.jsm',
     'PushCrypto.jsm',
     'PushDB.jsm',
     'PushRecord.jsm',
     'PushService.jsm',
 ]
 
 if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
     # Everything but Fennec.
new file mode 100644
--- /dev/null
+++ b/dom/push/test/xpcshell/broadcast_handler.jsm
@@ -0,0 +1,16 @@
+"use strict";
+
+var EXPORTED_SYMBOLS = ["broadcastHandler"];
+
+var broadcastHandler = {
+  reset() {
+    this.notifications = [];
+
+    this.wasNotified = new Promise((resolve, reject) => {
+      this.receivedBroadcastMessage = function() {
+        resolve();
+        this.notifications.push(Array.from(arguments));
+      };
+    });
+  }
+};
--- a/dom/push/test/xpcshell/head.js
+++ b/dom/push/test/xpcshell/head.js
@@ -7,16 +7,18 @@ ChromeUtils.import('resource://gre/modul
 ChromeUtils.import('resource://gre/modules/Services.jsm');
 ChromeUtils.import('resource://gre/modules/Timer.jsm');
 ChromeUtils.import('resource://gre/modules/Preferences.jsm');
 ChromeUtils.import('resource://gre/modules/PlacesUtils.jsm');
 ChromeUtils.import('resource://gre/modules/ObjectUtils.jsm');
 
 ChromeUtils.defineModuleGetter(this, 'PlacesTestUtils',
                                'resource://testing-common/PlacesTestUtils.jsm');
+ChromeUtils.defineModuleGetter(this, 'pushBroadcastService',
+                               'resource://gre/modules/PushBroadcastService.jsm', {});
 XPCOMUtils.defineLazyServiceGetter(this, 'PushServiceComponent',
                                    '@mozilla.org/push/Service;1', 'nsIPushService');
 
 const serviceExports = ChromeUtils.import('resource://gre/modules/PushService.jsm', {});
 const servicePrefs = new Preferences('dom.push.');
 
 const WEBSOCKET_CLOSE_GOING_AWAY = 1001;
 
@@ -180,16 +182,17 @@ function compareAscending(a, b) {
  */
 function MockWebSocket(originalURI, handlers = {}) {
   this._originalURI = originalURI;
   this._onHello = handlers.onHello;
   this._onRegister = handlers.onRegister;
   this._onUnregister = handlers.onUnregister;
   this._onACK = handlers.onACK;
   this._onPing = handlers.onPing;
+  this._onBroadcastSubscribe = handlers.onBroadcastSubscribe;
 }
 
 MockWebSocket.prototype = {
   _originalURI: null,
   _onHello: null,
   _onRegister: null,
   _onUnregister: null,
   _onACK: null,
@@ -252,16 +255,23 @@ MockWebSocket.prototype = {
       if (typeof this._onPing == 'function') {
         this._onPing(request);
       } else {
         // Echo ping packets.
         this.serverSendMsg('{}');
       }
       break;
 
+    case 'broadcast_subscribe':
+      if (typeof this._onBroadcastSubscribe != 'function') {
+        throw new Error('Unexpected broadcast_subscribe');
+      }
+      this._onBroadcastSubscribe(request);
+      break;
+
     default:
       throw new Error('Unexpected message: ' + messageType);
     }
   },
 
   sendMsg(msg) {
     this._handleMessage(msg);
   },
--- a/dom/push/test/xpcshell/moz.build
+++ b/dom/push/test/xpcshell/moz.build
@@ -1,4 +1,8 @@
 EXTRA_COMPONENTS += [
     'PushServiceHandler.js',
     'PushServiceHandler.manifest',
 ]
+
+TESTING_JS_MODULES += [
+    'broadcast_handler.jsm',
+]
new file mode 100644
--- /dev/null
+++ b/dom/push/test/xpcshell/test_broadcast_success.js
@@ -0,0 +1,267 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+'use strict';
+
+const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
+const {BroadcastService} = ChromeUtils.import("resource://gre/modules/PushBroadcastService.jsm", {});
+ChromeUtils.import("resource://gre/modules/JSONFile.jsm");
+
+ChromeUtils.import("resource://testing-common/Assert.jsm");
+ChromeUtils.import("resource://testing-common/FileTestUtils.jsm");
+ChromeUtils.import("resource://test/broadcast_handler.jsm");
+
+const broadcastService = pushBroadcastService;
+const assert = new Assert();
+const userAgentID = 'bd744428-f125-436a-b6d0-dd0c9845837f';
+const channelID = '0ef2ad4a-6c49-41ad-af6e-95d2425276bf';
+
+function run_test() {
+  do_get_profile();
+  setPrefs({
+    userAgentID,
+    alwaysConnect: true,
+    requestTimeout: 1000,
+    retryBaseInterval: 150
+  });
+  run_next_test();
+}
+
+function getPushServiceMock() {
+  return {
+    subscribed: [],
+    subscribeBroadcast: function(broadcastId, version) {
+      this.subscribed.push([broadcastId, version]);
+    },
+  };
+}
+
+add_task(async function test_register_success() {
+  await broadcastService._resetListeners();
+  let db = PushServiceWebSocket.newPushDB();
+  broadcastHandler.reset();
+  let notifications = broadcastHandler.notifications;
+  let socket;
+  registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
+
+  await broadcastService.addListener("broadcast-test", "2018-02-01", {
+    moduleURI: "resource://test/broadcast_handler.jsm",
+    symbolName: "broadcastHandler",
+  });
+
+  PushServiceWebSocket._generateID = () => channelID;
+
+  var broadcastSubscriptions = [];
+
+  await PushService.init({
+    serverURI: "wss://push.example.org/",
+    db,
+    makeWebSocket(uri) {
+      return new MockWebSocket(uri, {
+        onHello(data) {
+          socket = this;
+          deepEqual(data.broadcasts, {"broadcast-test": "2018-02-01"}, "Handshake: doesn't consult listeners");
+          equal(data.messageType, 'hello', 'Handshake: wrong message type');
+          equal(data.uaid, userAgentID, 'Handshake: wrong device ID');
+          this.serverSendMsg(JSON.stringify({
+            messageType: 'hello',
+            status: 200,
+            uaid: userAgentID
+          }));
+        },
+
+        onBroadcastSubscribe(data) {
+          broadcastSubscriptions.push(data);
+        },
+      });
+    }
+  })
+
+  socket.serverSendMsg(JSON.stringify({
+    messageType: "broadcast",
+    broadcasts: {
+      "broadcast-test": "2018-03-02"
+    }
+  }));
+
+  await broadcastHandler.wasNotified;
+
+  deepEqual(notifications, [["2018-03-02", "broadcast-test"]], "Broadcast notification didn't get delivered");
+
+  deepEqual(await broadcastService.getListeners(), {
+    "broadcast-test": "2018-03-02"
+  }, "Broadcast version wasn't updated");
+
+  await broadcastService.addListener("example-listener", "2018-03-01", {
+    moduleURI: "resource://gre/modules/not-real-example.jsm",
+    symbolName: "doesntExist"
+  });
+
+  deepEqual(broadcastSubscriptions, [{
+    messageType: "broadcast_subscribe",
+    broadcasts: {"example-listener": "2018-03-01"}
+  }]);
+});
+
+add_task(async function test_handle_hello_broadcasts() {
+  PushService.uninit();
+  await broadcastService._resetListeners();
+  let db = PushServiceWebSocket.newPushDB();
+  broadcastHandler.reset();
+  let notifications = broadcastHandler.notifications;
+  registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
+
+  await broadcastService.addListener("broadcast-test", "2018-02-01", {
+    moduleURI: "resource://test/broadcast_handler.jsm",
+    symbolName: "broadcastHandler",
+  });
+
+  PushServiceWebSocket._generateID = () => channelID;
+
+  await PushService.init({
+    serverURI: "wss://push.example.org/",
+    db,
+    makeWebSocket(uri) {
+      return new MockWebSocket(uri, {
+        onHello(data) {
+          deepEqual(data.broadcasts, {"broadcast-test": "2018-02-01"}, "Handshake: doesn't consult listeners");
+          equal(data.messageType, 'hello', 'Handshake: wrong message type');
+          equal(data.uaid, userAgentID, 'Handshake: wrong device ID');
+          this.serverSendMsg(JSON.stringify({
+            messageType: 'hello',
+            status: 200,
+            uaid: userAgentID,
+            broadcasts: {
+              "broadcast-test": "2018-02-02"
+            }
+          }));
+        },
+
+        onBroadcastSubscribe(data) {
+          broadcastSubscriptions.push(data);
+        },
+      });
+    }
+  })
+
+  await broadcastHandler.wasNotified;
+
+  deepEqual(notifications, [["2018-02-02", "broadcast-test"]], "Broadcast notification on hello was delivered");
+
+  deepEqual(await broadcastService.getListeners(), {
+    "broadcast-test": "2018-02-02"
+  }, "Broadcast version wasn't updated");
+});
+
+add_task(async function test_broadcast_unit() {
+  const fakeListenersData = {
+    "abc": {
+      version: "2018-03-04",
+      sourceInfo: {
+        moduleURI: "resource://gre/modules/abc.jsm",
+        symbolName: "getAbc"
+      }
+    },
+    "def": {
+      version: "2018-04-05",
+      sourceInfo: {
+        moduleURI: "resource://gre/modules/def.jsm",
+        symbolName: "getDef"
+      }
+    }
+  };
+  const path = FileTestUtils.getTempFile("broadcast-listeners.json").path;
+
+  const jsonFile = new JSONFile({path});
+  jsonFile.data = {
+    listeners: fakeListenersData,
+  };
+  await jsonFile._save();
+
+  const pushServiceMock = getPushServiceMock();
+
+  const broadcastService = new BroadcastService(pushServiceMock, path);
+  const listeners = await broadcastService.getListeners();
+  deepEqual(listeners, {
+    "abc": "2018-03-04",
+    "def": "2018-04-05"
+  });
+
+  await broadcastService.addListener("ghi", "2018-05-06", {
+    moduleURI: "resource://gre/modules/ghi.jsm",
+    symbolName: "getGhi"
+  });
+
+  deepEqual(pushServiceMock.subscribed, [
+    ["ghi", "2018-05-06"]
+  ]);
+
+  await broadcastService._saveImmediately();
+
+  const newJSONFile = new JSONFile({path});
+  await newJSONFile.load();
+
+  deepEqual(newJSONFile.data, {
+    listeners: {
+      ...fakeListenersData,
+      ghi: {
+        version: "2018-05-06",
+        sourceInfo: {
+          moduleURI: "resource://gre/modules/ghi.jsm",
+          symbolName: "getGhi"
+        }
+      }
+    },
+    version: 1,
+  });
+
+  deepEqual(await broadcastService.getListeners(), {
+    "abc": "2018-03-04",
+    "def": "2018-04-05",
+    "ghi": "2018-05-06"
+  });
+});
+
+add_task(async function test_broadcast_initialize_sane() {
+  const path = FileTestUtils.getTempFile("broadcast-listeners.json").path;
+  const broadcastService = new BroadcastService(getPushServiceMock(), path);
+  deepEqual(await broadcastService.getListeners(), {}, "listeners should start out sane");
+  await broadcastService._saveImmediately();
+  let onDiskJSONFile = new JSONFile({path});
+  await onDiskJSONFile.load();
+  deepEqual(onDiskJSONFile.data, {listeners: {}, version: 1},
+            "written JSON file has listeners and version fields");
+
+  await broadcastService.addListener("ghi", "2018-05-06", {
+    moduleURI: "resource://gre/modules/ghi.jsm",
+    symbolName: "getGhi"
+  });
+
+  await broadcastService._saveImmediately();
+
+  onDiskJSONFile = new JSONFile({path});
+  await onDiskJSONFile.load();
+
+  deepEqual(onDiskJSONFile.data, {
+    listeners: {
+      ghi: {
+        version: "2018-05-06",
+        sourceInfo: {
+          moduleURI: "resource://gre/modules/ghi.jsm",
+          symbolName: "getGhi"
+        }
+      }
+    },
+    version: 1,
+  }, "adding listeners to initial state is written OK");
+});
+
+add_task(async function test_broadcast_reject_invalid_sourceinfo() {
+  const path = FileTestUtils.getTempFile("broadcast-listeners.json").path;
+  const broadcastService = new BroadcastService(getPushServiceMock(), path);
+
+  await assert.rejects(broadcastService.addListener("ghi", "2018-05-06", {
+      moduleName: "resource://gre/modules/ghi.jsm",
+      symbolName: "getGhi"
+  }), "missing moduleURI", "rejects sourceInfo that doesn't have moduleURI");
+});
--- a/dom/push/test/xpcshell/test_observer_remoting.js
+++ b/dom/push/test/xpcshell/test_observer_remoting.js
@@ -1,14 +1,15 @@
 'use strict';
 
 const pushNotifier = Cc['@mozilla.org/push/Notifier;1']
                        .getService(Ci.nsIPushNotifier);
 
 add_task(async function test_observer_remoting() {
+  do_get_profile();
   if (isParent) {
     await testInParent();
   } else {
     await testInChild();
   }
 });
 
 const childTests = [{
@@ -17,16 +18,17 @@ const childTests = [{
 }];
 
 const parentTests = [{
   text: 'Hello from parent!',
   principal: Services.scriptSecurityManager.getSystemPrincipal(),
 }];
 
 async function testInParent() {
+  setPrefs();
   // Register observers for notifications from the child, then run the test in
   // the child and wait for the notifications.
   let promiseNotifications = childTests.reduce(
     (p, test) => p.then(_ => waitForNotifierObservers(test, /* shouldNotify = */ false)),
     Promise.resolve()
   );
   let promiseFinished = run_test_in_child('./test_observer_remoting.js');
   await promiseNotifications;
--- a/dom/push/test/xpcshell/test_service_parent.js
+++ b/dom/push/test/xpcshell/test_service_parent.js
@@ -2,16 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 'use strict';
 
 const {PushDB, PushService, PushServiceWebSocket} = serviceExports;
 
 function run_test() {
   do_get_profile();
+  setPrefs();
   run_next_test();
 }
 
 add_task(async function test_service_parent() {
   let db = PushServiceWebSocket.newPushDB();
   registerCleanupFunction(() => {return db.drop().then(_ => db.close());});
   await setUpServiceInParent(PushService, db);
 
--- a/dom/push/test/xpcshell/xpcshell.ini
+++ b/dom/push/test/xpcshell/xpcshell.ini
@@ -1,13 +1,15 @@
 [DEFAULT]
 head = head.js head-http2.js
 # Push notifications and alarms are currently disabled on Android.
 skip-if = toolkit == 'android'
+support-files = broadcast_handler.jsm
 
+[test_broadcast_success.js]
 [test_clear_forgetAboutSite.js]
 [test_clear_origin_data.js]
 [test_crypto.js]
 [test_crypto_encrypt.js]
 [test_drop_expired.js]
 [test_handler_service.js]
 support-files = PushServiceHandler.js PushServiceHandler.manifest
 [test_notification_ack.js]
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -189,16 +189,20 @@ function waitForApzFlushedRepaints(aCall
 // functions provided by SimpleTest are also mapped into the subtest's window.
 // For other things from the parent, the subtest can use window.opener.<whatever>
 // to access objects.
 function runSubtestsSeriallyInFreshWindows(aSubtests) {
   return new Promise(function(resolve, reject) {
     var testIndex = -1;
     var w = null;
 
+    // If the "apz.subtest" pref has been set, only a single subtest whose name matches
+    // the pref's value (if any) will be run.
+    var onlyOneSubtest = SpecialPowers.getCharPref("apz.subtest", /* default = */ "");
+
     function advanceSubtestExecution() {
       var test = aSubtests[testIndex];
       if (w) {
         // Run any cleanup functions registered in the subtest
         if (w.ApzCleanup) { // guard against the subtest not loading apz_test_utils.js
           w.ApzCleanup.execute();
         }
         if (typeof test.dp_suppression != 'undefined') {
@@ -221,16 +225,23 @@ function runSubtestsSeriallyInFreshWindo
 
       testIndex++;
       if (testIndex >= aSubtests.length) {
         resolve();
         return;
       }
 
       test = aSubtests[testIndex];
+
+      if (onlyOneSubtest && onlyOneSubtest != test.file) {
+        SimpleTest.ok(true, "Skipping " + test.file + " because only " + onlyOneSubtest + " is being run");
+        setTimeout(function() { advanceSubtestExecution(); }, 0);
+        return;
+      }
+
       if (typeof test.dp_suppression != 'undefined') {
         // Normally during a test, the displayport will get suppressed during page
         // load, and unsuppressed at a non-deterministic time during the test. The
         // unsuppression can trigger a repaint which interferes with the test, so
         // to avoid that we can force the displayport to be unsuppressed for the
         // entire test which is more deterministic.
         SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
       }
@@ -268,16 +279,18 @@ function runSubtestsSeriallyInFreshWindo
           w = spawnTest(test.file);
         });
       } else {
         w = spawnTest(test.file);
       }
     }
 
     advanceSubtestExecution();
+  }).catch(function(e) {
+    SimpleTest.ok(false, "Error occurred while running subtests: " + e);
   });
 }
 
 function pushPrefs(prefs) {
   return SpecialPowers.pushPrefEnv({'set': prefs});
 }
 
 async function waitUntilApzStable() {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -254,36 +254,35 @@ MayHaveAnimationOfProperty(EffectSet* ef
   if (aProperty == eCSSProperty_opacity &&
       !effects->MayHaveOpacityAnimation()) {
     return false;
   }
 
   return true;
 }
 
-bool
-nsLayoutUtils::MayHaveAnimationOfProperty(const nsIFrame* aFrame,
-                                          nsCSSPropertyID aProperty)
+static bool
+MayHaveAnimationOfProperty(const nsIFrame* aFrame, nsCSSPropertyID aProperty)
 {
   switch (aProperty) {
     case eCSSProperty_transform:
       return aFrame->MayHaveTransformAnimation();
     case eCSSProperty_opacity:
       return aFrame->MayHaveOpacityAnimation();
     default:
       MOZ_ASSERT_UNREACHABLE("unexpected property");
       return false;
   }
 }
 
 bool
 nsLayoutUtils::HasAnimationOfProperty(EffectSet* aEffectSet,
                                       nsCSSPropertyID aProperty)
 {
-  if (!aEffectSet || !::MayHaveAnimationOfProperty(aEffectSet, aProperty)) {
+  if (!aEffectSet || !MayHaveAnimationOfProperty(aEffectSet, aProperty)) {
     return false;
   }
 
   return HasMatchingAnimations(aEffectSet,
     [&aProperty](KeyframeEffect& aEffect)
     {
       return (aEffect.IsInEffect() || aEffect.IsCurrent()) &&
              aEffect.HasAnimationOfProperty(aProperty);
@@ -309,41 +308,30 @@ nsLayoutUtils::HasAnimationOfProperty(co
 
 }
 
 bool
 nsLayoutUtils::HasEffectiveAnimation(const nsIFrame* aFrame,
                                      nsCSSPropertyID aProperty)
 {
   EffectSet* effects = EffectSet::GetEffectSet(aFrame);
-  if (!effects || !::MayHaveAnimationOfProperty(effects, aProperty)) {
+  if (!effects || !MayHaveAnimationOfProperty(effects, aProperty)) {
     return false;
   }
 
 
   return HasMatchingAnimations(effects,
     [&aProperty](KeyframeEffect& aEffect)
     {
       return (aEffect.IsInEffect() || aEffect.IsCurrent()) &&
              aEffect.HasEffectiveAnimationOfProperty(aProperty);
     }
   );
 }
 
-bool
-nsLayoutUtils::MayHaveEffectiveAnimation(const nsIFrame* aFrame,
-                                         nsCSSPropertyID aProperty)
-{
-  EffectSet* effects = EffectSet::GetEffectSet(aFrame);
-  if (!effects || !::MayHaveAnimationOfProperty(effects, aProperty)) {
-    return false;
-  }
-  return true;
-}
-
 static float
 GetSuitableScale(float aMaxScale, float aMinScale,
                  nscoord aVisibleDimension, nscoord aDisplayDimension)
 {
   float displayVisibleRatio = float(aDisplayDimension) /
                               float(aVisibleDimension);
   // We want to rasterize based on the largest scale used during the
   // transform animation, unless that would make us rasterize something
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2329,34 +2329,30 @@ public:
   static bool HasCurrentTransitions(const nsIFrame* aFrame);
 
   /**
    * Returns true if |aFrame| has an animation of |aProperty| regardless of
    * whether the property is overridden by !important rule.
    */
   static bool HasAnimationOfProperty(const nsIFrame* aFrame,
                                      nsCSSPropertyID aProperty);
-  static bool MayHaveAnimationOfProperty(const nsIFrame* aFrame,
-                                         nsCSSPropertyID aProperty);
 
   /**
    * Returns true if |aEffectSet| has an animation of |aProperty| regardless of
    * whether the property is overridden by !important rule.
    */
   static bool HasAnimationOfProperty(mozilla::EffectSet* aEffectSet,
                                      nsCSSPropertyID aProperty);
 
   /**
    * Returns true if |aFrame| has an animation of |aProperty| which is
    * not overridden by !important rules.
    */
   static bool HasEffectiveAnimation(const nsIFrame* aFrame,
                                     nsCSSPropertyID aProperty);
-  static bool MayHaveEffectiveAnimation(const nsIFrame* aFrame,
-                                        nsCSSPropertyID aProperty);
 
   /**
    * Checks if off-main-thread animations are enabled.
    */
   static bool AreAsyncAnimationsEnabled();
 
   /**
    * Checks if we should warn about animations that can't be async
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2947,22 +2947,19 @@ nsIFrame::BuildDisplayListForStackingCon
     aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
   }
 
   // We build an opacity item if it's not going to be drawn by SVG content, or
   // SVG effects. SVG effects won't handle the opacity if we want an active
   // layer (for async animations), see
   // nsSVGIntegrationsUtils::PaintMaskAndClipPath or
   // nsSVGIntegrationsUtils::PaintFilter.
-  // Use MayNeedActiveLayer to decide, since we don't want to condition the wrapping
-  // display item on values that might change silently between paints (opacity activity
-  // can depend on the will-change budget).
   bool useOpacity = HasVisualOpacity(effectSet) &&
                     !nsSVGUtils::CanOptimizeOpacity(this) &&
-                    (!usingSVGEffects || nsDisplayOpacity::MayNeedActiveLayer(this));
+                    (!usingSVGEffects || nsDisplayOpacity::NeedsActiveLayer(aBuilder, this));
   bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
   bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
     IsScrollFrameActive(aBuilder,
                         nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
                         nsLayoutUtils::SCROLLABLE_SAME_DOC |
                         nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
   bool useFixedPosition = disp->mPosition == NS_STYLE_POSITION_FIXED &&
     (nsLayoutUtils::IsFixedPosFrameInDisplayPort(this) || BuilderHasScrolledClip(aBuilder));
--- a/layout/painting/ActiveLayerTracker.cpp
+++ b/layout/painting/ActiveLayerTracker.cpp
@@ -453,21 +453,17 @@ ActiveLayerTracker::IsStyleAnimated(nsDi
     }
     if (CheckScrollInducedActivity(layerActivity, activityIndex, aBuilder)) {
       return true;
     }
   }
   if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
     return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
   }
-  if (aBuilder) {
-    return nsLayoutUtils::HasEffectiveAnimation(aFrame, aProperty);
-  } else {
-    return nsLayoutUtils::MayHaveEffectiveAnimation(aFrame, aProperty);
-  }
+  return nsLayoutUtils::HasEffectiveAnimation(aFrame, aProperty);
 }
 
 /* static */ bool
 ActiveLayerTracker::IsOffsetStyleAnimated(nsIFrame* aFrame)
 {
   LayerActivity* layerActivity = GetLayerActivity(aFrame);
   if (layerActivity) {
     if (layerActivity->mRestyleCounts[LayerActivity::ACTIVITY_LEFT] >= 2 ||
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6304,22 +6304,16 @@ nsDisplayOpacity::NeedsActiveLayer(nsDis
       (ActiveLayerTracker::IsStyleAnimated(aBuilder, aFrame,
                                            eCSSProperty_opacity) &&
        !IsItemTooSmallForActiveLayer(aFrame))) {
     return true;
   }
   return false;
 }
 
-/* static */ bool
-nsDisplayOpacity::MayNeedActiveLayer(nsIFrame* aFrame)
-{
-  return ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_opacity);
-}
-
 void
 nsDisplayOpacity::ApplyOpacity(nsDisplayListBuilder* aBuilder,
                              float aOpacity,
                              const DisplayItemClipChain* aClip)
 {
   NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
   mOpacity = mOpacity * aOpacity;
   IntersectClip(aBuilder, aClip, false);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -5181,17 +5181,16 @@ public:
   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
 
   /**
    * Returns true if ShouldFlattenAway() applied opacity to children.
    */
   bool OpacityAppliedToChildren() const { return mOpacityAppliedToChildren; }
 
   static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
-  static bool MayNeedActiveLayer(nsIFrame* aFrame);
   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
   virtual void WriteDebugInfo(std::stringstream& aStream) override;
 
   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1290,17 +1290,17 @@ nsSVGUtils::CanOptimizeOpacity(nsIFrame 
   if (type == LayoutFrameType::SVGImage) {
     return true;
   }
   const nsStyleSVG *style = aFrame->StyleSVG();
   if (style->HasMarker()) {
     return false;
   }
 
-  if (nsLayoutUtils::MayHaveAnimationOfProperty(aFrame, eCSSProperty_opacity)) {
+  if (nsLayoutUtils::HasAnimationOfProperty(aFrame, eCSSProperty_opacity)) {
     return false;
   }
 
   if (!style->HasFill() || !HasStroke(aFrame)) {
     return true;
   }
   return false;
 }
--- a/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step2.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step2.html
@@ -2,17 +2,16 @@
 <html>
 <head>
   <title>Bug 383369 test, step 2</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/does_not_exist.css">
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   window.onload = function runTest() {
     window.setTimeout(function () {
       window.location =
         "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step3.html?runtest";
     }, 0);
   };
--- a/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step3.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step3.html
@@ -2,17 +2,16 @@
 <html>
 <head>
   <title>Bug 383369 test, final step</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure", "secure page after insecure download and insecure subcontent still secure");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug329869.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug329869.html
@@ -2,17 +2,16 @@
 <html>
 <head>
   <title>dymanic script load</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("secure");
     window.setTimeout(function () {
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug383369.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug383369.html
@@ -4,17 +4,16 @@
   <title>Bug 383369 test</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
   /* sendAsyncMessage isn't actually a global - this just mollifies eslint */
   /* global sendAsyncMessage */
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   // We want to start this test from an insecure context
   loadAsInsecure = true;
   // We don't want to go through the navigation back/forward test
   bypassNavigationTest = true;
 
   function runTest() {
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug455367.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug455367.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     SpecialPowers.pushPrefEnv(
       {"set": [["security.mixed_content.upgrade_display_content", false]]},
       null);
     isSecurityState("broken", "broken");
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug472986.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug472986.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   SimpleTest.expectAssertions(0, 4);
 
   // Clear the default onload assigned to test start because we must
   // wait for replaced image to load and only after that test the security state
   var onLoadFunction = window.onload;
   window.onload = function()
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug477118.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug477118.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure", "data <img> doesn't break security");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug521461.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug521461.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   loadAsInsecure = true;
 
   function runTest()
   {
     window.location = "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/nocontent.sjs";
     window.setTimeout(function() {
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_cssBefore1.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_cssBefore1.html
@@ -12,17 +12,16 @@
   <style type="text/css">
     p:before
     {
       content: url(http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg);
     }
   </style>
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("broken", "insecure content added by :before styling breaks security");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_cssContent1.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_cssContent1.html
@@ -13,17 +13,16 @@
   <style type="text/css">
     p
     {
       content: url(http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg);
     }
   </style>
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("broken", "insecure content added by :before styling breaks security");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_cssContent2.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_cssContent2.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   if (navigator.platform.startsWith("Mac")) {
     SimpleTest.expectAssertions(0, 1);
   }
 
   function runTest()
   {
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_documentWrite1.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_documentWrite1.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("broken", "insecure <img> written dynamically breaks security");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_documentWrite2.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_documentWrite2.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure iframe written dynamically breaks security");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynDelayedUnsecurePicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynDelayedUnsecurePicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure");
     window.setTimeout(function() {
       // Don't do this synchronously from onload handler
       document.getElementById("image1").src =
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynDelayedUnsecureXHR.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynDelayedUnsecureXHR.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("secure");
     window.setTimeout(() => {
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureBackground.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureBackground.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   // This test, as is, equals to https://kuix.de/misc/test17/358438.php
 
   function runTest()
   {
     isSecurityState("secure");
     document.body.background =
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureIframeRedirect.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureIframeRedirect.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("secure");
     let self = window;
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecurePicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecurePicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   // This test, as is, equals to https://kuix.de/misc/test17/358438.php
 
   function runTest()
   {
     isSecurityState("secure");
     document.getElementById("image1").src =
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecurePicturePreload.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecurePicturePreload.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   (new Image()).src =
     "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg";
 
   function runTest()
   {
     isSecurityState("broken", "(new Image()).src='http://...' changed to broken");
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureRedirect.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureRedirect.html
@@ -2,17 +2,16 @@
 <html>
 <head>
   <title>img.src changes to unsecure redirect test</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure");
     document.getElementById("image1").src =
       "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/imgunsecredirect.sjs";
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlDelayedUnsecurePicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlDelayedUnsecurePicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure");
 
     window.setTimeout(function () {
       document.getElementById("buddy").innerHTML =
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlUnsecurePicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlUnsecurePicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure");
 
     document.getElementById("buddy").innerHTML =
       "<img id='image1' src='http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg' />";
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_javascriptPicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_javascriptPicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("secure", "javascript: <img> should not break security");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_secureAll.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_secureAll.html
@@ -9,17 +9,16 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <link rel="stylesheet" type="text/css"
     href="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/somestyle.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   // Navigation test goes over an insecure page, test state leak
   navigateToInsecure = true;
 
   function runTest()
   {
     isSecurityState("secure", "insecure <img> load breaks security");
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_securePicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_securePicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   loadAsInsecure = true;
 
   function runTest()
   {
     isSecurityState("insecure", "left insecure");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureBackground.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureBackground.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   // This test, as is, equals to https://kuix.de/misc/test17/358438.php
 
   function runTest()
   {
     isSecurityState("broken", "security broken");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureCSS.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureCSS.html
@@ -9,17 +9,16 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <link rel="stylesheet" type="text/css"
     href="http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/somestyle.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure <img> load breaks security");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframe.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframe.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure <iframe> load breaks security");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframe2.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframe2.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure <iframe> load breaks security");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframeMetaRedirect.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframeMetaRedirect.html
@@ -2,17 +2,16 @@
 <html>
 <head>
   <title>Unsecure redirect iframe load</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     window.setTimeout(function()
     {
       isSecurityState("broken", "insecure meta-tag <iframe> load breaks security");
       finish();
@@ -30,9 +29,8 @@
 
   </script>
 </head>
 
 <body>
   <iframe src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframeMetaRedirect.html"></iframe>
 </body>
 </html>
- 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframeRedirect.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureIframeRedirect.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure <iframe> load breaks security");
     finish();
@@ -30,9 +29,8 @@
 
   </script>
 </head>
 
 <body>
   <iframe src="https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframeunsecredirect.sjs"></iframe>
 </body>
 </html>
- 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecurePicture.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecurePicture.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("broken", "insecure <img> load breaks security");
     finish();
   }
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecurePictureDup.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecurePictureDup.html
@@ -2,17 +2,16 @@
 <html>
 <head>
   <title>Unsecure img load in two windows</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   openTwoWindows = true;
   testPage = "unsecurePictureDup.html";
 
   </script>
 </head>
 
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecurePictureInIframe.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecurePictureInIframe.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure <img> in an <iframe> load breaks security");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureRedirect.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_unsecureRedirect.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   hasMixedActiveContent = true;
 
   function runTest()
   {
     isSecurityState("broken", "insecure <img> load breaks security");
     finish();
--- a/security/manager/ssl/tests/mochitest/mixedcontent/unsecurePictureDup.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/unsecurePictureDup.html
@@ -6,17 +6,16 @@
   <script type="text/javascript" src="/MochiKit/DOM.js"></script>
   <script type="text/javascript" src="/MochiKit/Style.js"></script>
   <script type="text/javascript" src="/MochiKit/Signal.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="mixedContentTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script class="testbody" type="text/javascript">
-  /* import-globals-from mixedContentTest.js */
   "use strict";
 
   function runTest()
   {
     isSecurityState("broken", "insecure <img> load breaks security");
     finish();
   }
 
--- a/services/settings/remote-settings.js
+++ b/services/settings/remote-settings.js
@@ -1,17 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* global __URI__ */
+
 "use strict";
 
 var EXPORTED_SYMBOLS = [
   "RemoteSettings",
-  "jexlFilterFunc"
+  "jexlFilterFunc",
+  "remoteSettingsBroadcastHandler",
 ];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm", {});
 XPCOMUtils.defineLazyGlobalGetters(this, ["fetch", "indexedDB"]);
 
 ChromeUtils.defineModuleGetter(this, "Kinto",
@@ -21,16 +24,18 @@ ChromeUtils.defineModuleGetter(this, "Ki
 ChromeUtils.defineModuleGetter(this, "CanonicalJSON",
                                "resource://gre/modules/CanonicalJSON.jsm");
 ChromeUtils.defineModuleGetter(this, "UptakeTelemetry",
                                "resource://services-common/uptake-telemetry.js");
 ChromeUtils.defineModuleGetter(this, "ClientEnvironmentBase",
                                "resource://gre/modules/components-utils/ClientEnvironment.jsm");
 ChromeUtils.defineModuleGetter(this, "FilterExpressions",
                                "resource://gre/modules/components-utils/FilterExpressions.jsm");
+ChromeUtils.defineModuleGetter(this, "pushBroadcastService",
+                               "resource://gre/modules/PushBroadcastService.jsm");
 
 const PREF_SETTINGS_SERVER             = "services.settings.server";
 const PREF_SETTINGS_DEFAULT_BUCKET     = "services.settings.default_bucket";
 const PREF_SETTINGS_DEFAULT_SIGNER     = "services.settings.default_signer";
 const PREF_SETTINGS_VERIFY_SIGNATURE   = "services.settings.verify_signature";
 const PREF_SETTINGS_SERVER_BACKOFF     = "services.settings.server.backoff";
 const PREF_SETTINGS_CHANGES_PATH       = "services.settings.changes.path";
 const PREF_SETTINGS_LAST_UPDATE        = "services.settings.last_update_seconds";
@@ -730,12 +735,33 @@ function remoteSettingsFunction() {
     // Save current Etag for next poll.
     if (currentEtag) {
       Services.prefs.setCharPref(PREF_SETTINGS_LAST_ETAG, currentEtag);
     }
 
     Services.obs.notifyObservers(null, "remote-settings-changes-polled");
   };
 
+
+  const broadcastID = "remote-settings/monitor_changes";
+  // When we start on a new profile there will be no ETag stored.
+  // Use an arbitrary ETag that is guaranteed not to occur.
+  // This will trigger a broadcast message but that's fine because we
+  // will check the changes on each collection and retrieve only the
+  // changes (e.g. nothing if we have a dump with the same data).
+  const currentVersion = Services.prefs.getStringPref(PREF_SETTINGS_LAST_ETAG, "\"0\"");
+  const moduleInfo = {
+    moduleURI: __URI__,
+    symbolName: "remoteSettingsBroadcastHandler",
+  };
+  pushBroadcastService.addListener(broadcastID, currentVersion,
+                                   moduleInfo);
+
   return remoteSettings;
 }
 
 var RemoteSettings = remoteSettingsFunction();
+
+var remoteSettingsBroadcastHandler = {
+  async receivedBroadcastMessage(data, broadcastID) {
+    return RemoteSettings.pollChanges();
+  }
+};
--- a/testing/talos/talos/generate-tart-xpi.html
+++ b/testing/talos/talos/generate-tart-xpi.html
@@ -6,17 +6,16 @@
  -->
 <head>
   <meta charset="UTF-8"/>
   <title>TART addon xpi generator</title>
   <script src="scripts/jszip.min.js"></script>
   <script src="scripts/xpigen.js"></script>
 
   <script>
-    /* import-globals-from scripts/xpigen.js */
     var base = "tests/tart/addon/";
     var files = [
       "bootstrap.js",
       "chrome.manifest",
       "install.rdf",
       "content/framescript.js",
       "content/tart.overlay.xul",
       "content/tart.html",
--- a/testing/talos/talos/generate-tresize-xpi.html
+++ b/testing/talos/talos/generate-tresize-xpi.html
@@ -6,17 +6,16 @@
  -->
 <head>
   <meta charset="UTF-8"/>
   <title>Tresize addon xpi generator</title>
   <script src="scripts/jszip.min.js"></script>
   <script src="scripts/xpigen.js"></script>
 
   <script>
-    /* import-globals-from scripts/xpigen.js */
     var base = "startup_test/tresize/addon/";
     var files = [
       "bootstrap.js",
       "chrome.manifest",
       "install.rdf",
       "content/framescript.js",
       "content/Profiler.js",
       "content/tresize.overlay.xul",
--- a/testing/talos/talos/tests/a11y/dhtml.html
+++ b/testing/talos/talos/tests/a11y/dhtml.html
@@ -1,17 +1,16 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <meta charset="utf-8">
 <head>
 <title>accessibility perf for dhtml</title>
 <script src="a11y.js"></script>
 <script src="chrome://talos-powers-content/content/TalosContentProfiler.js"></script>
 <script>
-  /* import-globals-from a11y.js */
   // based on: http://hacks.mozilla.org/2010/05/better-performance-with-lazy-frame-construction/
   var ppDate = null;
 
   function doInsertion() {
     if (!initAccessibility()) {
       dump("__FAILinit:AccessibilityUnvailable__FAIL");
       return;
     }
--- a/testing/talos/talos/tests/a11y/tablemutation.html
+++ b/testing/talos/talos/tests/a11y/tablemutation.html
@@ -72,17 +72,16 @@
 <tr><td>Row #0</td><td>348003</td><td>745393</td><td>658838</td><td>273744</td></tr><tr><td>Row #1</td><td>482498</td><td>724073</td><td>792474</td><td>549091</td></tr><tr><td>Row #2</td><td>639859</td><td>151692</td><td>251949</td><td>323840</td></tr><tr><td>Row #3</td><td>269274</td><td>211292</td><td>892989</td><td>473276</td></tr><tr><td>Row #4</td><td>148736</td><td>438719</td><td>789802</td><td>986023</td></tr><tr><td>Row #5</td><td>999863</td><td>782360</td><td>648663</td><td>959764</td></tr><tr><td>Row #6</td><td>302562</td><td>122962</td><td>623747</td><td>961374</td></tr><tr><td>Row #7</td><td>620408</td><td>740513</td><td>562968</td><td>868412</td></tr><tr><td>Row #8</td><td>485907</td><td>221807</td><td>142157</td><td>868405</td></tr><tr><td>Row #9</td><td>845880</td><td>834632</td><td>417497</td><td>485740</td></tr><tr><td>Row #10</td><td>886324</td><td>569447</td><td>709581</td><td>155598</td></tr><tr><td>Row #11</td><td>680740</td><td>602570</td><td>528874</td><td>729476</td></tr><tr><td>Row #12</td><td>941289</td><td>318677</td><td>715499</td><td>941153</td></tr><tr><td>Row #13</td><td>101037</td><td>364163</td><td>900918</td><td>303600</td></tr><tr><td>Row #14</td><td>387126</td><td>524665</td><td>264974</td><td>907534</td></tr><tr><td>Row #15</td><td>265179</td><td>727943</td><td>775947</td><td>651086</td></tr><tr><td>Row #16</td><td>849750</td><td>818104</td><td>519492</td><td>695631</td></tr><tr><td>Row #17</td><td>652736</td><td>836990</td><td>181371</td><td>539061</td></tr><tr><td>Row #18</td><td>406437</td><td>790952</td><td>594659</td><td>987177</td></tr><tr><td>Row #19</td><td>393523</td><td>123534</td><td>716653</td><td>334813</td></tr><tr><td>Row #20</td><td>342211</td><td>432153</td><td>275966</td><td>343248</td></tr><tr><td>Row #21</td><td>696316</td><td>176885</td><td>546849</td><td>983442</td></tr><tr><td>Row #22</td><td>601550</td><td>711824</td><td>890977</td><td>766730</td></tr><tr><td>Row #23</td><td>439767</td><td>666925</td><td>417816</td><td>289518</td></tr><tr><td>Row #24</td><td>485029</td><td>837309</td><td>885150</td><td>137766</td></tr>
 <tr><td>Row #0</td><td>348003</td><td>745393</td><td>658838</td><td>273744</td></tr><tr><td>Row #1</td><td>482498</td><td>724073</td><td>792474</td><td>549091</td></tr><tr><td>Row #2</td><td>639859</td><td>151692</td><td>251949</td><td>323840</td></tr><tr><td>Row #3</td><td>269274</td><td>211292</td><td>892989</td><td>473276</td></tr><tr><td>Row #4</td><td>148736</td><td>438719</td><td>789802</td><td>986023</td></tr><tr><td>Row #5</td><td>999863</td><td>782360</td><td>648663</td><td>959764</td></tr><tr><td>Row #6</td><td>302562</td><td>122962</td><td>623747</td><td>961374</td></tr><tr><td>Row #7</td><td>620408</td><td>740513</td><td>562968</td><td>868412</td></tr><tr><td>Row #8</td><td>485907</td><td>221807</td><td>142157</td><td>868405</td></tr><tr><td>Row #9</td><td>845880</td><td>834632</td><td>417497</td><td>485740</td></tr><tr><td>Row #10</td><td>886324</td><td>569447</td><td>709581</td><td>155598</td></tr><tr><td>Row #11</td><td>680740</td><td>602570</td><td>528874</td><td>729476</td></tr><tr><td>Row #12</td><td>941289</td><td>318677</td><td>715499</td><td>941153</td></tr><tr><td>Row #13</td><td>101037</td><td>364163</td><td>900918</td><td>303600</td></tr><tr><td>Row #14</td><td>387126</td><td>524665</td><td>264974</td><td>907534</td></tr><tr><td>Row #15</td><td>265179</td><td>727943</td><td>775947</td><td>651086</td></tr><tr><td>Row #16</td><td>849750</td><td>818104</td><td>519492</td><td>695631</td></tr><tr><td>Row #17</td><td>652736</td><td>836990</td><td>181371</td><td>539061</td></tr><tr><td>Row #18</td><td>406437</td><td>790952</td><td>594659</td><td>987177</td></tr><tr><td>Row #19</td><td>393523</td><td>123534</td><td>716653</td><td>334813</td></tr><tr><td>Row #20</td><td>342211</td><td>432153</td><td>275966</td><td>343248</td></tr><tr><td>Row #21</td><td>696316</td><td>176885</td><td>546849</td><td>983442</td></tr><tr><td>Row #22</td><td>601550</td><td>711824</td><td>890977</td><td>766730</td></tr><tr><td>Row #23</td><td>439767</td><td>666925</td><td>417816</td><td>289518</td></tr><tr><td>Row #24</td><td>485029</td><td>837309</td><td>885150</td><td>137766</td></tr>
 <tr><td>Row #0</td><td>348003</td><td>745393</td><td>658838</td><td>273744</td></tr><tr><td>Row #1</td><td>482498</td><td>724073</td><td>792474</td><td>549091</td></tr><tr><td>Row #2</td><td>639859</td><td>151692</td><td>251949</td><td>323840</td></tr><tr><td>Row #3</td><td>269274</td><td>211292</td><td>892989</td><td>473276</td></tr><tr><td>Row #4</td><td>148736</td><td>438719</td><td>789802</td><td>986023</td></tr><tr><td>Row #5</td><td>999863</td><td>782360</td><td>648663</td><td>959764</td></tr><tr><td>Row #6</td><td>302562</td><td>122962</td><td>623747</td><td>961374</td></tr><tr><td>Row #7</td><td>620408</td><td>740513</td><td>562968</td><td>868412</td></tr><tr><td>Row #8</td><td>485907</td><td>221807</td><td>142157</td><td>868405</td></tr><tr><td>Row #9</td><td>845880</td><td>834632</td><td>417497</td><td>485740</td></tr><tr><td>Row #10</td><td>886324</td><td>569447</td><td>709581</td><td>155598</td></tr><tr><td>Row #11</td><td>680740</td><td>602570</td><td>528874</td><td>729476</td></tr><tr><td>Row #12</td><td>941289</td><td>318677</td><td>715499</td><td>941153</td></tr><tr><td>Row #13</td><td>101037</td><td>364163</td><td>900918</td><td>303600</td></tr><tr><td>Row #14</td><td>387126</td><td>524665</td><td>264974</td><td>907534</td></tr><tr><td>Row #15</td><td>265179</td><td>727943</td><td>775947</td><td>651086</td></tr><tr><td>Row #16</td><td>849750</td><td>818104</td><td>519492</td><td>695631</td></tr><tr><td>Row #17</td><td>652736</td><td>836990</td><td>181371</td><td>539061</td></tr><tr><td>Row #18</td><td>406437</td><td>790952</td><td>594659</td><td>987177</td></tr><tr><td>Row #19</td><td>393523</td><td>123534</td><td>716653</td><td>334813</td></tr><tr><td>Row #20</td><td>342211</td><td>432153</td><td>275966</td><td>343248</td></tr><tr><td>Row #21</td><td>696316</td><td>176885</td><td>546849</td><td>983442</td></tr><tr><td>Row #22</td><td>601550</td><td>711824</td><td>890977</td><td>766730</td></tr><tr><td>Row #23</td><td>439767</td><td>666925</td><td>417816</td><td>289518</td></tr><tr><td>Row #24</td><td>485029</td><td>837309</td><td>885150</td><td>137766</td></tr>
 </table>
 </div>
 
 </body>
 <script>
-/* import-globals-from a11y.js */
 window.onload = function() {
   setTimeout(function() {
     mutateTable();
   }, 100);
 };
 function mutateTable() {
   var htmTable = document.getElementById("datatable");
   var TableRows = [ ];
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -119,16 +119,20 @@ try {
     let crashReporter =
           Cc["@mozilla.org/toolkit/crash-reporter;1"]
           .getService(Ci.nsICrashReporter);
     crashReporter.UpdateCrashEventsDir();
     crashReporter.minidumpPath = do_get_minidumpdir();
   }
 } catch (e) { }
 
+if (runningInParent) {
+  _Services.prefs.setBoolPref("dom.push.connection.enabled", false);
+}
+
 // Configure a console listener so messages sent to it are logged as part
 // of the test.
 try {
   let levelNames = {};
   for (let level of ["debug", "info", "warn", "error"]) {
     levelNames[Ci.nsIConsoleMessage[level]] = level;
   }
 
--- a/toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
+++ b/toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
@@ -7,17 +7,16 @@
   </script>
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 
   <script type="application/javascript">
     "use strict";
-    /* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
 
     let loadContext = SpecialPowers.Cc["@mozilla.org/loadcontext;1"].
                         createInstance(SpecialPowers.Ci.nsILoadContext);
     let privateLoadContext = SpecialPowers.Cc["@mozilla.org/privateloadcontext;1"].
                         createInstance(SpecialPowers.Ci.nsILoadContext);
 
     SimpleTest.waitForExplicitFinish();
 
--- a/toolkit/components/prompts/test/test_bug619644.html
+++ b/toolkit/components/prompts/test/test_bug619644.html
@@ -10,17 +10,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="text/javascript" src="prompt_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=619644">Mozilla Bug 619644</a>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from prompt_common.js */
 // This is a little yucky, but it works
 // The contents of bug619644_inner.html
 const expectedFinalDoc =
 "<head><\/head><body><p>Original content<\/p>\n<script>\n    window.opener.postMessage(\"\", \"*\");\n    confirm(\"Message\");\n    document.write(\"Extra content\");\n    window.opener.postMessage(document.documentElement.innerHTML, \"*\");\n<\/script>Extra content<\/body>";
 
 if (!isTabModal) {
   todo(false, "Test disabled when tab modal prompts are not enabled.");
 } else {
--- a/toolkit/components/prompts/test/test_bug620145.html
+++ b/toolkit/components/prompts/test/test_bug620145.html
@@ -19,18 +19,16 @@
 </div>
 <div id="text2" style="max-width: 100px">
   This is another short piece of text used for testing that mouse selecting is
   stopped when an alert appears.
 </div>
 <button id="button" onmouseup="openAlert()">Button</button>
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from ../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */
-/* import-globals-from prompt_common.js */
 var selectionTest = false;
 
 function openAlert() {
   info("opening alert...");
   alert("hello!");
   info("...alert done.");
 }
 
--- a/toolkit/components/prompts/test/test_dom_prompts.html
+++ b/toolkit/components/prompts/test/test_dom_prompts.html
@@ -8,17 +8,16 @@
   <script type="text/javascript" src="prompt_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 </pre>
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from prompt_common.js */
 var rv;
 var state, action;
 
 add_task(async function test_alert_ok() {
     info("Starting test: Alert");
     state = {
         msg: "This is the alert text.",
         iconClass: "alert-icon",
--- a/toolkit/components/prompts/test/test_modal_prompts.html
+++ b/toolkit/components/prompts/test/test_modal_prompts.html
@@ -12,17 +12,16 @@ Prompter tests: modal prompts
 <p id="display"></p>
 
 <div id="content" style="display: none">
   <iframe id="iframe"></iframe>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from prompt_common.js */
 async function runTests() {
     const { NetUtil } = SpecialPowers.Cu.import("resource://gre/modules/NetUtil.jsm");
     const { Services } = SpecialPowers.Cu.import("resource://gre/modules/Services.jsm");
     let state, action, promptDone;
     ok(true, "Running tests (isTabModal=" + isTabModal + ", usePromptService=" + usePromptService + ")");
 
     let prompter, promptArgs;
     if (usePromptService) {
--- a/toolkit/components/prompts/test/test_modal_select.html
+++ b/toolkit/components/prompts/test/test_modal_select.html
@@ -12,17 +12,16 @@ Prompter tests: modal prompts
 <p id="display"></p>
 
 <div id="content" style="display: none">
   <iframe id="iframe"></iframe>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from prompt_common.js */
 const { Services } = SpecialPowers.Cu.import("resource://gre/modules/Services.jsm");
 
 function checkPromptState(promptState, expectedState) {
     // XXX check title? OS X has title in content
     // XXX check focused element
     // XXX check button labels?
 
     is(promptState.msg, expectedState.msg, "Checking expected message");
--- a/toolkit/components/prompts/test/test_subresources_prompts.html
+++ b/toolkit/components/prompts/test/test_subresources_prompts.html
@@ -25,17 +25,16 @@
 
 <iframe id="iframe_same_origin" src="bug625187_iframe.html"></iframe>
 
 <iframe id="iframe_prompt"></iframe>
 
 <pre id="test"></pre>
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from prompt_common.js */
 var iframe1Loaded = onloadPromiseFor("iframe_diff_origin");
 var iframe2Loaded = onloadPromiseFor("iframe_same_origin");
 var iframe_prompt = document.getElementById("iframe_prompt");
 
 add_task(async function runTest() {
   // This test depends on tab modal prompts being enabled.
   if (!isTabModal) {
     todo(false, "Test disabled when tab modal prompts are not enabled.");
--- a/toolkit/components/satchel/test/test_bug_511615.html
+++ b/toolkit/components/satchel/test/test_bug_511615.html
@@ -18,18 +18,16 @@ Test for Form History Autocomplete Untru
   <form id="form1" onsubmit="return false;">
     <input  type="text" name="field1">
     <button type="submit">Submit</button>
   </form>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
-
 var resolvePopupShownListener;
 registerPopupShownListener(() => resolvePopupShownListener());
 
 function waitForNextPopup() {
   return new Promise(resolve => { resolvePopupShownListener = resolve; });
 }
 
 /**
--- a/toolkit/components/satchel/test/test_bug_787624.html
+++ b/toolkit/components/satchel/test/test_bug_787624.html
@@ -46,18 +46,16 @@ Form History Layout test: form field aut
         <button type="submit">Submit</button>
       </form>
     </div>
   </div>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
-
 /** Test for Form History autocomplete Layout: Bug 787624 **/
 
 var resolvePopupShownListener;
 registerPopupShownListener(() => resolvePopupShownListener());
 
 function waitForNextPopup() {
   return new Promise(resolve => { resolvePopupShownListener = resolve; });
 }
--- a/toolkit/components/satchel/test/test_datalist_with_caching.html
+++ b/toolkit/components/satchel/test/test_datalist_with_caching.html
@@ -25,20 +25,16 @@ Form History test: form field autocomple
     <option value="First"></option>
     <option value="Second"></option>
     <option value="Secomundo"></option>
   </datalist>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from ../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */
-/* import-globals-from ../../../../testing/mochitest/tests/SimpleTest/AddTask.js */
-/* import-globals-from satchel_common.js */
-
 let input = $_(1, "field1");
 
 function setupFormHistory(aCallback) {
   updateFormHistory([
     { op: "remove" },
     { op: "add", fieldname: "field1", value: "Sec" },
   ], () => {
     aCallback();
--- a/toolkit/components/satchel/test/test_form_autocomplete.html
+++ b/toolkit/components/satchel/test/test_form_autocomplete.html
@@ -134,19 +134,16 @@ Form History test: form field autocomple
     <input  type="datetime-local" name="field17">
     <button type="submit">Submit</button>
   </form>
 
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from ../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */
-/* import-globals-from satchel_common.js */
-
 /** Test for Form History autocomplete **/
 
 var input = $_(1, "field1");
 
 function setupFormHistory(aCallback) {
   updateFormHistory([
     { op: "remove" },
     { op: "add", fieldname: "field1", value: "value1" },
--- a/toolkit/components/satchel/test/test_form_autocomplete_with_list.html
+++ b/toolkit/components/satchel/test/test_form_autocomplete_with_list.html
@@ -36,18 +36,16 @@ Form History test: form field autocomple
     <option value="Google" label="PASS1">FAIL</option>
     <option value="Reddit">PASS2</option>
     <option value="final"></option>
   </datalist>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from ../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */
-/* import-globals-from satchel_common.js */
 /* eslint-disable complexity */
 
 /** Test for Form History autocomplete **/
 
 var input = $_(1, "field1");
 
 function setupFormHistory(aCallback) {
   updateFormHistory([
--- a/toolkit/components/satchel/test/test_form_submission.html
+++ b/toolkit/components/satchel/test/test_form_submission.html
@@ -236,17 +236,16 @@
   <form id="form109" action="https://www.example.com/" onsubmit="return checkSubmit(109)">
     <input type="text" name="test9">
     <button type="submit">Submit</button>
   </form>
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
 /* eslint-disable complexity */
 
 var numSubmittedForms = 0;
 
 var ccNumbers = {
   valid15: [
     "930771457288760", "474915027480942",
     "924894781317325", "714816113937185",
--- a/toolkit/components/satchel/test/test_form_submission_cap.html
+++ b/toolkit/components/satchel/test/test_form_submission_cap.html
@@ -12,18 +12,16 @@
 
   <form id="form1" onsubmit="return checkSubmit(1)">
     <button type="submit">Submit</button>
   </form>
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
-
 /* Test for bug 492701.
    Save only the first MAX_FIELDS_SAVED changed fields in a form.
    Generate numInputFields = MAX_FIELDS_SAVED + 1 fields, change all values,
    and test that only MAX_FIELDS_SAVED are actually saved and that
    field # numInputFields was not saved.
 */
 
 var numSubmittedForms = 0;
--- a/toolkit/components/satchel/test/test_form_submission_cap2.html
+++ b/toolkit/components/satchel/test/test_form_submission_cap2.html
@@ -117,18 +117,16 @@
     <input type="text" name="test100" value="100">
     <input type="text" name="test101" value="101">
     <button type="submit">Submit</button>
   </form>
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
-
 var numSubmittedForms = 0;
 var numInputFields = 101;
 
 function checkInitialState() {
   countEntries(null, null,
                function(num) {
                  ok(!num, "checking for initially empty storage");
                  startTest();
--- a/toolkit/components/satchel/test/test_password_autocomplete.html
+++ b/toolkit/components/satchel/test/test_password_autocomplete.html
@@ -30,18 +30,16 @@
   <form id="form2" onsubmit="return false;" action="http://mochi.test/">
     <input  type="to-be-password" name="field1" list="datalist1">
     <button type="submit">Submit</button>
   </form>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
-
 var resolvePopupShownListener;
 registerPopupShownListener(() => resolvePopupShownListener());
 
 function waitForNextPopup() {
   return new Promise(resolve => { resolvePopupShownListener = resolve; });
 }
 
 /**
--- a/toolkit/components/satchel/test/test_popup_direction.html
+++ b/toolkit/components/satchel/test/test_popup_direction.html
@@ -18,18 +18,16 @@ Test for Popup Direction
   <form id="form1" onsubmit="return false;">
     <input  type="text" name="field1">
     <button type="submit">Submit</button>
   </form>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from satchel_common.js */
-
 var resolvePopupShownListener;
 registerPopupShownListener(() => resolvePopupShownListener());
 
 function waitForNextPopup() {
   return new Promise(resolve => { resolvePopupShownListener = resolve; });
 }
 
 add_task(async function test_popup_direction() {
--- a/toolkit/components/satchel/test/test_popup_enter_event.html
+++ b/toolkit/components/satchel/test/test_popup_enter_event.html
@@ -16,18 +16,16 @@ Form History test: Test for events while
   <form id="form1">
     <input  type="text" name="field1">
     <button type="submit">Submit</button>
   </form>
 </div>
 
 <pre id="test">
 <script class="testbody">
-/* import-globals-from satchel_common.js */
-
 var form = document.getElementById("form1");
 var input = $_(1, "field1");
 var expectedValue = "value1";
 
 function setupFormHistory(aCallback) {
   updateFormHistory([
     { op: "remove" },
     { op: "add", fieldname: "field1", value: "value1" },
--- a/toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
@@ -14,17 +14,16 @@
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
-/* import-globals-from classifierHelper.js */
 
 var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIDOMWindow);
 
--- a/toolkit/components/url-classifier/tests/mochitest/test_bug1254766.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_bug1254766.html
@@ -10,18 +10,16 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script src="head.js"></script>
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
-
 const MALWARE_LIST = "test-malware-simple";
 const MALWARE_HOST1 = "malware.example.com/";
 const MALWARE_HOST2 = "test1.example.com/";
 
 const UNWANTED_LIST = "test-unwanted-simple";
 const UNWANTED_HOST1 = "unwanted.example.com/";
 const UNWANTED_HOST2 = "test2.example.com/";
 
--- a/toolkit/components/url-classifier/tests/mochitest/test_cachemiss.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_cachemiss.html
@@ -10,18 +10,16 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script src="head.js"></script>
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
-
 const MALWARE_LIST = "test-malware-simple";
 const MALWARE_HOST = "malware.example.com/";
 
 const UNWANTED_LIST = "test-unwanted-simple";
 const UNWANTED_HOST = "unwanted.example.com/";
 
 const GETHASH_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/cache.sjs";
 
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier.html
@@ -8,18 +8,16 @@
 </head>
 
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
-
 var firstLoad = true;
 
 // Add some URLs to the malware database.
 // Note that we intentionally don't touch test-phish-simple, and will
 // use the URL registered by addMozEntries().  Otherwise, classifierHelper.resetDatabase()
 // will reset this table, and waitForInit() can't find the known phishing
 // URL in test-phish-simple, breaking the tests following this one.
 var testData = [
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier_changetablepref_bug1395411.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier_changetablepref_bug1395411.html
@@ -11,17 +11,16 @@
 
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
 var Cc = SpecialPowers.Cc;
 var Ci = SpecialPowers.Ci;
 
 const testTableV2 = "mochi1-phish-simple";
 const testTableV4 = "mochi1-phish-proto";
 const UPDATE_URL_V2 = "http://mochi.test:8888/tests/toolkit/components/url-classifier/dummyV2";
 const UPDATE_URL_V4 = "http://mochi.test:8888/tests/toolkit/components/url-classifier/dummyV4";
 
@@ -66,9 +65,8 @@ function runTest() {
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
 <iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
 </body>
 </html>
-
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier_match.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier_match.html
@@ -9,17 +9,16 @@
 
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="application/javascript">
-/* import-globals-from classifierHelper.js */
 var Cc = SpecialPowers.Cc;
 var Ci = SpecialPowers.Ci;
 var Cr = SpecialPowers.Cr;
 
 var inputDatas = [
   { url: "malware.example.com/",
     db: "mochi-block-simple",
   },
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
@@ -8,18 +8,16 @@
 </head>
 
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
-
 // Add some URLs to the malware database.
 var testData = [
   { url: "example.com/tests/toolkit/components/url-classifier/tests/mochitest/evilWorker.js",
     db: "test-malware-simple"
   },
   { url: "example.com/tests/toolkit/components/url-classifier/tests/mochitest/unwantedWorker.js",
     db: "test-unwanted-simple"
   }
--- a/toolkit/components/url-classifier/tests/mochitest/test_classify_ping.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classify_ping.html
@@ -10,17 +10,16 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
   SimpleTest.requestFlakyTimeout("Delay to make sure ping is made prior than XHR");
-  /* import-globals-from classifierHelper.js */
 
   const timeout = 200;
   const host_nottrack = "http://not-tracking.example.com/";
   const host_track = "http://trackertest.org/";
   const path_ping = "tests/toolkit/components/url-classifier/tests/mochitest/ping.sjs";
   const TP_ENABLE_PREF = "privacy.trackingprotection.enabled";
   const RETRY_TIMEOUT_MS = 200;
 
--- a/toolkit/components/url-classifier/tests/mochitest/test_classify_track.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classify_track.html
@@ -13,17 +13,16 @@
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
   const PREF = "browser.safebrowsing.malware.enabled";
   const track_path = "tests/toolkit/components/url-classifier/tests/mochitest/basic.vtt";
   const malware_url = "http://malware.example.com/" + track_path;
   const validtrack_url = "http://mochi.test:8888/" + track_path;
-  /* import-globals-from classifierHelper.js */
 
   var video = document.createElement("video");
   video.src = "seek.webm";
   video.crossOrigin = "anonymous";
 
   document.body.appendChild(video);
 
   function testValidTrack() {
--- a/toolkit/components/url-classifier/tests/mochitest/test_gethash.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_gethash.html
@@ -12,18 +12,16 @@
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <iframe id="testFrame1" onload=""></iframe>
 <iframe id="testFrame2" onload=""></iframe>
 
 <script src="head.js"></script>
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
-
 const MALWARE_LIST = "test-malware-simple";
 const MALWARE_HOST = "malware.example.com/";
 
 const UNWANTED_LIST = "test-unwanted-simple";
 const UNWANTED_HOST = "unwanted.example.com/";
 
 const GETHASH_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/gethash.sjs";
 const NOTEXIST_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/nonexistserver.sjs";
--- a/toolkit/components/url-classifier/tests/mochitest/test_reporturl.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_reporturl.html
@@ -11,18 +11,16 @@
 
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
-
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/ContentTask.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 
 var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
--- a/toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html
@@ -12,17 +12,16 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script src="head.js"></script>
 <script class="testbody" type="text/javascript">
-/* import-globals-from classifierHelper.js */
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
--- a/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html
+++ b/toolkit/content/tests/chrome/test_autocomplete_with_composition_on_input.html
@@ -14,18 +14,16 @@
   <iframe id="formTarget" name="formTarget"></iframe>
   <form action="data:text/html," target="formTarget">
     <input name="test" id="input"><input type="submit">
   </form>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-/* import-globals-from file_autocomplete_with_composition.js */
-
 SimpleTest.waitForExplicitFinish();
 
 function runTests() {
   var formFillController =
     SpecialPowers.getFormFillController()
                  .QueryInterface(Ci.nsIAutoCompleteInput);
   var originalFormFillTimeout = formFillController.timeout;