Merge m-c to cedar
authorJames Graham <james@hoppipolla.co.uk>
Thu, 30 Apr 2015 10:24:08 +0100
changeset 326800 9067800cb505f717b2b5217a1f310812751f0d9f
parent 326799 a034d06779ae54f820d0d0fd66aa3b11895ffb9e (current diff)
parent 260486 4b9b12c248dcad6c574ccd9e824d93ae3298ec32 (diff)
child 326801 4ae9d300ac0aa0791b03ef0fd30e21ed60f38880
push id10169
push userdminor@mozilla.com
push dateThu, 28 Jan 2016 13:10:48 +0000
milestone40.0a1
Merge m-c to cedar
dom/cache/FetchPut.cpp
dom/cache/FetchPut.h
dom/events/test/chrome.ini
dom/push/PushService.jsm
js/src/jit-test/tests/basic/string-contains.js
layout/style/test/chrome/chrome.ini
mobile/android/base/tests/testReaderMode.java
testing/web-platform/meta/service-workers/cache-storage/common.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage-keys.https.html.ini
--- a/addon-sdk/source/lib/sdk/self.js
+++ b/addon-sdk/source/lib/sdk/self.js
@@ -23,17 +23,17 @@ const loadReason = readPref("load.reason
 const rootURI = readPref("rootURI") || options.rootURI || "";
 const baseURI = readPref("baseURI") || options.prefixURI + name + "/"
 const addonDataURI = baseURI + "data/";
 const metadata = options.metadata || {};
 const permissions = metadata.permissions || {};
 const isPacked = rootURI && rootURI.indexOf("jar:") === 0;
 
 const uri = (path="") =>
-  path.contains(":") ? path : addonDataURI + path.replace(/^\.\//, "");
+  path.includes(":") ? path : addonDataURI + path.replace(/^\.\//, "");
 
 let preferencesBranch = ("preferences-branch" in metadata)
                             ? metadata["preferences-branch"]
                             : options.preferencesBranch
 
 if (/[^\w{@}.-]/.test(preferencesBranch)) {
   preferencesBranch = id;
   console.warn("Ignoring preferences-branch (not a valid branch name)");
--- a/addon-sdk/source/test/addons/e10s-content/lib/test-page-worker.js
+++ b/addon-sdk/source/test/addons/e10s-content/lib/test-page-worker.js
@@ -475,17 +475,17 @@ exports.testMessageQueue = function (ass
 };
 
 exports.testWindowStopDontBreak = function (assert, done) {
   const { Ci, Cc } = require('chrome');
   const consoleService = Cc['@mozilla.org/consoleservice;1'].
                             getService(Ci.nsIConsoleService);
   const listener = {
     observe: ({message}) => {
-      if (message.contains('contentWorker is null'))
+      if (message.includes('contentWorker is null'))
         assert.fail('contentWorker is null');
     }
   };
   consoleService.registerListener(listener)
 
   let page = new Page({
     contentURL: 'data:text/html;charset=utf-8,testWindowStopDontBreak',
     contentScriptWhen: 'ready',
--- a/addon-sdk/source/test/fixtures.js
+++ b/addon-sdk/source/test/fixtures.js
@@ -1,16 +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/. */
 
 const { uri } = module;
 const prefix = uri.substr(0, uri.lastIndexOf("/") + 1) + "fixtures/";
 
-exports.url = (path="") => path && path.contains(":")
+exports.url = (path="") => path && path.includes(":")
   ? path
   : prefix + path.replace(/^\.\//, "");
 
 const base64jpeg = "data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQAAAQABAAD%2F" +
                   "2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCg" +
                   "sOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD%2F2wBDAQMDAwQDBAgEBAgQCw" +
                   "kLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ" +
                   "EBAQEBAQEBD%2FwAARCAAgACADAREAAhEBAxEB%2F8QAHwAAAQUBAQEBAQ" +
--- a/addon-sdk/source/test/test-content-events.js
+++ b/addon-sdk/source/test/test-content-events.js
@@ -129,17 +129,17 @@ exports["test dead object errors"] = fun
 
   // The dead object error is properly reported on console but
   // doesn't raise any test's exception
   function onMessage({ subject }) {
     let message = subject.wrappedJSObject;
     let { level } = message;
     let text = String(message.arguments[0]);
 
-    if (level === "error" && text.contains("can't access dead object"))
+    if (level === "error" && text.includes("can't access dead object"))
       fail(text);
   }
 
   let cleanup = () => system.off("console-api-log-event", onMessage);
   let fail = (reason) => {
     cleanup();
     assert.fail(reason);
   }
--- a/addon-sdk/source/test/test-page-worker.js
+++ b/addon-sdk/source/test/test-page-worker.js
@@ -483,17 +483,17 @@ exports.testMessageQueue = function (ass
 };
 
 exports.testWindowStopDontBreak = function (assert, done) {
   const { Ci, Cc } = require('chrome');
   const consoleService = Cc['@mozilla.org/consoleservice;1'].
                             getService(Ci.nsIConsoleService);
   const listener = {
     observe: ({message}) => {
-      if (message.contains('contentWorker is null'))
+      if (message.includes('contentWorker is null'))
         assert.fail('contentWorker is null');
     }
   };
   consoleService.registerListener(listener)
 
   let page = new Page({
     contentURL: 'data:text/html;charset=utf-8,testWindowStopDontBreak',
     contentScriptWhen: 'ready',
--- a/addon-sdk/source/test/test-system-input-output.js
+++ b/addon-sdk/source/test/test-system-input-output.js
@@ -21,17 +21,17 @@ const isConsoleEvent = topic =>
    "console-storage-cache-event"].indexOf(topic) >= 0;
 
 const message = x => ({wrappedJSObject: {data: x}});
 
 exports["test start / stop ports"] = assert => {
   const input = new InputPort({ id: Date.now().toString(32), initial: {data:0} });
   const topic = input.topic;
 
-  assert.ok(topic.contains(addonID), "topics are namespaced to add-on");
+  assert.ok(topic.includes(addonID), "topics are namespaced to add-on");
 
   const xs = lift(({data}) => "x:" + data, input);
   const ys = lift(({data}) => "y:" + data, input);
 
   assert.deepEqual(input.value, {data:0}, "initila value is set");
   assert.deepEqual(xs.value, "x:0", "initial value is mapped");
   assert.deepEqual(ys.value, "y:0", "initial value is mapped");
 
@@ -211,17 +211,17 @@ exports["test explicit input topic"] = (
 };
 
 
 exports["test receive what was send"] = assert => {
   const id = Date.now().toString(32);
   const input = new InputPort({ id: id, initial: 0});
   const output = new OutputPort({ id: id, sync: true });
 
-  assert.ok(input.topic.contains(addonID),
+  assert.ok(input.topic.includes(addonID),
             "input topic is namespaced to addon");
   assert.equal(input.topic, output.topic,
               "input & output get same topics from id.");
 
   start(input);
 
   assert.equal(input.value, 0, "initial value is set");
 
--- a/b2g/components/ProcessGlobal.js
+++ b/b2g/components/ProcessGlobal.js
@@ -99,16 +99,19 @@ ProcessGlobal.prototype = {
     lines.forEach((line) => {
       log(line);
       let params = line.split(" ");
       if (params[0] == "wipe") {
         this.wipeDir(params[1]);
       } else if (params[0] == "root") {
         log("unrestrict devtools");
         Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", false);
+        Services.prefs.setBoolPref("dom.apps.developer_mode", true);
+        // TODO: Remove once bug 1125916 is fixed.
+        Services.prefs.setBoolPref("network.disable.ipc.security", true);
         let lock = settings.createLock();
         lock.set("developer.menu.enabled", true, null);
       }
     });
   },
 
   cleanupAfterFactoryReset: function() {
     log("cleanupAfterWipe start");
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "6e35b0948c42a4398b8a5916015de167121683a1", 
+        "git_revision": "db8ea705c0fd1b1684807f5a8e837bb9a36a6f96", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "14e42674734ab45c745a6b431cac067fab6f7a77", 
+    "revision": "9f534d2f9b669389d3ee66bdcd521a8fb6b6279f", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="db8ea705c0fd1b1684807f5a8e837bb9a36a6f96"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1193,20 +1193,25 @@ pref("security.sandbox.windows.log", fal
 //     everything, but will definitely cause some functionality restrictions
 pref("dom.ipc.plugins.sandbox-level.default", 0);
 
 #if defined(MOZ_CONTENT_SANDBOX)
 // This controls the strength of the Windows content process sandbox for testing
 // purposes. This will require a restart.
 // On windows these levels are:
 // 0 - sandbox with USER_NON_ADMIN access token level
-// 1 - a more strict sandbox, which causes problems in specific areas
+// 1 - level 0 plus low integrity
 // 2 - a policy that we can reasonably call an effective sandbox
 // 3 - an equivalent basic policy to the Chromium renderer processes
+#if defined(NIGHTLY_BUILD)
+pref("security.sandbox.content.level", 1);
+#else
 pref("security.sandbox.content.level", 0);
+#endif
+
 
 #if defined(MOZ_STACKWALKING)
 // This controls the depth of stack trace that is logged when Windows sandbox
 // logging is turned on.  This is only currently available for the content
 // process because the only other sandbox (for GMP) has too strict a policy to
 // allow stack tracing.  This does not require a restart to take effect.
 pref("security.sandbox.windows.log.stackTraceDepth", 0);
 #endif
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -203,17 +203,17 @@
         }
 
         window.addEventListener("AboutNetErrorOptions", function(evt) {
         // Pinning errors are of type nssFailure2
           if (getErrorCode() == "nssFailure2") {
             var learnMoreLink = document.getElementById("learnMoreLink");
             // nssFailure2 also gets us other non-overrideable errors. Choose
             // a "learn more" link based on description:
-            if (getDescription().contains("mozilla_pkix_error_key_pinning_failure")) {
+            if (getDescription().includes("mozilla_pkix_error_key_pinning_failure")) {
               learnMoreLink.href = "https://support.mozilla.org/kb/certificate-pinning-reports";
             }
 
             var options = JSON.parse(evt.detail);
             if (options && options.enabled) {
               var checkbox = document.getElementById('automaticallyReportInFuture');
               showCertificateErrorReporting();
               if (options.automatic) {
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -108,17 +108,17 @@ let wrapper = {
     let iframe = document.getElementById("remote");
     this.iframe = iframe;
     iframe.addEventListener("load", this);
 
     // Ideally we'd just merge urlParams with new URL(url).searchParams, but our
     // URLSearchParams implementation doesn't support iteration (bug 1085284).
     let urlParamStr = urlParams.toString();
     if (urlParamStr) {
-      url += (url.contains("?") ? "&" : "?") + urlParamStr;
+      url += (url.includes("?") ? "&" : "?") + urlParamStr;
     }
     iframe.src = url;
   },
 
   handleEvent: function (evt) {
     switch (evt.type) {
       case "load":
         this.iframe.contentWindow.addEventListener("FirefoxAccountsCommand", this);
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -199,18 +199,18 @@ SocialUI = {
     }
   },
 
   get _chromeless() {
     // Is this a popup window that doesn't want chrome shown?
     let docElem = document.documentElement;
     // extrachrome is not restored during session restore, so we need
     // to check for the toolbar as well.
-    let chromeless = docElem.getAttribute("chromehidden").contains("extrachrome") ||
-                     docElem.getAttribute('chromehidden').contains("toolbar");
+    let chromeless = docElem.getAttribute("chromehidden").includes("extrachrome") ||
+                     docElem.getAttribute('chromehidden').includes("toolbar");
     // This property is "fixed" for a window, so avoid doing the check above
     // multiple times...
     delete this._chromeless;
     this._chromeless = chromeless;
     return chromeless;
   },
 
   get enabled() {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2983,17 +2983,17 @@ let BrowserOnClick = {
 function getMeOutOfHere() {
   // Get the start page from the *default* pref branch, not the user's
   var prefs = Services.prefs.getDefaultBranch(null);
   var url = BROWSER_NEW_TAB_URL;
   try {
     url = prefs.getComplexValue("browser.startup.homepage",
                                 Ci.nsIPrefLocalizedString).data;
     // If url is a pipe-delimited set of pages, just take the first one.
-    if (url.contains("|"))
+    if (url.includes("|"))
       url = url.split("|")[0];
   } catch(e) {
     Components.utils.reportError("Couldn't get homepage pref: " + e);
   }
   gBrowser.loadURI(url);
 }
 
 function BrowserFullScreen()
@@ -3675,17 +3675,17 @@ function FillHistoryMenu(aParent) {
     aParent.appendChild(item);
   }
   return true;
 }
 
 function addToUrlbarHistory(aUrlToAdd) {
   if (!PrivateBrowsingUtils.isWindowPrivate(window) &&
       aUrlToAdd &&
-      !aUrlToAdd.contains(" ") &&
+      !aUrlToAdd.includes(" ") &&
       !/[\x00-\x1F]/.test(aUrlToAdd))
     PlacesUIUtils.markPageAsTyped(aUrlToAdd);
 }
 
 function toJavaScriptConsole()
 {
   toOpenWindowByType("global:console", "chrome://global/content/console.xul");
 }
@@ -5273,61 +5273,27 @@ function UpdateDynamicShortcutTooltipTex
         args.push(ShortcutUtils.prettifyShortcut(shortcut));
       }
     }
     gDynamicTooltipCache.set(nodeId, gNavigatorBundle.getFormattedString(strId, args));
   }
   aTooltip.setAttribute("label", gDynamicTooltipCache.get(nodeId));
 }
 
-/**
- * Gets the selected text in the active browser. Leading and trailing
- * whitespace is removed, and consecutive whitespace is replaced by a single
- * space. A maximum of 150 characters will be returned, regardless of the value
- * of aCharLen.
- *
- * @param aCharLen
- *        The maximum number of characters to return.
- */
 function getBrowserSelection(aCharLen) {
-  // selections of more than 150 characters aren't useful
-  const kMaxSelectionLen = 150;
-  const charLen = Math.min(aCharLen || kMaxSelectionLen, kMaxSelectionLen);
-
-  let [element, focusedWindow] = BrowserUtils.getFocusSync(document);
-  var selection = focusedWindow.getSelection().toString();
-  // try getting a selected text in text input.
-  if (!selection) {
-    var isOnTextInput = function isOnTextInput(elem) {
-      // we avoid to return a value if a selection is in password field.
-      // ref. bug 565717
-      return elem instanceof HTMLTextAreaElement ||
-             (elem instanceof HTMLInputElement && elem.mozIsTextField(true));
-    };
-
-    if (isOnTextInput(element)) {
-      selection = element.QueryInterface(Ci.nsIDOMNSEditableElement)
-                         .editor.selection.toString();
-    }
-  }
-
-  if (selection) {
-    if (selection.length > charLen) {
-      // only use the first charLen important chars. see bug 221361
-      var pattern = new RegExp("^(?:\\s*.){0," + charLen + "}");
-      pattern.test(selection);
-      selection = RegExp.lastMatch;
-    }
-
-    selection = selection.trim().replace(/\s+/g, " ");
-
-    if (selection.length > charLen)
-      selection = selection.substr(0, charLen);
-  }
-  return selection;
+  Deprecated.warning("getBrowserSelection",
+                     "https://bugzilla.mozilla.org/show_bug.cgi?id=1134769");
+
+  let focusedElement = document.activeElement;
+  if (focusedElement && focusedElement.localName == "browser" &&
+      focusedElement.isRemoteBrowser) {
+    throw "getBrowserSelection doesn't support child process windows";
+  }
+
+  return BrowserUtils.getSelectionDetails(window, aCharLen).text;
 }
 
 var gWebPanelURI;
 function openWebPanel(title, uri) {
   // Ensure that the web panels sidebar is open.
   SidebarUI.show("viewWebPanelsSidebar");
 
   // Set the title of the panel.
@@ -6454,17 +6420,17 @@ function GetSearchFieldBookmarkData(node
     }
   }
 
   var postData;
 
   if (isURLEncoded)
     postData = formData.join("&");
   else {
-    let separator = spec.contains("?") ? "&" : "?";
+    let separator = spec.includes("?") ? "&" : "?";
     spec += separator + formData.join("&");
   }
 
   return {
     spec: spec,
     title: title,
     description: description,
     postData: postData,
@@ -7230,17 +7196,17 @@ let gPrivateBrowsingUI = {
       }
     }
 
     if (gURLBar &&
         !PrivateBrowsingUtils.permanentPrivateBrowsing) {
       // Disable switch to tab autocompletion for private windows.
       // We leave it enabled for permanent private browsing mode though.
       let value = gURLBar.getAttribute("autocompletesearchparam") || "";
-      if (!value.contains("disable-private-actions")) {
+      if (!value.includes("disable-private-actions")) {
         gURLBar.setAttribute("autocompletesearchparam",
                              value + " disable-private-actions");
       }
     }
   }
 };
 
 let gRemoteTabsUI = {
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -109,16 +109,18 @@ let handleContentContextMenu = function 
         contentType = props.get("type", Ci.nsISupportsCString).data;
         contentDisposition = props.get("content-disposition", Ci.nsISupportsCString).data;
       }
     } catch (e) {
       Cu.reportError(e);
     }
   }
 
+  let selectionInfo = BrowserUtils.getSelectionDetails(content);
+
   if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
     let editFlags = SpellCheckHelper.isEditable(event.target, content);
     let spellInfo;
     if (editFlags &
         (SpellCheckHelper.EDITABLE | SpellCheckHelper.CONTENTEDITABLE)) {
       spellInfo =
         InlineSpellCheckerContent.initContextMenu(event, editFlags, this);
     }
@@ -131,17 +133,17 @@ let handleContentContextMenu = function 
     event.target.ownerDocument.defaultView.updateCommands("contentcontextmenu");
 
     let customMenuItems = PageMenuChild.build(event.target);
     let principal = doc.nodePrincipal;
     sendSyncMessage("contextmenu",
                     { editFlags, spellInfo, customMenuItems, addonInfo,
                       principal, docLocation, charSet, baseURI, referrer,
                       referrerPolicy, contentType, contentDisposition,
-                      frameOuterWindowID },
+                      frameOuterWindowID, selectionInfo },
                     { event, popupNode: event.target });
   }
   else {
     // Break out to the parent window and pass the add-on info along
     let browser = docShell.chromeEventHandler;
     let mainWin = browser.ownerDocument.defaultView;
     mainWin.gContextMenuContentData = {
       isRemote: false,
@@ -151,16 +153,17 @@ let handleContentContextMenu = function 
       addonInfo: addonInfo,
       documentURIObject: doc.documentURIObject,
       docLocation: docLocation,
       charSet: charSet,
       referrer: referrer,
       referrerPolicy: referrerPolicy,
       contentType: contentType,
       contentDisposition: contentDisposition,
+      selectionInfo: selectionInfo,
     };
   }
 }
 
 Cc["@mozilla.org/eventlistenerservice;1"]
   .getService(Ci.nsIEventListenerService)
   .addSystemEventListener(global, "contextmenu", handleContentContextMenu, false);
 
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -37,17 +37,17 @@ nsContextMenu.prototype = {
 
     this.isFrameImage = document.getElementById("isFrameImage");
     this.ellipsis = "\u2026";
     try {
       this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
                                                    Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
 
-    this.isContentSelected = this.isContentSelection();
+    this.isContentSelected = !this.selectionInfo.docSelectionIsCollapsed;
     this.onPlainTextLink = false;
 
     // Initialize (disable/remove) menu items.
     this.initItems();
 
     // Register this opening of the menu with telemetry:
     this._checkTelemetryForMenu(aXulMenu);
   },
@@ -88,77 +88,25 @@ nsContextMenu.prototype = {
       var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                           getService(Ci.nsIExternalProtocolService).
                           getProtocolHandlerInfo("mailto");
       isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling &&
                           mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
                           (mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp));
     }
 
-    // Time to do some bad things and see if we've highlighted a URL that
-    // isn't actually linked.
-    if (this.isTextSelected && !this.onLink) {
-      // Ok, we have some text, let's figure out if it looks like a URL.
-      let selection =  this.focusedWindow.getSelection();
-      let linkText = selection.toString().trim();
-      let uri;
-      if (/^(?:https?|ftp):/i.test(linkText)) {
-        try {
-          uri = makeURI(linkText);
-        } catch (ex) {}
-      }
-      // Check if this could be a valid url, just missing the protocol.
-      else if (/^(?:[a-z\d-]+\.)+[a-z]+$/i.test(linkText)) {
-        // Now let's see if this is an intentional link selection. Our guess is
-        // based on whether the selection begins/ends with whitespace or is
-        // preceded/followed by a non-word character.
-
-        // selection.toString() trims trailing whitespace, so we look for
-        // that explicitly in the first and last ranges.
-        let beginRange = selection.getRangeAt(0);
-        let delimitedAtStart = /^\s/.test(beginRange);
-        if (!delimitedAtStart) {
-          let container = beginRange.startContainer;
-          let offset = beginRange.startOffset;
-          if (container.nodeType == Node.TEXT_NODE && offset > 0)
-            delimitedAtStart = /\W/.test(container.textContent[offset - 1]);
-          else
-            delimitedAtStart = true;
-        }
+    if (this.isTextSelected && !this.onLink &&
+        this.selectionInfo && this.selectionInfo.linkURL) {
+      this.linkURL = this.selectionInfo.linkURL;
+      try {
+        this.linkURI = makeURI(this.linkURL);
+      } catch (ex) {}
 
-        let delimitedAtEnd = false;
-        if (delimitedAtStart) {
-          let endRange = selection.getRangeAt(selection.rangeCount - 1);
-          delimitedAtEnd = /\s$/.test(endRange);
-          if (!delimitedAtEnd) {
-            let container = endRange.endContainer;
-            let offset = endRange.endOffset;
-            if (container.nodeType == Node.TEXT_NODE &&
-                offset < container.textContent.length)
-              delimitedAtEnd = /\W/.test(container.textContent[offset]);
-            else
-              delimitedAtEnd = true;
-          }
-        }
-
-        if (delimitedAtStart && delimitedAtEnd) {
-          let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
-                           .getService(Ci.nsIURIFixup);
-          try {
-            uri = uriFixup.createFixupURI(linkText, uriFixup.FIXUP_FLAG_NONE);
-          } catch (ex) {}
-        }
-      }
-
-      if (uri && uri.host) {
-        this.linkURI = uri;
-        this.linkURL = this.linkURI.spec;
-        this.linkText = linkText;
-        this.onPlainTextLink = true;
-      }
+      this.linkText = this.selectionInfo.linkText;
+      this.onPlainTextLink = true;
     }
 
     var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
     var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
     this.showItem("context-openlink", shouldShow && !isWindowPrivate);
     this.showItem("context-openlinkprivate", shouldShow);
     this.showItem("context-openlinkintab", shouldShow);
     this.showItem("context-openlinkincurrent", this.onPlainTextLink);
@@ -585,26 +533,29 @@ nsContextMenu.prototype = {
     this.inSrcdocFrame     = false;
     this.inSyntheticDoc    = false;
     this.hasBGImage        = false;
     this.bgImageURL        = "";
     this.onEditableArea    = false;
     this.isDesignMode      = false;
     this.onCTPPlugin       = false;
     this.canSpellCheck     = false;
-    this.textSelected      = getBrowserSelection();
+
+    if (this.isRemote) {
+      this.selectionInfo = gContextMenuContentData.selectionInfo;
+    } else {
+      this.selectionInfo = BrowserUtils.getSelectionDetails(window);
+    }
+
+    this.textSelected      = this.selectionInfo.text;
     this.isTextSelected    = this.textSelected.length != 0;
 
     // Remember the node that was clicked.
     this.target = aNode;
 
-    let [elt, win] = BrowserUtils.getFocusSync(document);
-    this.focusedWindow = win;
-    this.focusedElement = elt;
-
     let ownerDoc = this.target.ownerDocument;
     this.ownerDoc = ownerDoc;
 
     // If this is a remote context menu event, use the information from
     // gContextMenuContentData instead.
     if (this.isRemote) {
       this.browser = gContextMenuContentData.browser;
       this.principal = gContextMenuContentData.principal;
@@ -1540,21 +1491,16 @@ nsContextMenu.prototype = {
         if (!text || !text.match(/\S/))
           text = this.linkURL;
       }
     }
 
     return text;
   },
 
-  // Returns true if anything is selected.
-  isContentSelection: function() {
-    return !this.focusedWindow.getSelection().isCollapsed;
-  },
-
   isMediaURLReusable: function(aURL) {
     return !/^(?:blob|mediasource):/.test(aURL);
   },
 
   toString: function () {
     return "contextMenu.target     = " + this.target + "\n" +
            "contextMenu.onImage    = " + this.onImage + "\n" +
            "contextMenu.onLink     = " + this.onLink + "\n" +
--- a/browser/base/content/sync/aboutSyncTabs.js
+++ b/browser/base/content/sync/aboutSyncTabs.js
@@ -62,18 +62,18 @@ let RemoteTabViewer = {
     let numTabs = this._tabsList.getRowCount();
     let clientTabs = 0;
     let currentClient = null;
 
     for (let i = 0; i < numTabs; i++) {
       let item = this._tabsList.getItemAtIndex(i);
       let hide = false;
       if (item.getAttribute("type") == "tab") {
-        if (!item.getAttribute("url").toLowerCase().contains(val) &&
-            !item.getAttribute("title").toLowerCase().contains(val)) {
+        if (!item.getAttribute("url").toLowerCase().includes(val) &&
+            !item.getAttribute("title").toLowerCase().includes(val)) {
           hide = true;
         } else {
           clientTabs++;
         }
       }
       else if (item.getAttribute("type") == "client") {
         if (currentClient) {
           if (clientTabs == 0) {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -996,17 +996,17 @@
                 newTitle += sep;
             }
             newTitle += modifier;
 
             // If location bar is hidden and the URL type supports a host,
             // add the scheme and host to the title to prevent spoofing.
             // XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
             try {
-              if (docElement.getAttribute("chromehidden").contains("location")) {
+              if (docElement.getAttribute("chromehidden").includes("location")) {
                 var uri = this.mURIFixup.createExposableURI(
                             aBrowser.currentURI);
                 if (uri.scheme == "about")
                   newTitle = uri.spec + sep + newTitle;
                 else
                   newTitle = uri.prePath + sep + newTitle;
               }
             } catch (e) {}
@@ -3758,16 +3758,17 @@
                                           documentURIObject: documentURIObject,
                                           docLocation: aMessage.data.docLocation,
                                           charSet: aMessage.data.charSet,
                                           referrer: aMessage.data.referrer,
                                           referrerPolicy: aMessage.data.referrerPolicy,
                                           contentType: aMessage.data.contentType,
                                           contentDisposition: aMessage.data.contentDisposition,
                                           frameOuterWindowID: aMessage.data.frameOuterWindowID,
+                                          selectionInfo: aMessage.data.selectionInfo,
                                         };
               let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
               let event = gContextMenuContentData.event;
               popup.openPopupAtScreen(event.screenX, event.screenY, true);
               break;
             }
             case "DOMWebNotificationClicked": {
               let tab = this.getTabForBrowser(browser);
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -146,41 +146,37 @@ skip-if = buildapp == 'mulet' || toolkit
 [browser_bug304198.js]
 [browser_bug321000.js]
 skip-if = true # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
 [browser_bug329212.js]
 [browser_bug331772_xul_tooltiptext_in_html.js]
 [browser_bug356571.js]
 [browser_bug380960.js]
 [browser_bug386835.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug405137.js]
 [browser_bug406216.js]
 [browser_bug409481.js]
 [browser_bug409624.js]
 [browser_bug413915.js]
 [browser_bug416661.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug417483.js]
 skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug419612.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug422590.js]
 [browser_bug423833.js]
 skip-if = true # bug 428712
 [browser_bug424101.js]
-skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug427559.js]
 [browser_bug431826.js]
 [browser_bug432599.js]
 [browser_bug435035.js]
 [browser_bug435325.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1099156 - test directly manipulates content
 [browser_bug441778.js]
-skip-if = buildapp == 'mulet' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
+skip-if = buildapp == 'mulet'
 [browser_bug455852.js]
 [browser_bug460146.js]
 skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s
 [browser_bug462289.js]
 skip-if = toolkit == "cocoa" || e10s # Bug 1102017 - middle-button mousedown on selected tab2 does not activate tab - Didn't expect [object XULElement], but got it
 [browser_bug462673.js]
 [browser_bug477014.js]
 [browser_bug479408.js]
@@ -199,32 +195,30 @@ skip-if = e10s # Bug 866413 - PageInfo d
 [browser_bug537013.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1134458 - Find bar doesn't work correctly in a detached tab
 [browser_bug537474.js]
 skip-if = e10s # Bug 1102020 - test tries to use browserDOMWindow.openURI to open a link, and gets a null rv where it expects a window
 [browser_bug550565.js]
 [browser_bug553455.js]
 skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works on mulet?
 [browser_bug555224.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug555767.js]
 skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
 [browser_bug556061.js]
 [browser_bug559991.js]
 [browser_bug561623.js]
 [browser_bug561636.js]
 [browser_bug562649.js]
 [browser_bug563588.js]
 [browser_bug565575.js]
 [browser_bug565667.js]
 skip-if = toolkit != "cocoa"
 [browser_bug567306.js]
 [browser_bug575561.js]
 [browser_bug575830.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug577121.js]
 [browser_bug578534.js]
 [browser_bug579872.js]
 [browser_bug580638.js]
 [browser_bug580956.js]
 [browser_bug581242.js]
 [browser_bug581253.js]
 skip-if = e10s # Bug 1093756 - can't bookmark the data: url in e10s somehow
@@ -250,17 +244,16 @@ skip-if = buildapp == 'mulet' || e10s # 
 [browser_bug655584.js]
 [browser_bug664672.js]
 [browser_bug676619.js]
 skip-if = buildapp == 'mulet' || os == "mac" # mac: Intermittent failures, bug 925225
 [browser_bug678392.js]
 skip-if = e10s # bug 1102331 - does focus things on the content window which break in e10s mode
 [browser_bug710878.js]
 [browser_bug719271.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug724239.js]
 [browser_bug734076.js]
 skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug735471.js]
 [browser_bug749738.js]
 [browser_bug763468_perwindowpb.js]
 [browser_bug767836_perwindowpb.js]
 [browser_bug771331.js]
@@ -272,19 +265,18 @@ skip-if = e10s # Bug 1093155 - tries to 
 [browser_bug880101.js]
 skip-if = e10s # Bug 1126316 - New e10s windows erroneously fire initial about:blank location through nsIWebProgressListener
 [browser_bug882977.js]
 [browser_bug902156.js]
 [browser_bug906190.js]
 skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
 [browser_mixedContentFromOnunload.js]
 [browser_bug970746.js]
-skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug1015721.js]
-skip-if = os == 'win' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
+skip-if = os == 'win' || e10s # Bug 1159268 - Need a content-process safe version of synthesizeWheel
 [browser_bug1064280_changeUrlInPinnedTab.js]
 [browser_bug1070778.js]
 [browser_canonizeURL.js]
 skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
 [browser_clipboard.js]
 [browser_contentAreaClick.js]
 [browser_contextSearchTabPosition.js]
 skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash
--- a/browser/base/content/test/general/browser_bug424101.js
+++ b/browser/base/content/test/general/browser_bug424101.js
@@ -1,53 +1,52 @@
 /* Make sure that the context menu appears on form elements */
 
-function test() {
-  waitForExplicitFinish();
+add_task(function *() {
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/html,test");
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+  let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
 
-    let doc = gBrowser.contentDocument;
-    let testInput = function(type, expected) {
-      let element = doc.createElement("input");
-      element.setAttribute("type", type);
-      doc.body.appendChild(element);
-      document.popupNode = element;
+  let tests = [
+    { element: "input", type: "text" },
+    { element: "input", type: "password" },
+    { element: "input", type: "image" },
+    { element: "input", type: "button" },
+    { element: "input", type: "submit" },
+    { element: "input", type: "reset" },
+    { element: "input", type: "checkbox" },
+    { element: "input", type: "radio" },
+    { element: "button" },
+    { element: "select" },
+    { element: "option" },
+    { element: "optgroup" }
+  ];
 
-      let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
-      let contextMenu = new nsContextMenu(contentAreaContextMenu);
-
-      is(contextMenu.shouldDisplay, expected, "context menu behavior for <input type=" + type + "> is wrong");
-    };
-    let testElement = function(tag, expected) {
-      let element = doc.createElement(tag);
-      doc.body.appendChild(element);
-      document.popupNode = element;
+  for (let index = 0; index < tests.length; index++) {
+    let test = tests[index];
 
-      let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
-      let contextMenu = new nsContextMenu(contentAreaContextMenu);
-
-      is(contextMenu.shouldDisplay, expected, "context menu behavior for <" + tag + "> is wrong");
-    };
+    yield ContentTask.spawn(gBrowser.selectedBrowser,
+                            { element: test.element, type: test.type, index: index },
+                            function* (arg) {
+      let element = content.document.createElement(arg.element);
+      element.id = "element" + arg.index;
+      if (arg.type) {
+        element.setAttribute("type", arg.type);
+      }
+      content.document.body.appendChild(element);
+    });
 
-    testInput("text", true);
-    testInput("password", true);
-    testInput("image", true);
-    testInput("button", true);
-    testInput("submit", true);
-    testInput("reset", true);
-    testInput("checkbox", true);
-    testInput("radio", true);
-    testElement("button", true);
-    testElement("select", true);
-    testElement("option", true);
-    testElement("optgroup", true);
+    let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#element" + index,
+          { type: "contextmenu", button: 2}, gBrowser.selectedBrowser);
+    yield popupShownPromise;
 
-    // cleanup
-    document.popupNode = null;
-    gBrowser.removeCurrentTab();
-    finish();
-  }, true);
-  content.location = "data:text/html,test";
-}
+    let typeAttr = test.type ? "type=" + test.type + " " : "";
+    is(gContextMenu.shouldDisplay, true,
+        "context menu behavior for <" + test.element + " " + typeAttr + "> is wrong");
+
+    let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
+    contentAreaContextMenu.hidePopup();
+    yield popupHiddenPromise;
+  }
+
+  gBrowser.removeCurrentTab();
+});
--- a/browser/base/content/test/general/browser_bug839103.js
+++ b/browser/base/content/test/general/browser_bug839103.js
@@ -13,17 +13,17 @@ function test() {
 }
 
 function initialStylesheetAdded(evt) {
   gBrowser.removeEventListener("StyleSheetAdded", initialStylesheetAdded, true);
   ok(true, "received initial style sheet event");
   is(evt.type, "StyleSheetAdded", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.documentSheet, "style sheet is a document sheet");
 }
 
 function tabLoad(evt) {
   gTab.linkedBrowser.removeEventListener(evt.type, tabLoad, true);
   executeSoon(continueTest);
 }
 
@@ -58,17 +58,17 @@ function continueTest() {
 }
 
 function dynamicStylesheetAdded(evt) {
   gBrowser.removeEventListener("StyleSheetAdded", dynamicStylesheetAdded, true);
   ok(true, "received dynamic style sheet event");
   is(evt.type, "StyleSheetAdded", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.documentSheet, "style sheet is a document sheet");
 }
 
 function dynamicStylesheetApplicableStateChanged(evt) {
   gBrowser.removeEventListener("StyleSheetApplicableStateChanged", dynamicStylesheetApplicableStateChanged, true);
   ok(true, "received dynamic style sheet applicable state change event");
   is(evt.type, "StyleSheetApplicableStateChanged", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
@@ -92,58 +92,58 @@ function dynamicStylesheetApplicableStat
 }
 
 function dynamicStylesheetRemoved(evt) {
   gBrowser.removeEventListener("StyleSheetRemoved", dynamicStylesheetRemoved, true);
   ok(true, "received dynamic style sheet removal");
   is(evt.type, "StyleSheetRemoved", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
-  ok(evt.stylesheet.href.contains(gStyleSheet), "evt.stylesheet is the removed stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.href.includes(gStyleSheet), "evt.stylesheet is the removed stylesheet");
 
   gBrowser.addEventListener("StyleRuleAdded", styleRuleAdded, true);
   gBrowser.contentDocument.querySelector("style").sheet.insertRule("*{color:black}", 0);
 }
 
 function styleRuleAdded(evt) {
   gBrowser.removeEventListener("StyleRuleAdded", styleRuleAdded, true);
   ok(true, "received style rule added event");
   is(evt.type, "StyleRuleAdded", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.rule, "evt.rule is defined");
   is(evt.rule.cssText, "* { color: black; }", "evt.rule.cssText has expected value");
 
   gBrowser.addEventListener("StyleRuleChanged", styleRuleChanged, true);
   evt.rule.style.cssText = "color:green";
 }
 
 function styleRuleChanged(evt) {
   gBrowser.removeEventListener("StyleRuleChanged", styleRuleChanged, true);
   ok(true, "received style rule changed event");
   is(evt.type, "StyleRuleChanged", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.rule, "evt.rule is defined");
   is(evt.rule.cssText, "* { color: green; }", "evt.rule.cssText has expected value");
 
   gBrowser.addEventListener("StyleRuleRemoved", styleRuleRemoved, true);
   evt.stylesheet.deleteRule(0);
 }
 
 function styleRuleRemoved(evt) {
   gBrowser.removeEventListener("StyleRuleRemoved", styleRuleRemoved, true);
   ok(true, "received style rule removed event");
   is(evt.type, "StyleRuleRemoved", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.rule, "evt.rule is defined");
 
   executeSoon(concludeTest);
 }
 
 function concludeTest() {
   let doc = gBrowser.contentDocument;
   doc.removeEventListener("StyleSheetAdded", unexpectedContentEvent, false);
--- a/browser/base/content/test/general/browser_bug970746.js
+++ b/browser/base/content/test/general/browser_bug970746.js
@@ -1,125 +1,121 @@
 /* Make sure context menu includes option to search hyperlink text on search engine */
 
-function test() {
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
-
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+add_task(function *() {
+  const url = "http://mochi.test:8888/browser/browser/base/content/test/general/browser_bug970746.xhtml";
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 
-    let doc = gBrowser.contentDocument;
-    let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
-    let ellipsis = "\u2026";
+  const ellipsis = "\u2026";
 
-    // Tests if the "Search <engine> for '<some terms>'" context menu item is shown for the
-    // given query string of an element. Tests to make sure label includes the proper search terms.
-    //
-    // Options:
-    //
-    //   id: The id of the element to test.
-    //   isSelected: Flag to enable selection (text hilight) the contents of the element
-    //   shouldBeShown: The display state of the menu item
-    //   expectedLabelContents: The menu item label should contain a portion of this string.
-    //                          Will only be tested if shouldBeShown is true.
+  let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
 
-    let testElement = function(opts) {
-      let element = doc.getElementById(opts.id);
-      document.popupNode = element;
-
-      let selection = content.getSelection();
-      selection.removeAllRanges();
-
-      if(opts.isSelected) {
-        selection.selectAllChildren(element);
-      }
-
-      let contextMenu = new nsContextMenu(contentAreaContextMenu);
-      let menuItem = document.getElementById("context-searchselect");
-
-      is(document.getElementById("context-searchselect").hidden, !opts.shouldBeShown, "search context menu item is shown for  '#" + opts.id + "' and selected is '" + opts.isSelected + "'");
-
-      if(opts.shouldBeShown) {
-        ok(menuItem.label.contains(opts.expectedLabelContents), "Menu item text '" + menuItem.label  + "' contains the correct search terms '" + opts.expectedLabelContents  + "'");
-      }
-    }
-
-    testElement({
+  // Tests if the "Search <engine> for '<some terms>'" context menu item is shown for the
+  // given query string of an element. Tests to make sure label includes the proper search terms.
+  //
+  // Each test:
+  //
+  //   id: The id of the element to test.
+  //   isSelected: Flag to enable selecting (text highlight) the contents of the element
+  //   shouldBeShown: The display state of the menu item
+  //   expectedLabelContents: The menu item label should contain a portion of this string.
+  //                          Will only be tested if shouldBeShown is true.
+  let tests = [
+    {
       id: "link",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "I'm a link!",
-    });
-    testElement({
+    },
+    {
       id: "link",
       isSelected: false,
       shouldBeShown: true,
       expectedLabelContents: "I'm a link!",
-    });
-
-    testElement({
+    },
+    {
       id: "longLink",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "I'm a really lo" + ellipsis,
-    });
-    testElement({
+    },
+    {
       id: "longLink",
       isSelected: false,
       shouldBeShown: true,
       expectedLabelContents: "I'm a really lo" + ellipsis,
-    });
-
-    testElement({
+    },
+    {
       id: "plainText",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "Right clicking " + ellipsis,
-    });
-    testElement({
+    },
+    {
       id: "plainText",
       isSelected: false,
       shouldBeShown: false,
-    });
-
-    testElement({
+    },
+    {
       id: "mixedContent",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "I'm some text, " + ellipsis,
-    });
-    testElement({
+    },
+    {
       id: "mixedContent",
       isSelected: false,
       shouldBeShown: false,
-    });
-
-    testElement({
+    },
+    {
       id: "partialLink",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "link selection",
-    });
-
-    testElement({
+    },
+    {
       id: "partialLink",
       isSelected: false,
       shouldBeShown: true,
       expectedLabelContents: "A partial link " + ellipsis,
-    });
-
-    testElement({
+    },
+    {
       id: "surrogatePair",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "This character\uD83D\uDD25" + ellipsis,
+    }
+  ];
+
+  for (let test of tests) {
+    yield ContentTask.spawn(gBrowser.selectedBrowser,
+                            { selectElement: test.isSelected ? test.id : null },
+                            function* (arg) {
+      let selection = content.getSelection();
+      selection.removeAllRanges();
+
+      if (arg.selectElement) {
+        selection.selectAllChildren(content.document.getElementById(arg.selectElement));
+      }
     });
 
-    // cleanup
-    document.popupNode = null;
-    gBrowser.removeCurrentTab();
-    finish();
-  }, true);
+    let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#" + test.id,
+          { type: "contextmenu", button: 2}, gBrowser.selectedBrowser);
+    yield popupShownPromise;
+
+    let menuItem = document.getElementById("context-searchselect");
+    is(menuItem.hidden, !test.shouldBeShown,
+        "search context menu item is shown for  '#" + test.id + "' and selected is '" + test.isSelected + "'");
 
-  content.location = "http://mochi.test:8888/browser/browser/base/content/test/general/browser_bug970746.xhtml";
-}
+    if (test.shouldBeShown) {
+      ok(menuItem.label.includes(test.expectedLabelContents),
+         "Menu item text '" + menuItem.label  + "' contains the correct search terms '" + test.expectedLabelContents  + "'");
+    }
+
+    let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
+    contentAreaContextMenu.hidePopup();
+    yield popupHiddenPromise;
+  }
+
+  // cleanup
+  gBrowser.removeCurrentTab();
+});
--- a/browser/base/content/test/general/browser_devices_get_user_media.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media.js
@@ -149,17 +149,17 @@ function activateSecondaryAction(aAction
       EventUtils.synthesizeKey("VK_DOWN", {});
 
     // Activate
     EventUtils.synthesizeKey("VK_RETURN", {});
   }, false);
 
   // One down event to open the popup
   EventUtils.synthesizeKey("VK_DOWN",
-                           { altKey: !navigator.platform.contains("Mac") });
+                           { altKey: !navigator.platform.includes("Mac") });
 }
 
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
   kObservedTopics.forEach(topic => {
     Services.obs.removeObserver(observer, topic);
   });
   Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
--- a/browser/base/content/test/general/browser_devices_get_user_media_in_frame.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media_in_frame.js
@@ -143,17 +143,17 @@ function activateSecondaryAction(aAction
       EventUtils.synthesizeKey("VK_DOWN", {});
 
     // Activate
     EventUtils.synthesizeKey("VK_RETURN", {});
   }, false);
 
   // One down event to open the popup
   EventUtils.synthesizeKey("VK_DOWN",
-                           { altKey: !navigator.platform.contains("Mac") });
+                           { altKey: !navigator.platform.includes("Mac") });
 }
 
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
   kObservedTopics.forEach(topic => {
     Services.obs.removeObserver(observer, topic);
   });
   Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
--- a/browser/base/content/test/general/browser_fxa_migrate.js
+++ b/browser/base/content/test/general/browser_fxa_migrate.js
@@ -27,17 +27,17 @@ add_task(function* test() {
                                imports.fxaMigrator.STATE_USER_FXA_VERIFIED);
   buttonState = yield buttonPromise;
   assertButtonState(buttonState, "migrate-verify", true,
                     "foo@example.com not verified");
   let note = Weave.Notifications.notifications.find(n => {
     return n.title == NOTIFICATION_TITLE;
   });
   Assert.ok(!!note, "Needs-verification notification should be present");
-  Assert.ok(note.description.contains(email.data),
+  Assert.ok(note.description.includes(email.data),
             "Needs-verification notification should include email");
 
   // Fake the state where no migration is needed.
   buttonPromise = promiseButtonMutation();
   Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC, null);
   buttonState = yield buttonPromise;
   // In this case, the front end has called fxAccounts.getSignedInUser() to
   // update the button label and status.  But since there isn't actually a user,
--- a/browser/base/content/test/general/browser_homeDrop.js
+++ b/browser/base/content/test/general/browser_homeDrop.js
@@ -32,17 +32,17 @@ function test() {
     ok(true, "dialog appeared in response to home button drop");
     domwindow.document.documentElement.cancelDialog();
     Services.wm.removeListener(dialogListener);
 
     // Now trigger the invalid URI test
     executeSoon(function () {
       let consoleListener = {
         observe: function (m) {
-          if (m.message.contains("NS_ERROR_DOM_BAD_URI")) {
+          if (m.message.includes("NS_ERROR_DOM_BAD_URI")) {
             ok(true, "drop was blocked");
             executeSoon(finish);
           }
         }
       }
       Services.console.registerListener(consoleListener);
       registerCleanupFunction(function () {
         Services.console.unregisterListener(consoleListener);
--- a/browser/base/content/test/general/browser_parsable_css.js
+++ b/browser/base/content/test/general/browser_parsable_css.js
@@ -68,17 +68,17 @@ add_task(function checkAllTheCSS() {
 
   // Listen for errors caused by the CSS:
   let errorListener = {
     observe: function(aMessage) {
       if (!aMessage || !(aMessage instanceof Ci.nsIScriptError)) {
         return;
       }
       // Only care about CSS errors generated by our iframe:
-      if (aMessage.category.contains("CSS") && aMessage.innerWindowID === 0 && aMessage.outerWindowID === 0) {
+      if (aMessage.category.includes("CSS") && aMessage.innerWindowID === 0 && aMessage.outerWindowID === 0) {
         // Check if this error is whitelisted in kWhitelist
         if (!ignoredError(aMessage)) {
           ok(false, "Got error message for " + aMessage.sourceName + ": " + aMessage.errorMessage);
           errors++;
         } else {
           info("Ignored error for " + aMessage.sourceName + " because of filter.");
         }
       }
--- a/browser/base/content/test/general/browser_parsable_script.js
+++ b/browser/base/content/test/general/browser_parsable_script.js
@@ -78,32 +78,32 @@ add_task(function* checkAllTheJS() {
       return;
     }
     // Request a 10 minutes timeout (30 seconds * 20) for debug builds.
     requestLongerTimeout(20);
   }
 
   let uris;
   // If an absolute URI is specified on the command line, use it immediately.
-  if (parseValue && parseValue.contains(":")) {
+  if (parseValue && parseValue.includes(":")) {
     uris = [NetUtil.newURI(parseValue)];
   } else {
     let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
     // This asynchronously produces a list of URLs (sadly, mostly sync on our
     // test infrastructure because it runs against jarfiles there, and
     // our zipreader APIs are all sync)
     let startTimeMs = Date.now();
     info("Collecting URIs");
     uris = yield generateURIsFromDirTree(appDir, [".js", ".jsm"]);
     info("Collected URIs in " + (Date.now() - startTimeMs) + "ms");
 
     // Apply the filter specified on the command line, if any.
     if (parseValue) {
       uris = uris.filter(uri => {
-        if (uri.spec.contains(parseValue)) {
+        if (uri.spec.includes(parseValue)) {
           return true;
         }
         info("Not checking filtered out " + uri.spec);
         return false;
       });
     }
   }
 
--- a/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
+++ b/browser/base/content/test/general/browser_save_private_link_perwindowpb.js
@@ -19,17 +19,17 @@ function test() {
       onCacheStorageInfo: function(num, consumption)
       {
         info("disk storage contains " + num + " entries");
       },
       onCacheEntryInfo: function(uri)
       {
         var urispec = uri.asciiSpec;
         info(urispec);
-        is(urispec.contains(filename), false, "web content present in disk cache");
+        is(urispec.includes(filename), false, "web content present in disk cache");
       },
       onCacheEntryVisitCompleted: function()
       {
         goon();
       }
     };
     function Visitor() {}
 
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -465,107 +465,101 @@ registerCleanupFunction(() => waitForDoc
 
 let FullZoomHelper = {
 
   selectTabAndWaitForLocationChange: function selectTabAndWaitForLocationChange(tab) {
     if (!tab)
       throw new Error("tab must be given.");
     if (gBrowser.selectedTab == tab)
       return Promise.resolve();
-    gBrowser.selectedTab = tab;
-    return this.waitForLocationChange();
+
+    return Promise.all([BrowserTestUtils.switchTab(gBrowser, tab),
+                        this.waitForLocationChange()]);
   },
 
   removeTabAndWaitForLocationChange: function removeTabAndWaitForLocationChange(tab) {
     tab = tab || gBrowser.selectedTab;
     let selected = gBrowser.selectedTab == tab;
     gBrowser.removeTab(tab);
     if (selected)
       return this.waitForLocationChange();
     return Promise.resolve();
   },
 
   waitForLocationChange: function waitForLocationChange() {
-    let deferred = Promise.defer();
-    Services.obs.addObserver(function obs(subj, topic, data) {
-      Services.obs.removeObserver(obs, topic);
-      deferred.resolve();
-    }, "browser-fullZoom:location-change", false);
-    return deferred.promise;
+    return new Promise(resolve => {
+      Services.obs.addObserver(function obs(subj, topic, data) {
+        Services.obs.removeObserver(obs, topic);
+        resolve();
+      }, "browser-fullZoom:location-change", false);
+    });
   },
 
   load: function load(tab, url) {
-    let deferred = Promise.defer();
-    let didLoad = false;
-    let didZoom = false;
-
-    promiseTabLoadEvent(tab).then(event => {
-      didLoad = true;
-      if (didZoom)
-        deferred.resolve();
-    }, true);
+    return new Promise(resolve => {
+      let didLoad = false;
+      let didZoom = false;
 
-    this.waitForLocationChange().then(function () {
-      didZoom = true;
-      if (didLoad)
-        deferred.resolve();
+      promiseTabLoadEvent(tab).then(event => {
+        didLoad = true;
+        if (didZoom)
+          resolve();
+      }, true);
+
+      this.waitForLocationChange().then(function () {
+        didZoom = true;
+        if (didLoad)
+          resolve();
+      });
+
+      tab.linkedBrowser.loadURI(url);
     });
-
-    tab.linkedBrowser.loadURI(url);
-
-    return deferred.promise;
   },
 
   zoomTest: function zoomTest(tab, val, msg) {
     is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
   },
 
   enlarge: function enlarge() {
-    let deferred = Promise.defer();
-    FullZoom.enlarge(function () deferred.resolve());
-    return deferred.promise;
+    return new Promise(resolve => FullZoom.enlarge(resolve));
   },
 
   reduce: function reduce() {
-    let deferred = Promise.defer();
-    FullZoom.reduce(function () deferred.resolve());
-    return deferred.promise;
+    return new Promise(resolve => FullZoom.reduce(resolve));
   },
 
   reset: function reset() {
-    let deferred = Promise.defer();
-    FullZoom.reset(function () deferred.resolve());
-    return deferred.promise;
+    return new Promise(resolve => FullZoom.reset(resolve));
   },
 
   BACK: 0,
   FORWARD: 1,
   navigate: function navigate(direction) {
-    let deferred = Promise.defer();
-    let didPs = false;
-    let didZoom = false;
+    return new Promise(resolve => {
+      let didPs = false;
+      let didZoom = false;
 
-    gBrowser.addEventListener("pageshow", function (event) {
-      gBrowser.removeEventListener("pageshow", arguments.callee, true);
-      didPs = true;
-      if (didZoom)
-        deferred.resolve();
-    }, true);
+      gBrowser.addEventListener("pageshow", function (event) {
+        gBrowser.removeEventListener("pageshow", arguments.callee, true);
+        didPs = true;
+        if (didZoom)
+          resolve();
+      }, true);
 
-    if (direction == this.BACK)
-      gBrowser.goBack();
-    else if (direction == this.FORWARD)
-      gBrowser.goForward();
+      if (direction == this.BACK)
+        gBrowser.goBack();
+      else if (direction == this.FORWARD)
+        gBrowser.goForward();
 
-    this.waitForLocationChange().then(function () {
-      didZoom = true;
-      if (didPs)
-        deferred.resolve();
+      this.waitForLocationChange().then(function () {
+        didZoom = true;
+        if (didPs)
+          resolve();
+      });
     });
-    return deferred.promise;
   },
 
   failAndContinue: function failAndContinue(func) {
     return function (err) {
       ok(false, err);
       func();
     };
   },
--- a/browser/base/content/test/general/test_offline_gzip.html
+++ b/browser/base/content/test/general/test_offline_gzip.html
@@ -73,17 +73,17 @@ function handleMessageEvents(event) {
         // Sometimes document.body may not exist, and trying to access
         // it will throw an exception, so handle this case.
         try {
           var bodyInnerHTML = frames.testFrame.document.body.innerHTML;
         }
         catch (e) {
           var bodyInnerHTML = "";
         }
-        if (cacheCount == 2 || bodyInnerHTML.contains("error")) {
+        if (cacheCount == 2 || bodyInnerHTML.includes("error")) {
           clearInterval(intervalID);
           is(cacheCount, 2, "frame not reloaded successfully");
           if (cacheCount != 2) {
             finishTest();
           }
         }
       }, 100);
       break;
--- a/browser/base/content/test/newtab/browser_newtab_search.js
+++ b/browser/base/content/test/newtab/browser_newtab_search.js
@@ -299,17 +299,17 @@ function blobToBase64(blob) {
     }
     reader.onerror = reject;
     reader.readAsDataURL(blob);
   });
 }
 
 let checkCurrentEngine = Task.async(function* ({name: basename, logoPrefix1x, logoPrefix2x}) {
   let engine = Services.search.currentEngine;
-  ok(engine.name.contains(basename),
+  ok(engine.name.includes(basename),
      "Sanity check: current engine: engine.name=" + engine.name +
      " basename=" + basename);
 
   // gSearch.currentEngineName
   is(gSearch().currentEngineName, engine.name,
      "currentEngineName: " + engine.name);
 });
 
--- a/browser/base/content/test/plugins/browser_CTP_remove_navigate.js
+++ b/browser/base/content/test/plugins/browser_CTP_remove_navigate.js
@@ -70,13 +70,13 @@ add_task(function* () {
   let plugin = browser.contentDocument.getElementById("test");
   plugin.remove();
   yield loadPage(browser, gTestRoot + "plugin_small_2.html");
   let notification = yield waitForNotificationBar("plugin-hidden", browser);
   ok(notification, "There should be a notification shown for the new page.");
 
   // Ensure that the notification is showing information about
   // the x-second-test plugin.
-  ok(notification.label.contains("Second Test"), "Should mention the second plugin");
-  ok(!notification.label.contains("127.0.0.1"), "Should not refer to old principal");
-  ok(notification.label.contains("null"), "Should refer to the new principal");
+  ok(notification.label.includes("Second Test"), "Should mention the second plugin");
+  ok(!notification.label.includes("127.0.0.1"), "Should not refer to old principal");
+  ok(notification.label.includes("null"), "Should refer to the new principal");
   gBrowser.removeTab(newTab);
 });
--- a/browser/base/content/test/plugins/browser_bug797677.js
+++ b/browser/base/content/test/plugins/browser_bug797677.js
@@ -14,17 +14,17 @@ function test() {
   var newTab = gBrowser.addTab();
   gBrowser.selectedTab = newTab;
   gTestBrowser = gBrowser.selectedBrowser;
   gTestBrowser.addEventListener("PluginBindingAttached", pluginBindingAttached, true, true);
   var consoleService = Cc["@mozilla.org/consoleservice;1"]
                          .getService(Ci.nsIConsoleService);
   var errorListener = {
     observe: function(aMessage) {
-      if (aMessage.message.contains("NS_ERROR"))
+      if (aMessage.message.includes("NS_ERROR"))
         gConsoleErrors++;
     }
   };
   consoleService.registerListener(errorListener);
   registerCleanupFunction(function() {
     gTestBrowser.removeEventListener("PluginBindingAttached", pluginBindingAttached, true);
     consoleService.unregisterListener(errorListener);
     gBrowser.removeCurrentTab();
--- a/browser/base/content/test/popupNotifications/head.js
+++ b/browser/base/content/test/popupNotifications/head.js
@@ -302,10 +302,10 @@ function triggerSecondaryCommand(popup, 
       EventUtils.synthesizeKey("VK_DOWN", {});
     }
     // Activate
     EventUtils.synthesizeKey("VK_RETURN", {});
   }, false);
 
   // One down event to open the popup
   info("Open the popup to trigger secondary command for notification " + notification.id);
-  EventUtils.synthesizeKey("VK_DOWN", { altKey: !navigator.platform.contains("Mac") });
+  EventUtils.synthesizeKey("VK_DOWN", { altKey: !navigator.platform.includes("Mac") });
 }
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -518,17 +518,17 @@ file, You can obtain one at http://mozil
           var selectedVal = inputVal.substring(this.selectionStart, this.selectionEnd);
 
           // If the selection doesn't start at the beginning or doesn't span the full domain or
           // the URL bar is modified, nothing else to do here.
           if (this.selectionStart > 0 || this.valueIsTyped)
             return selectedVal;
           // The selection doesn't span the full domain if it doesn't contain a slash and is
           // followed by some character other than a slash.
-          if (!selectedVal.contains("/")) {
+          if (!selectedVal.includes("/")) {
             let remainder = inputVal.replace(selectedVal, "");
             if (remainder != "" && remainder[0] != "/")
               return selectedVal;
           }
 
           let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
 
           let uri;
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -429,17 +429,17 @@ const PanelUI = {
   _adjustLabelsForAutoHyphens: function(aNode) {
     let toolbarButtons = aNode ? [aNode] :
                                  this.contents.querySelectorAll(".toolbarbutton-1");
     for (let node of toolbarButtons) {
       let label = node.getAttribute("label");
       if (!label) {
         continue;
       }
-      if (label.contains("\u00ad")) {
+      if (label.includes("\u00ad")) {
         node.setAttribute("auto-hyphens", "off");
       } else {
         node.removeAttribute("auto-hyphens");
       }
     }
   },
 
   /**
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -413,18 +413,18 @@ HistoryDownloadElementShell.prototype = 
   // Returns whether or not the download handled by this shell should
   // show up in the search results for the given term.  Both the display
   // name for the download and the url are searched.
   matchesSearchTerm(aTerm) {
     if (!aTerm) {
       return true;
     }
     aTerm = aTerm.toLowerCase();
-    return this.displayName.toLowerCase().contains(aTerm) ||
-           this.download.source.url.toLowerCase().contains(aTerm);
+    return this.displayName.toLowerCase().includes(aTerm) ||
+           this.download.source.url.toLowerCase().includes(aTerm);
   },
 
   // Handles return keypress on the element (the keypress listener is
   // set in the DownloadsPlacesView object).
   doDefaultCommand() {
     function getDefaultCommandForState(aState) {
       switch (aState) {
         case nsIDM.DOWNLOAD_FINISHED:
--- a/browser/components/loop/LoopCalls.jsm
+++ b/browser/components/loop/LoopCalls.jsm
@@ -287,17 +287,17 @@ let LoopCallsInternal = {
         this.conversationInProgress.id = windowId;
       }
     };
 
     if (callData.type == "incoming" && ("callerId" in callData) &&
         EMAIL_OR_PHONE_RE.test(callData.callerId)) {
       LoopContacts.search({
         q: callData.callerId,
-        field: callData.callerId.contains("@") ? "email" : "tel"
+        field: callData.callerId.includes("@") ? "email" : "tel"
       }, (err, contacts) => {
         if (err) {
           // Database error, helas!
           openChat();
           return;
         }
 
         for (let contact of contacts) {
--- a/browser/components/loop/content/js/contacts.js
+++ b/browser/components/loop/content/js/contacts.js
@@ -564,18 +564,18 @@ loop.contacts = (function(_, mozL10n) {
       });
 
       let showFilter = Object.getOwnPropertyNames(this.contacts).length >=
                        MIN_CONTACTS_FOR_FILTERING;
       if (showFilter) {
         let filter = this.state.filter.trim().toLocaleLowerCase();
         if (filter) {
           let filterFn = contact => {
-            return contact.name[0].toLocaleLowerCase().contains(filter) ||
-                   getPreferred(contact, "email").value.toLocaleLowerCase().contains(filter);
+            return contact.name[0].toLocaleLowerCase().includes(filter) ||
+                   getPreferred(contact, "email").value.toLocaleLowerCase().includes(filter);
           };
           if (shownContacts.available) {
             shownContacts.available = shownContacts.available.filter(filterFn);
           }
           if (shownContacts.blocked) {
             shownContacts.blocked = shownContacts.blocked.filter(filterFn);
           }
         }
--- a/browser/components/loop/content/js/contacts.jsx
+++ b/browser/components/loop/content/js/contacts.jsx
@@ -564,18 +564,18 @@ loop.contacts = (function(_, mozL10n) {
       });
 
       let showFilter = Object.getOwnPropertyNames(this.contacts).length >=
                        MIN_CONTACTS_FOR_FILTERING;
       if (showFilter) {
         let filter = this.state.filter.trim().toLocaleLowerCase();
         if (filter) {
           let filterFn = contact => {
-            return contact.name[0].toLocaleLowerCase().contains(filter) ||
-                   getPreferred(contact, "email").value.toLocaleLowerCase().contains(filter);
+            return contact.name[0].toLocaleLowerCase().includes(filter) ||
+                   getPreferred(contact, "email").value.toLocaleLowerCase().includes(filter);
           };
           if (shownContacts.available) {
             shownContacts.available = shownContacts.available.filter(filterFn);
           }
           if (shownContacts.blocked) {
             shownContacts.blocked = shownContacts.blocked.filter(filterFn);
           }
         }
--- a/browser/components/loop/test/shared/mixins_test.js
+++ b/browser/components/loop/test/shared/mixins_test.js
@@ -224,19 +224,19 @@ describe("loop.shared.mixins", function(
       };
 
       sharedMixins.setRootObject(rootObject);
 
       view = TestUtils.renderIntoDocument(React.createElement(TestComp));
 
       sandbox.stub(view, "getDOMNode").returns({
         querySelector: function(classSelector) {
-          if (classSelector.contains("local")) {
+          if (classSelector.includes("local")) {
             return localElement;
-          } else if (classSelector.contains("screen")) {
+          } else if (classSelector.includes("screen")) {
             return screenShareElement;
           }
           return remoteElement;
         }
       });
     });
 
     afterEach(function() {
--- a/browser/components/loop/test/xpcshell/test_loopservice_token_send.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_token_send.js
@@ -8,21 +8,21 @@ add_test(function test_registration_uses
   loopServer.registerPathHandler("/registration", (request, response) => {
     // Check that we have an Authorization header with the correct bits. The
     // translation of values are tested in different modules, for the components
     // that we use.
     // XXX In future, we should reconsider our stubbing model, and possibly stub
     // components/interfaces at a higher level.
     let header = request.getHeader("Authorization");
 
-    Assert.notEqual(header.contains("Hawk id="), -1, "Should contain a hawk id");
-    Assert.notEqual(header.contains("ts="), -1, "Should contain a timestamp");
-    Assert.notEqual(header.contains("nonce="), -1, "Should contain a nonce");
-    Assert.notEqual(header.contains("hash="), -1, "Should contain a hash");
-    Assert.notEqual(header.contains("mac="), -1, "Should contain a mac");
+    Assert.notEqual(header.includes("Hawk id="), -1, "Should contain a hawk id");
+    Assert.notEqual(header.includes("ts="), -1, "Should contain a timestamp");
+    Assert.notEqual(header.includes("nonce="), -1, "Should contain a nonce");
+    Assert.notEqual(header.includes("hash="), -1, "Should contain a hash");
+    Assert.notEqual(header.includes("mac="), -1, "Should contain a mac");
 
     response.setStatusLine(null, 200, "OK");
     response.processAsync();
     response.finish();
   });
 
   MozLoopService.promiseRegisteredWithServers().then(() => {
     run_next_test();
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1794,17 +1794,17 @@ BrowserGlue.prototype = {
     }
 
     if (currentUIVersion < 12) {
       // Remove bookmarks-menu-button-container, then place
       // bookmarks-menu-button into its position.
       let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
       // Need to migrate only if toolbar is customized.
       if (currentset) {
-        if (currentset.contains("bookmarks-menu-button-container")) {
+        if (currentset.includes("bookmarks-menu-button-container")) {
           currentset = currentset.replace(/(^|,)bookmarks-menu-button-container($|,)/,
                                           "$1bookmarks-menu-button$2");
           xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
         }
       }
     }
 
     if (currentUIVersion < 14) {
@@ -1822,23 +1822,23 @@ BrowserGlue.prototype = {
     }
 
     // Insert the bookmarks-menu-button into the nav-bar if it isn't already
     // there.
     if (currentUIVersion < 17) {
       let currentset = xulStore.getValue(BROWSER_DOCURL, "nav-bar", "currentset");
       // Need to migrate only if toolbar is customized.
       if (currentset) {
-        if (!currentset.contains("bookmarks-menu-button")) {
+        if (!currentset.includes("bookmarks-menu-button")) {
           // The button isn't in the nav-bar, so let's look for an appropriate
           // place to put it.
-          if (currentset.contains("downloads-button")) {
+          if (currentset.includes("downloads-button")) {
             currentset = currentset.replace(/(^|,)downloads-button($|,)/,
                                             "$1bookmarks-menu-button,downloads-button$2");
-          } else if (currentset.contains("home-button")) {
+          } else if (currentset.includes("home-button")) {
             currentset = currentset.replace(/(^|,)home-button($|,)/,
                                             "$1bookmarks-menu-button,home-button$2");
           } else {
             // Just append.
             currentset = currentset.replace(/(^|,)window-controls($|,)/,
                                             "$1bookmarks-menu-button,window-controls$2")
           }
           xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -587,17 +587,17 @@
       <handler event="popupshown" phase="target"><![CDATA[
         this.setAttribute("panelopen", "true");
         let disablePointerEvents;
         if (!this.hasAttribute("disablepointereventsfortransition")) {
           let container = document.getAnonymousElementByAttribute(this, "anonid", "container");
           let cs = getComputedStyle(container);
           let transitionProp = cs.transitionProperty;
           let transitionTime = parseFloat(cs.transitionDuration);
-          disablePointerEvents = (transitionProp.contains("transform") ||
+          disablePointerEvents = (transitionProp.includes("transform") ||
                                   transitionProp == "all") &&
                                  transitionTime > 0;
           this.setAttribute("disablepointereventsfortransition", disablePointerEvents);
         } else {
           disablePointerEvents = this.getAttribute("disablepointereventsfortransition") == "true";
         }
         if (!disablePointerEvents) {
           this.style.removeProperty("pointer-events");
--- a/browser/components/places/tests/browser/browser_bookmarksProperties.js
+++ b/browser/components/places/tests/browser/browser_bookmarksProperties.js
@@ -245,17 +245,16 @@ gTests.push({
     PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["testTag"]);
     PlacesUtils.bookmarks.removeItem(this._itemId);
   }
 });
 
 
 //------------------------------------------------------------------------------
 // Bug 475529 -  Add button in new folder dialog not default anymore
-/*
 gTests.push({
   desc: "Bug 475529 - Add button in new folder dialog not default anymore",
   sidebar: SIDEBAR_BOOKMARKS_ID,
   action: ACTION_ADD,
   itemType: TYPE_FOLDER,
   window: null,
   _itemId: null,
 
@@ -281,16 +280,17 @@ gTests.push({
       self.window.removeEventListener("unload", arguments.callee, false);
       executeSoon(function () {
         self.finish();
       });
     }, false);
 
     info("About to focus the namePicker field");
     namePicker.focus();
+    namePicker.select();
     EventUtils.synthesizeKey("n", {}, this.window);
     EventUtils.synthesizeKey("VK_RETURN", {}, this.window);
   },
 
   finish: function() {
     // Window is already closed.
     SidebarUI.hide();
     runNextTest();
@@ -300,17 +300,16 @@ gTests.push({
     // Check that folder name has been changed.
     is(PlacesUtils.bookmarks.getItemTitle(this._itemId), "n",
        "Folder name has been edited");
 
     // Cleanup.
     PlacesUtils.bookmarks.removeItem(this._itemId);
   }
 });
-*/
 
 //------------------------------------------------------------------------------
 // Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel
 
 gTests.push({
   desc: "Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel",
   sidebar: SIDEBAR_BOOKMARKS_ID,
   action: ACTION_EDIT,
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -1,15 +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/. */
 
 Components.utils.import("resource://gre/modules/Downloads.jsm");
 Components.utils.import("resource://gre/modules/FileUtils.jsm");
 Components.utils.import("resource://gre/modules/Task.jsm");
+Components.utils.import("resource:///modules/TransientPrefs.jsm");
 
 var gMainPane = {
   /**
    * Initialization of this.
    */
   init: function ()
   {
     function setEventListener(aId, aEventType, aCallback)
@@ -42,16 +43,25 @@ var gMainPane = {
       let sysInfo = Cc["@mozilla.org/system-info;1"].
                     getService(Ci.nsIPropertyBag2);
       let ver = parseFloat(sysInfo.getProperty("version"));
       let showTabsInTaskbar = document.getElementById("showTabsInTaskbar");
       showTabsInTaskbar.hidden = ver < 6.1;
     } catch (ex) {}
 #endif
 
+    // The "closing multiple tabs" and "opening multiple tabs might slow down
+    // &brandShortName;" warnings provide options for not showing these
+    // warnings again. When the user disabled them, we provide checkboxes to
+    // re-enable the warnings.
+    if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnClose"))
+      document.getElementById("warnCloseMultiple").hidden = true;
+    if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnOpen"))
+      document.getElementById("warnOpenMany").hidden = true;
+
     setEventListener("browser.privatebrowsing.autostart", "change",
                      gMainPane.updateBrowserStartupLastSession);
     setEventListener("browser.download.dir", "change",
                      gMainPane.displayDownloadDirPref);
 #ifdef HAVE_SHELL_SERVICE
     setEventListener("setDefaultButton", "command",
                      gMainPane.setDefaultBrowser);
 #endif
--- a/browser/components/preferences/tabs.js
+++ b/browser/components/preferences/tabs.js
@@ -21,32 +21,41 @@ var gTabsPane = {
    *   allowed to cancel the action, false to just close the window
    * browser.tabs.warnOnOpen
    * - true if the user should be warned if he attempts to open a lot of tabs at
    *   once (e.g. a large folder of bookmarks), false otherwise
    * browser.taskbar.previews.enable
    * - true if tabs are to be shown in the Windows 7 taskbar
    */
 
+  init: function () {
 #ifdef XP_WIN
-  /**
-   * Initialize any platform-specific UI.
-   */
-  init: function () {
     const Cc = Components.classes;
     const Ci = Components.interfaces;
     try {
       let sysInfo = Cc["@mozilla.org/system-info;1"].
                     getService(Ci.nsIPropertyBag2);
       let ver = parseFloat(sysInfo.getProperty("version"));
       let showTabsInTaskbar = document.getElementById("showTabsInTaskbar");
       showTabsInTaskbar.hidden = ver < 6.1;
     } catch (ex) {}
+#endif
+
+    // The "closing multiple tabs" and "opening multiple tabs might slow down
+    // &brandShortName;" warnings provide options for not showing these
+    // warnings again. When the user disabled them, we provide checkboxes to
+    // re-enable the warnings.
+    let TransientPrefs =
+      Components.utils.import("resource:///modules/TransientPrefs.jsm", {})
+                .TransientPrefs;
+    if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnClose"))
+      document.getElementById("warnCloseMultiple").hidden = true;
+    if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnOpen"))
+      document.getElementById("warnOpenMany").hidden = true;
   },
-#endif
 
   /**
    * Determines where a link which opens a new window will open.
    *
    * @returns |true| if such links should be opened in new tabs
    */
   readLinkTarget: function() {
     var openNewWindow = document.getElementById("browser.link.open_newwindow");
--- a/browser/components/preferences/tabs.xul
+++ b/browser/components/preferences/tabs.xul
@@ -11,19 +11,17 @@
 <!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences/tabs.dtd">
 %tabsDTD;
 ]>
 
 <overlay id="TabsPaneOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <prefpane id="paneTabs"
-#ifdef XP_WIN
             onpaneload="gTabsPane.init();"
-#endif
             helpTopic="prefs-tabs">
 
     <preferences id="tabsPreferences">
       <preference id="browser.link.open_newwindow"     name="browser.link.open_newwindow"     type="int"/>
       <preference id="browser.tabs.loadInBackground"   name="browser.tabs.loadInBackground"   type="bool" inverted="true"/>
       <preference id="browser.tabs.warnOnClose"        name="browser.tabs.warnOnClose"        type="bool"/>
       <preference id="browser.tabs.warnOnOpen"         name="browser.tabs.warnOnOpen"         type="bool"/>
       <preference id="browser.sessionstore.restore_on_demand" name="browser.sessionstore.restore_on_demand" type="bool"/>
--- a/browser/components/sessionstore/test/browser_454908.js
+++ b/browser/components/sessionstore/test/browser_454908.js
@@ -38,15 +38,15 @@ add_task(function* test_dont_save_passwo
   is(username, usernameValue, "username was saved/restored");
   let passwd = yield getInputValue(browser, {id: "passwd"});
   is(passwd, "", "password wasn't saved/restored");
 
   // Write to disk and read our file.
   yield forceSaveState();
   yield promiseForEachSessionRestoreFile((state, key) =>
     // Ensure that we have not saved our password.
-    ok(!state.contains(PASS), "password has not been written to file " + key)
+    ok(!state.includes(PASS), "password has not been written to file " + key)
   );
 
 
   // Cleanup.
   gBrowser.removeTab(tab);
 });
--- a/browser/components/tabview/test/browser_tabview_bug626455.js
+++ b/browser/components/tabview/test/browser_tabview_bug626455.js
@@ -40,17 +40,17 @@ function testStayOnPage(win, blockingTab
     executeSoon(function () {
       showTabView(function () {
         is(win.gBrowser.tabs.length, 1,
            "The total number of tab is 1 when staying on the page");
 
         // The other initial tab has been closed when trying to close the tab
         // group. The only tab left is the one with the onbeforeunload dialog.
         let url = win.gBrowser.browsers[0].currentURI.spec;
-        ok(url.contains("onbeforeunload"), "The open tab is the expected one");
+        ok(url.includes("onbeforeunload"), "The open tab is the expected one");
 
         is(contentWindow.GroupItems.getActiveGroupItem(), activeGroup,
            "Active group is still the same");
 
         is(contentWindow.GroupItems.groupItems.length, 1,
            "Only one group is open");
 
         // start the next test
--- a/browser/components/test/browser_polaris_prefs.js
+++ b/browser/components/test/browser_polaris_prefs.js
@@ -19,17 +19,17 @@ function* assertPref(pref, enabled) {
 
 function* testPrefs(test) {
   for (let pref of prefs) {
     yield test(pref);
   }
 }
 
 function isNightly() {
-  return Services.appinfo.version.contains("a1");
+  return Services.appinfo.version.includes("a1");
 }
 
 add_task(function* test_default_values() {
   if (!isNightly()) {
     ok(true, "Skipping test, not Nightly")
     return;
   }
   Assert.ok(!Services.prefs.getBoolPref(POLARIS_ENABLED), POLARIS_ENABLED + " is disabled by default.");
--- a/browser/components/translation/BingTranslator.jsm
+++ b/browser/components/translation/BingTranslator.jsm
@@ -130,18 +130,18 @@ this.BingTranslator.prototype = {
    * request left.
    *
    * @param   aError   [optional] The XHR object of the request that failed.
    */
   _chunkFailed: function(aError) {
     if (aError instanceof Ci.nsIXMLHttpRequest &&
         [400, 401].indexOf(aError.status) != -1) {
       let body = aError.responseText;
-      if (body && body.contains("TranslateApiException") &&
-          (body.contains("balance") || body.contains("active state")))
+      if (body && body.includes("TranslateApiException") &&
+          (body.includes("balance") || body.includes("active state")))
         this._serviceUnavailable = true;
     }
 
     this._checkIfFinished();
   },
 
   /**
    * Function called when a request sent to the server has completed.
--- a/browser/components/translation/test/bing.sjs
+++ b/browser/components/translation/test/bing.sjs
@@ -125,17 +125,17 @@ function checkAuth(req) {
   if (!req.hasHeader("Authorization"))
     throw new HTTPError(401, "No Authorization header provided.");
 
   let auth = req.getHeader("Authorization");
   if (!auth.startsWith("Bearer "))
     throw new HTTPError(401, "Invalid Authorization header content: '" + auth + "'");
 
   // Rejecting inactive subscriptions.
-  if (auth.contains("inactive")) {
+  if (auth.includes("inactive")) {
     const INACTIVE_STATE_RESPONSE = "<html><body><h1>TranslateApiException</h1><p>Method: TranslateArray()</p><p>Message: The Azure Market Place Translator Subscription associated with the request credentials is not in an active state.</p><code></code><p>message id=5641.V2_Rest.TranslateArray.48CC6470</p></body></html>";
     throw new HTTPError(401, INACTIVE_STATE_RESPONSE);
   }
 
 }
 
 function reallyHandleRequest(req, res) {
   log("method: " + req.method);
--- a/browser/components/translation/test/browser_translation_exceptions.js
+++ b/browser/components/translation/test/browser_translation_exceptions.js
@@ -67,17 +67,17 @@ function openPopup(aPopup) {
   aPopup.addEventListener("popupshown", function popupShown() {
     aPopup.removeEventListener("popupshown", popupShown);
     deferred.resolve();
   });
 
   aPopup.focus();
   // One down event to open the popup.
   EventUtils.synthesizeKey("VK_DOWN",
-                           { altKey: !navigator.platform.contains("Mac") });
+                           { altKey: !navigator.platform.includes("Mac") });
 
   return deferred.promise;
 }
 
 function waitForWindowLoad(aWin) {
   let deferred = Promise.defer();
 
   aWin.addEventListener("load", function onload() {
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -420,17 +420,17 @@ this.UITour = {
         // The rest is only relevant if Telemetry is enabled.
         if (!UITelemetry.enabled) {
           log.debug("registerPageID: Telemetry disabled, not doing anything");
           break;
         }
 
         // We don't want to allow BrowserUITelemetry.BUCKET_SEPARATOR in the
         // pageID, as it could make parsing the telemetry bucket name difficult.
-        if (data.pageID.contains(BrowserUITelemetry.BUCKET_SEPARATOR)) {
+        if (data.pageID.includes(BrowserUITelemetry.BUCKET_SEPARATOR)) {
           log.warn("registerPageID: Invalid page ID specified");
           break;
         }
 
         this.addSeenPageID(data.pageID);
         this.pageIDSourceBrowsers.set(browser, data.pageID);
         this.setTelemetryBucket(data.pageID);
 
--- a/browser/devtools/canvasdebugger/callslist.js
+++ b/browser/devtools/canvasdebugger/callslist.js
@@ -348,20 +348,20 @@ let CallsListView = Heritage.extend(Widg
 
     this.filterContents(e => {
       let call = e.attachment.actor;
       let name = call.name.toLowerCase();
       let file = call.file.toLowerCase();
       let line = call.line.toString().toLowerCase();
       let args = call.argsPreview.toLowerCase();
 
-      return name.contains(lowerCaseSearchToken) ||
-             file.contains(lowerCaseSearchToken) ||
-             line.contains(lowerCaseSearchToken) ||
-             args.contains(lowerCaseSearchToken);
+      return name.includes(lowerCaseSearchToken) ||
+             file.includes(lowerCaseSearchToken) ||
+             line.includes(lowerCaseSearchToken) ||
+             args.includes(lowerCaseSearchToken);
     });
   },
 
   /**
    * The wheel listener for the filmstrip that contains all the thumbnails.
    */
   _onScroll: function(e) {
     this._filmstrip.scrollLeft += e.deltaX;
--- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-03.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-03.js
@@ -60,16 +60,16 @@ function ifTestingSupported() {
   is(functionCalls[7].type, CallWatcherFront.METHOD_FUNCTION,
     "The last called function is correctly identified as a method.");
   is(functionCalls[7].name, "requestAnimationFrame",
     "The last called function's name is correct.");
   is(functionCalls[7].file, SIMPLE_CANVAS_URL,
     "The last called function's file is correct.");
   is(functionCalls[7].line, 30,
     "The last called function's line is correct.");
-  ok(functionCalls[7].argsPreview.contains("Function"),
+  ok(functionCalls[7].argsPreview.includes("Function"),
     "The last called function's args preview is correct.");
   is(functionCalls[7].callerPreview, "",
     "The last called function's caller preview is correct.");
 
   yield removeTab(target.tab);
   finish();
 }
--- a/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-11.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-actor-test-11.js
@@ -60,17 +60,17 @@ function ifTestingSupported() {
   is(functionCalls[7].type, CallWatcherFront.METHOD_FUNCTION,
     "The last called function is correctly identified as a method.");
   is(functionCalls[7].name, "setTimeout",
     "The last called function's name is correct.");
   is(functionCalls[7].file, SET_TIMEOUT_URL,
     "The last called function's file is correct.");
   is(functionCalls[7].line, 30,
     "The last called function's line is correct.");
-  ok(functionCalls[7].argsPreview.contains("Function"),
+  ok(functionCalls[7].argsPreview.includes("Function"),
     "The last called function's args preview is correct.");
   is(functionCalls[7].callerPreview, "",
     "The last called function's caller preview is correct.");
 
   let firstNonDrawCall = yield functionCalls[1].getDetails();
   let secondNonDrawCall = yield functionCalls[3].getDetails();
   let lastNonDrawCall = yield functionCalls[7].getDetails();
 
--- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
@@ -27,26 +27,26 @@ function ifTestingSupported() {
   yield callStackDisplayed;
 
   isnot($(".call-item-stack", callItem.target), null,
     "There should be a stack container available now for the draw call.");
   is($all(".call-item-stack-fn", callItem.target).length, 4,
     "There should be 4 functions on the stack for the draw call.");
 
   ok($all(".call-item-stack-fn-name", callItem.target)[0].getAttribute("value")
-    .contains("C()"),
+    .includes("C()"),
     "The first function on the stack has the correct name.");
   ok($all(".call-item-stack-fn-name", callItem.target)[1].getAttribute("value")
-    .contains("B()"),
+    .includes("B()"),
     "The second function on the stack has the correct name.");
   ok($all(".call-item-stack-fn-name", callItem.target)[2].getAttribute("value")
-    .contains("A()"),
+    .includes("A()"),
     "The third function on the stack has the correct name.");
   ok($all(".call-item-stack-fn-name", callItem.target)[3].getAttribute("value")
-    .contains("drawRect()"),
+    .includes("drawRect()"),
     "The fourth function on the stack has the correct name.");
 
   is($all(".call-item-stack-fn-location", callItem.target)[0].getAttribute("value"),
     "doc_simple-canvas-deep-stack.html:26",
     "The first function on the stack has the correct location.");
   is($all(".call-item-stack-fn-location", callItem.target)[1].getAttribute("value"),
     "doc_simple-canvas-deep-stack.html:28",
     "The second function on the stack has the correct location.");
--- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-screenshots.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-img-screenshots.js
@@ -21,14 +21,14 @@ function ifTestingSupported() {
     "The screenshot container should now be visible.");
 
   is($("#screenshot-dimensions").getAttribute("value"), "128" + "\u00D7" + "128",
     "The screenshot dimensions label has the expected value.");
 
   is($("#screenshot-image").getAttribute("flipped"), "false",
     "The screenshot element should not be flipped vertically.");
 
-  ok(window.getComputedStyle($("#screenshot-image")).backgroundImage.contains("#screenshot-rendering"),
+  ok(window.getComputedStyle($("#screenshot-image")).backgroundImage.includes("#screenshot-rendering"),
     "The screenshot element should have an offscreen canvas element as a background.");
 
   yield teardown(panel);
   finish();
 }
--- a/browser/devtools/commandline/test/browser_cmd_appcache_valid.js
+++ b/browser/devtools/commandline/test/browser_cmd_appcache_valid.js
@@ -84,17 +84,17 @@ function* spawnTest() {
         args: {
           search: { value: 'page' },
         }
       },
       exec: {
         output: [ /page1/, /page2/, /page3/ ]
       },
       post: function(output, text) {
-        ok(!text.contains("index"), "index is not contained in output");
+        ok(!text.includes("index"), "index is not contained in output");
       }
     },
 
     {
       setup: 'appcache validate',
       check: {
         input:  'appcache validate',
         markup: 'VVVVVVVVVVVVVVVVV',
@@ -144,20 +144,20 @@ function* spawnTest() {
         markup: 'VVVVVVVVVVVVV',
         status: 'VALID',
         args: {},
       },
       exec: {
         output: [ /no results/ ]
       },
       post: function(output, text) {
-        ok(!text.contains("index"), "index is not contained in output");
-        ok(!text.contains("page1"), "page1 is not contained in output");
-        ok(!text.contains("page2"), "page1 is not contained in output");
-        ok(!text.contains("page3"), "page1 is not contained in output");
+        ok(!text.includes("index"), "index is not contained in output");
+        ok(!text.includes("page1"), "page1 is not contained in output");
+        ok(!text.includes("page2"), "page1 is not contained in output");
+        ok(!text.includes("page3"), "page1 is not contained in output");
       }
     },
 
     {
       setup: 'appcache viewentry --key ' + TEST_URI,
       check: {
         input:  'appcache viewentry --key ' + TEST_URI,
               // appcache viewentry --key http://sub1.test2.example.com/browser/browser/devtools/commandline/test/browser_cmd_appcache_valid_index.html
--- a/browser/devtools/commandline/test/browser_cmd_cookie.js
+++ b/browser/devtools/commandline/test/browser_cmd_cookie.js
@@ -121,50 +121,50 @@ function test() {
         exec: { },
       },
       {
         setup: "cookie list",
         exec: {
           output: [ /zap=zep/, /zup=banana/, /Edit/ ]
         },
         post: function(output, text) {
-          ok(!text.contains("zip"), "");
-          ok(!text.contains("zop"), "");
+          ok(!text.includes("zip"), "");
+          ok(!text.includes("zop"), "");
         }
       },
       {
         setup: "cookie remove zap",
         exec: { },
       },
       {
         setup: "cookie list",
         exec: {
           output: [ /zup=banana/, /Edit/ ]
         },
         post: function(output, text) {
-          ok(!text.contains("zap"), "");
-          ok(!text.contains("zep"), "");
-          ok(!text.contains("zip"), "");
-          ok(!text.contains("zop"), "");
+          ok(!text.includes("zap"), "");
+          ok(!text.includes("zep"), "");
+          ok(!text.includes("zip"), "");
+          ok(!text.includes("zop"), "");
         }
       },
       {
         setup: "cookie remove zup",
         exec: { }
       },
       {
         setup: "cookie list",
         exec: {
           output: 'No cookies found for host example.com'
         },
         post: function(output, text) {
-          ok(!text.contains("zap"), "");
-          ok(!text.contains("zep"), "");
-          ok(!text.contains("zip"), "");
-          ok(!text.contains("zop"), "");
-          ok(!text.contains("zup"), "");
-          ok(!text.contains("banana"), "");
-          ok(!text.contains("Edit"), "");
+          ok(!text.includes("zap"), "");
+          ok(!text.includes("zep"), "");
+          ok(!text.includes("zip"), "");
+          ok(!text.includes("zop"), "");
+          ok(!text.includes("zup"), "");
+          ok(!text.includes("banana"), "");
+          ok(!text.includes("Edit"), "");
         }
       },
     ]);
   }).then(finish, helpers.handleError);
 }
--- a/browser/devtools/debugger/test/browser_dbg_addonactor.js
+++ b/browser/devtools/debugger/test/browser_dbg_addonactor.js
@@ -67,17 +67,17 @@ function testDebugger() {
 }
 
 function testSources() {
   let deferred = promise.defer();
 
   gThreadClient.getSources(aResponse => {
     // source URLs contain launch-specific temporary directory path,
     // hence the ".contains" call.
-    const matches = aResponse.sources.filter(s => s.url.contains(ADDON_MODULE_URL));
+    const matches = aResponse.sources.filter(s => s.url.includes(ADDON_MODULE_URL));
     ok(matches.length > 0,
        "the main script of the addon is present in the source list");
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js
@@ -46,17 +46,17 @@ function test(){
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       })
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n  "),
+  ok(!gEditor.getText().includes("\n  "),
     "The source shouldn't be pretty printed yet.");
 }
 
 function testSecondSourceLabel(){
   let source = gSources.selectedItem.attachment.source;
   ok(source.url === EXAMPLE_URL + gSecondSourceLabel,
     "Second source url is correct.");
 }
@@ -88,17 +88,17 @@ function enableAutoPrettyPrint(){
 function testAutoPrettyPrintOff(){
   is(gPrefs.autoPrettyPrint, false,
     "The auto-pretty-print pref should be off.");
   isnot(gOptions._autoPrettyPrint.getAttribute("checked"), "true",
        "The Auto pretty print menu item should not be checked.");
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n  "),
+  ok(gEditor.getText().includes("\n  "),
     "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
--- a/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-02.js
@@ -58,17 +58,17 @@ function test(){
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       })
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n  "),
+  ok(!gEditor.getText().includes("\n  "),
     "The source shouldn't be pretty printed yet.");
 }
 
 function testFirstSourceLabel(){
   let source = gSources.selectedItem.attachment.source;
   ok(source.url === EXAMPLE_URL + gFirstSourceLabel,
     "First source url is correct.");
 }
@@ -96,17 +96,17 @@ function disableAutoPrettyPrint(){
   gOptions._toggleAutoPrettyPrint();
   gOptions._onPopupHidden();
   info("Disabled auto pretty printing.");
   // Wait for the pref update to be communicated to the server.
   return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n  "),
+  ok(gEditor.getText().includes("\n  "),
     "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gDebuggee = null;
   gPanel = null;
   gDebugger = null;
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-03.js
@@ -47,17 +47,17 @@ function test() {
       yield ensureThreadClientState(aPanel, "resumed");
       yield closeDebuggerAndFinish(aPanel);
     });
 
     function testEventItem(index, label, type, selectors, checked) {
       let item = gEvents.items[index];
       let node = item.target;
 
-      ok(item.attachment.url.contains(label),
+      ok(item.attachment.url.includes(label),
         "The event at index " + index + " has the correct url.");
       is(item.attachment.type, type,
         "The event at index " + index + " has the correct type.");
       is(item.attachment.selectors.toString(), selectors,
         "The event at index " + index + " has the correct selectors.");
       is(item.attachment.checkboxState, checked,
         "The event at index " + index + " has the correct checkbox state.");
 
--- a/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
+++ b/browser/devtools/debugger/test/browser_dbg_breakpoints-contextmenu.js
@@ -96,42 +96,53 @@ function test() {
     ok(isCaretPos(gPanel, 9),
       "The editor location is correct before pausing.");
 
     sendMouseClickToTab(gTab, content.document.querySelector("button"));
 
     return finished;
   }
 
-  function initialChecks() {
+  let initialChecks = Task.async(function*() {
     for (let source of gSources) {
       for (let breakpoint of source) {
         ok(gBreakpoints._getAdded(breakpoint.attachment),
           "All breakpoint items should have corresponding promises (1).");
         ok(!gBreakpoints._getRemoving(breakpoint.attachment),
           "All breakpoint items should have corresponding promises (2).");
         ok(breakpoint.attachment.actor,
           "All breakpoint items should have corresponding promises (3).");
         is(!!breakpoint.attachment.disabled, false,
           "All breakpoints should initially be enabled.");
 
         let prefix = "bp-cMenu-"; // "breakpoints context menu"
         let identifier = gBreakpoints.getIdentifier(breakpoint.attachment);
         let enableSelfId = prefix + "enableSelf-" + identifier + "-menuitem";
         let disableSelfId = prefix + "disableSelf-" + identifier + "-menuitem";
 
+        // Check to make sure that only the bp context menu is shown when right clicking
+        // this node (Bug 1159276).
+        let menu = gDebugger.document.getElementById("bp-mPop-" + identifier);
+        let contextMenuShown = once(gDebugger.document, "popupshown");
+        EventUtils.synthesizeMouseAtCenter(breakpoint.prebuiltNode, {type: 'contextmenu', button: 2}, gDebugger);
+        let event = yield contextMenuShown;
+        is (event.originalTarget.id, menu.id, "The correct context menu was shown");
+        let contextMenuHidden = once(gDebugger.document, "popuphidden");
+        menu.hidePopup();
+        yield contextMenuHidden;
+
         is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
           "The 'Enable breakpoint' context menu item should initially be hidden'.");
         ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
           "The 'Disable breakpoint' context menu item should initially not be hidden'.");
         is(breakpoint.attachment.view.checkbox.getAttribute("checked"), "true",
           "All breakpoints should initially have a checked checkbox.");
       }
     }
-  }
+  });
 
   function checkBreakpointToggleSelf(aIndex) {
     let deferred = promise.defer();
 
     EventUtils.sendMouseEvent({ type: "click" },
       gDebugger.document.querySelectorAll(".dbg-breakpoint")[aIndex],
       gDebugger);
 
--- a/browser/devtools/debugger/test/browser_dbg_file-reload.js
+++ b/browser/devtools/debugger/test/browser_dbg_file-reload.js
@@ -17,17 +17,17 @@ function test() {
 
     Task.spawn(function() {
       yield waitForSourceShown(aPanel, JS_URL);
 
       is(gSources.itemCount, 1,
         "There should be one source displayed in the view.")
       is(getSelectedSourceURL(gSources), JS_URL,
         "The correct source is currently selected in the view.");
-      ok(gEditor.getText().contains("bacon"),
+      ok(gEditor.getText().includes("bacon"),
         "The currently shown source contains bacon. Mmm, delicious!");
 
       let { source } = gSources.selectedItem.attachment;
       let [, firstText] = yield gControllerSources.getText(source);
       let firstNumber = parseFloat(firstText.match(/\d\.\d+/)[0]);
 
       is(firstText, gEditor.getText(),
         "gControllerSources.getText() returned the expected contents.");
@@ -35,17 +35,17 @@ function test() {
         "The generated number seems to be created correctly.");
 
       yield reloadActiveTab(aPanel, gDebugger.EVENTS.SOURCE_SHOWN);
 
       is(gSources.itemCount, 1,
         "There should be one source displayed in the view after reloading.")
       is(getSelectedSourceURL(gSources), JS_URL,
         "The correct source is currently selected in the view after reloading.");
-      ok(gEditor.getText().contains("bacon"),
+      ok(gEditor.getText().includes("bacon"),
         "The newly shown source contains bacon. Mmm, delicious!");
 
       ({ source } = gSources.selectedItem.attachment);
       let [, secondText] = yield gControllerSources.getText(source);
       let secondNumber = parseFloat(secondText.match(/\d\.\d+/)[0]);
 
       is(secondText, gEditor.getText(),
         "gControllerSources.getText() returned the expected contents.");
--- a/browser/devtools/debugger/test/browser_dbg_globalactor.js
+++ b/browser/devtools/debugger/test/browser_dbg_globalactor.js
@@ -22,17 +22,17 @@ function test() {
   gClient = new DebuggerClient(transport);
   gClient.connect((aType, aTraits) => {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     gClient.listTabs(aResponse => {
       let globalActor = aResponse.testGlobalActor1;
       ok(globalActor, "Found the test tab actor.")
-      ok(globalActor.contains("test_one"),
+      ok(globalActor.includes("test_one"),
         "testGlobalActor1's actorPrefix should be used.");
 
       gClient.request({ to: globalActor, type: "ping" }, aResponse => {
         is(aResponse.pong, "pong", "Actor should respond to requests.");
 
         // Send another ping to see if the same actor is used.
         gClient.request({ to: globalActor, type: "ping" }, aResponse => {
           is(aResponse.pong, "pong", "Actor should respond to requests.");
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-01.js
@@ -32,45 +32,45 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n  "),
+  ok(!gEditor.getText().includes("\n  "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 function testProgressBarShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 2, "The progress bar should be shown");
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n  "),
+  ok(gEditor.getText().includes("\n  "),
      "The source should be pretty printed.")
 }
 
 function testEditorShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 0, "The editor should be shown");
 }
 
 function testSourceIsStillPretty() {
   const deferred = promise.defer();
 
   const { source } = gSources.selectedItem.attachment;
   gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
-    ok(text.contains("\n  "),
+    ok(text.includes("\n  "),
        "Subsequent calls to getText return the pretty printed source.");
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-02.js
@@ -37,17 +37,17 @@ function selectContextMenuItem() {
   once(gContextMenu, "popupshown").then(() => {
     const menuItem = gDebugger.document.getElementById("se-dbg-cMenu-prettyPrint");
     menuItem.click();
   });
   gContextMenu.openPopup(gEditor.container, "overlap", 0, 0, true, false);
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n  "),
+  ok(gEditor.getText().includes("\n  "),
      "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-05.js
@@ -24,17 +24,17 @@ function test() {
 
       // From this point onward, the source editor's text should never change.
       gEditor.once("change", () => {
         ok(false, "The source editor text shouldn't have changed.");
       });
 
       is(getSelectedSourceURL(gSources), TAB_URL,
         "The correct source is currently selected.");
-      ok(gEditor.getText().contains("myFunction"),
+      ok(gEditor.getText().includes("myFunction"),
         "The source shouldn't be pretty printed yet.");
 
       clickPrettyPrintButton();
 
       let { source } = gSources.selectedItem.attachment;
       try {
         yield gControllerSources.togglePrettyPrint(source);
         ok(false, "The promise for a prettified source should be rejected!");
@@ -42,19 +42,19 @@ function test() {
         is(error, "Can't prettify non-javascript files.",
           "The promise was correctly rejected with a meaningful message.");
       }
 
       let text;
       [source, text] = yield gControllerSources.getText(source);
       is(getSelectedSourceURL(gSources), TAB_URL,
         "The correct source is still selected.");
-      ok(gEditor.getText().contains("myFunction"),
+      ok(gEditor.getText().includes("myFunction"),
         "The displayed source hasn't changed.");
-      ok(text.contains("myFunction"),
+      ok(text.includes("myFunction"),
         "The cached source text wasn't altered in any way.");
 
       yield closeDebuggerAndFinish(gPanel);
     });
   });
 }
 
 function clickPrettyPrintButton() {
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-06.js
@@ -40,37 +40,37 @@ function test() {
 
       // From this point onward, the source editor's text should never change.
       gEditor.once("change", () => {
         ok(false, "The source editor text shouldn't have changed.");
       });
 
       is(getSelectedSourceURL(gSources), JS_URL,
         "The correct source is currently selected.");
-      ok(gEditor.getText().contains("myFunction"),
+      ok(gEditor.getText().includes("myFunction"),
         "The source shouldn't be pretty printed yet.");
 
       clickPrettyPrintButton();
 
       let { source } = gSources.selectedItem.attachment;
       try {
         yield gControllerSources.togglePrettyPrint(source);
         ok(false, "The promise for a prettified source should be rejected!");
       } catch ([source, error]) {
-        ok(error.contains("prettyPrintError"),
+        ok(error.includes("prettyPrintError"),
           "The promise was correctly rejected with a meaningful message.");
       }
 
       let text;
       [source, text] = yield gControllerSources.getText(source);
       is(getSelectedSourceURL(gSources), JS_URL,
         "The correct source is still selected.");
-      ok(gEditor.getText().contains("myFunction"),
+      ok(gEditor.getText().includes("myFunction"),
         "The displayed source hasn't changed.");
-      ok(text.contains("myFunction"),
+      ok(text.includes("myFunction"),
         "The cached source text wasn't altered in any way.");
 
       is(gPrettyPrinted, true,
         "The hijacked pretty print method was executed.");
 
       yield closeDebuggerAndFinish(gPanel);
     });
   });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js
@@ -18,40 +18,40 @@ function test() {
 
     findSource();
   });
 }
 
 function findSource() {
   gThreadClient.getSources(({ error, sources }) => {
     ok(!error);
-    sources = sources.filter(s => s.url.contains('code_ugly-2.js'));
+    sources = sources.filter(s => s.url.includes('code_ugly-2.js'));
     is(sources.length, 1);
     gSource = sources[0];
     prettyPrintSource();
   });
 }
 
 function prettyPrintSource() {
   gThreadClient.source(gSource).prettyPrint(4, testPrettyPrinted);
 }
 
 function testPrettyPrinted({ error, source }) {
   ok(!error, "Should not get an error while pretty-printing");
-  ok(source.contains("\n    "),
+  ok(source.includes("\n    "),
     "Source should be pretty-printed");
   disablePrettyPrint();
 }
 
 function disablePrettyPrint() {
   gThreadClient.source(gSource).disablePrettyPrint(testUgly);
 }
 
 function testUgly({ error, source }) {
   ok(!error, "Should not get an error while disabling pretty-printing");
-  ok(!source.contains("\n    "),
+  ok(!source.includes("\n    "),
      "Source should not be pretty after disabling pretty-printing");
   closeDebuggerAndFinish(gPanel);
 }
 
 registerCleanupFunction(function() {
   gTab = gPanel = gClient = gThreadClient = gSource = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-08.js
@@ -22,17 +22,17 @@ function test() {
 const BP_LOCATION = {
   line: 5,
   // column: 0
 };
 
 function findSource() {
   gThreadClient.getSources(({ error, sources }) => {
     ok(!error, "error should exist");
-    sources = sources.filter(s => s.url.contains("code_ugly-3.js"));
+    sources = sources.filter(s => s.url.includes("code_ugly-3.js"));
     is(sources.length, 1, "sources.length should be 1");
     [gSource] = sources;
     BP_LOCATION.actor = gSource.actor;
 
     prettyPrintSource(sources[0]);
   });
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-09.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-09.js
@@ -61,17 +61,17 @@ function testDbgStatement(event, { frame
 }
 
 function disablePrettyPrint() {
   gThreadClient.source(gSource).disablePrettyPrint(testUgly);
 }
 
 function testUgly({ error, source }) {
   ok(!error);
-  ok(!source.contains("\n  "));
+  ok(!source.includes("\n  "));
   getFrame();
 }
 
 function getFrame() {
   gThreadClient.getFrames(0, 1, testFrame);
 }
 
 function testFrame({ frames: [frame] }) {
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-10.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-10.js
@@ -27,33 +27,33 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n    "),
+  ok(!gEditor.getText().includes("\n    "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   // Wait a tick before clicking to make sure the frontend's blackboxchange
   // handlers have finished.
   return new Promise(resolve => {
     gDebugger.document.getElementById("pretty-print").click();
     resolve();
   });
 }
 
 function testSourceIsStillUgly() {
   const { source } = gSources.selectedItem.attachment;
   return gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
-    ok(!text.contains("\n    "));
+    ok(!text.includes("\n    "));
   });
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-11.js
@@ -31,26 +31,26 @@ function test() {
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n  "),
+  ok(!gEditor.getText().includes("\n  "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n  "),
+  ok(gEditor.getText().includes("\n  "),
      "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-13.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-13.js
@@ -35,45 +35,45 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n  "),
+  ok(!gEditor.getText().includes("\n  "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 function testProgressBarShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 2, "The progress bar should be shown");
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n  "),
+  ok(gEditor.getText().includes("\n  "),
      "The source should be pretty printed.")
 }
 
 function testEditorShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 0, "The editor should be shown");
 }
 
 function testSourceIsStillPretty() {
   const deferred = promise.defer();
 
   const { source } = gSources.selectedItem.attachment;
   gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
-    ok(text.contains("\n  "),
+    ok(text.includes("\n  "),
        "Subsequent calls to getText return the pretty printed source.");
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/debugger/test/browser_dbg_scripts-switching-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-switching-03.js
@@ -31,17 +31,17 @@ function test() {
 
 function showBogusSource() {
   let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_ERROR_SHOWN);
   gView._setEditorSource({ url: "http://example.com/fake.js", actor: "fake.actor" });
   return finished;
 }
 
 function testDebuggerLoadingError() {
-  ok(gEditor.getText().contains(gL10N.getStr("errorLoadingText")),
+  ok(gEditor.getText().includes(gL10N.getStr("errorLoadingText")),
     "The valid error loading message is displayed.");
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gView = null;
--- a/browser/devtools/debugger/test/browser_dbg_search-basic-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-basic-02.js
@@ -98,19 +98,19 @@ function combineWithTokenColonSearch() {
 
   return finished.then(() => promise.all([
     ensureSourceIs(gPanel, "-01.js"),
     ensureCaretAt(gPanel, 2, 11)
   ]));
 }
 
 function verifySourceAndCaret(aUrl, aLine, aColumn, aSelection) {
-  ok(gSources.selectedItem.attachment.label.contains(aUrl),
+  ok(gSources.selectedItem.attachment.label.includes(aUrl),
     "The selected item's label appears to be correct.");
-  ok(gSources.selectedItem.attachment.source.url.contains(aUrl),
+  ok(gSources.selectedItem.attachment.source.url.includes(aUrl),
     "The selected item's value appears to be correct.");
   ok(isCaretPos(gPanel, aLine, aColumn),
     "The current caret position appears to be correct.");
   ok(isEditorSel(gPanel, aSelection),
     "The current editor selection appears to be correct.");
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/debugger/test/browser_dbg_search-basic-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-basic-03.js
@@ -96,19 +96,19 @@ function escapeAndHide() {
 
 function escapeAndClear() {
   EventUtils.sendKey("ESCAPE", gDebugger);
   is(gSearchBox.getAttribute("value"), "",
     "The searchbox has properly emptied after pressing escape.");
 }
 
 function verifySourceAndCaret(aUrl, aLine, aColumn) {
-  ok(gSources.selectedItem.attachment.label.contains(aUrl),
+  ok(gSources.selectedItem.attachment.label.includes(aUrl),
     "The selected item's label appears to be correct.");
-  ok(gSources.selectedItem.attachment.source.url.contains(aUrl),
+  ok(gSources.selectedItem.attachment.source.url.includes(aUrl),
     "The selected item's value appears to be correct.");
   ok(isCaretPos(gPanel, aLine, aColumn),
     "The current caret position appears to be correct.");
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
--- a/browser/devtools/debugger/test/browser_dbg_search-global-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-global-01.js
@@ -48,17 +48,17 @@ function firstSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       let sourceResults = gDebugger.document.querySelectorAll(".dbg-source-results");
       is(sourceResults.length, 2,
         "There should be matches found in two sources.");
 
@@ -162,17 +162,17 @@ function secondSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       let sourceResults = gDebugger.document.querySelectorAll(".dbg-source-results");
       is(sourceResults.length, 2,
         "There should be matches found in two sources.");
 
--- a/browser/devtools/debugger/test/browser_dbg_search-global-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-global-02.js
@@ -51,17 +51,17 @@ function firstSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       deferred.resolve();
     });
   });
 
@@ -72,17 +72,17 @@ function firstSearch() {
 
 function doFirstJump() {
   let deferred = promise.defer();
 
   waitForSourceAndCaret(gPanel, "-01.js", 4).then(() => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
-    ok(getSelectedSourceURL(gSources).contains("-01.js"),
+    ok(getSelectedSourceURL(gSources).includes("-01.js"),
       "The currently shown source is incorrect (1).");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search (1).");
 
     // The editor's selected text takes a tick to update.
     executeSoon(() => {
       ok(isCaretPos(gPanel, 4, 9),
         "The editor didn't jump to the correct line (1).");
@@ -100,17 +100,17 @@ function doFirstJump() {
 
 function doSecondJump() {
   let deferred = promise.defer();
 
   waitForSourceAndCaret(gPanel, "-02.js", 4).then(() => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
-    ok(getSelectedSourceURL(gSources).contains("-02.js"),
+    ok(getSelectedSourceURL(gSources).includes("-02.js"),
       "The currently shown source is incorrect (2).");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search (2).");
 
     // The editor's selected text takes a tick to update.
     executeSoon(() => {
       ok(isCaretPos(gPanel, 4, 9),
         "The editor didn't jump to the correct line (2).");
@@ -128,17 +128,17 @@ function doSecondJump() {
 
 function doWrapAroundJump() {
   let deferred = promise.defer();
 
   waitForSourceAndCaret(gPanel, "-01.js", 4).then(() => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
-    ok(getSelectedSourceURL(gSources).contains("-01.js"),
+    ok(getSelectedSourceURL(gSources).includes("-01.js"),
       "The currently shown source is incorrect (3).");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search (3).");
 
     // The editor's selected text takes a tick to update.
     executeSoon(() => {
       ok(isCaretPos(gPanel, 4, 9),
         "The editor didn't jump to the correct line (3).");
@@ -157,17 +157,17 @@ function doWrapAroundJump() {
 
 function doBackwardsWrapAroundJump() {
   let deferred = promise.defer();
 
   waitForSourceAndCaret(gPanel, "-02.js", 7).then(() => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
-    ok(getSelectedSourceURL(gSources).contains("-02.js"),
+    ok(getSelectedSourceURL(gSources).includes("-02.js"),
       "The currently shown source is incorrect (4).");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search (4).");
 
     // The editor's selected text takes a tick to update.
     executeSoon(() => {
       ok(isCaretPos(gPanel, 7, 11),
         "The editor didn't jump to the correct line (4).");
@@ -184,17 +184,17 @@ function doBackwardsWrapAroundJump() {
 }
 
 function testSearchTokenEmpty() {
   backspaceText(gSearchBox, 4);
 
   info("Current source url:\n" + getSelectedSourceURL(gSources));
   info("Debugger editor text:\n" + gEditor.getText());
 
-  ok(getSelectedSourceURL(gSources).contains("-02.js"),
+  ok(getSelectedSourceURL(gSources).includes("-02.js"),
     "The currently shown source is incorrect (4).");
   is(gSources.visibleItems.length, 2,
     "Not all the sources are shown after the global search (4).");
   ok(isCaretPos(gPanel, 7, 11),
     "The editor didn't remain at the correct line (4).");
   is(gEditor.getSelection(), "",
     "The editor shouldn't keep the previous text selected (4).");
 
--- a/browser/devtools/debugger/test/browser_dbg_search-global-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-global-03.js
@@ -47,17 +47,17 @@ function firstSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       deferred.resolve();
     });
   });
 
--- a/browser/devtools/debugger/test/browser_dbg_search-global-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-global-04.js
@@ -40,17 +40,17 @@ function firstSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       deferred.resolve();
     });
   });
 
@@ -63,17 +63,17 @@ function secondSearch() {
   let deferred = promise.defer();
 
   gDebugger.once(gDebugger.EVENTS.GLOBAL_SEARCH_MATCH_NOT_FOUND, () => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
     ok(isCaretPos(gPanel, 6),
       "The editor shouldn't have jumped to a matching line yet.");
-    ok(getSelectedSourceURL(gSources).contains("-02.js"),
+    ok(getSelectedSourceURL(gSources).includes("-02.js"),
       "The current source shouldn't have changed after a global search.");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search.");
 
     deferred.resolve();
   });
 
   typeText(gSearchBox, "/");
--- a/browser/devtools/debugger/test/browser_dbg_search-global-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-global-05.js
@@ -43,17 +43,17 @@ function doSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       deferred.resolve();
     });
   });
 
@@ -96,17 +96,17 @@ function testClickLineToJump() {
   waitForSourceAndCaret(gPanel, "-01.js", 1, 1).then(() => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
     ok(isCaretPos(gPanel, 1, 1),
       "The editor didn't jump to the correct line (1).");
     is(gEditor.getSelection(), "",
       "The editor didn't select the correct text (1).");
-    ok(getSelectedSourceURL(gSources).contains("-01.js"),
+    ok(getSelectedSourceURL(gSources).includes("-01.js"),
       "The currently shown source is incorrect (1).");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search (1).");
 
     deferred.resolve();
   });
 
   EventUtils.sendMouseEvent({ type: "click" }, firstLine);
@@ -125,17 +125,17 @@ function testClickMatchToJump() {
   waitForSourceAndCaret(gPanel, "-02.js", 1, 1).then(() => {
     info("Current source url:\n" + getSelectedSourceURL(gSources));
     info("Debugger editor text:\n" + gEditor.getText());
 
     ok(isCaretPos(gPanel, 1, 1),
       "The editor didn't jump to the correct line (2).");
     is(gEditor.getSelection(), "",
       "The editor didn't select the correct text (2).");
-    ok(getSelectedSourceURL(gSources).contains("-02.js"),
+    ok(getSelectedSourceURL(gSources).includes("-02.js"),
       "The currently shown source is incorrect (2).");
     is(gSources.visibleItems.length, 2,
       "Not all the sources are shown after the global search (2).");
 
     deferred.resolve();
   });
 
   EventUtils.sendMouseEvent({ type: "click" }, lastMatch);
--- a/browser/devtools/debugger/test/browser_dbg_search-global-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-global-06.js
@@ -49,17 +49,17 @@ function doSearch() {
     // Some operations are synchronously dispatched on the main thread,
     // to avoid blocking UI, thus giving the impression of faster searching.
     executeSoon(() => {
       info("Current source url:\n" + getSelectedSourceURL(gSources));
       info("Debugger editor text:\n" + gEditor.getText());
 
       ok(isCaretPos(gPanel, 6),
         "The editor shouldn't have jumped to a matching line yet.");
-      ok(getSelectedSourceURL(gSources).contains("-02.js"),
+      ok(getSelectedSourceURL(gSources).includes("-02.js"),
         "The current source shouldn't have changed after a global search.");
       is(gSources.visibleItems.length, 2,
         "Not all the sources are shown after the global search.");
 
       deferred.resolve();
     });
   });
 
--- a/browser/devtools/debugger/test/browser_dbg_search-symbols.js
+++ b/browser/devtools/debugger/test/browser_dbg_search-symbols.js
@@ -68,17 +68,17 @@ function htmlSearch() {
           is(target.querySelector(".results-panel-item-label").getAttribute("value"),
             gDebugger.SourceUtils.trimUrlLength(label + "()"),
             "The corect label (" + label + ") is currently selected.");
         } else {
           ok(!target.querySelector(".results-panel-item-label"),
             "Shouldn't create empty label nodes.");
         }
         if (value) {
-          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").contains(value),
+          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
             "The corect value (" + value + ") is attached.");
         } else {
           ok(!target.querySelector(".results-panel-item-label-below"),
             "Shouldn't create empty label nodes.");
         }
         if (description) {
           is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
             "The corect description (" + description + ") is currently shown.");
@@ -139,17 +139,17 @@ function firstJsSearch() {
           is(target.querySelector(".results-panel-item-label").getAttribute("value"),
             gDebugger.SourceUtils.trimUrlLength(label + "()"),
             "The corect label (" + label + ") is currently selected.");
         } else {
           ok(!target.querySelector(".results-panel-item-label"),
             "Shouldn't create empty label nodes.");
         }
         if (value) {
-          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").contains(value),
+          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
             "The corect value (" + value + ") is attached.");
         } else {
           ok(!target.querySelector(".results-panel-item-label-below"),
             "Shouldn't create empty label nodes.");
         }
         if (description) {
           is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
             "The corect description (" + description + ") is currently shown.");
@@ -210,17 +210,17 @@ function secondJsSearch() {
           is(target.querySelector(".results-panel-item-label").getAttribute("value"),
             gDebugger.SourceUtils.trimUrlLength(label + "()"),
             "The corect label (" + label + ") is currently selected.");
         } else {
           ok(!target.querySelector(".results-panel-item-label"),
             "Shouldn't create empty label nodes.");
         }
         if (value) {
-          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").contains(value),
+          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
             "The corect value (" + value + ") is attached.");
         } else {
           ok(!target.querySelector(".results-panel-item-label-below"),
             "Shouldn't create empty label nodes.");
         }
         if (description) {
           is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
             "The corect description (" + description + ") is currently shown.");
@@ -281,17 +281,17 @@ function thirdJsSearch() {
           is(target.querySelector(".results-panel-item-label").getAttribute("value"),
             gDebugger.SourceUtils.trimUrlLength(label + "()"),
             "The corect label (" + label + ") is currently selected.");
         } else {
           ok(!target.querySelector(".results-panel-item-label"),
             "Shouldn't create empty label nodes.");
         }
         if (value) {
-          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").contains(value),
+          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
             "The corect value (" + value + ") is attached.");
         } else {
           ok(!target.querySelector(".results-panel-item-label-below"),
             "Shouldn't create empty label nodes.");
         }
         if (description) {
           is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
             "The corect description (" + description + ") is currently shown.");
@@ -349,17 +349,17 @@ function filterSearch() {
           is(target.querySelector(".results-panel-item-label").getAttribute("value"),
             gDebugger.SourceUtils.trimUrlLength(label + "()"),
             "The corect label (" + label + ") is currently selected.");
         } else {
           ok(!target.querySelector(".results-panel-item-label"),
             "Shouldn't create empty label nodes.");
         }
         if (value) {
-          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").contains(value),
+          ok(target.querySelector(".results-panel-item-label-below").getAttribute("value").includes(value),
             "The corect value (" + value + ") is attached.");
         } else {
           ok(!target.querySelector(".results-panel-item-label-below"),
             "Shouldn't create empty label nodes.");
         }
         if (description) {
           is(target.querySelector(".results-panel-item-label-before").getAttribute("value"), description,
             "The corect description (" + description + ") is currently shown.");
--- a/browser/devtools/debugger/test/browser_dbg_sources-cache.js
+++ b/browser/devtools/debugger/test/browser_dbg_sources-cache.js
@@ -31,53 +31,53 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function initialChecks() {
-  ok(gEditor.getText().contains("First source!"),
+  ok(gEditor.getText().includes("First source!"),
     "Editor text contents appears to be correct.");
   is(gSources.selectedItem.attachment.label, "code_function-search-01.js",
     "The currently selected label in the sources container is correct.");
-  ok(getSelectedSourceURL(gSources).contains("code_function-search-01.js"),
+  ok(getSelectedSourceURL(gSources).includes("code_function-search-01.js"),
     "The currently selected value in the sources container appears to be correct.");
 
   is(gSources.itemCount, TOTAL_SOURCES,
     "There should be " + TOTAL_SOURCES + " sources present in the sources list.");
   is(gSources.visibleItems.length, TOTAL_SOURCES,
     "There should be " + TOTAL_SOURCES + " sources visible in the sources list.");
   is(gSources.attachments.length, TOTAL_SOURCES,
     "There should be " + TOTAL_SOURCES + " attachments stored in the sources container model.")
   is(gSources.values.length, TOTAL_SOURCES,
     "There should be " + TOTAL_SOURCES + " values stored in the sources container model.")
 
   info("Source labels: " + gSources.attachments.toSource());
   info("Source values: " + gSources.values.toSource());
 
   is(gSources.attachments[0].label, "code_function-search-01.js",
     "The first source label is correct.");
-  ok(gSources.attachments[0].source.url.contains("code_function-search-01.js"),
+  ok(gSources.attachments[0].source.url.includes("code_function-search-01.js"),
     "The first source value appears to be correct.");
 
   is(gSources.attachments[1].label, "code_function-search-02.js",
     "The second source label is correct.");
-  ok(gSources.attachments[1].source.url.contains("code_function-search-02.js"),
+  ok(gSources.attachments[1].source.url.includes("code_function-search-02.js"),
     "The second source value appears to be correct.");
 
   is(gSources.attachments[2].label, "code_function-search-03.js",
     "The third source label is correct.");
-  ok(gSources.attachments[2].source.url.contains("code_function-search-03.js"),
+  ok(gSources.attachments[2].source.url.includes("code_function-search-03.js"),
     "The third source value appears to be correct.");
 
   is(gSources.attachments[3].label, "doc_function-search.html",
     "The third source label is correct.");
-  ok(gSources.attachments[3].source.url.contains("doc_function-search.html"),
+  ok(gSources.attachments[3].source.url.includes("doc_function-search.html"),
     "The third source value appears to be correct.");
 
   is(gDebugger.SourceUtils._labelsCache.size, TOTAL_SOURCES,
     "There should be " + TOTAL_SOURCES + " labels cached.");
   is(gDebugger.SourceUtils._groupsCache.size, TOTAL_SOURCES,
     "There should be " + TOTAL_SOURCES + " groups cached.");
 }
 
@@ -93,17 +93,17 @@ function performReloadAndTestState() {
 
 function testCacheIntegrity(aSources) {
   for (let [actor, contents] of aSources) {
     // Sources of a debugee don't always finish fetching consecutively. D'uh.
     let index = gSources.values.indexOf(actor);
 
     ok(index >= 0 && index <= TOTAL_SOURCES,
       "Found a source actor cached correctly (" + index + ").");
-    ok(contents.contains(
+    ok(contents.includes(
       ["First source!", "Second source!", "Third source!", "Peanut butter jelly time!"][index]),
       "Found a source's text contents cached correctly (" + index + ").");
 
     info("Cached source actor at " + index + ": " + actor);
     info("Cached source text at " + index + ": " + contents);
   }
 }
 
--- a/browser/devtools/debugger/test/browser_dbg_tabactor-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_tabactor-01.js
@@ -37,17 +37,17 @@ function test() {
   });
 }
 
 function testTabActor([aGrip, aResponse]) {
   let deferred = promise.defer();
 
   ok(aGrip.testTabActor1,
     "Found the test tab actor.");
-  ok(aGrip.testTabActor1.contains("test_one"),
+  ok(aGrip.testTabActor1.includes("test_one"),
     "testTabActor1's actorPrefix should be used.");
 
   gClient.request({ to: aGrip.testTabActor1, type: "ping" }, aResponse => {
     is(aResponse.pong, "pong",
       "Actor should respond to requests.");
 
     deferred.resolve();
   });
--- a/browser/devtools/debugger/test/browser_dbg_tabactor-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_tabactor-02.js
@@ -37,17 +37,17 @@ function test() {
   });
 }
 
 function testTabActor([aGrip, aResponse]) {
   let deferred = promise.defer();
 
   ok(aGrip.testTabActor1,
     "Found the test tab actor.");
-  ok(aGrip.testTabActor1.contains("test_one"),
+  ok(aGrip.testTabActor1.includes("test_one"),
     "testTabActor1's actorPrefix should be used.");
 
   gClient.request({ to: aGrip.testTabActor1, type: "ping" }, aResponse => {
     is(aResponse.pong, "pong",
       "Actor should respond to requests.");
 
     deferred.resolve(aResponse.actor);
   });
--- a/browser/devtools/debugger/test/browser_dbg_tracing-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_tracing-01.js
@@ -44,24 +44,24 @@ function testTraceLogs() {
                                    t => t.querySelector(".trace-name[value=onclick]"));
   is(onclickLogs.length, 2, "Should have two logs from 'onclick'");
   ok(onclickLogs[0].querySelector(".trace-call"),
      "The first 'onclick' log should be a call.");
   ok(onclickLogs[1].querySelector(".trace-return"),
      "The second 'onclick' log should be a return.");
   for (let t of onclickLogs) {
     ok(t.querySelector(".trace-item").getAttribute("tooltiptext")
-        .contains("doc_tracing-01.html"));
+        .includes("doc_tracing-01.html"));
   }
 
   const nonOnclickLogs = filterTraces(gPanel,
                                       t => !t.querySelector(".trace-name[value=onclick]"));
   for (let t of nonOnclickLogs) {
     ok(t.querySelector(".trace-item").getAttribute("tooltiptext")
-        .contains("code_tracing-01.js"));
+        .includes("code_tracing-01.js"));
   }
 
   const mainLogs = filterTraces(gPanel,
                                 t => t.querySelector(".trace-name[value=main]"));
   is(mainLogs.length, 2, "Should have an enter and an exit for 'main'");
   ok(mainLogs[0].querySelector(".trace-call"),
      "The first 'main' log should be a call.");
   ok(mainLogs[1].querySelector(".trace-return"),
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-01.js
@@ -10,29 +10,29 @@ const TAB_URL = EXAMPLE_URL + "doc_recur
 
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let variables = aPanel.panelWin.DebuggerView.Variables;
     let testScope = variables.addScope("test");
 
     ok(testScope,
       "Should have created a scope.");
-    ok(testScope.id.contains("test"),
+    ok(testScope.id.includes("test"),
       "The newly created scope should have the default id set.");
     is(testScope.name, "test",
       "The newly created scope should have the desired name set.");
 
     ok(!testScope.displayValue,
       "The newly created scope should not have a displayed value (1).");
     ok(!testScope.displayValueClassName,
       "The newly created scope should not have a displayed value (2).");
 
     ok(testScope.target,
       "The newly created scope should point to a target node.");
-    ok(testScope.target.id.contains("test"),
+    ok(testScope.target.id.includes("test"),
       "Should have the correct scope id on the element.");
 
     is(testScope.target.querySelector(".name").getAttribute("value"), "test",
       "Any new scope should have the designated name.");
     is(testScope.target.querySelector(".variables-view-element-details.enum").childNodes.length, 0,
       "Any new scope should have a container with no enumerable child nodes.");
     is(testScope.target.querySelector(".variables-view-element-details.nonenum").childNodes.length, 0,
       "Any new scope should have a container with no non-enumerable child nodes.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-02.js
@@ -22,29 +22,29 @@ function test() {
 
     ok(testScope,
       "Should have created a scope.");
     is(duplVar, null,
       "Shouldn't be able to duplicate variables in the same scope.");
 
     ok(testVar,
       "Should have created a variable.");
-    ok(testVar.id.contains("something"),
+    ok(testVar.id.includes("something"),
       "The newly created variable should have the default id set.");
     is(testVar.name, "something",
       "The newly created variable should have the desired name set.");
 
     ok(!testVar.displayValue,
       "The newly created variable should not have a displayed value yet (1).");
     ok(!testVar.displayValueClassName,
       "The newly created variable should not have a displayed value yet (2).");
 
     ok(testVar.target,
       "The newly created scope should point to a target node.");
-    ok(testVar.target.id.contains("something"),
+    ok(testVar.target.id.includes("something"),
       "Should have the correct variable id on the element.");
 
     is(testVar.target.querySelector(".name").getAttribute("value"), "something",
       "Any new variable should have the designated name.");
     is(testVar.target.querySelector(".variables-view-element-details.enum").childNodes.length, 0,
       "Any new variable should have a container with no enumerable child nodes.");
     is(testVar.target.querySelector(".variables-view-element-details.nonenum").childNodes.length, 0,
       "Any new variable should have a container with no non-enumerable child nodes.");
@@ -152,29 +152,29 @@ function test() {
         type: "object",
         class: "Object"
       }
     });
 
     let testChild = testVar.get("child");
     ok(testChild,
       "Should have created a child property.");
-    ok(testChild.id.contains("child"),
+    ok(testChild.id.includes("child"),
       "The newly created property should have the default id set.");
     is(testChild.name, "child",
       "The newly created property should have the desired name set.");
 
     is(testChild.displayValue, "Object",
       "The newly created property should not have a displayed value yet (1).");
     is(testChild.displayValueClassName, "token-other",
       "The newly created property should not have a displayed value yet (2).");
 
     ok(testChild.target,
       "The newly created scope should point to a target node.");
-    ok(testChild.target.id.contains("child"),
+    ok(testChild.target.id.includes("child"),
       "Should have the correct property id on the element.");
 
     is(testChild.target.querySelector(".name").getAttribute("value"), "child",
       "Any new property should have the designated name.");
     is(testChild.target.querySelector(".variables-view-element-details.enum").childNodes.length, 0,
       "Any new property should have a container with no enumerable child nodes.");
     is(testChild.target.querySelector(".variables-view-element-details.nonenum").childNodes.length, 0,
       "Any new property should have a container with no non-enumerable child nodes.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-01.js
@@ -33,19 +33,19 @@ function test() {
   });
 }
 
 function initialChecks() {
   let scopeNodes = gDebugger.document.querySelectorAll(".variables-view-scope");
   is(scopeNodes.length, 2,
     "There should be 2 scopes available.");
 
-  ok(scopeNodes[0].querySelector(".name").getAttribute("value").contains("[test]"),
+  ok(scopeNodes[0].querySelector(".name").getAttribute("value").includes("[test]"),
     "The local scope should be properly identified.");
-  ok(scopeNodes[1].querySelector(".name").getAttribute("value").contains("[Window]"),
+  ok(scopeNodes[1].querySelector(".name").getAttribute("value").includes("[Window]"),
     "The global scope should be properly identified.");
 
   is(gVariables.getScopeAtIndex(0).target, scopeNodes[0],
     "getScopeAtIndex(0) didn't return the expected scope.");
   is(gVariables.getScopeAtIndex(1).target, scopeNodes[1],
     "getScopeAtIndex(1) didn't return the expected scope.");
 
   is(gVariables.getItemForNode(scopeNodes[0]).target, scopeNodes[0],
@@ -84,64 +84,64 @@ function testExpandVariables() {
     "The cVar should not be expanded at this point.");
 
   waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES, 3).then(() => {
     is(thisVar.get("window").target.querySelector(".name").getAttribute("value"), "window",
       "Should have the right property name for 'window'.");
     is(thisVar.get("window").target.querySelector(".value").getAttribute("value"),
       "Window \u2192 doc_frame-parameters.html",
       "Should have the right property value for 'window'.");
-    ok(thisVar.get("window").target.querySelector(".value").className.contains("token-other"),
+    ok(thisVar.get("window").target.querySelector(".value").className.includes("token-other"),
       "Should have the right token class for 'window'.");
 
     is(thisVar.get("document").target.querySelector(".name").getAttribute("value"), "document",
       "Should have the right property name for 'document'.");
     is(thisVar.get("document").target.querySelector(".value").getAttribute("value"),
       "HTMLDocument \u2192 doc_frame-parameters.html",
       "Should have the right property value for 'document'.");
-    ok(thisVar.get("document").target.querySelector(".value").className.contains("token-domnode"),
+    ok(thisVar.get("document").target.querySelector(".value").className.includes("token-domnode"),
       "Should have the right token class for 'document'.");
 
     let argsProps = argsVar.target.querySelectorAll(".variables-view-property");
     is(argsProps.length, 8,
       "The 'arguments' variable should contain 5 enumerable and 3 non-enumerable properties");
 
     is(argsProps[0].querySelector(".name").getAttribute("value"), "0",
       "Should have the right property name for '0'.");
     is(argsProps[0].querySelector(".value").getAttribute("value"), "Object",
       "Should have the right property value for '0'.");
-    ok(argsProps[0].querySelector(".value").className.contains("token-other"),
+    ok(argsProps[0].querySelector(".value").className.includes("token-other"),
       "Should have the right token class for '0'.");
 
     is(argsProps[1].querySelector(".name").getAttribute("value"), "1",
       "Should have the right property name for '1'.");
     is(argsProps[1].querySelector(".value").getAttribute("value"), "\"beta\"",
       "Should have the right property value for '1'.");
-    ok(argsProps[1].querySelector(".value").className.contains("token-string"),
+    ok(argsProps[1].querySelector(".value").className.includes("token-string"),
       "Should have the right token class for '1'.");
 
     is(argsProps[2].querySelector(".name").getAttribute("value"), "2",
       "Should have the right property name for '2'.");
     is(argsProps[2].querySelector(".value").getAttribute("value"), "3",
       "Should have the right property name for '2'.");
-    ok(argsProps[2].querySelector(".value").className.contains("token-number"),
+    ok(argsProps[2].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for '2'.");
 
     is(argsProps[3].querySelector(".name").getAttribute("value"), "3",
       "Should have the right property name for '3'.");
     is(argsProps[3].querySelector(".value").getAttribute("value"), "false",
       "Should have the right property value for '3'.");
-    ok(argsProps[3].querySelector(".value").className.contains("token-boolean"),
+    ok(argsProps[3].querySelector(".value").className.includes("token-boolean"),
       "Should have the right token class for '3'.");
 
     is(argsProps[4].querySelector(".name").getAttribute("value"), "4",
       "Should have the right property name for '4'.");
     is(argsProps[4].querySelector(".value").getAttribute("value"), "null",
       "Should have the right property name for '4'.");
-    ok(argsProps[4].querySelector(".value").className.contains("token-null"),
+    ok(argsProps[4].querySelector(".value").className.includes("token-null"),
       "Should have the right token class for '4'.");
 
     is(gVariables.getItemForNode(argsProps[0]).target,
        argsVar.target.querySelectorAll(".variables-view-property")[0],
       "getItemForNode([0]) didn't return the expected property.");
 
     is(gVariables.getItemForNode(argsProps[1]).target,
        argsVar.target.querySelectorAll(".variables-view-property")[1],
@@ -166,52 +166,52 @@ function testExpandVariables() {
     let cProps = cVar.target.querySelectorAll(".variables-view-property");
     is(cProps.length, 7,
       "The 'c' variable should contain 6 enumerable and 1 non-enumerable properties");
 
     is(cProps[0].querySelector(".name").getAttribute("value"), "a",
       "Should have the right property name for 'a'.");
     is(cProps[0].querySelector(".value").getAttribute("value"), "1",
       "Should have the right property value for 'a'.");
-    ok(cProps[0].querySelector(".value").className.contains("token-number"),
+    ok(cProps[0].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'a'.");
 
     is(cProps[1].querySelector(".name").getAttribute("value"), "b",
       "Should have the right property name for 'b'.");
     is(cProps[1].querySelector(".value").getAttribute("value"), "\"beta\"",
       "Should have the right property value for 'b'.");
-    ok(cProps[1].querySelector(".value").className.contains("token-string"),
+    ok(cProps[1].querySelector(".value").className.includes("token-string"),
       "Should have the right token class for 'b'.");
 
     is(cProps[2].querySelector(".name").getAttribute("value"), "c",
       "Should have the right property name for 'c'.");
     is(cProps[2].querySelector(".value").getAttribute("value"), "3",
       "Should have the right property value for 'c'.");
-    ok(cProps[2].querySelector(".value").className.contains("token-number"),
+    ok(cProps[2].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'c'.");
 
     is(cProps[3].querySelector(".name").getAttribute("value"), "d",
       "Should have the right property name for 'd'.");
     is(cProps[3].querySelector(".value").getAttribute("value"), "false",
       "Should have the right property value for 'd'.");
-    ok(cProps[3].querySelector(".value").className.contains("token-boolean"),
+    ok(cProps[3].querySelector(".value").className.includes("token-boolean"),
       "Should have the right token class for 'd'.");
 
     is(cProps[4].querySelector(".name").getAttribute("value"), "e",
       "Should have the right property name for 'e'.");
     is(cProps[4].querySelector(".value").getAttribute("value"), "null",
       "Should have the right property value for 'e'.");
-    ok(cProps[4].querySelector(".value").className.contains("token-null"),
+    ok(cProps[4].querySelector(".value").className.includes("token-null"),
       "Should have the right token class for 'e'.");
 
     is(cProps[5].querySelector(".name").getAttribute("value"), "f",
       "Should have the right property name for 'f'.");
     is(cProps[5].querySelector(".value").getAttribute("value"), "undefined",
       "Should have the right property value for 'f'.");
-    ok(cProps[5].querySelector(".value").className.contains("token-undefined"),
+    ok(cProps[5].querySelector(".value").className.includes("token-undefined"),
       "Should have the right token class for 'f'.");
 
     is(gVariables.getItemForNode(cProps[0]).target,
        cVar.target.querySelectorAll(".variables-view-property")[0],
       "getItemForNode([0]) didn't return the expected property.");
 
     is(gVariables.getItemForNode(cProps[1]).target,
        cVar.target.querySelectorAll(".variables-view-property")[1],
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-frame-parameters-02.js
@@ -51,94 +51,94 @@ function testScopeVariables() {
   is(localNonEnums.length, 0,
     "The local scope should contain all the created non-enumerable elements.");
 
   is(localEnums[0].querySelector(".name").getAttribute("value"), "this",
     "Should have the right property name for 'this'.");
   is(localEnums[0].querySelector(".value").getAttribute("value"),
     "Window \u2192 doc_frame-parameters.html",
     "Should have the right property value for 'this'.");
-  ok(localEnums[0].querySelector(".value").className.contains("token-other"),
+  ok(localEnums[0].querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'this'.");
 
   is(localEnums[1].querySelector(".name").getAttribute("value"), "aArg",
     "Should have the right property name for 'aArg'.");
   is(localEnums[1].querySelector(".value").getAttribute("value"), "Object",
     "Should have the right property value for 'aArg'.");
-  ok(localEnums[1].querySelector(".value").className.contains("token-other"),
+  ok(localEnums[1].querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'aArg'.");
 
   is(localEnums[2].querySelector(".name").getAttribute("value"), "bArg",
     "Should have the right property name for 'bArg'.");
   is(localEnums[2].querySelector(".value").getAttribute("value"), "\"beta\"",
     "Should have the right property value for 'bArg'.");
-  ok(localEnums[2].querySelector(".value").className.contains("token-string"),
+  ok(localEnums[2].querySelector(".value").className.includes("token-string"),
     "Should have the right token class for 'bArg'.");
 
   is(localEnums[3].querySelector(".name").getAttribute("value"), "cArg",
     "Should have the right property name for 'cArg'.");
   is(localEnums[3].querySelector(".value").getAttribute("value"), "3",
     "Should have the right property value for 'cArg'.");
-  ok(localEnums[3].querySelector(".value").className.contains("token-number"),
+  ok(localEnums[3].querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'cArg'.");
 
   is(localEnums[4].querySelector(".name").getAttribute("value"), "dArg",
     "Should have the right property name for 'dArg'.");
   is(localEnums[4].querySelector(".value").getAttribute("value"), "false",
     "Should have the right property value for 'dArg'.");
-  ok(localEnums[4].querySelector(".value").className.contains("token-boolean"),
+  ok(localEnums[4].querySelector(".value").className.includes("token-boolean"),
     "Should have the right token class for 'dArg'.");
 
   is(localEnums[5].querySelector(".name").getAttribute("value"), "eArg",
     "Should have the right property name for 'eArg'.");
   is(localEnums[5].querySelector(".value").getAttribute("value"), "null",
     "Should have the right property value for 'eArg'.");
-  ok(localEnums[5].querySelector(".value").className.contains("token-null"),
+  ok(localEnums[5].querySelector(".value").className.includes("token-null"),
     "Should have the right token class for 'eArg'.");
 
   is(localEnums[6].querySelector(".name").getAttribute("value"), "fArg",
     "Should have the right property name for 'fArg'.");
   is(localEnums[6].querySelector(".value").getAttribute("value"), "undefined",
     "Should have the right property value for 'fArg'.");
-  ok(localEnums[6].querySelector(".value").className.contains("token-undefined"),
+  ok(localEnums[6].querySelector(".value").className.includes("token-undefined"),
     "Should have the right token class for 'fArg'.");
 
   is(localEnums[7].querySelector(".name").getAttribute("value"), "a",
    "Should have the right property name for 'a'.");
   is(localEnums[7].querySelector(".value").getAttribute("value"), "1",
    "Should have the right property value for 'a'.");
-  ok(localEnums[7].querySelector(".value").className.contains("token-number"),
+  ok(localEnums[7].querySelector(".value").className.includes("token-number"),
    "Should have the right token class for 'a'.");
 
   is(localEnums[8].querySelector(".name").getAttribute("value"), "arguments",
     "Should have the right property name for 'arguments'.");
   is(localEnums[8].querySelector(".value").getAttribute("value"), "Arguments",
     "Should have the right property value for 'arguments'.");
-  ok(localEnums[8].querySelector(".value").className.contains("token-other"),
+  ok(localEnums[8].querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'arguments'.");
 
   is(localEnums[9].querySelector(".name").getAttribute("value"), "b",
    "Should have the right property name for 'b'.");
   is(localEnums[9].querySelector(".value").getAttribute("value"), "Object",
    "Should have the right property value for 'b'.");
-  ok(localEnums[9].querySelector(".value").className.contains("token-other"),
+  ok(localEnums[9].querySelector(".value").className.includes("token-other"),
    "Should have the right token class for 'b'.");
 
   is(localEnums[10].querySelector(".name").getAttribute("value"), "c",
    "Should have the right property name for 'c'.");
   is(localEnums[10].querySelector(".value").getAttribute("value"), "Object",
    "Should have the right property value for 'c'.");
-  ok(localEnums[10].querySelector(".value").className.contains("token-other"),
+  ok(localEnums[10].querySelector(".value").className.includes("token-other"),
    "Should have the right token class for 'c'.");
 
   is(localEnums[11].querySelector(".name").getAttribute("value"), "myVar",
    "Should have the right property name for 'myVar'.");
   is(localEnums[11].querySelector(".value").getAttribute("value"), "Object",
    "Should have the right property value for 'myVar'.");
-  ok(localEnums[11].querySelector(".value").className.contains("token-other"),
+  ok(localEnums[11].querySelector(".value").className.includes("token-other"),
    "Should have the right token class for 'myVar'.");
 }
 
 function testArgumentsProperties() {
   let deferred = promise.defer();
 
   let argsVar = gVariables.getScopeAtIndex(0).get("arguments");
   is(argsVar.expanded, false,
@@ -152,67 +152,67 @@ function testArgumentsProperties() {
       "The 'arguments' variable should contain all the created enumerable elements.");
     is(argsNonEnums.length, 3,
       "The 'arguments' variable should contain all the created non-enumerable elements.");
 
     is(argsEnums[0].querySelector(".name").getAttribute("value"), "0",
       "Should have the right property name for '0'.");
     is(argsEnums[0].querySelector(".value").getAttribute("value"), "Object",
       "Should have the right property value for '0'.");
-    ok(argsEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(argsEnums[0].querySelector(".value").className.includes("token-other"),
       "Should have the right token class for '0'.");
 
     is(argsEnums[1].querySelector(".name").getAttribute("value"), "1",
       "Should have the right property name for '1'.");
     is(argsEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"",
       "Should have the right property value for '1'.");
-    ok(argsEnums[1].querySelector(".value").className.contains("token-string"),
+    ok(argsEnums[1].querySelector(".value").className.includes("token-string"),
       "Should have the right token class for '1'.");
 
     is(argsEnums[2].querySelector(".name").getAttribute("value"), "2",
       "Should have the right property name for '2'.");
     is(argsEnums[2].querySelector(".value").getAttribute("value"), "3",
       "Should have the right property name for '2'.");
-    ok(argsEnums[2].querySelector(".value").className.contains("token-number"),
+    ok(argsEnums[2].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for '2'.");
 
     is(argsEnums[3].querySelector(".name").getAttribute("value"), "3",
       "Should have the right property name for '3'.");
     is(argsEnums[3].querySelector(".value").getAttribute("value"), "false",
       "Should have the right property value for '3'.");
-    ok(argsEnums[3].querySelector(".value").className.contains("token-boolean"),
+    ok(argsEnums[3].querySelector(".value").className.includes("token-boolean"),
       "Should have the right token class for '3'.");
 
     is(argsEnums[4].querySelector(".name").getAttribute("value"), "4",
       "Should have the right property name for '4'.");
     is(argsEnums[4].querySelector(".value").getAttribute("value"), "null",
       "Should have the right property name for '4'.");
-    ok(argsEnums[4].querySelector(".value").className.contains("token-null"),
+    ok(argsEnums[4].querySelector(".value").className.includes("token-null"),
       "Should have the right token class for '4'.");
 
     is(argsNonEnums[0].querySelector(".name").getAttribute("value"), "callee",
      "Should have the right property name for 'callee'.");
     is(argsNonEnums[0].querySelector(".value").getAttribute("value"),
      "test(aArg,bArg,cArg,dArg,eArg,fArg)",
      "Should have the right property name for 'callee'.");
-    ok(argsNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(argsNonEnums[0].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for 'callee'.");
 
     is(argsNonEnums[1].querySelector(".name").getAttribute("value"), "length",
       "Should have the right property name for 'length'.");
     is(argsNonEnums[1].querySelector(".value").getAttribute("value"), "5",
       "Should have the right property value for 'length'.");
-    ok(argsNonEnums[1].querySelector(".value").className.contains("token-number"),
+    ok(argsNonEnums[1].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'length'.");
 
     is(argsNonEnums[2].querySelector(".name").getAttribute("value"), "__proto__",
      "Should have the right property name for '__proto__'.");
     is(argsNonEnums[2].querySelector(".value").getAttribute("value"), "Object",
      "Should have the right property value for '__proto__'.");
-    ok(argsNonEnums[2].querySelector(".value").className.contains("token-other"),
+    ok(argsNonEnums[2].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for '__proto__'.");
 
     deferred.resolve();
   });
 
   argsVar.expand();
   return deferred.promise;
 }
@@ -232,24 +232,24 @@ function testSimpleObject() {
       "The 'b' variable should contain all the created enumerable elements.");
     is(bNonEnums.length, 1,
       "The 'b' variable should contain all the created non-enumerable elements.");
 
     is(bEnums[0].querySelector(".name").getAttribute("value"), "a",
       "Should have the right property name for 'a'.");
     is(bEnums[0].querySelector(".value").getAttribute("value"), "1",
       "Should have the right property value for 'a'.");
-    ok(bEnums[0].querySelector(".value").className.contains("token-number"),
+    ok(bEnums[0].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'a'.");
 
     is(bNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__",
      "Should have the right property name for '__proto__'.");
     is(bNonEnums[0].querySelector(".value").getAttribute("value"), "Object",
      "Should have the right property value for '__proto__'.");
-    ok(bNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(bNonEnums[0].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for '__proto__'.");
 
     deferred.resolve();
   });
 
   bVar.expand();
   return deferred.promise;
 }
@@ -269,59 +269,59 @@ function testComplexObject() {
       "The 'c' variable should contain all the created enumerable elements.");
     is(cNonEnums.length, 1,
       "The 'c' variable should contain all the created non-enumerable elements.");
 
     is(cEnums[0].querySelector(".name").getAttribute("value"), "a",
       "Should have the right property name for 'a'.");
     is(cEnums[0].querySelector(".value").getAttribute("value"), "1",
       "Should have the right property value for 'a'.");
-    ok(cEnums[0].querySelector(".value").className.contains("token-number"),
+    ok(cEnums[0].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'a'.");
 
     is(cEnums[1].querySelector(".name").getAttribute("value"), "b",
       "Should have the right property name for 'b'.");
     is(cEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"",
       "Should have the right property value for 'b'.");
-    ok(cEnums[1].querySelector(".value").className.contains("token-string"),
+    ok(cEnums[1].querySelector(".value").className.includes("token-string"),
       "Should have the right token class for 'b'.");
 
     is(cEnums[2].querySelector(".name").getAttribute("value"), "c",
       "Should have the right property name for 'c'.");
     is(cEnums[2].querySelector(".value").getAttribute("value"), "3",
       "Should have the right property value for 'c'.");
-    ok(cEnums[2].querySelector(".value").className.contains("token-number"),
+    ok(cEnums[2].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'c'.");
 
     is(cEnums[3].querySelector(".name").getAttribute("value"), "d",
       "Should have the right property name for 'd'.");
     is(cEnums[3].querySelector(".value").getAttribute("value"), "false",
       "Should have the right property value for 'd'.");
-    ok(cEnums[3].querySelector(".value").className.contains("token-boolean"),
+    ok(cEnums[3].querySelector(".value").className.includes("token-boolean"),
       "Should have the right token class for 'd'.");
 
     is(cEnums[4].querySelector(".name").getAttribute("value"), "e",
       "Should have the right property name for 'e'.");
     is(cEnums[4].querySelector(".value").getAttribute("value"), "null",
       "Should have the right property value for 'e'.");
-    ok(cEnums[4].querySelector(".value").className.contains("token-null"),
+    ok(cEnums[4].querySelector(".value").className.includes("token-null"),
       "Should have the right token class for 'e'.");
 
     is(cEnums[5].querySelector(".name").getAttribute("value"), "f",
       "Should have the right property name for 'f'.");
     is(cEnums[5].querySelector(".value").getAttribute("value"), "undefined",
       "Should have the right property value for 'f'.");
-    ok(cEnums[5].querySelector(".value").className.contains("token-undefined"),
+    ok(cEnums[5].querySelector(".value").className.includes("token-undefined"),
       "Should have the right token class for 'f'.");
 
     is(cNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__",
      "Should have the right property name for '__proto__'.");
     is(cNonEnums[0].querySelector(".value").getAttribute("value"), "Object",
      "Should have the right property value for '__proto__'.");
-    ok(cNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(cNonEnums[0].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for '__proto__'.");
 
     deferred.resolve();
   });
 
   cVar.expand();
   return deferred.promise;
 }
@@ -341,59 +341,59 @@ function testArgumentObject() {
       "The 'aArg' variable should contain all the created enumerable elements.");
     is(argNonEnums.length, 1,
       "The 'aArg' variable should contain all the created non-enumerable elements.");
 
     is(argEnums[0].querySelector(".name").getAttribute("value"), "a",
       "Should have the right property name for 'a'.");
     is(argEnums[0].querySelector(".value").getAttribute("value"), "1",
       "Should have the right property value for 'a'.");
-    ok(argEnums[0].querySelector(".value").className.contains("token-number"),
+    ok(argEnums[0].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'a'.");
 
     is(argEnums[1].querySelector(".name").getAttribute("value"), "b",
       "Should have the right property name for 'b'.");
     is(argEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"",
       "Should have the right property value for 'b'.");
-    ok(argEnums[1].querySelector(".value").className.contains("token-string"),
+    ok(argEnums[1].querySelector(".value").className.includes("token-string"),
       "Should have the right token class for 'b'.");
 
     is(argEnums[2].querySelector(".name").getAttribute("value"), "c",
       "Should have the right property name for 'c'.");
     is(argEnums[2].querySelector(".value").getAttribute("value"), "3",
       "Should have the right property value for 'c'.");
-    ok(argEnums[2].querySelector(".value").className.contains("token-number"),
+    ok(argEnums[2].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'c'.");
 
     is(argEnums[3].querySelector(".name").getAttribute("value"), "d",
       "Should have the right property name for 'd'.");
     is(argEnums[3].querySelector(".value").getAttribute("value"), "false",
       "Should have the right property value for 'd'.");
-    ok(argEnums[3].querySelector(".value").className.contains("token-boolean"),
+    ok(argEnums[3].querySelector(".value").className.includes("token-boolean"),
       "Should have the right token class for 'd'.");
 
     is(argEnums[4].querySelector(".name").getAttribute("value"), "e",
       "Should have the right property name for 'e'.");
     is(argEnums[4].querySelector(".value").getAttribute("value"), "null",
       "Should have the right property value for 'e'.");
-    ok(argEnums[4].querySelector(".value").className.contains("token-null"),
+    ok(argEnums[4].querySelector(".value").className.includes("token-null"),
       "Should have the right token class for 'e'.");
 
     is(argEnums[5].querySelector(".name").getAttribute("value"), "f",
       "Should have the right property name for 'f'.");
     is(argEnums[5].querySelector(".value").getAttribute("value"), "undefined",
       "Should have the right property value for 'f'.");
-    ok(argEnums[5].querySelector(".value").className.contains("token-undefined"),
+    ok(argEnums[5].querySelector(".value").className.includes("token-undefined"),
       "Should have the right token class for 'f'.");
 
     is(argNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__",
      "Should have the right property name for '__proto__'.");
     is(argNonEnums[0].querySelector(".value").getAttribute("value"), "Object",
      "Should have the right property value for '__proto__'.");
-    ok(argNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(argNonEnums[0].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for '__proto__'.");
 
     deferred.resolve();
   });
 
   argVar.expand();
   return deferred.promise;
 }
@@ -413,59 +413,59 @@ function testInnerArgumentObject() {
       "The 'arguments[0]' property should contain all the created enumerable elements.");
     is(argNonEnums.length, 1,
       "The 'arguments[0]' property should contain all the created non-enumerable elements.");
 
     is(argEnums[0].querySelector(".name").getAttribute("value"), "a",
       "Should have the right property name for 'a'.");
     is(argEnums[0].querySelector(".value").getAttribute("value"), "1",
       "Should have the right property value for 'a'.");
-    ok(argEnums[0].querySelector(".value").className.contains("token-number"),
+    ok(argEnums[0].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'a'.");
 
     is(argEnums[1].querySelector(".name").getAttribute("value"), "b",
       "Should have the right property name for 'b'.");
     is(argEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"",
       "Should have the right property value for 'b'.");
-    ok(argEnums[1].querySelector(".value").className.contains("token-string"),
+    ok(argEnums[1].querySelector(".value").className.includes("token-string"),
       "Should have the right token class for 'b'.");
 
     is(argEnums[2].querySelector(".name").getAttribute("value"), "c",
       "Should have the right property name for 'c'.");
     is(argEnums[2].querySelector(".value").getAttribute("value"), "3",
       "Should have the right property value for 'c'.");
-    ok(argEnums[2].querySelector(".value").className.contains("token-number"),
+    ok(argEnums[2].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for 'c'.");
 
     is(argEnums[3].querySelector(".name").getAttribute("value"), "d",
       "Should have the right property name for 'd'.");
     is(argEnums[3].querySelector(".value").getAttribute("value"), "false",
       "Should have the right property value for 'd'.");
-    ok(argEnums[3].querySelector(".value").className.contains("token-boolean"),
+    ok(argEnums[3].querySelector(".value").className.includes("token-boolean"),
       "Should have the right token class for 'd'.");
 
     is(argEnums[4].querySelector(".name").getAttribute("value"), "e",
       "Should have the right property name for 'e'.");
     is(argEnums[4].querySelector(".value").getAttribute("value"), "null",
       "Should have the right property value for 'e'.");
-    ok(argEnums[4].querySelector(".value").className.contains("token-null"),
+    ok(argEnums[4].querySelector(".value").className.includes("token-null"),
       "Should have the right token class for 'e'.");
 
     is(argEnums[5].querySelector(".name").getAttribute("value"), "f",
       "Should have the right property name for 'f'.");
     is(argEnums[5].querySelector(".value").getAttribute("value"), "undefined",
       "Should have the right property value for 'f'.");
-    ok(argEnums[5].querySelector(".value").className.contains("token-undefined"),
+    ok(argEnums[5].querySelector(".value").className.includes("token-undefined"),
       "Should have the right token class for 'f'.");
 
     is(argNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__",
      "Should have the right property name for '__proto__'.");
     is(argNonEnums[0].querySelector(".value").getAttribute("value"), "Object",
      "Should have the right property value for '__proto__'.");
-    ok(argNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(argNonEnums[0].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for '__proto__'.");
 
     deferred.resolve();
   });
 
   argProp.expand();
   return deferred.promise;
 }
@@ -485,55 +485,55 @@ function testGetterSetterObject() {
       "The myVar should contain all the created enumerable elements.");
     is(myVarNonEnums.length, 1,
       "The myVar should contain all the created non-enumerable elements.");
 
     is(myVarEnums[0].querySelector(".name").getAttribute("value"), "_prop",
       "Should have the right property name for '_prop'.");
     is(myVarEnums[0].querySelector(".value").getAttribute("value"), "42",
       "Should have the right property value for '_prop'.");
-    ok(myVarEnums[0].querySelector(".value").className.contains("token-number"),
+    ok(myVarEnums[0].querySelector(".value").className.includes("token-number"),
       "Should have the right token class for '_prop'.");
 
     is(myVarEnums[1].querySelector(".name").getAttribute("value"), "prop",
       "Should have the right property name for 'prop'.");
     is(myVarEnums[1].querySelector(".value").getAttribute("value"), "",
       "Should have the right property value for 'prop'.");
-    ok(!myVarEnums[1].querySelector(".value").className.contains("token"),
+    ok(!myVarEnums[1].querySelector(".value").className.includes("token"),
       "Should have no token class for 'prop'.");
 
     is(myVarNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__",
      "Should have the right property name for '__proto__'.");
     is(myVarNonEnums[0].querySelector(".value").getAttribute("value"), "Object",
      "Should have the right property value for '__proto__'.");
-    ok(myVarNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(myVarNonEnums[0].querySelector(".value").className.includes("token-other"),
      "Should have the right token class for '__proto__'.");
 
     let propEnums = myVarEnums[1].querySelector(".variables-view-element-details.enum").childNodes;
     let propNonEnums = myVarEnums[1].querySelector(".variables-view-element-details.nonenum").childNodes;
 
     is(propEnums.length, 0,
       "The propEnums should contain all the created enumerable elements.");
     is(propNonEnums.length, 2,
       "The propEnums should contain all the created non-enumerable elements.");
 
     is(propNonEnums[0].querySelector(".name").getAttribute("value"), "get",
       "Should have the right property name for 'get'.");
     is(propNonEnums[0].querySelector(".value").getAttribute("value"),
       "test/myVar.prop()",
       "Should have the right property value for 'get'.");
-    ok(propNonEnums[0].querySelector(".value").className.contains("token-other"),
+    ok(propNonEnums[0].querySelector(".value").className.includes("token-other"),
       "Should have the right token class for 'get'.");
 
     is(propNonEnums[1].querySelector(".name").getAttribute("value"), "set",
       "Should have the right property name for 'set'.");
     is(propNonEnums[1].querySelector(".value").getAttribute("value"),
       "test/myVar.prop(val)",
       "Should have the right property value for 'set'.");
-    ok(propNonEnums[1].querySelector(".value").className.contains("token-other"),
+    ok(propNonEnums[1].querySelector(".value").className.includes("token-other"),
       "Should have the right token class for 'set'.");
 
     deferred.resolve();
   });
 
   myVar.expand();
   return deferred.promise;
 }
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js
@@ -36,54 +36,54 @@ function test() {
     sendMouseClickToTab(gTab, content.document.querySelector("button"));
   });
 }
 
 function testFirstWithScope() {
   let firstWithScope = gVariables.getScopeAtIndex(0);
   is(firstWithScope.expanded, true,
     "The first 'with' scope should be expanded by default.");
-  ok(firstWithScope.target.querySelector(".name").getAttribute("value").contains("[Object]"),
+  ok(firstWithScope.target.querySelector(".name").getAttribute("value").includes("[Object]"),
     "The first 'with' scope should be properly identified.");
 
   let withEnums = firstWithScope._enum.childNodes;
   let withNonEnums = firstWithScope._nonenum.childNodes;
 
   is(withEnums.length, 3,
     "The first 'with' scope should contain all the created enumerable elements.");
   is(withNonEnums.length, 1,
     "The first 'with' scope should contain all the created non-enumerable elements.");
 
   is(withEnums[0].querySelector(".name").getAttribute("value"), "this",
     "Should have the right property name for 'this'.");
   is(withEnums[0].querySelector(".value").getAttribute("value"),
     "Window \u2192 doc_with-frame.html",
     "Should have the right property value for 'this'.");
-  ok(withEnums[0].querySelector(".value").className.contains("token-other"),
+  ok(withEnums[0].querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'this'.");
 
   is(withEnums[1].querySelector(".name").getAttribute("value"), "alpha",
     "Should have the right property name for 'alpha'.");
   is(withEnums[1].querySelector(".value").getAttribute("value"), "1",
     "Should have the right property value for 'alpha'.");
-  ok(withEnums[1].querySelector(".value").className.contains("token-number"),
+  ok(withEnums[1].querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'alpha'.");
 
   is(withEnums[2].querySelector(".name").getAttribute("value"), "beta",
     "Should have the right property name for 'beta'.");
   is(withEnums[2].querySelector(".value").getAttribute("value"), "2",
     "Should have the right property value for 'beta'.");
-  ok(withEnums[2].querySelector(".value").className.contains("token-number"),
+  ok(withEnums[2].querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'beta'.");
 
   is(withNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__",
    "Should have the right property name for '__proto__'.");
   is(withNonEnums[0].querySelector(".value").getAttribute("value"), "Object",
    "Should have the right property value for '__proto__'.");
-  ok(withNonEnums[0].querySelector(".value").className.contains("token-other"),
+  ok(withNonEnums[0].querySelector(".value").className.includes("token-other"),
    "Should have the right token class for '__proto__'.");
 }
 
 function expandSecondWithScope() {
   let deferred = promise.defer();
 
   let secondWithScope = gVariables.getScopeAtIndex(1);
   is(secondWithScope.expanded, false,
@@ -97,53 +97,53 @@ function expandSecondWithScope() {
 
   return deferred.promise;
 }
 
 function testSecondWithScope() {
   let secondWithScope = gVariables.getScopeAtIndex(1);
   is(secondWithScope.expanded, true,
     "The second 'with' scope should now be expanded.");
-  ok(secondWithScope.target.querySelector(".name").getAttribute("value").contains("[Math]"),
+  ok(secondWithScope.target.querySelector(".name").getAttribute("value").includes("[Math]"),
     "The second 'with' scope should be properly identified.");
 
   let withEnums = secondWithScope._enum.childNodes;
   let withNonEnums = secondWithScope._nonenum.childNodes;
 
   is(withEnums.length, 0,
     "The second 'with' scope should contain all the created enumerable elements.");
   isnot(withNonEnums.length, 0,
     "The second 'with' scope should contain all the created non-enumerable elements.");
 
   is(secondWithScope.get("E").target.querySelector(".name").getAttribute("value"), "E",
     "Should have the right property name for 'E'.");
   is(secondWithScope.get("E").target.querySelector(".value").getAttribute("value"), "2.718281828459045",
     "Should have the right property value for 'E'.");
-  ok(secondWithScope.get("E").target.querySelector(".value").className.contains("token-number"),
+  ok(secondWithScope.get("E").target.querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'E'.");
 
   is(secondWithScope.get("PI").target.querySelector(".name").getAttribute("value"), "PI",
     "Should have the right property name for 'PI'.");
   is(secondWithScope.get("PI").target.querySelector(".value").getAttribute("value"), "3.141592653589793",
     "Should have the right property value for 'PI'.");
-  ok(secondWithScope.get("PI").target.querySelector(".value").className.contains("token-number"),
+  ok(secondWithScope.get("PI").target.querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'PI'.");
 
   is(secondWithScope.get("random").target.querySelector(".name").getAttribute("value"), "random",
     "Should have the right property name for 'random'.");
   is(secondWithScope.get("random").target.querySelector(".value").getAttribute("value"), "random()",
     "Should have the right property value for 'random'.");
-  ok(secondWithScope.get("random").target.querySelector(".value").className.contains("token-other"),
+  ok(secondWithScope.get("random").target.querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'random'.");
 
   is(secondWithScope.get("__proto__").target.querySelector(".name").getAttribute("value"), "__proto__",
     "Should have the right property name for '__proto__'.");
   is(secondWithScope.get("__proto__").target.querySelector(".value").getAttribute("value"), "Object",
     "Should have the right property value for '__proto__'.");
-  ok(secondWithScope.get("__proto__").target.querySelector(".value").className.contains("token-other"),
+  ok(secondWithScope.get("__proto__").target.querySelector(".value").className.includes("token-other"),
     "Should have the right token class for '__proto__'.");
 }
 
 function expandFunctionScope() {
   let funcScope = gVariables.getScopeAtIndex(2);
   is(funcScope.expanded, false,
     "The function scope shouldn't be expanded by default, but the " +
     "variables have been already fetched. This is how local scopes work.");
@@ -154,53 +154,53 @@ function expandFunctionScope() {
 
   return promise.resolve(null);
 }
 
 function testFunctionScope() {
   let funcScope = gVariables.getScopeAtIndex(2);
   is(funcScope.expanded, true,
     "The function scope should now be expanded.");
-  ok(funcScope.target.querySelector(".name").getAttribute("value").contains("[test]"),
+  ok(funcScope.target.querySelector(".name").getAttribute("value").includes("[test]"),
     "The function scope should be properly identified.");
 
   let funcEnums = funcScope._enum.childNodes;
   let funcNonEnums = funcScope._nonenum.childNodes;
 
   is(funcEnums.length, 6,
     "The function scope should contain all the created enumerable elements.");
   is(funcNonEnums.length, 0,
     "The function scope should contain all the created non-enumerable elements.");
 
   is(funcScope.get("aNumber").target.querySelector(".name").getAttribute("value"), "aNumber",
     "Should have the right property name for 'aNumber'.");
   is(funcScope.get("aNumber").target.querySelector(".value").getAttribute("value"), "10",
     "Should have the right property value for 'aNumber'.");
-  ok(funcScope.get("aNumber").target.querySelector(".value").className.contains("token-number"),
+  ok(funcScope.get("aNumber").target.querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'aNumber'.");
 
   is(funcScope.get("a").target.querySelector(".name").getAttribute("value"), "a",
     "Should have the right property name for 'a'.");
   is(funcScope.get("a").target.querySelector(".value").getAttribute("value"), "314.1592653589793",
     "Should have the right property value for 'a'.");
-  ok(funcScope.get("a").target.querySelector(".value").className.contains("token-number"),
+  ok(funcScope.get("a").target.querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'a'.");
 
   is(funcScope.get("r").target.querySelector(".name").getAttribute("value"), "r",
     "Should have the right property name for 'r'.");
   is(funcScope.get("r").target.querySelector(".value").getAttribute("value"), "10",
     "Should have the right property value for 'r'.");
-  ok(funcScope.get("r").target.querySelector(".value").className.contains("token-number"),
+  ok(funcScope.get("r").target.querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'r'.");
 
   is(funcScope.get("foo").target.querySelector(".name").getAttribute("value"), "foo",
     "Should have the right property name for 'foo'.");
   is(funcScope.get("foo").target.querySelector(".value").getAttribute("value"), "6.283185307179586",
     "Should have the right property value for 'foo'.");
-  ok(funcScope.get("foo").target.querySelector(".value").className.contains("token-number"),
+  ok(funcScope.get("foo").target.querySelector(".value").className.includes("token-number"),
     "Should have the right token class for 'foo'.");
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gVariables = null;
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-large-array-buffer.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-large-array-buffer.js
@@ -41,31 +41,31 @@ function initialChecks() {
   ok(bufferVar, "There should be a 'buffer' variable present in the scope.");
   ok(arrayVar, "There should be a 'largeArray' variable present in the scope.");
   ok(objectVar, "There should be a 'largeObject' variable present in the scope.");
 
   is(bufferVar.target.querySelector(".name").getAttribute("value"), "buffer",
     "Should have the right property name for 'buffer'.");
   is(bufferVar.target.querySelector(".value").getAttribute("value"), "ArrayBuffer",
     "Should have the right property value for 'buffer'.");
-  ok(bufferVar.target.querySelector(".value").className.contains("token-other"),
+  ok(bufferVar.target.querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'buffer'.");
 
   is(arrayVar.target.querySelector(".name").getAttribute("value"), "largeArray",
     "Should have the right property name for 'largeArray'.");
   is(arrayVar.target.querySelector(".value").getAttribute("value"), "Int8Array[10000]",
     "Should have the right property value for 'largeArray'.");
-  ok(arrayVar.target.querySelector(".value").className.contains("token-other"),
+  ok(arrayVar.target.querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'largeArray'.");
 
   is(objectVar.target.querySelector(".name").getAttribute("value"), "largeObject",
     "Should have the right property name for 'largeObject'.");
   is(objectVar.target.querySelector(".value").getAttribute("value"), "Object[10000]",
     "Should have the right property value for 'largeObject'.");
-  ok(objectVar.target.querySelector(".value").className.contains("token-other"),
+  ok(objectVar.target.querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'largeObject'.");
 
   is(bufferVar.expanded, false,
     "The 'buffer' variable shouldn't be expanded.");
   is(arrayVar.expanded, false,
     "The 'largeArray' variable shouldn't be expanded.");
   is(objectVar.expanded, false,
     "The 'largeObject' variable shouldn't be expanded.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js
@@ -20,17 +20,17 @@ function test() {
     function verifyContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view containers added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
         "There should be a simple text node added to the tooltip instead.");
 
       is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent,
         "The inspected property's value is correct.");
-      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className),
+      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.includes(className),
         "The inspected property's value is colorized correctly.");
     }
 
     callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variables.
     yield openVarPopup(panel, { line: 15, ch: 12 });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js
@@ -18,17 +18,17 @@ function test() {
     function verifyContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view containers added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
         "There should be a simple text node added to the tooltip instead.");
 
       is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent,
         "The inspected property's value is correct.");
-      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className),
+      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.includes(className),
         "The inspected property's value is colorized correctly.");
     }
 
     callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect properties.
     yield openVarPopup(panel, { line: 19, ch: 10 });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js
@@ -18,17 +18,17 @@ function test() {
     function verifySimpleContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view container added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
         "There should be one simple text node added to the tooltip.");
 
       is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent,
         "The inspected property's value is correct.");
-      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className),
+      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.includes(className),
         "The inspected property's value is colorized correctly.");
     }
 
     function verifyComplexContents(propertyCount) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 1,
         "There should be one variables view container added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 0,
         "There should be no simple text node added to the tooltip.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js
@@ -20,17 +20,17 @@ function test() {
     function verifyContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view containers added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
         "There should be a simple text node added to the tooltip instead.");
 
       is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent,
         "The inspected property's value is correct.");
-      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className),
+      ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.includes(className),
         "The inspected property's value is colorized correctly.");
     }
 
     function checkView(selectedFrame, caretLine) {
       is(win.gThreadClient.state, "paused",
         "Should only be getting stack frames while paused.");
       is(frames.itemCount, 2,
         "Should have two frames.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-webidl.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-webidl.js
@@ -56,161 +56,161 @@ function performTest() {
   let buttonVar = globalScope.get("button");
   let buttonAsProtoVar = globalScope.get("buttonAsProto");
   let documentVar = globalScope.get("document");
 
   is(buttonVar.target.querySelector(".name").getAttribute("value"), "button",
     "Should have the right property name for 'button'.");
   is(buttonVar.target.querySelector(".value").getAttribute("value"), "<button>",
     "Should have the right property value for 'button'.");
-  ok(buttonVar.target.querySelector(".value").className.contains("token-domnode"),
+  ok(buttonVar.target.querySelector(".value").className.includes("token-domnode"),
     "Should have the right token class for 'button'.");
 
   is(buttonAsProtoVar.target.querySelector(".name").getAttribute("value"), "buttonAsProto",
     "Should have the right property name for 'buttonAsProto'.");
   is(buttonAsProtoVar.target.querySelector(".value").getAttribute("value"), "Object",
     "Should have the right property value for 'buttonAsProto'.");
-  ok(buttonAsProtoVar.target.querySelector(".value").className.contains("token-other"),
+  ok(buttonAsProtoVar.target.querySelector(".value").className.includes("token-other"),
     "Should have the right token class for 'buttonAsProto'.");
 
   is(documentVar.target.querySelector(".name").getAttribute("value"), "document",
     "Should have the right property name for 'document'.");
   is(documentVar.target.querySelector(".value").getAttribute("value"),
     "HTMLDocument \u2192 doc_frame-parameters.html",
     "Should have the right property value for 'document'.");
-  ok(documentVar.target.querySelector(".value").className.contains("token-domnode"),
+  ok(documentVar.target.querySelector(".value").className.includes("token-domnode"),
     "Should have the right token class for 'document'.");
 
   is(buttonVar.expanded, false,
     "The buttonVar should not be expanded at this point.");
   is(buttonAsProtoVar.expanded, false,
     "The buttonAsProtoVar should not be expanded at this point.");
   is(documentVar.expanded, false,
     "The documentVar should not be expanded at this point.");
 
   waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES, 3).then(() => {
     is(buttonVar.get("type").target.querySelector(".name").getAttribute("value"), "type",
       "Should have the right property name for 'type'.");
     is(buttonVar.get("type").target.querySelector(".value").getAttribute("value"), "\"submit\"",
       "Should have the right property value for 'type'.");
-    ok(buttonVar.get("type").target.querySelector(".value").className.contains("token-string"),
+    ok(buttonVar.get("type").target.querySelector(".value").className.includes("token-string"),
       "Should have the right token class for 'type'.");
 
     is(buttonVar.get("childNodes").target.querySelector(".name").getAttribute("value"), "childNodes",
       "Should have the right property name for 'childNodes'.");
     is(buttonVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList[1]",
       "Should have the right property value for 'childNodes'.");
-    ok(buttonVar.get("childNodes").target.querySelector(".value").className.contains("token-other"),
+    ok(buttonVar.get("childNodes").target.querySelector(".value").className.includes("token-other"),
       "Should have the right token class for 'childNodes'.");
 
     is(buttonVar.get("onclick").target.querySelector(".name").getAttribute("value"), "onclick",
       "Should have the right property name for 'onclick'.");
     is(buttonVar.get("onclick").target.querySelector(".value").getAttribute("value"), "onclick(event)",
       "Should have the right property value for 'onclick'.");
-    ok(buttonVar.get("onclick").target.querySelector(".value").className.contains("token-other"),
+    ok(buttonVar.get("onclick").target.querySelector(".value").className.includes("token-other"),
       "Should have the right token class for 'onclick'.");
 
     is(documentVar.get("title").target.querySelector(".name").getAttribute("value"), "title",
       "Should have the right property name for 'title'.");
     is(documentVar.get("title").target.querySelector(".value").getAttribute("value"), "\"Debugger test page\"",
       "Should have the right property value for 'title'.");
-    ok(documentVar.get("title").target.querySelector(".value").className.contains("token-string"),
+    ok(documentVar.get("title").target.querySelector(".value").className.includes("token-string"),
       "Should have the right token class for 'title'.");
 
     is(documentVar.get("childNodes").target.querySelector(".name").getAttribute("value"), "childNodes",
       "Should have the right property name for 'childNodes'.");
     is(documentVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList[3]",
       "Should have the right property value for 'childNodes'.");
-    ok(documentVar.get("childNodes").target.querySelector(".value").className.contains("token-other"),
+    ok(documentVar.get("childNodes").target.querySelector(".value").className.includes("token-other"),
       "Should have the right token class for 'childNodes'.");
 
     is(documentVar.get("onclick").target.querySelector(".name").getAttribute("value"), "onclick",
       "Should have the right property name for 'onclick'.");
     is(documentVar.get("onclick").target.querySelector(".value").getAttribute("value"), "null",
       "Should have the right property value for 'onclick'.");
-    ok(documentVar.get("onclick").target.querySelector(".value").className.contains("token-null"),
+    ok(documentVar.get("onclick").target.querySelector(".value").className.includes("token-null"),
       "Should have the right token class for 'onclick'.");
 
     let buttonProtoVar = buttonVar.get("__proto__");
     let buttonAsProtoProtoVar = buttonAsProtoVar.get("__proto__");
     let documentProtoVar = documentVar.get("__proto__");
 
     is(buttonProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
       "Should have the right property name for '__proto__'.");
     is(buttonProtoVar.target.querySelector(".value").getAttribute("value"), "HTMLButtonElementPrototype",
       "Should have the right property value for '__proto__'.");
-    ok(buttonProtoVar.target.querySelector(".value").className.contains("token-other"),
+    ok(buttonProtoVar.target.querySelector(".value").className.includes("token-other"),
       "Should have the right token class for '__proto__'.");
 
     is(buttonAsProtoProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
       "Should have the right property name for '__proto__'.");
     is(buttonAsProtoProtoVar.target.querySelector(".value").getAttribute("value"), "<button>",
       "Should have the right property value for '__proto__'.");
-    ok(buttonAsProtoProtoVar.target.querySelector(".value").className.contains("token-domnode"),
+    ok(buttonAsProtoProtoVar.target.querySelector(".value").className.includes("token-domnode"),
       "Should have the right token class for '__proto__'.");
 
     is(documentProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
       "Should have the right property name for '__proto__'.");
     is(documentProtoVar.target.querySelector(".value").getAttribute("value"), "HTMLDocumentPrototype",
       "Should have the right property value for '__proto__'.");
-    ok(documentProtoVar.target.querySelector(".value").className.contains("token-other"),
+    ok(documentProtoVar.target.querySelector(".value").className.includes("token-other"),
       "Should have the right token class for '__proto__'.");
 
     is(buttonProtoVar.expanded, false,
       "The buttonProtoVar should not be expanded at this point.");
     is(buttonAsProtoProtoVar.expanded, false,
       "The buttonAsProtoProtoVar should not be expanded at this point.");
     is(documentProtoVar.expanded, false,
       "The documentProtoVar should not be expanded at this point.");
 
     waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES, 3).then(() => {
       is(buttonAsProtoProtoVar.get("type").target.querySelector(".name").getAttribute("value"), "type",
         "Should have the right property name for 'type'.");
       is(buttonAsProtoProtoVar.get("type").target.querySelector(".value").getAttribute("value"), "\"submit\"",
         "Should have the right property value for 'type'.");
-      ok(buttonAsProtoProtoVar.get("type").target.querySelector(".value").className.contains("token-string"),
+      ok(buttonAsProtoProtoVar.get("type").target.querySelector(".value").className.includes("token-string"),
         "Should have the right token class for 'type'.");
 
       is(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".name").getAttribute("value"), "childNodes",
         "Should have the right property name for 'childNodes'.");
       is(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".value").getAttribute("value"), "NodeList[1]",
         "Should have the right property value for 'childNodes'.");
-      ok(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".value").className.contains("token-other"),
+      ok(buttonAsProtoProtoVar.get("childNodes").target.querySelector(".value").className.includes("token-other"),
         "Should have the right token class for 'childNodes'.");
 
       is(buttonAsProtoProtoVar.get("onclick").target.querySelector(".name").getAttribute("value"), "onclick",
         "Should have the right property name for 'onclick'.");
       is(buttonAsProtoProtoVar.get("onclick").target.querySelector(".value").getAttribute("value"), "onclick(event)",
         "Should have the right property value for 'onclick'.");
-      ok(buttonAsProtoProtoVar.get("onclick").target.querySelector(".value").className.contains("token-other"),
+      ok(buttonAsProtoProtoVar.get("onclick").target.querySelector(".value").className.includes("token-other"),
         "Should have the right token class for 'onclick'.");
 
       let buttonProtoProtoVar = buttonProtoVar.get("__proto__");
       let buttonAsProtoProtoProtoVar = buttonAsProtoProtoVar.get("__proto__");
       let documentProtoProtoVar = documentProtoVar.get("__proto__");
 
       is(buttonProtoProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
         "Should have the right property name for '__proto__'.");
       is(buttonProtoProtoVar.target.querySelector(".value").getAttribute("value"), "HTMLElementPrototype",
         "Should have the right property value for '__proto__'.");
-      ok(buttonProtoProtoVar.target.querySelector(".value").className.contains("token-other"),
+      ok(buttonProtoProtoVar.target.querySelector(".value").className.includes("token-other"),
         "Should have the right token class for '__proto__'.");
 
       is(buttonAsProtoProtoProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
         "Should have the right property name for '__proto__'.");
       is(buttonAsProtoProtoProtoVar.target.querySelector(".value").getAttribute("value"), "HTMLButtonElementPrototype",
         "Should have the right property value for '__proto__'.");
-      ok(buttonAsProtoProtoProtoVar.target.querySelector(".value").className.contains("token-other"),
+      ok(buttonAsProtoProtoProtoVar.target.querySelector(".value").className.includes("token-other"),
         "Should have the right token class for '__proto__'.");
 
       is(documentProtoProtoVar.target.querySelector(".name").getAttribute("value"), "__proto__",
         "Should have the right property name for '__proto__'.");
       is(documentProtoProtoVar.target.querySelector(".value").getAttribute("value"), "DocumentPrototype",
         "Should have the right property value for '__proto__'.");
-      ok(documentProtoProtoVar.target.querySelector(".value").className.contains("token-other"),
+      ok(documentProtoProtoVar.target.querySelector(".value").className.includes("token-other"),
         "Should have the right token class for '__proto__'.")
 
       is(buttonAsProtoProtoProtoVar.expanded, false,
         "The buttonAsProtoProtoProtoVar should not be expanded at this point.");
       is(buttonAsProtoProtoProtoVar.expanded, false,
         "The buttonAsProtoProtoProtoVar should not be expanded at this point.");
       is(documentProtoProtoVar.expanded, false,
         "The documentProtoProtoVar should not be expanded at this point.");
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -253,33 +253,33 @@ function waitForTime(aDelay) {
   return deferred.promise;
 }
 
 function waitForSourceShown(aPanel, aUrl) {
   return waitForDebuggerEvents(aPanel, aPanel.panelWin.EVENTS.SOURCE_SHOWN).then(aSource => {
     let sourceUrl = aSource.url || aSource.introductionUrl;
     info("Source shown: " + sourceUrl);
 
-    if (!sourceUrl.contains(aUrl)) {
+    if (!sourceUrl.includes(aUrl)) {
       return waitForSourceShown(aPanel, aUrl);
     } else {
       ok(true, "The correct source has been shown.");
     }
   });
 }
 
 function waitForEditorLocationSet(aPanel) {
   return waitForDebuggerEvents(aPanel, aPanel.panelWin.EVENTS.EDITOR_LOCATION_SET);
 }
 
 function ensureSourceIs(aPanel, aUrlOrSource, aWaitFlag = false) {
   let sources = aPanel.panelWin.DebuggerView.Sources;
 
   if (sources.selectedValue === aUrlOrSource ||
-      sources.selectedItem.attachment.source.url.contains(aUrlOrSource)) {
+      sources.selectedItem.attachment.source.url.includes(aUrlOrSource)) {
     ok(true, "Expected source is shown: " + aUrlOrSource);
     return promise.resolve(null);
   }
   if (aWaitFlag) {
     return waitForSourceShown(aPanel, aUrlOrSource);
   }
   ok(false, "Expected source was not already shown: " + aUrlOrSource);
   return promise.reject(null);
--- a/browser/devtools/debugger/utils.js
+++ b/browser/devtools/debugger/utils.js
@@ -44,17 +44,17 @@ const SourceUtils = {
    * Returns true if the specified url and/or content type are specific to
    * javascript files.
    *
    * @return boolean
    *         True if the source is likely javascript.
    */
   isJavaScript: function(aUrl, aContentType = "") {
     return (aUrl && /\.jsm?$/.test(this.trimUrlQuery(aUrl))) ||
-           aContentType.contains("javascript");
+           aContentType.includes("javascript");
   },
 
   /**
    * Determines if the source text is minified by using
    * the percentage indented of a subset of lines
    *
    * @return object
    *         A promise that resolves to true if source text is minified.
--- a/browser/devtools/debugger/views/event-listeners-view.js
+++ b/browser/devtools/debugger/views/event-listeners-view.js
@@ -79,17 +79,17 @@ EventListenersView.prototype = Heritage.
         targets.setAttribute("value", L10N.getFormatStr("eventNodes", selectors.length));
       }
       return;
     }
 
     // There's no easy way of grouping event types into higher-level groups,
     // so we need to do this by hand.
     let is = (...args) => args.indexOf(type) != -1;
-    let has = str => type.contains(str);
+    let has = str => type.includes(str);
     let starts = str => type.startsWith(str);
     let group;
 
     if (starts("animation")) {
       group = L10N.getStr("animationEvents");
     } else if (starts("audio")) {
       group = L10N.getStr("audioEvents");
     } else if (is("levelchange")) {
--- a/browser/devtools/debugger/views/global-search-view.js
+++ b/browser/devtools/debugger/views/global-search-view.js
@@ -145,31 +145,31 @@ GlobalSearchView.prototype = Heritage.ex
     for (let [actor, text] of aSources) {
       let item = this.DebuggerView.Sources.getItemByValue(actor);
       let url = item.attachment.source.url;
       if (!url) {
         continue;
       }
 
       // Verify that the search token is found anywhere in the source.
-      if (!text.toLowerCase().contains(lowerCaseToken)) {
+      if (!text.toLowerCase().includes(lowerCaseToken)) {
         continue;
       }
       // ...and if so, create a Map containing search details for each line.
       let sourceResults = new SourceResults(actor,
                                             globalResults,
                                             this.DebuggerView.Sources);
 
       // Search for the specified token in each line's text.
       text.split("\n").forEach((aString, aLine) => {
         // Search is not case sensitive, prepare the actual searched line.
         let lowerCaseLine = aString.toLowerCase();
 
         // Verify that the search token is found anywhere in this line.
-        if (!lowerCaseLine.contains(lowerCaseToken)) {
+        if (!lowerCaseLine.includes(lowerCaseToken)) {
           return;
         }
         // ...and if so, create a Map containing search details for each word.
         let lineResults = new LineResults(aLine, sourceResults);
 
         // Search for the specified token this line's text.
         lowerCaseLine.split(lowerCaseToken).reduce((aPrev, aCurr, aIndex, aArray) => {
           let prevLength = aPrev.length;
--- a/browser/devtools/debugger/views/tracer-view.js
+++ b/browser/devtools/debugger/views/tracer-view.js
@@ -292,17 +292,17 @@ TracerView.prototype = Heritage.extend(W
     }
   },
 
   /**
    * Listener for typing in the search box.
    */
   _onSearch: function() {
     const query = this._search.value.trim().toLowerCase();
-    const predicate = name => name.toLowerCase().contains(query);
+    const predicate = name => name.toLowerCase().includes(query);
     this.filterContents(item => predicate(item.attachment.trace.name));
   },
 
   /**
    * Select the traces tab in the sidebar.
    */
   selectTab: function() {
     const tabs = this._tracerTab.parentElement;
--- a/browser/devtools/framework/test/browser_toolbox_tool_remote_reopen.js
+++ b/browser/devtools/framework/test/browser_toolbox_tool_remote_reopen.js
@@ -109,22 +109,22 @@ function test() {
     for (let pool of client.__pools) {
       if (!pool.__poolMap) {
         continue;
       }
       for (let actor of pool.__poolMap.keys()) {
         // Bug 1056342: Profiler fails today because of framerate actor, but
         // this appears more complex to rework, so leave it for that bug to
         // resolve.
-        if (actor.contains("framerateActor")) {
+        if (actor.includes("framerateActor")) {
           todo(false, "Front for " + actor + " still held in pool!");
           continue;
         }
         // gcliActor is for the commandline which is separate to the toolbox
-        if (actor.contains("gcliActor")) {
+        if (actor.includes("gcliActor")) {
           continue;
         }
         ok(false, "Front for " + actor + " still held in pool!");
       }
     }
 
     gBrowser.removeCurrentTab();
     DebuggerServer.destroy();
--- a/browser/devtools/framework/test/browser_toolbox_window_shortcuts.js
+++ b/browser/devtools/framework/test/browser_toolbox_window_shortcuts.js
@@ -43,19 +43,19 @@ function testShortcuts(aToolbox, aIndex)
   toolbox = aToolbox;
   info("Toolbox fired a `ready` event");
 
   toolbox.once("select", selectCB);
 
   let key = gDevTools._tools.get(toolIDs[aIndex]).key;
   let toolModifiers = gDevTools._tools.get(toolIDs[aIndex]).modifiers;
   let modifiers = {
-    accelKey: toolModifiers.contains("accel"),
-    altKey: toolModifiers.contains("alt"),
-    shiftKey: toolModifiers.contains("shift"),
+    accelKey: toolModifiers.includes("accel"),
+    altKey: toolModifiers.includes("alt"),
+    shiftKey: toolModifiers.includes("shift"),
   };
   idIndex = aIndex;
   info("Testing shortcut for tool " + aIndex + ":" + toolIDs[aIndex] +
        " using key " + key);
   EventUtils.synthesizeKey(key, modifiers, toolbox.doc.defaultView.parent);
 }
 
 function selectCB(event, id) {
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -1657,23 +1657,23 @@ Toolbox.prototype = {
     if (dims === "2560×1600") return 9;
     if (dims === "2880x1800") return 10;
     if (width.value > 2880 || height.value > 1800) return 12;
 
     return 11; // Other dimension such as a VM.
   },
 
   _getOsCpu: function() {
-    if (oscpu.contains("NT 5.1") || oscpu.contains("NT 5.2")) return 0;
-    if (oscpu.contains("NT 6.0")) return 1;
-    if (oscpu.contains("NT 6.1")) return 2;
-    if (oscpu.contains("NT 6.2")) return 3;
-    if (oscpu.contains("NT 6.3")) return 4;
-    if (oscpu.contains("OS X"))   return 5;
-    if (oscpu.contains("Linux"))  return 6;
+    if (oscpu.includes("NT 5.1") || oscpu.includes("NT 5.2")) return 0;
+    if (oscpu.includes("NT 6.0")) return 1;
+    if (oscpu.includes("NT 6.1")) return 2;
+    if (oscpu.includes("NT 6.2")) return 3;
+    if (oscpu.includes("NT 6.3")) return 4;
+    if (oscpu.includes("OS X"))   return 5;
+    if (oscpu.includes("Linux"))  return 6;
 
     return 12; // Other OS.
   },
 
   /**
    * Destroy the current host, and remove event listeners from its frame.
    *
    * @return {promise} to be resolved when the host is destroyed.
--- a/browser/devtools/inspector/test/browser_inspector_menu-03-paste-items.js
+++ b/browser/devtools/inspector/test/browser_inspector_menu-03-paste-items.js
@@ -55,17 +55,17 @@ add_task(function* () {
 
     let onNodeReselected = inspector.markup.once("reselectedonremoved");
     let menu = inspector.panelDoc.getElementById("node-menu-pasteouterhtml");
     dispatchCommandEvent(menu);
 
     info("Waiting for inspector selection to update");
     yield onNodeReselected;
 
-    ok(content.document.body.outerHTML.contains(clipboard.get()),
+    ok(content.document.body.outerHTML.includes(clipboard.get()),
        "Clipboard content was pasted into the node's outer HTML.");
     ok(!getNode(outerHTMLSelector, { expectNoMatch: true }),
       "The original node was removed.");
   }
 
   function* testPasteInnerHTMLMenu() {
     info("Testing that 'Paste Inner HTML' menu item works.");
     clipboard.set("this was pasted (innerHTML)");
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -2487,18 +2487,18 @@ ElementEditor.prototype = {
     };
     this.template("attribute", data);
     var {attr, inner, name, val} = data;
 
     // Double quotes need to be handled specially to prevent DOMParser failing.
     // name="v"a"l"u"e" when editing -> name='v"a"l"u"e"'
     // name="v'a"l'u"e" when editing -> name="v'a&quot;l'u&quot;e"
     let editValueDisplayed = aAttr.value || "";
-    let hasDoubleQuote = editValueDisplayed.contains('"');
-    let hasSingleQuote = editValueDisplayed.contains("'");
+    let hasDoubleQuote = editValueDisplayed.includes('"');
+    let hasSingleQuote = editValueDisplayed.includes("'");
     let initial = aAttr.name + '="' + editValueDisplayed + '"';
 
     // Can't just wrap value with ' since the value contains both " and '.
     if (hasDoubleQuote && hasSingleQuote) {
         editValueDisplayed = editValueDisplayed.replace(/\"/g, "&quot;");
         initial = aAttr.name + '="' + editValueDisplayed + '"';
     }
 
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -983,61 +983,61 @@ RequestsMenuView.prototype = Heritage.ex
    * Predicates used when filtering items.
    *
    * @param object aItem
    *        The filtered item.
    * @return boolean
    *         True if the item should be visible, false otherwise.
    */
   isHtml: function({ attachment: { mimeType } })
-    mimeType && mimeType.contains("/html"),
+    mimeType && mimeType.includes("/html"),
 
   isCss: function({ attachment: { mimeType } })
-    mimeType && mimeType.contains("/css"),
+    mimeType && mimeType.includes("/css"),
 
   isJs: function({ attachment: { mimeType } })
     mimeType && (
-      mimeType.contains("/ecmascript") ||
-      mimeType.contains("/javascript") ||
-      mimeType.contains("/x-javascript")),
+      mimeType.includes("/ecmascript") ||
+      mimeType.includes("/javascript") ||
+      mimeType.includes("/x-javascript")),
 
   isXHR: function({ attachment: { isXHR } })
     isXHR,
 
   isFont: function({ attachment: { url, mimeType } }) // Fonts are a mess.
     (mimeType && (
-      mimeType.contains("font/") ||
-      mimeType.contains("/font"))) ||
-    url.contains(".eot") ||
-    url.contains(".ttf") ||
-    url.contains(".otf") ||
-    url.contains(".woff"),
+      mimeType.includes("font/") ||
+      mimeType.includes("/font"))) ||
+    url.includes(".eot") ||
+    url.includes(".ttf") ||
+    url.includes(".otf") ||
+    url.includes(".woff"),
 
   isImage: function({ attachment: { mimeType } })
-    mimeType && mimeType.contains("image/"),
+    mimeType && mimeType.includes("image/"),
 
   isMedia: function({ attachment: { mimeType } }) // Not including images.
     mimeType && (
-      mimeType.contains("audio/") ||
-      mimeType.contains("video/") ||
-      mimeType.contains("model/")),
+      mimeType.includes("audio/") ||
+      mimeType.includes("video/") ||
+      mimeType.includes("model/")),
 
   isFlash: function({ attachment: { url, mimeType } }) // Flash is a mess.
     (mimeType && (
-      mimeType.contains("/x-flv") ||
-      mimeType.contains("/x-shockwave-flash"))) ||
-    url.contains(".swf") ||
-    url.contains(".flv"),
+      mimeType.includes("/x-flv") ||
+      mimeType.includes("/x-shockwave-flash"))) ||
+    url.includes(".swf") ||
+    url.includes(".flv"),
 
   isOther: function(e)
     !this.isHtml(e) && !this.isCss(e) && !this.isJs(e) && !this.isXHR(e) &&
     !this.isFont(e) && !this.isImage(e) && !this.isMedia(e) && !this.isFlash(e),
 
   isFreetextMatch: function({ attachment: { url } }, text) //no text is a positive match
-    !text || url.contains(text),
+    !text || url.includes(text),
 
   /**
    * Predicates used when sorting items.
    *
    * @param object aFirst
    *        The first item used in the comparison.
    * @param object aSecond
    *        The second item used in the comparison.
@@ -1489,17 +1489,17 @@ RequestsMenuView.prototype = Heritage.ex
         node.setAttribute("value", text);
         node.setAttribute("tooltiptext", aValue);
         break;
       }
       case "responseContent": {
         let { mimeType } = aItem.attachment;
         let { text, encoding } = aValue.content;
 
-        if (mimeType.contains("image/")) {
+        if (mimeType.includes("image/")) {
           let responseBody = yield gNetwork.getString(text);
           let node = $(".requests-menu-icon", aItem.target);
           node.src = "data:" + mimeType + ";" + encoding + "," + responseBody;
           node.setAttribute("type", "thumbnail");
           node.removeAttribute("hidden");
 
           window.emit(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
         }
@@ -1778,17 +1778,17 @@ RequestsMenuView.prototype = Heritage.ex
     if (!requestItem || !requestItem.attachment.responseContent) {
       return;
     }
 
     let hovered = requestItem.attachment;
     let { url } = hovered;
     let { mimeType, text, encoding } = hovered.responseContent.content;
 
-    if (mimeType && mimeType.contains("image/") && (
+    if (mimeType && mimeType.includes("image/") && (
       aTarget.classList.contains("requests-menu-icon") ||
       aTarget.classList.contains("requests-menu-file")))
     {
       return gNetwork.getString(text).then(aString => {
         let anchor = $(".requests-menu-icon", requestItem.target);
         let src = "data:" + mimeType + ";" + encoding + "," + aString;
         aTooltip.setImageContent(src, { maxDim: REQUESTS_TOOLTIP_IMAGE_MAX_DIM });
         return anchor;
@@ -1843,17 +1843,17 @@ RequestsMenuView.prototype = Heritage.ex
     copyResponse.hidden = !selectedItem ||
       !selectedItem.attachment.responseContent ||
       !selectedItem.attachment.responseContent.content.text ||
       selectedItem.attachment.responseContent.content.text.length === 0;
 
     let copyImageAsDataUriElement = $("#request-menu-context-copy-image-as-data-uri");
     copyImageAsDataUriElement.hidden = !selectedItem ||
       !selectedItem.attachment.responseContent ||
-      !selectedItem.attachment.responseContent.content.mimeType.contains("image/");
+      !selectedItem.attachment.responseContent.content.mimeType.includes("image/");
 
     let separator = $("#request-menu-context-separator");
     separator.hidden = !selectedItem;
 
     let newTabElement = $("#request-menu-context-newtab");
     newTabElement.hidden = !selectedItem;
   },
 
@@ -2598,17 +2598,17 @@ NetworkDetailsView.prototype = {
     let contentTypeHeader = allHeaders.find(e => e.name.toLowerCase() == "content-type");
     let contentTypeLongString = contentTypeHeader ? contentTypeHeader.value : "";
     let postDataLongString = aPostDataResponse.postData.text;
 
     let postData = yield gNetwork.getString(postDataLongString);
     let contentType = yield gNetwork.getString(contentTypeLongString);
 
     // Handle query strings (e.g. "?foo=bar&baz=42").
-    if (contentType.contains("x-www-form-urlencoded")) {
+    if (contentType.includes("x-www-form-urlencoded")) {
       for (let section of postData.split(/\r\n|\r|\n/)) {
         // Before displaying it, make sure this section of the POST data
         // isn't a line containing upload stream headers.
         if (payloadHeaders.every(header => !section.startsWith(header.name))) {
           this._addParams(this._paramsFormData, section);
         }
       }
     }
@@ -2728,17 +2728,17 @@ NetworkDetailsView.prototype = {
         infoHeader.hidden = false;
 
         let editor = yield NetMonitorView.editor("#response-content-textarea");
         editor.setMode(Editor.modes.js);
         editor.setText(responseBody);
       }
     }
     // Handle images.
-    else if (mimeType.contains("image/")) {
+    else if (mimeType.includes("image/")) {
       $("#response-content-image-box").setAttribute("align", "center");
       $("#response-content-image-box").setAttribute("pack", "center");
       $("#response-content-image-box").hidden = false;
       $("#response-content-image").src =
         "data:" + mimeType + ";" + encoding + "," + responseBody;
 
       // Immediately display additional information about the image:
       // file name, mime type and encoding.
@@ -2761,17 +2761,17 @@ NetworkDetailsView.prototype = {
       $("#response-content-textarea-box").hidden = false;
       let editor = yield NetMonitorView.editor("#response-content-textarea");
       editor.setMode(Editor.modes.text);
       editor.setText(responseBody);
 
       // Maybe set a more appropriate mode in the Source Editor if possible,
       // but avoid doing this for very large files.
       if (responseBody.length < SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
-        let mapping = Object.keys(CONTENT_MIME_TYPE_MAPPINGS).find(key => mimeType.contains(key));
+        let mapping = Object.keys(CONTENT_MIME_TYPE_MAPPINGS).find(key => mimeType.includes(key));
         if (mapping) {
           editor.setMode(CONTENT_MIME_TYPE_MAPPINGS[mapping]);
         }
       }
     }
 
     window.emit(EVENTS.RESPONSE_BODY_DISPLAYED);
   }),
--- a/browser/devtools/netmonitor/test/browser_net_content-type.js
+++ b/browser/devtools/netmonitor/test/browser_net_content-type.js
@@ -9,17 +9,17 @@ function test() {
   initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
     let { document, L10N, Editor, NetMonitorView } = aMonitor.panelWin;
     let { RequestsMenu } = NetMonitorView;
 
     RequestsMenu.lazyUpdate = false;
 
-    waitForNetworkEvents(aMonitor, 6).then(() => {
+    waitForNetworkEvents(aMonitor, 7).then(() => {
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
         "GET", CONTENT_TYPE_SJS + "?fmt=xml", {
           status: 200,
           statusText: "OK",
           type: "xml",
           fullMimeType: "text/xml; charset=utf-8",
           size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
           time: true
@@ -65,16 +65,25 @@ function test() {
           fuzzyUrl: true,
           status: 200,
           statusText: "OK",
           type: "png",
           fullMimeType: "image/png",
           size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.76),
           time: true
         });
+      verifyRequestItemTarget(RequestsMenu.getItemAtIndex(6),
+        "GET", CONTENT_TYPE_SJS + "?fmt=gzip", {
+          status: 200,
+          statusText: "OK",
+          type: "plain",
+          fullMimeType: "text/plain",
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 10.73),
+          time: true
+        });
 
       EventUtils.sendMouseEvent({ type: "mousedown" },
         document.getElementById("details-pane-toggle"));
       EventUtils.sendMouseEvent({ type: "mousedown" },
         document.querySelectorAll("#details-pane tab")[3]);
 
       Task.spawn(function*() {
         yield waitForResponseBodyDisplayed();
@@ -89,16 +98,19 @@ function test() {
         yield waitForTabUpdated();
         yield testResponseTab("json");
         RequestsMenu.selectedIndex = 4;
         yield waitForTabUpdated();
         yield testResponseTab("html");
         RequestsMenu.selectedIndex = 5;
         yield waitForTabUpdated();
         yield testResponseTab("png");
+        RequestsMenu.selectedIndex = 6;
+        yield waitForTabUpdated();
+        yield testResponseTab("gzip");
         yield teardown(aMonitor);
         finish();
       });
 
       function testResponseTab(aType) {
         let tab = document.querySelectorAll("#details-pane tab")[3];
         let tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
 
@@ -211,16 +223,29 @@ function test() {
                 .getAttribute("value"), "16" + " \u00D7 " + "16",
                 "The image dimensions info isn't correct.");
 
               deferred.resolve();
             });
 
             return deferred.promise;
           }
+
+          case "gzip": {
+            checkVisibility("textarea");
+
+            let expected = new Array(1000).join("Hello gzip!");
+            return NetMonitorView.editor("#response-content-textarea").then((aEditor) => {
+              is(aEditor.getText(), expected,
+                "The text shown in the source editor is incorrect for the gzip request.");
+              is(aEditor.getMode(), Editor.modes.text,
+                "The mode active in the source editor is incorrect for the gzip request.");
+            });
+          }
+
         }
       }
 
       function waitForTabUpdated () {
         return waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.TAB_UPDATED);
       }
 
       function waitForResponseBodyDisplayed () {
--- a/browser/devtools/netmonitor/test/browser_net_copy_image_as_data_uri.js
+++ b/browser/devtools/netmonitor/test/browser_net_copy_image_as_data_uri.js
@@ -9,17 +9,17 @@ function test() {
   initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
     let { NetMonitorView } = aMonitor.panelWin;
     let { RequestsMenu } = NetMonitorView;
 
     RequestsMenu.lazyUpdate = false;
 
-    waitForNetworkEvents(aMonitor, 6).then(() => {
+    waitForNetworkEvents(aMonitor, 7).then(() => {
       let requestItem = RequestsMenu.getItemAtIndex(5);
       RequestsMenu.selectedItem = requestItem;
 
       waitForClipboard(TEST_IMAGE_DATA_URI, function setup() {
         RequestsMenu.copyImageAsDataUri();
       }, function onSuccess() {
         ok(true, "Clipboard contains the currently selected image as data uri.");
         cleanUp();
--- a/browser/devtools/netmonitor/test/browser_net_copy_response.js
+++ b/browser/devtools/netmonitor/test/browser_net_copy_response.js
@@ -11,17 +11,17 @@ function test() {
 
     const EXPECTED_RESULT = '{ "greeting": "Hello JSON!" }';
 
     let { NetMonitorView } = aMonitor.panelWin;
     let { RequestsMenu } = NetMonitorView;
 
     RequestsMenu.lazyUpdate = false;
 
-    waitForNetworkEvents(aMonitor, 6).then(() => {
+    waitForNetworkEvents(aMonitor, 7).then(() => {
       let requestItem = RequestsMenu.getItemAtIndex(3);
       RequestsMenu.selectedItem = requestItem;
 
       waitForClipboard(EXPECTED_RESULT, function setup() {
         RequestsMenu.copyResponse();
       }, function onSuccess() {
         ok(true, "Clipboard contains the currently selected item's response.");
         cleanUp();
--- a/browser/devtools/netmonitor/test/browser_net_icon-preview.js
+++ b/browser/devtools/netmonitor/test/browser_net_icon-preview.js
@@ -8,17 +8,17 @@
 function test() {
   initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
     let { $, $all, EVENTS, ACTIVITY_TYPE, NetMonitorView, NetMonitorController } = aMonitor.panelWin;
     let { RequestsMenu } = NetMonitorView;
 
     promise.all([
-      waitForNetworkEvents(aMonitor, 6),
+      waitForNetworkEvents(aMonitor, 7),
       waitFor(aMonitor.panelWin, EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED)
     ]).then(() => {
       info("Checking the image thumbnail when all items are shown.");
       checkImageThumbnail();
 
       RequestsMenu.sortBy("size");
       info("Checking the image thumbnail when all items are sorted.");
       checkImageThumbnail();
--- a/browser/devtools/netmonitor/test/browser_net_image-tooltip.js
+++ b/browser/devtools/netmonitor/test/browser_net_image-tooltip.js
@@ -8,17 +8,17 @@
 function test() {
   initNetMonitor(CONTENT_TYPE_WITHOUT_CACHE_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
     let { $, EVENTS, ACTIVITY_TYPE, NetMonitorView, NetMonitorController } = aMonitor.panelWin;
     let { RequestsMenu } = NetMonitorView;
 
     promise.all([
-      waitForNetworkEvents(aMonitor, 6),
+      waitForNetworkEvents(aMonitor, 7),
       waitFor(aMonitor.panelWin, EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED)
     ]).then(() => {
       info("Checking the image thumbnail after a few requests were made...");
       let requestItem = RequestsMenu.items[5];
       let requestTooltip = requestItem.attachment.tooltip;
       ok(requestTooltip, "There should be a tooltip instance for the image request.");
 
       let anchor = $(".requests-menu-file", requestItem.target);
--- a/browser/devtools/netmonitor/test/browser_net_post-data-01.js
+++ b/browser/devtools/netmonitor/test/browser_net_post-data-01.js
@@ -54,20 +54,20 @@ function test() {
         let tab = document.querySelectorAll("#details-pane tab")[2];
         let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
 
         is(tab.getAttribute("selected"), "true",
           "The params tab in the network details pane should be selected.");
 
         function checkVisibility(aBox) {
           is(tabpanel.querySelector("#request-params-box")
-            .hasAttribute("hidden"), !aBox.contains("params"),
+            .hasAttribute("hidden"), !aBox.includes("params"),
             "The request params box doesn't have the indended visibility.");
           is(tabpanel.querySelector("#request-post-data-textarea-box")
-            .hasAttribute("hidden"), !aBox.contains("textarea"),
+            .hasAttribute("hidden"), !aBox.includes("textarea"),
             "The request post data textarea box doesn't have the indended visibility.");
         }
 
         is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
           "There should be 2 param scopes displayed in this tabpanel.");
         is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
           "The empty notice should not be displayed in this tabpanel.");
 
@@ -122,29 +122,29 @@ function test() {
           is(tabpanel.querySelectorAll(".variables-view-variable").length, 3,
             "There should be 3 param values displayed in this tabpanel.");
           is(queryScope.querySelectorAll(".variables-view-variable").length, 3,
             "There should be 3 param values displayed in the query scope.");
           is(postScope.querySelectorAll(".variables-view-variable").length, 0,
             "There should be 0 param values displayed in the post scope.");
 
           return NetMonitorView.editor("#request-post-data-textarea").then((aEditor) => {
-            ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"text\""),
+            ok(aEditor.getText().includes("Content-Disposition: form-data; name=\"text\""),
               "The text shown in the source editor is incorrect (1.1).");
-            ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"email\""),
+            ok(aEditor.getText().includes("Content-Disposition: form-data; name=\"email\""),
               "The text shown in the source editor is incorrect (2.1).");
-            ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"range\""),
+            ok(aEditor.getText().includes("Content-Disposition: form-data; name=\"range\""),
               "The text shown in the source editor is incorrect (3.1).");
-            ok(aEditor.getText().contains("Content-Disposition: form-data; name=\"Custom field\""),
+            ok(aEditor.getText().includes("Content-Disposition: form-data; name=\"Custom field\""),
               "The text shown in the source editor is incorrect (4.1).");
-            ok(aEditor.getText().contains("Some text..."),
+            ok(aEditor.getText().includes("Some text..."),
               "The text shown in the source editor is incorrect (2.2).");
-            ok(aEditor.getText().contains("42"),
+            ok(aEditor.getText().includes("42"),
               "The text shown in the source editor is incorrect (3.2).");
-            ok(aEditor.getText().contains("Extra data"),
+            ok(aEditor.getText().includes("Extra data"),
               "The text shown in the source editor is incorrect (4.2).");
             is(aEditor.getMode(), Editor.modes.text,
               "The mode active in the source editor is incorrect.");
           });
         }
       }
     });
 
--- a/browser/devtools/netmonitor/test/browser_net_simple-request-details.js
+++ b/browser/devtools/netmonitor/test/browser_net_simple-request-details.js
@@ -74,17 +74,17 @@ function test() {
       let responseScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
       let requestScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
 
       is(responseScope.querySelector(".name").getAttribute("value"),
         L10N.getStr("responseHeaders") + " (" +
         L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(330/1024, 3)) + ")",
         "The response headers scope doesn't have the correct title.");
 
-      ok(requestScope.querySelector(".name").getAttribute("value").contains(
+      ok(requestScope.querySelector(".name").getAttribute("value").includes(
         L10N.getStr("requestHeaders") + " (0"),
         "The request headers scope doesn't have the correct title.");
       // Can't test for full request headers title because the size may
       // vary across platforms ("User-Agent" header differs). We're pretty
       // sure it's smaller than 1 MB though, so it starts with a 0.
 
       is(responseScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
         "Cache-Control", "The first response header name was incorrect.");
--- a/browser/devtools/netmonitor/test/html_content-type-without-cache-test-page.html
+++ b/browser/devtools/netmonitor/test/html_content-type-without-cache-test-page.html
@@ -29,17 +29,19 @@
 
       function performRequests() {
         get("sjs_content-type-test-server.sjs?fmt=xml", function() {
           get("sjs_content-type-test-server.sjs?fmt=css", function() {
             get("sjs_content-type-test-server.sjs?fmt=js", function() {
               get("sjs_content-type-test-server.sjs?fmt=json", function() {
                 get("sjs_content-type-test-server.sjs?fmt=bogus", function() {
                   get("test-image.png?v=" + Math.random(), function() {
-                    // Done.
+                    get("sjs_content-type-test-server.sjs?fmt=gzip", function() {
+                      // Done.
+                    });
                   });
                 });
               });
             });
           });
         });
       }
     </script>
--- a/browser/devtools/netmonitor/test/sjs_content-type-test-server.sjs
+++ b/browser/devtools/netmonitor/test/sjs_content-type-test-server.sjs
@@ -1,19 +1,46 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const { classes: Cc, interfaces: Ci } = Components;
 
+function gzipCompressString(string, obs) {
+
+  let scs = Cc["@mozilla.org/streamConverters;1"]
+           .getService(Ci.nsIStreamConverterService);
+  let listener = Cc["@mozilla.org/network/stream-loader;1"]
+                .createInstance(Ci.nsIStreamLoader);
+  listener.init(obs);
+  let converter = scs.asyncConvertData("uncompressed", "gzip",
+                                        listener, null);
+  let stringStream = Cc["@mozilla.org/io/string-input-stream;1"]
+                    .createInstance(Ci.nsIStringInputStream);
+  stringStream.data = string;
+  converter.onStartRequest(null, null);
+  converter.onDataAvailable(null, null, stringStream, 0, string.length);
+  converter.onStopRequest(null, null, null);
+}
+
+function doubleGzipCompressString(string, observer) {
+  let observer2 = {
+    onStreamComplete: function(loader, context, status, length, result) {
+      let buffer = String.fromCharCode.apply(this, result);
+      gzipCompressString(buffer, observer);
+    }
+  };
+  gzipCompressString(string, observer2);
+}
+
 function handleRequest(request, response) {
   response.processAsync();
 
   let params = request.queryString.split("&");
-  let format = (params.filter((s) => s.contains("fmt="))[0] || "").split("=")[1];
-  let status = (params.filter((s) => s.contains("sts="))[0] || "").split("=")[1] || 200;
+  let format = (params.filter((s) => s.includes("fmt="))[0] || "").split("=")[1];
+  let status = (params.filter((s) => s.includes("sts="))[0] || "").split("=")[1] || 200;
 
   let cachedCount = 0;
   let cacheExpire = 60; // seconds
 
   function setCacheHeaders() {
     if (status != 304) {
       response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
       response.setHeader("Pragma", "no-cache");
@@ -46,17 +73,17 @@ function handleRequest(request, response
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "text/xml; charset=utf-8", false);
         setCacheHeaders();
         response.write("<label value='greeting'>Hello XML!</label>");
         response.finish();
         break;
       }
       case "html": {
-        let content = params.filter((s) => s.contains("res="))[0].split("=")[1];
+        let content = params.filter((s) => s.includes("res="))[0].split("=")[1];
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "text/html; charset=utf-8", false);
         setCacheHeaders();
         response.write(content || "<p>Hello HTML!</p>");
         response.finish();
         break;
       }
       case "html-long": {
@@ -88,26 +115,26 @@ function handleRequest(request, response
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "application/json; charset=utf-8", false);
         setCacheHeaders();
         response.write("{ \"greeting\": \"Hello JSON!\" }");
         response.finish();
         break;
       }
       case "jsonp": {
-        let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1];
+        let fun = params.filter((s) => s.includes("jsonp="))[0].split("=")[1];
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "text/json; charset=utf-8", false);
         setCacheHeaders();
         response.write(fun + "({ \"greeting\": \"Hello JSONP!\" })");
         response.finish();
         break;
       }
       case "jsonp2": {
-        let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1];
+        let fun = params.filter((s) => s.includes("jsonp="))[0].split("=")[1];
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "text/json; charset=utf-8", false);
         setCacheHeaders();
         response.write(" " + fun + " ( { \"greeting\": \"Hello weird JSONP!\" } ) ; ");
         response.finish();
         break;
       }
       case "json-long": {
@@ -173,16 +200,35 @@ function handleRequest(request, response
       }
       case "flash": {
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "application/x-shockwave-flash", false);
         setCacheHeaders();
         response.finish();
         break;
       }
+      case "gzip": {
+        // Note: we're doing a double gzip encoding to test multiple
+        // converters in network monitor.
+        response.setStatusLine(request.httpVersion, status, "OK");
+        response.setHeader("Content-Type", "text/plain", false);
+        response.setHeader("Content-Encoding", "gzip\t ,gzip", false);
+        setCacheHeaders();
+        let observer = {
+          onStreamComplete: function(loader, context, status, length, result) {
+            let buffer = String.fromCharCode.apply(this, result);
+            response.setHeader("Content-Length", "" + buffer.length, false);
+            response.write(buffer);
+            response.finish();
+          }
+        };
+        let data = new Array(1000).join("Hello gzip!");
+        doubleGzipCompressString(data, observer);
+        break;
+      }
       default: {
         response.setStatusLine(request.httpVersion, 404, "Not Found");
         response.setHeader("Content-Type", "text/html; charset=utf-8", false);
         setCacheHeaders();
         response.write("<blink>Not Found</blink>");
         response.finish();
         break;
       }
--- a/browser/devtools/netmonitor/test/sjs_sorting-test-server.sjs
+++ b/browser/devtools/netmonitor/test/sjs_sorting-test-server.sjs
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const { classes: Cc, interfaces: Ci } = Components;
 
 function handleRequest(request, response) {
   response.processAsync();
 
   let params = request.queryString.split("&");
-  let index = params.filter((s) => s.contains("index="))[0].split("=")[1];
+  let index = params.filter((s) => s.includes("index="))[0].split("=")[1];
 
   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   timer.initWithCallback(() => {
     // to avoid garbage collection
     timer = null;
     response.setStatusLine(request.httpVersion, index == 1 ? 101 : index * 100, "Meh");
 
     response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
--- a/browser/devtools/netmonitor/test/sjs_status-codes-test-server.sjs
+++ b/browser/devtools/netmonitor/test/sjs_status-codes-test-server.sjs
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const { classes: Cc, interfaces: Ci } = Components;
 
 function handleRequest(request, response) {
   response.processAsync();
 
   let params = request.queryString.split("&");
-  let status = params.filter(s => s.contains("sts="))[0].split("=")[1];
+  let status = params.filter(s => s.includes("sts="))[0].split("=")[1];
   let cached = params.filter(s => s === 'cached').length !== 0;
 
   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   timer.initWithCallback(() => {
     // to avoid garbage collection
     timer = null;
     switch (status) {
       case "100":
--- a/browser/devtools/performance/test/browser_profiler_tree-view-02.js
+++ b/browser/devtools/performance/test/browser_profiler_tree-view-02.js
@@ -60,17 +60,17 @@ function test() {
   is($$perc(1).getAttribute("value"), "100%",
     "The .A node's percentage cell displays the correct value.");
   is($$sampl(1).getAttribute("value"), "4",
     "The .A node's samples cell displays the correct value.");
   is($$fun(".call-tree-name")[1].getAttribute("value"), "A",
     "The .A node's function cell displays the correct name.");
   is($$fun(".call-tree-url")[1].getAttribute("value"), "baz",
     "The .A node's function cell displays the correct url.");
-  ok($$fun(".call-tree-url")[1].getAttribute("tooltiptext").contains("http://foo/bar/baz"),
+  ok($$fun(".call-tree-url")[1].getAttribute("tooltiptext").includes("http://foo/bar/baz"),
     "The .A node's function cell displays the correct url tooltiptext.");
   is($$fun(".call-tree-line")[1].getAttribute("value"), ":12",
     "The .A node's function cell displays the correct line.");
   is($$fun(".call-tree-host")[1].getAttribute("value"), "foo",
     "The .A node's function cell displays the correct host.");
   is($$fun(".call-tree-category")[1].getAttribute("value"), "Gecko",
     "The .A node's function cell displays the correct category.");
 
@@ -89,17 +89,17 @@ function test() {
   is($$perc(2).getAttribute("value"), "75%",
     "The .A.B node's percentage cell displays the correct value.");
   is($$sampl(2).getAttribute("value"), "3",
     "The .A.B node's samples cell displays the correct value.");
   is($$fun(".call-tree-name")[2].getAttribute("value"), "B",
     "The .A.B node's function cell displays the correct name.");
   is($$fun(".call-tree-url")[2].getAttribute("value"), "baz",
     "The .A.B node's function cell displays the correct url.");
-  ok($$fun(".call-tree-url")[2].getAttribute("tooltiptext").contains("http://foo/bar/baz"),
+  ok($$fun(".call-tree-url")[2].getAttribute("tooltiptext").includes("http://foo/bar/baz"),
     "The .A.B node's function cell displays the correct url tooltiptext.");
   is($$fun(".call-tree-line")[2].getAttribute("value"), ":34",
     "The .A.B node's function cell displays the correct line.");
   is($$fun(".call-tree-host")[2].getAttribute("value"), "foo",
     "The .A.B node's function cell displays the correct host.");
   is($$fun(".call-tree-category")[2].getAttribute("value"), "Styles",
     "The .A.B node's function cell displays the correct category.");
 
@@ -108,17 +108,17 @@ function test() {
   is($$perc(3).getAttribute("value"), "25%",
     "The .A.E node's percentage cell displays the correct value.");
   is($$sampl(3).getAttribute("value"), "1",
     "The .A.E node's samples cell displays the correct value.");
   is($$fun(".call-tree-name")[3].getAttribute("value"), "E",
     "The .A.E node's function cell displays the correct name.");
   is($$fun(".call-tree-url")[3].getAttribute("value"), "baz",
     "The .A.E node's function cell displays the correct url.");
-  ok($$fun(".call-tree-url")[3].getAttribute("tooltiptext").contains("http://foo/bar/baz"),
+  ok($$fun(".call-tree-url")[3].getAttribute("tooltiptext").includes("http://foo/bar/baz"),
     "The .A.E node's function cell displays the correct url tooltiptext.");
   is($$fun(".call-tree-line")[3].getAttribute("value"), ":90",
     "The .A.E node's function cell displays the correct line.");
   is($$fun(".call-tree-host")[3].getAttribute("value"), "foo",
     "The .A.E node's function cell displays the correct host.");
   is($$fun(".call-tree-category")[3].getAttribute("value"), "GC",
     "The .A.E node's function cell displays the correct category.");
 
--- a/browser/devtools/projecteditor/lib/editors.js
+++ b/browser/devtools/projecteditor/lib/editors.js
@@ -129,18 +129,18 @@ var TextEditor = Class({
     let extraKeys = {};
 
     // Copy all of the registered keys into extraKeys object, to notify CodeMirror
     // that it should be ignoring these keys
     [...this.projectEditorKeyset.querySelectorAll("key")].forEach((key) => {
       let keyUpper = key.getAttribute("key").toUpperCase();
       let toolModifiers = key.getAttribute("modifiers");
       let modifiers = {
-        alt: toolModifiers.contains("alt"),
-        shift: toolModifiers.contains("shift")
+        alt: toolModifiers.includes("alt"),
+        shift: toolModifiers.includes("shift")
       };
 
       // On the key press, we will dispatch the event within projecteditor.
       extraKeys[Editor.accel(keyUpper, modifiers)] = () => {
         let doc = this.projectEditorCommandset.ownerDocument;
         let event = doc.createEvent('Event');
         event.initEvent('command', true, true);
         let command = this.projectEditorCommandset.querySelector("#" + key.getAttribute("command"));
--- a/browser/devtools/scratchpad/test/browser_scratchpad_eval_func.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_eval_func.js
@@ -73,14 +73,14 @@ function runTests(sw)
       sp.editor.setCursor({ line: 0, ch: 9 });
       return sp.evalTopLevelFunction();
     })
     .then(([text, error, result]) => {
       is(text, "function {}",
          "Should get the full text back since there was a parse error.");
       ok(!error, "Should not have got an error");
       ok(!result, "Should not have got a result");
-      ok(sp.getText().contains("SyntaxError"),
+      ok(sp.getText().includes("SyntaxError"),
          "We should have written the syntax error to the scratchpad.");
     })
 
     .then(finish, reportErrorAndQuit);
 }
--- a/browser/devtools/scratchpad/test/browser_scratchpad_pprint-02.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_pprint-02.js
@@ -22,17 +22,17 @@ function runTests(sw)
   gTabsize = Services.prefs.getIntPref("devtools.editor.tabsize");
   Services.prefs.setIntPref("devtools.editor.tabsize", 6);
   const space = " ".repeat(6);
 
   const sp = sw.Scratchpad;
   sp.setText("function main() { console.log(5); }");
   sp.prettyPrint().then(() => {
     const prettyText = sp.getText();
-    ok(prettyText.contains(space));
+    ok(prettyText.includes(space));
     finish();
   }).then(null, error => {
     ok(false, error);
   });
 }
 
 registerCleanupFunction(function () {
   Services.prefs.setIntPref("devtools.editor.tabsize", gTabsize);
--- a/browser/devtools/scratchpad/test/browser_scratchpad_pprint.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_pprint.js
@@ -16,14 +16,14 @@ function test()
 }
 
 function runTests(sw)
 {
   const sp = sw.Scratchpad;
   sp.setText("function main() { console.log(5); }");
   sp.prettyPrint().then(() => {
     const prettyText = sp.getText();
-    ok(prettyText.contains("\n"));
+    ok(prettyText.includes("\n"));
     finish();
   }).then(null, error => {
     ok(false, error);
   });
 }
--- a/browser/devtools/shadereditor/test/browser_se_editors-error-gutter.js
+++ b/browser/devtools/shadereditor/test/browser_se_editors-error-gutter.js
@@ -90,19 +90,19 @@ function ifWebGLSupported() {
     is(parsed.length >= 1, bool,
       "There's " + (bool ? ">= 1" : "< 1") + " parsed vertex shader error(s).");
 
     if (bool) {
       is(parsed[0].line, line,
         "The correct line was parsed.");
       is(parsed[0].messages.length, 2,
         "There are 2 parsed messages.");
-      ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
+      ok(parsed[0].messages[0].includes("'constructor' : too many arguments"),
         "The correct first message was parsed.");
-      ok(parsed[0].messages[1].contains("'assign' : cannot convert from"),
+      ok(parsed[0].messages[1].includes("'assign' : cannot convert from"),
         "The correct second message was parsed.");
     }
   }
 
   function checkHasVertSecondError(bool, error) {
     ok(error, "Vertex shader compiled with errors.");
     isnot(error.link, "", "The linkage status should not be empty.");
 
@@ -118,17 +118,17 @@ function ifWebGLSupported() {
     is(parsed.length >= 2, bool,
       "There's " + (bool ? ">= 2" : "< 2") + " parsed vertex shader error(s).");
 
     if (bool) {
       is(parsed[1].line, line,
         "The correct line was parsed.");
       is(parsed[1].messages.length, 1,
         "There is 1 parsed message.");
-      ok(parsed[1].messages[0].contains("'assign' : cannot convert from"),
+      ok(parsed[1].messages[0].includes("'assign' : cannot convert from"),
         "The correct message was parsed.");
     }
   }
 
   function checkHasFragError(bool, error) {
     ok(error, "Fragment shader compiled with errors.");
     isnot(error.link, "", "The linkage status should not be empty.");
 
@@ -144,13 +144,13 @@ function ifWebGLSupported() {
     is(parsed.length >= 1, bool,
       "There's " + (bool ? ">= 2" : "< 1") + " parsed fragment shader error(s).");
 
     if (bool) {
       is(parsed[0].line, line,
         "The correct line was parsed.");
       is(parsed[0].messages.length, 1,
         "There is 1 parsed message.");
-      ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
+      ok(parsed[0].messages[0].includes("'constructor' : too many arguments"),
         "The correct message was parsed.");
     }
   }
 }
--- a/browser/devtools/shadereditor/test/browser_se_editors-error-tooltip.js
+++ b/browser/devtools/shadereditor/test/browser_se_editors-error-tooltip.js
@@ -30,27 +30,27 @@ function ifWebGLSupported() {
   ShadersEditorsView._onMarkerMouseOver(7, marker, parsed);
 
   let tooltip = marker._markerErrorsTooltip;
   ok(tooltip, "A tooltip was created successfully.");
 
   let content = tooltip.content;
   ok(tooltip.content,
     "Some tooltip's content was set.");
-  ok(tooltip.content.className.contains("devtools-tooltip-simple-text-container"),
+  ok(tooltip.content.className.includes("devtools-tooltip-simple-text-container"),
     "The tooltip's content container was created correctly.");
 
   let messages = content.childNodes;
   is(messages.length, 2,
     "There are two messages displayed in the tooltip.");
-  ok(messages[0].className.contains("devtools-tooltip-simple-text"),
+  ok(messages[0].className.includes("devtools-tooltip-simple-text"),
     "The first message was created correctly.");
-  ok(messages[1].className.contains("devtools-tooltip-simple-text"),
+  ok(messages[1].className.includes("devtools-tooltip-simple-text"),
     "The second message was created correctly.");
 
-  ok(messages[0].textContent.contains("'constructor' : too many arguments"),
+  ok(messages[0].textContent.includes("'constructor' : too many arguments"),
     "The first message contains the correct text.");
-  ok(messages[1].textContent.contains("'assign' : cannot convert"),
+  ok(messages[1].textContent.includes("'assign' : cannot convert"),
     "The second message contains the correct text.");
 
   yield teardown(panel);
   finish();
 }
--- a/browser/devtools/shadereditor/test/browser_se_shaders-edit-02.js
+++ b/browser/devtools/shadereditor/test/browser_se_shaders-edit-02.js
@@ -28,35 +28,35 @@ function ifWebGLSupported() {
 
   // The implementation has the choice to defer all compile-time errors to link time.
   let infoLog = (error.compile != "") ? error.compile : error.link;
 
   isnot(infoLog, "",
     "The one of the compile or link info logs should not be empty.");
   is(infoLog.split("ERROR").length - 1, 2,
     "The info log status contains two errors.");
-  ok(infoLog.contains("ERROR: 0:8: 'constructor'"),
+  ok(infoLog.includes("ERROR: 0:8: 'constructor'"),
     "A constructor error is contained in the info log.");
-  ok(infoLog.contains("ERROR: 0:8: 'assign'"),
+  ok(infoLog.includes("ERROR: 0:8: 'assign'"),
     "An assignment error is contained in the info log.");
 
 
   fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
   [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
 
   ok(error,
     "The new fragment shader source was compiled with errors.");
 
   infoLog = (error.compile != "") ? error.compile : error.link;
 
   isnot(infoLog, "",
     "The one of the compile or link info logs should not be empty.");
   is(infoLog.split("ERROR").length - 1, 1,
     "The info log contains one error.");
-  ok(infoLog.contains("ERROR: 0:6: 'constructor'"),
+  ok(infoLog.includes("ERROR: 0:6: 'constructor'"),
     "A constructor error is contained in the info log.");
 
 
   yield ensurePixelIs(gFront, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(gFront, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
 
   vsEditor.replaceText("vec4", { line: 7, ch: 22 }, { line: 7, ch: 26 });
   [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-05.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-05.js
@@ -10,18 +10,18 @@ function ifWebGLSupported() {
   let { target, front } = yield initBackend(SIMPLE_CANVAS_URL);
   front.setup({ reload: true });
 
   let programActor = yield once(front, "program-linked");
   let vertexShader = yield programActor.getVertexShader();
   let fragmentShader = yield programActor.getFragmentShader();
 
   let vertSource = yield vertexShader.getText();
-  ok(vertSource.contains("gl_Position"),
+  ok(vertSource.includes("gl_Position"),
     "The correct vertex shader source was retrieved.");
 
   let fragSource = yield fragmentShader.getText();
-  ok(fragSource.contains("gl_FragColor"),
+  ok(fragSource.includes("gl_FragColor"),
     "The correct fragment shader source was retrieved.");
 
   yield removeTab(target.tab);
   finish();
 }
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-06.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-06.js
@@ -49,16 +49,16 @@ function ifWebGLSupported() {
       let newFragmentShader = yield programActor.getFragmentShader();
       is(vertexShader, newVertexShader,
         "The same vertex shader actor was retrieved.");
       is(fragmentShader, newFragmentShader,
         "The same fragment shader actor was retrieved.");
 
       let vertSource = yield newVertexShader.getText();
       let fragSource = yield newFragmentShader.getText();
-      ok(vertSource.contains("I'm special!") &&
-         fragSource.contains("I'm also special!"), aMessage);
+      ok(vertSource.includes("I'm special!") &&
+         fragSource.includes("I'm also special!"), aMessage);
     });
   }
 
   yield removeTab(target.tab);
   finish();
 }
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-07.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-07.js
@@ -14,48 +14,48 @@ function ifWebGLSupported() {
   let fragmentShader = yield programActor.getFragmentShader();
 
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 128, y: 128 }, { r: 191, g: 64, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
 
   let vertSource = yield vertexShader.getText();
   let fragSource = yield fragmentShader.getText();
-  ok(!vertSource.contains("2.0"),
+  ok(!vertSource.includes("2.0"),
     "The vertex shader source is correct before changing it.");
-  ok(!fragSource.contains("0.5"),
+  ok(!fragSource.includes("0.5"),
     "The fragment shader source is correct before changing it.");
 
   let newVertSource = vertSource.replace("1.0", "2.0");
   let status = yield vertexShader.compile(newVertSource);
   ok(!status,
     "The new vertex shader source was compiled without errors.");
 
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
 
   vertSource = yield vertexShader.getText();
   fragSource = yield fragmentShader.getText();
-  ok(vertSource.contains("2.0"),
+  ok(vertSource.includes("2.0"),
     "The vertex shader source is correct after changing it.");
-  ok(!fragSource.contains("0.5"),
+  ok(!fragSource.includes("0.5"),
     "The fragment shader source is correct after changing the vertex shader.");
 
   let newFragSource = fragSource.replace("1.0", "0.5");
   status = yield fragmentShader.compile(newFragSource);
   ok(!status,
     "The new fragment shader source was compiled without errors.");
 
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 127 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
 
   vertSource = yield vertexShader.getText();
   fragSource = yield fragmentShader.getText();
-  ok(vertSource.contains("2.0"),
+  ok(vertSource.includes("2.0"),
     "The vertex shader source is correct after changing the fragment shader.");
-  ok(fragSource.contains("0.5"),
+  ok(fragSource.includes("0.5"),
     "The fragment shader source is correct after changing it.");
 
   yield removeTab(target.tab);
   finish();
 }
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-08.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-08.js
@@ -22,16 +22,16 @@ function ifWebGLSupported() {
 
   yield front.waitForFrame();
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
   yield ensurePixelIs(front, { x: 128, y: 128 }, { r: 0, g: 0, b: 255, a: 255 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
 
   let vertSource = yield vertexShader.getText();
   let fragSource = yield fragmentShader.getText();
-  ok(vertSource.contains("vFragmentColor = vec3(0, 0, 1);"),
+  ok(vertSource.includes("vFragmentColor = vec3(0, 0, 1);"),
     "The vertex shader source is correct after changing it.");
-  ok(fragSource.contains("gl_FragColor = vec4(vFragmentColor, 1.0);"),
+  ok(fragSource.includes("gl_FragColor = vec4(vFragmentColor, 1.0);"),
     "The fragment shader source is correct after changing the vertex shader.");
 
   yield removeTab(target.tab);
   finish();
 }
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-09.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-09.js
@@ -26,28 +26,28 @@ function ifWebGLSupported() {
 
     // The implementation has the choice to defer all compile-time errors to link time.
     let infoLog = (error.compile != "") ? error.compile : error.link;
 
     isnot(infoLog, "",
       "The one of the compile or link info logs should not be empty.");
     is(infoLog.split("ERROR").length - 1, 2,
       "The info log contains two errors.");
-    ok(infoLog.contains("ERROR: 0:8: 'constructor'"),
+    ok(infoLog.includes("ERROR: 0:8: 'constructor'"),
       "A constructor error is contained in the info log.");
-    ok(infoLog.contains("ERROR: 0:8: 'assign'"),
+    ok(infoLog.includes("ERROR: 0:8: 'assign'"),
       "An assignment error is contained in the info log.");
   }
 
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
   ok(true, "The shader was reverted to the old source.");
 
   let vertSource = yield vertexShader.getText();
-  ok(vertSource.contains("vec4(aVertexPosition, 1.0);"),
+  ok(vertSource.includes("vec4(aVertexPosition, 1.0);"),
     "The previous correct vertex shader source was preserved.");
 
   let oldFragSource = yield fragmentShader.getText();
   let newFragSource = oldFragSource.replace("vec3", "vec4");
 
   try {
     yield fragmentShader.compile(newFragSource);
     ok(false, "Fragment shader was compiled with a defective source!");
@@ -57,26 +57,26 @@ function ifWebGLSupported() {
 
     // The implementation has the choice to defer all compile-time errors to link time.
     let infoLog = (error.compile != "") ? error.compile : error.link;
 
     isnot(infoLog, "",
       "The one of the compile or link info logs should not be empty.");
     is(infoLog.split("ERROR").length - 1, 1,
       "The info log contains one error.");
-    ok(infoLog.contains("ERROR: 0:6: 'constructor'"),
+    ok(infoLog.includes("ERROR: 0:6: 'constructor'"),
       "A constructor error is contained in the info log.");
   }
 
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
   ok(true, "The shader was reverted to the old source.");
 
   let fragSource = yield fragmentShader.getText();
-  ok(fragSource.contains("vec3 vFragmentColor;"),
+  ok(fragSource.includes("vec3 vFragmentColor;"),
     "The previous correct fragment shader source was preserved.");
 
   yield programActor.highlight([0, 1, 0, 1]);
   yield ensurePixelIs(front, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(front, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
   ok(true, "Highlighting worked after setting a defective fragment source.");
 
   yield programActor.unhighlight();
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-12.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-12.js
@@ -12,16 +12,16 @@ function ifWebGLSupported() {
 
   let programActor = yield once(front, "program-linked");
   let vertexShader = yield programActor.getVertexShader();
   let fragmentShader = yield programActor.getFragmentShader();
 
   let vertSource = yield vertexShader.getText();
   let fragSource = yield fragmentShader.getText();
 
-  ok(vertSource.contains("I'm a vertex shader!"),
+  ok(vertSource.includes("I'm a vertex shader!"),
     "The correct vertex shader text was retrieved.");
-  ok(fragSource.contains("I'm a fragment shader!"),
+  ok(fragSource.includes("I'm a fragment shader!"),
     "The correct fragment shader text was retrieved.");
 
   yield removeTab(target.tab);
   finish();
 }
--- a/browser/devtools/shared/Curl.jsm
+++ b/browser/devtools/shared/Curl.jsm
@@ -152,24 +152,24 @@ this.CurlUtils = {
    */
   isUrlEncodedRequest: function(aData) {
     let postDataText = aData.postDataText;
     if (!postDataText) {
       return false;
     }
 
     postDataText = postDataText.toLowerCase();
-    if (postDataText.contains("content-type: application/x-www-form-urlencoded")) {
+    if (postDataText.includes("content-type: application/x-www-form-urlencoded")) {
       return true;
     }
 
     let contentType = this.findHeader(aData.headers, "content-type");
 
     return (contentType &&
-      contentType.toLowerCase().contains("application/x-www-form-urlencoded"));
+      contentType.toLowerCase().includes("application/x-www-form-urlencoded"));
   },
 
   /**
    * Check if the request is a multipart request.
    *
    * @param object aData
    *        The data source.
    * @return boolean
@@ -177,24 +177,24 @@ this.CurlUtils = {
    */
   isMultipartRequest: function(aData) {
     let postDataText = aData.postDataText;
     if (!postDataText) {
       return false;
     }
 
     postDataText = postDataText.toLowerCase();
-    if (postDataText.contains("content-type: multipart/form-data")) {
+    if (postDataText.includes("content-type: multipart/form-data")) {
       return true;
     }
 
     let contentType = this.findHeader(aData.headers, "content-type");
 
     return (contentType &&
-      contentType.toLowerCase().contains("multipart/form-data;"));
+      contentType.toLowerCase().includes("multipart/form-data;"));
   },
 
   /**
    * Write out paramters from post data text.
    *
    * @param object aPostDataText
    *        Post data text.
    * @return string
@@ -273,18 +273,18 @@ this.CurlUtils = {
     let parts = aMultipartText.split(boundary);
     for (let part of parts) {
       // Each part is expected to have a content disposition line.
       let contentDispositionLine = part.trimLeft().split("\r\n")[0];
       if (!contentDispositionLine) {
         continue;
       }
       contentDispositionLine = contentDispositionLine.toLowerCase();
-      if (contentDispositionLine.contains("content-disposition: form-data")) {
-        if (contentDispositionLine.contains("filename=")) {
+      if (contentDispositionLine.includes("content-disposition: form-data")) {
+        if (contentDispositionLine.includes("filename=")) {
           // The header lines and the binary blob is separated by 2 CRLF's.
           // Add only the headers to the result.
           let headers = part.split("\r\n\r\n")[0];
           result += boundary + "\r\n" + headers + "\r\n\r\n";
         }
         else {
           result += boundary + "\r\n" + part;
         }
--- a/browser/devtools/shared/Parser.jsm
+++ b/browser/devtools/shared/Parser.jsm
@@ -327,17 +327,17 @@ SyntaxTree.prototype = {
 
     SyntaxTreeVisitor.walk(this.AST, {
       /**
        * Callback invoked for each function declaration node.
        * @param Node aNode
        */
       onFunctionDeclaration: function(aNode) {
         let functionName = aNode.id.name;
-        if (functionName.toLowerCase().contains(lowerCaseToken)) {
+        if (functionName.toLowerCase().includes(lowerCaseToken)) {
           store.push({
             functionName: functionName,
             functionLocation: ParserHelpers.getNodeLocation(aNode)
           });
         }
       },
 
       /**
@@ -355,18 +355,18 @@ SyntaxTree.prototype = {
         let inferredChain = inferredInfo.chain;
         let inferredLocation = inferredInfo.loc;
 
         // Current node may be part of a larger assignment expression stack.
         if (aNode._parent.type == "AssignmentExpression") {
           this.onFunctionExpression(aNode._parent);
         }
 
-        if ((functionName && functionName.toLowerCase().contains(lowerCaseToken)) ||
-            (inferredName && inferredName.toLowerCase().contains(lowerCaseToken))) {
+        if ((functionName && functionName.toLowerCase().includes(lowerCaseToken)) ||
+            (inferredName && inferredName.toLowerCase().includes(lowerCaseToken))) {
           store.push({
             functionName: functionName,
             functionLocation: functionLocation,
             inferredName: inferredName,
             inferredChain: inferredChain,
             inferredLocation: inferredLocation
           });
         }
@@ -383,17 +383,17 @@ SyntaxTree.prototype = {
         let inferredChain = inferredInfo.chain;
         let inferredLocation = inferredInfo.loc;
 
         // Current node may be part of a larger assignment expression stack.
         if (aNode._parent.type == "AssignmentExpression") {
           this.onFunctionExpression(aNode._parent);
         }
 
-        if (inferredName && inferredName.toLowerCase().contains(lowerCaseToken)) {
+        if (inferredName && inferredName.toLowerCase().includes(lowerCaseToken)) {
           store.push({
             inferredName: inferredName,
             inferredChain: inferredChain,
             inferredLocation: inferredLocation
           });
         }
       }
     });
--- a/browser/devtools/shared/autocomplete-popup.js
+++ b/browser/devtools/shared/autocomplete-popup.js
@@ -255,17 +255,17 @@ AutocompletePopup.prototype = {
 
   /**
    * Selects the first item of the richlistbox. Note that first item here is the
    * item closes to the input element, which means that 0th index if position is
    * below, and last index if position is above.
    */
   selectFirstItem: function AP_selectFirstItem()
   {
-    if (this.position.contains("before")) {
+    if (this.position.includes("before")) {
       this.selectedIndex = this.itemCount - 1;
     }
     else {
       this.selectedIndex = 0;
     }
     this._list.ensureIndexIsVisible(this._list.selectedIndex);
   },
 
--- a/browser/devtools/shared/profiler/frame-utils.js
+++ b/browser/devtools/shared/profiler/frame-utils.js
@@ -59,18 +59,18 @@ exports.parseLocation = function parseLo
 * @param object frame
 *        The { category, location } properties of the frame.
 * @return boolean
 *         True if a content frame, false if a chrome frame.
 */
 exports.isContent = function isContent ({ category, location }) {
   // Only C++ stack frames have associated category information.
   return !!(!category &&
-    !CHROME_SCHEMES.find(e => location.contains(e)) &&
-    CONTENT_SCHEMES.find(e => location.contains(e)));
+    !CHROME_SCHEMES.find(e => location.includes(e)) &&
+    CONTENT_SCHEMES.find(e => location.includes(e)));
 }
 
 /**
  * This filters out platform data frames in a sample. With latest performance
  * tool in Fx40, when displaying only content, we still filter out all platform data,
  * except we generalize platform data that are leaves. We do this because of two
  * observations:
  *
--- a/browser/devtools/shared/test/browser_flame-graph-04.js
+++ b/browser/devtools/shared/test/browser_flame-graph-04.js
@@ -50,17 +50,17 @@ function testGraph(graph) {
   info("Text at 1px width   : " + text1px);
 
   is(text1000px, text,
     "The fitted text for 1000px width is correct.");
 
   isnot(text50px, text,
     "The fitted text for 50px width is correct (1).");
 
-  ok(text50px.contains(L10N.ellipsis),
+  ok(text50px.includes(L10N.ellipsis),
     "The fitted text for 50px width is correct (2).");
 
   is(graph._getFittedText(text, 10), L10N.ellipsis,
     "The fitted text for 10px width is correct.");
 
   is(graph._getFittedText(text, 1), "",
     "The fitted text for 1px width is correct.");
 }
--- a/browser/devtools/shared/test/browser_telemetry_button_eyedropper.js
+++ b/browser/devtools/shared/test/browser_telemetry_button_eyedropper.js
@@ -36,17 +36,17 @@ function* testButton(toolbox, Telemetry)
   checkResults("_EYEDROPPER_", Telemetry);
 }
 
 function checkResults(histIdFocus, Telemetry) {
   let result = Telemetry.prototype.telemetryInfo;
 
   for (let [histId, value] of Iterator(result)) {
     if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
-        !histId.contains(histIdFocus)) {
+        !histId.includes(histIdFocus)) {
       // Inspector stats are tested in
       // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
       // because we only open the inspector once for this test.
       continue;
     }
 
     if (histId.endsWith("OPENED_PER_USER_FLAG")) {
       ok(value.length === 1 && value[0] === true,
--- a/browser/devtools/shared/test/browser_telemetry_button_paintflashing.js
+++ b/browser/devtools/shared/test/browser_telemetry_button_paintflashing.js
@@ -53,17 +53,17 @@ function delayedClicks(node, clicks) {
   });
 }
 
 function checkResults(histIdFocus, Telemetry) {
   let result = Telemetry.prototype.telemetryInfo;
 
   for (let [histId, value] of Iterator(result)) {
     if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
-        !histId.contains(histIdFocus)) {
+        !histId.includes(histIdFocus)) {
       // Inspector stats are tested in
       // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
       // because we only open the inspector once for this test.
       continue;
     }
 
     if (histId.endsWith("OPENED_PER_USER_FLAG")) {
       ok(value.length === 1 && value[0] === true,
--- a/browser/devtools/shared/test/browser_telemetry_button_responsive.js
+++ b/browser/devtools/shared/test/browser_telemetry_button_responsive.js
@@ -53,17 +53,17 @@ function delayedClicks(node, clicks) {
   });
 }
 
 function checkResults(histIdFocus, Telemetry) {
   let result = Telemetry.prototype.telemetryInfo;
 
   for (let [histId, value] of Iterator(result)) {
     if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
-        !histId.contains(histIdFocus)) {
+        !histId.includes(histIdFocus)) {
       // Inspector stats are tested in
       // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
       // because we only open the inspector once for this test.
       continue;
     }
 
     if (histId.endsWith("OPENED_PER_USER_FLAG")) {
       ok(value.length === 1 && value[0] === true,
--- a/browser/devtools/shared/test/browser_telemetry_button_scratchpad.js
+++ b/browser/devtools/shared/test/browser_telemetry_button_scratchpad.js
@@ -91,17 +91,17 @@ function delayedClicks(node, clicks) {
   });
 }
 
 function checkResults(histIdFocus, Telemetry) {
   let result = Telemetry.prototype.telemetryInfo;
 
   for (let [histId, value] of Iterator(result)) {
     if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
-        !histId.contains(histIdFocus)) {
+        !histId.includes(histIdFocus)) {
       // Inspector stats are tested in
       // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
       // because we only open the inspector once for this test.
       continue;
     }
 
     if (histId.endsWith("OPENED_PER_USER_FLAG")) {
       ok(value.length === 1 && value[0] === true,
--- a/browser/devtools/shared/test/browser_telemetry_button_tilt.js
+++ b/browser/devtools/shared/test/browser_telemetry_button_tilt.js
@@ -53,17 +53,17 @@ function delayedClicks(node, clicks) {
   });
 }
 
 function checkResults(histIdFocus, Telemetry) {
   let result = Telemetry.prototype.telemetryInfo;
 
   for (let [histId, value] of Iterator(result)) {
     if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
-        !histId.contains(histIdFocus)) {
+        !histId.includes(histIdFocus)) {
       // Inspector stats are tested in
       // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
       // because we only open the inspector once for this test.
       continue;
     }
 
     if (histId.endsWith("OPENED_PER_USER_FLAG")) {
       ok(value.length === 1 && value[0] === true,
--- a/browser/devtools/shared/widgets/SideMenuWidget.jsm
+++ b/browser/devtools/shared/widgets/SideMenuWidget.jsm
@@ -395,16 +395,25 @@ SideMenuWidget.prototype = {
   /**
    * Shows the contextMenu element.
    */
   _showContextMenu: function(e) {
     if (!this._contextMenu) {
       return;
     }
 
+    // Don't show the menu if a descendant node is going to be visible also.
+    let node = e.originalTarget;
+    while (node && node !== this._list) {
+      if (node.hasAttribute("contextmenu")) {
+        return;
+      }
+      node = node.parentNode;
+    }
+
     this._contextMenu.openPopupAtScreen(e.screenX, e.screenY, true);
   },
 
   window: null,
   document: null,
   _showArrows: false,
   _showItemCheckboxes: false,
   _showGroupCheckboxes: false,
@@ -505,17 +514,17 @@ SideMenuGroup.prototype = {
    */
   findExpectedIndexForSelf: function(sortPredicate) {
     let identifier = this.identifier;
     let groupsArray = this._orderedGroupElementsArray;
 
     for (let group of groupsArray) {
       let name = group.getAttribute("name");
       if (sortPredicate(name, identifier) > 0 && // Insertion sort at its best :)
-          !name.contains(identifier)) { // Least significant group should be last.
+          !name.includes(identifier)) { // Least significant group should be last.
         return groupsArray.indexOf(group);
       }
     }
     return -1;
   },
 
   window: null,
   document: null,
--- a/browser/devtools/shared/widgets/VariablesView.jsm
+++ b/browser/devtools/shared/widgets/VariablesView.jsm
@@ -1145,17 +1145,17 @@ VariablesView.getterOrSetterEvalMacro = 
 
     default:
       // Wrap statements inside a function declaration if not already wrapped.
       if (!aCurrentString.startsWith("function")) {
         let header = "function(" + (type == "set" ? "value" : "") + ")";
         let body = "";
         // If there's a return statement explicitly written, always use the
         // standard function definition syntax
-        if (aCurrentString.contains("return ")) {
+        if (aCurrentString.includes("return ")) {
           body = "{" + aCurrentString + "}";
         }
         // If block syntax is used, use the whole string as the function body.
         else if (aCurrentString.startsWith("{")) {
           body = aCurrentString;
         }
         // Prefer an expression closure.
         else {
@@ -1920,18 +1920,18 @@ Scope.prototype = {
    */
   _performSearch: function(aLowerCaseQuery) {
     for (let [, variable] of this._store) {
       let currentObject = variable;
       let lowerCaseName = variable._nameString.toLowerCase();
       let lowerCaseValue = variable._valueString.toLowerCase();
 
       // Non-matched variables or properties require a corresponding attribute.
-      if (!lowerCaseName.contains(aLowerCaseQuery) &&
-          !lowerCaseValue.contains(aLowerCaseQuery)) {
+      if (!lowerCaseName.includes(aLowerCaseQuery) &&
+          !lowerCaseValue.includes(aLowerCaseQuery)) {
         variable._matched = false;
       }
       // Variable or property is matched.
       else {
         variable._matched = true;
 
         // If the variable was ever expanded, there's a possibility it may
         // contain some matched properties, so make sure they're visible
--- a/browser/devtools/sourceeditor/editor.js
+++ b/browser/devtools/sourceeditor/editor.js
@@ -1151,17 +1151,17 @@ function getCSSKeywords() {
   }
 
   let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
                    .getService(Ci.inIDOMUtils);
   let cssProperties = domUtils.getCSSPropertyNames(domUtils.INCLUDE_ALIASES);
   let cssColors = {};
   let cssValues = {};
   cssProperties.forEach(property => {
-    if (property.contains("color")) {
+    if (property.includes("color")) {
       domUtils.getCSSValuesForProperty(property).forEach(value => {
         cssColors[value] = true;
       });
     }
     else {
       domUtils.getCSSValuesForProperty(property).forEach(value => {
         cssValues[value] = true;
       });
--- a/browser/devtools/storage/ui.js
+++ b/browser/devtools/storage/ui.js
@@ -443,18 +443,18 @@ StorageUI.prototype = {
       let kv = separators[i];
       for (let j = 0; j < separators.length; j++) {
         if (i == j) {
           continue;
         }
         let p = separators[j];
         let regex = new RegExp("^([^" + kv + p + "]*" + kv + "+[^" + kv + p +
                                "]*" + p + "*)+$", "g");
-        if (value.match(regex) && value.contains(kv) &&
-            (value.contains(p) || value.split(kv).length == 2)) {
+        if (value.match(regex) && value.includes(kv) &&
+            (value.includes(p) || value.split(kv).length == 2)) {
           return makeObject(kv, p);
         }
       }
     }
     // Testing for array
     for (let i = 0; i < separators.length; i++) {
       let p = separators[i];
       let regex = new RegExp("^[^" + p + "]+(" + p + "+[^" + p + "]*)+$", "g");
--- a/browser/devtools/styleeditor/test/browser_styleeditor_private_perwindowpb.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_private_perwindowpb.js
@@ -38,17 +38,17 @@ function checkDiskCacheFor(host)
     onCacheStorageInfo: function(num, consumption)
     {
       info("disk storage contains " + num + " entries");
     },
     onCacheEntryInfo: function(uri)
     {
       var urispec = uri.asciiSpec;
       info(urispec);
-      foundPrivateData |= urispec.contains(host);
+      foundPrivateData |= urispec.includes(host);
     },
     onCacheEntryVisitCompleted: function()
     {
       is(foundPrivateData, false, "web content present in disk cache");
       deferred.resolve();
     }
   };
   function Visitor() {}
--- a/browser/devtools/styleinspector/css-parsing-utils.js
+++ b/browser/devtools/styleinspector/css-parsing-utils.js
@@ -7,18 +7,18 @@
 "use strict";
 
 const cssTokenizer  = require("devtools/sourceeditor/css-tokenizer");
 
 /**
  * Returns the string enclosed in quotes
  */
 function quoteString(string) {
-  let hasDoubleQuotes = string.contains('"');
-  let hasSingleQuotes = string.contains("'");
+  let hasDoubleQuotes = string.includes('"');
+  let hasSingleQuotes = string.includes("'");
 
   let quote = '"';
   if (hasDoubleQuotes && !hasSingleQuotes) {
     quote = "'";
   }
 
   // Quote special characters as specified by the CSS grammar.
   // See http://www.w3.org/TR/CSS2/syndata.html#tokenization
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -2060,17 +2060,17 @@ CssRuleView.prototype = {
     } else if (aRule.domRule.type === ELEMENT_STYLE) {
       selectorNodes = [];
     }
 
     aValue = aValue.trim();
 
     // Highlight search matches in the rule selectors
     for (let selectorNode of selectorNodes) {
-      if (selectorNode.textContent.toLowerCase().contains(aValue)) {
+      if (selectorNode.textContent.toLowerCase().includes(aValue)) {
         selectorNode.classList.add("ruleview-highlight");
         this._highlightedElements.push(selectorNode);
         isHighlighted = true;
       }
     }
 
     // Parse search value as a single property line and extract the property
     // name and value. Otherwise, use the search value as both the name and
@@ -2085,20 +2085,20 @@ CssRuleView.prototype = {
       let propertyValue = textProp.editor.valueSpan.textContent.toLowerCase();
       let propertyName = textProp.name.toLowerCase();
 
       // If the input value matches a property line like `font-family: arial`,
       // then check to make sure the name and value match.  Otherwise, just
       // compare the input string directly against the name and value elements.
       let matches = false;
       if (propertyMatch && name && value) {
-        matches = propertyName.contains(name) && propertyValue.contains(value);
+        matches = propertyName.includes(name) && propertyValue.includes(value);
       } else {
-        matches = (name && propertyName.contains(name)) ||
-                  (value && propertyValue.contains(value));
+        matches = (name && propertyName.includes(name)) ||
+                  (value && propertyValue.includes(value));
       }
 
       if (matches) {
       // if (matchTextProperty || matchNameOrValue) {
         textProp.editor.element.classList.add("ruleview-highlight");
         this._highlightedElements.push(textProp.editor.element);
         isHighlighted = true;
       }
--- a/browser/devtools/webconsole/test/browser_bug_865871_variables_view_close_on_esc_key.js
+++ b/browser/devtools/webconsole/test/browser_bug_865871_variables_view_close_on_esc_key.js
@@ -23,17 +23,17 @@ function test()
 
     let msg = yield execute("fooObj");
     ok(msg, "output message found");
 
     let anchor = msg.querySelector("a");
     let body = msg.querySelector(".message-body");
     ok(anchor, "object anchor");
     ok(body, "message body");
-    ok(body.textContent.contains('testProp: "testValue"'), "message text check");
+    ok(body.textContent.includes('testProp: "testValue"'), "message text check");
 
     msg.scrollIntoView();
     executeSoon(() => {
       EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
     });
 
     let vviewVar = yield jsterm.once("variablesview-fetched");
     let vview = vviewVar._variablesView;
@@ -57,17 +57,17 @@ function test()
 
     msg = yield execute("window.location");
     ok(msg, "output message found");
 
     body = msg.querySelector(".message-body");
     ok(body, "message body");
     anchor = msg.querySelector("a");
     ok(anchor, "object anchor");
-    ok(body.textContent.contains("Location \u2192 http://example.com/browser/"),
+    ok(body.textContent.includes("Location \u2192 http://example.com/browser/"),
        "message text check");
 
     msg.scrollIntoView();
     executeSoon(() => {
       EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow)
     });
     vviewVar = yield jsterm.once("variablesview-fetched");
 
--- a/browser/devtools/webconsole/test/browser_bug_869003_inspect_cross_domain_object.js
+++ b/browser/devtools/webconsole/test/browser_bug_869003_inspect_cross_domain_object.js
@@ -35,17 +35,17 @@ let test = asyncTest(function* () {
   let msg = [...result.matched][0];
   ok(msg, "message element");
 
   let body = msg.querySelector(".message-body");
   ok(body, "message body");
 
   let clickable = result.clickableElements[0];
   ok(clickable, "clickable object found");
-  ok(body.textContent.contains('{ hello: "world!",'), "message text check");
+  ok(body.textContent.includes('{ hello: "world!",'), "message text check");
 
   executeSoon(() => {
     EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow)
   });
 
   let aVar = yield hud.jsterm.once("variablesview-fetched");
   ok(aVar, "variables view fetched");
   ok(aVar._variablesView, "variables view object");
--- a/browser/devtools/webconsole/test/browser_console_log_inspectable_object.js
+++ b/browser/devtools/webconsole/test/browser_console_log_inspectable_object.js
@@ -28,17 +28,17 @@ let test = asyncTest(function*() {
   let msg = [...result.matched][0];
   ok(msg, "message element");
 
   let body = msg.querySelector(".message-body");
   ok(body, "message body");
 
   let clickable = result.clickableElements[0];
   ok(clickable, "the console.log() object anchor was found");
-  ok(body.textContent.contains('{ abba: "omgBug676722" }'),
+  ok(body.textContent.includes('{ abba: "omgBug676722" }'),
      "clickable node content is correct");
 
   executeSoon(() => {
     EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
   });
 
   let varView = yield hud.jsterm.once("variablesview-fetched");
   ok(varView, "object inspector opened on click");
--- a/browser/devtools/webconsole/test/browser_console_variables_view.js
+++ b/browser/devtools/webconsole/test/browser_console_variables_view.js
@@ -16,17 +16,17 @@ let test = asyncTest(function* () {
 
   hud = yield openConsole();
 
   gWebConsole = hud;
   gJSTerm = hud.jsterm;
   let msg = yield gJSTerm.execute("fooObj");
 
   ok(msg, "output message found");
-  ok(msg.textContent.contains('{ testProp: "testValue" }'), "message text check");
+  ok(msg.textContent.includes('{ testProp: "testValue" }'), "message text check");
 
   let anchor = msg.querySelector("a");
   ok(anchor, "object link found");
 
   let fetched = gJSTerm.once("variablesview-fetched");
 
   // executeSoon
   EventUtils.synthesizeMouse(anchor, 2, 2, {}, gWebConsole.iframeWindow);
--- a/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging.js
+++ b/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging.js
@@ -55,17 +55,17 @@ function onFramesAdded()
     )
   );
 }
 
 
 function onExecuteFooObj(msg)
 {
   ok(msg, "output message found");
-  ok(msg.textContent.contains('{ testProp2: "testValue2" }'), "message text check");
+  ok(msg.textContent.includes('{ testProp2: "testValue2" }'), "message text check");
 
   let anchor = msg.querySelector("a");
   ok(anchor, "object link found");
 
   gJSTerm.once("variablesview-fetched", onFooObjFetch);
 
   executeSoon(() => EventUtils.synthesizeMouse(anchor, 2, 2, {},
                                                gWebConsole.iframeWindow));
--- a/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js
+++ b/browser/devtools/webconsole/test/browser_console_variables_view_while_debugging_and_inspecting.js
@@ -52,17 +52,17 @@ function onFramesAdded()
   info("onFramesAdded");
 
   openConsole().then(() => gJSTerm.execute("fooObj").then(onExecuteFooObj));
 }
 
 function onExecuteFooObj(msg)
 {
   ok(msg, "output message found");
-  ok(msg.textContent.contains('{ testProp2: "testValue2" }'),
+  ok(msg.textContent.includes('{ testProp2: "testValue2" }'),
      "message text check");
 
   let anchor = msg.querySelector("a");
   ok(anchor, "object link found");
 
   gJSTerm.once("variablesview-fetched", onFooObjFetch);
 
   EventUtils.synthesizeMouse(anchor, 2, 2, {}, gWebConsole.iframeWindow);
--- a/browser/devtools/webconsole/test/browser_webconsole_column_numbers.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_column_numbers.js
@@ -30,13 +30,13 @@ function consoleOpened(aHud) {
 
 function testLocationColumn() {
   let messages = hud.outputNode.children;
   let expected = ['10:7', '10:39', '11:9', '12:11', '13:9', '14:7'];
 
   for(let i = 0, len = messages.length; i < len; i++) {
     let msg = messages[i].textContent;
 
-    is(msg.contains(expected[i]), true, 'Found expected line:column of ' + expected[i]);
+    is(msg.includes(expected[i]), true, 'Found expected line:column of ' + expected[i]);
   }
 
   finishTest();
 }
--- a/browser/devtools/webide/content/runtimedetails.js
+++ b/browser/devtools/webide/content/runtimedetails.js
@@ -130,20 +130,23 @@ function CheckLockState() {
     }
 
   }
 
 }
 
 function EnableCertApps() {
   let device = AppManager.selectedRuntime.device;
+  // TODO: Remove `network.disable.ipc.security` once bug 1125916 is fixed.
   device.shell(
     "stop b2g && " +
     "cd /data/b2g/mozilla/*.default/ && " +
     "echo 'user_pref(\"devtools.debugger.forbid-certified-apps\", false);' >> prefs.js && " +
+    "echo 'user_pref(\"dom.apps.developer_mode\", true);' >> prefs.js && " +
+    "echo 'user_pref(\"network.disable.ipc.security\", true);' >> prefs.js && " +
     "start b2g"
   );
 }
 
 function RootADB() {
   let device = AppManager.selectedRuntime.device;
   device.summonRoot().then(CheckLockState, (e) => console.error(e));
 }
--- a/browser/extensions/pdfjs/test/browser.ini
+++ b/browser/extensions/pdfjs/test/browser.ini
@@ -1,13 +1,9 @@
 [DEFAULT]
-skip-if = e10s # Bug 942707 - PDF viewer doesn't work with e10s.
+skip-if = e10s # Bug 1159385
 support-files = file_pdfjs_test.pdf
 
 [browser_pdfjs_main.js]
-skip-if = debug # bug 1058695
 [browser_pdfjs_navigation.js]
-skip-if = debug # bug 1058695
 [browser_pdfjs_savedialog.js]
 [browser_pdfjs_views.js]
-skip-if = debug # bug 1058695
 [browser_pdfjs_zoom.js]
-skip-if = debug # bug 1058695
--- a/browser/modules/Chat.jsm
+++ b/browser/modules/Chat.jsm
@@ -19,18 +19,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 function isWindowChromeless(win) {
   // XXX - stolen from browser-social.js, but there's no obvious place to
   // put this so it can be shared.
 
   // Is this a popup window that doesn't want chrome shown?
   let docElem = win.document.documentElement;
   // extrachrome is not restored during session restore, so we need
   // to check for the toolbar as well.
-  let chromeless = docElem.getAttribute("chromehidden").contains("extrachrome") ||
-                   docElem.getAttribute('chromehidden').contains("toolbar");
+  let chromeless = docElem.getAttribute("chromehidden").includes("extrachrome") ||
+                   docElem.getAttribute('chromehidden').includes("toolbar");
   return chromeless;
 }
 
 function isWindowGoodForChats(win) {
   return !win.closed &&
          !!win.document.getElementById("pinnedchats") &&
          !isWindowChromeless(win) &&
          !PrivateBrowsingUtils.isWindowPrivate(win);
new file mode 100644
--- /dev/null
+++ b/browser/modules/TransientPrefs.jsm
@@ -0,0 +1,24 @@
+/* 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";
+
+this.EXPORTED_SYMBOLS = ["TransientPrefs"];
+
+Components.utils.import("resource://gre/modules/Preferences.jsm");
+
+let prefVisibility = new Map;
+
+/* Use for preferences that should only be visible when they've been modified.
+   When reset to their default state, they remain visible until restarting the
+   application. */
+
+this.TransientPrefs = {
+  prefShouldBeVisible: function (prefName) {
+    if (Preferences.isSet(prefName))
+      prefVisibility.set(prefName, true);
+
+    return !!prefVisibility.get(prefName);
+  }
+};
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -34,16 +34,17 @@ EXTRA_JS_MODULES += [
     'PluginContent.jsm',
     'ProcessHangMonitor.jsm',
     'ReaderParent.jsm',
     'RecentWindow.jsm',
     'RemotePrompt.jsm',
     'SelfSupportBackend.jsm',
     'SitePermissions.jsm',
     'Social.jsm',
+    'TransientPrefs.jsm',
     'WebappManager.jsm',
     'webrtcUI.jsm',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXTRA_JS_MODULES += [
         'Windows8WindowFrameColor.jsm',
         'WindowsJumpLists.jsm',
--- a/configure.in
+++ b/configure.in
@@ -6493,17 +6493,17 @@ MOZ_ARG_DISABLE_BOOL(sandbox,
 dnl ========================================================
 dnl = Content process sandboxing
 dnl ========================================================
 if test -n "$gonkdir"; then
     MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX
 fi
 
 case "$OS_TARGET:$NIGHTLY_BUILD" in
-WINNT:*)
+WINNT:1)
     MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX
     ;;
 Darwin:1)
     MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX
     ;;
 esac
 
 MOZ_ARG_ENABLE_BOOL(content-sandbox,
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -9410,71 +9410,84 @@ namespace {
 #ifdef MOZ_PLACES
 // Callback used by CopyFavicon to inform the favicon service that one URI
 // (mNewURI) has the same favicon URI (OnComplete's aFaviconURI) as another.
 class nsCopyFaviconCallback final : public nsIFaviconDataCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
-  nsCopyFaviconCallback(nsIURI* aNewURI, bool aInPrivateBrowsing)
-    : mNewURI(aNewURI)
+  nsCopyFaviconCallback(mozIAsyncFavicons* aSvc,
+                        nsIURI* aNewURI,
+                        bool aInPrivateBrowsing)
+    : mSvc(aSvc)
+    , mNewURI(aNewURI)
     , mInPrivateBrowsing(aInPrivateBrowsing)
   {
   }
 
   NS_IMETHODIMP
   OnComplete(nsIURI* aFaviconURI, uint32_t aDataLen,
              const uint8_t* aData, const nsACString& aMimeType) override
   {
     // Continue only if there is an associated favicon.
     if (!aFaviconURI) {
       return NS_OK;
     }
 
-    NS_ASSERTION(aDataLen == 0,
-                 "We weren't expecting the callback to deliver data.");
-    nsCOMPtr<mozIAsyncFavicons> favSvc =
-      do_GetService("@mozilla.org/browser/favicon-service;1");
-    NS_ENSURE_STATE(favSvc);
-
-    return favSvc->SetAndFetchFaviconForPage(
+    MOZ_ASSERT(aDataLen == 0,
+               "We weren't expecting the callback to deliver data.");
+
+    return mSvc->SetAndFetchFaviconForPage(
       mNewURI, aFaviconURI, false,
       mInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE :
                            nsIFaviconService::FAVICON_LOAD_NON_PRIVATE,
       nullptr);
   }
 
 private:
   ~nsCopyFaviconCallback() {}
 
+  nsCOMPtr<mozIAsyncFavicons> mSvc;
   nsCOMPtr<nsIURI> mNewURI;
   bool mInPrivateBrowsing;
 };
 
 NS_IMPL_ISUPPORTS(nsCopyFaviconCallback, nsIFaviconDataCallback)
 #endif
 
-// Tell the favicon service that aNewURI has the same favicon as aOldURI.
+} // anonymous namespace
+
 void
-CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI, bool aInPrivateBrowsing)
-{
+nsDocShell::CopyFavicon(nsIURI* aOldURI,
+                        nsIURI* aNewURI,
+                        bool aInPrivateBrowsing)
+{
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
+    if (contentChild) {
+      mozilla::ipc::URIParams oldURI, newURI;
+      SerializeURI(aOldURI, oldURI);
+      SerializeURI(aNewURI, newURI);
+      contentChild->SendCopyFavicon(oldURI, newURI, aInPrivateBrowsing);
+    }
+    return;
+  }
+
 #ifdef MOZ_PLACES
   nsCOMPtr<mozIAsyncFavicons> favSvc =
     do_GetService("@mozilla.org/browser/favicon-service;1");
   if (favSvc) {
     nsCOMPtr<nsIFaviconDataCallback> callback =
-      new nsCopyFaviconCallback(aNewURI, aInPrivateBrowsing);
+      new nsCopyFaviconCallback(favSvc, aNewURI, aInPrivateBrowsing);
     favSvc->GetFaviconURLForPage(aOldURI, callback);
   }
 #endif
 }
 
-} // anonymous namespace
-
 class InternalLoadEvent : public nsRunnable
 {
 public:
   InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
                     nsISupports* aOwner, uint32_t aFlags,
                     const char* aTypeHint, nsIInputStream* aPostData,
                     nsIInputStream* aHeadersData, uint32_t aLoadType,
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -272,16 +272,21 @@ public:
   void AddProfileTimelineMarker(const char* aName,
                                 TracingMetadata aMetaData);
   void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>&& aMarker);
 
   // Global counter for how many docShells are currently recording profile
   // timeline markers
   static unsigned long gProfileTimelineRecordingsCount;
 
+  // Tell the favicon service that aNewURI has the same favicon as aOldURI.
+  static void CopyFavicon(nsIURI* aOldURI,
+                          nsIURI* aNewURI,
+                          bool aInPrivateBrowsing);
+
 protected:
   // Object Management
   virtual ~nsDocShell();
   virtual void DestroyChildren() override;
 
   // Content Viewer Management
   nsresult EnsureContentViewer();
   // aPrincipal can be passed in if the caller wants.  If null is
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -2082,16 +2082,17 @@ Navigator::GetMozAudioChannelManager(Err
 }
 #endif
 
 bool
 Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
                      JS::Handle<jsid> aId,
                      JS::MutableHandle<JSPropertyDescriptor> aDesc)
 {
+  // Note: Keep this in sync with MayResolve.
   if (!JSID_IS_STRING(aId)) {
     return true;
   }
 
   nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager();
   if (!nameSpaceManager) {
     return Throw(aCx, NS_ERROR_NOT_INITIALIZED);
   }
@@ -2233,16 +2234,38 @@ Navigator::DoResolve(JSContext* aCx, JS:
   if (!JS_WrapValue(aCx, &prop_val)) {
     return Throw(aCx, NS_ERROR_UNEXPECTED);
   }
 
   FillPropertyDescriptor(aDesc, aObject, prop_val, false);
   return true;
 }
 
+/* static */
+bool
+Navigator::MayResolve(jsid aId)
+{
+  // Note: This function does not fail and may not have any side-effects.
+  // Note: Keep this in sync with DoResolve.
+  if (!JSID_IS_STRING(aId)) {
+    return false;
+  }
+
+  nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
+  if (!nameSpaceManager) {
+    // Really shouldn't happen here.  Fail safe.
+    return true;
+  }
+
+  nsAutoString name;
+  AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
+
+  return nameSpaceManager->LookupNavigatorName(name);
+}
+
 struct NavigatorNameEnumeratorClosure
 {
   NavigatorNameEnumeratorClosure(JSContext* aCx, JSObject* aWrapper,
                                  nsTArray<nsString>& aNames)
     : mCx(aCx),
       mWrapper(aCx, aWrapper),
       mNames(aNames)
   {
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -276,16 +276,19 @@ public:
                               ErrorResult& aRv);
 #endif // MOZ_MEDIA_NAVIGATOR
 
   already_AddRefed<ServiceWorkerContainer> ServiceWorker();
 
   bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
                  JS::Handle<jsid> aId,
                  JS::MutableHandle<JSPropertyDescriptor> aDesc);
+  // The return value is whether DoResolve might end up resolving the given id.
+  // If in doubt, return true.
+  static bool MayResolve(jsid aId);
   void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
                            ErrorResult& aRv);
   void GetLanguages(nsTArray<nsString>& aLanguages);
 
   bool MozE10sEnabled();
 
   static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
 
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -43,16 +43,17 @@
 #include "nsIDOMNode.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIWebNavigation.h"
 #include "nsGenericHTMLElement.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsIObserverService.h"
 #include "mozilla/Preferences.h"
 #include "nsParserConstants.h"
+#include "nsSandboxFlags.h"
 
 using namespace mozilla;
 
 PRLogModuleInfo* gContentSinkLogModuleInfo;
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink)
 
@@ -760,20 +761,26 @@ nsContentSink::ProcessMETATag(nsIContent
   NS_ASSERTION(aContent, "missing meta-element");
 
   nsresult rv = NS_OK;
 
   // set any HTTP-EQUIV data into document's header data as well as url
   nsAutoString header;
   aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
   if (!header.IsEmpty()) {
+    // Ignore META REFRESH when document is sandboxed from automatic features.
+    nsContentUtils::ASCIIToLower(header);
+    if (nsGkAtoms::refresh->Equals(header) &&
+        (mDocument->GetSandboxFlags() & SANDBOXED_AUTOMATIC_FEATURES)) {
+      return NS_OK;
+    }
+
     nsAutoString result;
     aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result);
     if (!result.IsEmpty()) {
-      nsContentUtils::ASCIIToLower(header);
       nsCOMPtr<nsIAtom> fieldAtom(do_GetAtom(header));
       rv = ProcessHeaderData(fieldAtom, result, aContent); 
     }
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
                             nsGkAtoms::handheldFriendly, eIgnoreCase)) {
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3608,16 +3608,28 @@ nsDOMWindowUtils::GetCompositorAPZTestDa
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::PostRestyleSelfEvent(nsIDOMElement* aElement)
+{
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
+  if (!element) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  nsLayoutUtils::PostRestyleEvent(element, eRestyle_Self, nsChangeHint(0));
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::GetAudioMuted(bool* aMuted)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   *aMuted = window->GetAudioMuted();
   return NS_OK;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4261,29 +4261,69 @@ nsGlobalWindow::GetSupportedNames(nsTArr
 
 bool
 nsGlobalWindow::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
                           JS::Handle<jsid> aId,
                           JS::MutableHandle<JSPropertyDescriptor> aDesc)
 {
   MOZ_ASSERT(IsInnerWindow());
 
+  // Note: Keep this in sync with MayResolve.
+
   // Note: The infallibleInit call in GlobalResolve depends on this check.
   if (!JSID_IS_STRING(aId)) {
     return true;
   }
 
   nsresult rv = nsWindowSH::GlobalResolve(this, aCx, aObj, aId, aDesc);
   if (NS_FAILED(rv)) {
     return Throw(aCx, rv);
   }
 
   return true;
 }
 
+/* static */
+bool
+nsGlobalWindow::MayResolve(jsid aId)
+{
+  // Note: This function does not fail and may not have any side-effects.
+  // Note: Keep this in sync with DoResolve.
+  if (!JSID_IS_STRING(aId)) {
+    return false;
+  }
+
+  if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) {
+    return true;
+  }
+
+  if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_CONTROLLERS)) {
+    // We only resolve .controllers in release builds and on non-chrome windows,
+    // but let's not worry about any of that stuff.
+    return true;
+  }
+
+  nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
+  if (!nameSpaceManager) {
+    // Really shouldn't happen.  Fail safe.
+    return true;
+  }
+
+  nsAutoString name;
+  AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
+
+  const nsGlobalNameStruct *name_struct =
+    nameSpaceManager->LookupName(name);
+
+  // LookupName only returns structs for the global.
+  MOZ_ASSERT_IF(name_struct,
+                name_struct->mType != nsGlobalNameStruct::eTypeNavigatorProperty);
+  return name_struct;
+}
+
 struct GlobalNameEnumeratorClosure
 {
   GlobalNameEnumeratorClosure(JSContext* aCx, nsGlobalWindow* aWindow,
                               nsTArray<nsString>& aNames)
     : mCx(aCx),
       mWindow(aWindow),
       mWrapper(aCx, aWindow->GetWrapper()),
       mNames(aNames)
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -497,16 +497,19 @@ public:
   static bool IsPrivilegedChromeWindow(JSContext* /* unused */, JSObject* aObj);
 
   static bool IsShowModalDialogEnabled(JSContext* /* unused */ = nullptr,
                                        JSObject* /* unused */ = nullptr);
 
   bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
                  JS::Handle<jsid> aId,
                  JS::MutableHandle<JSPropertyDescriptor> aDesc);
+  // The return value is whether DoResolve might end up resolving the given id.
+  // If in doubt, return true.
+  static bool MayResolve(jsid aId);
 
   void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
                            mozilla::ErrorResult& aRv);
 
   // Object Management
   static already_AddRefed<nsGlobalWindow> Create(nsGlobalWindow *aOuterWindow);
 
   static nsGlobalWindow *FromSupports(nsISupports *supports)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2821,16 +2821,22 @@ mozilla::dom::GetNameSpaceManager()
 
     nsresult rv = gNameSpaceManager->Init();
     NS_ENSURE_SUCCESS(rv, nullptr);
   }
 
   return gNameSpaceManager;
 }
 
+nsScriptNameSpaceManager*
+mozilla::dom::PeekNameSpaceManager()
+{
+  return gNameSpaceManager;
+}
+
 void
 mozilla::dom::ShutdownJSEnvironment()
 {
   KillTimers();
 
   NS_IF_RELEASE(gNameSpaceManager);
 
   if (!sContextCount) {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -177,16 +177,19 @@ namespace mozilla {
 namespace dom {
 
 void StartupJSEnvironment();
 void ShutdownJSEnvironment();
 
 // Get the NameSpaceManager, creating if necessary
 nsScriptNameSpaceManager* GetNameSpaceManager();
 
+// Peek the NameSpaceManager, without creating it.
+nsScriptNameSpaceManager* PeekNameSpaceManager();
+
 // Runnable that's used to do async error reporting
 class AsyncErrorReporter : public nsRunnable
 {
 public:
   // aWindow may be null if this error report is not associated with a window
   AsyncErrorReporter(JSRuntime* aRuntime, xpc::ErrorReport* aReport)
     : mReport(aReport)
   {}
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -3662,16 +3662,24 @@ nsObjectLoadingContent::DoResolve(JSCont
   nsRefPtr<nsNPAPIPluginInstance> pi;
   nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
   if (NS_FAILED(rv)) {
     return mozilla::dom::Throw(aCx, rv);
   }
   return true;
 }
 
+/* static */
+bool
+nsObjectLoadingContent::MayResolve(jsid aId)
+{
+  // We can resolve anything, really.
+  return true;
+}
+
 void
 nsObjectLoadingContent::GetOwnPropertyNames(JSContext* aCx,
                                             nsTArray<nsString>& /* unused */,
                                             ErrorResult& aRv)
 {
   // Just like DoResolve, just make sure we're instantiated.  That will do
   // the work our Enumerate hook needs to do.  This purposefully does not fire
   // for xray resolves, see bug 967694
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -166,16 +166,20 @@ class nsObjectLoadingContent : public ns
 
     // Remove plugin from protochain
     void TeardownProtoChain();
 
     // Helper for WebIDL NeedResolve
     bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
                    JS::Handle<jsid> aId,
                    JS::MutableHandle<JSPropertyDescriptor> aDesc);
+    // The return value is whether DoResolve might end up resolving the given
+    // id.  If in doubt, return true.
+    static bool MayResolve(jsid aId);
+
     // Helper for WebIDL enumeration
     void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& /* unused */,
                              mozilla::ErrorResult& aRv);
 
     // WebIDL API
     nsIDocument* GetContentDocument();
     void GetActualType(nsAString& aType) const
     {
--- a/dom/base/test/chrome/window_nsITextInputProcessor.xul
+++ b/dom/base/test/chrome/window_nsITextInputProcessor.xul
@@ -119,25 +119,25 @@ function runBeginInputTransactionMethodT
      description + "The input element should have composing string");
 
   // Composing nsITextInputProcessor instance shouldn't allow initialize it again.
   try {
     TIP1.beginInputTransaction(window, simpleCallback);
     ok(false,
        "TIP1.beginInputTransaction(window) should cause throwing an exception because it's composing with different purpose");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
        description + "TIP1.beginInputTransaction(window) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing for tests");
   }
   try {
     TIP1.beginInputTransactionForTests(otherWindow);
     ok(false,
        "TIP1.beginInputTransactionForTests(otherWindow) should cause throwing an exception because it's composing on different window");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
        description + "TIP1.beginInputTransaction(otherWindow) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing on this window");
   }
   ok(TIP1.beginInputTransactionForTests(window),
      description + "TIP1.beginInputTransactionForTests(window) should succeed because TextEventDispatcher was initialized with same purpose");
   ok(TIP1.beginInputTransactionForTests(childWindow),
      description + "TIP1.beginInputTransactionForTests(childWindow) should succeed because TextEventDispatcher was initialized with same purpose and is shared by window and childWindow");
   ok(!TIP2.beginInputTransaction(window, simpleCallback),
      description + "TIP2.beginInputTransaction(window) should not succeed because there is composition synthesized by TIP1");
@@ -609,17 +609,17 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionstart", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionstart\" should throw an exception during startComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionstart\" should cause NS_ERROR_ALREADY_INITIALIZED during startComposition()");
     }
   }, false);
   TIP1.beginInputTransaction(window, simpleCallback);
   TIP1.startComposition();
   is(events.length, 1,
      description + "compositionstart event should be fired by TIP1.startComposition()");
   TIP1.cancelComposition();
@@ -629,53 +629,53 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionstart", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionstart\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionstart\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   input.addEventListener("compositionupdate", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionupdate\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionupdate\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   TIP1.beginInputTransaction(window, simpleCallback);
   TIP1.setPendingCompositionString(composingStr);
   TIP1.appendClauseToPendingComposition(composingStr.length, TIP1.ATTR_RAW_CLAUSE);
   TIP1.flushPendingComposition();
   is(events.length, 4,
@@ -699,41 +699,41 @@ function runBeginInputTransactionMethodT
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should throw an exception during commitComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during commitComposition()");
     }
   }, false);
   input.addEventListener("compositionend", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionend\" should throw an exception during commitComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionend\" should cause NS_ERROR_ALREADY_INITIALIZED during commitComposition()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should throw an exception during commitComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during commitComposition()");
     }
   }, false);
   TIP1.commitComposition();
   is(events.length, 3,
      description + "text, compositionend and input events should be fired by TIP1.commitComposition()");
   is(events[0].type, "text",
      description + "events[0] should be text");
@@ -747,65 +747,65 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionstart", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionstart\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionstart\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("compositionupdate", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionupdate\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionupdate\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("compositionend", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionend\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionend\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   TIP1.beginInputTransaction(window, simpleCallback);
   TIP1.commitCompositionWith("bar");
   is(events.length, 5,
      description + "compositionstart, compositionupdate, text, compositionend and input events should be fired by TIP1.commitCompositionWith(\"bar\")");
   is(events[0].type, "compositionstart",
@@ -828,53 +828,53 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionupdate", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionupdate\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionupdate\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   input.addEventListener("compositionend", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionend\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"compositionend\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   TIP1.cancelComposition();
   is(events.length, 4,
      description + "compositionupdate, text, compositionend and input events should be fired by TIP1.cancelComposition()");
   is(events[0].type, "compositionupdate",
      description + "events[0] should be compositionupdate");
@@ -891,53 +891,53 @@ function runBeginInputTransactionMethodT
   input.addEventListener("keydown", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"keydown\" should throw an exception during keydown()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"keydown\" should cause NS_ERROR_ALREADY_INITIALIZED during keydown()");
     }
   }, false);
   input.addEventListener("keypress", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"keypress\" should throw an exception during keydown()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"keypress\" should cause NS_ERROR_ALREADY_INITIALIZED during keydown()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should throw an exception during keydown()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during keydown()");
     }
   }, false);
   input.addEventListener("keyup", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransaction(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"keyup\" should throw an exception during keyup()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransaction(otherWindow, simpleCallback) called from \"keyup\" should cause NS_ERROR_ALREADY_INITIALIZED during keyup()");
     }
   }, false);
   var keyA = new KeyboardEvent("", { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
   TIP1.keydown(keyA);
   TIP1.keyup(keyA);
   is(events.length, 4,
      description + "keydown, keypress, input, keyup events should be fired by TIP1.keydown() and TIP1.keyup()");
@@ -955,17 +955,17 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionstart", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionstart\" should throw an exception during startComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionstart\" should cause NS_ERROR_ALREADY_INITIALIZED during startComposition()");
     }
   }, false);
   TIP1.beginInputTransactionForTests(window, simpleCallback);
   TIP1.startComposition();
   is(events.length, 1,
      description + "compositionstart event should be fired by TIP1.startComposition()");
   TIP1.cancelComposition();
@@ -975,53 +975,53 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionstart", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionstart\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionstart\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   input.addEventListener("compositionupdate", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionupdate\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionupdate\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should throw an exception during flushPendingComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during flushPendingComposition()");
     }
   }, false);
   TIP1.beginInputTransactionForTests(window, simpleCallback);
   TIP1.setPendingCompositionString(composingStr);
   TIP1.appendClauseToPendingComposition(composingStr.length, TIP1.ATTR_RAW_CLAUSE);
   TIP1.flushPendingComposition();
   is(events.length, 4,
@@ -1045,41 +1045,41 @@ function runBeginInputTransactionMethodT
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should throw an exception during commitComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during commitComposition()");
     }
   }, false);
   input.addEventListener("compositionend", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionend\" should throw an exception during commitComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionend\" should cause NS_ERROR_ALREADY_INITIALIZED during commitComposition()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should throw an exception during commitComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during commitComposition()");
     }
   }, false);
   TIP1.commitComposition();
   is(events.length, 3,
      description + "text, compositionend and input events should be fired by TIP1.commitComposition()");
   is(events[0].type, "text",
      description + "events[0] should be text");
@@ -1093,65 +1093,65 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionstart", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionstart\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionstart\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("compositionupdate", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionupdate\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionupdate\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("compositionend", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionend\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionend\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should throw an exception during commitCompositionWith(\"bar\")");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during commitCompositionWith(\"bar\")");
     }
   }, false);
   TIP1.beginInputTransactionForTests(window, simpleCallback);
   TIP1.commitCompositionWith("bar");
   is(events.length, 5,
      description + "compositionstart, compositionupdate, text, compositionend and input events should be fired by TIP1.commitCompositionWith(\"bar\")");
   is(events[0].type, "compositionstart",
@@ -1174,53 +1174,53 @@ function runBeginInputTransactionMethodT
   input.addEventListener("compositionupdate", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionupdate\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionupdate\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   input.addEventListener("text", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"text\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   input.addEventListener("compositionend", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionend\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"compositionend\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should throw an exception during cancelComposition()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during cancelComposition()");
     }
   }, false);
   TIP1.cancelComposition();
   is(events.length, 4,
      description + "compositionupdate, text, compositionend and input events should be fired by TIP1.cancelComposition()");
   is(events[0].type, "compositionupdate",
      description + "events[0] should be compositionupdate");
@@ -1237,53 +1237,53 @@ function runBeginInputTransactionMethodT
   input.addEventListener("keydown", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"keydown\" should throw an exception during keydown()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"keydown\" should cause NS_ERROR_ALREADY_INITIALIZED during keydown()");
     }
   }, false);
   input.addEventListener("keypress", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"keypress\" should throw an exception during keydown()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"keypress\" should cause NS_ERROR_ALREADY_INITIALIZED during keydown()");
     }
   }, false);
   input.addEventListener("input", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should throw an exception during keydown()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"input\" should cause NS_ERROR_ALREADY_INITIALIZED during keydown()");
     }
   }, false);
   input.addEventListener("keyup", function (aEvent) {
     events.push(aEvent);
     input.removeEventListener(aEvent.type, arguments.callee, false);
     try {
       TIP1.beginInputTransactionForTests(otherWindow, simpleCallback);
       ok(false,
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"keyup\" should throw an exception during keyup()");
     } catch (e) {
-      ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
+      ok(e.message.includes("NS_ERROR_ALREADY_INITIALIZED"),
          description + "TIP1.beginInputTransactionForTests(otherWindow, simpleCallback) called from \"keyup\" should cause NS_ERROR_ALREADY_INITIALIZED during keyup()");
     }
   }, false);
   var keyA = new KeyboardEvent("", { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
   TIP1.keydown(keyA);
   TIP1.keyup(keyA);
   is(events.length, 4,
      description + "keydown, keypress, input, keyup events should be fired by TIP1.keydown() and TIP1.keyup()");
@@ -1303,17 +1303,17 @@ function runBeginInputTransactionMethodT
   ok(TIP2.beginInputTransactionForTests(window),
      description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
   try {
     TIP1.startComposition();
     ok(false,
        description + "TIP1.startComposition() should cause throwing an exception because TIP2 took the ownership");
     TIP1.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.startComposition() should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not have commit string");
   }
 
   // Let's check if flushPendingComposition() throws an exception after ownership is stolen.
   ok(TIP1.beginInputTransactionForTests(window),
@@ -1324,17 +1324,17 @@ function runBeginInputTransactionMethodT
   try {
     TIP1.setPendingCompositionString(composingStr);
     TIP1.appendClauseToPendingComposition(composingStr.length, TIP1.ATTR_RAW_CLAUSE);
     TIP1.flushPendingComposition()
     ok(false,
        description + "TIP1.flushPendingComposition() should cause throwing an exception because TIP2 took the ownership");
     TIP1.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.flushPendingComposition() should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not have commit string");
   }
 
   // Let's check if commitCompositionWith("bar") throws an exception after ownership is stolen.
   ok(TIP1.beginInputTransactionForTests(window),
@@ -1342,17 +1342,17 @@ function runBeginInputTransactionMethodT
   ok(TIP2.beginInputTransactionForTests(window),
      description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
   input.value = "";
   try {
     TIP1.commitCompositionWith("bar");
     ok(false,
        description + "TIP1.commitCompositionWith(\"bar\") should cause throwing an exception because TIP2 took the ownership");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.commitCompositionWith(\"bar\") should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not have commit string");
   }
 
   // Let's check if keydown() throws an exception after ownership is stolen.
   ok(TIP1.beginInputTransactionForTests(window),
@@ -1361,17 +1361,17 @@ function runBeginInputTransactionMethodT
      description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
   input.value = "";
   try {
     var keyF = new KeyboardEvent("", { key: "f", code: "KeyF", keyCode: KeyboardEvent.DOM_VK_F });
     TIP1.keydown(keyF);
     ok(false,
        description + "TIP1.keydown(keyF) should cause throwing an exception because TIP2 took the ownership");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.keydown(keyF) should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not be modified");
   }
 
   // Let's check if keyup() throws an exception after ownership is stolen.
   ok(TIP1.beginInputTransactionForTests(window),
@@ -1380,50 +1380,50 @@ function runBeginInputTransactionMethodT
      description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
   input.value = "";
   try {
     var keyF = new KeyboardEvent("", { key: "f", code: "KeyF", keyCode: KeyboardEvent.DOM_VK_F });
     TIP1.keyup(keyF);
     ok(false,
        description + "TIP1.keyup(keyF) should cause throwing an exception because TIP2 took the ownership");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
+    ok(e.message.includes("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.keyup(keyF) should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not be modified");
   }
 
   // aCallback of nsITextInputProcessor.beginInputTransaction() must not be omitted.
   try {
     TIP1.beginInputTransaction(window);
     ok(false,
        description + "TIP1.beginInputTransaction(window) should be failed since aCallback is omitted");
   } catch (e) {
-    ok(e.message.contains("Not enough arguments"),
+    ok(e.message.includes("Not enough arguments"),
        description + "TIP1.beginInputTransaction(window) should cause throwing an exception including \"Not enough arguments\" since aCallback is omitted");
   }
 
   // aCallback of nsITextInputProcessor.beginInputTransaction() must not be undefined.
   try {
     TIP1.beginInputTransaction(window, undefined);
     ok(false,
        description + "TIP1.beginInputTransaction(window, undefined) should be failed since aCallback is undefined");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "TIP1.beginInputTransaction(window, undefined) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is undefined");
   }
 
   // aCallback of nsITextInputProcessor.beginInputTransaction() must not be null.
   try {
     TIP1.beginInputTransaction(window, null);
     ok(false,
        description + "TIP1.beginInputTransaction(window, null) should be failed since aCallback is null");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "TIP1.beginInputTransaction(window, null) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is null");
   }
 }
 
 function runReleaseTests()
 {
   var description = "runReleaseTests(): ";
 
@@ -3343,49 +3343,49 @@ function runErrorTests()
 
   // startComposition() should throw an exception if there is already a composition
   TIP.startComposition();
   try {
     TIP.startComposition();
     ok(false,
        description + "startComposition() should fail if it was already called");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_FAILURE"),
+    ok(e.message.includes("NS_ERROR_FAILURE"),
        description + "startComposition() should cause NS_ERROR_FAILURE if there is already composition");
   } finally {
     TIP.cancelComposition();
   }
 
   // cancelComposition() should throw an exception if there is no composition
   try {
     TIP.cancelComposition();
     ok(false,
        description + "cancelComposition() should fail if there is no composition");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_FAILURE"),
+    ok(e.message.includes("NS_ERROR_FAILURE"),
        description + "cancelComposition() should cause NS_ERROR_FAILURE if there is no composition");
   }
 
   // commitComposition() without commit string should throw an exception if there is no composition
   try {
     TIP.commitComposition();
     ok(false,
        description + "commitComposition() should fail if there is no composition");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_FAILURE"),
+    ok(e.message.includes("NS_ERROR_FAILURE"),
        description + "commitComposition() should cause NS_ERROR_FAILURE if there is no composition");
   }
 
   // commitCompositionWith("") should throw an exception if there is no composition
   try {
     TIP.commitCompositionWith("");
     ok(false,
        description + "commitCompositionWith(\"\") should fail if there is no composition");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_FAILURE"),
+    ok(e.message.includes("NS_ERROR_FAILURE"),
        description + "commitCompositionWith(\"\") should cause NS_ERROR_FAILURE if there is no composition");
   }
 
   // Pending composition string should allow to flush without clause information (for compatibility)
   try {
     TIP.setPendingCompositionString("foo");
     TIP.flushPendingComposition();
     ok(true,
@@ -3400,201 +3400,201 @@ function runErrorTests()
   try {
     TIP.setPendingCompositionString("foo");
     TIP.appendClauseToPendingComposition(2, TIP.ATTR_RAW_CLAUSE);
     TIP.flushPendingComposition();
     ok(false,
        description + "flushPendingComposition() should fail if appendClauseToPendingComposition() doesn't fill all composition string");
     TIP.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "flushPendingComposition() should cause NS_ERROR_ILLEGAL_VALUE if appendClauseToPendingComposition() doesn't fill all composition string");
   }
 
   // Pending composition string must not be shorter than appended clause length
   try {
     TIP.setPendingCompositionString("foo");
     TIP.appendClauseToPendingComposition(4, TIP.ATTR_RAW_CLAUSE);
     TIP.flushPendingComposition();
     ok(false,
        description + "flushPendingComposition() should fail if appendClauseToPendingComposition() appends longer clause information");
     TIP.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "flushPendingComposition() should cause NS_ERROR_ILLEGAL_VALUE if appendClauseToPendingComposition() appends longer clause information");
   }
 
   // Pending composition must not have clause information with empty string
   try {
     TIP.appendClauseToPendingComposition(1, TIP.ATTR_RAW_CLAUSE);
     TIP.flushPendingComposition();
     ok(false,
        description + "flushPendingComposition() should fail if there is a clause with empty string");
     TIP.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "flushPendingComposition() should cause NS_ERROR_ILLEGAL_VALUE if there is a clause with empty string");
   }
 
   // Appending a clause whose length is 0 should cause an exception
   try {
     TIP.appendClauseToPendingComposition(0, TIP.ATTR_RAW_CLAUSE);
     ok(false,
        description + "appendClauseToPendingComposition() should fail if the length is 0");
     TIP.flushPendingComposition();
     TIP.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "appendClauseToPendingComposition() should cause NS_ERROR_ILLEGAL_VALUE if the length is 0");
   }
 
   // Appending a clause whose attribute is invalid should cause an exception
   try {
     TIP.setPendingCompositionString("foo");
     TIP.appendClauseToPendingComposition(3, 0);
     ok(false,
        description + "appendClauseToPendingComposition() should fail if the attribute is invalid");
     TIP.flushPendingComposition();
     TIP.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "appendClauseToPendingComposition() should cause NS_ERROR_ILLEGAL_VALUE if the attribute is invalid");
   }
 
   // Setting caret position outside of composition string should cause an exception
   try {
     TIP.setPendingCompositionString("foo");
     TIP.appendClauseToPendingComposition(3, TIP.ATTR_RAW_CLAUSE);
     TIP.setCaretInPendingComposition(4);
     TIP.flushPendingComposition();
     ok(false,
        description + "flushPendingComposition() should fail if caret position is out of composition string");
     TIP.cancelComposition();
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "flushPendingComposition() should cause NS_ERROR_ILLEGAL_VALUE if caret position is out of composition string");
   }
 
   // Calling keydown() with a KeyboardEvent initialized with invalid code value should cause an exception.
   input.value = "";
   try {
     var keyInvalidCode = new KeyboardEvent("", { key: "f", code: "InvalidCodeValue", keyCode: KeyboardEvent.DOM_VK_F });
     TIP.keydown(keyInvalidCode);
     ok(false,
        description + "TIP.keydown(keyInvalidCode) should cause throwing an exception because its code value is not registered");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "TIP.keydown(keyInvalidCode) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE");
   } finally {
     is(input.value, "",
        description + "The input element should not be modified");
   }
 
   // Calling keyup() with a KeyboardEvent initialized with invalid code value should cause an exception.
   input.value = "";
   try {
     var keyInvalidCode = new KeyboardEvent("", { key: "f", code: "InvalidCodeValue", keyCode: KeyboardEvent.DOM_VK_F });
     TIP.keyup(keyInvalidCode);
     ok(false,
        description + "TIP.keyup(keyInvalidCode) should cause throwing an exception because its code value is not registered");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "TIP.keyup(keyInvalidCode) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE");
   } finally {
     is(input.value, "",
        description + "The input element should not be modified");
   }
 
   // Calling keydown(KEY_NON_PRINTABLE_KEY) with a KeyboardEvent initialized with non-key name should cause an exception.
   input.value = "";
   try {
     var keyInvalidKey = new KeyboardEvent("", { key: "ESCAPE", code: "Escape", keyCode: KeyboardEvent.DOM_VK_Escape});
     TIP.keydown(keyInvalidKey, TIP.KEY_NON_PRINTABLE_KEY);
     ok(false,
        description + "TIP.keydown(keyInvalidKey, TIP.KEY_NON_PRINTABLE_KEY) should cause throwing an exception because its key value is not registered");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keydown(keyInvalidKey, TIP.KEY_NON_PRINTABLE_KEY) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE");
   } finally {
     is(input.value, "",
        description + "The input element should not be modified");
   }
 
   // Calling keyup(KEY_NON_PRINTABLE_KEY) with a KeyboardEvent initialized with non-key name should cause an exception.
   input.value = "";
   try {
     var keyInvalidKey = new KeyboardEvent("", { key: "ESCAPE", code: "Escape", keyCode: KeyboardEvent.DOM_VK_Escape});
     TIP.keydown(keyInvalidKey, TIP.KEY_NON_PRINTABLE_KEY);
     ok(false,
        description + "TIP.keyup(keyInvalidKey, TIP.KEY_NON_PRINTABLE_KEY) should cause throwing an exception because its key value is not registered");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keyup(keyInvalidKey, TIP.KEY_NON_PRINTABLE_KEY) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE");
   } finally {
     is(input.value, "",
        description + "The input element should not be modified");
   }
 
   // KEY_KEEP_KEY_LOCATION_STANDARD flag should be used only when .location is not initialized with non-zero value.
   try {
     var keyEvent = new KeyboardEvent("", { code: "Enter", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT });
     TIP.keydown(keyEvent, TIP.KEY_KEEP_KEY_LOCATION_STANDARD);
     ok(false,
        description + "keydown(KEY_KEEP_KEY_LOCATION_STANDARD) should fail if the .location of the key event is initialized with non-zero value");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keydown(KEY_KEEP_KEY_LOCATION_STANDARD) should cause NS_ERROR_ILLEGAL_VALUE if the .location of the key event is initialized with nonzero value");
   }
   try {
     var keyEvent = new KeyboardEvent("", { code: "Enter", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT });
     TIP.keyup(keyEvent, TIP.KEY_KEEP_KEY_LOCATION_STANDARD);
     ok(false,
        description + "keyup(KEY_KEEP_KEY_LOCATION_STANDARD) should fail if the .location of the key event is initialized with non-zero value");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keyup(KEY_KEEP_KEY_LOCATION_STANDARD) should cause NS_ERROR_ILLEGAL_VALUE if the .location of the key event is initialized with nonzero value");
   }
 
   // KEY_KEEP_KEYCODE_ZERO flag should be used only when .keyCode is not initialized with non-zero value.
   try {
     var keyEvent = new KeyboardEvent("", { key: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
     TIP.keydown(keyEvent, TIP.KEY_KEEP_KEYCODE_ZERO);
     ok(false,
        description + "keydown(KEY_KEEP_KEYCODE_ZERO) should fail if the .keyCode of the key event is initialized with non-zero value");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keydown(KEY_KEEP_KEYCODE_ZERO) should cause NS_ERROR_ILLEGAL_VALUE if the .keyCode of the key event is initialized with nonzero value");
   }
   try {
     var keyEvent = new KeyboardEvent("", { key: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
     TIP.keyup(keyEvent, TIP.KEY_KEEP_KEYCODE_ZERO);
     ok(false,
        description + "keyup(KEY_KEEP_KEYCODE_ZERO) should fail if the .keyCode of the key event is initialized with non-zero value");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keyup(KEY_KEEP_KEYCODE_ZERO) should cause NS_ERROR_ILLEGAL_VALUE if the .keyCode of the key event is initialized with nonzero value");
   }
 
   // Specifying KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT with non-modifier key, it should cause an exception.
   try {
     var keyEvent = new KeyboardEvent("", { key: "a", code: "ShiftLeft" });
     TIP.keyup(keyEvent, TIP.KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT);
     ok(false,
        description + "keydown(KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT) should fail if the .key value isn't a modifier key");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keydown(KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT) should cause NS_ERROR_ILLEGAL_VALUE if the .key value isn't a modifier key");
   }
   try {
     var keyEvent = new KeyboardEvent("", { key: "Enter", code: "ShiftLeft" });
     TIP.keyup(keyEvent, TIP.KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT);
     ok(false,
        description + "keydown(KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT) should fail if the .key value isn't a modifier key");
   } catch (e) {
-    ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+    ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
        description + "keydown(KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT) should cause NS_ERROR_ILLEGAL_VALUE if the .key value isn't a modifier key");
   }
 
   // The type of key events specified to composition methods should be "" or "keydown".
   var kKeyEventTypes = [
     { type: "keydown",   valid: true },
     { type: "keypress",  valid: false },
     { type: "keyup",     valid: false },
@@ -3609,64 +3609,64 @@ function runErrorTests()
     try {
       TIP.startComposition(keyEvent);
       ok(kKeyEventTypes[i].valid,
          testDescription + "TIP.startComposition(keyEvent) should not accept the event type");
       TIP.cancelComposition();
     } catch (e) {
       ok(!kKeyEventTypes[i].valid,
          testDescription + "TIP.startComposition(keyEvent) should not throw an exception for the event type");
-      ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+      ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
          testDescription + "TIP.startComposition(keyEvent) should cause NS_ERROR_ILLEGAL_VALUE if the key event type isn't valid");
     }
     try {
       TIP.setPendingCompositionString("foo");
       TIP.appendClauseToPendingComposition(3, TIP.ATTR_RAW_CLAUSE);
       TIP.setCaretInPendingComposition(3);
       TIP.flushPendingComposition(keyEvent);
       ok(kKeyEventTypes[i].valid,
          testDescription + "TIP.flushPendingComposition(keyEvent) should not accept the event type");
       TIP.cancelComposition();
     } catch (e) {
       ok(!kKeyEventTypes[i].valid,
          testDescription + "TIP.flushPendingComposition(keyEvent) should not throw an exception for the event type");
-      ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+      ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
          testDescription + "TIP.flushPendingComposition(keyEvent) should cause NS_ERROR_ILLEGAL_VALUE if the key event type isn't valid");
     }
     try {
       TIP.startComposition();
       TIP.commitComposition(keyEvent);
       ok(kKeyEventTypes[i].valid,
          testDescription + "TIP.commitComposition(keyEvent) should not accept the event type");
     } catch (e) {
       ok(!kKeyEventTypes[i].valid,
          testDescription + "TIP.commitComposition(keyEvent) should not throw an exception for the event type");
-      ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+      ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
          testDescription + "TIP.commitComposition(keyEvent) should cause NS_ERROR_ILLEGAL_VALUE if the key event type isn't valid");
       TIP.cancelComposition();
     }
     try {
       TIP.commitCompositionWith("foo", keyEvent);
       ok(kKeyEventTypes[i].valid,
          testDescription + "TIP.commitCompositionWith(\"foo\", keyEvent) should not accept the event type");
     } catch (e) {
       ok(!kKeyEventTypes[i].valid,
          testDescription + "TIP.commitCompositionWith(\"foo\", keyEvent) should not throw an exception for the event type");
-      ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+      ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
          testDescription + "TIP.commitCompositionWith(\"foo\", keyEvent) should cause NS_ERROR_ILLEGAL_VALUE if the key event type isn't valid");
     }
     try {
       TIP.startComposition();
       TIP.cancelComposition(keyEvent);
       ok(kKeyEventTypes[i].valid,
          testDescription + "TIP.cancelComposition(keyEvent) should not accept the event type");
     } catch (e) {
       ok(!kKeyEventTypes[i].valid,
          testDescription + "TIP.cancelComposition(keyEvent) should not throw an exception for the event type");
-      ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
+      ok(e.message.includes("NS_ERROR_ILLEGAL_VALUE"),
          testDescription + "TIP.cancelComposition(keyEvent) should cause NS_ERROR_ILLEGAL_VALUE if the key event type isn't valid");
       TIP.cancelComposition();
     }
     input.value = "";
   }
 }
 
 function runCommitCompositionTests()
--- a/dom/base/test/csp/test_CSP_frameancestors.html
+++ b/dom/base/test/csp/test_CSP_frameancestors.html
@@ -68,17 +68,17 @@ examiner.prototype  = {
     try {
       asciiSpec = SpecialPowers.getPrivilegedProps(
                     SpecialPowers.do_QueryInterface(subject, "nsIURI"),
                     "asciiSpec");
 
       // skip checks on the test harness -- can't do this skipping for
       // cross-origin blocking since the observer doesn't get the URI.  This
       // can cause this test to over-succeed (but only in specific cases).
-      if (asciiSpec.contains("test_CSP_frameancestors.html")) {
+      if (asciiSpec.includes("test_CSP_frameancestors.html")) {
         return;
       }
     } catch (ex) {
       // was not an nsIURI, so it was probably a cross-origin report.
     }
 
 
     if (topic === "csp-on-violate-policy") {
--- a/dom/base/test/csp/test_connect-src.html
+++ b/dom/base/test/csp/test_connect-src.html
@@ -73,30 +73,30 @@ function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
   SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
    if (topic === "specialpowers-http-notify-request") {
       // making sure we do not bubble a result for something other
       // then the request in question.
-      if (!data.contains("file_csp_testserver.sjs?foo")) {
+      if (!data.includes("file_csp_testserver.sjs?foo")) {
         return;
       }
       checkResult("allowed");
     }
 
     if (topic === "csp-on-violate-policy") {
       // making sure we do not bubble a result for something other
       // then the request in question.
       var asciiSpec = SpecialPowers.getPrivilegedProps(
                         SpecialPowers.do_QueryInterface(subject, "nsIURI"),
                         "asciiSpec");
 
-      if (!asciiSpec.contains("file_csp_testserver.sjs?foo")) {
+      if (!asciiSpec.includes("file_csp_testserver.sjs?foo")) {
         return;
       }
       checkResult("blocked");
     }
   },
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
     SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
--- a/dom/base/test/csp/test_form-action.html
+++ b/dom/base/test/csp/test_form-action.html
@@ -50,29 +50,29 @@ function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
   SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
    if (topic === "specialpowers-http-notify-request") {
       // making sure we do not bubble a result for something other
       // then the request in question.
-      if (!data.contains("submit-form")) {
+      if (!data.includes("submit-form")) {
         return;
       }
       checkResult("allowed");
     }
 
     if (topic === "csp-on-violate-policy") {
       // making sure we do not bubble a result for something other
       // then the request in question.
       var asciiSpec = SpecialPowers.getPrivilegedProps(
                         SpecialPowers.do_QueryInterface(subject, "nsIURI"),
                         "asciiSpec");
-      if (!asciiSpec.contains("submit-form")) {
+      if (!asciiSpec.includes("submit-form")) {
         return;
       }
       checkResult("blocked");
     }
   },
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
     SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
--- a/dom/base/test/csp/test_leading_wildcard.html
+++ b/dom/base/test/csp/test_leading_wildcard.html
@@ -45,37 +45,37 @@ function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
   SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
 
    // allowed requests
    if (topic === "specialpowers-http-notify-request") {
-      if (data.contains("leading_wildcard_allowed.js")) {
+      if (data.includes("leading_wildcard_allowed.js")) {
         ok (true, "CSP should allow file_leading_wildcard_allowed.js!");
         finishTest();
       }
-      if (data.contains("leading_wildcard_blocked.js")) {
+      if (data.includes("leading_wildcard_blocked.js")) {
         ok(false, "CSP should not allow file_leading_wildcard_blocked.js!");
         finishTest();
       }
     }
 
     // blocked requests
     if (topic === "csp-on-violate-policy") {
       var asciiSpec = SpecialPowers.getPrivilegedProps(
                         SpecialPowers.do_QueryInterface(subject, "nsIURI"),
                         "asciiSpec");
 
-      if (asciiSpec.contains("leading_wildcard_allowed.js")) {
+      if (asciiSpec.includes("leading_wildcard_allowed.js")) {
         ok (false, "CSP should not block file_leading_wildcard_allowed.js!");
         finishTest();
       }
-      if (asciiSpec.contains("leading_wildcard_blocked.js")) {
+      if (asciiSpec.includes("leading_wildcard_blocked.js")) {
         ok (true, "CSP should block file_leading_wildcard_blocked.js!");
         finishTest();
       }
     }
   },
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
     SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
--- a/dom/base/test/test_getFeature_with_perm.html
+++ b/dom/base/test/test_getFeature_with_perm.html
@@ -13,17 +13,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=983502">Mozilla Bug 983502</a>
 <script type="application/javascript">
 
 function testSupported() {
   var mem;
   navigator.getFeature("hardware.memory").then(function(mem) {
 
     var isLinux = (navigator.platform.indexOf('Linux') != -1);
-    var isAndroid = !!navigator.userAgent.contains("Android");
+    var isAndroid = !!navigator.userAgent.includes("Android");
     var isB2G = !isAndroid && /Mobile|Tablet/.test(navigator.userAgent);
 
     if (isLinux) {
       info("It is Linux version:");
     }
     if (isAndroid) {
       info("It is Android version");
     }
@@ -98,17 +98,17 @@ info("About to run " + tests.length + " 
 
 SpecialPowers.pushPermissions([
   {type: "feature-detection", allow: 1, context: document}
 ], function() {
   ok('getFeature' in navigator, "navigator.getFeature should exist");
   ok('hasFeature' in navigator, "navigator.hasFeature should exist");
   // B2G specific manifest features.
   // Touching navigator before pushPermissions makes it fail.
-  if (!navigator.userAgent.contains("Android") &&
+  if (!navigator.userAgent.includes("Android") &&
         /Mobile|Tablet/.test(navigator.userAgent)) {
     info("Adding B2G specific tests");
     tests.push(createManifestTest("manifest.chrome.navigation"));
     tests.push(createManifestTest("manifest.precompile"));
   }
   runNextTest();
   ok(true, "Test DONE");
 });
--- a/dom/base/test/test_hasFeature.html
+++ b/dom/base/test/test_hasFeature.html
@@ -18,17 +18,17 @@ function testAPIs() {
     try {
       return SpecialPowers.getBoolPref(name);
     } catch (e) {
       return false;
     }
   }
 
   var b2gOnly = (function() {
-    var isAndroid = !!navigator.userAgent.contains("Android");
+    var isAndroid = !!navigator.userAgent.includes("Android");
     var isMulet = pref("b2g.is_mulet");
     var isB2g = isMulet || (!isAndroid && /Mobile|Tablet/.test(navigator.userAgent));
     return isB2g ? true : undefined;
   })();
 
   var APIEndPoints = [
     { name: "MozMobileNetworkInfo", enabled: pref("dom.mobileconnection.enabled") },
     // { name: "Navigator.mozBluetooth", enabled: b2gOnly }, // conditional on MOZ_B2G_BT, tricky to test
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2432,16 +2432,22 @@ ResolveGlobal(JSContext* aCx, JS::Handle
   MOZ_ASSERT(JS_IsGlobalObject(aObj),
              "Should have a global here, since we plan to resolve standard "
              "classes!");
 
   return JS_ResolveStandardClass(aCx, aObj, aId, aResolvedp);
 }
 
 bool
+MayResolveGlobal(const JSAtomState& aNames, jsid aId, JSObject* aMaybeObj)
+{
+  return JS_MayResolveStandardClass(aNames, aId, aMaybeObj);
+}
+
+bool
 EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj)
 {
   MOZ_ASSERT(JS_IsGlobalObject(aObj),
              "Should have a global here, since we plan to enumerate standard "
              "classes!");
 
   return JS_EnumerateStandardClasses(aCx, aObj);
 }
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2964,16 +2964,19 @@ IsInCertifiedApp(JSContext* aCx, JSObjec
 void
 FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
 
 bool
 ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
               JS::Handle<jsid> aId, bool* aResolvedp);
 
 bool
+MayResolveGlobal(const JSAtomState& aNames, jsid aId, JSObject* aMaybeObj);
+
+bool
 EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
 
 template <class T>
 struct CreateGlobalOptions
 {
   static MOZ_CONSTEXPR_VAR ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
     ProtoAndIfaceCache::NonWindowLike;
   // Intl API is broken and makes JS_InitStandardClasses fail intermittently,
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -192,16 +192,17 @@ DOMInterfaces = {
       'mozilla::dom::bluetooth::BluetoothPairingListener',
 },
 
 'BoxObject': {
     'resultNotAddRefed': ['element'],
 },
 
 'Cache': {
+    'implicitJSContext': [ 'add', 'addAll' ],
     'nativeType': 'mozilla::dom::cache::Cache',
 },
 
 'CacheStorage': {
     'nativeType': 'mozilla::dom::cache::CacheStorage',
 },
 
 'CameraCapabilities': {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -18,16 +18,17 @@ AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 OBJECT_MOVED_HOOK_NAME = '_objectMoved'
 CONSTRUCT_HOOK_NAME = '_constructor'
 LEGACYCALLER_HOOK_NAME = '_legacycaller'
 HASINSTANCE_HOOK_NAME = '_hasInstance'
 RESOLVE_HOOK_NAME = '_resolve'
+MAY_RESOLVE_HOOK_NAME = '_mayResolve'
 ENUMERATE_HOOK_NAME = '_enumerate'
 ENUM_ENTRY_VARIABLE_NAME = 'strings'
 INSTANCE_RESERVED_SLOTS = 1
 
 
 def memberReservedSlot(member):
     return "(DOM_INSTANCE_RESERVED_SLOTS + %d)" % member.slotIndex
 
@@ -452,36 +453,39 @@ class CGDOMJSClass(CGThing):
                     }
                     """,
                     objectMoved=objectMovedHook)
         else:
             classFlags += "JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount
             reservedSlots = slotCount
         if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
             resolveHook = RESOLVE_HOOK_NAME
+            mayResolveHook = MAY_RESOLVE_HOOK_NAME
             enumerateHook = ENUMERATE_HOOK_NAME
         elif self.descriptor.isGlobal():
             resolveHook = "mozilla::dom::ResolveGlobal"
+            mayResolveHook = "mozilla::dom::MayResolveGlobal"
             enumerateHook = "mozilla::dom::EnumerateGlobal"
         else:
             resolveHook = "nullptr"
+            mayResolveHook = "nullptr"
             enumerateHook = "nullptr"
 
         return fill(
             """
             static const DOMJSClass Class = {
               { "${name}",
                 ${flags},
                 ${addProperty}, /* addProperty */
                 nullptr,               /* delProperty */
                 nullptr,               /* getProperty */
                 nullptr,               /* setProperty */
                 ${enumerate}, /* enumerate */
                 ${resolve}, /* resolve */
-                nullptr,               /* mayResolve */
+                ${mayResolve}, /* mayResolve */
                 nullptr,               /* convert */
                 ${finalize}, /* finalize */
                 ${call}, /* call */
                 nullptr,               /* hasInstance */
                 nullptr,               /* construct */
                 ${trace}, /* trace */
                 JS_NULL_CLASS_SPEC,
                 $*{classExtensionAndObjectOps}
@@ -493,16 +497,17 @@ class CGDOMJSClass(CGThing):
             static_assert(${reservedSlots} >= ${slotCount},
                           "Must have enough reserved slots.");
             """,
             name=self.descriptor.interface.identifier.name,
             flags=classFlags,
             addProperty=ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'nullptr',
             enumerate=enumerateHook,
             resolve=resolveHook,
+            mayResolve=mayResolveHook,
             finalize=FINALIZE_HOOK_NAME,
             call=callHook,
             trace=traceHook,
             classExtensionAndObjectOps=classExtensionAndObjectOps,
             descriptor=DOMClass(self.descriptor),
             instanceReservedSlots=INSTANCE_RESERVED_SLOTS,
             reservedSlots=reservedSlots,
             slotCount=slotCount)
@@ -7764,67 +7769,93 @@ class CGLegacyCallHook(CGAbstractBinding
 
     def generate_code(self):
         name = self._legacycaller.identifier.name
         nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
         return CGMethodCall(nativeName, False, self.descriptor,
                             self._legacycaller)
 
 
-class CGResolveHook(CGAbstractBindingMethod):
+class CGResolveHook(CGAbstractClassHook):
     """
     Resolve hook for objects that have the NeedResolve extended attribute.
     """
     def __init__(self, descriptor):
         assert descriptor.interface.getExtendedAttribute("NeedResolve")
 
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'obj'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('bool*', 'resolvedp')]
-        # Our "self" is actually the "obj" argument in this case, not the thisval.
-        CGAbstractBindingMethod.__init__(
-            self, descriptor, RESOLVE_HOOK_NAME,
-            args, getThisObj="", callArgs="")
+        CGAbstractClassHook.__init__(self, descriptor, RESOLVE_HOOK_NAME,
+                                     "bool", args)
 
     def generate_code(self):
-        return CGGeneric(dedent("""
+        return dedent("""
             JS::Rooted<JSPropertyDescriptor> desc(cx);
             if (!self->DoResolve(cx, obj, id, &desc)) {
               return false;
             }
             if (!desc.object()) {
               return true;
             }
             // If desc.value() is undefined, then the DoResolve call
             // has already defined it on the object.  Don't try to also
             // define it.
             if (!desc.value().isUndefined() &&
                 !JS_DefinePropertyById(cx, obj, id, desc)) {
               return false;
             }
             *resolvedp = true;
             return true;
-            """))
+            """)
 
     def definition_body(self):
         if self.descriptor.isGlobal():
             # Resolve standard classes
             prefix = dedent("""
                 if (!ResolveGlobal(cx, obj, id, resolvedp)) {
                   return false;
                 }
                 if (*resolvedp) {
                   return true;
                 }
 
                 """)
         else:
             prefix = ""
-        return prefix + CGAbstractBindingMethod.definition_body(self)
+        return prefix + CGAbstractClassHook.definition_body(self)
+
+
+class CGMayResolveHook(CGAbstractStaticMethod):
+    """
+    Resolve hook for objects that have the NeedResolve extended attribute.
+    """
+    def __init__(self, descriptor):
+        assert descriptor.interface.getExtendedAttribute("NeedResolve")
+
+        args = [Argument('const JSAtomState&', 'names'),
+                Argument('jsid', 'id'),
+                Argument('JSObject*', 'maybeObj')]
+        CGAbstractStaticMethod.__init__(self, descriptor, MAY_RESOLVE_HOOK_NAME,
+                                        "bool", args)
+
+    def definition_body(self):
+        if self.descriptor.isGlobal():
+            # Check whether this would resolve as a standard class.
+            prefix = dedent("""
+                if (MayResolveGlobal(names, id, maybeObj)) {
+                  return true;
+                }
+
+                """)
+        else:
+            prefix = ""
+        return (prefix +
+                "return %s::MayResolve(id);\n" % self.descriptor.nativeType)
 
 
 class CGEnumerateHook(CGAbstractBindingMethod):
     """
     Enumerate hook for objects with custom hooks.
     """
     def __init__(self, descriptor):
         assert descriptor.interface.getExtendedAttribute("NeedResolve")
@@ -11343,16 +11374,17 @@ class CGDescriptor(CGThing):
             cgThings.append(CGInterfaceObjectJSClass(descriptor, properties))
             if descriptor.needsConstructHookHolder():
                 cgThings.append(CGClassConstructHookHolder(descriptor))
             cgThings.append(CGNamedConstructors(descriptor))
 
         cgThings.append(CGLegacyCallHook(descriptor))
         if descriptor.interface.getExtendedAttribute("NeedResolve"):
             cgThings.append(CGResolveHook(descriptor))
+            cgThings.append(CGMayResolveHook(descriptor))
             cgThings.append(CGEnumerateHook(descriptor))
 
         if descriptor.hasNamedPropertiesObject:
             cgThings.append(CGGetNamedPropertiesObjectMethod(descriptor))
 
         if descriptor.interface.hasInterfacePrototypeObject():
             cgThings.append(CGPrototypeJSClass(descriptor, properties))
 
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -20,16 +20,17 @@ class Configuration:
         execfile(filename, glbl)
         config = glbl['DOMInterfaces']
 
         # Build descriptors for all the interfaces we have in the parse data.
         # This allows callers to specify a subset of interfaces by filtering
         # |parseData|.
         self.descriptors = []
         self.interfaces = {}
+        self.optimizedOutDescriptorNames = set()
         self.generatedEvents = generatedEvents;
         self.maxProtoChainLength = 0;
         for thing in parseData:
             if isinstance(thing, IDLImplementsStatement):
                 # Our build system doesn't support dep build involving
                 # addition/removal of "implements" statements that appear in a
                 # different .webidl file than their LHS interface.  Make sure we
                 # don't have any of those.
@@ -55,16 +56,17 @@ class Configuration:
                 continue
             iface = thing
             self.interfaces[iface.identifier.name] = iface
             if iface.identifier.name not in config:
                 # Completely skip consequential interfaces with no descriptor
                 # if they have no interface object because chances are we
                 # don't need to do anything interesting with them.
                 if iface.isConsequential() and not iface.hasInterfaceObject():
+                    self.optimizedOutDescriptorNames.add(iface.identifier.name)
                     continue
                 entry = {}
             else:
                 entry = config[iface.identifier.name]
             if not isinstance(entry, list):
                 assert isinstance(entry, dict)
                 entry = [entry]
             elif len(entry) == 1:
@@ -241,24 +243,34 @@ class Configuration:
     def getCallbacks(self, **filters):
         return self._filterForFileAndWorkers(self.callbacks, filters)
 
     def getDescriptor(self, interfaceName, workers):
         """
         Gets the appropriate descriptor for the given interface name
         and the given workers boolean.
         """
-        for d in self.descriptorsByName[interfaceName]:
+        # We may have optimized out this descriptor, but the chances of anyone
+        # asking about it are then slim.  Put the check for that _after_ we've
+        # done our normal lookups.  But that means we have to do our normal
+        # lookups in a way that will not throw if they fail.
+        for d in self.descriptorsByName.get(interfaceName, []):
             if d.workers == workers:
                 return d
 
         if workers:
-            for d in self.descriptorsByName[interfaceName]:
+            for d in self.descriptorsByName.get(interfaceName, []):
                 return d
 
+        if interfaceName in self.optimizedOutDescriptorNames:
+            raise NoSuchDescriptorError(
+                "No descriptor for '%s', which is a mixin ([NoInterfaceObject] "
+                "and a consequential interface) without an explicit "
+                "Bindings.conf annotation." % interfaceName)
+
         raise NoSuchDescriptorError("For " + interfaceName + " found no matches");
     def getDescriptorProvider(self, workers):
         """
         Gets a descriptor provider that can provide descriptors as needed,
         for the given workers boolean
         """
         return DescriptorProvider(self, workers)
 
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -154,41 +154,16 @@ DOMProxyHandler::preventExtensions(JSCon
 bool
 DOMProxyHandler::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible) const
 {
   *extensible = true;
   return true;
 }
 
 bool
-BaseDOMProxyHandler::getPropertyDescriptor(JSContext* cx,
-                                           JS::Handle<JSObject*> proxy,
-                                           JS::Handle<jsid> id,
-                                           MutableHandle<JSPropertyDescriptor> desc) const
-{
-  if (!getOwnPropertyDescriptor(cx, proxy, id, desc)) {
-    return false;
-  }
-  if (desc.object()) {
-    return true;
-  }
-
-  JS::Rooted<JSObject*> proto(cx);
-  if (!js::GetObjectProto(cx, proxy, &proto)) {
-    return false;
-  }
-  if (!proto) {
-    desc.object().set(nullptr);
-    return true;
-  }
-
-  return JS_GetPropertyDescriptorById(cx, proto, id, desc);
-}
-
-bool
 BaseDOMProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
                                               JS::Handle<JSObject*> proxy,
                                               JS::Handle<jsid> id,
                                               MutableHandle<JSPropertyDescriptor> desc) const
 {
   return getOwnPropDescriptor(cx, proxy, id, /* ignoreNamedProps = */ false,
                               desc);
 }
--- a/dom/bindings/DOMJSProxyHandler.h
+++ b/dom/bindings/DOMJSProxyHandler.h
@@ -53,20 +53,16 @@ public:
   // Implementations of methods that can be implemented in terms of
   // other lower-level methods.
   bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
                                 JS::Handle<jsid> id,
                                 JS::MutableHandle<JSPropertyDescriptor> desc) const override;
   virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                JS::AutoIdVector &props) const override;
 
-  bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
-                             JS::Handle<jsid> id,
-                             JS::MutableHandle<JSPropertyDescriptor> desc) const override;
-
   virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
                          JS::MutableHandle<JSObject*> objp) const override;
 
   // We override getOwnEnumerablePropertyKeys() and implement it directly
   // instead of using the default implementation, which would call
   // ownPropertyKeys and then filter out the non-enumerable ones. This avoids
   // unnecessary work during enumeration.
   virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
--- a/dom/bindings/test/test_sequence_detection.html
+++ b/dom/bindings/test/test_sequence_detection.html
@@ -18,26 +18,26 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     var nonIterableObject = {[Symbol.iterator]: 5};
 
     try {
       testInterfaceJS.testSequenceOverload(nonIterableObject);
       ok(false, "Should have thrown in the overload case");  // see long comment above!
     } catch (e) {
       ise(e.name, "TypeError", "Should get a TypeError for the overload case");
-      ok(e.message.contains("not iterable"),
+      ok(e.message.includes("not iterable"),
          "Should have a message about being non-iterable in the overload case");
     }
 
     try {
       testInterfaceJS.testSequenceUnion(nonIterableObject);
       ok(false, "Should have thrown in the union case");
     } catch (e) {
       ise(e.name, "TypeError", "Should get a TypeError for the union case");
-      ok(e.message.contains("not iterable"),
+      ok(e.message.includes("not iterable"),
          "Should have a message about being non-iterable in the union case");
     }
 
     SimpleTest.finish();
   });
 
   </script>
 </head>
--- a/dom/cache/AutoUtils.cpp
+++ b/dom/cache/AutoUtils.cpp
@@ -2,26 +2,30 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "mozilla/dom/cache/AutoUtils.h"
 
 #include "mozilla/unused.h"
+#include "mozilla/dom/InternalHeaders.h"
+#include "mozilla/dom/InternalRequest.h"
 #include "mozilla/dom/cache/CacheParent.h"
 #include "mozilla/dom/cache/CachePushStreamChild.h"
 #include "mozilla/dom/cache/CacheStreamControlParent.h"
 #include "mozilla/dom/cache/ReadStream.h"
 #include "mozilla/dom/cache/SavedTypes.h"
 #include "mozilla/dom/cache/StreamList.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
+#include "nsCRT.h"
+#include "nsHttp.h"
 
 namespace {
 
 using mozilla::unused;
 using mozilla::dom::cache::CachePushStreamChild;
 using mozilla::dom::cache::CacheReadStream;
 using mozilla::dom::cache::CacheReadStreamOrVoid;
 using mozilla::ipc::FileDescriptor;
@@ -163,25 +167,16 @@ AutoChildOpArgs::~AutoChildOpArgs()
     {
       CacheMatchAllArgs& args = mOpArgs.get_CacheMatchAllArgs();
       if (args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t) {
         break;
       }
       CleanupChild(args.requestOrVoid().get_CacheRequest().body(), action);
       break;
     }
-    case CacheOpArgs::TCacheAddAllArgs:
-    {
-      CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
-      auto& list = args.requestList();
-      for (uint32_t i = 0; i < list.Length(); ++i) {
-        CleanupChild(list[i].body(), action);
-      }
-      break;
-    }
     case CacheOpArgs::TCachePutAllArgs:
     {
       CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
       auto& list = args.requestResponseList();
       for (uint32_t i = 0; i < list.Length(); ++i) {
         CleanupChild(list[i].request().body(), action);
         CleanupChild(list[i].response().body(), action);
       }
@@ -211,113 +206,200 @@ AutoChildOpArgs::~AutoChildOpArgs()
     default:
       // Other types do not need cleanup
       break;
   }
 }
 
 void
 AutoChildOpArgs::Add(InternalRequest* aRequest, BodyAction aBodyAction,
-                     ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
-                     ErrorResult& aRv)
+                     SchemeAction aSchemeAction, ErrorResult& aRv)
 {
   MOZ_ASSERT(!mSent);
 
   switch(mOpArgs.type()) {
     case CacheOpArgs::TCacheMatchArgs:
     {
       CacheMatchArgs& args = mOpArgs.get_CacheMatchArgs();
       mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
+                                 aSchemeAction, aRv);
       break;
     }
     case CacheOpArgs::TCacheMatchAllArgs:
     {
       CacheMatchAllArgs& args = mOpArgs.get_CacheMatchAllArgs();
       MOZ_ASSERT(args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t);
       args.requestOrVoid() = CacheRequest();
       mTypeUtils->ToCacheRequest(args.requestOrVoid().get_CacheRequest(),
-                                  aRequest, aBodyAction, aReferrerAction,
-                                  aSchemeAction, aRv);
-      break;
-    }
-    case CacheOpArgs::TCacheAddAllArgs:
-    {
-      CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
-
-      // The FileDescriptorSetChild asserts in its destructor that all fds have
-      // been removed.  The copy constructor, however, simply duplicates the
-      // fds without removing any.  This means each temporary and copy must be
-      // explicitly cleaned up.
-      //
-      // Avoid a lot of this hassle by making sure we only create one here.  On
-      // error we remove it.
-      CacheRequest& request = *args.requestList().AppendElement();
-
-      mTypeUtils->ToCacheRequest(request, aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
-      if (aRv.Failed()) {
-        args.requestList().RemoveElementAt(args.requestList().Length() - 1);
-      }
+                                  aRequest, aBodyAction, aSchemeAction, aRv);
       break;
     }
     case CacheOpArgs::TCacheDeleteArgs:
     {
       CacheDeleteArgs& args = mOpArgs.get_CacheDeleteArgs();
       mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
+                                 aSchemeAction, aRv);
       break;
     }
     case CacheOpArgs::TCacheKeysArgs:
     {
       CacheKeysArgs& args = mOpArgs.get_CacheKeysArgs();
       MOZ_ASSERT(args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t);
       args.requestOrVoid() = CacheRequest();
       mTypeUtils->ToCacheRequest(args.requestOrVoid().get_CacheRequest(),
-                                  aRequest, aBodyAction, aReferrerAction,
-                                  aSchemeAction, aRv);
+                                  aRequest, aBodyAction, aSchemeAction, aRv);
       break;
     }
     case CacheOpArgs::TStorageMatchArgs:
     {
       StorageMatchArgs& args = mOpArgs.get_StorageMatchArgs();
       mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
+                                 aSchemeAction, aRv);