Merge mozilla-central to inbound. a=merge CLOSED TREE
authorOana Pop Rus <opoprus@mozilla.com>
Wed, 20 Mar 2019 13:12:03 +0200
changeset 465364 e1350f7a1914e74bb5686f371452ce7a9c72ff7f
parent 465363 487ede41ade2cf105784224623ef131cebcb680a (current diff)
parent 465169 708979f9c3f33c77fb2e9106054b215c77044a04 (diff)
child 465365 acedfe3d732706386dee314f67ddc24081eed456
push id35737
push userncsoregi@mozilla.com
push dateThu, 21 Mar 2019 10:41:32 +0000
treeherdermozilla-central@b2f1edb41241 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.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 inbound. a=merge CLOSED TREE
js/src/tests/non262/fields/basic.js
js/src/tests/non262/fields/error.js
js/src/tests/non262/fields/literal.js
js/src/tests/non262/fields/mixed_methods.js
js/src/tests/non262/fields/quirks.js
security/manager/ssl/CertBlocklist.cpp
security/manager/ssl/CertBlocklist.h
security/manager/ssl/nsICertBlocklist.idl
security/manager/ssl/tests/unit/test_cert_blocklist.js
services/.eslintrc.js
taskcluster/scripts/tester/test-linux.sh
testing/web-platform/meta/mathml/relations/html5-tree/integration-point-2.html.ini
testing/web-platform/meta/mediacapture-streams/MediaDevices-SecureContext.html.ini
testing/web-platform/meta/mediacapture-streams/MediaDevices-getSupportedConstraints.html.ini
testing/web-platform/meta/mediacapture-streams/historical.html.ini
testing/web-platform/meta/xhr/send-content-type-charset.htm.ini
testing/web-platform/tests/mediacapture-streams/MediaDevices-getSupportedConstraints.html
testing/web-platform/tests/mediacapture-streams/historical.html
--- a/.eslintignore
+++ b/.eslintignore
@@ -162,17 +162,16 @@ devtools/server/tests/unit/xpcshell_debu
 # dom/ exclusions
 dom/animation/**
 dom/base/*.*
 dom/base/test/*.*
 dom/base/test/unit/test_serializers_entities*.js
 dom/base/test/unit_ipc/**
 dom/base/test/jsmodules/**
 dom/bindings/**
-dom/browser-element/**
 dom/canvas/**
 dom/encoding/**
 dom/events/**
 dom/fetch/**
 dom/file/**
 dom/flex/**
 dom/grid/**
 dom/html/**
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -47,10 +47,65 @@ module.exports = {
       "mozilla/reject-importGlobalProperties": "off",
     }
   }, {
     // TODO: Bug 1515949. Enable no-undef for gfx/
     "files": "gfx/layers/apz/test/mochitest/**",
     "rules": {
       "no-undef": "off",
     }
+  }, {
+    // TODO: Bug 1246594. Empty this list once the rule has landed for all dirs
+    "files": [
+      "accessible/tests/mochitest/events.js",
+      "browser/actors/ContextMenuChild.jsm",
+      "browser/base/content/**",
+      "browser/components/customizableui/**",
+      "browser/components/enterprisepolicies/Policies.jsm",
+      "browser/components/places/content/**",
+      "browser/components/preferences/**",
+      "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js",
+      "browser/components/urlbar/tests/browser/head-common.js",
+      "browser/extensions/fxmonitor/privileged/FirefoxMonitor.jsm",
+      "browser/modules/**",
+      "browser/tools/mozscreenshots/mozscreenshots/extension/TestRunner.jsm",
+      "docshell/test/chrome/docshell_helpers.js",
+      "docshell/test/navigation/NavigationUtils.js",
+      "dom/asmjscache/test/**",
+      "dom/cache/test/mochitest/test_cache_tons_of_fd.html",
+      "dom/crypto/test/**",
+      "dom/indexedDB/test/**",
+      "dom/localstorage/test/unit/test_migration.js",
+      "dom/plugins/test/mochitest/head.js",
+      "gfx/layers/apz/test/mochitest/**",
+      "mobile/android/components/**",
+      "mobile/android/modules/**",
+      "modules/libmar/tests/unit/head_libmar.js",
+      "netwerk/protocol/http/WellKnownOpportunisticUtils.jsm",
+      "netwerk/test/httpserver/httpd.js",
+      "netwerk/test/httpserver/test/**",
+      "parser/htmlparser/tests/mochitest/parser_datreader.js",
+      "testing/marionette/event.js",
+      "testing/mochitest/**",
+      "testing/modules/tests/xpcshell/test_assert.js",
+      "testing/specialpowers/content/specialpowersAPI.js",
+      "testing/talos/talos/**",
+      "toolkit/components/aboutmemory/content/aboutMemory.js",
+      "toolkit/components/captivedetect/test/unit/test_multiple_requests.js",
+      "toolkit/components/cleardata/ServiceWorkerCleanUp.jsm",
+      "toolkit/components/ctypes/**",
+      "toolkit/components/downloads/**",
+      "toolkit/components/places/tests/**",
+      "toolkit/components/processsingleton/MainProcessSingleton.jsm",
+      "toolkit/components/prompts/**",
+      "toolkit/components/search/SearchService.jsm",
+      "toolkit/components/telemetry/app/TelemetryEnvironment.jsm",
+      "toolkit/content/**",
+      "toolkit/modules/**",
+      "toolkit/mozapps/**",
+      "tools/leak-gauge/leak-gauge.html",
+      "xpcom/tests/unit/test_iniParser.js",
+    ],
+    "rules": {
+      "no-throw-literal": "off",
+    }
   }]
 };
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2009,17 +2009,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "plain"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "plane-split"
-version = "0.13.7"
+version = "0.13.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3134,17 +3134,17 @@ dependencies = [
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "plane-split 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.60.0",
@@ -3508,17 +3508,17 @@ dependencies = [
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
-"checksum plane-split 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9760bb0546502fcfae6d2d1d638fac6b9272027a3efae34060218152d0ce8387"
+"checksum plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)" = "91c621d83b9c5a85b7ca7ca2bec643136debb327ad29d0a08768db1325780365"
 "checksum plist 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95bef0807b4fe77618f8d24f0c4ec37a4ad1dad9348c3b27d8b624c824d8cf48"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
 "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
--- a/accessible/tests/browser/.eslintrc.js
+++ b/accessible/tests/browser/.eslintrc.js
@@ -52,17 +52,16 @@ module.exports = {
     "no-process-exit": "off",
     "no-proto": "error",
     "no-restricted-modules": "off",
     "no-return-assign": "error",
     "no-script-url": "off",
     "no-shadow": "error",
     "no-sync": "off",
     "no-ternary": "off",
-    "no-throw-literal": "error",
     "no-underscore-dangle": "off",
     "no-undefined": "off",
     "no-unused-vars": ["error", {"vars": "all", "args": "none"}],
     "no-use-before-define": "off",
     "no-var": "off",
     "no-warning-comments": "off",
     "object-shorthand": "off",
     "one-var": ["error", "never"],
--- a/browser/base/content/browser-sync.js
+++ b/browser/base/content/browser-sync.js
@@ -205,17 +205,17 @@ var gSync = {
     }
 
     document.getElementById("PanelUI-fxa-menu-sendtab-button").setAttribute("label", title);
   },
 
   showSendToDeviceView(anchor) {
     PanelUI.showSubView("PanelUI-sendTabToDevice", anchor);
     let panelViewNode = document.getElementById("PanelUI-sendTabToDevice");
-    this.populateSendTabToDevicesView(panelViewNode, this.populateSendTabToDevicesView);
+    this.populateSendTabToDevicesView(panelViewNode, this.populateSendTabToDevicesView.bind(this));
   },
 
   populateSendTabToDevicesView(panelViewNode, reloadFunc) {
     let bodyNode = panelViewNode.querySelector(".panel-subview-body");
     let panelNode = panelViewNode.closest("panel");
     let browser = gBrowser.selectedBrowser;
     let url = browser.currentURI.spec;
     let title = browser.contentTitle;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -1084,17 +1084,17 @@
                        onkeypress="PanelUI.showSubView('appMenu-libraryView', this, event);"
                        closemenu="none"
                        cui-areatype="toolbar"
                        tooltiptext="&libraryButton.tooltip;"
                        label="&places.library.title;"/>
 
         <toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 badged-button"
                        onmousedown="gSync.toggleAccountPanel('PanelUI-fxa', event)"
-                       onkeypress="gSync.toggleAccountPanel('PanelUI-fxa, event)"
+                       onkeypress="gSync.toggleAccountPanel('PanelUI-fxa', event)"
                        consumeanchor="fxa-toolbar-menu-button"
                        closemenu="none"
                        label="&fxa.menu.firefoxAccount;"
                        tooltiptext="&fxa.menu.firefoxAccount;"
                        cui-areatype="toolbar"
                        removable="true">
                        <vbox>
                         <image id="fxa-avatar-image"/>
--- a/browser/base/content/test/siteIdentity/browser.ini
+++ b/browser/base/content/test/siteIdentity/browser.ini
@@ -105,8 +105,12 @@ support-files =
   test_no_mcb_for_onions.html
 [browser_check_identity_state.js]
 [browser_iframe_navigation.js]
 support-files =
   iframe_navigation.html
 [browser_navigation_failures.js]
 [browser_secure_transport_insecure_scheme.js]
 [browser_ignore_same_page_navigation.js]
+[browser_mixed_content_with_navigation.js]
+support-files =
+  file_mixedPassiveContent.html
+  file_bug1045809_1.html
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/siteIdentity/browser_mixed_content_with_navigation.js
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that the site identity indicator is properly updated when loading from
+// the BF cache. This is achieved by loading a page, navigating to another page,
+// and then going "back" to the first page, as well as the reverse (loading to
+// the other page, navigating to the page we're interested in, going back, and
+// then going forward again).
+
+const kBaseURI = getRootDirectory(gTestPath).replace("chrome://mochitests/content",
+                                                     "https://example.com");
+const kSecureURI =  kBaseURI + "dummy_page.html";
+
+const kTestcases = [
+  {
+    uri: kBaseURI + "file_mixedPassiveContent.html",
+    expectErrorPage: false,
+    expectedIdentityMode: "mixedDisplayContent",
+  },
+  {
+    uri: kBaseURI + "file_bug1045809_1.html",
+    expectErrorPage: false,
+    expectedIdentityMode: "mixedActiveBlocked",
+  },
+  {
+    uri: "https://expired.example.com",
+    expectErrorPage: true,
+    expectedIdentityMode: "unknownIdentity",
+  },
+];
+
+add_task(async function() {
+  for (let testcase of kTestcases) {
+    await run_testcase(testcase);
+  }
+});
+
+async function run_testcase(testcase) {
+  // Test the forward and back case.
+  // Start by loading an unrelated URI so that this generalizes well when the
+  // testcase would otherwise first navigate to an error page, which doesn't
+  // seem to work with withNewTab.
+  await BrowserTestUtils.withNewTab("about:blank", async (browser) => {
+    // Navigate to the test URI.
+    await BrowserTestUtils.loadURI(browser, testcase.uri);
+    if (!testcase.expectErrorPage) {
+      await BrowserTestUtils.browserLoaded(browser, false, testcase.uri);
+    } else {
+      await BrowserTestUtils.waitForErrorPage(browser);
+    }
+    let identityMode = window.document.getElementById("identity-box").classList;
+    ok(identityMode.contains(testcase.expectedIdentityMode),
+       `identity should be ${testcase.expectedIdentityMode}`);
+
+    // Navigate to a URI that should be secure.
+    await BrowserTestUtils.loadURI(browser, kSecureURI);
+    await BrowserTestUtils.browserLoaded(browser, false, kSecureURI);
+    let secureIdentityMode = window.document.getElementById("identity-box").className;
+    is(secureIdentityMode, "verifiedDomain", "identity should be secure now");
+
+    // Go back to the test page.
+    browser.webNavigation.goBack();
+    if (!testcase.expectErrorPage) {
+      await BrowserTestUtils.browserStopped(browser, testcase.uri);
+    } else {
+      await BrowserTestUtils.waitForErrorPage(browser);
+    }
+    let identityModeAgain = window.document.getElementById("identity-box").classList;
+    ok(identityModeAgain.contains(testcase.expectedIdentityMode),
+       `identity should again be ${testcase.expectedIdentityMode}`);
+  });
+
+  // Test the back and forward case.
+  // Start on a secure page.
+  await BrowserTestUtils.withNewTab(kSecureURI, async (browser) => {
+    let secureIdentityMode = window.document.getElementById("identity-box").className;
+    is(secureIdentityMode, "verifiedDomain", "identity should start as secure");
+
+    // Navigate to the test URI.
+    await BrowserTestUtils.loadURI(browser, testcase.uri);
+    if (!testcase.expectErrorPage) {
+      await BrowserTestUtils.browserLoaded(browser, false, testcase.uri);
+    } else {
+      await BrowserTestUtils.waitForErrorPage(browser);
+    }
+    let identityMode = window.document.getElementById("identity-box").classList;
+    ok(identityMode.contains(testcase.expectedIdentityMode),
+       `identity should be ${testcase.expectedIdentityMode}`);
+
+    // Go back to the secure page.
+    browser.webNavigation.goBack();
+    await BrowserTestUtils.browserStopped(browser, kSecureURI);
+    let secureIdentityModeAgain = window.document.getElementById("identity-box").classList;
+    is(secureIdentityModeAgain, "verifiedDomain", "identity should be secure again");
+
+    // Go forward again to the test URI.
+    browser.webNavigation.goForward();
+    if (!testcase.expectErrorPage) {
+      await BrowserTestUtils.browserStopped(browser, testcase.uri);
+    } else {
+      await BrowserTestUtils.waitForErrorPage(browser);
+    }
+    let identityModeAgain = window.document.getElementById("identity-box").classList;
+    ok(identityModeAgain.contains(testcase.expectedIdentityMode),
+       `identity should again be ${testcase.expectedIdentityMode}`);
+  });
+}
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media.js
@@ -525,16 +525,20 @@ var gTests = [
     await closeStream();
   },
 },
 
 {
   desc: "'Always Allow' disabled on http pages",
   run: async function checkNoAlwaysOnHttp() {
     // Load an http page instead of the https version.
+    await SpecialPowers.pushPrefEnv({ set: [
+        ["media.devices.insecure.enabled", true],
+        ["media.getusermedia.insecure.enabled", true],
+    ]});
     let browser = gBrowser.selectedBrowser;
     BrowserTestUtils.loadURI(browser, browser.documentURI.spec.replace("https://", "http://"));
     await BrowserTestUtils.browserLoaded(browser);
 
     // Initially set both permissions to 'allow'.
     let Perms = Services.perms;
     let uri = browser.documentURI;
     Perms.add(uri, "microphone", Perms.ALLOW_ACTION);
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -756,17 +756,17 @@
                          label="&appMenuRemoteTabs.label;"
                          closemenu="none"
                          oncommand="PanelUI.showSubView('PanelUI-remotetabs', this)"/>
           <toolbarbutton id="PanelUI-fxa-menu-view-sidebar"
                          class="subviewbutton subviewbutton-iconic"
                          label="&appMenuRemoteTabs.sidebar.label;"
                          oncommand="SidebarUI.toggle('viewTabsSidebar');"/>
           <toolbarseparator/>
-          <toolbarbutton class="subviewbutton" label="&fxa.menu.connectAnotherDevice.label;" oncommand="gSync.openConnectAnotherDevice('fxa_discoverability_native');"/>
+          <toolbarbutton class="subviewbutton" label="&fxa.menu.connectAnotherDevice2.label;" oncommand="gSync.openConnectAnotherDevice('fxa_discoverability_native');"/>
           <toolbarbutton class="subviewbutton" label="&fxa.menu.manageAccount.label;" oncommand="gSync.openFxAManagePage('fxa_discoverability_native');"/>
           <toolbarbutton class="subviewbutton" label="&fxa.menu.syncSettings.label;" oncommand="gSync.openPrefs('fxa_discoverability_native');"/>
           <toolbarseparator/>
           <toolbarbutton id="PanelUI-fxa-menu-syncnow-button"
                          label="&syncSyncNowItem.label;"
                          syncinglabel="&syncSyncNowItemSyncing.label;"
                          class="subviewbutton subviewbutton-iconic"
                          oncommand="gSync.doSync();"
--- a/browser/components/migration/.eslintrc.js
+++ b/browser/components/migration/.eslintrc.js
@@ -7,16 +7,15 @@ module.exports = {
     "indent-legacy": ["error", 2, {"SwitchCase": 1, "ArrayExpression": "first", "ObjectExpression": "first"}],
     "max-nested-callbacks": ["error", 3],
     "new-parens": "error",
     "no-extend-native": "error",
     "no-fallthrough": ["error", { "commentPattern": ".*[Ii]ntentional(?:ly)?\\s+fall(?:ing)?[\\s-]*through.*" }],
     "no-multi-str": "error",
     "no-return-assign": "error",
     "no-shadow": "error",
-    "no-throw-literal": "error",
     "no-unused-vars": ["error", { "args": "after-used", "vars": "all" }],
     "semi-spacing": ["error", {"before": false, "after": true}],
     "space-in-parens": ["error", "never"],
     "strict": ["error", "global"],
     "yoda": "error"
   }
 };
--- a/browser/components/newtab/.eslintrc.js
+++ b/browser/components/newtab/.eslintrc.js
@@ -180,17 +180,16 @@ module.exports = {
     "no-restricted-syntax": 0,
     "no-return-assign": [2, "except-parens"],
     "no-script-url": 2,
     "no-shadow": 2,
     "no-spaced-func": 2,
     "no-sync": 0,
     "no-template-curly-in-string": 2,
     "no-ternary": 0,
-    "no-throw-literal": 2,
     "no-undef-init": 2,
     "no-undefined": 0,
     "no-underscore-dangle": 0,
     "no-unmodified-loop-condition": 2,
     "no-unused-expressions": 2,
     "no-use-before-define": 2,
     "no-useless-computed-key": 2,
     "no-useless-constructor": 2,
--- a/browser/components/payments/.eslintrc.js
+++ b/browser/components/payments/.eslintrc.js
@@ -46,17 +46,16 @@ module.exports = {
     "new-parens": "error",
     "no-console": ["error", { allow: ["error"] }],
     "no-fallthrough": "error",
     "no-multi-str": "error",
     "no-multiple-empty-lines": ["error", {
       max: 2,
     }],
     "no-proto": "error",
-    "no-throw-literal": "error",
     "no-unused-expressions": "error",
     "no-unused-vars": ["error", {
       args: "none",
       vars: "all"
     }],
     "no-use-before-define": ["error", {
       functions: false,
     }],
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -12,17 +12,17 @@ support-files =
 [browser_applications_selection.js]
 [browser_advanced_update.js]
 skip-if = !updater
 [browser_basic_rebuild_fonts_test.js]
 [browser_bug410900.js]
 [browser_bug731866.js]
 [browser_search_no_results_change_category.js]
 [browser_search_within_preferences_1.js]
-skip-if = (os == 'win' && processor == "x86_64") # Bug 1480314
+skip-if = (os == 'win' && (processor == "x86_64" || processor == "aarch64")) # Bug 1480314, aarch64 due to 1536560
 [browser_search_within_preferences_2.js]
 [browser_search_within_preferences_command.js]
 [browser_search_subdialogs_within_preferences_1.js]
 [browser_search_subdialogs_within_preferences_2.js]
 [browser_search_subdialogs_within_preferences_3.js]
 [browser_search_subdialogs_within_preferences_4.js]
 [browser_search_subdialogs_within_preferences_5.js]
 [browser_search_subdialogs_within_preferences_6.js]
@@ -64,16 +64,17 @@ skip-if = (!debug && os == 'win') # Bug 
 [browser_notifications_do_not_disturb.js]
 [browser_password_management.js]
 [browser_performance.js]
 skip-if = !e10s
 [browser_performance_e10srollout.js]
 skip-if = !e10s
 [browser_performance_non_e10s.js]
 skip-if = e10s
+[browser_permissions_checkPermissionsWereAdded.js]
 [browser_permissions_urlFieldHidden.js]
 [browser_proxy_backup.js]
 [browser_privacypane_2.js]
 [browser_privacypane_3.js]
 [browser_sanitizeOnShutdown_prefLocked.js]
 [browser_searchShowSuggestionsFirst.js]
 [browser_searchsuggestions.js]
 [browser_security-1.js]
--- a/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
+++ b/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
@@ -7,194 +7,270 @@ add_task(async function testAllow() {
   await runTest(async (params, observeAllPromise, apply) => {
     assertListContents(params, []);
 
     params.url.value = "test.com";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://test.com", params.allowL10nId],
+      ["https://test.com", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://test.com", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://test.com", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testBlock() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "test.com";
     params.btnBlock.doCommand();
 
     assertListContents(params, [
       ["http://test.com", params.denyL10nId],
+      ["https://test.com", params.denyL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "changed",
-        capability: Ci.nsIPermissionManager.DENY_ACTION  }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  },
+            { type: "cookie", origin: "https://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  }];
+  });
 });
 
 add_task(async function testAllowAgain() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "test.com";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://test.com", params.allowL10nId],
+      ["https://test.com", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "changed",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://test.com", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testRemove() {
   await runTest(async (params, observeAllPromise, apply) => {
-    params.richlistbox.selectedIndex = 0;
-    params.btnRemove.doCommand();
-
+    while (params.richlistbox.itemCount) {
+      params.richlistbox.selectedIndex = 0;
+      params.btnRemove.doCommand();
+    }
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://test.com", data: "deleted" }]);
+  }, (params) => {
+    let richlistItems = params.richlistbox.getElementsByAttribute("origin", "*");
+    let observances = [];
+    for (let item of richlistItems) {
+      observances.push({
+        type: "cookie",
+        origin: item.getAttribute("origin"),
+        data: "deleted",
+      });
+    }
+    return observances;
+  });
 });
 
 add_task(async function testAdd() {
   await runTest(async (params, observeAllPromise, apply) => {
     let uri = Services.io.newURI("http://test.com");
     Services.perms.add(uri, "popup", Ci.nsIPermissionManager.DENY_ACTION);
 
     info("Adding unrelated permission should not change display.");
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
 
     Services.perms.remove(uri, "popup");
-  }, [{ type: "popup", origin: "http://test.com", data: "added",
-        capability: Ci.nsIPermissionManager.DENY_ACTION }]);
+  }, (params) => {
+    return [{ type: "popup", origin: "http://test.com", data: "added",
+              capability: Ci.nsIPermissionManager.DENY_ACTION }];
+  });
 });
 
 add_task(async function testAllowHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "https://test.com:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["https://test.com:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "https://test.com:12345", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testBlockHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "https://test.com:12345";
     params.btnBlock.doCommand();
 
     assertListContents(params, [
       ["https://test.com:12345", params.denyL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.DENY_ACTION  }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  }];
+  });
 });
 
 add_task(async function testAllowAgainHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "https://test.com:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["https://test.com:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testRemoveHTTPSWithPort() {
   await runTest(async (params, observeAllPromise, apply) => {
-    params.richlistbox.selectedIndex = 0;
-    params.btnRemove.doCommand();
+    while (params.richlistbox.itemCount) {
+      params.richlistbox.selectedIndex = 0;
+      params.btnRemove.doCommand();
+    }
 
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "https://test.com:12345", data: "deleted" }]);
+  }, (params) => {
+    let richlistItems = params.richlistbox.getElementsByAttribute("origin", "*");
+    let observances = [];
+    for (let item of richlistItems) {
+      observances.push({
+        type: "cookie",
+        origin: item.getAttribute("origin"),
+        data: "deleted",
+      });
+    }
+    return observances;
+  });
 });
 
 add_task(async function testAllowPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "localhost:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://localhost:12345", params.allowL10nId],
+      ["https://localhost:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://localhost:12345", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://localhost:12345", data: "added",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testBlockPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "localhost:12345";
     params.btnBlock.doCommand();
 
     assertListContents(params, [
       ["http://localhost:12345", params.denyL10nId],
+      ["https://localhost:12345", params.denyL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.DENY_ACTION  }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  },
+            { type: "cookie", origin: "https://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.DENY_ACTION  }];
+  });
 });
 
 add_task(async function testAllowAgainPort() {
   await runTest(async (params, observeAllPromise, apply) => {
     params.url.value = "localhost:12345";
     params.btnAllow.doCommand();
 
     assertListContents(params, [
       ["http://localhost:12345", params.allowL10nId],
+      ["https://localhost:12345", params.allowL10nId],
     ]);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+            { type: "cookie", origin: "https://localhost:12345", data: "changed",
+              capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 add_task(async function testRemovePort() {
   await runTest(async (params, observeAllPromise, apply) => {
-    params.richlistbox.selectedIndex = 0;
-    params.btnRemove.doCommand();
+    while (params.richlistbox.itemCount) {
+      params.richlistbox.selectedIndex = 0;
+      params.btnRemove.doCommand();
+    }
 
     assertListContents(params, []);
 
     apply();
     await observeAllPromise;
-  }, [{ type: "cookie", origin: "http://localhost:12345", data: "deleted" }]);
+  }, (params) => {
+    let richlistItems = params.richlistbox.getElementsByAttribute("origin", "*");
+    let observances = [];
+    for (let item of richlistItems) {
+      observances.push({
+        type: "cookie",
+        origin: item.getAttribute("origin"),
+        data: "deleted",
+      });
+    }
+    return observances;
+  });
 });
 
 add_task(async function testSort() {
   await runTest(async (params, observeAllPromise, apply) => {
     // Sort by site name.
     EventUtils.synthesizeMouseAtCenter(params.doc.getElementById("siteCol"), {},
                                        params.doc.defaultView);
 
@@ -221,37 +297,39 @@ add_task(async function testSort() {
 
     apply();
     await observeAllPromise;
 
     for (let URL of ["http://a", "http://z", "http://b"]) {
       let uri = Services.io.newURI(URL);
       Services.perms.remove(uri, "cookie");
     }
-  }, [{ type: "cookie", origin: "http://a", data: "added",
+  }, (params) => {
+    return [{ type: "cookie", origin: "http://a", data: "added",
         capability: Ci.nsIPermissionManager.ALLOW_ACTION },
       { type: "cookie", origin: "http://z", data: "added",
         capability: Ci.nsIPermissionManager.ALLOW_ACTION },
       { type: "cookie", origin: "http://b", data: "added",
-        capability: Ci.nsIPermissionManager.ALLOW_ACTION }]);
+        capability: Ci.nsIPermissionManager.ALLOW_ACTION }];
+  });
 });
 
 function assertListContents(params, expected) {
   Assert.equal(params.richlistbox.itemCount, expected.length);
+
   for (let i = 0; i < expected.length; i++) {
-    let richlistitem = params.richlistbox.getItemAtIndex(i);
-    Assert.equal(richlistitem.getAttribute("origin"), expected[i][0]);
-    Assert.equal(richlistitem.querySelector(".website-name > label")
-                             .getAttribute("value"), expected[i][0]);
-    Assert.equal(richlistitem.querySelector(".website-capability-value")
+    let website = expected[i][0];
+    let elements = params.richlistbox.getElementsByAttribute("origin", website);
+    Assert.equal(elements.length, 1); // "It should find only one coincidence"
+    Assert.equal(elements[0].querySelector(".website-capability-value")
                              .getAttribute("data-l10n-id"), expected[i][1]);
   }
 }
 
-async function runTest(test, observances) {
+async function runTest(test, getObservances) {
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("privacy.history.custom");
   });
 
   await openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
 
   let doc = gBrowser.contentDocument;
   let historyMode = doc.getElementById("historyMode");
@@ -273,16 +351,17 @@ async function runTest(test, observances
     btnBlock: doc.getElementById("btnBlock"),
     btnRemove: doc.getElementById("removePermission"),
     allowL10nId: win.gPermissionManager._getCapabilityL10nId(Ci.nsIPermissionManager.ALLOW_ACTION),
     denyL10nId: win.gPermissionManager._getCapabilityL10nId(Ci.nsIPermissionManager.DENY_ACTION),
     allow: Ci.nsIPermissionManager.ALLOW_ACTION,
     deny: Ci.nsIPermissionManager.DENY_ACTION,
   };
   let btnApplyChanges = doc.getElementById("btnApplyChanges");
+  let observances = getObservances(params);
   let observeAllPromise = createObserveAllPromise(observances);
 
   await test(params, observeAllPromise, () => btnApplyChanges.doCommand());
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 }
 
 function createObserveAllPromise(observances) {
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_permissions_checkPermissionsWereAdded.js
@@ -0,0 +1,102 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PERMISSIONS_URL = "chrome://browser/content/preferences/permissions.xul";
+
+const _checkAndOpenCookiesDialog = async (doc) => {
+  let cookieExceptionsButton = doc.getElementById("cookieExceptions");
+  ok(cookieExceptionsButton, "cookieExceptionsButton found");
+  let dialogPromise = promiseLoadSubDialog(PERMISSIONS_URL);
+  cookieExceptionsButton.click();
+  let dialog = await dialogPromise;
+  return dialog;
+};
+
+const _checkCookiesDialog = (dialog, buttonIds) => {
+  ok(dialog, "dialog loaded");
+  let urlLabel = dialog.document.getElementById("urlLabel");
+  ok(!urlLabel.hidden, "urlLabel should be visible");
+  let url = dialog.document.getElementById("url");
+  ok(!url.hidden, "url should be visible");
+  for (let buttonId of buttonIds) {
+    let buttonDialog = dialog.document.getElementById(buttonId);
+    ok(buttonDialog, "blockButtonDialog found");
+    is(buttonDialog.hasAttribute("disabled"), true, "If the user hasn't added an url the button shouldn't be clickable");
+  }
+  return dialog;
+};
+
+const _addWebsiteAddressToPermissionBox = (websiteAddress, dialog, buttonId) => {
+  let url = dialog.document.getElementById("url");
+  let buttonDialog = dialog.document.getElementById(buttonId);
+  url.value = websiteAddress;
+  url.dispatchEvent(new Event("input", {bubbles: true}));
+  is(buttonDialog.hasAttribute("disabled"), false, "When the user add an url the button should be clickable");
+  buttonDialog.click();
+  let permissionsBox = dialog.document.getElementById("permissionsBox");
+  let children = permissionsBox.getElementsByAttribute("origin", "*");
+  is(children.length == 0, false, "Website added in url should be in the list");
+};
+
+const _checkIfPermissionsWereAdded = (dialog, expectedResult) => {
+  let permissionsBox = dialog.document.getElementById("permissionsBox");
+  for (let website of expectedResult) {
+    let elements = permissionsBox.getElementsByAttribute("origin", website);
+    is(elements.length, 1, "It should find only one coincidence");
+  }
+};
+
+const _removesAllSitesInPermissionBox = (dialog) => {
+  let removeAllWebsitesButton = dialog.document.getElementById("removeAllPermissions");
+  ok(removeAllWebsitesButton, "removeAllWebsitesButton found");
+  is(removeAllWebsitesButton.hasAttribute("disabled"), false, "There should be websites in the list");
+  removeAllWebsitesButton.click();
+};
+
+add_task(async function checkCookiePermissions() {
+  await openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
+  let win = gBrowser.selectedBrowser.contentWindow;
+  let doc = win.document;
+  let buttonIds = ["btnBlock", "btnSession", "btnAllow"];
+
+  let dialog = await _checkAndOpenCookiesDialog(doc);
+  _checkCookiesDialog(dialog, buttonIds);
+
+  let tests = [{
+      "inputWebsite": "google.com",
+      "expectedResult": ["http://google.com", "https://google.com"],
+    },
+    {
+      "inputWebsite": "https://google.com",
+      "expectedResult": ["https://google.com"],
+    },
+    {
+      "inputWebsite": "http://",
+      "expectedResult": ["http://http", "https://http"],
+    },
+    {
+      "inputWebsite": "s3.eu-central-1.amazonaws.com",
+      "expectedResult": ["http://s3.eu-central-1.amazonaws.com", "https://s3.eu-central-1.amazonaws.com"],
+    },
+    {
+      "inputWebsite": "file://",
+      "expectedResult": ["file:///"],
+    },
+    {
+      "inputWebsite": "about:config",
+      "expectedResult": ["about:config"],
+    },
+  ];
+
+  for (let buttonId of buttonIds) {
+    for (let test of tests) {
+      _addWebsiteAddressToPermissionBox(test.inputWebsite, dialog, buttonId);
+      _checkIfPermissionsWereAdded(dialog, test.expectedResult);
+      _removesAllSitesInPermissionBox(dialog);
+    }
+  }
+
+  gBrowser.removeCurrentTab();
+});
--- a/browser/components/preferences/in-content/tests/browser_site_login_exceptions.js
+++ b/browser/components/preferences/in-content/tests/browser_site_login_exceptions.js
@@ -44,33 +44,42 @@ add_task(async function addALoginExcepti
   let inputBox = doc.getElementById("url");
   inputBox.focus();
 
   EventUtils.sendString("www.example.com", exceptionsDialog);
 
   let btnBlock = doc.getElementById("btnBlock");
   btnBlock.click();
 
-  await TestUtils.waitForCondition(() => richlistbox.itemCount == 1);
+  await TestUtils.waitForCondition(() => richlistbox.itemCount == 2);
 
-  Assert.equal(richlistbox.getItemAtIndex(0).getAttribute("origin"),
-               "http://www.example.com");
+  let expectedResult = ["http://www.example.com", "https://www.example.com"];
+  for (let website of expectedResult) {
+    let elements = richlistbox.getElementsByAttribute("origin", website);
+    is(elements.length, 1, "It should find only one coincidence");
+  }
 });
 
 add_task(async function deleteALoginException() {
   let doc = exceptionsDialog.document;
 
   let richlistbox = doc.getElementById("permissionsBox");
-  Assert.equal(richlistbox.itemCount, 1, "Row count should initially be 1");
+  let currentItems = 2;
+  Assert.equal(richlistbox.itemCount, currentItems,
+               `Row count should initially be ${currentItems}`);
   richlistbox.focus();
-  richlistbox.selectedIndex = 0;
+
+  while (richlistbox.itemCount) {
+    richlistbox.selectedIndex = 0;
 
-  if (AppConstants.platform == "macosx") {
-    EventUtils.synthesizeKey("KEY_Backspace");
-  } else {
-    EventUtils.synthesizeKey("KEY_Delete");
-  }
+    if (AppConstants.platform == "macosx") {
+      EventUtils.synthesizeKey("KEY_Backspace");
+    } else {
+      EventUtils.synthesizeKey("KEY_Delete");
+    }
 
-  await TestUtils.waitForCondition(() => richlistbox.itemCount == 0);
+    currentItems -= 1;
 
-  is_element_visible(content.gSubDialog._dialogs[0]._box,
-    "Subdialog is visible after deleting an element");
+    await TestUtils.waitForCondition(() => richlistbox.itemCount == currentItems);
+    is_element_visible(content.gSubDialog._dialogs[0]._box,
+      "Subdialog is visible after deleting an element");
+  }
 });
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -178,62 +178,72 @@ var gPermissionManager = {
       return;
     if (!this._isCapabilitySupported(perm.capability))
       return;
 
     let p = new Permission(perm.principal, perm.type, perm.capability);
     this._permissions.set(p.origin, p);
   },
 
+  _addOrModifyPermission(principal, capability) {
+    // check whether the permission already exists, if not, add it
+    let permissionParams = {principal, type: this._type, capability};
+    let existingPermission = this._permissions.get(principal.origin);
+    if (!existingPermission) {
+      this._permissionsToAdd.set(principal.origin, permissionParams);
+      this._addPermissionToList(permissionParams);
+      this.buildPermissionsList();
+    } else if (existingPermission.capability != capability) {
+      existingPermission.capability = capability;
+      this._permissionsToAdd.set(principal.origin, permissionParams);
+      this._handleCapabilityChange(existingPermission);
+    }
+  },
+
+  _addNewPrincipalToList(list, uri) {
+    list.push(Services.scriptSecurityManager.createCodebasePrincipal(uri, {}));
+    // If we have ended up with an unknown scheme, the following will throw.
+    list[list.length - 1].origin;
+  },
+
   addPermission(capability) {
     let textbox = document.getElementById("url");
     let input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space
-    let principal;
+    let principals = [];
     try {
       // The origin accessor on the principal object will throw if the
       // principal doesn't have a canonical origin representation. This will
       // help catch cases where the URI parser parsed something like
       // `localhost:8080` as having the scheme `localhost`, rather than being
       // an invalid URI. A canonical origin representation is required by the
       // permission manager for storage, so this won't prevent any valid
       // permissions from being entered by the user.
-      let uri;
       try {
-        uri = Services.io.newURI(input_url);
-        principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
+        let uri = Services.io.newURI(input_url);
+        let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
         if (principal.origin.startsWith("moz-nullprincipal:")) {
           throw "Null principal";
         }
+        principals.push(principal);
       } catch (ex) {
-        uri = Services.io.newURI("http://" + input_url);
-        principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
-        // If we have ended up with an unknown scheme, the following will throw.
-        principal.origin;
+        this._addNewPrincipalToList(principals, Services.io.newURI("http://" + input_url));
+        this._addNewPrincipalToList(principals, Services.io.newURI("https://" + input_url));
       }
     } catch (ex) {
       document.l10n.formatValues([
         {id: "permissions-invalid-uri-title"},
         {id: "permissions-invalid-uri-label"},
       ]).then(([title, message]) => {
         Services.prompt.alert(window, title, message);
       });
       return;
     }
 
-    // check whether the permission already exists, if not, add it
-    let permissionParams = {principal, type: this._type, capability};
-    let existingPermission = this._permissions.get(principal.origin);
-    if (!existingPermission) {
-      this._permissionsToAdd.set(principal.origin, permissionParams);
-      this._addPermissionToList(permissionParams);
-      this.buildPermissionsList();
-    } else if (existingPermission.capability != capability) {
-      existingPermission.capability = capability;
-      this._permissionsToAdd.set(principal.origin, permissionParams);
-      this._handleCapabilityChange(existingPermission);
+    for (let principal of principals) {
+      this._addOrModifyPermission(principal, capability);
     }
 
     textbox.value = "";
     textbox.focus();
 
     // covers a case where the site exists already, so the buttons don't disable
     this.onHostInput(textbox);
 
--- a/browser/extensions/formautofill/.eslintrc.js
+++ b/browser/extensions/formautofill/.eslintrc.js
@@ -83,20 +83,16 @@ module.exports = {
 
     // Disallow usage of __proto__ property.
     "no-proto": "error",
 
     // Disallow use of assignment in return statement. It is preferable for a
     // single line of code to have only one easily predictable effect.
     "no-return-assign": "error",
 
-    // Disallow throwing literals (eg. throw "error" instead of
-    // throw new Error("error")).
-    "no-throw-literal": "error",
-
     // Require use of the second argument for parseInt().
     "radix": "error",
 
     // Enforce spacing after semicolons.
     "semi-spacing": ["error", {"before": false, "after": true}],
 
     // Require "use strict" to be defined globally in the script.
     "strict": ["error", "global"],
--- a/browser/extensions/webcompat-reporter/.eslintrc.js
+++ b/browser/extensions/webcompat-reporter/.eslintrc.js
@@ -78,20 +78,16 @@ module.exports = {
 
     // Disallow usage of __proto__ property.
     "no-proto": "error",
 
     // Disallow use of assignment in return statement. It is preferable for a
     // single line of code to have only one easily predictable effect.
     "no-return-assign": "error",
 
-    // Disallow throwing literals (eg. throw "error" instead of
-    // throw new Error("error")).
-    "no-throw-literal": "error",
-
     // Require use of the second argument for parseInt().
     "radix": "error",
 
     // Enforce spacing after semicolons.
     "semi-spacing": ["error", {"before": false, "after": true}],
 
     // Require "use strict" to be defined globally in the script.
     "strict": ["error", "global"],
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -227,17 +227,17 @@ These should match what Safari and other
 <!ENTITY fxa.unverified.button.label "Open &syncBrand.shortName.label; Settings…">
 
 <!-- LOCALIZATION NOTE (fxa.menu) Used to define the different labels
      for the Firefox Account toolbart menu screen. The `Signed in as` text is
      followed by the user's email. -->
 <!ENTITY fxa.menu.signedInAs.label "Signed in as">
 <!ENTITY fxa.menu.manageAccount.label "Manage Account…">
 <!ENTITY fxa.menu.syncSettings.label "&syncBrand.shortName.label; Settings…">
-<!ENTITY fxa.menu.connectAnotherDevice.label "&syncedTabs.sidebar.connectAnotherDevice;">
+<!ENTITY fxa.menu.connectAnotherDevice2.label "Connect Another Device…">
 <!ENTITY fxa.menu.firefoxAccount "&syncBrand.fxAccount.label;">
 
 <!-- LOCALIZATION NOTE (fullscreenWarning.beforeDomain.label,
      fullscreenWarning.afterDomain.label): these two strings are used
      respectively before and after the domain requiring fullscreen.
      Localizers can use one of them, or both, to better adapt this
      sentence to their language. -->
 <!ENTITY fullscreenWarning.beforeDomain.label "">
--- a/browser/tools/mozscreenshots/browser.ini
+++ b/browser/tools/mozscreenshots/browser.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
 subsuite = screenshots
 support-files =
   head.js
 
 [browser_screenshots.js]
 [browser_screenshots_cropping.js]
+skip-if = (os == "win" && processor == "aarch64") # aarch64 due to bug 1536729
 [browser_boundingbox.js]
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -299,16 +299,17 @@ def build_one_stage(cc, cxx, asm, ld, ar
             cmake_args += [
                 "-DBUILTINS_%s_ANDROID=1" % target,
                 "-DBUILTINS_%s_CMAKE_ASM_FLAGS=%s" % (target, rt_asm_flags),
                 "-DBUILTINS_%s_CMAKE_CXX_FLAGS=%s" % (target, rt_cxx_flags),
                 "-DBUILTINS_%s_CMAKE_C_FLAGS=%s" % (target, rt_c_flags),
                 "-DBUILTINS_%s_CMAKE_EXE_LINKER_FLAGS=%s" % (target, android_link_flags),
                 "-DBUILTINS_%s_CMAKE_SHARED_LINKER_FLAGS=%s" % (target, android_link_flags),
                 "-DBUILTINS_%s_CMAKE_SYSROOT=%s" % (target, sysroot_dir),
+                "-DRUNTIMES_%s_ANDROID=1" % target,
                 "-DRUNTIMES_%s_CMAKE_ASM_FLAGS=%s" % (target, rt_asm_flags),
                 "-DRUNTIMES_%s_CMAKE_CXX_FLAGS=%s" % (target, rt_cxx_flags),
                 "-DRUNTIMES_%s_CMAKE_C_FLAGS=%s" % (target, rt_c_flags),
                 "-DRUNTIMES_%s_CMAKE_EXE_LINKER_FLAGS=%s" % (target, android_link_flags),
                 "-DRUNTIMES_%s_CMAKE_SHARED_LINKER_FLAGS=%s" % (target, android_link_flags),
                 "-DRUNTIMES_%s_CMAKE_SYSROOT=%s" % (target, sysroot_dir),
                 "-DRUNTIMES_%s_COMPILER_RT_BUILD_PROFILE=ON" % target,
                 "-DRUNTIMES_%s_COMPILER_RT_BUILD_SANITIZERS=OFF" % target,
--- a/build/moz.configure/warnings.configure
+++ b/build/moz.configure/warnings.configure
@@ -118,17 +118,23 @@ check_and_add_gcc_warning('-Wno-error=ma
 # we don't want our builds held hostage when a platform-specific API
 # becomes deprecated.
 check_and_add_gcc_warning('-Wno-error=deprecated-declarations')
 
 # false positives depending on optimization
 check_and_add_gcc_warning('-Wno-error=array-bounds')
 
 # can't get rid of those PGO warnings
-check_and_add_gcc_warning('-Wno-error=coverage-mismatch', when='MOZ_PGO')
+check_and_add_gcc_warning('-Wno-error=coverage-mismatch')
+
+# -Wbackend-plugin warnings from Android PGO profile-use builds:
+# error: /builds/worker/workspace/build/src/mozglue/misc/AutoProfilerLabel.cpp:
+#  Function control flow change detected (hash mismatch)
+#  _ZN7mozilla17AutoProfilerLabelD2Ev [-Werror,-Wbackend-plugin]
+check_and_add_gcc_warning('-Wno-error=backend-plugin')
 
 # false positives depending on optimizations
 check_and_add_gcc_warning('-Wno-error=free-nonheap-object')
 
 # Would be a pain to fix all occurrences, for very little gain
 check_and_add_gcc_warning('-Wno-error=multistatement-macros')
 
 # Disable the -Werror for return-std-move because of a false positive
--- a/devtools/.eslintrc.js
+++ b/devtools/.eslintrc.js
@@ -325,19 +325,16 @@ module.exports = {
     // in a small helper function rather than having to come up with another
     // random name.
     // Still, making this a warning can help people avoid being confused.
     "no-shadow": "error",
     // Allow use of synchronous methods (not a node environment).
     "no-sync": "off",
     // Allow the use of ternary operators.
     "no-ternary": "off",
-    // Disallow throwing literals (eg. throw "error" instead of
-    // throw new Error("error")).
-    "no-throw-literal": "error",
     // Allow dangling underscores in identifiers (for privates).
     "no-underscore-dangle": "off",
     // Allow use of undefined variable.
     "no-undefined": "off",
     // Disallow global and local variables that aren't used, but allow unused
     // function arguments.
     "no-unused-vars": ["error", {"args": "none", "vars": "all"}],
     // Allow using variables before they are defined.
--- a/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
+++ b/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
@@ -1,16 +1,18 @@
 /* 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";
 
 const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
+const { gDevTools } = require("devtools/client/framework/devtools");
 const { gDevToolsBrowser } = require("devtools/client/framework/devtools-browser");
+const { Toolbox } = require("devtools/client/framework/toolbox");
 const { remoteClientManager } =
   require("devtools/client/shared/remote-debugging/remote-client-manager");
 
 const { l10n } = require("../modules/l10n");
 
 const {
   debugAddon,
   openTemporaryExtension,
@@ -22,16 +24,19 @@ const {
   getCurrentRuntime,
 } = require("../modules/runtimes-state-helper");
 
 const {
   DEBUG_TARGETS,
   REQUEST_EXTENSIONS_FAILURE,
   REQUEST_EXTENSIONS_START,
   REQUEST_EXTENSIONS_SUCCESS,
+  REQUEST_PROCESSES_FAILURE,
+  REQUEST_PROCESSES_START,
+  REQUEST_PROCESSES_SUCCESS,
   REQUEST_TABS_FAILURE,
   REQUEST_TABS_START,
   REQUEST_TABS_SUCCESS,
   REQUEST_WORKERS_FAILURE,
   REQUEST_WORKERS_START,
   REQUEST_WORKERS_SUCCESS,
   TEMPORARY_EXTENSION_INSTALL_FAILURE,
   TEMPORARY_EXTENSION_INSTALL_START,
@@ -58,16 +63,33 @@ function inspectDebugTarget(type, id) {
           window.open(`about:devtools-toolbox?type=tab&id=${id}`);
         }
         break;
       }
       case DEBUG_TARGETS.EXTENSION: {
         await debugAddon(id, runtimeDetails.clientWrapper.client);
         break;
       }
+      case DEBUG_TARGETS.PROCESS: {
+        const devtoolsClient = runtimeDetails.clientWrapper.client;
+        const processTargetFront = devtoolsClient.getActor(id);
+        const toolbox = await gDevTools.showToolbox(processTargetFront, null,
+          Toolbox.HostType.WINDOW);
+
+        // Once the target is destroyed after closing the toolbox, the front is gone and
+        // can no longer be used. Extensions don't have the issue because we don't list
+        // the target fronts directly, but proxies on which we call connect to create a
+        // target front when we want to inspect them. Local workers don't have this issue
+        // because closing the toolbox stops several workers which will indirectly trigger
+        // a requestWorkers action. However workers on a remote runtime have the exact
+        // same issue.
+        // To workaround the issue we request processes after the toolbox is closed.
+        toolbox.once("destroy", () => dispatch(Actions.requestProcesses()));
+        break;
+      }
       case DEBUG_TARGETS.WORKER: {
         // Open worker toolbox in new window.
         const devtoolsClient = runtimeDetails.clientWrapper.client;
         const front = devtoolsClient.getActor(id);
         gDevToolsBrowser.openWorkerToolbox(front);
         break;
       }
       default: {
@@ -184,16 +206,38 @@ function requestExtensions() {
         temporaryExtensions,
       });
     } catch (e) {
       dispatch({ type: REQUEST_EXTENSIONS_FAILURE, error: e });
     }
   };
 }
 
+function requestProcesses() {
+  return async (dispatch, getState) => {
+    dispatch({ type: REQUEST_PROCESSES_START });
+
+    const clientWrapper = getCurrentClient(getState().runtimes);
+
+    try {
+      const mainProcessFront = await clientWrapper.getMainProcess();
+
+      dispatch({
+        type: REQUEST_PROCESSES_SUCCESS,
+        mainProcess: {
+          id: 0,
+          processFront: mainProcessFront,
+        },
+      });
+    } catch (e) {
+      dispatch({ type: REQUEST_PROCESSES_FAILURE, error: e });
+    }
+  };
+}
+
 function requestWorkers() {
   return async (dispatch, getState) => {
     dispatch({ type: REQUEST_WORKERS_START });
 
     const clientWrapper = getCurrentClient(getState().runtimes);
 
     try {
       const {
@@ -247,12 +291,13 @@ function unregisterServiceWorker(registr
 module.exports = {
   inspectDebugTarget,
   installTemporaryExtension,
   pushServiceWorker,
   reloadTemporaryExtension,
   removeTemporaryExtension,
   requestTabs,
   requestExtensions,
+  requestProcesses,
   requestWorkers,
   startServiceWorker,
   unregisterServiceWorker,
 };
--- a/devtools/client/aboutdebugging-new/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging-new/src/actions/runtimes.js
@@ -9,25 +9,29 @@ const Actions = require("./index");
 const {
   getAllRuntimes,
   getCurrentRuntime,
   findRuntimeById,
 } = require("../modules/runtimes-state-helper");
 
 const { l10n } = require("../modules/l10n");
 const { createClientForRuntime } = require("../modules/runtime-client-factory");
-const { isExtensionDebugSettingNeeded } = require("../modules/debug-target-support");
+const {
+  isExtensionDebugSettingNeeded,
+  isSupportedDebugTargetPane,
+} = require("../modules/debug-target-support");
 
 const { remoteClientManager } =
   require("devtools/client/shared/remote-debugging/remote-client-manager");
 
 const {
   CONNECT_RUNTIME_FAILURE,
   CONNECT_RUNTIME_START,
   CONNECT_RUNTIME_SUCCESS,
+  DEBUG_TARGET_PANE,
   DISCONNECT_RUNTIME_FAILURE,
   DISCONNECT_RUNTIME_START,
   DISCONNECT_RUNTIME_SUCCESS,
   PAGE_TYPES,
   REMOTE_RUNTIMES_UPDATED,
   RUNTIME_PREFERENCE,
   RUNTIMES,
   THIS_FIREFOX_RUNTIME_CREATED,
@@ -255,16 +259,21 @@ function watchRuntime(id) {
 
       // The selected runtime should already have a connected client assigned.
       const runtime = findRuntimeById(id, getState().runtimes);
       await dispatch({ type: WATCH_RUNTIME_SUCCESS, runtime });
 
       dispatch(Actions.requestExtensions());
       dispatch(Actions.requestTabs());
       dispatch(Actions.requestWorkers());
+
+      if (isSupportedDebugTargetPane(runtime.runtimeDetails.info.type,
+                                     DEBUG_TARGET_PANE.PROCESSES)) {
+        dispatch(Actions.requestProcesses());
+      }
     } catch (e) {
       dispatch({ type: WATCH_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function unwatchRuntime(id) {
   return async (dispatch, getState) => {
--- a/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
+++ b/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
@@ -19,16 +19,17 @@ const ExtensionDetail = createFactory(re
 const InspectAction = createFactory(require("./debugtarget/InspectAction"));
 const ProfilerDialog = createFactory(require("./ProfilerDialog"));
 const RuntimeActions = createFactory(require("./RuntimeActions"));
 const RuntimeInfo = createFactory(require("./RuntimeInfo"));
 const ServiceWorkerAction = createFactory(require("./debugtarget/ServiceWorkerAction"));
 const ServiceWorkerAdditionalActions =
   createFactory(require("./debugtarget/ServiceWorkerAdditionalActions"));
 const ServiceWorkersWarning = createFactory(require("./ServiceWorkersWarning"));
+const ProcessDetail = createFactory(require("./debugtarget/ProcessDetail"));
 const TabDetail = createFactory(require("./debugtarget/TabDetail"));
 const TemporaryExtensionAdditionalActions =
   createFactory(require("./debugtarget/TemporaryExtensionAdditionalActions"));
 const TemporaryExtensionDetail = createFactory(require("./debugtarget/TemporaryExtensionDetail"));
 const TemporaryExtensionInstallSection =
   createFactory(require("./debugtarget/TemporaryExtensionInstallSection"));
 const WorkerDetail = createFactory(require("./debugtarget/WorkerDetail"));
 
@@ -43,16 +44,17 @@ class RuntimePage extends PureComponent 
   static get propTypes() {
     return {
       collapsibilities: Types.collapsibilities.isRequired,
       dispatch: PropTypes.func.isRequired,
       installedExtensions: PropTypes.arrayOf(PropTypes.object).isRequired,
       otherWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       runtimeDetails: Types.runtimeDetails,
       runtimeId: PropTypes.string.isRequired,
+      processes: PropTypes.arrayOf(PropTypes.object).isRequired,
       serviceWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       sharedWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       showProfilerDialog: PropTypes.bool.isRequired,
       tabs: PropTypes.arrayOf(PropTypes.object).isRequired,
       temporaryExtensions: PropTypes.arrayOf(PropTypes.object).isRequired,
       temporaryInstallError: PropTypes.object,
     };
   }
@@ -63,16 +65,18 @@ class RuntimePage extends PureComponent 
     const { dispatch, runtimeId } = this.props;
     dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, runtimeId));
   }
 
   getIconByType(type) {
     switch (type) {
       case DEBUG_TARGETS.EXTENSION:
         return "chrome://devtools/skin/images/debugging-addons.svg";
+      case DEBUG_TARGETS.PROCESS:
+        return "chrome://devtools/skin/images/settings.svg";
       case DEBUG_TARGETS.TAB:
         return "chrome://devtools/skin/images/debugging-tabs.svg";
       case DEBUG_TARGETS.WORKER:
         return "chrome://devtools/skin/images/debugging-workers.svg";
     }
 
     throw new Error(`Unsupported type [${ type }]`);
   }
@@ -118,16 +122,17 @@ class RuntimePage extends PureComponent 
     return TemporaryExtensionInstallSection({ dispatch, temporaryInstallError });
   }
 
   render() {
     const {
       dispatch,
       installedExtensions,
       otherWorkers,
+      processes,
       runtimeDetails,
       runtimeId,
       serviceWorkers,
       sharedWorkers,
       showProfilerDialog,
       tabs,
       temporaryExtensions,
     } = this.props;
@@ -197,26 +202,36 @@ class RuntimePage extends PureComponent 
                                  this.getIconByType(DEBUG_TARGETS.WORKER),
                                  otherWorkers,
                                  null,
                                  InspectAction,
                                  null,
                                  WorkerDetail,
                                  DEBUG_TARGET_PANE.OTHER_WORKER,
                                  "about-debugging-runtime-other-workers"),
+      this.renderDebugTargetPane("Processes",
+                                 this.getIconByType(DEBUG_TARGETS.PROCESS),
+                                 processes,
+                                 null,
+                                 InspectAction,
+                                 null,
+                                 ProcessDetail,
+                                 DEBUG_TARGET_PANE.PROCESSES,
+                                 "about-debugging-runtime-processes"),
 
       showProfilerDialog ? ProfilerDialog({ dispatch, runtimeDetails }) : null,
     );
   }
 }
 
 const mapStateToProps = state => {
   return {
     collapsibilities: state.ui.debugTargetCollapsibilities,
     installedExtensions: state.debugTargets.installedExtensions,
+    processes: state.debugTargets.processes,
     otherWorkers: state.debugTargets.otherWorkers,
     runtimeDetails: getCurrentRuntimeDetails(state.runtimes),
     serviceWorkers: state.debugTargets.serviceWorkers,
     sharedWorkers: state.debugTargets.sharedWorkers,
     showProfilerDialog: state.ui.showProfilerDialog,
     tabs: state.debugTargets.tabs,
     temporaryExtensions: state.debugTargets.temporaryExtensions,
     temporaryInstallError: state.ui.temporaryInstallError,
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/ProcessDetail.js
@@ -0,0 +1,27 @@
+/* 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";
+
+const { PureComponent } = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const Types = require("../../types/index");
+
+/**
+ * This component displays detail information for a process.
+ */
+class ProcessDetail extends PureComponent {
+  static get propTypes() {
+    return {
+      target: Types.debugTarget.isRequired,
+    };
+  }
+
+  render() {
+    const { description } = this.props.target.details;
+    return dom.p({ className: "debug-target-item__subname ellipsis-text" }, description);
+  }
+}
+
+module.exports = ProcessDetail;
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/moz.build
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/moz.build
@@ -9,16 +9,17 @@ DevToolsModules(
     'DebugTargetList.js',
     'DebugTargetPane.css',
     'DebugTargetPane.js',
     'ExtensionAction.js',
     'ExtensionDetail.js',
     'FieldPair.css',
     'FieldPair.js',
     'InspectAction.js',
+    'ProcessDetail.js',
     'ServiceWorkerAction.css',
     'ServiceWorkerAction.js',
     'ServiceWorkerAdditionalActions.js',
     'TabDetail.js',
     'TemporaryExtensionAdditionalActions.js',
     'TemporaryExtensionDetail.js',
     'TemporaryExtensionInstaller.js',
     'TemporaryExtensionInstallSection.css',
--- a/devtools/client/aboutdebugging-new/src/constants.js
+++ b/devtools/client/aboutdebugging-new/src/constants.js
@@ -23,16 +23,19 @@ const actionTypes = {
   DISCONNECT_RUNTIME_START: "DISCONNECT_RUNTIME_START",
   DISCONNECT_RUNTIME_SUCCESS: "DISCONNECT_RUNTIME_SUCCESS",
   HIDE_PROFILER_DIALOG: "HIDE_PROFILER_DIALOG",
   NETWORK_LOCATIONS_UPDATED: "NETWORK_LOCATIONS_UPDATED",
   REMOTE_RUNTIMES_UPDATED: "REMOTE_RUNTIMES_UPDATED",
   REQUEST_EXTENSIONS_FAILURE: "REQUEST_EXTENSIONS_FAILURE",
   REQUEST_EXTENSIONS_START: "REQUEST_EXTENSIONS_START",
   REQUEST_EXTENSIONS_SUCCESS: "REQUEST_EXTENSIONS_SUCCESS",
+  REQUEST_PROCESSES_FAILURE: "REQUEST_PROCESSES_FAILURE",
+  REQUEST_PROCESSES_START: "REQUEST_PROCESSES_START",
+  REQUEST_PROCESSES_SUCCESS: "REQUEST_PROCESSES_SUCCESS",
   REQUEST_TABS_FAILURE: "REQUEST_TABS_FAILURE",
   REQUEST_TABS_START: "REQUEST_TABS_START",
   REQUEST_TABS_SUCCESS: "REQUEST_TABS_SUCCESS",
   REQUEST_WORKERS_FAILURE: "REQUEST_WORKERS_FAILURE",
   REQUEST_WORKERS_START: "REQUEST_WORKERS_START",
   REQUEST_WORKERS_SUCCESS: "REQUEST_WORKERS_SUCCESS",
   SELECT_PAGE_FAILURE: "SELECT_PAGE_FAILURE",
   SELECT_PAGE_START: "SELECT_PAGE_START",
@@ -60,22 +63,24 @@ const actionTypes = {
   USB_RUNTIMES_SCAN_SUCCESS: "USB_RUNTIMES_SCAN_SUCCESS",
   WATCH_RUNTIME_FAILURE: "WATCH_RUNTIME_FAILURE",
   WATCH_RUNTIME_START: "WATCH_RUNTIME_START",
   WATCH_RUNTIME_SUCCESS: "WATCH_RUNTIME_SUCCESS",
 };
 
 const DEBUG_TARGETS = {
   EXTENSION: "EXTENSION",
+  PROCESS: "PROCESS",
   TAB: "TAB",
   WORKER: "WORKER",
 };
 
 const DEBUG_TARGET_PANE = {
   INSTALLED_EXTENSION: "installedExtension",
+  PROCESSES: "processes",
   OTHER_WORKER: "otherWorker",
   SERVICE_WORKER: "serviceWorker",
   SHARED_WORKER: "sharedWorker",
   TAB: "tab",
   TEMPORARY_EXTENSION: "temporaryExtension",
 };
 
 const MESSAGE_LEVEL = {
@@ -87,16 +92,18 @@ const MESSAGE_LEVEL = {
 const PAGE_TYPES = {
   RUNTIME: "runtime",
   CONNECT: "connect",
 };
 
 const PREFERENCES = {
   // Temporary preference without any default value until network locations are enabled.
   NETWORK_ENABLED: "devtools.aboutdebugging.network",
+  // Preference that drives the display of the "Processes" debug target category.
+  PROCESS_DEBUGGING_ENABLED: "devtools.aboutdebugging.process-debugging",
   // Preference that drives the display of system addons in about:debugging.
   SHOW_SYSTEM_ADDONS: "devtools.aboutdebugging.showSystemAddons",
   // Temporary preference without any default value until wifi is enabled.
   WIFI_ENABLED: "devtools.aboutdebugging.wifi",
 };
 
 const RUNTIME_PREFERENCE = {
   CHROME_DEBUG_ENABLED: "devtools.chrome.enabled",
--- a/devtools/client/aboutdebugging-new/src/create-store.js
+++ b/devtools/client/aboutdebugging-new/src/create-store.js
@@ -13,16 +13,17 @@ const { waitUntilService } = require("de
 const rootReducer = require("./reducers/index");
 const { DebugTargetsState } = require("./reducers/debug-targets-state");
 const { RuntimesState } = require("./reducers/runtimes-state");
 const { UiState } = require("./reducers/ui-state");
 const debugTargetListenerMiddleware = require("./middleware/debug-target-listener");
 const errorLoggingMiddleware = require("./middleware/error-logging");
 const eventRecordingMiddleware = require("./middleware/event-recording");
 const extensionComponentDataMiddleware = require("./middleware/extension-component-data");
+const processComponentDataMiddleware = require("./middleware/process-component-data");
 const tabComponentDataMiddleware = require("./middleware/tab-component-data");
 const workerComponentDataMiddleware = require("./middleware/worker-component-data");
 const { getDebugTargetCollapsibilities } = require("./modules/debug-target-collapsibilities");
 const { getNetworkLocations } = require("./modules/network-locations");
 
 const { PREFERENCES } = require("./constants");
 
 function configureStore() {
@@ -32,16 +33,17 @@ function configureStore() {
     ui: getUiState(),
   };
 
   const middleware = applyMiddleware(thunk,
                                      debugTargetListenerMiddleware,
                                      errorLoggingMiddleware,
                                      eventRecordingMiddleware,
                                      extensionComponentDataMiddleware,
+                                     processComponentDataMiddleware,
                                      tabComponentDataMiddleware,
                                      workerComponentDataMiddleware,
                                      waitUntilService);
 
   return createStore(rootReducer, initialState, middleware);
 }
 
 function getUiState() {
--- a/devtools/client/aboutdebugging-new/src/middleware/debug-target-listener.js
+++ b/devtools/client/aboutdebugging-new/src/middleware/debug-target-listener.js
@@ -32,32 +32,30 @@ function debugTargetListenerMiddleware(s
         // Tabs
         clientWrapper.addListener("tabListChanged", onTabsUpdated);
 
         // Addons
         clientWrapper.addListener("addonListChanged", onExtensionsUpdated);
 
         // Workers
         clientWrapper.addListener("workersUpdated", onWorkersUpdated);
-
         break;
       }
       case UNWATCH_RUNTIME_START: {
         const { runtime } = action;
         const { clientWrapper } = runtime.runtimeDetails;
 
         // Tabs
         clientWrapper.removeListener("tabListChanged", onTabsUpdated);
 
         // Addons
         clientWrapper.removeListener("addonListChanged", onExtensionsUpdated);
 
         // Workers
         clientWrapper.removeListener("workersUpdated", onWorkersUpdated);
-
         break;
       }
     }
 
     return next(action);
   };
 }
 
--- a/devtools/client/aboutdebugging-new/src/middleware/moz.build
+++ b/devtools/client/aboutdebugging-new/src/middleware/moz.build
@@ -2,11 +2,12 @@
 # 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/.
 
 DevToolsModules(
     'debug-target-listener.js',
     'error-logging.js',
     'event-recording.js',
     'extension-component-data.js',
+    'process-component-data.js',
     'tab-component-data.js',
     'worker-component-data.js',
 )
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/middleware/process-component-data.js
@@ -0,0 +1,49 @@
+/* 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";
+
+const { l10n } = require("../modules/l10n");
+
+const {
+  DEBUG_TARGETS,
+  REQUEST_PROCESSES_SUCCESS,
+} = require("../constants");
+
+/**
+ * This middleware converts tabs object that get from DebuggerClient.listProcesses() to
+ * data which is used in DebugTargetItem.
+ */
+const processComponentDataMiddleware = store => next => action => {
+  switch (action.type) {
+    case REQUEST_PROCESSES_SUCCESS: {
+      const mainProcessComponentData = toMainProcessComponentData(action.mainProcess);
+      action.processes = [mainProcessComponentData];
+      break;
+    }
+  }
+
+  return next(action);
+};
+
+function toMainProcessComponentData(process) {
+  const type = DEBUG_TARGETS.PROCESS;
+  const id = process.processFront.actorID;
+  const icon = "chrome://devtools/skin/images/settings.svg";
+  const name = l10n.getString("about-debugging-main-process-name");
+  const description = l10n.getString("about-debugging-main-process-description");
+
+  return {
+    name,
+    icon,
+    id,
+    type,
+    details: {
+      description,
+      processId: process.id,
+    },
+  };
+}
+
+module.exports = processComponentDataMiddleware;
--- a/devtools/client/aboutdebugging-new/src/modules/client-wrapper.js
+++ b/devtools/client/aboutdebugging-new/src/modules/client-wrapper.js
@@ -135,16 +135,20 @@ class ClientWrapper {
   async listAddons(options) {
     return this.client.mainRoot.listAddons(options);
   }
 
   async getAddon({ id }) {
     return this.client.mainRoot.getAddon({ id });
   }
 
+  async getMainProcess() {
+    return this.client.mainRoot.getMainProcess();
+  }
+
   async getServiceWorkerFront({ id }) {
     const { serviceWorkers } = await this.listWorkers();
     const workerFronts = serviceWorkers.map(sw => sw.workerTargetFront);
     return workerFronts.find(front => front && front.actorID === id);
   }
 
   async listWorkers() {
     const { other, service, shared } = await this.client.mainRoot.listAllWorkers();
--- a/devtools/client/aboutdebugging-new/src/modules/debug-target-support.js
+++ b/devtools/client/aboutdebugging-new/src/modules/debug-target-support.js
@@ -1,31 +1,45 @@
 /* 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";
 
-const { DEBUG_TARGET_PANE, RUNTIMES } = require("../constants");
+const { DEBUG_TARGET_PANE, PREFERENCES, RUNTIMES } = require("../constants");
+
+const Services = require("Services");
+
+// Process target debugging is disabled by default.
+function isProcessDebuggingSupported() {
+  return Services.prefs.getBoolPref(PREFERENCES.PROCESS_DEBUGGING_ENABLED, false);
+}
 
 const ALL_DEBUG_TARGET_PANES = [
   DEBUG_TARGET_PANE.INSTALLED_EXTENSION,
+  ...(isProcessDebuggingSupported() ? [DEBUG_TARGET_PANE.PROCESSES] : []),
   DEBUG_TARGET_PANE.OTHER_WORKER,
   DEBUG_TARGET_PANE.SERVICE_WORKER,
   DEBUG_TARGET_PANE.SHARED_WORKER,
   DEBUG_TARGET_PANE.TAB,
   DEBUG_TARGET_PANE.TEMPORARY_EXTENSION,
 ];
 
 // All debug target panes except temporary extensions
 const REMOTE_DEBUG_TARGET_PANES = ALL_DEBUG_TARGET_PANES.filter(p =>
   p !== DEBUG_TARGET_PANE.TEMPORARY_EXTENSION);
 
+// Main process debugging is not available for This Firefox.
+// At the moment only the main process is listed under processes, so remove the category
+// for this runtime.
+const THIS_FIREFOX_DEBUG_TARGET_PANES = ALL_DEBUG_TARGET_PANES.filter(p =>
+  p !== DEBUG_TARGET_PANE.PROCESSES);
+
 const SUPPORTED_TARGET_PANE_BY_RUNTIME = {
-  [RUNTIMES.THIS_FIREFOX]: ALL_DEBUG_TARGET_PANES,
+  [RUNTIMES.THIS_FIREFOX]: THIS_FIREFOX_DEBUG_TARGET_PANES,
   [RUNTIMES.USB]: REMOTE_DEBUG_TARGET_PANES,
   [RUNTIMES.NETWORK]: REMOTE_DEBUG_TARGET_PANES,
 };
 
 /**
  * If extension debug setting is needed for given runtime type, return true.
  *
  * @param {String} runtimeType
--- a/devtools/client/aboutdebugging-new/src/reducers/debug-targets-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/debug-targets-state.js
@@ -1,41 +1,47 @@
 /* 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";
 
 const {
   REQUEST_EXTENSIONS_SUCCESS,
+  REQUEST_PROCESSES_SUCCESS,
   REQUEST_TABS_SUCCESS,
   REQUEST_WORKERS_SUCCESS,
   UNWATCH_RUNTIME_SUCCESS,
 } = require("../constants");
 
 function DebugTargetsState() {
   return {
     installedExtensions: [],
     otherWorkers: [],
+    processes: [],
     serviceWorkers: [],
     sharedWorkers: [],
     tabs: [],
     temporaryExtensions: [],
   };
 }
 
 function debugTargetsReducer(state = DebugTargetsState(), action) {
   switch (action.type) {
     case UNWATCH_RUNTIME_SUCCESS: {
       return DebugTargetsState();
     }
     case REQUEST_EXTENSIONS_SUCCESS: {
       const { installedExtensions, temporaryExtensions } = action;
       return Object.assign({}, state, { installedExtensions, temporaryExtensions });
     }
+    case REQUEST_PROCESSES_SUCCESS: {
+      const { processes } = action;
+      return Object.assign({}, state, { processes });
+    }
     case REQUEST_TABS_SUCCESS: {
       const { tabs } = action;
       return Object.assign({}, state, { tabs });
     }
     case REQUEST_WORKERS_SUCCESS: {
       const { otherWorkers, serviceWorkers, sharedWorkers } = action;
       return Object.assign({}, state, { otherWorkers, serviceWorkers, sharedWorkers });
     }
--- a/devtools/client/aboutdebugging-new/src/types/debug-target.js
+++ b/devtools/client/aboutdebugging-new/src/types/debug-target.js
@@ -14,16 +14,23 @@ const extensionTargetDetails = {
   // local extensions so it might be null.
   manifestURL: PropTypes.string,
   // unique extension id.
   uuid: PropTypes.string.isRequired,
   // warning messages forwarded from the addon manager.
   warnings: PropTypes.arrayOf(PropTypes.string).isRequired,
 };
 
+const processTargetDetails = {
+  // Description for the process.
+  description: PropTypes.string.isRequired,
+  // The id for the process. #0 is the main/parent process, #1++ are parent processes
+  processId: PropTypes.number.isRequired,
+};
+
 const tabTargetDetails = {
   // the url of the tab.
   url: PropTypes.string.isRequired,
 };
 
 const workerTargetDetails = {
   // (service worker specific) one of "LISTENING", "NOT_LISTENING". undefined otherwise.
   fetch: PropTypes.string,
@@ -34,16 +41,17 @@ const workerTargetDetails = {
   // (service worker specific) one of "RUNNING", "REGISTERING", "STOPPED".
   status: PropTypes.string,
 };
 
 const debugTarget = {
   // details property will contain a type-specific object.
   details: PropTypes.oneOfType([
     PropTypes.shape(extensionTargetDetails),
+    PropTypes.shape(processTargetDetails),
     PropTypes.shape(tabTargetDetails),
     PropTypes.shape(workerTargetDetails),
   ]).isRequired,
   // icon to display for the debug target.
   icon: PropTypes.string.isRequired,
   // unique id for the target (unique in the scope of the application lifecycle).
   // - extensions: {String} extension id (for instance "someextension@mozilla.org")
   // - tabs: {Number} outerWindowID
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -57,16 +57,18 @@ skip-if = (os == 'linux' && bits == 32) 
 [browser_aboutdebugging_devtoolstoolbox_contextmenu_markupview.js]
 [browser_aboutdebugging_devtoolstoolbox_menubar.js]
 [browser_aboutdebugging_devtoolstoolbox_reload.js]
 [browser_aboutdebugging_devtoolstoolbox_shortcuts.js]
 skip-if = (os == "win" && ccov) # Bug 1521349
 [browser_aboutdebugging_devtoolstoolbox_tooltip_markupview.js]
 [browser_aboutdebugging_navigate.js]
 [browser_aboutdebugging_persist_connection.js]
+[browser_aboutdebugging_process_category.js]
+[browser_aboutdebugging_process_main.js]
 [browser_aboutdebugging_profiler_dialog.js]
 [browser_aboutdebugging_real_usb_runtime_page_runtime_info.js]
 [browser_aboutdebugging_real_usb_sidebar.js]
 [browser_aboutdebugging_routes.js]
 [browser_aboutdebugging_runtime_compatibility_warning.js]
 [browser_aboutdebugging_runtime_disconnect_remote_runtime.js]
 [browser_aboutdebugging_runtime_remote_runtime_buttons.js]
 [browser_aboutdebugging_runtime_usbclient_closed.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_process_category.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const CATEGORY_NAME = "Processes";
+const RUNTIME_ID = "test-runtime-id";
+const RUNTIME_DEVICE_NAME = "test device name";
+const RUNTIME_APP_NAME = "TestApp";
+
+// Test whether process category exists by the runtime type.
+add_task(async function() {
+  await pushPref("devtools.aboutdebugging.process-debugging", true);
+
+  const mocks = new Mocks();
+
+  const { document, tab, window } = await openAboutDebugging();
+  await selectThisFirefoxPage(document, window.AboutDebugging.store);
+
+  const usbRuntime = mocks.createUSBRuntime(RUNTIME_ID, {
+    deviceName: RUNTIME_DEVICE_NAME,
+    name: RUNTIME_APP_NAME,
+  });
+  usbRuntime.getMainProcess = () => {
+    return { actorID: 0 };
+  };
+  mocks.emitUSBUpdate();
+
+  info("Check the process category existence for this firefox");
+  ok(!getDebugTargetPane(CATEGORY_NAME, document),
+     "Process category should not display for this firefox");
+
+  info("Check the process category existence for USB runtime");
+  await connectToRuntime(RUNTIME_DEVICE_NAME, document);
+  await selectRuntime(RUNTIME_DEVICE_NAME, RUNTIME_APP_NAME, document);
+  ok(getDebugTargetPane(CATEGORY_NAME, document),
+     "Process category should display for USB runtime");
+
+  info("Remove USB runtime");
+  mocks.removeUSBRuntime(RUNTIME_ID);
+  mocks.emitUSBUpdate();
+  info("Wait until the USB sidebar item disappears");
+  await waitUntil(() => !findSidebarItemByText(RUNTIME_DEVICE_NAME, document));
+
+  await removeTab(tab);
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_process_main.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* import-globals-from helper-collapsibilities.js */
+Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-collapsibilities.js", this);
+
+const MAIN_PROCESS_NAME = "Main Process";
+const RUNTIME_ID = "test-runtime-id";
+const RUNTIME_DEVICE_NAME = "test device name";
+const RUNTIME_APP_NAME = "TestApp";
+
+// Test whether process category exists by the runtime type.
+add_task(async function() {
+  await pushPref("devtools.aboutdebugging.process-debugging", true);
+
+  const mocks = new Mocks();
+
+  const { document, tab } = await openAboutDebugging();
+
+  const usbRuntime = mocks.createUSBRuntime(RUNTIME_ID, {
+    deviceName: RUNTIME_DEVICE_NAME,
+    name: RUNTIME_APP_NAME,
+  });
+  usbRuntime.getMainProcess = () => {
+    return { actorID: 0 };
+  };
+  mocks.emitUSBUpdate();
+
+  info("Select USB runtime");
+  await connectToRuntime(RUNTIME_DEVICE_NAME, document);
+  await selectRuntime(RUNTIME_DEVICE_NAME, RUNTIME_APP_NAME, document);
+
+  info("Check debug target item of the main process");
+  const mainProcessItem = findDebugTargetByText(MAIN_PROCESS_NAME, document);
+  ok(mainProcessItem, "Debug target item of the main process should display");
+  ok(mainProcessItem.textContent.includes("Main Process for the target runtime"),
+     "Debug target item of the main process should contains the description");
+
+  info("Remove USB runtime");
+  mocks.removeUSBRuntime(RUNTIME_ID);
+  mocks.emitUSBUpdate();
+  info("Wait until the USB sidebar item disappears");
+  await waitUntil(() => !findSidebarItemByText(RUNTIME_DEVICE_NAME, document));
+
+  await removeTab(tab);
+});
--- a/devtools/client/aboutdebugging-new/test/browser/mocks/helper-client-wrapper-mock.js
+++ b/devtools/client/aboutdebugging-new/test/browser/mocks/helper-client-wrapper-mock.js
@@ -65,25 +65,29 @@ function createClientMock() {
       }
       if (prefName in DEFAULT_PREFERENCES) {
         return DEFAULT_PREFERENCES[prefName];
       }
       return null;
     },
     // Empty array of addons
     listAddons: () => [],
+    // Empty array of processes
+    listProcesses: () => [],
     // Empty array of tabs
     listTabs: () => [],
     // Empty arrays of workers
     listWorkers: () => ({
       otherWorkers: [],
       serviceWorkers: [],
       sharedWorkers: [],
     }),
     // no-op
+    getMainProcess: () => {},
+    // no-op
     getFront: () => {},
     // no-op
     onFront: () => {},
     // stores the preference locally (doesn't update about:config)
     setPreference: function(prefName, value) {
       this._preferences[prefName] = value;
     },
     getPerformancePanelUrl: () => "data:text/html;charset=UTF-8,fake_profiler_page",
@@ -114,9 +118,8 @@ function createThisFirefoxClientMock() {
 
   const mockThisFirefoxClient = createClientMock();
   mockThisFirefoxClient.listTabs = () => ([mockAboutDebuggingTab]);
   mockThisFirefoxClient.getDeviceDescription = () => mockThisFirefoxDescription;
 
   return mockThisFirefoxClient;
 }
 /* exported createThisFirefoxClientMock */
-
--- a/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
+++ b/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
@@ -302,8 +302,12 @@ about-debugging-profiler-dialog-title = 
 # The "Learn more" link points to MDN.
 # https://developer.mozilla.org/docs/Tools/about:debugging#Enabling_add-on_debugging
 about-debugging-extension-debug-setting-label = Enable extension debugging <a>Learn more</a>
 
 # Clicking on the header of a debug target category will expand or collapse the debug
 # target items in the category. This text is used as ’title’ attribute of the header,
 # to describe this feature.
 about-debugging-collapse-expand-debug-targets = Collapse / expand
+
+about-debugging-main-process-name = Main Process
+about-debugging-main-process-description = Main Process for the target runtime
+
--- a/devtools/client/locales/en-US/responsive.properties
+++ b/devtools/client/locales/en-US/responsive.properties
@@ -65,51 +65,48 @@ responsive.devicePixelRatio.auto=Device 
 # device).
 responsive.customDeviceName=Custom Device
 
 # LOCALIZATION NOTE (responsive.customDeviceNameFromBase): Default value in a
 # form to add a custom device based on the properties of another.  %1$S is the
 # name of the device we're staring from, such as "Apple iPhone 6".
 responsive.customDeviceNameFromBase=%1$S (Custom)
 
-# LOCALIZATION NOTE (responsive.addDevice): Button text that reveals a form to
+# LOCALIZATION NOTE (responsive.addDevice2): Button text that reveals a form to
 # be used for adding custom devices.
-responsive.addDevice=Add Device
+responsive.addDevice2=Add Custom Device…
 
 # LOCALIZATION NOTE (responsive.deviceAdderName): Label of form field for the
-# name of a new device.  The available width is very low, so you might see
-# overlapping text if the length is much longer than 5 or so characters.
+# name of a new device.
 responsive.deviceAdderName=Name
 
 # LOCALIZATION NOTE (responsive.deviceAdderSize): Label of form field for the
-# size of a new device.  The available width is very low, so you might see
-# overlapping text if the length is much longer than 5 or so characters.
+# size of a new device.
 responsive.deviceAdderSize=Size
 
-# LOCALIZATION NOTE (responsive.deviceAdderPixelRatio): Label of form field for
-# the device pixel ratio of a new device.  The available width is very low, so you
-# might see overlapping text if the length is much longer than 5 or so
-# characters.
-responsive.deviceAdderPixelRatio=DPR
+# LOCALIZATION NOTE (responsive.deviceAdderPixelRatio2): Label of form field for
+# the device pixel ratio of a new device.
+responsive.deviceAdderPixelRatio2=Device Pixel Ratio
 
-# LOCALIZATION NOTE (responsive.deviceAdderUserAgent): Label of form field for
-# the user agent of a new device.  The available width is very low, so you might
-# see overlapping text if the length is much longer than 5 or so characters.
-responsive.deviceAdderUserAgent=UA
+# LOCALIZATION NOTE (responsive.deviceAdderUserAgent2): Label of form field for
+# the user agent of a new device.
+responsive.deviceAdderUserAgent2=User Agent String
 
-# LOCALIZATION NOTE (responsive.deviceAdderTouch): Label of form field for the
-# touch input support of a new device.  The available width is very low, so you
-# might see overlapping text if the length is much longer than 5 or so
-# characters.
-responsive.deviceAdderTouch=Touch
+# LOCALIZATION NOTE (responsive.deviceAdderTouch2): Label of form field for the
+# touch input support of a new device.
+responsive.deviceAdderTouch2=Touch Screen
 
 # LOCALIZATION NOTE (responsive.deviceAdderSave): Button text that submits a
 # form to add a new device.
 responsive.deviceAdderSave=Save
 
+# LOCALIZATION NOTE (responsive.deviceAdderCancel): Button text that cancels a
+# form to add a new device.
+responsive.deviceAdderCancel=Cancel
+
 # LOCALIZATION NOTE (responsive.deviceDetails): Tooltip that appears when
 # hovering on a device in the device modal.  %1$S is the width of the device.
 # %2$S is the height of the device.  %3$S is the device pixel ratio value of the
 # device.  %4$S is the user agent of the device.  %5$S is a boolean value
 # noting whether touch input is supported.
 responsive.deviceDetails=Size: %1$S x %2$S\nDPR: %3$S\nUA: %4$S\nTouch: %5$S
 
 # LOCALIZATION NOTE (responsive.devicePixelRatioOption): UI option in a menu to configure
@@ -137,8 +134,16 @@ responsive.leftAlignViewport=Left-align 
 # Responsive Design Mode.
 responsive.settingOnboarding.content=New: Change to left-alignment or edit reload behavior here.
 
 # LOCALIZATION NOTE (responsive.customUserAgent): This is the placeholder for the user
 # agent input in the responsive design mode toolbar.
 responsive.customUserAgent=Custom User Agent
 
 responsive.showUserAgentInput=Show user agent
+
+# LOCALIZATION NOTE (responsive.deviceSettings): The header text for the device settings
+# view.
+responsive.deviceSettings=Device Settings
+
+# LOCALIZATION NOTE (responsive.deviceNameAlreadyInUse): This is the text shown when adding a new
+# device with an already existing device name.
+responsive.deviceNameAlreadyInUse=Device name already in use
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -340,16 +340,18 @@ pref("devtools.responsive.showUserAgentI
 #endif
 
 // Enable new about:debugging.
 pref("devtools.aboutdebugging.new-enabled", false);
 // Enable the network location feature.
 pref("devtools.aboutdebugging.network", false);
 // Enable the wifi feature.
 pref("devtools.aboutdebugging.wifi", false);
+// Show process debug targets.
+pref("devtools.aboutdebugging.process-debugging", false);
 // Stringified array of network locations that users can connect to.
 pref("devtools.aboutdebugging.network-locations", "[]");
 // Debug target pane collapse/expand settings.
 pref("devtools.aboutdebugging.collapsibilities.installedExtension", false);
 pref("devtools.aboutdebugging.collapsibilities.otherWorker", false);
 pref("devtools.aboutdebugging.collapsibilities.serviceWorker", false);
 pref("devtools.aboutdebugging.collapsibilities.sharedWorker", false);
 pref("devtools.aboutdebugging.collapsibilities.tab", false);
new file mode 100644
--- /dev/null
+++ b/devtools/client/responsive.html/components/Device.js
@@ -0,0 +1,79 @@
+/* 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/. */
+
+/* eslint-env browser */
+
+"use strict";
+
+const { PureComponent } = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+
+const { getFormatStr } = require("../utils/l10n");
+const Types = require("../types");
+
+class Device extends PureComponent {
+  static get propTypes() {
+    return {
+      // props.children are the buttons rendered as part of custom device label.
+      children: PropTypes.oneOfType([
+        PropTypes.arrayOf(PropTypes.node),
+        PropTypes.node,
+      ]),
+      device: PropTypes.shape(Types.devices).isRequired,
+      onDeviceCheckboxChange: PropTypes.func.isRequired,
+    };
+  }
+
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      // Whether or not the device's input label is checked.
+      isChecked: this.props.device.isChecked,
+    };
+
+    this.onCheckboxChanged = this.onCheckboxChanged.bind(this);
+  }
+
+  onCheckboxChanged(e) {
+    this.setState(prevState => {
+      return { isChecked: !prevState.isChecked };
+    });
+
+    this.props.onDeviceCheckboxChange(e);
+  }
+
+  render() {
+    const { children, device } = this.props;
+    const details = getFormatStr(
+      "responsive.deviceDetails", device.width, device.height,
+      device.pixelRatio, device.userAgent, device.touch
+    );
+
+    return (
+      dom.label(
+        {
+          className: "device-label",
+          key: device.name,
+          title: details,
+        },
+        dom.input({
+          className: "device-input-checkbox",
+          name: device.name,
+          type: "checkbox",
+          value: device.name,
+          checked: device.isChecked,
+          onChange: this.onCheckboxChanged,
+        }),
+        dom.span({ className: "device-name" },
+          device.name
+        ),
+        children
+      )
+    );
+  }
+}
+
+module.exports = Device;
new file mode 100644
--- /dev/null
+++ b/devtools/client/responsive.html/components/DeviceForm.js
@@ -0,0 +1,186 @@
+/* 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/. */
+
+/* eslint-env browser */
+
+"use strict";
+
+const { createFactory, createRef, PureComponent } = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+
+const ViewportDimension = createFactory(require("./ViewportDimension"));
+
+const { getStr } = require("../utils/l10n");
+const Types = require("../types");
+
+class DeviceForm extends PureComponent {
+  static get propTypes() {
+    return {
+      buttonText: PropTypes.string,
+      formType: PropTypes.string.isRequired,
+      device: PropTypes.shape(Types.device).isRequired,
+      onSave: PropTypes.func.isRequired,
+      validateName: PropTypes.func.isRequired,
+      viewportTemplate: PropTypes.shape(Types.viewport).isRequired,
+      onDeviceFormHide: PropTypes.func.isRequired,
+      onDeviceFormShow: PropTypes.func.isRequired,
+    };
+  }
+
+  constructor(props) {
+    super(props);
+
+    const {
+      height,
+      width,
+    } = this.props.viewportTemplate;
+
+    this.state = {
+      isShown: false,
+      height,
+      width,
+    };
+
+    this.nameInputRef = createRef();
+    this.pixelRatioInputRef = createRef();
+    this.touchInputRef = createRef();
+    this.userAgentInputRef = createRef();
+
+    this.onChangeSize = this.onChangeSize.bind(this);
+    this.onDeviceFormHide  = this.onDeviceFormHide.bind(this);
+    this.onDeviceFormShow = this.onDeviceFormShow.bind(this);
+    this.onDeviceFormSave = this.onDeviceFormSave.bind(this);
+  }
+
+  onChangeSize(_, width, height) {
+    this.setState({
+      width,
+      height,
+    });
+  }
+
+  onDeviceFormSave() {
+    if (!this.pixelRatioInputRef.current.checkValidity()) {
+      return;
+    }
+
+    if (!this.props.validateName(this.nameInputRef.current.value)) {
+      this.nameInputRef.current
+        .setCustomValidity(getStr("responsive.deviceNameAlreadyInUse"));
+      return;
+    }
+
+    this.props.onSave({
+      name: this.nameInputRef.current.value.trim(),
+      width: this.state.width,
+      height: this.state.height,
+      pixelRatio: parseFloat(this.pixelRatioInputRef.current.value),
+      userAgent: this.userAgentInputRef.current.value,
+      touch: this.touchInputRef.current.checked,
+    });
+
+    this.onDeviceFormHide();
+  }
+
+  onDeviceFormHide() {
+    this.setState({ isShown: false });
+
+    // Ensure that we have onDeviceFormHide before calling it.
+    if (this.props.onDeviceFormHide) {
+      this.props.onDeviceFormHide();
+    }
+  }
+
+  onDeviceFormShow() {
+    this.setState({ isShown: true });
+
+    // Ensure that we have onDeviceFormShow before calling it.
+    if (this.props.onDeviceFormShow) {
+      this.props.onDeviceFormShow();
+    }
+  }
+
+  render() {
+    const { buttonText, device, formType } = this.props;
+    const { isShown, width, height } = this.state;
+
+    if (!isShown) {
+      return (
+        dom.button(
+          {
+            id: `device-${formType}-button`,
+            className: "devtools-button",
+            onClick: this.onDeviceFormShow,
+          },
+          buttonText,
+        )
+      );
+    }
+
+    return (
+      dom.form({ id: "device-form" },
+        dom.label({ id: "device-form-name", className: formType },
+          dom.span({ className: "device-form-label" },
+            getStr("responsive.deviceAdderName")
+          ),
+          dom.input({
+            defaultValue: device.name,
+            ref: this.nameInputRef,
+          })
+        ),
+        dom.label({ id: "device-form-size" },
+          dom.span({ className: "device-form-label" },
+            getStr("responsive.deviceAdderSize")
+          ),
+          ViewportDimension({
+            viewport: { width, height },
+            doResizeViewport: this.onChangeSize,
+            onRemoveDeviceAssociation: () => {},
+          })
+        ),
+        dom.label({ id: "device-form-pixel-ratio" },
+          dom.span({ className: "device-form-label" },
+            getStr("responsive.deviceAdderPixelRatio2")
+          ),
+          dom.input({
+            type: "number",
+            step: "any",
+            defaultValue: device.pixelRatio,
+            ref: this.pixelRatioInputRef,
+          })
+        ),
+        dom.label({ id: "device-form-user-agent" },
+          dom.span({ className: "device-form-label" },
+            getStr("responsive.deviceAdderUserAgent2")
+          ),
+          dom.input({
+            defaultValue: device.userAgent,
+            ref: this.userAgentInputRef,
+          })
+        ),
+        dom.label({ id: "device-form-touch" },
+          dom.input({
+            defaultChecked: device.touch,
+            type: "checkbox",
+            ref: this.touchInputRef,
+          }),
+          dom.span({ className: "device-form-label" },
+            getStr("responsive.deviceAdderTouch2")
+          )
+        ),
+        dom.div({ className: "device-form-buttons" },
+          dom.button({ id: "device-form-save", onClick: this.onDeviceFormSave },
+            getStr("responsive.deviceAdderSave")
+          ),
+          dom.button({ id: "device-form-cancel", onClick: this.onDeviceFormHide },
+            getStr("responsive.deviceAdderCancel")
+          )
+        )
+      )
+    );
+  }
+}
+
+module.exports = DeviceForm;
new file mode 100644
--- /dev/null
+++ b/devtools/client/responsive.html/components/DeviceList.js
@@ -0,0 +1,70 @@
+/* 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/. */
+
+/* eslint-env browser */
+
+"use strict";
+
+const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+
+const Types = require("../types");
+
+const Device = createFactory(require("./Device"));
+
+class DeviceList extends PureComponent {
+  static get propTypes() {
+    return {
+      devices: PropTypes.shape(Types.devices).isRequired,
+      onDeviceCheckboxChange: PropTypes.func.isRequired,
+      onRemoveCustomDevice: PropTypes.func.isRequired,
+      type: PropTypes.string.isRequired,
+    };
+  }
+
+  renderCustomDevice(device) {
+    const { onRemoveCustomDevice, onDeviceCheckboxChange, type } = this.props;
+
+    // Show a remove button for custom devices.
+    const removeDeviceButton = dom.button({
+        id: "device-editor-remove",
+        className: "device-remove-button devtools-button",
+        onClick: () => onRemoveCustomDevice(device),
+    });
+
+    return Device(
+      {
+        device,
+        key: device.name,
+        type,
+        onDeviceCheckboxChange,
+      },
+      removeDeviceButton
+    );
+  }
+
+  render() {
+    const { devices, type, onDeviceCheckboxChange } = this.props;
+
+    return (
+      dom.div({ className: "device-list"},
+        devices[type].map(device => {
+          if (type === "custom") {
+            return this.renderCustomDevice(device);
+          }
+
+          return Device({
+            device,
+            key: device.name,
+            type,
+            onDeviceCheckboxChange,
+          });
+        })
+      )
+    );
+  }
+}
+
+module.exports = DeviceList;
--- a/devtools/client/responsive.html/components/DeviceModal.js
+++ b/devtools/client/responsive.html/components/DeviceModal.js
@@ -5,19 +5,20 @@
 /* eslint-env browser */
 
 "use strict";
 
 const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
-const DeviceAdder = createFactory(require("./DeviceAdder"));
+const DeviceForm = createFactory(require("./DeviceForm"));
+const DeviceList = createFactory(require("./DeviceList"));
 
-const { getStr, getFormatStr } = require("../utils/l10n");
+const { getFormatStr, getStr } = require("../utils/l10n");
 const Types = require("../types");
 
 class DeviceModal extends PureComponent {
   static get propTypes() {
     return {
       deviceAdderViewportTemplate: PropTypes.shape(Types.viewport).isRequired,
       devices: PropTypes.shape(Types.devices).isRequired,
       onAddCustomDevice: PropTypes.func.isRequired,
@@ -26,27 +27,32 @@ class DeviceModal extends PureComponent 
       onUpdateDeviceDisplayed: PropTypes.func.isRequired,
       onUpdateDeviceModal: PropTypes.func.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
 
-    this.state = {};
+    this.state = {
+      isDeviceFormShown: false,
+    };
     for (const type of this.props.devices.types) {
       for (const device of this.props.devices[type]) {
         this.state[device.name] = device.displayed;
       }
     }
 
     this.onAddCustomDevice = this.onAddCustomDevice.bind(this);
     this.onDeviceCheckboxChange = this.onDeviceCheckboxChange.bind(this);
+    this.onDeviceFormShow = this.onDeviceFormShow.bind(this);
+    this.onDeviceFormHide = this.onDeviceFormHide.bind(this);
     this.onDeviceModalSubmit = this.onDeviceModalSubmit.bind(this);
     this.onKeyDown = this.onKeyDown.bind(this);
+    this.validateAddDeviceFormNameField = this.validateAddDeviceFormNameField.bind(this);
   }
 
   componentDidMount() {
     window.addEventListener("keydown", this.onKeyDown, true);
   }
 
   componentWillUnmount() {
     window.removeEventListener("keydown", this.onKeyDown, true);
@@ -64,16 +70,24 @@ class DeviceModal extends PureComponent 
     if (button !== 0) {
       return;
     }
     this.setState({
       [target.value]: !this.state[target.value],
     });
   }
 
+  onDeviceFormShow() {
+    this.setState({ isDeviceFormShown: true });
+  }
+
+  onDeviceFormHide() {
+    this.setState({ isDeviceFormShown: false });
+  }
+
   onDeviceModalSubmit() {
     const {
       devices,
       onDeviceListUpdate,
       onUpdateDeviceDisplayed,
       onUpdateDeviceModal,
     } = this.props;
 
@@ -110,100 +124,137 @@ class DeviceModal extends PureComponent 
     if (event.keyCode === 27) {
       const {
         onUpdateDeviceModal,
       } = this.props;
       onUpdateDeviceModal(false);
     }
   }
 
+  renderAddDeviceForm(devices, viewportTemplate) {
+    // If a device is currently selected, fold its attributes into a single object for use
+    // as the starting values of the form.  If no device is selected, use the values for
+    // the current window.
+    const deviceTemplate = viewportTemplate;
+    if (viewportTemplate.device) {
+      const device = devices[viewportTemplate.deviceType].find(d => {
+        return d.name == viewportTemplate.device;
+      });
+      Object.assign(deviceTemplate, {
+        pixelRatio: device.pixelRatio,
+        userAgent: device.userAgent,
+        touch: device.touch,
+        name: getFormatStr("responsive.customDeviceNameFromBase", device.name),
+      });
+    } else {
+      Object.assign(deviceTemplate, {
+        pixelRatio: window.devicePixelRatio,
+        userAgent: navigator.userAgent,
+        touch: false,
+        name: getStr("responsive.customDeviceName"),
+      });
+    }
+
+    return (
+      DeviceForm({
+        formType: "add",
+        buttonText: getStr("responsive.addDevice2"),
+        device: deviceTemplate,
+        onDeviceFormHide: this.onDeviceFormHide,
+        onDeviceFormShow: this.onDeviceFormShow,
+        onSave: this.onAddCustomDevice,
+        validateName: this.validateAddDeviceFormNameField,
+        viewportTemplate,
+      })
+    );
+  }
+
+  renderDevices() {
+    const sortedDevices = {};
+    for (const type of this.props.devices.types) {
+      sortedDevices[type] = this.props.devices[type]
+        .sort((a, b) => a.name.localeCompare(b.name));
+
+      sortedDevices[type].forEach(device => {
+        device.isChecked = this.state[device.name];
+      });
+    }
+
+    return (
+      this.props.devices.types.map(type => {
+        return sortedDevices[type].length ?
+          dom.div(
+            {
+              className: `device-type device-type-${type}`,
+              key: type,
+            },
+            dom.header({ className: "device-header" }, type),
+            DeviceList({
+              devices: sortedDevices,
+              type,
+              onDeviceCheckboxChange: this.onDeviceCheckboxChange,
+              onRemoveCustomDevice: this.props.onRemoveCustomDevice,
+            })
+          )
+          :
+          null;
+      })
+    );
+  }
+
+  /**
+   * Validates the name field's value by checking if the added device's name already
+   * exists in the custom devices list.
+   *
+   * @param  {String} value
+   *         The input field value for the device name.
+   * @return {Boolean} true if device name is valid, false otherwise.
+   */
+  validateAddDeviceFormNameField(value) {
+    const { devices } = this.props;
+    const nameFieldValue = value.trim();
+    const deviceFound = devices.custom.find(device => device.name == nameFieldValue);
+
+    return !deviceFound;
+  }
+
   render() {
     const {
       deviceAdderViewportTemplate,
       devices,
-      onRemoveCustomDevice,
       onUpdateDeviceModal,
     } = this.props;
 
-    const {
-      onAddCustomDevice,
-    } = this;
-
-    const sortedDevices = {};
-    for (const type of devices.types) {
-      sortedDevices[type] = Object.assign([], devices[type])
-        .sort((a, b) => a.name.localeCompare(b.name));
-    }
-
     return (
       dom.div(
         {
           id: "device-modal-wrapper",
           className: this.props.devices.isModalOpen ? "opened" : "closed",
         },
         dom.div({ className: "device-modal" },
-          dom.button({
-            id: "device-close-button",
-            className: "devtools-button",
-            onClick: () => onUpdateDeviceModal(false),
-          }),
-          dom.div({ className: "device-modal-content" },
-            devices.types.map(type => {
-              return dom.div(
-                {
-                  className: `device-type device-type-${type}`,
-                  key: type,
-                },
-                dom.header({ className: "device-header" },
-                  type
-                ),
-                sortedDevices[type].map(device => {
-                  const details = getFormatStr(
-                    "responsive.deviceDetails", device.width, device.height,
-                    device.pixelRatio, device.userAgent, device.touch
-                  );
-
-                  let removeDeviceButton;
-                  if (type == "custom") {
-                    removeDeviceButton = dom.button({
-                      className: "device-remove-button devtools-button",
-                      onClick: () => onRemoveCustomDevice(device),
-                    });
-                  }
-
-                  return dom.label(
-                    {
-                      className: "device-label",
-                      key: device.name,
-                      title: details,
-                    },
-                    dom.input({
-                      className: "device-input-checkbox",
-                      type: "checkbox",
-                      value: device.name,
-                      checked: this.state[device.name],
-                      onChange: this.onDeviceCheckboxChange,
-                    }),
-                    dom.span(
-                      {
-                        className: "device-name",
-                      },
-                      device.name
-                    ),
-                    removeDeviceButton
-                  );
+          dom.div({ className: "device-modal-header" },
+            !this.state.isDeviceFormShown ?
+              dom.header({ className: "device-modal-title" },
+                getStr("responsive.deviceSettings"),
+                dom.button({
+                  id: "device-close-button",
+                  className: "devtools-button",
+                  onClick: () => onUpdateDeviceModal(false),
                 })
-              );
-            })
+              )
+              :
+              null,
+            this.renderAddDeviceForm(devices, deviceAdderViewportTemplate)
           ),
-          DeviceAdder({
-            devices,
-            viewportTemplate: deviceAdderViewportTemplate,
-            onAddCustomDevice,
-          }),
+          dom.div({
+            className: `device-modal-content
+              ${this.state.isDeviceFormShown ? " form-shown" : ""}`,
+          },
+          this.renderDevices()
+          ),
           dom.button(
             {
               id: "device-submit-button",
               onClick: this.onDeviceModalSubmit,
             },
             getStr("responsive.done")
           )
         ),
--- a/devtools/client/responsive.html/components/moz.build
+++ b/devtools/client/responsive.html/components/moz.build
@@ -2,17 +2,19 @@
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
     'App.js',
     'Browser.js',
-    'DeviceAdder.js',
+    'Device.js',
+    'DeviceForm.js',
+    'DeviceList.js',
     'DeviceModal.js',
     'DevicePixelRatioMenu.js',
     'DeviceSelector.js',
     'ResizableViewport.js',
     'SettingsMenu.js',
     'Toolbar.js',
     'UserAgentInput.js',
     'ViewportDimension.js',
--- a/devtools/client/responsive.html/index.css
+++ b/devtools/client/responsive.html/index.css
@@ -6,24 +6,26 @@
  */
 
 :root {
   --rdm-box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26);
   --submit-button-active-background-color: rgba(0,0,0,0.12);
   --submit-button-active-color: var(--theme-body-color);
   --viewport-active-color: #3b3b3b;
   --input-invalid-border-color: var(--red-60);
+  --custom-device-button-hover: var(--grey-30);
 }
 
 :root.theme-dark {
   --rdm-box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26);
   --submit-button-active-background-color: var(--theme-toolbar-hover-active);
   --submit-button-active-color: var(--theme-selection-color);
   --viewport-active-color: #fcfcfc;
   --input-invalid-border-color: var(--red-50);
+  --custom-device-button-hover: var(--grey-10-a20)
 }
 
 * {
   box-sizing: border-box;
 }
 
 :root,
 input,
@@ -390,30 +392,34 @@ body,
   100% {
     opacity: 0;
     transform: translateY(5px);
     visibility: hidden;
   }
 }
 
 .device-modal {
+  display: grid;
+  grid-template-rows: minmax(80px, auto) auto 20px;
   background-color: var(--theme-toolbar-background);
   border: 1px solid var(--theme-splitter-color);
   border-radius: 2px;
   box-shadow: var(--rdm-box-shadow);
   position: absolute;
   margin: auto;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
-  width: 800px;
-  max-width: 90%;
-  height: 650px;
+  width: 90%;
+  height: 90%;
+  max-width: 750px;
+  max-height: 730px;
   z-index: 1;
+  overflow: hidden;
 }
 
 /* Handles the opening/closing of the modal */
 #device-modal-wrapper.opened .device-modal {
   animation: fade-in-and-up 0.3s ease forwards;
 }
 
 #device-modal-wrapper.closed .device-modal {
@@ -427,59 +433,182 @@ body,
   left: 0;
   height: 100%;
   width: 100%;
   z-index: 0;
   opacity: 0.5;
 }
 
 .device-modal-content {
-  display: flex;
-  flex-direction: column;
-  flex-wrap: wrap;
+  display: grid;
+  grid-row-gap: 30px;
   overflow: auto;
-  height: 515px;
-  margin: 20px 20px 0;
+  height: 100%;
+  padding: 10px 32px 50px 32px;
+}
+
+.device-modal-content.form-shown {
+  padding-top: 30px;
+}
+
+/* On screens that are >750px*/
+@media (min-width: 750px) {
+  #device-form {
+    grid-template-areas: "name size dpr"
+                         "user-agent touch buttons";
+  }
+
+  #device-form-name input,
+  #device-form-user-agent input {
+    width: 350px;
+  }
+
+  .device-modal-content {
+    grid-template-columns: 1fr 1fr 1fr;
+    grid-template-areas: "phone phone custom"
+                         "tablet laptop tv";
+  }
+}
+
+/* On screens that are between 450px and 749px */
+@media (min-width: 450px) and (max-width: 749px) {
+  #device-form {
+    grid-template-areas: "name size"
+                         "user-agent dpr"
+                         "touch buttons";
+    grid-template-columns: 2fr 1fr;
+  }
+
+  #device-form-name {
+    grid-area: name;
+  }
+
+  #device-form-name input,
+  #device-form-user-agent input {
+    width: 100%;
+  }
+
+  .device-modal-content {
+    grid-template-columns: 1fr 1fr;
+    grid-template-areas: "phone phone"
+                         "tablet laptop"
+                         "tv custom";
+  }
+}
+
+/* On screens that are <450px */
+@media (max-width: 449px) {
+  #device-form {
+    grid-template-areas: "name"
+                         "size"
+                         "dpr"
+                         "user-agent"
+                         "touch"
+                         "buttons";
+  }
+
+  #device-form-name input,
+  #device-form-user-agent input {
+    width: 90%;
+  }
+
+  #device-form-size {
+    justify-self: unset;
+  }
+
+  .device-modal-content {
+    grid-template-areas: "phone"
+                         "phone"
+                         "tablet"
+                         "laptop"
+                         "tv"
+                         "custom";
+  }
+
+  .device-type.device-type-phones .device-list {
+    grid-template-columns: 1fr;
+  }
+
+  .device-modal-header {
+    flex-direction: column;
+  }
 }
 
 #device-close-button {
   position: absolute;
   top: 5px;
   right: 2px;
 }
 
 #device-close-button::before {
   background-image: url("chrome://devtools/skin/images/close.svg");
 }
 
 .device-type {
   display: flex;
   flex-direction: column;
-  padding: 10px;
 }
 
 .device-header {
-  font-weight: bold;
+  font-size: 17px;
+  margin-bottom: 7px;
+  height: 20px;
   text-transform: capitalize;
-  padding: 0 0 3px 23px;
 }
 
 .device-label {
   color: var(--theme-body-color);
-  padding-bottom: 3px;
+  padding-bottom: 5px;
+  padding-top: 5px;
   display: flex;
   align-items: center;
-  /* Largest size without horizontal scrollbars */
-  max-width: 181px;
+}
+
+.device-label > button {
+  visibility: hidden;
+}
+
+.device-label:focus-within > button,
+.device-label:hover > button {
+  visibility: visible;
+}
+
+.device-label:focus-within,
+.device-label:hover {
+  background-color: var(--toolbarbutton-hover-background);
+}
+
+.device-modal-header {
+  display: flex;
+  justify-content: space-between;
+  z-index: 1;
+}
+
+.device-modal-header > #device-add-button {
+  margin: 30px 75px 0 30px;
+}
+
+.device-modal-header > #device-form {
+  margin-top: 15px;
+}
+
+.device-list {
+  display: grid;
+  font-size: 13px;
 }
 
 .device-input-checkbox {
   margin-right: 5px;
 }
 
+.device-modal-title {
+  font-size: 22px;
+  margin: 30px 0 0px 30px;
+}
+
 .device-name {
   flex: 1;
 }
 
 .device-remove-button:empty::before {
   background-image: url("chrome://devtools/skin/images/close.svg");
 }
 
@@ -501,90 +630,173 @@ body,
 }
 
 #device-submit-button:hover:active {
   background-color: var(--submit-button-active-background-color);
   color: var(--submit-button-active-color);
 }
 
 /**
- * Device Adder
+ * Device Form
  */
 
-#device-adder {
-  display: flex;
-  flex-direction: column;
-  margin: 0 20px;
+#device-form {
+  display: grid;
+  width: 100%;
+  background-color: var(--theme-toolbar-background);
+  min-height: 150px;
+  padding-left: 20px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid var(--theme-splitter-color);
+  overflow: auto;
 }
 
-#device-adder-content {
-  display: flex;
+#device-add-button {
+  margin-right: 70px;
 }
 
-#device-adder-column-1 {
-  flex: 1;
-  margin-right: 10px;
+#device-add-button,
+#device-form button {
+  background-color: rgba(12, 12, 13, 0.1);
+  border: 1px solid var(--theme-splitter-color);
+  border-radius: 2px;
+  cursor: pointer;
+  width: 167px;
+  height: 32px;
 }
 
-#device-adder-column-2 {
-  flex: 2;
+#device-editor-remove {
+  cursor: pointer;
 }
 
-#device-adder button {
-  background-color: var(--theme-tab-toolbar-background);
-  border: 1px solid var(--theme-splitter-color);
-  border-radius: 2px;
-  color: var(--theme-body-color);
-  margin: 0 auto;
+#device-editor-remove.device-remove-button:focus-within,
+#device-editor-remove.device-remove-button:hover {
+  background-color: var(--custom-device-button-hover);
 }
 
-#device-adder label {
+#device-form label {
   display: flex;
-  margin-bottom: 5px;
+  flex-direction: column;
+  margin: 5px;
+}
+
+#device-form label > .viewport-dimension {
+  color: var(--theme-body-color-inactive);
+  display: flex;
   align-items: center;
 }
 
-#device-adder label > input,
-#device-adder label > .viewport-dimension {
-  flex: 1;
-  margin: 0;
-}
-
-#device-adder label > .viewport-dimension {
-  border-bottom: 1px solid transparent;
-  color: var(--theme-body-color-inactive);
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  transition: all 0.25s ease;
-}
-
-#device-adder label > .viewport-dimension.editing {
-  border-bottom-color: var(--theme-selection-background);
-}
-
-#device-adder label > .viewport-dimension.editing.invalid {
-  border-bottom-color: #d92215;
-}
-
-#device-adder input {
+#device-form input {
   background: transparent;
-  border: 1px solid transparent;
+  border: 1px solid;
+  border-radius: 2px;
   text-align: center;
   color: var(--theme-body-color-inactive);
   transition: all 0.25s ease;
 }
 
-#device-adder input:focus {
-  color: var(--viewport-active-color);
+#device-form #device-form-name input,
+#device-form #device-form-user-agent input {
+  text-align: left;
+  padding-left: 12px;
+  padding-right: 12px;
 }
 
-#device-adder label > input:focus,
-#device-adder label > .viewport-dimension:focus  {
-  border-bottom: 1px solid var(--theme-selection-background);
+#device-form input:focus {
+  color: var(--viewport-active-color);
+  border-color: var(--blue-55);
+}
+
+#device-form label > input:focus,
+#device-form label > .viewport-dimension:focus  {
   outline: none;
 }
 
-.device-adder-label {
+#device-form-pixel-ratio {
+  grid-area: dpr;
+}
+
+#device-form-pixel-ratio input {
+  -moz-appearance: textfield;
+}
+
+#device-form-user-agent {
+  grid-area: user-agent;
+}
+
+#device-form-name input,
+#device-form-pixel-ratio input,
+#device-form-user-agent input,
+#device-form-size input {
+  height: 35px;
+}
+
+#device-form #device-form-touch {
+  flex-direction: row;
+  grid-area: touch;
+}
+
+#device-form-touch .device-form-label {
+  align-self: center;
+  margin-left: 5px;
+}
+
+#device-form #device-form-save {
+  background-color: #0060DF;
+  color: #fff;
+  border:1px solid #0060DF;
+  width: 50px;
+}
+
+#device-form-size {
+  grid-area: size;
+}
+
+#device-form-size input,
+#device-form #device-form-cancel {
+  width: 60px;
+}
+
+#device-form-save,
+#device-form-cancel {
+  align-self: center;
+}
+
+.device-form-buttons {
+  display: flex;
+  grid-area: buttons;
+  justify-content: space-evenly;
+  width: 154px;
+}
+
+.device-form-label {
   display: inline-block;
-  margin-right: 5px;
+  margin: 0 5px 5px 0;
   min-width: 35px;
+  font-size: 13px;
 }
+
+/* Device Types */
+
+.device-type-phones {
+  grid-area: phone;
+}
+
+.device-type-phones .device-list {
+  grid-template-columns: repeat(2, auto);
+}
+
+.device-type-custom {
+  grid-area: custom;
+  align-self: start;
+}
+
+.device-type-tablets {
+  grid-area: tablet;
+}
+
+.device-type-laptops {
+  grid-area: laptop;
+}
+
+.device-type-televisions {
+  grid-area: tv;
+}
--- a/devtools/client/responsive.html/test/browser/browser_device_custom.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_custom.js
@@ -32,17 +32,17 @@ addRDMTask(TEST_URL, async function({ ui
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
   await openDeviceModal(ui);
 
   info("Reveal device adder form, check that defaults match the viewport");
-  const adderShow = document.getElementById("device-adder-show");
+  const adderShow = document.getElementById("device-add-button");
   adderShow.click();
   testDeviceAdder(ui, {
     name: "Custom Device",
     width: 320,
     height: 480,
     pixelRatio: window.devicePixelRatio,
     userAgent: navigator.userAgent,
     touch: false,
@@ -77,17 +77,17 @@ addRDMTask(TEST_URL, async function({ ui
     && state.devices.listState == Types.loadableState.LOADED);
 
   info("Select existing device from the selector");
   await selectDevice(ui, "Test Device");
 
   await openDeviceModal(ui);
 
   info("Reveal device adder form, check that defaults are based on selected device");
-  const adderShow = document.getElementById("device-adder-show");
+  const adderShow = document.getElementById("device-add-button");
   adderShow.click();
   testDeviceAdder(ui, Object.assign({}, device, {
     name: "Test Device (Custom)",
   }));
 
   info("Remove previously added custom device");
   const deviceRemoveButton = document.querySelector(".device-remove-button");
   const submitButton = document.getElementById("device-submit-button");
@@ -121,17 +121,17 @@ addRDMTask(TEST_URL, async function({ ui
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
   await openDeviceModal(ui);
 
   info("Reveal device adder form");
-  const adderShow = document.querySelector("#device-adder-show");
+  const adderShow = document.querySelector("#device-add-button");
   adderShow.click();
 
   info("Fill out device adder form by setting details to unicode device and save");
   await addDeviceInModal(ui, unicodeDevice);
 
   info("Verify unicode device defaults to enabled in modal");
   const deviceCb = [...document.querySelectorAll(".device-input-checkbox")].find(cb => {
     return cb.value == unicodeDevice.name;
@@ -166,22 +166,22 @@ addRDMTask(TEST_URL, async function({ ui
     const menuItem = items.find(i => i.getAttribute("label") === unicodeDevice.name);
     ok(menuItem, "Custom unicode device option present in device selector");
   });
 });
 
 function testDeviceAdder(ui, expected) {
   const { document } = ui.toolWindow;
 
-  const nameInput = document.querySelector("#device-adder-name input");
+  const nameInput = document.querySelector("#device-form-name input");
   const [ widthInput, heightInput ] =
-    document.querySelectorAll("#device-adder-size input");
-  const pixelRatioInput = document.querySelector("#device-adder-pixel-ratio input");
-  const userAgentInput = document.querySelector("#device-adder-user-agent input");
-  const touchInput = document.querySelector("#device-adder-touch input");
+    document.querySelectorAll("#device-form-size input");
+  const pixelRatioInput = document.querySelector("#device-form-pixel-ratio input");
+  const userAgentInput = document.querySelector("#device-form-user-agent input");
+  const touchInput = document.querySelector("#device-form-touch input");
 
   is(nameInput.value, expected.name, "Device name matches");
   is(parseInt(widthInput.value, 10), expected.width, "Width matches");
   is(parseInt(heightInput.value, 10), expected.height, "Height matches");
   is(parseFloat(pixelRatioInput.value), expected.pixelRatio,
      "devicePixelRatio matches");
   is(userAgentInput.value, expected.userAgent, "User agent matches");
   is(touchInput.checked, expected.touch, "Touch matches");
--- a/devtools/client/responsive.html/test/browser/browser_device_custom_remove.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_custom_remove.js
@@ -34,24 +34,24 @@ addRDMTask(TEST_URL, async function({ ui
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
   const deviceSelector = document.getElementById("device-selector");
 
   await openDeviceModal(ui);
 
   info("Reveal device adder form");
-  let adderShow = document.querySelector("#device-adder-show");
+  let adderShow = document.querySelector("#device-add-button");
   adderShow.click();
 
   info("Add test device 1");
   await addDeviceInModal(ui, device1);
 
   info("Reveal device adder form");
-  adderShow = document.querySelector("#device-adder-show");
+  adderShow = document.querySelector("#device-add-button");
   adderShow.click();
 
   info("Add test device 2");
   await addDeviceInModal(ui, device2);
 
   info("Verify all custom devices default to enabled in modal");
   const submitButton = document.getElementById("device-submit-button");
   const deviceCbs =
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -475,22 +475,22 @@ async function changeUserAgentInput(ui, 
  * Assuming the device modal is open and the device adder form is shown, this helper
  * function adds `device` via the form, saves it, and waits for it to appear in the store.
  */
 function addDeviceInModal(ui, device) {
   const { Simulate } =
     ui.toolWindow.require("devtools/client/shared/vendor/react-dom-test-utils");
   const { document, store } = ui.toolWindow;
 
-  const nameInput = document.querySelector("#device-adder-name input");
+  const nameInput = document.querySelector("#device-form-name input");
   const [ widthInput, heightInput ] =
-    document.querySelectorAll("#device-adder-size input");
-  const pixelRatioInput = document.querySelector("#device-adder-pixel-ratio input");
-  const userAgentInput = document.querySelector("#device-adder-user-agent input");
-  const touchInput = document.querySelector("#device-adder-touch input");
+    document.querySelectorAll("#device-form-size input");
+  const pixelRatioInput = document.querySelector("#device-form-pixel-ratio input");
+  const userAgentInput = document.querySelector("#device-form-user-agent input");
+  const touchInput = document.querySelector("#device-form-touch input");
 
   nameInput.value = device.name;
   Simulate.change(nameInput);
   widthInput.value = device.width;
   Simulate.change(widthInput);
   Simulate.blur(widthInput);
   heightInput.value = device.height;
   Simulate.change(heightInput);
@@ -498,17 +498,17 @@ function addDeviceInModal(ui, device) {
   pixelRatioInput.value = device.pixelRatio;
   Simulate.change(pixelRatioInput);
   userAgentInput.value = device.userAgent;
   Simulate.change(userAgentInput);
   touchInput.checked = device.touch;
   Simulate.change(touchInput);
 
   const existingCustomDevices = store.getState().devices.custom.length;
-  const adderSave = document.querySelector("#device-adder-save");
+  const adderSave = document.querySelector("#device-form-save");
   const saved = waitUntilState(store, state =>
     state.devices.custom.length == existingCustomDevices + 1
   );
   Simulate.click(adderSave);
   return saved;
 }
 
 function reloadOnUAChange(enabled) {
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -5673,16 +5673,35 @@ exports.CSS_PROPERTIES = {
     "values": [
       "auto",
       "inherit",
       "initial",
       "revert",
       "unset"
     ]
   },
+  "contain": {
+    "isInherited": false,
+    "subproperties": [
+      "contain"
+    ],
+    "supports": [],
+    "values": [
+      "content",
+      "inherit",
+      "initial",
+      "layout",
+      "none",
+      "paint",
+      "revert",
+      "size",
+      "strict",
+      "unset"
+    ]
+  },
   "content": {
     "isInherited": false,
     "subproperties": [
       "content"
     ],
     "supports": [],
     "values": [
       "-moz-alt-content",
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -25,16 +25,23 @@
 
 #include "nsDocShell.h"
 #include "nsGlobalWindowOuter.h"
 #include "nsContentUtils.h"
 #include "nsScriptError.h"
 #include "nsThreadUtils.h"
 #include "xpcprivate.h"
 
+#include "AutoplayPolicy.h"
+
+extern mozilla::LazyLogModule gAutoplayPermissionLog;
+
+#define AUTOPLAY_LOG(msg, ...) \
+  MOZ_LOG(gAutoplayPermissionLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
+
 namespace mozilla {
 namespace dom {
 
 extern mozilla::LazyLogModule gUserInteractionPRLog;
 
 #define USER_ACTIVATION_LOG(msg, ...) \
   MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
 
@@ -741,16 +748,33 @@ void BrowsingContext::LocationProxy::Rep
   nsPIDOMWindowOuter* win = GetBrowsingContext()->GetDOMWindow();
   if (!win || !win->GetLocation()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
   win->GetLocation()->Replace(aUrl, aSubjectPrincipal, aError);
 }
 
+void BrowsingContext::StartDelayedAutoplayMediaComponents() {
+  if (!mDocShell) {
+    return;
+  }
+  AUTOPLAY_LOG("%s : StartDelayedAutoplayMediaComponents for bc 0x%08" PRIx64,
+               XRE_IsParentProcess() ? "Parent" : "Child", Id());
+  mDocShell->StartDelayedAutoplayMediaComponents();
+}
+
+void BrowsingContext::DidSetIsActivatedByUserGesture(ContentParent* aSource) {
+  MOZ_ASSERT(!mParent, "Set user activation flag on non top-level context!");
+  USER_ACTIVATION_LOG(
+      "Set user gesture activation %d for %s browsing context 0x%08" PRIx64,
+      mIsActivatedByUserGesture, XRE_IsParentProcess() ? "Parent" : "Child",
+      Id());
+}
+
 }  // namespace dom
 
 namespace ipc {
 
 void IPDLParamTraits<dom::BrowsingContext>::Write(
     IPC::Message* aMsg, IProtocol* aActor, dom::BrowsingContext* aParam) {
   uint64_t id = aParam ? aParam->Id() : 0;
   WriteIPDLParam(aMsg, aActor, id);
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -84,17 +84,16 @@ class BrowsingContextBase {
 // BrowsingContext tree for a tab, in both the parent and the child
 // process.
 //
 // Trees of BrowsingContexts should only ever contain nodes of the
 // same BrowsingContext::Type. This is enforced by asserts in the
 // BrowsingContext::Create* methods.
 class BrowsingContext : public nsWrapperCache,
                         public SupportsWeakPtr<BrowsingContext>,
-                        public LinkedListElement<RefPtr<BrowsingContext>>,
                         public BrowsingContextBase {
  public:
   enum class Type { Chrome, Content };
 
   static void Init();
   static LogModule* GetLog();
   static void CleanupContexts(uint64_t aProcessId);
 
@@ -243,16 +242,18 @@ class BrowsingContext : public nsWrapper
                       const Sequence<JSObject*>& aTransfer,
                       nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const WindowPostMessageOptions& aOptions,
                       nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
 
   JSObject* WrapObject(JSContext* aCx);
 
+  void StartDelayedAutoplayMediaComponents();
+
   /**
    * Transaction object. This object is used to specify and then commit
    * modifications to synchronized fields in BrowsingContexts.
    */
   class Transaction {
    public:
     // Apply the changes from this transaction to the specified BrowsingContext
     // in all processes. This method will call the correct `WillSet` and
@@ -393,16 +394,19 @@ class BrowsingContext : public nsWrapper
   // Ensure that opener is in the same BrowsingContextGroup.
   void WillSetOpener(const uint64_t& aValue, ContentParent* aSource) {
     if (aValue != 0) {
       RefPtr<BrowsingContext> opener = Get(aValue);
       MOZ_RELEASE_ASSERT(opener && opener->Group() == Group());
     }
   }
 
+  // Ensure that we only set the flag on the top level browsing context.
+  void DidSetIsActivatedByUserGesture(ContentParent* aSource);
+
   // Type of BrowsingContent
   const Type mType;
 
   // Unique id identifying BrowsingContext
   const uint64_t mBrowsingContextId;
 
   RefPtr<BrowsingContextGroup> mGroup;
   RefPtr<BrowsingContext> mParent;
--- a/docshell/base/CanonicalBrowsingContext.cpp
+++ b/docshell/base/CanonicalBrowsingContext.cpp
@@ -5,16 +5,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/CanonicalBrowsingContext.h"
 
 #include "mozilla/dom/BrowsingContextGroup.h"
 #include "mozilla/dom/WindowGlobalParent.h"
 #include "mozilla/dom/ContentProcessManager.h"
 
+extern mozilla::LazyLogModule gAutoplayPermissionLog;
+
+#define AUTOPLAY_LOG(msg, ...) \
+  MOZ_LOG(gAutoplayPermissionLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
+
 namespace mozilla {
 namespace dom {
 
 extern mozilla::LazyLogModule gUserInteractionPRLog;
 
 #define USER_ACTIVATION_LOG(msg, ...) \
   MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
 
@@ -114,10 +119,30 @@ void CanonicalBrowsingContext::Traverse(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobals);
 }
 
 void CanonicalBrowsingContext::Unlink() {
   CanonicalBrowsingContext* tmp = this;
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobals);
 }
 
+void CanonicalBrowsingContext::NotifyStartDelayedAutoplayMedia() {
+  if (!mCurrentWindowGlobal) {
+    return;
+  }
+
+  // As this function would only be called when user click the play icon on the
+  // tab bar. That's clear user intent to play, so gesture activate the browsing
+  // context so that the block-autoplay logic allows the media to autoplay.
+  NotifyUserGestureActivation();
+  AUTOPLAY_LOG("NotifyStartDelayedAutoplayMedia for chrome bc 0x%08" PRIx64,
+               Id());
+  StartDelayedAutoplayMediaComponents();
+  // Notfiy all content browsing contexts which are related with the canonical
+  // browsing content tree to start delayed autoplay media.
+  for (auto iter = Group()->ContentParentsIter(); !iter.Done(); iter.Next()) {
+    auto entry = iter.Get();
+    Unused << entry->GetKey()->SendStartDelayedAutoplayMediaComponents(this);
+  }
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/docshell/base/CanonicalBrowsingContext.h
+++ b/docshell/base/CanonicalBrowsingContext.h
@@ -55,16 +55,22 @@ class CanonicalBrowsingContext final : p
 
   // This functions would set/reset its user gesture activation flag and then
   // notify other browsing contexts which are not the one related with the
   // current window global to set/reset the flag. (the corresponding browsing
   // context of the current global window has been set/reset before calling this
   // function)
   void NotifySetUserGestureActivationFromIPC(bool aIsUserGestureActivation);
 
+  // This function is used to start the autoplay media which are delayed to
+  // start. If needed, it would also notify the content browsing context which
+  // are related with the canonical browsing content tree to start delayed
+  // autoplay media.
+  void NotifyStartDelayedAutoplayMedia();
+
   // Validate that the given process is allowed to perform the given
   // transaction. aSource is |nullptr| if set in the parent process.
   bool ValidateTransaction(const Transaction& aTransaction,
                            ContentParent* aSource);
 
  protected:
   void Traverse(nsCycleCollectionTraversalCallback& cb);
   void Unlink();
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -980,16 +980,25 @@ nsresult nsDocShell::DispatchToTabGroup(
 NS_IMETHODIMP
 nsDocShell::DispatchLocationChangeEvent() {
   return DispatchToTabGroup(
       TaskCategory::Other,
       NewRunnableMethod("nsDocShell::FireDummyOnLocationChange", this,
                         &nsDocShell::FireDummyOnLocationChange));
 }
 
+NS_IMETHODIMP
+nsDocShell::StartDelayedAutoplayMediaComponents() {
+  RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
+  if (outerWindow) {
+    outerWindow->SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
+  }
+  return NS_OK;
+}
+
 bool nsDocShell::MaybeInitTiming() {
   if (mTiming && !mBlankTiming) {
     return false;
   }
 
   bool canBeReset = false;
 
   if (mScriptGlobal && mBlankTiming) {
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1077,16 +1077,22 @@ interface nsIDocShell : nsIDocShellTreeI
    */
   attribute boolean useTrackingProtection;
 
  /**
   * Fire a dummy location change event asynchronously.
   */
   [noscript] void dispatchLocationChangeEvent();
 
+
+  /**
+   * Start delayed autoplay media which are in the current document.
+   */
+  [noscript] void startDelayedAutoplayMediaComponents();
+
   /**
    * Take ownership of the ClientSource representing an initial about:blank
    * document that was never needed.  As an optimization we avoid creating
    * this document if no code calls GetDocument(), but we still need a
    * ClientSource object to represent the about:blank window.  This may return
    * nullptr; for example if the docshell has created a real window and document
    * already.
    */
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -1200,17 +1200,17 @@ Document::Document(const char* aContentT
       mCharacterSetSource(0),
       mParentDocument(nullptr),
       mCachedRootElement(nullptr),
       mNodeInfoManager(nullptr),
 #ifdef DEBUG
       mStyledLinksCleared(false),
 #endif
       mBidiEnabled(false),
-      mFontGroupCacheDirty(true),
+      mMayNeedFontPrefsUpdate(true),
       mMathMLEnabled(false),
       mIsInitialDocumentInWindow(false),
       mIgnoreDocGroupMismatches(false),
       mLoadedAsData(false),
       mLoadedAsInteractiveData(false),
       mMayStartLayout(true),
       mHaveFiredTitleChange(false),
       mIsShowing(false),
@@ -3514,17 +3514,17 @@ void Document::SetHeaderData(nsAtom* aHe
     if (!aData.IsEmpty() && !found) {
       // didn't find, append
       *lastPtr = new DocHeaderData(aHeaderField, aData);
     }
   }
 
   if (aHeaderField == nsGkAtoms::headerContentLanguage) {
     CopyUTF16toUTF8(aData, mContentLanguage);
-    ResetLangPrefs();
+    mMayNeedFontPrefsUpdate = true;
     if (auto* presContext = GetPresContext()) {
       presContext->ContentLanguageChanged();
     }
   }
 
   if (aHeaderField == nsGkAtoms::headerDefaultStyle) {
     SetPreferredStyleSheetSet(aData);
   }
@@ -12626,45 +12626,45 @@ already_AddRefed<nsAtom> Document::GetLa
     lang = mLanguageFromCharset;
   }
   return lang.forget();
 }
 
 const LangGroupFontPrefs* Document::GetFontPrefsForLang(
     nsAtom* aLanguage, bool* aNeedsToCache) const {
   nsAtom* lang = aLanguage ? aLanguage : mLanguageFromCharset.get();
-  return StaticPresData::Get()->GetFontPrefsForLangHelper(
-      lang, &mLangGroupFontPrefs, aNeedsToCache);
+  return StaticPresData::Get()->GetFontPrefsForLang(lang, aNeedsToCache);
 }
 
 void Document::DoCacheAllKnownLangPrefs() {
-  MOZ_ASSERT(mFontGroupCacheDirty);
+  MOZ_ASSERT(mMayNeedFontPrefsUpdate);
   RefPtr<nsAtom> lang = GetLanguageForStyle();
-  GetFontPrefsForLang(lang.get());
-  GetFontPrefsForLang(nsGkAtoms::x_math);
+  StaticPresData* data = StaticPresData::Get();
+  data->GetFontPrefsForLang(lang ? lang.get() : mLanguageFromCharset.get());
+  data->GetFontPrefsForLang(nsGkAtoms::x_math);
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1362599#c12
-  GetFontPrefsForLang(nsGkAtoms::Unicode);
+  data->GetFontPrefsForLang(nsGkAtoms::Unicode);
   for (auto iter = mLanguagesUsed.Iter(); !iter.Done(); iter.Next()) {
-    GetFontPrefsForLang(iter.Get()->GetKey());
-  }
-  mFontGroupCacheDirty = false;
+    data->GetFontPrefsForLang(iter.Get()->GetKey());
+  }
+  mMayNeedFontPrefsUpdate = false;
 }
 
 void Document::RecomputeLanguageFromCharset() {
   nsLanguageAtomService* service = nsLanguageAtomService::GetService();
   RefPtr<nsAtom> language = service->LookupCharSet(mCharacterSet);
   if (language == nsGkAtoms::Unicode) {
     language = service->GetLocaleLanguage();
   }
 
   if (language == mLanguageFromCharset) {
     return;
   }
 
-  ResetLangPrefs();
+  mMayNeedFontPrefsUpdate = true;
   mLanguageFromCharset = language.forget();
 }
 
 nsICookieSettings* Document::CookieSettings() {
   // If we are here, this is probably a javascript: URL document. In any case,
   // we must have a nsCookieSettings. Let's create it.
   if (!mCookieSettings) {
     mCookieSettings = net::CookieSettings::Create();
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3601,20 +3601,19 @@ class Document : public nsINode,
  public:
   bool IsThirdPartyForFlashClassifier();
 
  private:
   void DoCacheAllKnownLangPrefs();
   void RecomputeLanguageFromCharset();
 
  public:
-  void ResetLangPrefs() {
-    mLangGroupFontPrefs.Reset();
-    mFontGroupCacheDirty = true;
-  }
+  void SetMayNeedFontPrefsUpdate() { mMayNeedFontPrefsUpdate = true; }
+
+  bool MayNeedFontPrefsUpdate() { return mMayNeedFontPrefsUpdate; }
 
   already_AddRefed<nsAtom> GetContentLanguageAsAtomForStyle() const;
   already_AddRefed<nsAtom> GetLanguageForStyle() const;
 
   /**
    * Fetch the user's font preferences for the given aLanguage's
    * language group.
    */
@@ -3624,17 +3623,17 @@ class Document : public nsINode,
   void ForceCacheLang(nsAtom* aLanguage) {
     if (!mLanguagesUsed.EnsureInserted(aLanguage)) {
       return;
     }
     GetFontPrefsForLang(aLanguage);
   }
 
   void CacheAllKnownLangPrefs() {
-    if (!mFontGroupCacheDirty) {
+    if (!mMayNeedFontPrefsUpdate) {
       return;
     }
     DoCacheAllKnownLangPrefs();
   }
 
   nsINode* GetServoRestyleRoot() const { return mServoRestyleRoot; }
 
   uint32_t GetServoRestyleRootDirtyBits() const {
@@ -3981,18 +3980,18 @@ class Document : public nsINode,
   EventStates mDocumentState;
 
   RefPtr<Promise> mReadyForIdle;
 
   RefPtr<FeaturePolicy> mFeaturePolicy;
 
   // True if BIDI is enabled.
   bool mBidiEnabled : 1;
-  // True if mLangGroupFontPrefs is not initialized or dirty in some other way.
-  bool mFontGroupCacheDirty : 1;
+  // True if we may need to recompute the language prefs for this document.
+  bool mMayNeedFontPrefsUpdate : 1;
   // True if a MathML element has ever been owned by this document.
   bool mMathMLEnabled : 1;
 
   // True if this document is the initial document for a window.  This should
   // basically be true only for documents that exist in newly-opened windows or
   // documents created to satisfy a GetDocument() on a window when there's no
   // document in it.
   bool mIsInitialDocumentInWindow : 1;
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1511,21 +1511,23 @@ void Navigator::OnNavigation() {
 }
 
 JSObject* Navigator::WrapObject(JSContext* cx,
                                 JS::Handle<JSObject*> aGivenProto) {
   return Navigator_Binding::Wrap(cx, this, aGivenProto);
 }
 
 /* static */
-bool Navigator::HasUserMediaSupport(JSContext* /* unused */,
-                                    JSObject* /* unused */) {
-  // Make enabling peerconnection enable getUserMedia() as well
-  return Preferences::GetBool("media.navigator.enabled", false) ||
-         Preferences::GetBool("media.peerconnection.enabled", false);
+bool Navigator::HasUserMediaSupport(JSContext* cx, JSObject* obj) {
+  // Make enabling peerconnection enable getUserMedia() as well.
+  // Emulate [SecureContext] unless media.devices.insecure.enabled=true
+  return (StaticPrefs::media_navigator_enabled() ||
+          StaticPrefs::media_peerconnection_enabled()) &&
+         (IsSecureContextOrObjectIsFromSecureContext(cx, obj) ||
+          StaticPrefs::media_devices_insecure_enabled());
 }
 
 /* static */
 already_AddRefed<nsPIDOMWindowInner> Navigator::GetWindowFromGlobal(
     JSObject* aGlobal) {
   nsCOMPtr<nsPIDOMWindowInner> win = xpc::WindowOrNull(aGlobal);
   return win.forget();
 }
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -6806,16 +6806,18 @@ void nsGlobalWindowInner::StoreSharedWor
 void nsGlobalWindowInner::ForgetSharedWorker(SharedWorker* aSharedWorker) {
   MOZ_ASSERT(aSharedWorker);
   MOZ_ASSERT(mSharedWorkers.Contains(aSharedWorker));
 
   mSharedWorkers.RemoveElement(aSharedWorker);
 }
 
 void nsGlobalWindowInner::StorageAccessGranted() {
+  PropagateFirstPartyStorageAccessGrantedToWorkers(this);
+
   // If we have a partitioned localStorage, it's time to replace it with a real
   // one in order to receive notifications.
 
   if (mLocalStorage &&
       mLocalStorage->Type() == Storage::ePartitionedLocalStorage) {
     IgnoredErrorResult error;
     GetLocalStorage(error);
     if (NS_WARN_IF(error.Failed())) {
--- a/dom/base/test/browser.ini
+++ b/dom/base/test/browser.ini
@@ -50,13 +50,14 @@ uses-unsafe-cpows = true
 [browser_pagehide_on_tab_close.js]
 skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s.
 [browser_promiseDocumentFlushed.js]
 [browser_state_notifications.js]
 skip-if = true # Bug 1271028
 [browser_use_counters.js]
 skip-if = verify
 [browser_timeout_throttling_with_audio_playback.js]
+skip-if = (os == "win" && processor == "aarch64") # aarch64 due to bug 1536566
 [browser_bug1303838.js]
 [browser_inputStream_structuredClone.js]
 [browser_multiple_popups.js]
 skip-if = os == 'win' && !debug # Bug 1505235
 support-files = browser_multiple_popups.html
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -1,18 +1,21 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+/* global api, CopyPasteAssistent */
+
 "use strict";
 
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 function debug(msg) {
-  //dump("BrowserElementChild - " + msg + "\n");
+  // dump("BrowserElementChild - " + msg + "\n");
 }
 
 // NB: this must happen before we process any messages from
 // mozbrowser API clients.
 docShell.isActive = true;
 
 function parentDocShell(docshell) {
   if (!docshell) {
@@ -31,19 +34,19 @@ function isTopBrowserElement(docShell) {
   }
   return true;
 }
 
 var BrowserElementIsReady;
 
 debug(`Might load BE scripts: BEIR: ${BrowserElementIsReady}`);
 if (!BrowserElementIsReady) {
-  debug("Loading BE scripts")
+  debug("Loading BE scripts");
   if (!("BrowserElementIsPreloaded" in this)) {
-    if(Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
+    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
       // general content apps
       if (isTopBrowserElement(docShell)) {
         Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js", this);
       }
     } else {
       // rocketbar in system app and other in-process case (ex. B2G desktop client)
       Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js", this);
     }
@@ -65,9 +68,9 @@ if (!BrowserElementIsReady) {
   }
   addMessageListener("browser-element-api:destroy", onDestroy);
 
   BrowserElementIsReady = true;
 } else {
   debug("BE already loaded, abort");
 }
 
-sendAsyncMessage('browser-element-api:call', { 'msg_name': 'hello' });
+sendAsyncMessage("browser-element-api:call", { "msg_name": "hello" });
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -1,14 +1,16 @@
 /* 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";
 
+/* eslint-env mozilla/frame-script */
+
 function debug(msg) {
   // dump("BrowserElementChildPreload - " + msg + "\n");
 }
 
 debug("loaded");
 
 var BrowserElementIsReady;
 
@@ -28,41 +30,41 @@ function sendAsyncMsg(msg, data) {
     return;
   }
 
   if (!data) {
     data = { };
   }
 
   data.msg_name = msg;
-  sendAsyncMessage('browser-element-api:call', data);
+  sendAsyncMessage("browser-element-api:call", data);
 }
 
 function sendSyncMsg(msg, data) {
   // Ensure that we don't send any messages before BrowserElementChild.js
   // finishes loading.
   if (!BrowserElementIsReady) {
-    return;
+    return undefined;
   }
 
   if (!data) {
     data = { };
   }
 
   data.msg_name = msg;
-  return sendSyncMessage('browser-element-api:call', data);
+  return sendSyncMessage("browser-element-api:call", data);
 }
 
-var CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
+var CERTIFICATE_ERROR_PAGE_PREF = "security.alternate_certificate_error_page";
 
 var OBSERVED_EVENTS = [
-  'xpcom-shutdown',
-  'audio-playback',
-  'activity-done',
-  'will-launch-app'
+  "xpcom-shutdown",
+  "audio-playback",
+  "activity-done",
+  "will-launch-app",
 ];
 
 var LISTENED_EVENTS = [
   { type: "DOMTitleChanged", useCapture: true, wantsUntrusted: false },
   { type: "DOMLinkAdded", useCapture: true, wantsUntrusted: false },
   { type: "MozScrolledAreaChanged", useCapture: true, wantsUntrusted: false },
   { type: "MozDOMFullscreen:Request", useCapture: true, wantsUntrusted: false },
   { type: "MozDOMFullscreen:NewOrigin", useCapture: true, wantsUntrusted: false },
@@ -105,24 +107,24 @@ var global = this;
 
 function BrowserElementChild() {
   // Maps outer window id --> weak ref to window.  Used by modal dialog code.
   this._windowIDDict = {};
 
   this._isContentWindowCreated = false;
 
   this._init();
-};
+}
 
 BrowserElementChild.prototype = {
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference]),
 
-  _init: function() {
+  _init() {
     debug("Starting up.");
 
     BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
 
     docShell.QueryInterface(Ci.nsIWebProgress)
             .addProgressListener(this._progressListener,
                                  Ci.nsIWebProgress.NOTIFY_LOCATION |
                                  Ci.nsIWebProgress.NOTIFY_SECURITY |
@@ -132,83 +134,79 @@ BrowserElementChild.prototype = {
     if (!webNavigation.sessionHistory) {
       // XXX(nika): I don't think this code should ever be hit? We should run
       // TabChild::Init before we run this code which will perform this setup
       // for us.
       docShell.initSessionHistory();
     }
 
     // This is necessary to get security web progress notifications.
-    var securityUI = Cc['@mozilla.org/secure_browser_ui;1']
+    var securityUI = Cc["@mozilla.org/secure_browser_ui;1"]
                        .createInstance(Ci.nsISecureBrowserUI);
     securityUI.init(docShell);
 
     // A cache of the menuitem dom objects keyed by the id we generate
     // and pass to the embedder
     this._ctxHandlers = {};
     // Counter of contextmenu events fired
     this._ctxCounter = 0;
 
     this._shuttingDown = false;
 
     LISTENED_EVENTS.forEach(event => {
       addEventListener(event.type, this, event.useCapture, event.wantsUntrusted);
     });
 
     // Registers a MozAfterPaint handler for the very first paint.
-    this._addMozAfterPaintHandler(function () {
-      sendAsyncMsg('firstpaint');
+    this._addMozAfterPaintHandler(function() {
+      sendAsyncMsg("firstpaint");
     });
 
     addMessageListener("browser-element-api:call", this);
 
-    let els = Cc["@mozilla.org/eventlistenerservice;1"]
-                .getService(Ci.nsIEventListenerService);
     LISTENED_SYSTEM_EVENTS.forEach(event => {
-      els.addSystemEventListener(global, event.type, this, event.useCapture);
+      Services.els.addSystemEventListener(global, event.type, this, event.useCapture);
     });
 
     OBSERVED_EVENTS.forEach((aTopic) => {
       Services.obs.addObserver(this, aTopic);
     });
   },
 
   /**
    * Shut down the frame's side of the browser API.  This is called when:
    *   - our TabChildGlobal starts to die
    *   - the content is moved to frame without the browser API
    * This is not called when the page inside |content| unloads.
    */
-  destroy: function() {
+  destroy() {
     debug("Destroying");
     this._shuttingDown = true;
 
     BrowserElementPromptService.unmapWindowToBrowserElementChild(content);
 
     docShell.QueryInterface(Ci.nsIWebProgress)
             .removeProgressListener(this._progressListener);
 
     LISTENED_EVENTS.forEach(event => {
       removeEventListener(event.type, this, event.useCapture, event.wantsUntrusted);
     });
 
     removeMessageListener("browser-element-api:call", this);
 
-    let els = Cc["@mozilla.org/eventlistenerservice;1"]
-                .getService(Ci.nsIEventListenerService);
     LISTENED_SYSTEM_EVENTS.forEach(event => {
-      els.removeSystemEventListener(global, event.type, this, event.useCapture);
+      Services.els.removeSystemEventListener(global, event.type, this, event.useCapture);
     });
 
     OBSERVED_EVENTS.forEach((aTopic) => {
       Services.obs.removeObserver(this, aTopic);
     });
   },
 
-  handleEvent: function(event) {
+  handleEvent(event) {
     switch (event.type) {
       case "DOMTitleChanged":
         this._titleChangedHandler(event);
         break;
       case "DOMLinkAdded":
         this._linkAddedHandler(event);
         break;
       case "MozScrolledAreaChanged":
@@ -254,66 +252,67 @@ BrowserElementChild.prototype = {
         this._contextmenuHandler(event);
         break;
       case "scroll":
         this._scrollEventHandler(event);
         break;
     }
   },
 
-  receiveMessage: function(message) {
+  receiveMessage(message) {
     let self = this;
 
     let mmCalls = {
       "send-mouse-event": this._recvSendMouseEvent,
       "get-can-go-back": this._recvCanGoBack,
       "get-can-go-forward": this._recvCanGoForward,
       "go-back": this._recvGoBack,
       "go-forward": this._recvGoForward,
       "reload": this._recvReload,
       "stop": this._recvStop,
       "zoom": this._recvZoom,
       "unblock-modal-prompt": this._recvStopWaiting,
       "fire-ctx-callback": this._recvFireCtxCallback,
       "owner-visibility-change": this._recvOwnerVisibilityChange,
       "entered-fullscreen": this._recvEnteredFullscreen,
       "exit-fullscreen": this._recvExitFullscreen,
-    }
+    };
 
     if (message.data.msg_name in mmCalls) {
       return mmCalls[message.data.msg_name].apply(self, arguments);
     }
+    return undefined;
   },
 
   _paintFrozenTimer: null,
-  observe: function(subject, topic, data) {
+  observe(subject, topic, data) {
     // Ignore notifications not about our document.  (Note that |content| /can/
     // be null; see bug 874900.)
 
-    if (topic !== 'activity-done' &&
-        topic !== 'audio-playback' &&
-        topic !== 'will-launch-app' &&
+    if (topic !== "activity-done" &&
+        topic !== "audio-playback" &&
+        topic !== "will-launch-app" &&
         (!content || subject !== content.document)) {
       return;
     }
-    if (topic == 'activity-done' && docShell !== subject)
+    if (topic == "activity-done" && docShell !== subject)
       return;
     switch (topic) {
-      case 'activity-done':
-        sendAsyncMsg('activitydone', { success: (data == 'activity-success') });
+      case "activity-done":
+        sendAsyncMsg("activitydone", { success: (data == "activity-success") });
         break;
-      case 'audio-playback':
+      case "audio-playback":
         if (subject === content) {
-          sendAsyncMsg('audioplaybackchange', { _payload_: data });
+          sendAsyncMsg("audioplaybackchange", { _payload_: data });
         }
         break;
-      case 'xpcom-shutdown':
+      case "xpcom-shutdown":
         this._shuttingDown = true;
         break;
-      case 'will-launch-app':
+      case "will-launch-app":
         // If the launcher is not visible, let's ignore the message.
         if (!docShell.isActive) {
           return;
         }
 
         // If this is not a content process, let's not freeze painting.
         if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_CONTENT) {
           return;
@@ -322,70 +321,70 @@ BrowserElementChild.prototype = {
         docShell.contentViewer.pausePainting();
 
         this._paintFrozenTimer && this._paintFrozenTimer.cancel();
         this._paintFrozenTimer = new Timer(this, 3000, Ci.nsITimer.TYPE_ONE_SHOT);
         break;
     }
   },
 
-  notify: function(timer) {
+  notify(timer) {
     docShell.contentViewer.resumePainting();
     this._paintFrozenTimer.cancel();
     this._paintFrozenTimer = null;
   },
 
   get _windowUtils() {
     return content.document.defaultView.windowUtils;
   },
 
-  _tryGetInnerWindowID: function(win) {
+  _tryGetInnerWindowID(win) {
     let utils = win.windowUtils;
     try {
       return utils.currentInnerWindowID;
-    }
-    catch(e) {
+    } catch (e) {
       return null;
     }
   },
 
   /**
    * Show a modal prompt.  Called by BrowserElementPromptService.
    */
-  showModalPrompt: function(win, args) {
+  showModalPrompt(win, args) {
     let utils = win.windowUtils;
 
     args.windowID = { outer: utils.outerWindowID,
                       inner: this._tryGetInnerWindowID(win) };
-    sendAsyncMsg('showmodalprompt', args);
+    sendAsyncMsg("showmodalprompt", args);
 
     let returnValue = this._waitForResult(win);
 
-    if (args.promptType == 'prompt' ||
-        args.promptType == 'confirm' ||
-        args.promptType == 'custom-prompt') {
+    if (args.promptType == "prompt" ||
+        args.promptType == "confirm" ||
+        args.promptType == "custom-prompt") {
       return returnValue;
     }
+    return undefined;
   },
 
   /**
    * Spin in a nested event loop until we receive a unblock-modal-prompt message for
    * this window.
    */
-  _waitForResult: function(win) {
+  _waitForResult(win) {
     debug("_waitForResult(" + win + ")");
     let utils = win.windowUtils;
 
     let outerWindowID = utils.outerWindowID;
     let innerWindowID = this._tryGetInnerWindowID(win);
     if (innerWindowID === null) {
       // I have no idea what waiting for a result means when there's no inner
       // window, so let's just bail.
       debug("_waitForResult: No inner window. Bailing.");
-      return;
+      return undefined;
     }
 
     this._windowIDDict[outerWindowID] = Cu.getWeakReference(win);
 
     debug("Entering modal state (outerWindowID=" + outerWindowID + ", " +
                                 "innerWindowID=" + innerWindowID + ")");
 
     utils.enterModalState();
@@ -431,17 +430,17 @@ BrowserElementChild.prototype = {
       utils.leaveModalState();
     }
 
     debug("Leaving modal state (outerID=" + outerWindowID + ", " +
                                "innerID=" + innerWindowID + ")");
     return returnValue;
   },
 
-  _recvStopWaiting: function(msg) {
+  _recvStopWaiting(msg) {
     let outerID = msg.json.windowID.outer;
     let innerID = msg.json.windowID.inner;
     let returnValue = msg.json.returnValue;
     debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID +
           ", returnValue=" + returnValue + ")");
 
     if (!this._windowIDDict[outerID]) {
       debug("recvStopWaiting: No record of outer window ID " + outerID);
@@ -460,789 +459,780 @@ BrowserElementChild.prototype = {
       return;
     }
 
     debug("recvStopWaiting " + win);
     win.modalReturnValue = returnValue;
     win.modalDepth--;
   },
 
-  _recvEnteredFullscreen: function() {
+  _recvEnteredFullscreen() {
     if (!this._windowUtils.handleFullscreenRequests() &&
         !content.document.fullscreenElement) {
       // If we don't actually have any pending fullscreen request
       // to handle, neither we have been in fullscreen, tell the
       // parent to just exit.
       sendAsyncMsg("exit-dom-fullscreen");
     }
   },
 
-  _recvExitFullscreen: function() {
+  _recvExitFullscreen() {
     this._windowUtils.exitFullscreen();
   },
 
-  _titleChangedHandler: function(e) {
+  _titleChangedHandler(e) {
     debug("Got titlechanged: (" + e.target.title + ")");
     var win = e.target.defaultView;
 
     // Ignore titlechanges which don't come from the top-level
     // <iframe mozbrowser> window.
     if (win == content) {
-      sendAsyncMsg('titlechange', { _payload_: e.target.title });
-    }
-    else {
+      sendAsyncMsg("titlechange", { _payload_: e.target.title });
+    } else {
       debug("Not top level!");
     }
   },
 
-  _maybeCopyAttribute: function(src, target, attribute) {
+  _maybeCopyAttribute(src, target, attribute) {
     if (src.getAttribute(attribute)) {
       target[attribute] = src.getAttribute(attribute);
     }
   },
 
-  _iconChangedHandler: function(e) {
-    debug('Got iconchanged: (' + e.target.href + ')');
+  _iconChangedHandler(e) {
+    debug("Got iconchanged: (" + e.target.href + ")");
     let icon = { href: e.target.href };
-    this._maybeCopyAttribute(e.target, icon, 'sizes');
-    this._maybeCopyAttribute(e.target, icon, 'rel');
-    sendAsyncMsg('iconchange', icon);
+    this._maybeCopyAttribute(e.target, icon, "sizes");
+    this._maybeCopyAttribute(e.target, icon, "rel");
+    sendAsyncMsg("iconchange", icon);
   },
 
-  _openSearchHandler: function(e) {
-    debug('Got opensearch: (' + e.target.href + ')');
+  _openSearchHandler(e) {
+    debug("Got opensearch: (" + e.target.href + ")");
 
     if (e.target.type !== "application/opensearchdescription+xml") {
       return;
     }
 
-    sendAsyncMsg('opensearch', { title: e.target.title,
+    sendAsyncMsg("opensearch", { title: e.target.title,
                                  href: e.target.href });
-
   },
 
   // Processes the "rel" field in <link> tags and forward to specific handlers.
-  _linkAddedHandler: function(e) {
+  _linkAddedHandler(e) {
     let win = e.target.ownerGlobal;
     // Ignore links which don't come from the top-level
     // <iframe mozbrowser> window.
     if (win != content) {
-      debug('Not top level!');
+      debug("Not top level!");
       return;
     }
 
     let handlers = {
-      'icon': this._iconChangedHandler.bind(this),
-      'apple-touch-icon': this._iconChangedHandler.bind(this),
-      'apple-touch-icon-precomposed': this._iconChangedHandler.bind(this),
-      'search': this._openSearchHandler,
+      "icon": this._iconChangedHandler.bind(this),
+      "apple-touch-icon": this._iconChangedHandler.bind(this),
+      "apple-touch-icon-precomposed": this._iconChangedHandler.bind(this),
+      "search": this._openSearchHandler,
     };
 
-    debug('Got linkAdded: (' + e.target.href + ') ' + e.target.rel);
-    e.target.rel.split(' ').forEach(function(x) {
+    debug("Got linkAdded: (" + e.target.href + ") " + e.target.rel);
+    e.target.rel.split(" ").forEach(function(x) {
       let token = x.toLowerCase();
       if (handlers[token]) {
         handlers[token](e);
       }
     }, this);
   },
 
-  _metaChangedHandler: function(e) {
+  _metaChangedHandler(e) {
     let win = e.target.ownerGlobal;
     // Ignore metas which don't come from the top-level
     // <iframe mozbrowser> window.
     if (win != content) {
-      debug('Not top level!');
+      debug("Not top level!");
       return;
     }
 
     var name = e.target.name;
     var property = e.target.getAttributeNS(null, "property");
 
     if (!name && !property) {
       return;
     }
 
-    debug('Got metaChanged: (' + (name || property) + ') ' +
+    debug("Got metaChanged: (" + (name || property) + ") " +
           e.target.content);
 
     let handlers = {
-      'viewmode': this._genericMetaHandler,
-      'theme-color': this._genericMetaHandler,
-      'theme-group': this._genericMetaHandler,
-      'application-name': this._applicationNameChangedHandler
+      "viewmode": this._genericMetaHandler,
+      "theme-color": this._genericMetaHandler,
+      "theme-group": this._genericMetaHandler,
+      "application-name": this._applicationNameChangedHandler,
     };
     let handler = handlers[name];
 
     if ((property || name).match(/^og:/)) {
       name = property || name;
       handler = this._genericMetaHandler;
     }
 
     if (handler) {
       handler(name, e.type, e.target);
     }
   },
 
-  _applicationNameChangedHandler: function(name, eventType, target) {
-    if (eventType !== 'DOMMetaAdded') {
+  _applicationNameChangedHandler(name, eventType, target) {
+    if (eventType !== "DOMMetaAdded") {
       // Bug 1037448 - Decide what to do when <meta name="application-name">
       // changes
       return;
     }
 
-    let meta = { name: name,
+    let meta = { name,
                  content: target.content };
 
     let lang;
     let elm;
 
     for (elm = target;
          !lang && elm && elm.nodeType == target.ELEMENT_NODE;
          elm = elm.parentNode) {
-      if (elm.hasAttribute('lang')) {
-        lang = elm.getAttribute('lang');
+      if (elm.hasAttribute("lang")) {
+        lang = elm.getAttribute("lang");
         continue;
       }
 
-      if (elm.hasAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang')) {
-        lang = elm.getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
+      if (elm.hasAttributeNS("http://www.w3.org/XML/1998/namespace", "lang")) {
+        lang = elm.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang");
         continue;
       }
     }
 
     // No lang has been detected.
     if (!lang && elm.nodeType == target.DOCUMENT_NODE) {
       lang = elm.contentLanguage;
     }
 
     if (lang) {
       meta.lang = lang;
     }
 
-    sendAsyncMsg('metachange', meta);
+    sendAsyncMsg("metachange", meta);
   },
 
-  _ScrollViewChangeHandler: function(e) {
+  _ScrollViewChangeHandler(e) {
     e.stopPropagation();
     let detail = {
       state: e.state,
     };
-    sendAsyncMsg('scrollviewchange', detail);
+    sendAsyncMsg("scrollviewchange", detail);
   },
 
-  _ClickHandler: function(e) {
-
+  _ClickHandler(e) {
     let isHTMLLink = node =>
         ((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
          (ChromeUtils.getClassName(node) === "HTMLAreaElement" && node.href) ||
          ChromeUtils.getClassName(node) === "HTMLLinkElement");
 
     // Open in a new tab if middle click or ctrl/cmd-click,
     // and e.target is a link or inside a link.
-    if ((Services.appinfo.OS == 'Darwin' && e.metaKey) ||
-        (Services.appinfo.OS != 'Darwin' && e.ctrlKey) ||
+    if ((Services.appinfo.OS == "Darwin" && e.metaKey) ||
+        (Services.appinfo.OS != "Darwin" && e.ctrlKey) ||
          e.button == 1) {
-
       let node = e.target;
       while (node && !isHTMLLink(node)) {
         node = node.parentNode;
       }
 
       if (node) {
-        sendAsyncMsg('opentab', {url: node.href});
+        sendAsyncMsg("opentab", {url: node.href});
       }
     }
   },
 
-  _genericMetaHandler: function(name, eventType, target) {
+  _genericMetaHandler(name, eventType, target) {
     let meta = {
-      name: name,
+      name,
       content: target.content,
-      type: eventType.replace('DOMMeta', '').toLowerCase()
+      type: eventType.replace("DOMMeta", "").toLowerCase(),
     };
-    sendAsyncMsg('metachange', meta);
+    sendAsyncMsg("metachange", meta);
   },
 
-  _addMozAfterPaintHandler: function(callback) {
+  _addMozAfterPaintHandler(callback) {
     function onMozAfterPaint() {
       let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
       if (uri.spec != "about:blank") {
         debug("Got afterpaint event: " + uri.spec);
-        removeEventListener('MozAfterPaint', onMozAfterPaint,
+        removeEventListener("MozAfterPaint", onMozAfterPaint,
                             /* useCapture = */ true);
         callback();
       }
     }
 
-    addEventListener('MozAfterPaint', onMozAfterPaint, /* useCapture = */ true);
+    addEventListener("MozAfterPaint", onMozAfterPaint, /* useCapture = */ true);
     return onMozAfterPaint;
   },
 
-  _windowCloseHandler: function(e) {
+  _windowCloseHandler(e) {
     let win = e.target;
     if (win != content || e.defaultPrevented) {
       return;
     }
 
     debug("Closing window " + win);
-    sendAsyncMsg('close');
+    sendAsyncMsg("close");
 
     // Inform the window implementation that we handled this close ourselves.
     e.preventDefault();
   },
 
-  _windowCreatedHandler: function(e) {
+  _windowCreatedHandler(e) {
     let targetDocShell = e.target.defaultView.docShell;
     if (targetDocShell != docShell) {
       return;
     }
 
     let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
     debug("Window created: " + uri.spec);
     if (uri.spec != "about:blank") {
-      this._addMozAfterPaintHandler(function () {
-        sendAsyncMsg('documentfirstpaint');
+      this._addMozAfterPaintHandler(function() {
+        sendAsyncMsg("documentfirstpaint");
       });
       this._isContentWindowCreated = true;
     }
   },
 
-  _windowResizeHandler: function(e) {
+  _windowResizeHandler(e) {
     let win = e.target;
     if (win != content || e.defaultPrevented) {
       return;
     }
 
     debug("resizing window " + win);
-    sendAsyncMsg('resize', { width: e.detail.width, height: e.detail.height });
+    sendAsyncMsg("resize", { width: e.detail.width, height: e.detail.height });
 
     // Inform the window implementation that we handled this resize ourselves.
     e.preventDefault();
   },
 
-  _contextmenuHandler: function(e) {
+  _contextmenuHandler(e) {
     debug("Got contextmenu");
 
     if (e.defaultPrevented) {
       return;
     }
 
     this._ctxCounter++;
     this._ctxHandlers = {};
 
     var elem = e.target;
     var menuData = {systemTargets: [], contextmenu: null};
     var ctxMenuId = null;
-    var clipboardPlainTextOnly = Services.prefs.getBoolPref('clipboard.plainTextOnly');
+    var clipboardPlainTextOnly = Services.prefs.getBoolPref("clipboard.plainTextOnly");
     var copyableElements = {
       image: false,
       link: false,
-      hasElements: function() {
+      hasElements() {
         return this.image || this.link;
-      }
+      },
     };
 
     // Set the event target as the copy image command needs it to
     // determine what was context-clicked on.
     docShell.contentViewer.QueryInterface(Ci.nsIContentViewerEdit).setCommandNode(elem);
 
     while (elem && elem.parentNode) {
       var ctxData = this._getSystemCtxMenuData(elem);
       if (ctxData) {
         menuData.systemTargets.push({
           nodeName: elem.nodeName,
-          data: ctxData
+          data: ctxData,
         });
       }
 
-      if (!ctxMenuId && 'hasAttribute' in elem && elem.hasAttribute('contextmenu')) {
-        ctxMenuId = elem.getAttribute('contextmenu');
+      if (!ctxMenuId && "hasAttribute" in elem && elem.hasAttribute("contextmenu")) {
+        ctxMenuId = elem.getAttribute("contextmenu");
       }
 
       // Enable copy image/link option
-      if (elem.nodeName == 'IMG') {
+      if (elem.nodeName == "IMG") {
         copyableElements.image = !clipboardPlainTextOnly;
-      } else if (elem.nodeName == 'A') {
+      } else if (elem.nodeName == "A") {
         copyableElements.link = true;
       }
 
       elem = elem.parentNode;
     }
 
     if (ctxMenuId || copyableElements.hasElements()) {
       var menu = null;
       if (ctxMenuId) {
         menu = e.target.ownerDocument.getElementById(ctxMenuId);
       }
-      menuData.contextmenu = this._buildMenuObj(menu, '', copyableElements);
+      menuData.contextmenu = this._buildMenuObj(menu, "", copyableElements);
     }
 
     // Pass along the position where the context menu should be located
     menuData.clientX = e.clientX;
     menuData.clientY = e.clientY;
     menuData.screenX = e.screenX;
     menuData.screenY = e.screenY;
 
     // The value returned by the contextmenu sync call is true if the embedder
     // called preventDefault() on its contextmenu event.
     //
     // We call preventDefault() on our contextmenu event if the embedder called
     // preventDefault() on /its/ contextmenu event.  This way, if the embedder
     // ignored the contextmenu event, TabChild will fire a click.
-    if (sendSyncMsg('contextmenu', menuData)[0]) {
+    if (sendSyncMsg("contextmenu", menuData)[0]) {
       e.preventDefault();
     } else {
       this._ctxHandlers = {};
     }
   },
 
-  _getSystemCtxMenuData: function(elem) {
+  _getSystemCtxMenuData(elem) {
     let documentURI =
       docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec;
 
     if ((ChromeUtils.getClassName(elem) === "HTMLAnchorElement" && elem.href) ||
         (ChromeUtils.getClassName(elem) === "HTMLAreaElement" && elem.href)) {
       return {uri: elem.href,
-              documentURI: documentURI,
+              documentURI,
               text: elem.textContent.substring(0, kLongestReturnedString)};
     }
     if (elem instanceof Ci.nsIImageLoadingContent &&
         (elem.currentRequestFinalURI || elem.currentURI)) {
       let uri = elem.currentRequestFinalURI || elem.currentURI;
-      return {uri: uri.spec, documentURI: documentURI};
+      return {uri: uri.spec, documentURI};
     }
     if (ChromeUtils.getClassName(elem) === "HTMLImageElement") {
-      return {uri: elem.src, documentURI: documentURI};
+      return {uri: elem.src, documentURI};
     }
     if (ChromeUtils.getClassName(elem) === "HTMLVideoElement" ||
         ChromeUtils.getClassName(elem) === "HTMLAudioElement") {
       let hasVideo = !(elem.readyState >= elem.HAVE_METADATA &&
                        (elem.videoWidth == 0 || elem.videoHeight == 0));
       return {uri: elem.currentSrc || elem.src,
-              hasVideo: hasVideo,
-              documentURI: documentURI};
+              hasVideo,
+              documentURI};
     }
     if (ChromeUtils.getClassName(elem) === "HTMLInputElement" &&
         elem.hasAttribute("name")) {
       // For input elements, we look for a parent <form> and if there is
       // one we return the form's method and action uri.
       let parent = elem.parentNode;
       while (parent) {
         if (ChromeUtils.getClassName(parent) === "HTMLFormElement" &&
             parent.hasAttribute("action")) {
           let actionHref = docShell.QueryInterface(Ci.nsIWebNavigation)
                                    .currentURI
                                    .resolve(parent.getAttribute("action"));
           let method = parent.hasAttribute("method")
             ? parent.getAttribute("method").toLowerCase()
             : "get";
           return {
-            documentURI: documentURI,
+            documentURI,
             action: actionHref,
-            method: method,
+            method,
             name: elem.getAttribute("name"),
-          }
+          };
         }
         parent = parent.parentNode;
       }
     }
     return false;
   },
 
-  _scrollEventHandler: function(e) {
+  _scrollEventHandler(e) {
     let win = e.target.defaultView;
     if (win != content) {
       return;
     }
 
     debug("scroll event " + win);
     sendAsyncMsg("scroll", { top: win.scrollY, left: win.scrollX });
   },
 
-  _mozScrollAreaChanged: function(e) {
-    sendAsyncMsg('scrollareachanged', {
+  _mozScrollAreaChanged(e) {
+    sendAsyncMsg("scrollareachanged", {
       width: e.width,
-      height: e.height
+      height: e.height,
     });
   },
 
-  _mozRequestedDOMFullscreen: function(e) {
+  _mozRequestedDOMFullscreen(e) {
     sendAsyncMsg("requested-dom-fullscreen");
   },
 
-  _mozFullscreenOriginChange: function(e) {
+  _mozFullscreenOriginChange(e) {
     sendAsyncMsg("fullscreen-origin-change", {
-      originNoSuffix: e.target.nodePrincipal.originNoSuffix
+      originNoSuffix: e.target.nodePrincipal.originNoSuffix,
     });
   },
 
-  _mozExitDomFullscreen: function(e) {
+  _mozExitDomFullscreen(e) {
     sendAsyncMsg("exit-dom-fullscreen");
   },
 
-  _recvFireCtxCallback: function(data) {
+  _recvFireCtxCallback(data) {
     debug("Received fireCtxCallback message: (" + data.json.menuitem + ")");
 
     let doCommandIfEnabled = (command) => {
       if (docShell.isCommandEnabled(command)) {
         docShell.doCommand(command);
       }
     };
 
-    if (data.json.menuitem == 'copy-image') {
-      doCommandIfEnabled('cmd_copyImage');
-    } else if (data.json.menuitem == 'copy-link') {
-      doCommandIfEnabled('cmd_copyLink');
+    if (data.json.menuitem == "copy-image") {
+      doCommandIfEnabled("cmd_copyImage");
+    } else if (data.json.menuitem == "copy-link") {
+      doCommandIfEnabled("cmd_copyLink");
     } else if (data.json.menuitem in this._ctxHandlers) {
       this._ctxHandlers[data.json.menuitem].click();
       this._ctxHandlers = {};
     } else {
       // We silently ignore if the embedder uses an incorrect id in the callback
       debug("Ignored invalid contextmenu invocation");
     }
   },
 
-  _buildMenuObj: function(menu, idPrefix, copyableElements) {
-    var menuObj = {type: 'menu', customized: false, items: []};
+  _buildMenuObj(menu, idPrefix, copyableElements) {
+    var menuObj = {type: "menu", customized: false, items: []};
     // Customized context menu
     if (menu) {
-      this._maybeCopyAttribute(menu, menuObj, 'label');
+      this._maybeCopyAttribute(menu, menuObj, "label");
 
-      for (var i = 0, child; child = menu.children[i++];) {
-        if (child.nodeName === 'MENU') {
-          menuObj.items.push(this._buildMenuObj(child, idPrefix + i + '_', false));
-        } else if (child.nodeName === 'MENUITEM') {
-          var id = this._ctxCounter + '_' + idPrefix + i;
-          var menuitem = {id: id, type: 'menuitem'};
-          this._maybeCopyAttribute(child, menuitem, 'label');
-          this._maybeCopyAttribute(child, menuitem, 'icon');
+      for (var i = 0, child; (child = menu.children[i++]);) {
+        if (child.nodeName === "MENU") {
+          menuObj.items.push(this._buildMenuObj(child, idPrefix + i + "_", false));
+        } else if (child.nodeName === "MENUITEM") {
+          var id = this._ctxCounter + "_" + idPrefix + i;
+          var menuitem = {id, type: "menuitem"};
+          this._maybeCopyAttribute(child, menuitem, "label");
+          this._maybeCopyAttribute(child, menuitem, "icon");
           this._ctxHandlers[id] = child;
           menuObj.items.push(menuitem);
         }
       }
 
       if (menuObj.items.length > 0) {
         menuObj.customized = true;
       }
     }
     // Note: Display "Copy Link" first in order to make sure "Copy Image" is
     //       put together with other image options if elem is an image link.
     // "Copy Link" menu item
     if (copyableElements.link) {
-      menuObj.items.push({id: 'copy-link'});
+      menuObj.items.push({id: "copy-link"});
     }
     // "Copy Image" menu item
     if (copyableElements.image) {
-      menuObj.items.push({id: 'copy-image'});
+      menuObj.items.push({id: "copy-image"});
     }
 
     return menuObj;
   },
 
   /**
    * Called when the window which contains this iframe becomes hidden or
    * visible.
    */
-  _recvOwnerVisibilityChange: function(data) {
+  _recvOwnerVisibilityChange(data) {
     debug("Received ownerVisibilityChange: (" + data.json.visible + ")");
     var visible = data.json.visible;
     if (docShell && docShell.isActive !== visible) {
       docShell.isActive = visible;
 
       // Ensure painting is not frozen if the app goes visible.
       if (visible && this._paintFrozenTimer) {
         this.notify();
       }
     }
   },
 
-  _recvSendMouseEvent: function(data) {
+  _recvSendMouseEvent(data) {
     let json = data.json;
     let utils = content.windowUtils;
     utils.sendMouseEventToWindow(json.type, json.x, json.y, json.button,
                                  json.clickCount, json.modifiers);
   },
 
-  _recvCanGoBack: function(data) {
+  _recvCanGoBack(data) {
     var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
-    sendAsyncMsg('got-can-go-back', {
+    sendAsyncMsg("got-can-go-back", {
       id: data.json.id,
-      successRv: webNav.canGoBack
+      successRv: webNav.canGoBack,
     });
   },
 
-  _recvCanGoForward: function(data) {
+  _recvCanGoForward(data) {
     var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
-    sendAsyncMsg('got-can-go-forward', {
+    sendAsyncMsg("got-can-go-forward", {
       id: data.json.id,
-      successRv: webNav.canGoForward
+      successRv: webNav.canGoForward,
     });
   },
 
-  _recvGoBack: function(data) {
+  _recvGoBack(data) {
     try {
       docShell.QueryInterface(Ci.nsIWebNavigation).goBack();
-    } catch(e) {
+    } catch (e) {
       // Silently swallow errors; these happen when we can't go back.
     }
   },
 
-  _recvGoForward: function(data) {
+  _recvGoForward(data) {
     try {
       docShell.QueryInterface(Ci.nsIWebNavigation).goForward();
-    } catch(e) {
+    } catch (e) {
       // Silently swallow errors; these happen when we can't go forward.
     }
   },
 
-  _recvReload: function(data) {
+  _recvReload(data) {
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     let reloadFlags = data.json.hardReload ?
       webNav.LOAD_FLAGS_BYPASS_PROXY | webNav.LOAD_FLAGS_BYPASS_CACHE :
       webNav.LOAD_FLAGS_NONE;
     try {
       webNav.reload(reloadFlags);
-    } catch(e) {
+    } catch (e) {
       // Silently swallow errors; these can happen if a used cancels reload
     }
   },
 
-  _recvStop: function(data) {
+  _recvStop(data) {
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     webNav.stop(webNav.STOP_NETWORK);
   },
 
   // The docShell keeps a weak reference to the progress listener, so we need
   // to keep a strong ref to it ourselves.
   _progressListener: {
     QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener,
                                             Ci.nsISupportsWeakReference]),
     _seenLoadStart: false,
 
-    onLocationChange: function(webProgress, request, location, flags) {
+    onLocationChange(webProgress, request, location, flags) {
       // We get progress events from subshells here, which is kind of weird.
       if (webProgress != docShell) {
         return;
       }
 
       // Ignore locationchange events which occur before the first loadstart.
       // These are usually about:blank loads we don't care about.
       if (!this._seenLoadStart) {
         return;
       }
 
       // Remove password from uri.
-      location = Cc["@mozilla.org/docshell/urifixup;1"]
-        .getService(Ci.nsIURIFixup).createExposableURI(location);
+      location = Services.uriFixup.createExposableURI(location);
 
       var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
 
-      sendAsyncMsg('locationchange', { url: location.spec,
+      sendAsyncMsg("locationchange", { url: location.spec,
                                        canGoBack: webNav.canGoBack,
                                        canGoForward: webNav.canGoForward });
     },
 
-    onStateChange: function(webProgress, request, stateFlags, status) {
+    // eslint-disable-next-line complexity
+    onStateChange(webProgress, request, stateFlags, status) {
       if (webProgress != docShell) {
         return;
       }
 
       if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
         this._seenLoadStart = true;
-        sendAsyncMsg('loadstart');
+        sendAsyncMsg("loadstart");
       }
 
       if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
-        let bgColor = 'transparent';
+        let bgColor = "transparent";
         try {
           bgColor = content.getComputedStyle(content.document.body)
-                           .getPropertyValue('background-color');
+                           .getPropertyValue("background-color");
         } catch (e) {}
-        sendAsyncMsg('loadend', {backgroundColor: bgColor});
+        sendAsyncMsg("loadend", {backgroundColor: bgColor});
 
         switch (status) {
           case Cr.NS_OK :
           case Cr.NS_BINDING_ABORTED :
             // Ignoring NS_BINDING_ABORTED, which is set when loading page is
             // stopped.
           case Cr.NS_ERROR_PARSED_DATA_CACHED:
             return;
 
           // TODO See nsDocShell::DisplayLoadError to see what extra
           // information we should be annotating this first block of errors
           // with. Bug 1107091.
           case Cr.NS_ERROR_UNKNOWN_PROTOCOL :
-            sendAsyncMsg('error', { type: 'unknownProtocolFound' });
+            sendAsyncMsg("error", { type: "unknownProtocolFound" });
             return;
           case Cr.NS_ERROR_FILE_NOT_FOUND :
-            sendAsyncMsg('error', { type: 'fileNotFound' });
+            sendAsyncMsg("error", { type: "fileNotFound" });
             return;
           case Cr.NS_ERROR_UNKNOWN_HOST :
-            sendAsyncMsg('error', { type: 'dnsNotFound' });
+            sendAsyncMsg("error", { type: "dnsNotFound" });
             return;
           case Cr.NS_ERROR_CONNECTION_REFUSED :
-            sendAsyncMsg('error', { type: 'connectionFailure' });
+            sendAsyncMsg("error", { type: "connectionFailure" });
             return;
           case Cr.NS_ERROR_NET_INTERRUPT :
-            sendAsyncMsg('error', { type: 'netInterrupt' });
+            sendAsyncMsg("error", { type: "netInterrupt" });
             return;
           case Cr.NS_ERROR_NET_TIMEOUT :
-            sendAsyncMsg('error', { type: 'netTimeout' });
+            sendAsyncMsg("error", { type: "netTimeout" });
             return;
           case Cr.NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION :
-            sendAsyncMsg('error', { type: 'cspBlocked' });
+            sendAsyncMsg("error", { type: "cspBlocked" });
             return;
           case Cr.NS_ERROR_PHISHING_URI :
-            sendAsyncMsg('error', { type: 'deceptiveBlocked' });
+            sendAsyncMsg("error", { type: "deceptiveBlocked" });
             return;
           case Cr.NS_ERROR_MALWARE_URI :
-            sendAsyncMsg('error', { type: 'malwareBlocked' });
+            sendAsyncMsg("error", { type: "malwareBlocked" });
             return;
           case Cr.NS_ERROR_HARMFUL_URI :
-            sendAsyncMsg('error', { type: 'harmfulBlocked' });
+            sendAsyncMsg("error", { type: "harmfulBlocked" });
             return;
           case Cr.NS_ERROR_UNWANTED_URI :
-            sendAsyncMsg('error', { type: 'unwantedBlocked' });
+            sendAsyncMsg("error", { type: "unwantedBlocked" });
             return;
           case Cr.NS_ERROR_FORBIDDEN_URI :
-            sendAsyncMsg('error', { type: 'forbiddenBlocked' });
+            sendAsyncMsg("error", { type: "forbiddenBlocked" });
             return;
 
           case Cr.NS_ERROR_OFFLINE :
-            sendAsyncMsg('error', { type: 'offline' });
+            sendAsyncMsg("error", { type: "offline" });
             return;
           case Cr.NS_ERROR_MALFORMED_URI :
-            sendAsyncMsg('error', { type: 'malformedURI' });
+            sendAsyncMsg("error", { type: "malformedURI" });
             return;
           case Cr.NS_ERROR_REDIRECT_LOOP :
-            sendAsyncMsg('error', { type: 'redirectLoop' });
+            sendAsyncMsg("error", { type: "redirectLoop" });
             return;
           case Cr.NS_ERROR_UNKNOWN_SOCKET_TYPE :
-            sendAsyncMsg('error', { type: 'unknownSocketType' });
+            sendAsyncMsg("error", { type: "unknownSocketType" });
             return;
           case Cr.NS_ERROR_NET_RESET :
-            sendAsyncMsg('error', { type: 'netReset' });
+            sendAsyncMsg("error", { type: "netReset" });
             return;
           case Cr.NS_ERROR_DOCUMENT_NOT_CACHED :
-            sendAsyncMsg('error', { type: 'notCached' });
+            sendAsyncMsg("error", { type: "notCached" });
             return;
           case Cr.NS_ERROR_DOCUMENT_IS_PRINTMODE :
-            sendAsyncMsg('error', { type: 'isprinting' });
+            sendAsyncMsg("error", { type: "isprinting" });
             return;
           case Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED :
-            sendAsyncMsg('error', { type: 'deniedPortAccess' });
+            sendAsyncMsg("error", { type: "deniedPortAccess" });
             return;
           case Cr.NS_ERROR_UNKNOWN_PROXY_HOST :
-            sendAsyncMsg('error', { type: 'proxyResolveFailure' });
+            sendAsyncMsg("error", { type: "proxyResolveFailure" });
             return;
           case Cr.NS_ERROR_PROXY_CONNECTION_REFUSED :
-            sendAsyncMsg('error', { type: 'proxyConnectFailure' });
+            sendAsyncMsg("error", { type: "proxyConnectFailure" });
             return;
           case Cr.NS_ERROR_INVALID_CONTENT_ENCODING :
-            sendAsyncMsg('error', { type: 'contentEncodingFailure' });
+            sendAsyncMsg("error", { type: "contentEncodingFailure" });
             return;
           case Cr.NS_ERROR_REMOTE_XUL :
-            sendAsyncMsg('error', { type: 'remoteXUL' });
+            sendAsyncMsg("error", { type: "remoteXUL" });
             return;
           case Cr.NS_ERROR_UNSAFE_CONTENT_TYPE :
-            sendAsyncMsg('error', { type: 'unsafeContentType' });
+            sendAsyncMsg("error", { type: "unsafeContentType" });
             return;
           case Cr.NS_ERROR_CORRUPTED_CONTENT :
-            sendAsyncMsg('error', { type: 'corruptedContentErrorv2' });
+            sendAsyncMsg("error", { type: "corruptedContentErrorv2" });
             return;
           case Cr.NS_ERROR_BLOCKED_BY_POLICY :
-            sendAsyncMsg('error', { type: 'blockedByPolicy' });
+            sendAsyncMsg("error", { type: "blockedByPolicy" });
             return;
 
           default:
             // getErrorClass() will throw if the error code passed in is not a NSS
             // error code.
             try {
-              let nssErrorsService = Cc['@mozilla.org/nss_errors_service;1']
+              let nssErrorsService = Cc["@mozilla.org/nss_errors_service;1"]
                                        .getService(Ci.nsINSSErrorsService);
               if (nssErrorsService.getErrorClass(status)
                     == Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT) {
                 // XXX Is there a point firing the event if the error page is not
                 // certerror? If yes, maybe we should add a property to the
                 // event to to indicate whether there is a custom page. That would
                 // let the embedder have more control over the desired behavior.
                 let errorPage = Services.prefs.getCharPref(CERTIFICATE_ERROR_PAGE_PREF, "");
 
-                if (errorPage == 'certerror') {
-                  sendAsyncMsg('error', { type: 'certerror' });
+                if (errorPage == "certerror") {
+                  sendAsyncMsg("error", { type: "certerror" });
                   return;
                 }
               }
             } catch (e) {}
 
-            sendAsyncMsg('error', { type: 'other' });
-            return;
+            sendAsyncMsg("error", { type: "other" });
         }
       }
     },
 
-    onSecurityChange: function(webProgress, request, state) {
+    onSecurityChange(webProgress, request, state) {
       if (webProgress != docShell) {
         return;
       }
 
       var securityStateDesc;
       if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
-        securityStateDesc = 'secure';
-      }
-      else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
-        securityStateDesc = 'broken';
-      }
-      else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
-        securityStateDesc = 'insecure';
-      }
-      else {
+        securityStateDesc = "secure";
+      } else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
+        securityStateDesc = "broken";
+      } else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
+        securityStateDesc = "insecure";
+      } else {
         debug("Unexpected securitychange state!");
-        securityStateDesc = '???';
+        securityStateDesc = "???";
       }
 
       var mixedStateDesc;
       if (state & Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT) {
-        mixedStateDesc = 'blocked_mixed_active_content';
-      }
-      else if (state & Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) {
+        mixedStateDesc = "blocked_mixed_active_content";
+      } else if (state & Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) {
         // Note that STATE_LOADED_MIXED_ACTIVE_CONTENT implies STATE_IS_BROKEN
-        mixedStateDesc = 'loaded_mixed_active_content';
+        mixedStateDesc = "loaded_mixed_active_content";
       }
 
       var isEV = !!(state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
       var isMixedContent = !!(state &
         (Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT |
         Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT));
 
-      sendAsyncMsg('securitychange', {
+      sendAsyncMsg("securitychange", {
         state: securityStateDesc,
         mixedState: mixedStateDesc,
         extendedValidation: isEV,
         mixedContent: isMixedContent,
       });
     },
   },
 
   // Expose the message manager for WebApps and others.
   _messageManagerPublic: {
     sendAsyncMessage: global.sendAsyncMessage.bind(global),
     sendSyncMessage: global.sendSyncMessage.bind(global),
     addMessageListener: global.addMessageListener.bind(global),
-    removeMessageListener: global.removeMessageListener.bind(global)
+    removeMessageListener: global.removeMessageListener.bind(global),
   },
 
   get messageManager() {
     return this._messageManagerPublic;
-  }
+  },
 };
 
 var api = null;
-if ('DoPreloadPostfork' in this && typeof this.DoPreloadPostfork === 'function') {
+if ("DoPreloadPostfork" in this && typeof this.DoPreloadPostfork === "function") {
   // If we are preloaded, instantiate BrowserElementChild after a content
   // process is forked.
   this.DoPreloadPostfork(function() {
     api = new BrowserElementChild();
   });
 } else {
   api = new BrowserElementChild();
 }
--- a/dom/browser-element/BrowserElementCopyPaste.js
+++ b/dom/browser-element/BrowserElementCopyPaste.js
@@ -1,82 +1,90 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* 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";
 
+/*
+global addMessageListener
+global removeMessageListener
+global docShell
+global content
+global sendAsyncMsg
+*/
+
 function debug(msg) {
   // dump("BrowserElementCopyPaste - " + msg + "\n");
 }
 
 debug("loaded");
 
 var CopyPasteAssistent = {
   COMMAND_MAP: {
-    'cut': 'cmd_cut',
-    'copy': 'cmd_copy',
-    'paste': 'cmd_paste',
-    'selectall': 'cmd_selectAll'
+    "cut": "cmd_cut",
+    "copy": "cmd_copy",
+    "paste": "cmd_paste",
+    "selectall": "cmd_selectAll",
   },
 
-  init: function() {
+  init() {
     addEventListener("mozcaretstatechanged", this,
                      /* useCapture = */ true, /* wantsUntrusted = */ false);
     addMessageListener("browser-element-api:call", this);
   },
 
-  destroy: function() {
+  destroy() {
     removeEventListener("mozcaretstatechanged", this,
                         /* useCapture = */ true, /* wantsUntrusted = */ false);
     removeMessageListener("browser-element-api:call", this);
   },
 
-  handleEvent: function(event) {
+  handleEvent(event) {
     switch (event.type) {
       case "mozcaretstatechanged":
         this._caretStateChangedHandler(event);
         break;
     }
   },
 
-  receiveMessage: function(message) {
+  receiveMessage(message) {
     switch (message.name) {
       case "browser-element-api:call":
         this._browserAPIHandler(message);
         break;
     }
   },
 
-  _browserAPIHandler: function(e) {
+  _browserAPIHandler(e) {
     switch (e.data.msg_name) {
-      case 'copypaste-do-command':
+      case "copypaste-do-command":
         if (this._isCommandEnabled(e.data.command)) {
           docShell.doCommand(this.COMMAND_MAP[e.data.command]);
         }
         break;
     }
   },
 
-  _isCommandEnabled: function(cmd) {
+  _isCommandEnabled(cmd) {
     let command = this.COMMAND_MAP[cmd];
     if (!command) {
       return false;
     }
 
     return docShell.isCommandEnabled(command);
   },
 
-  _caretStateChangedHandler: function(e) {
+  _caretStateChangedHandler(e) {
     e.stopPropagation();
 
     let boundingClientRect = e.boundingClientRect;
-    let canPaste = this._isCommandEnabled("paste");
+    this._isCommandEnabled("paste");
     let zoomFactor = content.innerWidth == 0 ? 1 : content.screen.width / content.innerWidth;
 
     let detail = {
       rect: {
         width: boundingClientRect ? boundingClientRect.width : 0,
         height: boundingClientRect ? boundingClientRect.height : 0,
         top: boundingClientRect ? boundingClientRect.top : 0,
         bottom: boundingClientRect ? boundingClientRect.bottom : 0,
@@ -84,38 +92,38 @@ var CopyPasteAssistent = {
         right: boundingClientRect ? boundingClientRect.right : 0,
       },
       commands: {
         canSelectAll: this._isCommandEnabled("selectall"),
         canCut: this._isCommandEnabled("cut"),
         canCopy: this._isCommandEnabled("copy"),
         canPaste: this._isCommandEnabled("paste"),
       },
-      zoomFactor: zoomFactor,
+      zoomFactor,
       reason: e.reason,
       collapsed: e.collapsed,
       caretVisible: e.caretVisible,
       selectionVisible: e.selectionVisible,
       selectionEditable: e.selectionEditable,
-      selectedTextContent: e.selectedTextContent
+      selectedTextContent: e.selectedTextContent,
     };
 
     // Get correct geometry information if we have nested iframe.
     let currentWindow = e.target.defaultView;
     while (currentWindow.realFrameElement) {
       let currentRect = currentWindow.realFrameElement.getBoundingClientRect();
       detail.rect.top += currentRect.top;
       detail.rect.bottom += currentRect.top;
       detail.rect.left += currentRect.left;
       detail.rect.right += currentRect.left;
       currentWindow = currentWindow.realFrameElement.ownerGlobal;
 
       let targetDocShell = currentWindow.docShell;
-      if(targetDocShell.isMozBrowser) {
+      if (targetDocShell.isMozBrowser) {
         break;
       }
     }
 
-    sendAsyncMsg('caretstatechanged', detail);
+    sendAsyncMsg("caretstatechanged", detail);
   },
 };
 
 CopyPasteAssistent.init();
--- a/dom/browser-element/BrowserElementParent.jsm
+++ b/dom/browser-element/BrowserElementParent.jsm
@@ -8,26 +8,17 @@
  * child.  We then listen to messages from the child script and take
  * appropriate action here in the parent.
  */
 
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const {BrowserElementPromptService} = ChromeUtils.import("resource://gre/modules/BrowserElementPromptService.jsm");
 
 function debug(msg) {
-  //dump("BrowserElementParent - " + msg + "\n");
-}
-
-function getIntPref(prefName, def) {
-  try {
-    return Services.prefs.getIntPref(prefName);
-  }
-  catch(err) {
-    return def;
-  }
+  // dump("BrowserElementParent - " + msg + "\n");
 }
 
 function handleWindowEvent(e) {
   if (this._browserElementParents) {
     let beps = ChromeUtils.nondeterministicGetWeakMapKeys(this._browserElementParents);
     beps.forEach(bep => bep._handleOwnerEvent(e));
   }
 }
@@ -56,31 +47,31 @@ function definePromiseMethod(msgName) {
 function BrowserElementParent() {
   debug("Creating new BrowserElementParent object");
   this._promiseCounter = 0;
   this._domRequestReady = false;
   this._pendingAPICalls = [];
   this._pendingPromises = {};
   this._pendingDOMFullscreen = false;
 
-  Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
-  Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true);
-  Services.obs.addObserver(this, 'back-docommand', /* ownsWeak = */ true);
+  Services.obs.addObserver(this, "oop-frameloader-crashed", /* ownsWeak = */ true);
+  Services.obs.addObserver(this, "ask-children-to-execute-copypaste-command", /* ownsWeak = */ true);
+  Services.obs.addObserver(this, "back-docommand", /* ownsWeak = */ true);
 }
 
 BrowserElementParent.prototype = {
 
   classDescription: "BrowserElementAPI implementation",
   classID: Components.ID("{9f171ac4-0939-4ef8-b360-3408aedc3060}"),
   contractID: "@mozilla.org/dom/browser-element-api;1",
   QueryInterface: ChromeUtils.generateQI([Ci.nsIBrowserElementAPI,
                                           Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference]),
 
-  setFrameLoader: function(frameLoader) {
+  setFrameLoader(frameLoader) {
     debug("Setting frameLoader");
     this._frameLoader = frameLoader;
     this._frameElement = frameLoader.ownerElement;
     if (!this._frameElement) {
       debug("No frame element?");
       return;
     }
     // Listen to visibilitychange on the iframe's owner window, and forward
@@ -91,60 +82,58 @@ BrowserElementParent.prototype = {
     // To accomplish this, we register just one listener on the window, and have
     // it reference a WeakMap whose keys are all the BrowserElementParent objects
     // on the window.  Then when the listener fires, we iterate over the
     // WeakMap's keys (which we can do, because we're chrome) to notify the
     // BrowserElementParents.
     if (!this._window._browserElementParents) {
       this._window._browserElementParents = new WeakMap();
       let handler = handleWindowEvent.bind(this._window);
-      let windowEvents = ['visibilitychange', 'fullscreenchange'];
-      let els = Cc["@mozilla.org/eventlistenerservice;1"]
-                  .getService(Ci.nsIEventListenerService);
+      let windowEvents = ["visibilitychange", "fullscreenchange"];
       for (let event of windowEvents) {
-        els.addSystemEventListener(this._window, event, handler,
-                                   /* useCapture = */ true);
+        Services.els.addSystemEventListener(this._window, event, handler,
+                                            /* useCapture = */ true);
       }
     }
 
     this._window._browserElementParents.set(this, null);
 
     // Insert ourself into the prompt service.
     BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
     this._setupMessageListener();
   },
 
   destroyFrameScripts() {
     debug("Destroying frame scripts");
     this._mm.sendAsyncMessage("browser-element-api:destroy");
   },
 
-  _runPendingAPICall: function() {
+  _runPendingAPICall() {
     if (!this._pendingAPICalls) {
       return;
     }
     for (let i = 0; i < this._pendingAPICalls.length; i++) {
       try {
         this._pendingAPICalls[i]();
       } catch (e) {
         // throw the expections from pending functions.
-        debug('Exception when running pending API call: ' +  e);
+        debug("Exception when running pending API call: " + e);
       }
     }
     delete this._pendingAPICalls;
   },
 
-  _setupMessageListener: function() {
+  _setupMessageListener() {
     this._mm = this._frameLoader.messageManager;
-    this._mm.addMessageListener('browser-element-api:call', this);
+    this._mm.addMessageListener("browser-element-api:call", this);
   },
 
-  receiveMessage: function(aMsg) {
+  receiveMessage(aMsg) {
     if (!this._isAlive()) {
-      return;
+      return undefined;
     }
 
     // Messages we receive are handed to functions which take a (data) argument,
     // where |data| is the message manager's data object.
     // We use a single message and dispatch to various function based
     // on data.msg_name
     let mmCalls = {
       "hello": this._recvHello,
@@ -172,51 +161,51 @@ BrowserElementParent.prototype = {
       "iconchange": this._fireEventFromMsg,
       "scrollareachanged": this._fireEventFromMsg,
       "titlechange": this._fireProfiledEventFromMsg,
       "opensearch": this._fireEventFromMsg,
       "metachange": this._fireEventFromMsg,
       "resize": this._fireEventFromMsg,
       "activitydone": this._fireEventFromMsg,
       "scroll": this._fireEventFromMsg,
-      "opentab": this._fireEventFromMsg
+      "opentab": this._fireEventFromMsg,
     };
 
     if (aMsg.data.msg_name in mmCalls) {
       return mmCalls[aMsg.data.msg_name].apply(this, arguments);
     } else if (aMsg.data.msg_name in mmSecuritySensitiveCalls) {
       return mmSecuritySensitiveCalls[aMsg.data.msg_name].apply(this, arguments);
     }
+    return undefined;
   },
 
-  _removeMessageListener: function() {
-    this._mm.removeMessageListener('browser-element-api:call', this);
+  _removeMessageListener() {
+    this._mm.removeMessageListener("browser-element-api:call", this);
   },
 
   /**
    * You shouldn't touch this._frameElement or this._window if _isAlive is
    * false.  (You'll likely get an exception if you do.)
    */
-  _isAlive: function() {
+  _isAlive() {
     return !Cu.isDeadWrapper(this._frameElement) &&
            !Cu.isDeadWrapper(this._frameElement.ownerDocument) &&
            !Cu.isDeadWrapper(this._frameElement.ownerGlobal);
   },
 
   get _window() {
     return this._frameElement.ownerGlobal;
   },
 
   get _windowUtils() {
     return this._window.windowUtils;
   },
 
-  promptAuth: function(authDetail, callback) {
+  promptAuth(authDetail, callback) {
     let evt;
-    let self = this;
     let callbackCalled = false;
     let cancelCallback = function() {
       if (!callbackCalled) {
         callbackCalled = true;
         callback(false, null, null);
       }
     };
 
@@ -226,52 +215,52 @@ BrowserElementParent.prototype = {
       return;
     }
 
     /* username and password */
     let detail = {
       host:     authDetail.host,
       path:     authDetail.path,
       realm:    authDetail.realm,
-      isProxy:  authDetail.isProxy
+      isProxy:  authDetail.isProxy,
     };
 
-    evt = this._createEvent('usernameandpasswordrequired', detail,
+    evt = this._createEvent("usernameandpasswordrequired", detail,
                             /* cancelable */ true);
     Cu.exportFunction(function(username, password) {
       if (callbackCalled)
         return;
       callbackCalled = true;
       callback(true, username, password);
-    }, evt.detail, { defineAs: 'authenticate' });
+    }, evt.detail, { defineAs: "authenticate" });
 
-    Cu.exportFunction(cancelCallback, evt.detail, { defineAs: 'cancel' });
+    Cu.exportFunction(cancelCallback, evt.detail, { defineAs: "cancel" });
 
     this._frameElement.dispatchEvent(evt);
 
     if (!evt.defaultPrevented) {
       cancelCallback();
     }
   },
 
-  _sendAsyncMsg: function(msg, data) {
+  _sendAsyncMsg(msg, data) {
     try {
       if (!data) {
         data = { };
       }
 
       data.msg_name = msg;
-      this._mm.sendAsyncMessage('browser-element-api:call', data);
+      this._mm.sendAsyncMessage("browser-element-api:call", data);
     } catch (e) {
       return false;
     }
     return true;
   },
 
-  _recvHello: function() {
+  _recvHello() {
     debug("recvHello");
 
     // Inform our child if our owner element's document is invisible.  Note
     // that we must do so here, rather than in the BrowserElementParent
     // constructor, because the BrowserElementChild may not be initialized when
     // we run our constructor.
     if (this._window.document.hidden) {
       this._ownerVisibilityChange();
@@ -280,106 +269,106 @@ BrowserElementParent.prototype = {
     if (!this._domRequestReady) {
       // At least, one message listener such as for hello is registered.
       // So we can use sendAsyncMessage now.
       this._domRequestReady = true;
       this._runPendingAPICall();
     }
   },
 
-  _fireCtxMenuEvent: function(data) {
+  _fireCtxMenuEvent(data) {
     let detail = data.json;
     let evtName = detail.msg_name;
 
-    debug('fireCtxMenuEventFromMsg: ' + evtName + ' ' + detail);
+    debug("fireCtxMenuEventFromMsg: " + evtName + " " + detail);
     let evt = this._createEvent(evtName, detail, /* cancellable */ true);
 
     if (detail.contextmenu) {
       var self = this;
       Cu.exportFunction(function(id) {
-        self._sendAsyncMsg('fire-ctx-callback', {menuitem: id});
-      }, evt.detail, { defineAs: 'contextMenuItemSelected' });
+        self._sendAsyncMsg("fire-ctx-callback", {menuitem: id});
+      }, evt.detail, { defineAs: "contextMenuItemSelected" });
     }
 
     // The embedder may have default actions on context menu events, so
     // we fire a context menu event even if the child didn't define a
     // custom context menu
     return !this._frameElement.dispatchEvent(evt);
   },
 
   /**
    * add profiler marker for each event fired.
    */
-  _fireProfiledEventFromMsg: function(data) {
+  _fireProfiledEventFromMsg(data) {
     if (Services.profiler !== undefined) {
       Services.profiler.AddMarker(data.json.msg_name);
     }
     this._fireEventFromMsg(data);
   },
 
   /**
    * Fire either a vanilla or a custom event, depending on the contents of
    * |data|.
    */
-  _fireEventFromMsg: function(data) {
+  _fireEventFromMsg(data) {
     let detail = data.json;
     let name = detail.msg_name;
 
     // For events that send a "_payload_" property, we just want to transmit
     // this in the event.
     if ("_payload_" in detail) {
       detail = detail._payload_;
     }
 
-    debug('fireEventFromMsg: ' + name + ', ' + JSON.stringify(detail));
+    debug("fireEventFromMsg: " + name + ", " + JSON.stringify(detail));
     let evt = this._createEvent(name, detail,
                                 /* cancelable = */ false);
     this._frameElement.dispatchEvent(evt);
   },
 
-  _handleShowModalPrompt: function(data) {
+  _handleShowModalPrompt(data) {
     // Fire a showmodalprmopt event on the iframe.  When this method is called,
     // the child is spinning in a nested event loop waiting for an
     // unblock-modal-prompt message.
     //
     // If the embedder calls preventDefault() on the showmodalprompt event,
     // we'll block the child until event.detail.unblock() is called.
     //
     // Otherwise, if preventDefault() is not called, we'll send the
     // unblock-modal-prompt message to the child as soon as the event is done
     // dispatching.
 
     let detail = data.json;
-    debug('handleShowPrompt ' + JSON.stringify(detail));
+    debug("handleShowPrompt " + JSON.stringify(detail));
 
     // Strip off the windowID property from the object we send along in the
     // event.
     let windowID = detail.windowID;
     delete detail.windowID;
     debug("Event will have detail: " + JSON.stringify(detail));
-    let evt = this._createEvent('showmodalprompt', detail,
+    let evt = this._createEvent("showmodalprompt", detail,
                                 /* cancelable = */ true);
 
     let self = this;
     let unblockMsgSent = false;
     function sendUnblockMsg() {
       if (unblockMsgSent) {
         return;
       }
       unblockMsgSent = true;
 
       // We don't need to sanitize evt.detail.returnValue (e.g. converting the
       // return value of confirm() to a boolean); Gecko does that for us.
 
-      let data = { windowID: windowID,
+      let data = { windowID,
                    returnValue: evt.detail.returnValue };
-      self._sendAsyncMsg('unblock-modal-prompt', data);
+      self._sendAsyncMsg("unblock-modal-prompt", data);
     }
 
-    Cu.exportFunction(sendUnblockMsg, evt.detail, { defineAs: 'unblock' });
+    Cu.exportFunction(sendUnblockMsg, evt.detail, { defineAs: "unblock" });
 
     this._frameElement.dispatchEvent(evt);
 
     if (!evt.defaultPrevented) {
       // Unblock the inner frame immediately.  Otherwise we'll unblock upon
       // evt.detail.unblock().
       sendUnblockMsg();
     }
@@ -397,77 +386,77 @@ BrowserElementParent.prototype = {
   //            "updateposition", "longpressonemptycontent", "taponcaret", "presscaret",
   //            "releasecaret".
   //  - collapsed: Indicate current selection is collapsed or not.
   //  - caretVisible: Indicate the caret visiibility.
   //  - selectionVisible: Indicate current selection is visible or not.
   //  - selectionEditable: Indicate current selection is editable or not.
   //  - selectedTextContent: Contains current selected text content, which is
   //                         equivalent to the string returned by Selection.toString().
-  _handleCaretStateChanged: function(data) {
-    let evt = this._createEvent('caretstatechanged', data.json,
+  _handleCaretStateChanged(data) {
+    let evt = this._createEvent("caretstatechanged", data.json,
                                 /* cancelable = */ false);
 
     let self = this;
     function sendDoCommandMsg(cmd) {
       let data = { command: cmd };
-      self._sendAsyncMsg('copypaste-do-command', data);
+      self._sendAsyncMsg("copypaste-do-command", data);
     }
-    Cu.exportFunction(sendDoCommandMsg, evt.detail, { defineAs: 'sendDoCommandMsg' });
+    Cu.exportFunction(sendDoCommandMsg, evt.detail, { defineAs: "sendDoCommandMsg" });
 
     this._frameElement.dispatchEvent(evt);
   },
 
-  _handleScrollViewChange: function(data) {
+  _handleScrollViewChange(data) {
     let evt = this._createEvent("scrollviewchange", data.json,
                                 /* cancelable = */ false);
     this._frameElement.dispatchEvent(evt);
   },
 
-  _createEvent: function(evtName, detail, cancelable) {
+  _createEvent(evtName, detail, cancelable) {
     // This will have to change if we ever want to send a CustomEvent with null
     // detail.  For now, it's OK.
     if (detail !== undefined && detail !== null) {
       detail = Cu.cloneInto(detail, this._window);
-      return new this._window.CustomEvent('mozbrowser' + evtName,
+      return new this._window.CustomEvent("mozbrowser" + evtName,
                                           { bubbles: true,
-                                            cancelable: cancelable,
-                                            detail: detail });
+                                            cancelable,
+                                            detail });
     }
 
-    return new this._window.Event('mozbrowser' + evtName,
+    return new this._window.Event("mozbrowser" + evtName,
                                   { bubbles: true,
-                                    cancelable: cancelable });
+                                    cancelable });
   },
 
   /**
    * Kick off an async operation in the child process.
    *
    * We'll send a message called |msgName| to the child process, passing along
    * an object with two fields:
    *
    *  - id:  the ID of this async call.
    *  - arg: arguments to pass to the child along with this async call.
    *
    * We expect the child to pass the ID back to us upon completion of the
    * call.  See _gotAsyncResult.
    */
-  _sendAsyncRequest: function(msgName, args) {
-    let id = 'req_' + this._promiseCounter++;
+  _sendAsyncRequest(msgName, args) {
+    let id = "req_" + this._promiseCounter++;
     let resolve, reject;
     let p = new this._window.Promise((res, rej) => {
       resolve = res;
       reject = rej;
     });
     let self = this;
     let send = function() {
       if (!self._isAlive()) {
         return;
       }
-      if (self._sendAsyncMsg(msgName, {id: id, args: args})) {
+      if (self._sendAsyncMsg(msgName, {id, args})) {
         self._pendingPromises[id] = { p, resolve, reject };
       } else {
         reject(new this._window.DOMException("fail"));
       }
     };
     if (this._domRequestReady) {
       send();
     } else {
@@ -485,26 +474,25 @@ BrowserElementParent.prototype = {
    * The fields have the following meanings:
    *
    *  - id:        the ID of the async call (see _sendAsyncRequest)
    *  - successRv: the call's return value, if the call succeeded
    *  - errorMsg:  the message to pass to the Promise reject callback, if the
    *               call failed.
    *
    */
-  _gotAsyncResult: function(data) {
+  _gotAsyncResult(data) {
     let p = this._pendingPromises[data.json.id];
     delete this._pendingPromises[data.json.id];
 
-    if ('successRv' in data.json) {
+    if ("successRv" in data.json) {
       debug("Successful gotAsyncResult.");
       let clientObj = Cu.cloneInto(data.json.successRv, this._window);
       p.resolve(clientObj);
-    }
-    else {
+    } else {
       debug("Got error in gotAsyncResult.");
       p.reject(new this._window.DOMException(
         Cu.cloneInto(data.json.errorMsg, this._window)));
     }
   },
 
   sendMouseEvent: defineNoReturnMethod(function(type, x, y, button, clickCount, modifiers) {
     // This method used to attempt to transform from the parent
@@ -512,100 +500,100 @@ BrowserElementParent.prototype = {
     // transform was always a no-op, because this._frameLoader.tabParent
     // was null.
     this._sendAsyncMsg("send-mouse-event", {
       "type": type,
       "x": x,
       "y": y,
       "button": button,
       "clickCount": clickCount,
-      "modifiers": modifiers
+      "modifiers": modifiers,
     });
   }),
 
-  getCanGoBack: definePromiseMethod('get-can-go-back'),
-  getCanGoForward: definePromiseMethod('get-can-go-forward'),
+  getCanGoBack: definePromiseMethod("get-can-go-back"),
+  getCanGoForward: definePromiseMethod("get-can-go-forward"),
 
   goBack: defineNoReturnMethod(function() {
-    this._sendAsyncMsg('go-back');
+    this._sendAsyncMsg("go-back");
   }),
 
   goForward: defineNoReturnMethod(function() {
-    this._sendAsyncMsg('go-forward');
+    this._sendAsyncMsg("go-forward");
   }),
 
   reload: defineNoReturnMethod(function(hardReload) {
-    this._sendAsyncMsg('reload', {hardReload: hardReload});
+    this._sendAsyncMsg("reload", {hardReload});
   }),
 
   stop: defineNoReturnMethod(function() {
-    this._sendAsyncMsg('stop');
+    this._sendAsyncMsg("stop");
   }),
 
   /**
    * Called when the visibility of the window which owns this iframe changes.
    */
-  _ownerVisibilityChange: function() {
-    this._sendAsyncMsg('owner-visibility-change',
+  _ownerVisibilityChange() {
+    this._sendAsyncMsg("owner-visibility-change",
                        {visible: !this._window.document.hidden});
   },
 
-  _requestedDOMFullscreen: function() {
+  _requestedDOMFullscreen() {
     this._pendingDOMFullscreen = true;
     this._windowUtils.remoteFrameFullscreenChanged(this._frameElement);
   },
 
-  _fullscreenOriginChange: function(data) {
+  _fullscreenOriginChange(data) {
     Services.obs.notifyObservers(
       this._frameElement, "fullscreen-origin-change", data.json.originNoSuffix);
   },
 
-  _exitDomFullscreen: function(data) {
+  _exitDomFullscreen(data) {
     this._windowUtils.remoteFrameFullscreenReverted();
   },
 
-  _handleOwnerEvent: function(evt) {
+  _handleOwnerEvent(evt) {
     switch (evt.type) {
-      case 'visibilitychange':
+      case "visibilitychange":
         this._ownerVisibilityChange();
         break;
-      case 'fullscreenchange':
+      case "fullscreenchange":
         if (!this._window.document.fullscreenElement) {
-          this._sendAsyncMsg('exit-fullscreen');
+          this._sendAsyncMsg("exit-fullscreen");
         } else if (this._pendingDOMFullscreen) {
           this._pendingDOMFullscreen = false;
-          this._sendAsyncMsg('entered-fullscreen');
+          this._sendAsyncMsg("entered-fullscreen");
         }
         break;
     }
   },
 
-  _fireFatalError: function() {
-    let evt = this._createEvent('error', {type: 'fatal'},
+  _fireFatalError() {
+    let evt = this._createEvent("error", {type: "fatal"},
                                 /* cancelable = */ false);
     this._frameElement.dispatchEvent(evt);
   },
 
-  observe: function(subject, topic, data) {
-    switch(topic) {
-    case 'oop-frameloader-crashed':
+  observe(subject, topic, data) {
+    switch (topic) {
+    case "oop-frameloader-crashed":
       if (this._isAlive() && subject == this._frameLoader) {
         this._fireFatalError();
       }
       break;
-    case 'ask-children-to-execute-copypaste-command':
+    case "ask-children-to-execute-copypaste-command":
       if (this._isAlive() && this._frameElement == subject.wrappedJSObject) {
-        this._sendAsyncMsg('copypaste-do-command', { command: data });
+        this._sendAsyncMsg("copypaste-do-command", { command: data });
       }
       break;
-    case 'back-docommand':
+    case "back-docommand":
       if (this._isAlive() && this._frameLoader.visible) {
           this.goBack();
       }
       break;
     default:
-      debug('Unknown topic: ' + topic);
+      debug("Unknown topic: " + topic);
       break;
-    };
+    }
   },
 };
 
 var EXPORTED_SYMBOLS = ["BrowserElementParent"];
--- a/dom/browser-element/BrowserElementPromptService.jsm
+++ b/dom/browser-element/BrowserElementPromptService.jsm
@@ -10,176 +10,176 @@ var Cm = Components.manager.QueryInterfa
 var EXPORTED_SYMBOLS = ["BrowserElementPromptService"];
 
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
 const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
 
 function debug(msg) {
-  //dump("BrowserElementPromptService - " + msg + "\n");
+  // dump("BrowserElementPromptService - " + msg + "\n");
 }
 
 function BrowserElementPrompt(win, browserElementChild) {
   this._win = win;
   this._browserElementChild = browserElementChild;
 }
 
 BrowserElementPrompt.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIPrompt]),
 
-  alert: function(title, text) {
+  alert(title, text) {
     this._browserElementChild.showModalPrompt(
-      this._win, {promptType: "alert", title: title, message: text, returnValue: undefined});
+      this._win, {promptType: "alert", title, message: text, returnValue: undefined});
   },
 
-  alertCheck: function(title, text, checkMsg, checkState) {
+  alertCheck(title, text, checkMsg, checkState) {
     // Treat this like a normal alert() call, ignoring the checkState.  The
     // front-end can do its own suppression of the alert() if it wants.
     this.alert(title, text);
   },
 
-  confirm: function(title, text) {
+  confirm(title, text) {
     return this._browserElementChild.showModalPrompt(
-      this._win, {promptType: "confirm", title: title, message: text, returnValue: undefined});
+      this._win, {promptType: "confirm", title, message: text, returnValue: undefined});
   },
 
-  confirmCheck: function(title, text, checkMsg, checkState) {
+  confirmCheck(title, text, checkMsg, checkState) {
     return this.confirm(title, text);
   },
 
   // Each button is described by an object with the following schema
   // {
   //   string messageType,  // 'builtin' or 'custom'
   //   string message, // 'ok', 'cancel', 'yes', 'no', 'save', 'dontsave',
   //                   // 'revert' or a string from caller if messageType was 'custom'.
   // }
   //
   // Expected result from embedder:
   // {
   //   int button, // Index of the button that user pressed.
   //   boolean checked, // True if the check box is checked.
   // }
-  confirmEx: function(title, text, buttonFlags, button0Title, button1Title,
+  confirmEx(title, text, buttonFlags, button0Title, button1Title,
                       button2Title, checkMsg, checkState) {
     let buttonProperties = this._buildConfirmExButtonProperties(buttonFlags,
                                                                 button0Title,
                                                                 button1Title,
                                                                 button2Title);
     let defaultReturnValue = { selectedButton: buttonProperties.defaultButton };
     if (checkMsg) {
       defaultReturnValue.checked = checkState.value;
     }
     let ret = this._browserElementChild.showModalPrompt(
       this._win,
       {
         promptType: "custom-prompt",
-        title: title,
+        title,
         message: text,
         defaultButton: buttonProperties.defaultButton,
         buttons: buttonProperties.buttons,
         showCheckbox: !!checkMsg,
         checkboxMessage: checkMsg,
         checkboxCheckedByDefault: !!checkState.value,
-        returnValue: defaultReturnValue
+        returnValue: defaultReturnValue,
       }
     );
     if (checkMsg) {
       checkState.value = ret.checked;
     }
     return buttonProperties.indexToButtonNumberMap[ret.selectedButton];
   },
 
-  prompt: function(title, text, value, checkMsg, checkState) {
+  prompt(title, text, value, checkMsg, checkState) {
     let rv = this._browserElementChild.showModalPrompt(
       this._win,
       { promptType: "prompt",
-        title: title,
+        title,
         message: text,
         initialValue: value.value,
         returnValue: null });
 
     value.value = rv;
 
     // nsIPrompt::Prompt returns true if the user pressed "OK" at the prompt,
     // and false if the user pressed "Cancel".
     //
     // BrowserElementChild returns null for "Cancel" and returns the string the
     // user entered otherwise.
     return rv !== null;
   },
 
-  promptUsernameAndPassword: function(title, text, username, password, checkMsg, checkState) {
+  promptUsernameAndPassword(title, text, username, password, checkMsg, checkState) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
-  promptPassword: function(title, text, password, checkMsg, checkState) {
+  promptPassword(title, text, password, checkMsg, checkState) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
-  select: function(title, text, aCount, aSelectList, aOutSelection) {
+  select(title, text, aCount, aSelectList, aOutSelection) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
-  _buildConfirmExButtonProperties: function(buttonFlags, button0Title,
+  _buildConfirmExButtonProperties(buttonFlags, button0Title,
                                             button1Title, button2Title) {
     let r = {
       defaultButton: -1,
       buttons: [],
       // This map is for translating array index to the button number that
       // is recognized by Gecko. This shouldn't be exposed to embedder.
-      indexToButtonNumberMap: []
+      indexToButtonNumberMap: [],
     };
 
-    let defaultButton = 0;  // Default to Button 0.
+    let defaultButton = 0; // Default to Button 0.
     if (buttonFlags & Ci.nsIPrompt.BUTTON_POS_1_DEFAULT) {
       defaultButton = 1;
     } else if (buttonFlags & Ci.nsIPrompt.BUTTON_POS_2_DEFAULT) {
       defaultButton = 2;
     }
 
     // Properties of each button.
     let buttonPositions = [
       Ci.nsIPrompt.BUTTON_POS_0,
       Ci.nsIPrompt.BUTTON_POS_1,
-      Ci.nsIPrompt.BUTTON_POS_2
+      Ci.nsIPrompt.BUTTON_POS_2,
     ];
 
     function buildButton(buttonTitle, buttonNumber) {
       let ret = {};
       let buttonPosition = buttonPositions[buttonNumber];
-      let mask = 0xff * buttonPosition;  // 8 bit mask
+      let mask = 0xff * buttonPosition; // 8 bit mask
       let titleType = (buttonFlags & mask) / buttonPosition;
 
-      ret.messageType = 'builtin';
-      switch(titleType) {
+      ret.messageType = "builtin";
+      switch (titleType) {
       case Ci.nsIPrompt.BUTTON_TITLE_OK:
-        ret.message = 'ok';
+        ret.message = "ok";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_CANCEL:
-        ret.message = 'cancel';
+        ret.message = "cancel";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_YES:
-        ret.message = 'yes';
+        ret.message = "yes";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_NO:
-        ret.message = 'no';
+        ret.message = "no";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_SAVE:
-        ret.message = 'save';
+        ret.message = "save";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_DONT_SAVE:
-        ret.message = 'dontsave';
+        ret.message = "dontsave";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_REVERT:
-        ret.message = 'revert';
+        ret.message = "revert";
         break;
       case Ci.nsIPrompt.BUTTON_TITLE_IS_STRING:
         ret.message = buttonTitle;
-        ret.messageType = 'custom';
+        ret.messageType = "custom";
         break;
       default:
         // This button is not shown.
         return;
       }
 
       // If this is the default button, set r.defaultButton to
       // the index of this button in the array. This value is going to be
@@ -237,70 +237,68 @@ BrowserElementAuthPrompt.prototype = {
 
     if (!browserElementParent) {
       debug("Failed to load browser element parent.");
       throw Cr.NS_ERROR_FAILURE;
     }
 
     let consumer = {
       QueryInterface: ChromeUtils.generateQI([Ci.nsICancelable]),
-      callback: callback,
-      context: context,
-      cancel: function() {
+      callback,
+      context,
+      cancel() {
         this.callback.onAuthCancelled(this.context, false);
         this.callback = null;
         this.context = null;
-      }
+      },
     };
 
     let [hostname, httpRealm] = this._getAuthTarget(channel, authInfo);
     let hashKey = level + "|" + hostname + "|" + httpRealm;
     let asyncPrompt = this._asyncPrompts[hashKey];
     if (asyncPrompt) {
       asyncPrompt.consumers.push(consumer);
       return consumer;
     }
 
     asyncPrompt = {
       consumers: [consumer],
-      channel: channel,
-      authInfo: authInfo,
-      level: level,
+      channel,
+      authInfo,
+      level,
       inProgress: false,
-      browserElementParent: browserElementParent
+      browserElementParent,
     };
 
     this._asyncPrompts[hashKey] = asyncPrompt;
     this._doAsyncPrompt();
     return consumer;
   },
 
   // Utilities for nsIAuthPrompt2 ----------------
 
   _asyncPrompts: {},
   _asyncPromptInProgress: new WeakMap(),
-  _doAsyncPrompt: function() {
+  _doAsyncPrompt() {
     // Find the key of a prompt whose browser element parent does not have
     // async prompt in progress.
     let hashKey = null;
     for (let key in this._asyncPrompts) {
       let prompt = this._asyncPrompts[key];
       if (!this._asyncPromptInProgress.get(prompt.browserElementParent)) {
         hashKey = key;
         break;
       }
     }
 
     // Didn't find an available prompt, so just return.
     if (!hashKey)
       return;
 
     let prompt = this._asyncPrompts[hashKey];
-    let [hostname, httpRealm] = this._getAuthTarget(prompt.channel,
-                                                    prompt.authInfo);
 
     this._asyncPromptInProgress.set(prompt.browserElementParent, true);
     prompt.inProgress = true;
 
     let self = this;
     let callback = function(ok, username, password) {
       debug("Async auth callback is called, ok = " +
             ok + ", username = " + username);
@@ -351,47 +349,47 @@ BrowserElementAuthPrompt.prototype = {
         } catch (e) { /* Throw away exceptions caused by callback */ }
       }
 
       // Process the next prompt, if one is pending.
       self._doAsyncPrompt();
     };
 
     let runnable = {
-      run: function() {
+      run() {
         // Call promptAuth of browserElementParent, to show the prompt.
         prompt.browserElementParent.promptAuth(
           self._createAuthDetail(prompt.channel, prompt.authInfo),
           callback);
-      }
-    }
+      },
+    };
 
     Services.tm.dispatchToMainThread(runnable);
   },
 
-  _getFrameFromChannel: function(channel) {
+  _getFrameFromChannel(channel) {
     let loadContext = channel.notificationCallbacks.getInterface(Ci.nsILoadContext);
     return loadContext.topFrameElement;
   },
 
-  _createAuthDetail: function(channel, authInfo) {
+  _createAuthDetail(channel, authInfo) {
     let [hostname, httpRealm] = this._getAuthTarget(channel, authInfo);
     return {
       host:             hostname,
       path:             channel.URI.pathQueryRef,
       realm:            httpRealm,
       username:         authInfo.username,
       isProxy:          !!(authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY),
-      isOnlyPassword:   !!(authInfo.flags & Ci.nsIAuthInformation.ONLY_PASSWORD)
+      isOnlyPassword:   !!(authInfo.flags & Ci.nsIAuthInformation.ONLY_PASSWORD),
     };
   },
 
   // The code is taken from nsLoginManagerPrompter.js, with slight
   // modification for parameter name consistency here.
-  _getAuthTarget : function (channel, authInfo) {
+  _getAuthTarget(channel, authInfo) {
     let hostname, realm;
 
     // If our proxy is demanding authentication, don't use the
     // channel's actual destination.
     if (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) {
       if (!(channel instanceof Ci.nsIProxiedChannel))
         throw new Error("proxy auth needs nsIProxiedChannel");
 
@@ -423,91 +421,88 @@ BrowserElementAuthPrompt.prototype = {
       realm = hostname;
 
     return [hostname, realm];
   },
 
   /**
    * Strip out things like userPass and path for display.
    */
-  _getFormattedHostname : function(uri) {
+  _getFormattedHostname(uri) {
     return uri.scheme + "://" + uri.hostPort;
   },
 };
 
 
 function AuthPromptWrapper(oldImpl, browserElementImpl) {
   this._oldImpl = oldImpl;
   this._browserElementImpl = browserElementImpl;
 }
 
 AuthPromptWrapper.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAuthPrompt2]),
-  promptAuth: function(channel, level, authInfo) {
+  promptAuth(channel, level, authInfo) {
     if (this._canGetParentElement(channel)) {
       return this._browserElementImpl.promptAuth(channel, level, authInfo);
-    } else {
+    }
       return this._oldImpl.promptAuth(channel, level, authInfo);
-    }
   },
 
-  asyncPromptAuth: function(channel, callback, context, level, authInfo) {
+  asyncPromptAuth(channel, callback, context, level, authInfo) {
     if (this._canGetParentElement(channel)) {
       return this._browserElementImpl.asyncPromptAuth(channel, callback, context, level, authInfo);
-    } else {
+    }
       return this._oldImpl.asyncPromptAuth(channel, callback, context, level, authInfo);
-    }
   },
 
-  _canGetParentElement: function(channel) {
+  _canGetParentElement(channel) {
     try {
       let context = channel.notificationCallbacks.getInterface(Ci.nsILoadContext);
       let frame = context.topFrameElement;
       if (!frame) {
         // This function returns a boolean value
         return !!context.nestedFrameId;
       }
 
       if (!BrowserElementPromptService.getBrowserElementParentForFrame(frame))
         return false;
 
       return true;
     } catch (e) {
       return false;
     }
-  }
+  },
 };
 
 function BrowserElementPromptFactory(toWrap) {
   this._wrapped = toWrap;
 }
 
 BrowserElementPromptFactory.prototype = {
   classID: Components.ID("{24f3d0cf-e417-4b85-9017-c9ecf8bb1299}"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIPromptFactory]),
 
-  _mayUseNativePrompt: function() {
+  _mayUseNativePrompt() {
     try {
       return Services.prefs.getBoolPref("browser.prompt.allowNative");
     } catch (e) {
       // This properity is default to true.
       return true;
     }
   },
 
-  _getNativePromptIfAllowed: function(win, iid, err) {
+  _getNativePromptIfAllowed(win, iid, err) {
     if (this._mayUseNativePrompt())
       return this._wrapped.getPrompt(win, iid);
-    else {
+
       // Not allowed, throw an exception.
       throw err;
-    }
   },
 
-  getPrompt: function(win, iid) {
+  getPrompt(win, iid) {
     // It is possible for some object to get a prompt without passing
     // valid reference of window, like nsNSSComponent. In such case, we
     // should just fall back to the native prompt service
     if (!win)
       return this._getNativePromptIfAllowed(win, iid, Cr.NS_ERROR_INVALID_ARG);
 
     if (iid.number != Ci.nsIPrompt.number &&
         iid.number != Ci.nsIAuthPrompt2.number) {
@@ -537,140 +532,131 @@ BrowserElementPromptFactory.prototype = 
       // it doesn't mean that we should fallback. It is possible that we can
       // get the BrowserElementParent from nsIChannel that passed to
       // functions of nsIAuthPrompt2.
       if (this._mayUseNativePrompt()) {
         return new AuthPromptWrapper(
             this._wrapped.getPrompt(win, iid),
             new BrowserElementAuthPrompt().QueryInterface(iid))
           .QueryInterface(iid);
-      } else {
+      }
         // Falling back is not allowed, so we don't need wrap the
         // BrowserElementPrompt.
         return new BrowserElementAuthPrompt().QueryInterface(iid);
-      }
     }
 
     if (!browserElementChild) {
       debug("We can't find a browserElementChild for " +
             win + ", " + win.location);
       return this._getNativePromptIfAllowed(win, iid, Cr.NS_ERROR_FAILURE);
     }
 
     debug("Returning wrapped getPrompt for " + win);
     return new BrowserElementPrompt(win, browserElementChild)
                                    .QueryInterface(iid);
-  }
+  },
 };
 
 var BrowserElementPromptService = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference]),
 
   _initialized: false,
 
-  _init: function() {
+  _init() {
     if (this._initialized) {
       return;
     }
 
     // If the pref is disabled, do nothing except wait for the pref to change.
     if (!this._browserFramesPrefEnabled()) {
-      var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
-      prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
+      Services.prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
       return;
     }
 
     this._initialized = true;
     this._browserElementParentMap = new WeakMap();
 
-    var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
-    os.addObserver(this, "outer-window-destroyed", /* ownsWeak = */ true);
+    Services.obs.addObserver(this, "outer-window-destroyed", /* ownsWeak = */ true);
 
     // Wrap the existing @mozilla.org/prompter;1 implementation.
     var contractID = "@mozilla.org/prompter;1";
     var oldCID = Cm.contractIDToCID(contractID);
     var newCID = BrowserElementPromptFactory.prototype.classID;
     var oldFactory = Cm.getClassObject(Cc[contractID], Ci.nsIFactory);
 
     if (oldCID == newCID) {
       debug("WARNING: Wrapped prompt factory is already installed!");
       return;
     }
 
     var oldInstance = oldFactory.createInstance(null, Ci.nsIPromptFactory);
     var newInstance = new BrowserElementPromptFactory(oldInstance);
 
     var newFactory = {
-      createInstance: function(outer, iid) {
+      createInstance(outer, iid) {
         if (outer != null) {
           throw Cr.NS_ERROR_NO_AGGREGATION;
         }
         return newInstance.QueryInterface(iid);
-      }
+      },
     };
     Cm.registerFactory(newCID,
                        "BrowserElementPromptService's prompter;1 wrapper",
                        contractID, newFactory);
 
     debug("Done installing new prompt factory.");
   },
 
-  _getOuterWindowID: function(win) {
+  _getOuterWindowID(win) {
     return win.windowUtils.outerWindowID;
   },
 
   _browserElementChildMap: {},
-  mapWindowToBrowserElementChild: function(win, browserElementChild) {
+  mapWindowToBrowserElementChild(win, browserElementChild) {
     this._browserElementChildMap[this._getOuterWindowID(win)] = browserElementChild;
   },
-  unmapWindowToBrowserElementChild: function(win) {
+  unmapWindowToBrowserElementChild(win) {
     delete this._browserElementChildMap[this._getOuterWindowID(win)];
   },
 
-  getBrowserElementChildForWindow: function(win) {
+  getBrowserElementChildForWindow(win) {
     // We only have a mapping for <iframe mozbrowser>s, not their inner
     // <iframes>, so we look up win.top below.  window.top (when called from
     // script) respects <iframe mozbrowser> boundaries.
     return this._browserElementChildMap[this._getOuterWindowID(win.top)];
   },
 
-  mapFrameToBrowserElementParent: function(frame, browserElementParent) {
+  mapFrameToBrowserElementParent(frame, browserElementParent) {
     this._browserElementParentMap.set(frame, browserElementParent);
   },
 
-  getBrowserElementParentForFrame: function(frame) {
+  getBrowserElementParentForFrame(frame) {
     return this._browserElementParentMap.get(frame);
   },
 
-  _observeOuterWindowDestroyed: function(outerWindowID) {
+  _observeOuterWindowDestroyed(outerWindowID) {
     let id = outerWindowID.QueryInterface(Ci.nsISupportsPRUint64).data;
     debug("observeOuterWindowDestroyed " + id);
     delete this._browserElementChildMap[outerWindowID.data];
   },
 
-  _browserFramesPrefEnabled: function() {
-    var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
-    try {
-      return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
-    }
-    catch(e) {
-      return false;
-    }
+  _browserFramesPrefEnabled() {
+    return Services.prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF, false);
   },
 
-  observe: function(subject, topic, data) {
-    switch(topic) {
+  observe(subject, topic, data) {
+    switch (topic) {
     case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
       if (data == BROWSER_FRAMES_ENABLED_PREF) {
         this._init();
       }
       break;
     case "outer-window-destroyed":
       this._observeOuterWindowDestroyed(subject);
       break;
     default:
       debug("Observed unexpected topic " + topic);
     }
-  }
+  },
 };
 
 BrowserElementPromptService._init();
--- a/dom/browser-element/mochitest/async.js
+++ b/dom/browser-element/mochitest/async.js
@@ -34,19 +34,19 @@
   function async(func, self) {
     return function asyncFunction() {
       const functionArgs = Array.from(arguments);
       return new Promise(function(resolve, reject) {
         var gen;
         if (typeof func !== "function") {
           reject(new TypeError("Expected a Function."));
         }
-        //not a generator, wrap it.
+        // not a generator, wrap it.
         if (func.constructor.name !== "GeneratorFunction") {
-          gen = (function*() {
+          gen = (function* () {
             return func.apply(self, functionArgs);
           }());
         } else {
           gen = func.apply(self, functionArgs);
         }
         try {
           step(gen.next(undefined));
         } catch (err) {
@@ -64,15 +64,15 @@
                 try {
                   step(gen.throw(error));
                 } catch (err) {
                   throw err;
                 }
               }
             ).catch(err => reject(err));
           }
-          step(gen.next(value));
+          return step(gen.next(value));
         }
       });
     };
   }
   exports.async = async;
 }(this || self));
--- a/dom/browser-element/mochitest/browserElementTestHelpers.js
+++ b/dom/browser-element/mochitest/browserElementTestHelpers.js
@@ -4,129 +4,128 @@
 // Helpers for managing the browser frame preferences.
 "use strict";
 
 function _getPath() {
   if (window.location.protocol == "chrome:") {
     return "/chrome/dom/browser-element/mochitest";
   }
   return window.location.pathname
-               .substring(0, window.location.pathname.lastIndexOf('/'))
+               .substring(0, window.location.pathname.lastIndexOf("/"))
                .replace("/priority", "");
 }
 
 const browserElementTestHelpers = {
-  _getBoolPref: function(pref) {
+  _getBoolPref(pref) {
     try {
       return SpecialPowers.getBoolPref(pref);
-    }
-    catch (e) {
+    } catch (e) {
       return undefined;
     }
   },
 
-  _setPref: function(pref, value) {
+  _setPref(pref, value) {
     this.lockTestReady();
     if (value !== undefined && value !== null) {
-      SpecialPowers.pushPrefEnv({'set': [[pref, value]]}, this.unlockTestReady.bind(this));
+      SpecialPowers.pushPrefEnv({"set": [[pref, value]]}, this.unlockTestReady.bind(this));
     } else {
-      SpecialPowers.pushPrefEnv({'clear': [[pref]]}, this.unlockTestReady.bind(this));
+      SpecialPowers.pushPrefEnv({"clear": [[pref]]}, this.unlockTestReady.bind(this));
     }
   },
 
-  _setPrefs: function() {
+  _setPrefs() {
     this.lockTestReady();
-    SpecialPowers.pushPrefEnv({'set': Array.slice(arguments)}, this.unlockTestReady.bind(this));
+    SpecialPowers.pushPrefEnv({"set": Array.slice(arguments)}, this.unlockTestReady.bind(this));
   },
 
   _testReadyLockCount: 0,
   _firedTestReady: false,
-  lockTestReady: function() {
+  lockTestReady() {
     this._testReadyLockCount++;
   },
 
-  unlockTestReady: function() {
+  unlockTestReady() {
     this._testReadyLockCount--;
     if (this._testReadyLockCount == 0 && !this._firedTestReady) {
       this._firedTestReady = true;
       dispatchEvent(new Event("testready"));
     }
   },
 
-  enableProcessPriorityManager: function() {
+  enableProcessPriorityManager() {
     this._setPrefs(
-      ['dom.ipc.processPriorityManager.testMode', true],
-      ['dom.ipc.processPriorityManager.enabled', true]
+      ["dom.ipc.processPriorityManager.testMode", true],
+      ["dom.ipc.processPriorityManager.enabled", true]
     );
   },
 
-  setClipboardPlainTextOnlyPref: function(value) {
-    this._setPref('clipboard.plainTextOnly', value);
+  setClipboardPlainTextOnlyPref(value) {
+    this._setPref("clipboard.plainTextOnly", value);
   },
 
-  setEnabledPref: function(value) {
-    this._setPrefs(['dom.mozBrowserFramesEnabled', value],
-                   ['network.disable.ipc.security', value]);
+  setEnabledPref(value) {
+    this._setPrefs(["dom.mozBrowserFramesEnabled", value],
+                   ["network.disable.ipc.security", value]);
   },
 
-  setupAccessibleCaretPref: function() {
-    this._setPref('layout.accessiblecaret.enabled', true);
+  setupAccessibleCaretPref() {
+    this._setPref("layout.accessiblecaret.enabled", true);
     // Disable hide carets for mouse input for select-all tests so that we can
     // get mozbrowsercaretstatechanged events.
-    this._setPref('layout.accessiblecaret.hide_carets_for_mouse_input', false);
+    this._setPref("layout.accessiblecaret.hide_carets_for_mouse_input", false);
   },
 
-  getOOPByDefaultPref: function() {
+  getOOPByDefaultPref() {
     return this._getBoolPref("dom.ipc.browser_frames.oop_by_default");
   },
 
-  addPermission: function() {
+  addPermission() {
     this.lockTestReady();
     SpecialPowers.pushPermissions(
-      [{'type': "browser", 'allow': 1, 'context': document}],
+      [{"type": "browser", "allow": 1, "context": document}],
       this.unlockTestReady.bind(this));
   },
 
-  allowTopLevelDataURINavigation: function() {
+  allowTopLevelDataURINavigation() {
     this._setPref("security.data_uri.block_toplevel_data_uri_navigations", false);
   },
 
   _observers: [],
 
   // This function is a wrapper which lets you register an observer to one of
   // the process priority manager's test-only topics.  observerFn should be a
   // function which takes (subject, topic, data).
   //
   // We'll clean up any observers you add at the end of the test.
-  addProcessPriorityObserver: function(processPriorityTopic, observerFn) {
+  addProcessPriorityObserver(processPriorityTopic, observerFn) {
     var topic = "process-priority-manager:TEST-ONLY:" + processPriorityTopic;
 
     // SpecialPowers appears to require that the observer be an object, not a
     // function.
     var observer = {
-      observe: observerFn
+      observe: observerFn,
     };
 
     SpecialPowers.addObserver(observer, topic);
     this._observers.push([observer, topic]);
   },
 
-  cleanUp: function() {
+  cleanUp() {
     for (var i = 0; i < this._observers.length; i++) {
       SpecialPowers.removeObserver(this._observers[i][0],
                                    this._observers[i][1]);
     }
   },
 
   // Some basically-empty pages from different domains you can load.
-  'emptyPage1': 'http://example.com' + _getPath() + '/file_empty.html',
-  'fileEmptyPage1': 'file_empty.html',
-  'emptyPage2': 'http://example.org' + _getPath() + '/file_empty.html',
-  'emptyPage3': 'http://test1.example.org' + _getPath() + '/file_empty.html',
-  'focusPage': 'http://example.org' + _getPath() + '/file_focus.html',
+  "emptyPage1": "http://example.com" + _getPath() + "/file_empty.html",
+  "fileEmptyPage1": "file_empty.html",
+  "emptyPage2": "http://example.org" + _getPath() + "/file_empty.html",
+  "emptyPage3": "http://test1.example.org" + _getPath() + "/file_empty.html",
+  "focusPage": "http://example.org" + _getPath() + "/file_focus.html",
 };
 
 // Returns a promise which is resolved when a subprocess is created.  The
 // argument to resolve() is the childID of the subprocess.
 function expectProcessCreated(/* optional */ initialPriority) {
   return new Promise(function(resolve, reject) {
     var observed = false;
     browserElementTestHelpers.addProcessPriorityObserver(
@@ -135,17 +134,17 @@ function expectProcessCreated(/* optiona
         // Don't run this observer twice, so we don't ok(true) twice.  (It's fine
         // to resolve a promise twice; the second resolve() call does nothing.)
         if (observed) {
           return;
         }
         observed = true;
 
         var childID = parseInt(data);
-        ok(true, 'Got new process, id=' + childID);
+        ok(true, "Got new process, id=" + childID);
         if (initialPriority) {
           expectPriorityChange(childID, initialPriority).then(function() {
             resolve(childID);
           });
         } else {
           resolve(childID);
         }
       }
@@ -154,65 +153,65 @@ function expectProcessCreated(/* optiona
 }
 
 // Just like expectProcessCreated(), except we'll call ok(false) if a second
 // process is created.
 function expectOnlyOneProcessCreated(/* optional */ initialPriority) {
   var p = expectProcessCreated(initialPriority);
   p.then(function() {
     expectProcessCreated().then(function(childID) {
-      ok(false, 'Got unexpected process creation, childID=' + childID);
+      ok(false, "Got unexpected process creation, childID=" + childID);
     });
   });
   return p;
 }
 
 // Returns a promise which is resolved or rejected the next time the process
 // childID changes its priority. We resolve if the priority matches
 // expectedPriority, and we reject otherwise.
 
 function expectPriorityChange(childID, expectedPriority) {
   return new Promise(function(resolve, reject) {
     var observed = false;
     browserElementTestHelpers.addProcessPriorityObserver(
-      'process-priority-set',
+      "process-priority-set",
       function(subject, topic, data) {
         if (observed) {
           return;
         }
 
         var [id, priority] = data.split(":");
         if (id != childID) {
           return;
         }
 
         // Make sure we run the is() calls in this observer only once, otherwise
         // we'll expect /every/ priority change to match expectedPriority.
         observed = true;
 
         is(priority, expectedPriority,
-           'Expected priority of childID ' + childID +
-           ' to change to ' + expectedPriority);
+           "Expected priority of childID " + childID +
+           " to change to " + expectedPriority);
 
         if (priority == expectedPriority) {
           resolve();
         } else {
           reject();
         }
       }
     );
   });
 }
 
 // Returns a promise which is resolved the first time the given iframe fires
 // the mozbrowser##eventName event.
 function expectMozbrowserEvent(iframe, eventName) {
   return new Promise(function(resolve, reject) {
-    iframe.addEventListener('mozbrowser' + eventName, function handler(e) {
-      iframe.removeEventListener('mozbrowser' + eventName, handler);
+    iframe.addEventListener("mozbrowser" + eventName, function handler(e) {
+      iframe.removeEventListener("mozbrowser" + eventName, handler);
       resolve(e);
     });
   });
 }
 
 // Set some prefs:
 //
 //  * browser.pagethumbnails.capturing_disabled: true
@@ -244,28 +243,28 @@ function expectMozbrowserEvent(iframe, e
 //    it to false.
 //
 //  * security.mixed_content.block_active_content: false
 //
 //    Disable mixed active content blocking, so that tests can confirm that mixed
 //    content results in a broken security state.
 
 (function() {
-  var oop = !location.pathname.includes('_inproc_');
+  var oop = !location.pathname.includes("_inproc_");
 
   browserElementTestHelpers.lockTestReady();
   SpecialPowers.setBoolPref("network.disable.ipc.security", true);
   SpecialPowers.pushPrefEnv({set: [["browser.pagethumbnails.capturing_disabled", true],
                                    ["dom.ipc.browser_frames.oop_by_default", oop],
                                    ["dom.ipc.tabs.disabled", false],
                                    ["security.mixed_content.block_active_content", false]]},
                             browserElementTestHelpers.unlockTestReady.bind(browserElementTestHelpers));
 })();
 
-addEventListener('unload', function() {
+addEventListener("unload", function() {
   browserElementTestHelpers.cleanUp();
 });
 
 // Wait for the load event before unlocking the test-ready event.
 browserElementTestHelpers.lockTestReady();
-addEventListener('load', function() {
+addEventListener("load", function() {
   SimpleTest.executeSoon(browserElementTestHelpers.unlockTestReady.bind(browserElementTestHelpers));
 });
--- a/dom/browser-element/mochitest/browserElement_Alert.js
+++ b/dom/browser-element/mochitest/browserElement_Alert.js
@@ -1,51 +1,52 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that alert works.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 var numPendingChildTests = 0;
 var iframe;
 var mm;
 
 function runTest() {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe);
 
   mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-  mm.addMessageListener('test-success', function(msg) {
+  mm.addMessageListener("test-success", function(msg) {
     numPendingChildTests--;
     ok(true, SpecialPowers.wrap(msg).json);
   });
-  mm.addMessageListener('test-fail', function(msg) {
+  mm.addMessageListener("test-fail", function(msg) {
     numPendingChildTests--;
     ok(false, SpecialPowers.wrap(msg).json);
   });
 
   // Wait for the initial load to finish, then navigate the page, then wait
   // for that load to finish, then start test1.
-  iframe.addEventListener('mozbrowserloadend', function() {
+  iframe.addEventListener("mozbrowserloadend", function() {
     iframe.src = browserElementTestHelpers.emptyPage1;
 
-    iframe.addEventListener('mozbrowserloadend', function() {
+    iframe.addEventListener("mozbrowserloadend", function() {
       SimpleTest.executeSoon(test1);
     }, {once: true});
   }, {once: true});
-
 }
 
 function test1() {
-  iframe.addEventListener('mozbrowsershowmodalprompt', test2);
+  iframe.addEventListener("mozbrowsershowmodalprompt", test2);
 
   // Do window.alert within the iframe, then modify the global |testState|
   // after the alert.
   var script = 'data:,\
     this.testState = 0; \
     content.alert("Hello, world!"); \
     this.testState = 1; \
   ';
@@ -54,17 +55,17 @@ function test1() {
 
   // Triggers a mozbrowsershowmodalprompt event, which sends us down to test2.
 }
 
 // test2 is a mozbrowsershowmodalprompt listener.
 function test2(e) {
   iframe.removeEventListener("mozbrowsershowmodalprompt", test2);
 
-  is(e.detail.message, 'Hello, world!');
+  is(e.detail.message, "Hello, world!");
   e.preventDefault(); // cause the alert to block.
 
   SimpleTest.executeSoon(function() { test2a(e); });
 }
 
 function test2a(e) {
   // The iframe should be blocked on the alert call at the moment, so testState
   // should still be 0.
@@ -93,78 +94,78 @@ function test3(e) {
     else { \
       sendAsyncMessage("test-try-again", "2: Wrong testState (for now): " + this.testState); \
     }';
 
   // Urgh.  e.unblock() didn't necessarily unblock us immediately, so we have
   // to spin and wait.
   function onTryAgain() {
     SimpleTest.executeSoon(function() {
-      //dump('onTryAgain\n');
+      // dump('onTryAgain\n');
       mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
     });
   }
 
-  mm.addMessageListener('test-try-again', onTryAgain);
+  mm.addMessageListener("test-try-again", onTryAgain);
   numPendingChildTests++;
 
   onTryAgain();
   waitForPendingTests(function() {
-    mm.removeMessageListener('test-try-again', onTryAgain);
+    mm.removeMessageListener("test-try-again", onTryAgain);
     test4();
   });
 }
 
 function test4() {
   // Navigate the iframe while an alert is pending.  This shouldn't screw
   // things up.
 
   iframe.addEventListener("mozbrowsershowmodalprompt", test5);
 
   var script = 'data:,content.alert("test4");';
   mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
 }
 
 // test4 is a mozbrowsershowmodalprompt listener.
 function test5(e) {
-  iframe.removeEventListener('mozbrowsershowmodalprompt', test5);
+  iframe.removeEventListener("mozbrowsershowmodalprompt", test5);
 
-  is(e.detail.message, 'test4');
+  is(e.detail.message, "test4");
   e.preventDefault(); // cause the page to block.
 
   SimpleTest.executeSoon(test5a);
 }
 
 function test5a() {
-  iframe.addEventListener('mozbrowserloadend', test5b);
+  iframe.addEventListener("mozbrowserloadend", test5b);
   iframe.src = browserElementTestHelpers.emptyPage2;
 }
 
 function test5b() {
-  iframe.removeEventListener('mozbrowserloadend', test5b);
+  iframe.removeEventListener("mozbrowserloadend", test5b);
   SimpleTest.executeSoon(test6);
 }
 
 // Test nested alerts
 var promptBlockers = [];
 function test6() {
   iframe.addEventListener("mozbrowsershowmodalprompt", test6a);
 
-  var script = 'data:,\
+  var script = "data:,\
     this.testState = 0; \
     content.alert(1); \
     this.testState = 3; \
-  ';
+  ";
   mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
 }
 
 function test6a(e) {
   iframe.removeEventListener("mozbrowsershowmodalprompt", test6a);
 
-  is(e.detail.message, '1');
+  is(e.detail.message, "1");
   e.preventDefault(); // cause the alert to block.
   promptBlockers.push(e);
 
   SimpleTest.executeSoon(test6b);
 }
 
 function test6b() {
   var script = 'data:,\
@@ -178,28 +179,28 @@ function test6b() {
   numPendingChildTests++;
 
   waitForPendingTests(test6c);
 }
 
 function test6c() {
   iframe.addEventListener("mozbrowsershowmodalprompt", test6d);
 
-  var script = 'data:,\
+  var script = "data:,\
     this.testState = 1; \
     content.alert(2); \
     this.testState = 2; \
-  ';
+  ";
   mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
 }
 
 function test6d(e) {
   iframe.removeEventListener("mozbrowsershowmodalprompt", test6d);
 
-  is(e.detail.message, '2');
+  is(e.detail.message, "2");
   e.preventDefault(); // cause the alert to block.
   promptBlockers.push(e);
 
   SimpleTest.executeSoon(test6e);
 }
 
 function test6e() {
   var script = 'data:,\
@@ -227,27 +228,27 @@ function test6f() {
     else { \
       sendAsyncMessage("test-try-again", "3: Wrong testState (for now): " + this.testState); \
     }';
 
   // Urgh.  e.unblock() didn't necessarily unblock us immediately, so we have
   // to spin and wait.
   function onTryAgain() {
     SimpleTest.executeSoon(function() {
-      //dump('onTryAgain\n');
+      // dump('onTryAgain\n');
       mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
     });
   }
 
-  mm.addMessageListener('test-try-again', onTryAgain);
+  mm.addMessageListener("test-try-again", onTryAgain);
   numPendingChildTests++;
 
   onTryAgain();
   waitForPendingTests(function() {
-    mm.removeMessageListener('test-try-again', onTryAgain);
+    mm.removeMessageListener("test-try-again", onTryAgain);
     test6g();
   });
 }
 
 function test6g() {
   var e = promptBlockers.pop();
   // Now unblock the iframe and check that the script completed.
   e.detail.unblock();
@@ -259,27 +260,27 @@ function test6g() {
     else { \
       sendAsyncMessage("test-try-again", "4: Wrong testState (for now): " + this.testState); \
     }';
 
   // Urgh.  e.unblock() didn't necessarily unblock us immediately, so we have
   // to spin and wait.
   function onTryAgain() {
     SimpleTest.executeSoon(function() {
-      //dump('onTryAgain\n');
+      // dump('onTryAgain\n');
       mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
     });
   }
 
-  mm.addMessageListener('test-try-again', onTryAgain);
+  mm.addMessageListener("test-try-again", onTryAgain);
   numPendingChildTests++;
 
   onTryAgain();
   waitForPendingTests(function() {
-    mm.removeMessageListener('test-try-again', onTryAgain);
+    mm.removeMessageListener("test-try-again", onTryAgain);
     test6h();
   });
 }
 
 function test6h() {
   SimpleTest.finish();
 }
 
@@ -294,9 +295,9 @@ function waitForPendingTests(next) {
     SimpleTest.executeSoon(function() { waitForPendingTests(next); });
     return;
   }
 
   prevNumPendingTests = null;
   next();
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_AlertInFrame.js
+++ b/dom/browser-element/mochitest/browserElement_AlertInFrame.js
@@ -1,24 +1,26 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that alert works from inside an <iframe> inside an <iframe mozbrowser>.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    is(e.detail.message, 'Hello');
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    is(e.detail.message, "Hello");
     SimpleTest.finish();
   });
 
-  iframe.src = 'file_browserElement_AlertInFrame.html';
+  iframe.src = "file_browserElement_AlertInFrame.html";
   document.body.appendChild(iframe);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_Auth.js
+++ b/dom/browser-element/mochitest/browserElement_Auth.js
@@ -1,244 +1,239 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that auth prompt works.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
-const { NetUtil } = SpecialPowers.Cu.import('resource://gre/modules/NetUtil.jsm');
+const { NetUtil } = SpecialPowers.Cu.import("resource://gre/modules/NetUtil.jsm");
 
 function testFail(msg) {
   ok(false, JSON.stringify(msg));
 }
 
 var iframe;
 
 function runTest() {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe);
 
   // Wait for the initial load to finish, then navigate the page, then start test
   // by loading SJS with http 401 response.
-  iframe.addEventListener('mozbrowserloadend', function() {
-    iframe.addEventListener('mozbrowserusernameandpasswordrequired', testHttpAuthCancel);
+  iframe.addEventListener("mozbrowserloadend", function() {
+    iframe.addEventListener("mozbrowserusernameandpasswordrequired", testHttpAuthCancel);
     SimpleTest.executeSoon(function() {
       // Use absolute path because we need to specify host.
-      iframe.src = 'http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs';
+      iframe.src = "http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
     });
   }, {once: true});
 }
 
 function testHttpAuthCancel(e) {
   iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testHttpAuthCancel);
   // Will cancel authentication, but prompt should not be shown again. Instead,
   // we will be led to fail message
   iframe.addEventListener("mozbrowserusernameandpasswordrequired", testFail);
-  iframe.addEventListener("mozbrowsertitlechange", function(e) {
+  iframe.addEventListener("mozbrowsertitlechange", function(f) {
     iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail);
-    is(e.detail, 'http auth failed', 'expected authentication to fail');
-    iframe.addEventListener('mozbrowserusernameandpasswordrequired', testHttpAuth);
+    is(f.detail, "http auth failed", "expected authentication to fail");
+    iframe.addEventListener("mozbrowserusernameandpasswordrequired", testHttpAuth);
     SimpleTest.executeSoon(function() {
       // Use absolute path because we need to specify host.
-      iframe.src = 'http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs';
+      iframe.src = "http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
     });
   }, {once: true});
 
-  is(e.detail.realm, 'http_realm', 'expected realm matches');
-  is(e.detail.host, 'http://test', 'expected host matches');
+  is(e.detail.realm, "http_realm", "expected realm matches");
+  is(e.detail.host, "http://test", "expected host matches");
   is(e.detail.path,
-     '/tests/dom/browser-element/mochitest/file_http_401_response.sjs',
-     'expected path matches');
+     "/tests/dom/browser-element/mochitest/file_http_401_response.sjs",
+     "expected path matches");
   e.preventDefault();
 
   SimpleTest.executeSoon(function() {
     e.detail.cancel();
   });
 }
 
 function testHttpAuth(e) {
   iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testHttpAuth);
 
   // Will authenticate with correct password, prompt should not be
   // called again.
   iframe.addEventListener("mozbrowserusernameandpasswordrequired", testFail);
-  iframe.addEventListener("mozbrowsertitlechange", function(e) {
+  iframe.addEventListener("mozbrowsertitlechange", function(f) {
     iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail);
-    is(e.detail, 'http auth success', 'expect authentication to succeed');
+    is(f.detail, "http auth success", "expect authentication to succeed");
     SimpleTest.executeSoon(testProxyAuth);
   }, {once: true});
 
-  is(e.detail.realm, 'http_realm', 'expected realm matches');
-  is(e.detail.host, 'http://test', 'expected host matches');
+  is(e.detail.realm, "http_realm", "expected realm matches");
+  is(e.detail.host, "http://test", "expected host matches");
   is(e.detail.path,
-     '/tests/dom/browser-element/mochitest/file_http_401_response.sjs',
-     'expected path matches');
-  is(e.detail.isProxy, false, 'expected isProxy is false');
+     "/tests/dom/browser-element/mochitest/file_http_401_response.sjs",
+     "expected path matches");
+  is(e.detail.isProxy, false, "expected isProxy is false");
   e.preventDefault();
 
   SimpleTest.executeSoon(function() {
     e.detail.authenticate("httpuser", "httppass");
   });
 }
 
-function testProxyAuth(e) {
+function testProxyAuth() {
   // The testingSJS simulates the 407 proxy authentication required response
   // for proxy server, which will trigger the browser element to send prompt
   // event with proxy infomation.
-  var testingSJS = 'http://test/tests/dom/browser-element/mochitest/file_http_407_response.sjs';
+  var testingSJS = "http://test/tests/dom/browser-element/mochitest/file_http_407_response.sjs";
   var mozproxy;
 
   function onUserNameAndPasswordRequired(e) {
     iframe.removeEventListener("mozbrowserusernameandpasswordrequired",
                                onUserNameAndPasswordRequired);
-    iframe.addEventListener("mozbrowsertitlechange", function(e) {
+    iframe.addEventListener("mozbrowsertitlechange", function(event) {
       iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail);
-      is(e.detail, 'http auth success', 'expect authentication to succeed');
+      is(event.detail, "http auth success", "expect authentication to succeed");
       SimpleTest.executeSoon(testAuthJarNoInterfere);
     }, {once: true});
 
-    is(e.detail.realm, 'http_realm', 'expected realm matches');
-    is(e.detail.host, mozproxy, 'expected host matches');
+    is(e.detail.realm, "http_realm", "expected realm matches");
+    is(e.detail.host, mozproxy, "expected host matches");
     is(e.detail.path,
-       '/tests/dom/browser-element/mochitest/file_http_407_response.sjs',
-       'expected path matches');
-    is(e.detail.isProxy, true, 'expected isProxy is true');
+       "/tests/dom/browser-element/mochitest/file_http_407_response.sjs",
+       "expected path matches");
+    is(e.detail.isProxy, true, "expected isProxy is true");
     e.preventDefault();
 
     SimpleTest.executeSoon(function() {
       e.detail.authenticate("proxyuser", "proxypass");
     });
   }
 
   // Resolve proxy information used by the test suite, we need it to validate
   // whether the proxy information delivered with the prompt event is correct.
   var resolveCallback = SpecialPowers.wrapCallbackObject({
-    QueryInterface: function (iid) {
+    // eslint-disable-next-line mozilla/use-chromeutils-generateqi
+    QueryInterface(iid) {
       const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
-
-      if (!interfaces.some( function(v) { return iid.equals(v) } )) {
+      if (!interfaces.some( function(v) { return iid.equals(v); } )) {
         throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
       }
       return this;
     },
 
-    onProxyAvailable: function (req, channel, pi, status) {
-      isnot(pi, null, 'expected proxy information available');
+    onProxyAvailable(req, channel, pi, status) {
+      isnot(pi, null, "expected proxy information available");
       if (pi) {
         mozproxy = "moz-proxy://" + pi.host + ":" + pi.port;
       }
       iframe.addEventListener("mozbrowserusernameandpasswordrequired",
                               onUserNameAndPasswordRequired);
 
       iframe.src = testingSJS;
-    }
+    },
   });
 
   var channel = NetUtil.newChannel({
     uri: testingSJS,
-    loadUsingSystemPrincipal: true
+    loadUsingSystemPrincipal: true,
   });
 
   var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"]
             .getService();
 
   pps.asyncResolve(channel, 0, resolveCallback);
 }
 
 function testAuthJarNoInterfere(e) {
-  var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1']
+  let authMgr = SpecialPowers.Cc["@mozilla.org/network/http-auth-manager;1"]
     .getService(SpecialPowers.Ci.nsIHttpAuthManager);
-  var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
-               .getService(SpecialPowers.Ci.nsIScriptSecurityManager);
-  var ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
-                  .getService(SpecialPowers.Ci.nsIIOService);
+  let secMan = SpecialPowers.Services.scriptSecurityManager;
+  let ioService = SpecialPowers.Services.io;
   var uri = ioService.newURI("http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs");
 
   // Set a bunch of auth data that should not conflict with the correct auth data already
   // stored in the cache.
   var attrs = {appId: 1};
   var principal = secMan.createCodebasePrincipal(uri, attrs);
-  authMgr.setAuthIdentity('http', 'test', -1, 'basic', 'http_realm',
-                          'tests/dom/browser-element/mochitest/file_http_401_response.sjs',
-                          '', 'httpuser', 'wrongpass', false, principal);
+  authMgr.setAuthIdentity("http", "test", -1, "basic", "http_realm",
+                          "tests/dom/browser-element/mochitest/file_http_401_response.sjs",
+                          "", "httpuser", "wrongpass", false, principal);
   attrs = {appId: 1, inIsolatedMozBrowser: true};
   principal = secMan.createCodebasePrincipal(uri, attrs);
-  authMgr.setAuthIdentity('http', 'test', -1, 'basic', 'http_realm',
-                          'tests/dom/browser-element/mochitest/file_http_401_response.sjs',
-                          '', 'httpuser', 'wrongpass', false, principal);
+  authMgr.setAuthIdentity("http", "test", -1, "basic", "http_realm",
+                          "tests/dom/browser-element/mochitest/file_http_401_response.sjs",
+                          "", "httpuser", "wrongpass", false, principal);
   principal = secMan.createCodebasePrincipal(uri, {});
-  authMgr.setAuthIdentity('http', 'test', -1, 'basic', 'http_realm',
-                          'tests/dom/browser-element/mochitest/file_http_401_response.sjs',
-                          '', 'httpuser', 'wrongpass', false, principal);
+  authMgr.setAuthIdentity("http", "test", -1, "basic", "http_realm",
+                          "tests/dom/browser-element/mochitest/file_http_401_response.sjs",
+                          "", "httpuser", "wrongpass", false, principal);
 
   // Will authenticate with correct password, prompt should not be
   // called again.
   iframe.addEventListener("mozbrowserusernameandpasswordrequired", testFail);
-  iframe.addEventListener("mozbrowsertitlechange", function(e) {
+  iframe.addEventListener("mozbrowsertitlechange", function(f) {
     iframe.removeEventListener("mozbrowserusernameandpasswordrequired", testFail);
-    is(e.detail, 'http auth success', 'expected authentication success');
+    is(f.detail, "http auth success", "expected authentication success");
     SimpleTest.executeSoon(testAuthJarInterfere);
   }, {once: true});
 
   // Once more with feeling. Ensure that our new auth data doesn't interfere with this mozbrowser's
   // auth data.
-  iframe.src = 'http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs';
+  iframe.src = "http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
 }
 
 function testAuthJarInterfere(e) {
-  var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1']
+  let authMgr = SpecialPowers.Cc["@mozilla.org/network/http-auth-manager;1"]
     .getService(SpecialPowers.Ci.nsIHttpAuthManager);
-  var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
-               .getService(SpecialPowers.Ci.nsIScriptSecurityManager);
-  var ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
-                  .getService(SpecialPowers.Ci.nsIIOService);
+  let secMan = SpecialPowers.Services.scriptSecurityManager;
+  let ioService = SpecialPowers.Services.io;
   var uri = ioService.newURI("http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs");
 
   // Set some auth data that should overwrite the successful stored details.
   var principal = secMan.createCodebasePrincipal(uri, {inIsolatedMozBrowser: true});
-  authMgr.setAuthIdentity('http', 'test', -1, 'basic', 'http_realm',
-                          'tests/dom/browser-element/mochitest/file_http_401_response.sjs',
-                          '', 'httpuser', 'wrongpass', false, principal);
+  authMgr.setAuthIdentity("http", "test", -1, "basic", "http_realm",
+                          "tests/dom/browser-element/mochitest/file_http_401_response.sjs",
+                          "", "httpuser", "wrongpass", false, principal);
 
   // Will authenticate with correct password, prompt should not be
   // called again.
   var gotusernamepasswordrequired = false;
   function onUserNameAndPasswordRequired() {
       gotusernamepasswordrequired = true;
   }
   iframe.addEventListener("mozbrowserusernameandpasswordrequired",
                           onUserNameAndPasswordRequired);
-  iframe.addEventListener("mozbrowsertitlechange", function(e) {
+  iframe.addEventListener("mozbrowsertitlechange", function(f) {
     iframe.removeEventListener("mozbrowserusernameandpasswordrequired",
                                onUserNameAndPasswordRequired);
     ok(gotusernamepasswordrequired,
        "Should have dispatched mozbrowserusernameandpasswordrequired event");
     testFinish();
   }, {once: true});
 
   // Once more with feeling. Ensure that our new auth data interferes with this mozbrowser's
   // auth data.
-  iframe.src = 'http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs';
+  iframe.src = "http://test/tests/dom/browser-element/mochitest/file_http_401_response.sjs";
 }
 
 function testFinish() {
   // Clear login information stored in password manager.
-  var authMgr = SpecialPowers.Cc['@mozilla.org/network/http-auth-manager;1']
+  let authMgr = SpecialPowers.Cc["@mozilla.org/network/http-auth-manager;1"]
     .getService(SpecialPowers.Ci.nsIHttpAuthManager);
   authMgr.clearAll();
 
-  var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
-    .getService(SpecialPowers.Ci.nsILoginManager);
-  pwmgr.removeAllLogins();
+  SpecialPowers.Services.logins.removeAllLogins();
 
   SimpleTest.finish();
 }
 
-addEventListener('testready', function() {
+addEventListener("testready", function() {
   // Enable http authentiication.
-  SpecialPowers.pushPrefEnv({'set': [['network.auth.non-web-content-triggered-resources-http-auth-allow', true]]}, runTest);
+  SpecialPowers.pushPrefEnv({"set": [["network.auth.non-web-content-triggered-resources-http-auth-allow", true]]}, runTest);
 });
-
--- a/dom/browser-element/mochitest/browserElement_BackForward.js
+++ b/dom/browser-element/mochitest/browserElement_BackForward.js
@@ -1,33 +1,36 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 741755 - Test that canGo{Back,Forward} and go{Forward,Back} work with
 // <iframe mozbrowser>.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 
 var iframe;
 function addOneShotIframeEventListener(event, fn) {
   function wrapper(e) {
     iframe.removeEventListener(event, wrapper);
     fn(e);
-  };
+  }
 
   iframe.addEventListener(event, wrapper);
 }
 
 function runTest() {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  addOneShotIframeEventListener('mozbrowserloadend', function() {
+  addOneShotIframeEventListener("mozbrowserloadend", function() {
     SimpleTest.executeSoon(test2);
   });
 
   iframe.src = browserElementTestHelpers.emptyPage1;
   document.body.appendChild(iframe);
 }
 
 function checkCanGoBackAndForward(canGoBack, canGoForward, nextTest) {
@@ -54,51 +57,51 @@ function checkCanGoBackAndForward(canGoB
   }
 }
 
 function test2() {
   checkCanGoBackAndForward(false, false, test3);
 }
 
 function test3() {
-  addOneShotIframeEventListener('mozbrowserloadend', function() {
+  addOneShotIframeEventListener("mozbrowserloadend", function() {
     checkCanGoBackAndForward(true, false, test4);
   });
 
   SimpleTest.executeSoon(function() {
     iframe.src = browserElementTestHelpers.emptyPage2;
   });
 }
 
 function test4() {
-  addOneShotIframeEventListener('mozbrowserlocationchange', function(e) {
+  addOneShotIframeEventListener("mozbrowserlocationchange", function(e) {
     is(e.detail.url, browserElementTestHelpers.emptyPage3);
     is(e.detail.canGoBack, true);
     is(e.detail.canGoForward, false);
     checkCanGoBackAndForward(true, false, test5);
   });
 
   SimpleTest.executeSoon(function() {
     iframe.src = browserElementTestHelpers.emptyPage3;
   });
 }
 
 function test5() {
-  addOneShotIframeEventListener('mozbrowserlocationchange', function(e) {
+  addOneShotIframeEventListener("mozbrowserlocationchange", function(e) {
     is(e.detail.url, browserElementTestHelpers.emptyPage2);
     is(e.detail.canGoBack, true);
     is(e.detail.canGoForward, true);
     checkCanGoBackAndForward(true, true, test6);
   });
   iframe.goBack();
 }
 
 function test6() {
-  addOneShotIframeEventListener('mozbrowserlocationchange', function(e) {
+  addOneShotIframeEventListener("mozbrowserlocationchange", function(e) {
     is(e.detail.url, browserElementTestHelpers.emptyPage1);
     is(e.detail.canGoBack, false);
     is(e.detail.canGoForward, true);
     checkCanGoBackAndForward(false, true, SimpleTest.finish);
   });
   iframe.goBack();
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js
+++ b/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js
@@ -2,56 +2,57 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 780351 - Test that mozbrowser does /not/ divide the window name namespace.
 // Multiple mozbrowsers inside the same app are like multiple browser tabs;
 // they share a window name namespace.
 
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe1 = document.createElement('iframe');
-  iframe1.setAttribute('mozbrowser', 'true');
+  var iframe1 = document.createElement("iframe");
+  iframe1.setAttribute("mozbrowser", "true");
 
   // Two mozbrowser frames with the same code both do the same
   // window.open("foo", "bar") call.  We should only get one
   // mozbrowseropenwindow event.
 
-  iframe1.addEventListener('mozbrowseropenwindow', function(e) {
+  iframe1.addEventListener("mozbrowseropenwindow", function(e) {
     ok(true, "Got first mozbrowseropenwindow event.");
     document.body.appendChild(e.detail.frameElement);
 
-    e.detail.frameElement.addEventListener('mozbrowserlocationchange', function(e) {
-      if (e.detail.url == "http://example.com/#2") {
+    e.detail.frameElement.addEventListener("mozbrowserlocationchange", function(f) {
+      if (f.detail.url == "http://example.com/#2") {
         ok(true, "Got locationchange to http://example.com/#2");
         SimpleTest.finish();
-      }
-      else {
-        ok(true, "Got locationchange to " + e.detail.url);
+      } else {
+        ok(true, "Got locationchange to " + f.detail.url);
       }
     });
 
     SimpleTest.executeSoon(function() {
-      var iframe2 = document.createElement('iframe');
+      var iframe2 = document.createElement("iframe");
       // Make sure that iframe1 and iframe2 are in the same TabGroup by linking
       // them through opener. Right now this API requires chrome privileges, as
       // it is on MozFrameLoaderOwner.
       SpecialPowers.wrap(iframe2).presetOpenerWindow(iframe1.contentWindow);
-      iframe2.setAttribute('mozbrowser', 'true');
+      iframe2.setAttribute("mozbrowser", "true");
 
-      iframe2.addEventListener('mozbrowseropenwindow', function(e) {
+      iframe2.addEventListener("mozbrowseropenwindow", function(f) {
         ok(false, "Got second mozbrowseropenwindow event.");
       });
 
       document.body.appendChild(iframe2);
-      iframe2.src = 'file_browserElement_BrowserWindowNamespace.html#2';
+      iframe2.src = "file_browserElement_BrowserWindowNamespace.html#2";
     });
   });
 
   document.body.appendChild(iframe1);
-  iframe1.src = 'file_browserElement_BrowserWindowNamespace.html#1';
+  iframe1.src = "file_browserElement_BrowserWindowNamespace.html#1";
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js
+++ b/dom/browser-element/mochitest/browserElement_BrowserWindowResize.js
@@ -1,14 +1,16 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 891763 - Test the mozbrowserresize event
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
   var srcResizeTo = "data:text/html,       \
     <script type='application/javascript'> \
@@ -20,33 +22,33 @@ function runTest() {
     <script type='application/javascript'> \
       window.resizeBy(-100, -100);         \
     <\/script>                             \
   ";
 
   var count = 0;
   function checkSize(iframe) {
     count++;
-    is(iframe.clientWidth,  400, "iframe width does not change");
+    is(iframe.clientWidth, 400, "iframe width does not change");
     is(iframe.clientHeight, 400, "iframe height does not change");
     if (count == 2) {
       SimpleTest.finish();
     }
   }
 
   function testIFrameWithSrc(src) {
-    var iframe = document.createElement('iframe');
-    iframe.setAttribute('mozbrowser', 'true');
+    var iframe = document.createElement("iframe");
+    iframe.setAttribute("mozbrowser", "true");
     iframe.style = "border:none; width:400px; height:400px;";
     iframe.src = src;
-    iframe.addEventListener("mozbrowserresize", function (e) {
-      is(e.detail.width,  300, "Received correct resize event width");
+    iframe.addEventListener("mozbrowserresize", function(e) {
+      is(e.detail.width, 300, "Received correct resize event width");
       is(e.detail.height, 300, "Received correct resize event height");
       SimpleTest.executeSoon(checkSize.bind(undefined, iframe));
     });
     document.body.appendChild(iframe);
   }
 
   testIFrameWithSrc(srcResizeTo);
   testIFrameWithSrc(srcResizeBy);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_Close.js
+++ b/dom/browser-element/mochitest/browserElement_Close.js
@@ -1,25 +1,27 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that window.close() works.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe);
 
   iframe.addEventListener("mozbrowserclose", function(e) {
     ok(true, "got mozbrowserclose event.");
     SimpleTest.finish();
   });
 
-  iframe.src = "data:text/html,<html><body><script>window.close()</scr"+"ipt></body></html>";
+  iframe.src = "data:text/html,<html><body><script>window.close()</script></body></html>";
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_CloseFromOpener.js
+++ b/dom/browser-element/mochitest/browserElement_CloseFromOpener.js
@@ -1,33 +1,35 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 764718 - Test that window.close() works from the opener window.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
     ok(true, "got openwindow event.");
     document.body.appendChild(e.detail.frameElement);
 
-    e.detail.frameElement.addEventListener("mozbrowserclose", function(e) {
+    e.detail.frameElement.addEventListener("mozbrowserclose", function(f) {
       ok(true, "got mozbrowserclose event.");
       SimpleTest.finish();
     });
   });
 
 
   document.body.appendChild(iframe);
 
   // file_browserElement_CloseFromOpener opens a new window and then calls
   // close() on it.
   iframe.src = "file_browserElement_CloseFromOpener.html";
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
+++ b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
@@ -1,352 +1,355 @@
-'use strict';
+"use strict";
+
+/* global browserElementTestHelpers */
+/* eslint-env mozilla/frame-script */
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.setClipboardPlainTextOnlyPref(false);
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
 
-var audioUrl = 'http://mochi.test:8888/tests/dom/browser-element/mochitest/audio.ogg';
-var videoUrl = 'http://mochi.test:8888/tests/dom/browser-element/mochitest/short-video.ogv';
+var audioUrl = "http://mochi.test:8888/tests/dom/browser-element/mochitest/audio.ogg";
+var videoUrl = "http://mochi.test:8888/tests/dom/browser-element/mochitest/short-video.ogv";
 
 function runTests() {
   createIframe(function onIframeLoaded() {
     checkEmptyContextMenu();
   });
 }
 
 function checkEmptyContextMenu() {
-  sendContextMenuTo('body', function onContextMenu(detail) {
-    is(detail.contextmenu, null, 'Body context clicks have no context menu');
+  sendContextMenuTo("body", function onContextMenu(detail) {
+    is(detail.contextmenu, null, "Body context clicks have no context menu");
 
     checkInnerContextMenu();
   });
 }
 
 function checkInnerContextMenu() {
-  sendContextMenuTo('#inner-link', function onContextMenu(detail) {
-    is(detail.systemTargets.length, 1, 'Includes anchor data');
-    is(detail.contextmenu.items.length, 3, 'Inner clicks trigger correct customized menu');
-    is(detail.contextmenu.items[0].label, 'foo', 'Customized menu has a "foo" menu item');
-    is(detail.contextmenu.items[1].label, 'bar', 'Customized menu has a "bar" menu item');
-    is(detail.contextmenu.items[2].id, 'copy-link', '#inner-link has a copy-link menu item');
-    is(detail.contextmenu.customized, true, 'Make sure contextmenu has customized items');
+  sendContextMenuTo("#inner-link", function onContextMenu(detail) {
+    is(detail.systemTargets.length, 1, "Includes anchor data");
+    is(detail.contextmenu.items.length, 3, "Inner clicks trigger correct customized menu");
+    is(detail.contextmenu.items[0].label, "foo", 'Customized menu has a "foo" menu item');
+    is(detail.contextmenu.items[1].label, "bar", 'Customized menu has a "bar" menu item');
+    is(detail.contextmenu.items[2].id, "copy-link", "#inner-link has a copy-link menu item");
+    is(detail.contextmenu.customized, true, "Make sure contextmenu has customized items");
 
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'A', 'Reports correct nodeName');
-    is(target.data.uri, 'foo.html', 'Reports correct uri');
-    is(target.data.text, 'Menu 1', 'Reports correct link text');
+    is(target.nodeName, "A", "Reports correct nodeName");
+    is(target.data.uri, "foo.html", "Reports correct uri");
+    is(target.data.text, "Menu 1", "Reports correct link text");
 
     checkCustomContextMenu();
   });
 }
 
 function checkCustomContextMenu() {
-  sendContextMenuTo('#menu1-trigger', function onContextMenu(detail) {
-    is(detail.contextmenu.items.length, 2, 'trigger custom contextmenu');
+  sendContextMenuTo("#menu1-trigger", function onContextMenu(detail) {
+    is(detail.contextmenu.items.length, 2, "trigger custom contextmenu");
 
     checkNestedContextMenu();
   });
 }
 
 function checkNestedContextMenu() {
-  sendContextMenuTo('#menu2-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu2-trigger", function onContextMenu(detail) {
     var innerMenu = detail.contextmenu.items.filter(function(x) {
-      return x.type === 'menu';
+      return x.type === "menu";
     });
-    is(detail.systemTargets.length, 2, 'Includes two systemTargets');
-    is(detail.systemTargets[0].nodeName, 'IMG', 'Includes "IMG" node');
-    is(detail.systemTargets[0].data.uri, 'example.png', 'Img data has the correct uri');
-    is(detail.systemTargets[1].nodeName, 'A', 'Includes "A" node');
-    is(detail.systemTargets[1].data.uri, 'bar.html', 'Anchor has the correct uri');
-    ok(innerMenu.length > 0, 'Menu contains a nested menu');
+    is(detail.systemTargets.length, 2, "Includes two systemTargets");
+    is(detail.systemTargets[0].nodeName, "IMG", 'Includes "IMG" node');
+    is(detail.systemTargets[0].data.uri, "example.png", "Img data has the correct uri");
+    is(detail.systemTargets[1].nodeName, "A", 'Includes "A" node');
+    is(detail.systemTargets[1].data.uri, "bar.html", "Anchor has the correct uri");
+    ok(innerMenu.length > 0, "Menu contains a nested menu");
 
-    is(detail.contextmenu.items.length, 4, 'We have correct # of menu items')
-    is(detail.contextmenu.customized, true, 'Make sure contextmenu has customized items');
-    is(detail.contextmenu.items[0].label, 'outer', 'Customized menu has an "outer" menu item');
-    is(detail.contextmenu.items[1].label, 'submenu', 'Customized menu has an "submenu" menu item');
-    is(detail.contextmenu.items[2].id, 'copy-link', 'Has a copy-link menu item');
-    is(detail.contextmenu.items[3].id, 'copy-image', 'Has a copy-image menu item');
+    is(detail.contextmenu.items.length, 4, "We have correct # of menu items");
+    is(detail.contextmenu.customized, true, "Make sure contextmenu has customized items");
+    is(detail.contextmenu.items[0].label, "outer", 'Customized menu has an "outer" menu item');
+    is(detail.contextmenu.items[1].label, "submenu", 'Customized menu has an "submenu" menu item');
+    is(detail.contextmenu.items[2].id, "copy-link", "Has a copy-link menu item");
+    is(detail.contextmenu.items[3].id, "copy-image", "Has a copy-image menu item");
     checkPreviousContextMenuHandler();
   });
 }
 
  // Finished testing the data passed to the contextmenu handler,
  // now we start selecting contextmenu items
 function checkPreviousContextMenuHandler() {
   // This is previously triggered contextmenu data, since we have
   // fired subsequent contextmenus this should not be mistaken
   // for a current menuitem
   var detail = previousContextMenuDetail;
   var previousId = detail.contextmenu.items[0].id;
   checkContextMenuCallbackForId(detail, previousId, function onCallbackFired(label) {
-    is(label, null, 'Callback label should be empty since this handler is old');
+    is(label, null, "Callback label should be empty since this handler is old");
 
     checkCurrentContextMenuHandler();
   });
 }
 
 function checkCurrentContextMenuHandler() {
   // This triggers a current menuitem
   var detail = currentContextMenuDetail;
 
   var innerMenu = detail.contextmenu.items.filter(function(x) {
-    return x.type === 'menu';
+    return x.type === "menu";
   });
 
   var currentId = innerMenu[0].items[1].id;
   checkContextMenuCallbackForId(detail, currentId, function onCallbackFired(label) {
-    is(label, 'inner 2', 'Callback label should be set correctly');
+    is(label, "inner 2", "Callback label should be set correctly");
 
     checkAgainCurrentContextMenuHandler();
   });
 }
 
 function checkAgainCurrentContextMenuHandler() {
   // Once an item it selected, subsequent selections are ignored
   var detail = currentContextMenuDetail;
 
   var innerMenu = detail.contextmenu.items.filter(function(x) {
-    return x.type === 'menu';
+    return x.type === "menu";
   });
 
   var currentId = innerMenu[0].items[1].id;
   checkContextMenuCallbackForId(detail, currentId, function onCallbackFired(label) {
-    is(label, null, 'Callback label should be empty since this handler has already been used');
+    is(label, null, "Callback label should be empty since this handler has already been used");
 
     checkCallbackWithPreventDefault();
   });
-};
+}
 
 // Finished testing callbacks if the embedder calls preventDefault() on the
 // mozbrowsercontextmenu event, now we start checking for some cases where the embedder
 // does not want to call preventDefault() for some reasons.
 function checkCallbackWithPreventDefault() {
-  sendContextMenuTo('#menu1-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu1-trigger", function onContextMenu(detail) {
     var id = detail.contextmenu.items[0].id;
     checkContextMenuCallbackForId(detail, id, function onCallbackFired(label) {
-      is(label, 'foo', 'Callback label should be set correctly');
+      is(label, "foo", "Callback label should be set correctly");
 
       checkCallbackWithoutPreventDefault();
     });
   });
 }
 
 function checkCallbackWithoutPreventDefault() {
-  sendContextMenuTo('#menu1-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu1-trigger", function onContextMenu(detail) {
     var id = detail.contextmenu.items[0].id;
     checkContextMenuCallbackForId(detail, id, function onCallbackFired(label) {
-      is(label, null, 'Callback label should be null');
+      is(label, null, "Callback label should be null");
 
       checkImageContextMenu();
     });
   }, /* ignorePreventDefault */ true);
 }
 
 function checkImageContextMenu() {
-  sendContextMenuTo('#menu3-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu3-trigger", function onContextMenu(detail) {
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'IMG', 'Reports correct nodeName');
-    is(target.data.uri, 'example.png', 'Reports correct uri');
-    is(detail.contextmenu.items.length, 1, 'Reports correct # of menu items');
-    is(detail.contextmenu.items[0].id, 'copy-image', 'IMG has a copy-image menu item');
-    is(detail.contextmenu.customized, false, 'Make sure we do not have customized items');
+    is(target.nodeName, "IMG", "Reports correct nodeName");
+    is(target.data.uri, "example.png", "Reports correct uri");
+    is(detail.contextmenu.items.length, 1, "Reports correct # of menu items");
+    is(detail.contextmenu.items[0].id, "copy-image", "IMG has a copy-image menu item");
+    is(detail.contextmenu.customized, false, "Make sure we do not have customized items");
 
     checkVideoContextMenu();
   }, /* ignorePreventDefault */ true);
 }
 
 function checkVideoContextMenu() {
-  sendContextMenuTo('#menu4-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu4-trigger", function onContextMenu(detail) {
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'VIDEO', 'Reports correct nodeName');
-    is(target.data.uri, videoUrl, 'Reports uri correctly in data');
+    is(target.nodeName, "VIDEO", "Reports correct nodeName");
+    is(target.data.uri, videoUrl, "Reports uri correctly in data");
     is(target.data.hasVideo, true, 'Video data in video tag does "hasVideo"');
 
     checkAudioContextMenu();
   }, /* ignorePreventDefault */ true);
 }
 
 function checkAudioContextMenu() {
-  sendContextMenuTo('#menu6-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu6-trigger", function onContextMenu(detail) {
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'AUDIO', 'Reports correct nodeName');
-    is(target.data.uri, audioUrl, 'Reports uri correctly in data');
+    is(target.nodeName, "AUDIO", "Reports correct nodeName");
+    is(target.data.uri, audioUrl, "Reports uri correctly in data");
 
     checkAudioinVideoContextMenu();
   }, /* ignorePreventDefault */ true);
 }
 
 function checkAudioinVideoContextMenu() {
-  sendSrcTo('#menu5-trigger', audioUrl, function onSrcSet() {
-    sendContextMenuTo('#menu5-trigger', function onContextMenu(detail) {
+  sendSrcTo("#menu5-trigger", audioUrl, function onSrcSet() {
+    sendContextMenuTo("#menu5-trigger", function onContextMenu(detail) {
       var target = detail.systemTargets[0];
-      is(target.nodeName, 'VIDEO', 'Reports correct nodeName');
-      is(target.data.uri, audioUrl, 'Reports uri correctly in data');
+      is(target.nodeName, "VIDEO", "Reports correct nodeName");
+      is(target.data.uri, audioUrl, "Reports uri correctly in data");
       is(target.data.hasVideo, false, 'Audio data in video tag reports no "hasVideo"');
 
       checkFormNoMethod();
     }, /* ignorePreventDefault */ true);
   });
 }
 
 function checkFormNoMethod() {
-  sendContextMenuTo('#menu7-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu7-trigger", function onContextMenu(detail) {
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'INPUT', 'Reports correct nodeName');
-    is(target.data.method, 'get', 'Reports correct method');
-    is(target.data.action, 'no_method', 'Reports correct action url');
-    is(target.data.name, 'input1', 'Reports correct input name');
+    is(target.nodeName, "INPUT", "Reports correct nodeName");
+    is(target.data.method, "get", "Reports correct method");
+    is(target.data.action, "no_method", "Reports correct action url");
+    is(target.data.name, "input1", "Reports correct input name");
 
     checkFormGetMethod();
   }, /* ignorePreventDefault */ true);
 }
 
 function checkFormGetMethod() {
-  sendContextMenuTo('#menu8-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu8-trigger", function onContextMenu(detail) {
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'INPUT', 'Reports correct nodeName');
-    is(target.data.method, 'get', 'Reports correct method');
-    is(target.data.action, 'http://example.com/get_method', 'Reports correct action url');
-    is(target.data.name, 'input2', 'Reports correct input name');
+    is(target.nodeName, "INPUT", "Reports correct nodeName");
+    is(target.data.method, "get", "Reports correct method");
+    is(target.data.action, "http://example.com/get_method", "Reports correct action url");
+    is(target.data.name, "input2", "Reports correct input name");
 
     checkFormPostMethod();
   }, /* ignorePreventDefault */ true);
 }
 
 function checkFormPostMethod() {
-  sendContextMenuTo('#menu9-trigger', function onContextMenu(detail) {
+  sendContextMenuTo("#menu9-trigger", function onContextMenu(detail) {
     var target = detail.systemTargets[0];
-    is(target.nodeName, 'INPUT', 'Reports correct nodeName');
-    is(target.data.method, 'post', 'Reports correct method');
-    is(target.data.action, 'post_method', 'Reports correct action url');
-    is(target.data.name, 'input3', 'Reports correct input name');
+    is(target.nodeName, "INPUT", "Reports correct nodeName");
+    is(target.data.method, "post", "Reports correct method");
+    is(target.data.action, "post_method", "Reports correct action url");
+    is(target.data.name, "input3", "Reports correct input name");
 
     SimpleTest.finish();
   }, /* ignorePreventDefault */ true);
 }
 
 /* Helpers */
 var mm = null;
 var previousContextMenuDetail = null;
 var currentContextMenuDetail = null;
 
 function sendSrcTo(selector, src, callback) {
-  mm.sendAsyncMessage('setsrc', { 'selector': selector, 'src': src });
-  mm.addMessageListener('test:srcset', function onSrcSet(msg) {
-    mm.removeMessageListener('test:srcset', onSrcSet);
+  mm.sendAsyncMessage("setsrc", { "selector": selector, "src": src });
+  mm.addMessageListener("test:srcset", function onSrcSet(msg) {
+    mm.removeMessageListener("test:srcset", onSrcSet);
     callback();
   });
 }
 
 function sendContextMenuTo(selector, callback, ignorePreventDefault) {
-  iframe.addEventListener('mozbrowsercontextmenu', function oncontextmenu(e) {
+  iframe.addEventListener("mozbrowsercontextmenu", function oncontextmenu(e) {
     iframe.removeEventListener(e.type, oncontextmenu);
 
     // The embedder should call preventDefault() on the event if it will handle
-    // it. Not calling preventDefault() means it won't handle the event and 
+    // it. Not calling preventDefault() means it won't handle the event and
     // should not be able to deal with context menu callbacks.
     if (ignorePreventDefault !== true) {
       e.preventDefault();
     }
 
     // Keep a reference to previous/current contextmenu event details.
     previousContextMenuDetail = currentContextMenuDetail;
     currentContextMenuDetail = e.detail;
 
     setTimeout(function() { callback(e.detail); });
   });
 
-  mm.sendAsyncMessage('contextmenu', { 'selector': selector });
+  mm.sendAsyncMessage("contextmenu", { "selector": selector });
 }
 
 function checkContextMenuCallbackForId(detail, id, callback) {
-  mm.addMessageListener('test:callbackfired', function onCallbackFired(msg) {
-    mm.removeMessageListener('test:callbackfired', onCallbackFired);
+  mm.addMessageListener("test:callbackfired", function onCallbackFired(msg) {
+    mm.removeMessageListener("test:callbackfired", onCallbackFired);
 
     msg = SpecialPowers.wrap(msg);
     setTimeout(function() { callback(msg.data.label); });
   });
 
   detail.contextMenuItemSelected(id);
 }
 
 
 var iframe = null;
 function createIframe(callback) {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  iframe.src = 'data:text/html,<html>' +
-    '<body>' +
+  iframe.src = "data:text/html,<html>" +
+    "<body>" +
     '<menu type="context" id="menu1" label="firstmenu">' +
       '<menuitem label="foo" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
       '<menuitem label="bar" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
-    '</menu>' +
+    "</menu>" +
     '<menu type="context" id="menu2" label="secondmenu">' +
       '<menuitem label="outer" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
       '<menu label="submenu">' +
         '<menuitem label="inner 1"></menuitem>' +
         '<menuitem label="inner 2" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
-      '</menu>' +
-    '</menu>' +
+      "</menu>" +
+    "</menu>" +
     '<div id="menu1-trigger" contextmenu="menu1"><a id="inner-link" href="foo.html">Menu 1</a></div>' +
     '<a href="bar.html" contextmenu="menu2"><img id="menu2-trigger" src="example.png" /></a>' +
     '<img id="menu3-trigger" src="example.png" />' +
     '<video id="menu4-trigger" src="' + videoUrl + '"></video>' +
     '<video id="menu5-trigger" preload="metadata"></video>' +
     '<audio id="menu6-trigger" src="' + audioUrl + '"></audio>' +
     '<form action="no_method"><input id="menu7-trigger" name="input1"></input></form>' +
     '<form action="http://example.com/get_method" method="get"><input id="menu8-trigger" name="input2"></input></form>' +
     '<form action="post_method" method="post"><input id="menu9-trigger" name="input3"></input></form>' +
-    '</body></html>';
+    "</body></html>";
   document.body.appendChild(iframe);
 
   // The following code will be included in the child
   // =========================================================================
   function iframeScript() {
-    addMessageListener('contextmenu', function onContextMenu(msg) {
+    addMessageListener("contextmenu", function onContextMenu(msg) {
       var document = content.document;
-      var evt = document.createEvent('HTMLEvents');
-      evt.initEvent('contextmenu', true, true);
+      var evt = document.createEvent("HTMLEvents");
+      evt.initEvent("contextmenu", true, true);
       document.querySelector(msg.data.selector).dispatchEvent(evt);
     });
 
-    addMessageListener('setsrc', function onContextMenu(msg) {
+    addMessageListener("setsrc", function onContextMenu(msg) {
       var wrappedTarget = content.document.querySelector(msg.data.selector);
       var target = XPCNativeWrapper.unwrap(wrappedTarget);
-      target.addEventListener('loadedmetadata', function() {
-        sendAsyncMessage('test:srcset');
+      target.addEventListener("loadedmetadata", function() {
+        sendAsyncMessage("test:srcset");
       });
       target.src = msg.data.src;
     });
 
-    addMessageListener('browser-element-api:call', function onCallback(msg) {
-      if (msg.data.msg_name != 'fire-ctx-callback')
+    addMessageListener("browser-element-api:call", function onCallback(msg) {
+      if (msg.data.msg_name != "fire-ctx-callback")
         return;
 
       /* Use setTimeout in order to react *after* the platform */
       content.setTimeout(function() {
-        sendAsyncMessage('test:callbackfired', { label: label });
+        sendAsyncMessage("test:callbackfired", { label });
         label = null;
       });
     });
 
     var label = null;
     XPCNativeWrapper.unwrap(content).onContextMenuCallbackFired = function(e) {
-      label = e.target.getAttribute('label');
+      label = e.target.getAttribute("label");
     };
   }
   // =========================================================================
 
-  iframe.addEventListener('mozbrowserloadend', function onload(e) {
+  iframe.addEventListener("mozbrowserloadend", function onload(e) {
     iframe.removeEventListener(e.type, onload);
     mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-    mm.loadFrameScript('data:,(' + iframeScript.toString() + ')();', false);
+    mm.loadFrameScript("data:,(" + iframeScript.toString() + ")();", false);
 
     // Now we're ready, let's start testing.
     callback();
   });
 }
 
-addEventListener('testready', runTests);
+addEventListener("testready", runTests);
--- a/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js
+++ b/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js
@@ -1,51 +1,53 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 806127 - Test that cookies set by <iframe mozbrowser> are not considered
 // third-party.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  const innerPage = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html';
+  const innerPage = "http://example.com/tests/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html";
 
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    if (e.detail.message == 'next') {
-      iframe.src = innerPage + '?step=2';
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    if (e.detail.message == "next") {
+      iframe.src = innerPage + "?step=2";
       return;
     }
 
-    if (e.detail.message.startsWith('success:')) {
+    if (e.detail.message.startsWith("success:")) {
       ok(true, e.detail.message);
       return;
     }
 
-    if (e.detail.message.startsWith('failure:')) {
+    if (e.detail.message.startsWith("failure:")) {
       ok(false, e.detail.message);
       return;
     }
 
-    if (e.detail.message == 'finish') {
+    if (e.detail.message == "finish") {
       SimpleTest.finish();
     }
   });
 
   // innerPage will set a cookie and then alert('next').  We'll load
   // innerPage?step=2.  That page will check that the cooke exists (despite the
   // fact that we've disabled third-party cookies) and alert('success:') or
   // alert('failure:'), as appropriate.  Finally, the page will
   // alert('finish');
   iframe.src = innerPage;
   document.body.appendChild(iframe);
 }
 
 // Disable third-party cookies for this test.
-addEventListener('testready', function() {
-  SpecialPowers.pushPrefEnv({'set': [['network.cookie.cookieBehavior', 1]]}, runTest);
+addEventListener("testready", function() {
+  SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 1]]}, runTest);
 });
--- a/dom/browser-element/mochitest/browserElement_CopyPaste.js
+++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js
@@ -1,21 +1,22 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that "cut, copy, paste, selectall" and caretstatechanged event works from inside an <iframe mozbrowser>.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout("untriaged");
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.setupAccessibleCaretPref();
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
-const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm');
 
 var gTextarea = null;
 var mm;
 var iframeOuter;
 var iframeInner;
 var state = 0;
 var stateMeaning;
 var defaultData;
@@ -43,67 +44,67 @@ function getScriptForGetContent() {
         txt = elt.value; \
       } \
     } \
     sendAsyncMessage("content-text", txt);';
   return script;
 }
 
 function getScriptForSetFocus() {
-  var script = 'data:,' + focusScript + 'sendAsyncMessage("content-focus")';
+  var script = "data:," + focusScript + 'sendAsyncMessage("content-focus")';
   return script;
 }
 
 function runTest() {
-  iframeOuter = document.createElement('iframe');
-  iframeOuter.setAttribute('mozbrowser', 'true');
+  iframeOuter = document.createElement("iframe");
+  iframeOuter.setAttribute("mozbrowser", "true");
   if (createEmbededFrame) {
     iframeOuter.src = "file_empty.html";
   }
   document.body.appendChild(iframeOuter);
 
-  gTextarea = document.createElement('textarea');
+  gTextarea = document.createElement("textarea");
   document.body.appendChild(gTextarea);
 
   iframeOuter.addEventListener("mozbrowserloadend", function(e) {
     if (createEmbededFrame) {
       var contentWin = SpecialPowers.wrap(iframeOuter)
                              .frameLoader.docShell.contentViewer.DOMDocument.defaultView;
       var contentDoc = contentWin.document;
-      iframeInner = contentDoc.createElement('iframe');
-      iframeInner.setAttribute('mozbrowser', true);
-      iframeInner.setAttribute('remote', 'false');
+      iframeInner = contentDoc.createElement("iframe");
+      iframeInner.setAttribute("mozbrowser", true);
+      iframeInner.setAttribute("remote", "false");
       contentDoc.body.appendChild(iframeInner);
-      iframeInner.addEventListener("mozbrowserloadend", function(e) {
+      iframeInner.addEventListener("mozbrowserloadend", function(f) {
         mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner);
-        dispatchTest(e);
+        dispatchTest(f);
       }, {once: true});
     } else {
       iframeInner = iframeOuter;
       mm = SpecialPowers.getBrowserFrameMessageManager(iframeInner);
       dispatchTest(e);
     }
   }, {once: true});
 }
 
 function doCommand(cmd) {
   var COMMAND_MAP = {
-    'cut': 'cmd_cut',
-    'copy': 'cmd_copy',
-    'paste': 'cmd_paste',
-    'selectall': 'cmd_selectAll'
+    "cut": "cmd_cut",
+    "copy": "cmd_copy",
+    "paste": "cmd_paste",
+    "selectall": "cmd_selectAll",
   };
   var script = 'data:,docShell.doCommand("' + COMMAND_MAP[cmd] + '");';
   mm.loadFrameScript(script, false);
 }
 
 function dispatchTest(e) {
-  iframeInner.addEventListener("mozbrowserloadend", function(e) {
+  iframeInner.addEventListener("mozbrowserloadend", function(f) {
     iframeInner.focus();
-    SimpleTest.executeSoon(function() { testSelectAll(e); });
+    SimpleTest.executeSoon(function() { testSelectAll(f); });
   }, {once: true});
 
   switch (state) {
     case 0: // test for textarea
       defaultData = "Test for selection change event";
       pasteData = "from parent ";
       iframeInner.src = "data:text/html,<html><body>" +
                    "<textarea id='text'>" + defaultData + "</textarea>" +
@@ -175,38 +176,37 @@ function dispatchTest(e) {
         state = 0;
         runTest();
       }
       break;
   }
 }
 
 function isChildProcess() {
-  return SpecialPowers.Cc["@mozilla.org/xre/app-info;1"]
-                         .getService(SpecialPowers.Ci.nsIXULRuntime)
-                         .processType != SpecialPowers.Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+  return SpecialPowers.Services.appinfo
+                      .processType != SpecialPowers.Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
 }
 
 function testSelectAll(e) {
   // Skip mozbrowser test if we're at child process.
   if (!isChildProcess()) {
     let eventName = "mozbrowsercaretstatechanged";
-    iframeOuter.addEventListener(eventName, function(e) {
+    iframeOuter.addEventListener(eventName, function(f) {
       ok(true, "got mozbrowsercaretstatechanged event." + stateMeaning);
-      ok(e.detail, "event.detail is not null." + stateMeaning);
-      ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning);
-      ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning);
-      SimpleTest.executeSoon(function() { testCopy1(e); });
+      ok(f.detail, "event.detail is not null." + stateMeaning);
+      ok(f.detail.width != 0, "event.detail.width is not zero" + stateMeaning);
+      ok(f.detail.height != 0, "event.detail.height is not zero" + stateMeaning);
+      SimpleTest.executeSoon(function() { testCopy1(f); });
     }, {capture: true, once: true});
   }
 
-  mm.addMessageListener('content-focus', function messageforfocus(msg) {
-    mm.removeMessageListener('content-focus', messageforfocus);
+  mm.addMessageListener("content-focus", function messageforfocus(msg) {
+    mm.removeMessageListener("content-focus", messageforfocus);
     // test selectall command, after calling this the caretstatechanged event should be fired.
-    doCommand('selectall');
+    doCommand("selectall");
     if (isChildProcess()) {
       SimpleTest.executeSoon(function() { testCopy1(e); });
     }
   });
 
   mm.loadFrameScript(getScriptForSetFocus(), false);
 }
 
@@ -220,40 +220,40 @@ function testCopy1(e) {
 
     let nextTest = function(success) {
       ok(success, "copy command works" + stateMeaning);
       SimpleTest.executeSoon(function() { testPaste1(e); });
     };
 
     let success = function() {
       nextTest(true);
-    }
+    };
 
     let fail = function() {
       nextTest(false);
-    }
+    };
 
     let compareData = defaultData;
     SimpleTest.waitForClipboard(compareData, setup, success, fail);
   });
 }
 
 function testPaste1(e) {
   // Next test paste command, first we copy to global clipboard in parent side.
   // Then paste it to child side.
   copyToClipboard(pasteData, () => {
-    doCommand('selectall');
+    doCommand("selectall");
     doCommand("paste");
     SimpleTest.executeSoon(function() { testPaste2(e); });
   });
 }
 
 function testPaste2(e) {
-  mm.addMessageListener('content-text', function messageforpaste(msg) {
-    mm.removeMessageListener('content-text', messageforpaste);
+  mm.addMessageListener("content-text", function messageforpaste(msg) {
+    mm.removeMessageListener("content-text", messageforpaste);
     if (state == 4) {
       // normal div cannot paste, so the content remain unchange
       ok(SpecialPowers.wrap(msg).json === defaultData, "paste command works" + stateMeaning);
     } else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
       // Something weird when we doCommand with content editable element in OOP. Mark this case as todo
       todo(false, "paste command works" + stateMeaning);
     } else {
       ok(SpecialPowers.wrap(msg).json === pasteData, "paste command works" + stateMeaning);
@@ -279,39 +279,39 @@ function testCut1(e) {
       } else {
         ok(success, "cut function works" + stateMeaning);
       }
       SimpleTest.executeSoon(function() { testCut2(e); });
     };
 
     let success = function() {
       nextTest(true);
-    }
+    };
 
     let fail = function() {
       nextTest(false);
-    }
+    };
 
     let compareData = pasteData;
 
     // Something weird when we doCommand with content editable element in OOP.
     // Always true in this case
     // Normal div case cannot cut, always true as well.
     if ((state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) ||
         state == 4) {
-      compareData = function() { return true; }
+      compareData = function() { return true; };
     }
 
     SimpleTest.waitForClipboard(compareData, setup, success, fail);
   });
 }
 
 function testCut2(e) {
-  mm.addMessageListener('content-text', function messageforcut(msg) {
-    mm.removeMessageListener('content-text', messageforcut);
+  mm.addMessageListener("content-text", function messageforcut(msg) {
+    mm.removeMessageListener("content-text", messageforcut);
     // normal div cannot cut
     if (state == 4) {
       ok(SpecialPowers.wrap(msg).json !== "", "cut command works" + stateMeaning);
     } else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
       // Something weird when we doCommand with content editable element in OOP. Mark this case as todo
       todo(false, "cut command works" + stateMeaning);
     } else {
       ok(SpecialPowers.wrap(msg).json === "", "cut command works" + stateMeaning);
@@ -326,14 +326,13 @@ function testCut2(e) {
 
 // Give our origin permission to open browsers, and remove it when the test is complete.
 var principal = SpecialPowers.wrap(document).nodePrincipal;
 var context = { url: SpecialPowers.wrap(principal.URI).spec,
                 originAttributes: {
                   appId: principal.appId,
                   inIsolatedMozBrowser: true }};
 
-addEventListener('testready', function() {
+addEventListener("testready", function() {
   SpecialPowers.pushPermissions([
-    {type: 'browser', allow: 1, context: context}
+    {type: "browser", allow: 1, context},
   ], runTest);
 });
-
--- a/dom/browser-element/mochitest/browserElement_DataURI.js
+++ b/dom/browser-element/mochitest/browserElement_DataURI.js
@@ -1,68 +1,71 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that data: URIs work with mozbrowserlocationchange events.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
-  var iframe1 = document.createElement('iframe');
-  iframe1.setAttribute('mozbrowser', 'true');
-  iframe1.id = 'iframe1';
-  iframe1.addEventListener('mozbrowserloadend', function() {
-    ok(true, 'Got first loadend event.');
+  var iframe1 = document.createElement("iframe");
+  iframe1.setAttribute("mozbrowser", "true");
+  iframe1.id = "iframe1";
+  iframe1.addEventListener("mozbrowserloadend", function() {
+    ok(true, "Got first loadend event.");
     SimpleTest.executeSoon(runTest2);
   }, {once: true});
   iframe1.src = browserElementTestHelpers.emptyPage1;
   document.body.appendChild(iframe1);
 
-  var iframe2 = document.createElement('iframe');
-  iframe2.id = 'iframe2';
+  var iframe2 = document.createElement("iframe");
+  iframe2.id = "iframe2";
   document.body.appendChild(iframe2);
 }
 
 function runTest2() {
-  var iframe1 = document.getElementById('iframe1');
-  var iframe2 = document.getElementById('iframe2');
+  var iframe1 = document.getElementById("iframe1");
+  var iframe2 = document.getElementById("iframe2");
 
   var sawLoadEnd = false;
   var sawLocationChange = false;
 
-  iframe1.addEventListener('mozbrowserlocationchange', function(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(!sawLocationChange, 'Just one locationchange event.');
-    ok(!sawLoadEnd, 'locationchange before load.');
-    is(e.detail.url, 'data:text/html,1', "event's reported location");
+  iframe1.addEventListener("mozbrowserlocationchange", function(e) {
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(!sawLocationChange, "Just one locationchange event.");
+    ok(!sawLoadEnd, "locationchange before load.");
+    is(e.detail.url, "data:text/html,1", "event's reported location");
     sawLocationChange = true;
   });
 
-  iframe1.addEventListener('mozbrowserloadend', function() {
-    ok(sawLocationChange, 'Loadend after locationchange.');
-    ok(!sawLoadEnd, 'Just one loadend event.');
+  iframe1.addEventListener("mozbrowserloadend", function() {
+    ok(sawLocationChange, "Loadend after locationchange.");
+    ok(!sawLoadEnd, "Just one loadend event.");
     sawLoadEnd = true;
   });
 
   function iframe2Load() {
     if (!sawLoadEnd || !sawLocationChange) {
       // Spin if iframe1 hasn't loaded yet.
       SimpleTest.executeSoon(iframe2Load);
       return;
     }
-    ok(true, 'Got iframe2 load.');
+    ok(true, "Got iframe2 load.");
     SimpleTest.finish();
   }
-  iframe2.addEventListener('load', iframe2Load);
+  iframe2.addEventListener("load", iframe2Load);
 
 
-  iframe1.src = 'data:text/html,1';
+  iframe1.src = "data:text/html,1";
 
   // Load something into iframe2 to check that it doesn't trigger a
   // locationchange for our iframe1 listener.
   iframe2.src = browserElementTestHelpers.emptyPage2;
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_DataURILoad.js
+++ b/dom/browser-element/mochitest/browserElement_DataURILoad.js
@@ -1,57 +1,60 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout("testing mozbrowser data: navigation is blocked");
 
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 // make sure top level data: URI navigations are blocked.
 const PREF = "security.data_uri.block_toplevel_data_uri_navigations";
 browserElementTestHelpers._setPref(PREF, true);
 
 const INNER = "foo";
 const DATA_URI = "data:text/html,<html><body>" + INNER + "</body></html>";
 const HTTP_URI = "browserElement_DataURILoad.html";
 
 function runTest1() {
-  let frame = document.createElement('iframe');
-  frame.setAttribute('mozbrowser', 'true');
-  frame.src = DATA_URI
+  let frame = document.createElement("iframe");
+  frame.setAttribute("mozbrowser", "true");
+  frame.src = DATA_URI;
   document.body.appendChild(frame);
   let wrappedFrame = SpecialPowers.wrap(frame);
 
   // wait for 1000ms and check that the data: URI did not load
-  setTimeout(function () {
+  setTimeout(function() {
     isnot(wrappedFrame.contentWindow.document.body.innerHTML,
-          INNER, 
+          INNER,
           "data: URI navigation should be blocked");
     runTest2();
   }, 1000);
 }
 
 function runTest2() {
-  let frame = document.createElement('iframe');
-  frame.setAttribute('mozbrowser', 'true');
+  let frame = document.createElement("iframe");
+  frame.setAttribute("mozbrowser", "true");
   frame.src = HTTP_URI;
   document.body.appendChild(frame);
   let wrappedFrame = SpecialPowers.wrap(frame);
 
   wrappedFrame.addEventListener("mozbrowserloadend", function onloadend(e) {
     ok(wrappedFrame.contentWindow.document.location.href.endsWith(HTTP_URI),
        "http: URI navigation should be allowed");
-    frame.src = DATA_URI
+    frame.src = DATA_URI;
 
     // wait for 1000ms and check that the data: URI did not load
-    setTimeout(function () {
+    setTimeout(function() {
       isnot(wrappedFrame.contentWindow.document.body.innerHTML,
-            INNER, 
+            INNER,
             "data: URI navigation should be blocked");
       SimpleTest.finish();
     }, 1000);
   }, {once: true});
 }
 
-addEventListener('testready', runTest1);
+addEventListener("testready", runTest1);
--- a/dom/browser-element/mochitest/browserElement_DocumentFirstPaint.js
+++ b/dom/browser-element/mochitest/browserElement_DocumentFirstPaint.js
@@ -1,32 +1,34 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 829486 - Add mozdocumentbrowserfirstpaint event.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 
 var iframe;
 
 function runTestQueue(queue) {
   if (queue.length == 0) {
     SimpleTest.finish();
     return;
   }
 
   var gotFirstPaint = false;
   var gotFirstLocationChange = false;
   var test = queue.shift();
 
   function runNext() {
-    iframe.removeEventListener('mozbrowserdocumentfirstpaint', documentfirstpainthandler);
-    iframe.removeEventListener('mozbrowserloadend', loadendhandler);
+    iframe.removeEventListener("mozbrowserdocumentfirstpaint", documentfirstpainthandler);
+    iframe.removeEventListener("mozbrowserloadend", loadendhandler);
     runTestQueue(queue);
   }
 
   function documentfirstpainthandler(e) {
     ok(!gotFirstPaint, "Got firstpaint only once");
     gotFirstPaint = true;
     if (gotFirstLocationChange) {
       runNext();
@@ -35,18 +37,18 @@ function runTestQueue(queue) {
 
   function loadendhandler(e) {
     gotFirstLocationChange = true;
     if (gotFirstPaint) {
       runNext();
     }
   }
 
-  iframe.addEventListener('mozbrowserdocumentfirstpaint', documentfirstpainthandler);
-  iframe.addEventListener('mozbrowserloadend', loadendhandler);
+  iframe.addEventListener("mozbrowserdocumentfirstpaint", documentfirstpainthandler);
+  iframe.addEventListener("mozbrowserloadend", loadendhandler);
 
   test();
 }
 
 function testChangeLocation() {
   iframe.src = browserElementTestHelpers.emptyPage1 + "?2";
 }
 
@@ -55,15 +57,15 @@ function testReload() {
 }
 
 function testFirstLoad() {
   document.body.appendChild(iframe);
   iframe.src = browserElementTestHelpers.emptyPage1;
 }
 
 function runTest() {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   runTestQueue([testFirstLoad, testReload, testChangeLocation]);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_ErrorSecurity.js
+++ b/dom/browser-element/mochitest/browserElement_ErrorSecurity.js
@@ -1,23 +1,25 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 764718 - Test that mozbrowsererror works for a security error.
 
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 var iframe = null;
 function runTest() {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe);
 
   checkForDnsError();
 }
 
 function checkForDnsError() {
   iframe.addEventListener("mozbrowsererror", function onDnsError(e) {
     iframe.removeEventListener(e.type, onDnsError);
@@ -50,9 +52,9 @@ function checkForNoCertificateError() {
     ok(e.detail.type == "certerror", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
 
     SimpleTest.finish();
   });
 
   iframe.src = "https://nocert.example.com";
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_ExposableURI.js
+++ b/dom/browser-element/mochitest/browserElement_ExposableURI.js
@@ -1,35 +1,38 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 795317: Test that the browser element sanitizes its URIs by removing the
 // "unexposable" parts before sending them in the locationchange event.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 var iframe;
 
 function testPassword() {
   function locationchange(e) {
     var uri = e.detail.url;
-    is(uri, 'http://mochi.test:8888/tests/dom/browser-element/mochitest/file_empty.html',
+    is(uri, "http://mochi.test:8888/tests/dom/browser-element/mochitest/file_empty.html",
        "Username and password shouldn't be exposed in uri.");
     SimpleTest.finish();
   }
 
-  iframe.addEventListener('mozbrowserlocationchange', locationchange);
+  iframe.addEventListener("mozbrowserlocationchange", locationchange);
   iframe.src = "http://iamuser:iampassword@mochi.test:8888/tests/dom/browser-element/mochitest/file_empty.html";
 }
 
 function runTest() {
-  SpecialPowers.pushPrefEnv({set: [["network.http.rcwn.enabled", false]]}, _=>{
-    iframe = document.createElement('iframe');
-    iframe.setAttribute('mozbrowser', 'true');
+  SpecialPowers.pushPrefEnv({set: [["network.http.rcwn.enabled", false]]}, _ => {
+    iframe = document.createElement("iframe");
+    iframe.setAttribute("mozbrowser", "true");
     document.body.appendChild(iframe);
     testPassword();
   });
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_FirstPaint.js
+++ b/dom/browser-element/mochitest/browserElement_FirstPaint.js
@@ -1,43 +1,44 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 787378 - Add mozbrowserfirstpaint event.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   var gotFirstPaint = false;
   var gotFirstLocationChange = false;
-  iframe.addEventListener('mozbrowserfirstpaint', function(e) {
+  iframe.addEventListener("mozbrowserfirstpaint", function(e) {
     ok(!gotFirstPaint, "Got only one first paint.");
     gotFirstPaint = true;
 
     if (gotFirstLocationChange) {
-      iframe.src = browserElementTestHelpers.emptyPage1 + '?2';
+      iframe.src = browserElementTestHelpers.emptyPage1 + "?2";
     }
   });
 
-  iframe.addEventListener('mozbrowserlocationchange', function(e) {
+  iframe.addEventListener("mozbrowserlocationchange", function(e) {
     if (e.detail.url == browserElementTestHelpers.emptyPage1) {
       gotFirstLocationChange = true;
       if (gotFirstPaint) {
-        iframe.src = browserElementTestHelpers.emptyPage1 + '?2';
+        iframe.src = browserElementTestHelpers.emptyPage1 + "?2";
       }
-    }
-    else if (e.detail.url.endsWith('?2')) {
+    } else if (e.detail.url.endsWith("?2")) {
       SimpleTest.finish();
     }
   });
 
   document.body.appendChild(iframe);
 
   iframe.src = browserElementTestHelpers.emptyPage1;
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_ForwardName.js
+++ b/dom/browser-element/mochitest/browserElement_ForwardName.js
@@ -1,43 +1,45 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 781320 - Test that the name in <iframe mozbrowser name="foo"> is
 // forwarded down to remote mozbrowsers.
 
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
-  iframe.setAttribute('name', 'foo');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
+  iframe.setAttribute("name", "foo");
 
   iframe.addEventListener("mozbrowseropenwindow", function(e) {
-    ok(false, 'Got mozbrowseropenwindow, but should not have.');
+    ok(false, "Got mozbrowseropenwindow, but should not have.");
   });
 
-  iframe.addEventListener('mozbrowserlocationchange', function(e) {
+  iframe.addEventListener("mozbrowserlocationchange", function(e) {
     ok(true, "Got locationchange to " + e.detail.url);
     if (e.detail.url.endsWith("ForwardName.html#finish")) {
       SimpleTest.finish();
     }
   });
 
   // The file sends us messages via alert() that start with "success:" or
   // "failure:".
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    ok(e.detail.message.startsWith('success:'), e.detail.message);
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    ok(e.detail.message.startsWith("success:"), e.detail.message);
   });
 
   document.body.appendChild(iframe);
 
   // This file does window.open('file_browserElement_ForwardName.html#finish',
   // 'foo');  That should open in the curent window, because the window should
   // be named foo.
-  iframe.src = 'file_browserElement_ForwardName.html';
+  iframe.src = "file_browserElement_ForwardName.html";
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_FrameWrongURI.js
+++ b/dom/browser-element/mochitest/browserElement_FrameWrongURI.js
@@ -1,52 +1,54 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 804446 - Test that window.open(javascript:..) works with <iframe mozbrowser>.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframeJS = document.createElement('iframe');
-  iframeJS.setAttribute('mozbrowser', 'true');
+  var iframeJS = document.createElement("iframe");
+  iframeJS.setAttribute("mozbrowser", "true");
 
-  iframeJS.addEventListener('mozbrowserloadstart', function(e) {
+  iframeJS.addEventListener("mozbrowserloadstart", function(e) {
     ok(false, "This should not happen!");
   });
 
-  iframeJS.addEventListener('mozbrowserloadend', function(e) {
+  iframeJS.addEventListener("mozbrowserloadend", function(e) {
     ok(false, "This should not happen!");
   });
 
   iframeJS.src = 'javascript:alert("Foo");';
   document.body.appendChild(iframeJS);
 
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   var gotPopup = false;
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    is(gotPopup, false, 'Should get just one popup.');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    is(gotPopup, false, "Should get just one popup.");
     gotPopup = true;
 
     document.body.appendChild(e.detail.frameElement);
   });
 
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    ok(gotPopup, 'Got mozbrowseropenwindow event before showmodalprompt event.');
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    ok(gotPopup, "Got mozbrowseropenwindow event before showmodalprompt event.");
     if (e.detail.message.indexOf("success") == 0) {
       ok(true, e.detail.message);
       SimpleTest.finish();
-    }
-    else {
+    } else {
       ok(false, "Got invalid message: " + e.detail.message);
     }
   });
 
-  iframe.src = 'file_browserElement_FrameWrongURI.html';
+  iframe.src = "file_browserElement_FrameWrongURI.html";
   document.body.appendChild(iframe);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_Iconchange.js
+++ b/dom/browser-element/mochitest/browserElement_Iconchange.js
@@ -1,130 +1,124 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that the onmozbrowsericonchange event works.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function createHtml(link) {
-  return 'data:text/html,<html><head>' + link + '<body></body></html>';
+  return "data:text/html,<html><head>" + link + "<body></body></html>";
 }
 
 function createLink(name, sizes, rel) {
-  var s = sizes ? 'sizes="' + sizes + '"' : '';
+  var s = sizes ? 'sizes="' + sizes + '"' : "";
   if (!rel) {
-    rel = 'icon';
+    rel = "icon";
   }
   return '<link rel="' + rel + '" type="image/png" ' + s +
     ' href="http://example.com/' + name + '.png">';
 }
 
 function runTest() {
-  var iframe1 = document.createElement('iframe');
-  iframe1.setAttribute('mozbrowser', 'true');
+  var iframe1 = document.createElement("iframe");
+  iframe1.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe1);
 
   // iframe2 is a red herring; we modify its favicon but don't listen for
   // iconchanges; we want to make sure that its iconchange events aren't
   // picked up by the listener on iframe1.
-  var iframe2 = document.createElement('iframe');
-  iframe2.setAttribute('mozbrowser', 'true');
+  var iframe2 = document.createElement("iframe");
+  iframe2.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe2);
 
   // iframe3 is another red herring.  It's not a mozbrowser, so we shouldn't
   // get any iconchange events on it.
-  var iframe3 = document.createElement('iframe');
+  var iframe3 = document.createElement("iframe");
   document.body.appendChild(iframe3);
 
   var numIconChanges = 0;
 
-  iframe1.addEventListener('mozbrowsericonchange', function(e) {
-
+  iframe1.addEventListener("mozbrowsericonchange", function(e) {
     numIconChanges++;
 
     if (numIconChanges == 1) {
-      is(e.detail.href, 'http://example.com/myicon.png');
+      is(e.detail.href, "http://example.com/myicon.png");
 
       // We should recieve iconchange events when the user creates new links
       // to a favicon, but only when we listen for them
       SpecialPowers.getBrowserFrameMessageManager(iframe1)
                    .loadFrameScript("data:,content.document.title='New title';",
                                     /* allowDelayedLoad = */ false);
 
       SpecialPowers.getBrowserFrameMessageManager(iframe1)
                    .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=ICON href=http://example.com/newicon.png>')",
                                     /* allowDelayedLoad = */ false);
 
       SpecialPowers.getBrowserFrameMessageManager(iframe2)
                    .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=ICON href=http://example.com/newicon.png>')",
                                     /* allowDelayedLoad = */ false);
-    }
-    else if (numIconChanges == 2) {
-      is(e.detail.href, 'http://example.com/newicon.png');
+    } else if (numIconChanges == 2) {
+      is(e.detail.href, "http://example.com/newicon.png");
 
       // Full new pages should trigger iconchange events
-      iframe1.src = createHtml(createLink('3rdicon'));
-    }
-    else if (numIconChanges == 3) {
-      is(e.detail.href, 'http://example.com/3rdicon.png');
+      iframe1.src = createHtml(createLink("3rdicon"));
+    } else if (numIconChanges == 3) {
+      is(e.detail.href, "http://example.com/3rdicon.png");
 
       // the rel attribute can have various space seperated values, make
       // sure we only pick up correct values for 'icon'
       SpecialPowers.getBrowserFrameMessageManager(iframe1)
                    .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=shortcuticon href=http://example.com/newicon.png>')",
                                     /* allowDelayedLoad = */ false);
       // Test setting a page with multiple links elements
-      iframe1.src = createHtml(createLink('another') + createLink('icon'));
-    }
-    else if (numIconChanges == 4) {
-      is(e.detail.href, 'http://example.com/another.png');
+      iframe1.src = createHtml(createLink("another") + createLink("icon"));
+    } else if (numIconChanges == 4) {
+      is(e.detail.href, "http://example.com/another.png");
       // 2 events will be triggered by previous test, wait for next
-    }
-    else if (numIconChanges == 5) {
-      is(e.detail.href, 'http://example.com/icon.png');
+    } else if (numIconChanges == 5) {
+      is(e.detail.href, "http://example.com/icon.png");
 
       // Make sure icon check is case insensitive
       SpecialPowers.getBrowserFrameMessageManager(iframe1)
                    .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<link rel=ICON href=http://example.com/ucaseicon.png>')",
                                     /* allowDelayedLoad = */ false);
-    }
-    else if (numIconChanges == 6) {
-      is(e.detail.href, 'http://example.com/ucaseicon.png');
-      iframe1.src = createHtml(createLink('testsize', '50x50', 'icon'));
-    }
-    else if (numIconChanges == 7) {
-      is(e.detail.href, 'http://example.com/testsize.png');
-      is(e.detail.sizes, '50x50');
-      iframe1.src = createHtml(createLink('testapple1', '100x100', 'apple-touch-icon'));
+    } else if (numIconChanges == 6) {
+      is(e.detail.href, "http://example.com/ucaseicon.png");
+      iframe1.src = createHtml(createLink("testsize", "50x50", "icon"));
+    } else if (numIconChanges == 7) {
+      is(e.detail.href, "http://example.com/testsize.png");
+      is(e.detail.sizes, "50x50");
+      iframe1.src = createHtml(createLink("testapple1", "100x100", "apple-touch-icon"));
     } else if (numIconChanges == 8) {
-      is(e.detail.href, 'http://example.com/testapple1.png');
-      is(e.detail.rel, 'apple-touch-icon');
-      is(e.detail.sizes, '100x100');
+      is(e.detail.href, "http://example.com/testapple1.png");
+      is(e.detail.rel, "apple-touch-icon");
+      is(e.detail.sizes, "100x100");
 
-      iframe1.src = createHtml(createLink('testapple2', '100x100', 'apple-touch-icon-precomposed'));
+      iframe1.src = createHtml(createLink("testapple2", "100x100", "apple-touch-icon-precomposed"));
     } else if (numIconChanges == 9) {
-      is(e.detail.href, 'http://example.com/testapple2.png');
-      is(e.detail.rel, 'apple-touch-icon-precomposed');
-      is(e.detail.sizes, '100x100');
+      is(e.detail.href, "http://example.com/testapple2.png");
+      is(e.detail.rel, "apple-touch-icon-precomposed");
+      is(e.detail.sizes, "100x100");
       SimpleTest.finish();
     } else {
-      ok(false, 'Too many iconchange events.');
+      ok(false, "Too many iconchange events.");
     }
   });
 
-  iframe3.addEventListener('mozbrowsericonchange', function(e) {
-    ok(false, 'Should not get a iconchange event for iframe3.');
+  iframe3.addEventListener("mozbrowsericonchange", function(e) {
+    ok(false, "Should not get a iconchange event for iframe3.");
   });
 
 
-  iframe1.src = createHtml(createLink('myicon'));
+  iframe1.src = createHtml(createLink("myicon"));
   // We should not recieve icon change events for either of the below iframes
-  iframe2.src = createHtml(createLink('myicon'));
-  iframe3.src = createHtml(createLink('myicon'));
-
+  iframe2.src = createHtml(createLink("myicon"));
+  iframe3.src = createHtml(createLink("myicon"));
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_LoadEvents.js
+++ b/dom/browser-element/mochitest/browserElement_LoadEvents.js
@@ -1,124 +1,127 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that an iframe with the |mozbrowser| attribute emits mozbrowserloadX
 // events when this page is in the whitelist.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
   // Load emptypage1 into the iframe, wait for that to finish loading, then
   // call runTest2.
   //
   // This should trigger loadstart, locationchange, and loadend events.
 
   var seenLoadEnd = false;
   var seenLoadStart = false;
   var seenLocationChange = false;
 
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
-  iframe.id = 'iframe';
-  iframe.src = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_LoadEvents.html';
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
+  iframe.id = "iframe";
+  iframe.src = "http://example.com/tests/dom/browser-element/mochitest/file_browserElement_LoadEvents.html";
 
   function loadstart(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(!seenLoadEnd, 'loadstart before loadend.');
-    ok(!seenLoadStart, 'Just one loadstart event.');
-    ok(!seenLocationChange, 'loadstart before locationchange.');
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(!seenLoadEnd, "loadstart before loadend.");
+    ok(!seenLoadStart, "Just one loadstart event.");
+    ok(!seenLocationChange, "loadstart before locationchange.");
     seenLoadStart = true;
   }
 
   function locationchange(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(!seenLocationChange, 'Just one locationchange event.');
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(!seenLocationChange, "Just one locationchange event.");
     seenLocationChange = true;
-    ok(seenLoadStart, 'Location change after load start.');
-    ok(!seenLoadEnd, 'Location change before load end.');
+    ok(seenLoadStart, "Location change after load start.");
+    ok(!seenLoadEnd, "Location change before load end.");
     // XXX: Switched to from ok() to todo_is() in Bug 1467712. Follow up in 1503862
     // Fails with: event's reported location -
     //   got "http://example.com/tests/dom/browser-element/mochitest/file_browserElement_LoadEvents.html",
     //   expected "http://example.com/tests/dom/browser-element/mochitest/file_empty.html"
     todo_is(e.detail.url, browserElementTestHelpers.emptyPage1, "event's reported location");
   }
 
   function loadend(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(seenLoadStart, 'loadend after loadstart.');
-    ok(!seenLoadEnd, 'Just one loadend event.');
-    ok(seenLocationChange, 'loadend after locationchange.');
-    is(e.detail.backgroundColor, 'rgb(0, 128, 0)', 'Expected background color reported')
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(seenLoadStart, "loadend after loadstart.");
+    ok(!seenLoadEnd, "Just one loadend event.");
+    ok(seenLocationChange, "loadend after locationchange.");
+    is(e.detail.backgroundColor, "rgb(0, 128, 0)", "Expected background color reported");
     seenLoadEnd = true;
   }
 
-  iframe.addEventListener('mozbrowserloadstart', loadstart);
-  iframe.addEventListener('mozbrowserlocationchange', locationchange);
-  iframe.addEventListener('mozbrowserloadend', loadend);
+  iframe.addEventListener("mozbrowserloadstart", loadstart);
+  iframe.addEventListener("mozbrowserlocationchange", locationchange);
+  iframe.addEventListener("mozbrowserloadend", loadend);
 
   function waitForAllCallbacks() {
     if (!seenLoadStart || !seenLoadEnd) {
       SimpleTest.executeSoon(waitForAllCallbacks);
       return;
     }
 
-    iframe.removeEventListener('mozbrowserloadstart', loadstart);
-    iframe.removeEventListener('mozbrowserlocationchange', locationchange);
-    iframe.removeEventListener('mozbrowserloadend', loadend);
+    iframe.removeEventListener("mozbrowserloadstart", loadstart);
+    iframe.removeEventListener("mozbrowserlocationchange", locationchange);
+    iframe.removeEventListener("mozbrowserloadend", loadend);
     runTest2();
   }
 
   document.body.appendChild(iframe);
   waitForAllCallbacks();
 }
 
 function runTest2() {
   var seenLoadStart = false;
   var seenLoadEnd = false;
   var seenLocationChange = false;
 
   // Add this event listener to the document; the events should bubble.
-  document.addEventListener('mozbrowserloadstart', function(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(!seenLoadStart, 'Just one loadstart event.');
+  document.addEventListener("mozbrowserloadstart", function(e) {
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(!seenLoadStart, "Just one loadstart event.");
     seenLoadStart = true;
-    ok(!seenLoadEnd, 'Got mozbrowserloadstart before loadend.');
-    ok(!seenLocationChange, 'Got mozbrowserloadstart before locationchange.');
+    ok(!seenLoadEnd, "Got mozbrowserloadstart before loadend.");
+    ok(!seenLocationChange, "Got mozbrowserloadstart before locationchange.");
   });
 
-  var iframe = document.getElementById('iframe');
-  iframe.addEventListener('mozbrowserlocationchange', function(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(!seenLocationChange, 'Just one locationchange event.');
+  var iframe = document.getElementById("iframe");
+  iframe.addEventListener("mozbrowserlocationchange", function(e) {
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(!seenLocationChange, "Just one locationchange event.");
     seenLocationChange = true;
-    ok(seenLoadStart, 'Location change after load start.');
-    ok(!seenLoadEnd, 'Location change before load end.');
+    ok(seenLoadStart, "Location change after load start.");
+    ok(!seenLoadEnd, "Location change before load end.");
     is(e.detail.url, browserElementTestHelpers.emptyPage2, "event's reported location");
   });
 
-  iframe.addEventListener('mozbrowserloadend', function(e) {
-    ok(e.isTrusted, 'Event should be trusted.');
-    ok(!seenLoadEnd, 'Just one load end event.');
+  iframe.addEventListener("mozbrowserloadend", function(e) {
+    ok(e.isTrusted, "Event should be trusted.");
+    ok(!seenLoadEnd, "Just one load end event.");
     seenLoadEnd = true;
-    ok(seenLoadStart, 'Load end after load start.');
-    ok(seenLocationChange, 'Load end after location change.');
-    is(e.detail.backgroundColor, 'rgba(0, 0, 0, 0)', 'Expected background color reported')
+    ok(seenLoadStart, "Load end after load start.");
+    ok(seenLocationChange, "Load end after location change.");
+    is(e.detail.backgroundColor, "rgba(0, 0, 0, 0)", "Expected background color reported");
   });
 
   iframe.src = browserElementTestHelpers.emptyPage2;
 
   function waitForAllCallbacks() {
     if (!seenLoadStart || !seenLoadEnd || !seenLocationChange) {
       SimpleTest.executeSoon(waitForAllCallbacks);
       return;
     }
 
     SimpleTest.finish();
   }
 
   waitForAllCallbacks();
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_Metachange.js
+++ b/dom/browser-element/mochitest/browserElement_Metachange.js
@@ -1,178 +1,167 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that the onmozbrowsermetachange event works.
 "use strict";
 
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function createHtml(meta) {
-  return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + meta + '<body></body></html>';
+  return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + meta + "<body></body></html>";
 }
 
 function createHtmlWithLang(meta, lang) {
-  return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace" lang="' + lang + '"><head>' + meta + '<body></body></html>';
+  return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace" lang="' + lang + '"><head>' + meta + "<body></body></html>";
 }
 
 function createMeta(name, content) {
   return '<meta name="' + name + '" content="' + content + '">';
 }
 
 function createMetaWithLang(name, content, lang) {
   return '<meta name="' + name + '" content="' + content + '" lang="' + lang + '">';
 }
 
 function createMetaWithProperty(property, content) {
   return '<meta property="' + property + '" content="' + content + '">';
 }
 
 function runTest() {
-  var iframe1 = document.createElement('iframe');
-  iframe1.setAttribute('mozbrowser', 'true');
+  var iframe1 = document.createElement("iframe");
+  iframe1.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe1);
 
   // iframe2 is a red herring; we modify its meta elements but don't listen for
   // metachanges; we want to make sure that its metachange events aren't
   // picked up by the listener on iframe1.
-  var iframe2 = document.createElement('iframe');
-  iframe2.setAttribute('mozbrowser', 'true');
+  var iframe2 = document.createElement("iframe");
+  iframe2.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe2);
 
   // iframe3 is another red herring.  It's not a mozbrowser, so we shouldn't
   // get any metachange events on it.
-  var iframe3 = document.createElement('iframe');
+  var iframe3 = document.createElement("iframe");
   document.body.appendChild(iframe3);
 
   var numMetaChanges = 0;
 
-  iframe1.addEventListener('mozbrowsermetachange', function(e) {
-
+  iframe1.addEventListener("mozbrowsermetachange", function(e) {
     numMetaChanges++;
 
     if (numMetaChanges == 1) {
-      is(e.detail.name, 'application-name');
-      is(e.detail.content, 'foobar');
+      is(e.detail.name, "application-name");
+      is(e.detail.content, "foobar");
 
       // We should recieve metachange events when the user creates new metas
       SpecialPowers.getBrowserFrameMessageManager(iframe1)
                    .loadFrameScript("data:,content.document.title='New title';",
                                     /* allowDelayedLoad = */ false);
 
       SpecialPowers.getBrowserFrameMessageManager(iframe1)
                    .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<meta name=application-name content=new_foobar>')",
                                     /* allowDelayedLoad = */ false);
 
       SpecialPowers.getBrowserFrameMessageManager(iframe2)
                    .loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<meta name=application-name content=new_foobar>')",
                                     /* allowDelayedLoad = */ false);
-    }
-    else if (numMetaChanges == 2) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'new_foobar', 'content matches');
-      ok(!("lang" in e.detail), 'lang not present');
+    } else if (numMetaChanges == 2) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "new_foobar", "content matches");
+      ok(!("lang" in e.detail), "lang not present");
 
       // Full new pages should trigger metachange events
-      iframe1.src = createHtml(createMeta('application-name', '3rd_foobar'));
-    }
-    else if (numMetaChanges == 3) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, '3rd_foobar', 'content matches');
-      ok(!("lang" in e.detail), 'lang not present');
+      iframe1.src = createHtml(createMeta("application-name", "3rd_foobar"));
+    } else if (numMetaChanges == 3) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "3rd_foobar", "content matches");
+      ok(!("lang" in e.detail), "lang not present");
 
       // Test setting a page with multiple meta elements
-      iframe1.src = createHtml(createMeta('application-name', 'foobar_1') + createMeta('application-name', 'foobar_2'));
-    }
-    else if (numMetaChanges == 4) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'foobar_1', 'content matches');
-      ok(!("lang" in e.detail), 'lang not present');
+      iframe1.src = createHtml(createMeta("application-name", "foobar_1") + createMeta("application-name", "foobar_2"));
+    } else if (numMetaChanges == 4) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "foobar_1", "content matches");
+      ok(!("lang" in e.detail), "lang not present");
       // 2 events will be triggered by previous test, wait for next
-    }
-    else if (numMetaChanges == 5) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'foobar_2', 'content matches');
-      ok(!("lang" in e.detail), 'lang not present');
+    } else if (numMetaChanges == 5) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "foobar_2", "content matches");
+      ok(!("lang" in e.detail), "lang not present");
 
       // Test the language
-      iframe1.src = createHtml(createMetaWithLang('application-name', 'foobar_lang_1', 'en'));
-    }
-    else if (numMetaChanges == 6) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'foobar_lang_1', 'content matches');
-      is(e.detail.lang, 'en', 'language matches');
+      iframe1.src = createHtml(createMetaWithLang("application-name", "foobar_lang_1", "en"));
+    } else if (numMetaChanges == 6) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "foobar_lang_1", "content matches");
+      is(e.detail.lang, "en", "language matches");
 
       // Test the language in the ancestor element
-      iframe1.src = createHtmlWithLang(createMeta('application-name', 'foobar_lang_2'), 'es');
-    }
-    else if (numMetaChanges == 7) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'foobar_lang_2', 'content matches');
-      is(e.detail.lang, 'es', 'language matches');
+      iframe1.src = createHtmlWithLang(createMeta("application-name", "foobar_lang_2"), "es");
+    } else if (numMetaChanges == 7) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "foobar_lang_2", "content matches");
+      is(e.detail.lang, "es", "language matches");
 
       // Test the language in the ancestor element
-      iframe1.src = createHtmlWithLang(createMetaWithLang('application-name', 'foobar_lang_3', 'it'), 'fi');
-    }
-    else if (numMetaChanges == 8) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'foobar_lang_3', 'content matches');
-      is(e.detail.lang, 'it', 'language matches');
+      iframe1.src = createHtmlWithLang(createMetaWithLang("application-name", "foobar_lang_3", "it"), "fi");
+    } else if (numMetaChanges == 8) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "foobar_lang_3", "content matches");
+      is(e.detail.lang, "it", "language matches");
 
       // Test the content-language
       iframe1.src = "http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru";
-    }
-    else if (numMetaChanges == 9) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'sjs', 'content matches');
-      is(e.detail.lang, 'ru', 'language matches');
+    } else if (numMetaChanges == 9) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "sjs", "content matches");
+      is(e.detail.lang, "ru", "language matches");
 
       // Test the content-language
       iframe1.src = "http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru|dk";
-    }
-    else if (numMetaChanges == 10) {
-      is(e.detail.name, 'application-name', 'name matches');
-      is(e.detail.content, 'sjs', 'content matches');
-      is(e.detail.lang, 'dk', 'language matches');
+    } else if (numMetaChanges == 10) {
+      is(e.detail.name, "application-name", "name matches");
+      is(e.detail.content, "sjs", "content matches");
+      is(e.detail.lang, "dk", "language matches");
 
       // Test Open Graph property
-      iframe1.src = createHtml(createMetaWithProperty('og:description', 'Fascinating article'));
+      iframe1.src = createHtml(createMetaWithProperty("og:description", "Fascinating article"));
 
       // We should not get event if property doesn't start with 'og:'
-      iframe3.src = createHtml(createMetaWithProperty('go:description', 'Fascinating article'));
-    }
-    else if (numMetaChanges == 11) {
-      is(e.detail.name, 'og:description', 'property name matches');
-      is(e.detail.content, 'Fascinating article', 'content matches');
+      iframe3.src = createHtml(createMetaWithProperty("go:description", "Fascinating article"));
+    } else if (numMetaChanges == 11) {
+      is(e.detail.name, "og:description", "property name matches");
+      is(e.detail.content, "Fascinating article", "content matches");
 
       // Sometimes 'name' is used instead of 'property'. Verify that works.
-      iframe1.src = createHtml(createMeta('og:title', 'One weird trick!'));
+      iframe1.src = createHtml(createMeta("og:title", "One weird trick!"));
 
       // We should not get event if property doesn't start with 'og:'
-      iframe3.src = createHtml(createMeta('go:title', 'One weird trick!'));
-    }
-    else if (numMetaChanges == 12) {
-      is(e.detail.name, 'og:title', 'property name matches');
-      is(e.detail.content, 'One weird trick!', 'content matches');
+      iframe3.src = createHtml(createMeta("go:title", "One weird trick!"));
+    } else if (numMetaChanges == 12) {
+      is(e.detail.name, "og:title", "property name matches");
+      is(e.detail.content, "One weird trick!", "content matches");
 
       // Test the language
       SimpleTest.finish();
     } else {
-      ok(false, 'Too many metachange events.');
+      ok(false, "Too many metachange events.");
     }
   });
 
-  iframe3.addEventListener('mozbrowsermetachange', function(e) {
-    ok(false, 'Should not get a metachange event for iframe3.');
+  iframe3.addEventListener("mozbrowsermetachange", function(e) {
+    ok(false, "Should not get a metachange event for iframe3.");
   });
 
 
-  iframe1.src = createHtml(createMeta('application-name', 'foobar'));
+  iframe1.src = createHtml(createMeta("application-name", "foobar"));
   // We should not recieve meta change events for either of the below iframes
-  iframe2.src = createHtml(createMeta('application-name', 'foobar'));
-  iframe3.src = createHtml(createMeta('application-name', 'foobar'));
-
+  iframe2.src = createHtml(createMeta("application-name", "foobar"));
+  iframe3.src = createHtml(createMeta("application-name", "foobar"));
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenNamed.js
+++ b/dom/browser-element/mochitest/browserElement_OpenNamed.js
@@ -1,55 +1,58 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 742944 - In <iframe mozbrowser>, test that if we call window.open twice
 // with the same name, we get only one mozbrowseropenwindow event.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 var iframe;
 var popupFrame;
 function runTest() {
-  iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   var gotPopup = false;
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    is(gotPopup, false, 'Should get just one popup.');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    is(gotPopup, false, "Should get just one popup.");
     gotPopup = true;
     popupFrame = e.detail.frameElement;
-    is(popupFrame.getAttribute('name'), 'OpenNamed');
+    is(popupFrame.getAttribute("name"), "OpenNamed");
 
     // Called when file_browserElement_OpenNamed2.html loads into popupFrame.
-    popupFrame.addEventListener('mozbrowsershowmodalprompt', function(e) {
-      ok(gotPopup, 'Got openwindow event before showmodalprompt event.');
-      is(e.detail.message, 'success: loaded');
+    popupFrame.addEventListener("mozbrowsershowmodalprompt", function(f) {
+      ok(gotPopup, "Got openwindow event before showmodalprompt event.");
+      is(f.detail.message, "success: loaded");
       SimpleTest.executeSoon(test2);
     }, {once: true});
 
     document.body.appendChild(popupFrame);
   });
 
   // OpenNamed.html will call
   //
   //    window.open('file_browserElement_OpenNamed2.html', 'OpenNamed').
   //
   // Once that popup loads, we reload OpenNamed.html.  That will call
   // window.open again, but we shouldn't get another openwindow event, because
   // we're opening into the same named window.
-  iframe.src = 'file_browserElement_OpenNamed.html';
+  iframe.src = "file_browserElement_OpenNamed.html";
   document.body.appendChild(iframe);
 }
 
 function test2() {
-  popupFrame.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    is(e.detail.message, 'success: loaded');
+  popupFrame.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    is(e.detail.message, "success: loaded");
     SimpleTest.finish();
   });
 
-  iframe.src = 'file_browserElement_OpenNamed.html?test2';
+  iframe.src = "file_browserElement_OpenNamed.html?test2";
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenTab.js
+++ b/dom/browser-element/mochitest/browserElement_OpenTab.js
@@ -1,21 +1,24 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 1144015 - test middle/ctrl/cmd-click on a link.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  let iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  let iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
   document.body.appendChild(iframe);
 
   let x = 2;
   let y = 2;
   // This test used to try to transform the coordinates from child
   // to parent coordinate space by first calling
   // iframe.getBoundingClientRect();
   // to refresh offsets and then calling
@@ -23,40 +26,40 @@ function runTest() {
   //                .frameLoader.tabParent;
   // and calling tabParent.getChildProcessOffset(offsetX, offsetY) if
   // tabParent was not null, but tabParent was always null.
 
   let sendCtrlClick = () => {
     let nsIDOMWindowUtils = SpecialPowers.Ci.nsIDOMWindowUtils;
     let mod = nsIDOMWindowUtils.MODIFIER_META |
               nsIDOMWindowUtils.MODIFIER_CONTROL;
-    iframe.sendMouseEvent('mousedown', x, y, 0, 1, mod);
-    iframe.sendMouseEvent('mouseup', x, y, 0, 1, mod);
-  }
+    iframe.sendMouseEvent("mousedown", x, y, 0, 1, mod);
+    iframe.sendMouseEvent("mouseup", x, y, 0, 1, mod);
+  };
 
   let onCtrlClick = e => {
-    is(e.detail.url, 'http://example.com/', 'URL matches');
-    iframe.removeEventListener('mozbrowseropentab', onCtrlClick);
-    iframe.addEventListener('mozbrowseropentab', onMiddleClick);
+    is(e.detail.url, "http://example.com/", "URL matches");
+    iframe.removeEventListener("mozbrowseropentab", onCtrlClick);
+    iframe.addEventListener("mozbrowseropentab", onMiddleClick);
     sendMiddleClick();
-  }
+  };
 
   let sendMiddleClick = () => {
-    iframe.sendMouseEvent('mousedown', x, y, 1, 1, 0);
-    iframe.sendMouseEvent('mouseup', x, y, 1, 1, 0);
-  }
+    iframe.sendMouseEvent("mousedown", x, y, 1, 1, 0);
+    iframe.sendMouseEvent("mouseup", x, y, 1, 1, 0);
+  };
 
   let onMiddleClick = e => {
-    is(e.detail.url, 'http://example.com/', 'URL matches');
-    iframe.removeEventListener('mozbrowseropentab', onMiddleClick);
+    is(e.detail.url, "http://example.com/", "URL matches");
+    iframe.removeEventListener("mozbrowseropentab", onMiddleClick);
     SimpleTest.finish();
-  }
+  };
 
-  iframe.addEventListener('mozbrowserloadend', e => {
-    iframe.addEventListener('mozbrowseropentab', onCtrlClick);
+  iframe.addEventListener("mozbrowserloadend", e => {
+    iframe.addEventListener("mozbrowseropentab", onCtrlClick);
     sendCtrlClick();
   });
 
 
   iframe.src = 'data:text/html,<body style="margin:0"><a href="http://example.com"><span>click here</span></a></body>';
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenWindow.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindow.js
@@ -1,58 +1,58 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 742944 - Test that window.open works with <iframe mozbrowser>.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   var gotPopup = false;
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    is(gotPopup, false, 'Should get just one popup.');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    is(gotPopup, false, "Should get just one popup.");
     gotPopup = true;
 
     document.body.appendChild(e.detail.frameElement);
 
     ok(/file_browserElement_Open2\.html$/.test(e.detail.url),
        "Popup's URL (got " + e.detail.url + ")");
     is(e.detail.name, "name");
     is(e.detail.features, "dialog=1");
   });
 
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    ok(gotPopup, 'Got mozbrowseropenwindow event before showmodalprompt event.');
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    ok(gotPopup, "Got mozbrowseropenwindow event before showmodalprompt event.");
     if (e.detail.message.indexOf("success:") == 0) {
       ok(true, e.detail.message);
-    }
-    else if (e.detail.message.indexOf("failure:") == 0) {
+    } else if (e.detail.message.indexOf("failure:") == 0) {
       ok(false, e.detail.message);
-    }
-    else if (e.detail.message == "finish") {
+    } else if (e.detail.message == "finish") {
       SimpleTest.finish();
-    }
-    else {
+    } else {
       ok(false, "Got invalid message: " + e.detail.message);
     }
   });
 
   /**
    * file_browserElementOpen1 does
    *
    *   window.open('file_browserElement_Open2.html', 'name', 'dialog=1')
    *
    * then adds an event listener to the opened window and waits for onload.
    *
    * Onload, we fire a few alerts saying "success:REASON" or "failure:REASON".
    * Finally, we fire a "finish" alert, which ends the test.
    */
-  iframe.src = 'file_browserElement_Open1.html';
+  iframe.src = "file_browserElement_Open1.html";
   document.body.appendChild(iframe);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js
@@ -1,41 +1,44 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 769182 - window.open to a different origin should load the page.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    ok(true, 'Got first window.open call');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    ok(true, "Got first window.open call");
 
-    e.detail.frameElement.addEventListener('mozbrowseropenwindow', function(e) {
-      ok(true, 'Got second window.open call');
-      document.body.appendChild(e.detail.frameElement);
+    e.detail.frameElement.addEventListener("mozbrowseropenwindow", function(f) {
+      ok(true, "Got second window.open call");
+      document.body.appendChild(f.detail.frameElement);
     });
 
-    e.detail.frameElement.addEventListener('mozbrowsershowmodalprompt', function(e) {
-      ok(true, 'Got alert from second window.');
+    e.detail.frameElement.addEventListener("mozbrowsershowmodalprompt", function(f) {
+      ok(true, "Got alert from second window.");
       SimpleTest.finish();
     });
 
     document.body.appendChild(e.detail.frameElement);
   });
 
   // DifferentOrigin.html?1 calls
   //
   //   window.open('http://example.com/.../DifferentOrigin.html?2'),
   //
   // which calls alert().
 
-  iframe.src = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html?1';
+  iframe.src = "http://example.org/tests/dom/browser-element/mochitest/file_browserElement_OpenWindowDifferentOrigin.html?1";
   document.body.appendChild(iframe);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenWindowEmpty.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowEmpty.js
@@ -1,31 +1,34 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 1216937 - Test that window.open with null/empty URL should use
 // about:blank as default
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   var gotPopup = false;
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    is(gotPopup, false, 'Should get just one popup.');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    is(gotPopup, false, "Should get just one popup.");
     gotPopup = true;
 
-    is(e.detail.url, 'about:blank', "Popup's has correct URL");
+    is(e.detail.url, "about:blank", "Popup's has correct URL");
     e.preventDefault();
 
     SimpleTest.finish();
   });
 
-  iframe.src = 'file_browserElement_OpenWindowEmpty.html';
+  iframe.src = "file_browserElement_OpenWindowEmpty.html";
   document.body.appendChild(iframe);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js
@@ -5,61 +5,61 @@
 //
 // This is basically the same as browserElement_OpenWindow, except that instead
 // of loading file_browserElement_Open1.html directly inside the <iframe
 // mozbrowser>, we load file_browserElement_OpenWindowInFrame.html into the
 // mozbrowser.  OpenWindowInFrame loads file_browserElement_Open1.html inside
 // an iframe.
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
   var gotPopup = false;
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    is(gotPopup, false, 'Should get just one popup.');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    is(gotPopup, false, "Should get just one popup.");
     gotPopup = true;
 
     document.body.appendChild(e.detail.frameElement);
 
     ok(/file_browserElement_Open2\.html$/.test(e.detail.url),
        "Popup's URL (got " + e.detail.url + ")");
     is(e.detail.name, "name");
     is(e.detail.features, "dialog=1");
   });
 
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    ok(gotPopup, 'Got mozbrowseropenwindow event before showmodalprompt event.');
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+    ok(gotPopup, "Got mozbrowseropenwindow event before showmodalprompt event.");
     if (e.detail.message.indexOf("success:") == 0) {
       ok(true, e.detail.message);
-    }
-    else if (e.detail.message.indexOf("failure:") == 0) {
+    } else if (e.detail.message.indexOf("failure:") == 0) {
       ok(false, e.detail.message);
-    }
-    else if (e.detail.message == "finish") {
+    } else if (e.detail.message == "finish") {
       SimpleTest.finish();
-    }
-    else {
+    } else {
       ok(false, "Got invalid message: " + e.detail.message);
     }
   });
 
   /**
    * file_browserElement_OpenWindowInFrame.html loads
    * file_browserElement_Open1.html in an iframe.  Open1.html does
    *
    *   window.open('file_browserElement_Open2.html', 'name', 'dialog=1')
    *
    * then adds an event listener to the opened window and waits for onload.
    *
    * Onload, we fire a few alerts saying "success:REASON" or "failure:REASON".
    * Finally, we fire a "finish" alert, which ends the test.
    */
-  iframe.src = 'file_browserElement_OpenWindowInFrame.html';
+  iframe.src = "file_browserElement_OpenWindowInFrame.html";
   document.body.appendChild(iframe);
 }
 
-addEventListener('testready', runTest);
+addEventListener("testready", runTest);
--- a/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
@@ -1,44 +1,45 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Bug 742944 - Do window.open from inside <iframe mozbrowser>.  But then
 // reject the call.  This shouldn't cause problems (crashes, leaks).
 
 "use strict";
+
+/* global browserElementTestHelpers */
+
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
 
 function runTest() {
-  var iframe = document.createElement('iframe');
-  iframe.setAttribute('mozbrowser', 'true');
+  var iframe = document.createElement("iframe");
+  iframe.setAttribute("mozbrowser", "true");
 
-  iframe.addEventListener('mozbrowseropenwindow', function(e) {
-    ok(e.detail.url.includes('does_not_exist.html'),
-       'Opened URL; got ' + e.detail.url);
-    is(e.detail.name, '');
-    is(e.detail.features, '');
+  iframe.addEventListener("mozbrowseropenwindow", function(e) {
+    ok(e.detail.url.includes("does_not_exist.html"),
+       "Opened URL; got " + e.detail.url);
+    is(e.detail.name, "");
+    is(e.detail.features, "");
 
     // Don't add e.detail.frameElement to the DOM, so the window.open is
     // effectively blocked.
     e.preventDefault();
   });
 
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
+  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
     var msg = e.detail.message;
-    if (msg.indexOf('success:') == 0) {