Merge m-c to inbound. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 05 Dec 2015 15:27:33 -0500
changeset 309940 fea8e8cb105e34fefbea7521afe53e69f32c6aa8
parent 309939 5b71c7baa25502b9d1ea52c28c13f90a5ac74fee (current diff)
parent 309812 fb4801cfdbbf072a071f6a6ef8c1cf13dd6de960 (diff)
child 309941 bb05a1110e4c7b9fa6eaca8aeaad1dfff18acf41
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound. a=merge
storage/.eslintrc
toolkit/components/extensions/.eslintrc
--- a/.eslintignore
+++ b/.eslintignore
@@ -37,41 +37,17 @@ nsprpub/**
 other-licenses/**
 parser/**
 probes/**
 python/**
 rdf/**
 security/**
 services/**
 startupcache/**
-storage/**
 testing/**
-toolkit/components/**
-toolkit/content/**
-toolkit/crashreporter/**
-toolkit/forgetaboutsite/**
-toolkit/identity/**
-toolkit/library/**
-toolkit/locales/**
-toolkit/modules/**
-# This file contains preprocessor statements.
-toolkit/mozapps/extensions/internal/AddonConstants.jsm
-toolkit/mozapps/downloads/**
-toolkit/mozapps/handling/**
-toolkit/mozapps/installer/**
-toolkit/mozapps/preferences/**
-toolkit/mozapps/update/**
-toolkit/obsolete/**
-toolkit/pluginproblem/**
-toolkit/profile/**
-toolkit/system/**
-toolkit/themes/**
-toolkit/toolkit.mozbuild/**
-toolkit/webapps/**
-toolkit/xre/**
 tools/**
 uriloader/**
 view/**
 webapprt/**
 widget/**
 xpcom/**
 xpfe/**
 xulrunner/**
@@ -191,8 +167,39 @@ mobile/android/modules/ContactService.js
 #   https://github.com/eslint/espree/issues/125
 mobile/android/modules/WebappManager.jsm
 
 # Non-standard `(catch ex if ...)`
 mobile/android/components/Snippets.js
 
 # Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"
 mobile/android/modules/HomeProvider.jsm
+
+# toolkit/ exclusions
+
+# Not part of the default build
+toolkit/components/help/**
+
+# Intentionally invalid JS
+toolkit/components/workerloader/tests/moduleF-syntax-error.js
+
+# Tests old non-star function generators
+toolkit/modules/tests/xpcshell/test_task.js
+
+# Not yet updated
+toolkit/components/osfile/**
+toolkit/components/passwordmgr/**
+toolkit/components/places/**
+toolkit/mozapps/extensions/**
+
+# Uses preprocessing
+toolkit/content/contentAreaUtils.js
+toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+toolkit/components/search/nsSearchService.js
+toolkit/components/url-classifier/**
+toolkit/components/urlformatter/nsURLFormatter.js
+toolkit/identity/FirefoxAccounts.jsm
+toolkit/modules/AppConstants.jsm
+toolkit/modules/SessionRecorder.jsm
+toolkit/mozapps/downloads/nsHelperAppDlg.js
+toolkit/mozapps/extensions/internal/AddonConstants.jsm
+toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js
+toolkit/webapps/**
--- a/b2g/components/RecoveryService.js
+++ b/b2g/components/RecoveryService.js
@@ -49,19 +49,19 @@ if (isGonk) {
       FotaUpdateStatus:    FotaUpdateStatus,
       getFotaUpdateStatus: library.declare("getFotaUpdateStatus",
                                            ctypes.default_abi,
                                            ctypes.int,
                                            FotaUpdateStatus.ptr)
     };
   })();
 
-  const gFactoryResetFile = "__post_reset_cmd__";
+}
 
-}
+const gFactoryResetFile = "__post_reset_cmd__";
 
 function RecoveryService() {}
 
 RecoveryService.prototype = {
   classID: RECOVERYSERVICE_CID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIRecoveryService]),
   classInfo: XPCOMUtils.generateCI({
     classID: RECOVERYSERVICE_CID,
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/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="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
@@ -105,17 +105,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="f0c3b4edf597c40aae4ea311575f39c8bcf203df"/>
   <project name="platform/libcore" path="libcore" revision="baf7d8068dd501cfa338d3a8b1b87216d6ce0571"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="50c4430e32849530ced32680fd6ee98963b3f7ac"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="c739cffa6394c06e099ea48879a20341b6163338"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
   <project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>
   <project name="platform/external/curl" path="external/curl" revision="e68addd988448959ea8157c5de637346b4180c33"/>
   <project name="platform/external/icu4c" path="external/icu4c" revision="d3ec7428eb276db43b7ed0544e09344a6014806c"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="76c4bf4bc430a1b8317f2f21ef735867733e50cc"/>
--- 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="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
@@ -111,17 +111,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="68b0c269fd1889f47ecfb9119c05281e9b6db0af"/>
   <project name="platform/libcore" path="libcore" revision="e195beab082c09217318fc19250caeaf4c1bd800"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="feeb36c2bd4adfe285f98f5de92e0f3771b2c115"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="c739cffa6394c06e099ea48879a20341b6163338"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
   <project name="platform/system/media" path="system/media" revision="188b3e51e0a2ce1e16dc8067edef7be3d2365ad9"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/netd" path="system/netd" revision="3ae56364946d4a5bf5a5f83f12f9a45a30398e33"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
   <project name="platform/system/vold" path="system/vold" revision="fe12a9e2268da653d1cd4c39ec89a42211d22f25"/>
   <!--original fetch url was http://sprdsource.spreadtrum.com:8085/b2g/android-->
   <remote fetch="https://git.mozilla.org/external/sprd-aosp" name="sprd-aosp"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/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 git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gecko and Gaia -->
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <!-- Gonk-specific things and forks -->
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
   <project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- 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="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <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="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
@@ -113,17 +113,17 @@
   <project name="platform/libcore" path="libcore" revision="3552ed1686d04a65b85e56ccc24ff3fcf77725e6"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="4792069e90385889b0638e97ae62c67cdf274e22"/>
   <project name="platform/ndk" path="ndk" revision="7666b97bbaf1d645cdd6b4430a367b7a2bb53369"/>
   <project name="platform/prebuilts/misc" path="prebuilts/misc" revision="f6ab40b3257abc07741188fd173ac392575cc8d2"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="e52099755d0bd3a579130eefe8e58066cc6c0cb6"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
   <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
--- 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="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
@@ -109,17 +109,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="01f436c51dc68aec7cc1c85fda6e6792b2a95066"/>
   <project name="platform/libcore" path="libcore" revision="9877ade9617bb0db6e59aa2a54719a9bc92600f3"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="46c96ace65eb1ccab05bf15b9bf8e53e443039af"/>
   <project name="platform/ndk" path="ndk" revision="cb5519af32ae7b4a9c334913a612462ecd04c5d0"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="c739cffa6394c06e099ea48879a20341b6163338"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="6aa61f8557a22039a30b42b7f283996381fd625d"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
   <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
   <project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="2da3a2d5100f8afa1229bb50aa2a29ea0aaf8417"/>
--- 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="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
@@ -121,17 +121,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="8d075b4d5e9e032b18fbc8b5def63827d1b4a30d"/>
   <project name="platform/libcore" path="libcore" revision="bdec7d684c083760bef7bc4ba2429cceccaaf7d0"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="27bcc086236cedd31c056303e255c6d0ea3d4a50"/>
   <project name="platform/ndk" path="ndk" revision="42e85f81cc6c74af145056ee80b06e520cccb9a7"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="179d485578c6907c0daf343a3bd7bc53b5e137a1"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="1d080491f26dfdfd76d5bbc3e6b40c660e8565af"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="61a10cbd19d6b7fc052a8cb92dfa1b37b93754f3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="9e892a67a01671f312c76b0880dedaa6ba478148"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="47fa016e2248b80aebd5928402c7409f8e0ca64e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/media" path="system/media" revision="70bfebc66d9c6a4c614a8c7efde90e8e7e1d8641"/>
   <project name="platform/system/netd" path="system/netd" revision="d113f0ceefa9ce29eb3c86e2d23c7417a70b4048"/>
   <project name="platform/system/security" path="system/security" revision="94e1617f6f2bc2286d005e79cffa6bf0721b06b3"/>
   <project name="platform/system/vold" path="system/vold" revision="c065e301e38ea0c241164e2a373e1ecefbeaf2ec"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="6971327dda6bead878724ac1c767ee2d23a2a9e1"/>
   <project name="platform_frameworks_base" path="frameworks/base" remote="b2g" revision="04e26ebdc36ca83f4ee3e9e2082b3fcf04c5b971"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/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 git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gecko and Gaia -->
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <!-- Gonk-specific things and forks -->
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
   <project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- 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="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
@@ -104,17 +104,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="f0c3b4edf597c40aae4ea311575f39c8bcf203df"/>
   <project name="platform/libcore" path="libcore" revision="baf7d8068dd501cfa338d3a8b1b87216d6ce0571"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="50c4430e32849530ced32680fd6ee98963b3f7ac"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="c739cffa6394c06e099ea48879a20341b6163338"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
   <project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>
   <project name="platform/external/curl" path="external/curl" revision="e68addd988448959ea8157c5de637346b4180c33"/>
   <project name="platform/external/icu4c" path="external/icu4c" revision="d3ec7428eb276db43b7ed0544e09344a6014806c"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="76c4bf4bc430a1b8317f2f21ef735867733e50cc"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "e9419046f360dd05b2717c4994990608519b93e4", 
+        "git_revision": "b930e25e9f2e5ec2106dd31005468575cdf87d50", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "f8b0a6383f642ae3160fad856fc7c93496a9a1ae", 
+    "revision": "ef09f991c6706eae886785ececae0cc155b9cebd", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-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="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
@@ -111,17 +111,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="01f436c51dc68aec7cc1c85fda6e6792b2a95066"/>
   <project name="platform/libcore" path="libcore" revision="9877ade9617bb0db6e59aa2a54719a9bc92600f3"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="46c96ace65eb1ccab05bf15b9bf8e53e443039af"/>
   <project name="platform/ndk" path="ndk" revision="cb5519af32ae7b4a9c334913a612462ecd04c5d0"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="c739cffa6394c06e099ea48879a20341b6163338"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="6aa61f8557a22039a30b42b7f283996381fd625d"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
   <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
   <project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="2da3a2d5100f8afa1229bb50aa2a29ea0aaf8417"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -13,17 +13,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <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="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
@@ -114,17 +114,17 @@
   <project name="platform/libcore" path="libcore" revision="3552ed1686d04a65b85e56ccc24ff3fcf77725e6"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="4792069e90385889b0638e97ae62c67cdf274e22"/>
   <project name="platform/ndk" path="ndk" revision="7666b97bbaf1d645cdd6b4430a367b7a2bb53369"/>
   <project name="platform/prebuilts/misc" path="prebuilts/misc" revision="f6ab40b3257abc07741188fd173ac392575cc8d2"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="e52099755d0bd3a579130eefe8e58066cc6c0cb6"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
   <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/media" path="system/media" revision="d90b836f66bf1d9627886c96f3a2d9c3007fbb80"/>
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
--- 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="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e9419046f360dd05b2717c4994990608519b93e4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b930e25e9f2e5ec2106dd31005468575cdf87d50"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
@@ -122,17 +122,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="8d075b4d5e9e032b18fbc8b5def63827d1b4a30d"/>
   <project name="platform/libcore" path="libcore" revision="bdec7d684c083760bef7bc4ba2429cceccaaf7d0"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="27bcc086236cedd31c056303e255c6d0ea3d4a50"/>
   <project name="platform/ndk" path="ndk" revision="42e85f81cc6c74af145056ee80b06e520cccb9a7"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="179d485578c6907c0daf343a3bd7bc53b5e137a1"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="1d080491f26dfdfd76d5bbc3e6b40c660e8565af"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="61a10cbd19d6b7fc052a8cb92dfa1b37b93754f3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="9e892a67a01671f312c76b0880dedaa6ba478148"/>
-  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="bdb3469b9302bb22e7df8912e582feefbd05d55f"/>
+  <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="570531db9e81a871c421b27025ae558022b1015a"/>
   <project name="platform/system/extras" path="system/extras" revision="47fa016e2248b80aebd5928402c7409f8e0ca64e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
   <project name="platform/system/media" path="system/media" revision="70bfebc66d9c6a4c614a8c7efde90e8e7e1d8641"/>
   <project name="platform/system/netd" path="system/netd" revision="d113f0ceefa9ce29eb3c86e2d23c7417a70b4048"/>
   <project name="platform/system/security" path="system/security" revision="94e1617f6f2bc2286d005e79cffa6bf0721b06b3"/>
   <project name="platform/system/vold" path="system/vold" revision="c065e301e38ea0c241164e2a373e1ecefbeaf2ec"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="6971327dda6bead878724ac1c767ee2d23a2a9e1"/>
   <project name="platform_frameworks_base" path="frameworks/base" remote="b2g" revision="04e26ebdc36ca83f4ee3e9e2082b3fcf04c5b971"/>
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -280,70 +280,82 @@
         var event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
         document.dispatchEvent(event);
 
         if (err == "nssBadCert") {
           // Remove the "Try again" button for security exceptions, since it's
           // almost certainly useless.
           document.getElementById("errorTryAgain").style.display = "none";
           document.getElementById("errorPageContainer").setAttribute("class", "certerror");
-          addDomainErrorLink();
         }
         else {
           // Remove the override block for non-certificate errors.  CSS-hiding
           // isn't good enough here, because of bug 39098
           var secOverride = document.getElementById("securityOverrideDiv");
           secOverride.parentNode.removeChild(secOverride);
         }
+        addDomainErrorLinks();
       }
 
       function showSecuritySection() {
         // Swap link out, content in
         document.getElementById('securityOverrideContent').style.display = '';
         document.getElementById('securityOverrideLink').style.display = 'none';
       }
 
-      /* In the case of SSL error pages about domain mismatch, see if
+      /* Try to preserve the links contained in the error description, like
+         the error code.
+
+         Also, in the case of SSL error pages about domain mismatch, see if
          we can hyperlink the user to the correct site.  We don't want
          to do this generically since it allows MitM attacks to redirect
          users to a site under attacker control, but in certain cases
          it is safe (and helpful!) to do so.  Bug 402210
       */
-      function addDomainErrorLink() {
+      function addDomainErrorLinks() {
         // Rather than textContent, we need to treat description as HTML
         var sd = document.getElementById("errorShortDescText");
         if (sd) {
           var desc = getDescription();
 
           // sanitize description text - see bug 441169
 
-          // First, find the index of the <a> tag we care about, being careful not to
-          // use an over-greedy regex
-          var re = /<a id="cert_domain_link" title="([^"]+)">/;
-          var result = re.exec(desc);
-          if(!result)
+          // First, find the index of the <a> tags we care about, being
+          // careful not to use an over-greedy regex.
+          var codeRe = /<a id="errorCode" title="([^"]+)">/;
+          var codeResult = codeRe.exec(desc);
+          var domainRe = /<a id="cert_domain_link" title="([^"]+)">/;
+          var domainResult = domainRe.exec(desc);
+
+          // The order of these links in the description is fixed in
+          // TransportSecurityInfo.cpp:formatOverridableCertErrorMessage.
+          var firstResult = domainResult;
+          if(!domainResult)
+            firstResult = codeResult;
+          if (!firstResult)
             return;
-
           // Remove sd's existing children
           sd.textContent = "";
 
-          // Everything up to the link should be text content
-          sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
+          // Everything up to the first link should be text content.
+          sd.appendChild(document.createTextNode(desc.slice(0, firstResult.index)));
 
-          // Now create the link itself
-          var anchorEl = document.createElement("a");
-          anchorEl.setAttribute("id", "cert_domain_link");
-          anchorEl.setAttribute("title", result[1]);
-          anchorEl.appendChild(document.createTextNode(result[1]));
-          sd.appendChild(anchorEl);
+          // Now create the actual links.
+          if (domainResult) {
+            createLink(sd, "cert_domain_link", domainResult[1])
+            // Append text for anything between the two links.
+            sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length, codeResult.index)));
+          }
+          createLink(sd, "errorCode", codeResult[1])
 
-          // Finally, append text for anything after the closing </a>
-          sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
+          // Finally, append text for anything after the last closing </a>.
+          sd.appendChild(document.createTextNode(desc.slice(desc.lastIndexOf("</a>") + "</a>".length)));
         }
 
+        // Initialize the cert domain link.
         var link = document.getElementById('cert_domain_link');
         if (!link)
           return;
 
         var okHost = link.getAttribute("title");
         var thisHost = document.location.hostname;
         var proto = document.location.protocol;
 
@@ -360,30 +372,39 @@
          * Make sure to include the "." ahead of thisHost so that
          * a MitM attack on paypal.com doesn't hyperlink to "notpaypal.com"
          *
          * We'd normally just use a RegExp here except that we lack a
          * library function to escape them properly (bug 248062), and
          * domain names are famous for having '.' characters in them,
          * which would allow spurious and possibly hostile matches.
          */
-        if (endsWith(okHost, "." + thisHost))
+        if (okHost.endsWith("." + thisHost))
           link.href = proto + okHost;
 
         /* case #2:
          * browser.garage.maemo.org uses an invalid security certificate.
          *
          * The certificate is only valid for garage.maemo.org
          */
-        if (endsWith(thisHost, "." + okHost))
+        if (thisHost.endsWith("." + okHost))
           link.href = proto + okHost;
+
+        // If we set a link, meaning there's something helpful for
+        // the user here, expand the section by default
+        if (link.href && getCSSClass() != "expertBadCert")
+          toggleVisibility("advancedPanel");
       }
 
-      function endsWith(haystack, needle) {
-        return haystack.slice(-needle.length) == needle;
+      function createLink(el, id, text) {
+        var anchorEl = document.createElement("a");
+        anchorEl.setAttribute("id", id);
+        anchorEl.setAttribute("title", text);
+        anchorEl.appendChild(document.createTextNode(text));
+        el.appendChild(anchorEl);
       }
     ]]></script>
   </head>
 
   <body dir="&locale.dir;">
 
     <!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
     <div id="errorContainer">
@@ -439,18 +460,18 @@
         <div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
         <div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
         <div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
         <div id="ed_unwantedBlocked">&unwantedBlocked.longDesc;</div>
         <div id="ed_forbiddenBlocked">&forbiddenBlocked.longDesc;</div>
         <div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
         <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
         <div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
-        <div id="ed_sslv3Used">&sslv3Used.longDesc;</div>
-        <div id="ed_weakCryptoUsed">&weakCryptoUsed.longDesc;</div>
+        <div id="ed_sslv3Used">&sslv3Used.longDesc2;</div>
+        <div id="ed_weakCryptoUsed">&weakCryptoUsed.longDesc2;</div>
       </div>
     </div>
 
     <!-- PAGE CONTAINER (for styling purposes only) -->
     <div id="errorPageContainer">
 
       <!-- Error Title -->
       <div id="errorTitle">
--- a/browser/base/content/aboutcerterror/aboutCertError.xhtml
+++ b/browser/base/content/aboutcerterror/aboutCertError.xhtml
@@ -50,16 +50,23 @@
         // parenthetical match is the second entry
         return decodeURIComponent(matches[1]);
       }
 
       function toggleVisibility(id)
       {
         var node = document.getElementById(id);
         node.style.visibility = node.style.visibility == "" ? "hidden" : "";
+        // Toggling the advanced panel must ensure that the debugging
+        // information panel is hidden as well, since it's opened by the
+        // error code link in the advanced panel.
+        if (id == "advancedPanel") {
+          var div = document.getElementById("certificateErrorDebugInformation");
+          div.style.display = "none";
+        }
       }
 
       function getDescription()
       {
         var url = document.documentURI;
         var desc = url.search(/d\=/);
 
         // desc == -1 if not found; if so, return an empty string
@@ -90,57 +97,89 @@
         if (cssClass != "badStsCert") {
           document.getElementById("badStsCertExplanation").setAttribute("hidden", "true");
         }
 
         var tech = document.getElementById("technicalContentText");
         if (tech)
           tech.textContent = getDescription();
 
-        addDomainErrorLink();
+        var event = new CustomEvent("AboutCertErrorLoad", {bubbles:true});
+        document.getElementById("advancedButton").dispatchEvent(event);
+
+        addDomainErrorLinks();
       }
 
-      /* In the case of SSL error pages about domain mismatch, see if
+      /* Try to preserve the links contained in the error description, like
+         the error code.
+
+         Also, in the case of SSL error pages about domain mismatch, see if
          we can hyperlink the user to the correct site.  We don't want
          to do this generically since it allows MitM attacks to redirect
          users to a site under attacker control, but in certain cases
          it is safe (and helpful!) to do so.  Bug 402210
       */
-      function addDomainErrorLink() {
+      function addDomainErrorLinks() {
         // Rather than textContent, we need to treat description as HTML
         var sd = document.getElementById("technicalContentText");
         if (sd) {
           var desc = getDescription();
 
           // sanitize description text - see bug 441169
 
-          // First, find the index of the <a> tag we care about, being careful not to
-          // use an over-greedy regex
-          var re = /<a id="cert_domain_link" title="([^"]+)">/;
-          var result = re.exec(desc);
-          if(!result)
+          // First, find the index of the <a> tags we care about, being
+          // careful not to use an over-greedy regex.
+          var codeRe = /<a id="errorCode" title="([^"]+)">/;
+          var codeResult = codeRe.exec(desc);
+          var domainRe = /<a id="cert_domain_link" title="([^"]+)">/;
+          var domainResult = domainRe.exec(desc);
+
+          // The order of these links in the description is fixed in
+          // TransportSecurityInfo.cpp:formatOverridableCertErrorMessage.
+          var firstResult = domainResult;
+          if(!domainResult)
+            firstResult = codeResult;
+          if (!firstResult)
             return;
 
           // Remove sd's existing children
           sd.textContent = "";
 
-          // Everything up to the link should be text content
-          sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
+          // Everything up to the first link should be text content.
+          sd.appendChild(document.createTextNode(desc.slice(0, firstResult.index)));
 
-          // Now create the link itself
-          var anchorEl = document.createElement("a");
-          anchorEl.setAttribute("id", "cert_domain_link");
-          anchorEl.setAttribute("title", result[1]);
-          anchorEl.appendChild(document.createTextNode(result[1]));
-          sd.appendChild(anchorEl);
+          // Now create the actual links.
+          if (domainResult) {
+            createLink(sd, "cert_domain_link", domainResult[1])
+            // Append text for anything between the two links.
+            sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length, codeResult.index)));
+          }
+          createLink(sd, "errorCode", codeResult[1])
 
-          // Finally, append text for anything after the closing </a>
-          sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
+          // Finally, append text for anything after the last closing </a>.
+          sd.appendChild(document.createTextNode(desc.slice(desc.lastIndexOf("</a>") + "</a>".length)));
         }
 
+        // Initialize the error code link embedded in the error message to
+        // display debug information about the cert error.
+        var errorCode = document.getElementById("errorCode");
+        if (errorCode) {
+          errorCode.href = "#technicalInformation";
+          errorCode.addEventListener("click", () => {
+            var div = document.getElementById("certificateErrorDebugInformation");
+            if (div.style.display == "block") {
+              div.style.display = "none";
+            } else {
+              div.style.display = "block";
+              div.scrollIntoView(true);
+            }
+          }, false);
+        }
+
+        // Then initialize the cert domain link.
         var link = document.getElementById('cert_domain_link');
         if (!link)
           return;
 
         var okHost = link.getAttribute("title");
         var thisHost = document.location.hostname;
         var proto = document.location.protocol;
 
@@ -173,16 +212,24 @@
         if (thisHost.endsWith("." + okHost))
           link.href = proto + okHost;
 
         // If we set a link, meaning there's something helpful for
         // the user here, expand the section by default
         if (link.href && getCSSClass() != "expertBadCert")
           toggleVisibility("advancedPanel");
       }
+
+      function createLink(el, id, text) {
+        var anchorEl = document.createElement("a");
+        anchorEl.setAttribute("id", id);
+        anchorEl.setAttribute("title", text);
+        anchorEl.appendChild(document.createTextNode(text));
+        el.appendChild(anchorEl);
+      }
     ]]></script>
   </head>
 
   <body dir="&locale.dir;">
     <!-- PAGE CONTAINER (for styling purposes only) -->
     <div id="errorPageContainer">
 
       <!-- Error Title -->
@@ -205,21 +252,28 @@
         <div id="buttonContainer">
           <button id="returnButton" autocomplete="off" autofocus="true">&certerror.returnToPreviousPage.label;</button>
           <div id="buttonSpacer"></div>
           <button id="advancedButton" autocomplete="off" onclick="toggleVisibility('advancedPanel');" autofocus="true">&certerror.advanced.label;</button>
         </div>
         <!-- Advanced panel, which is hidden by default -->
         <div id="advancedPanel" style="visibility: hidden;">
           <p id="technicalContentText"/>
-          <button id='exceptionDialogButton'>&certerror.addException.label;</button>
+          <button id="exceptionDialogButton">&certerror.addException.label;</button>
         </div>
       </div>
     </div>
 
+    <div id="certificateErrorDebugInformation">
+      <a name="technicalInformation"></a>
+      <button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
+      <div id="certificateErrorText"/>
+      <button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
+    </div>
+
     <!--
     - Note: It is important to run the script this way, instead of using
     - an onload handler. This is because error pages are loaded as
     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
     -->
     <script type="application/javascript">initPage();</script>
 
   </body>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2696,17 +2696,17 @@ var BrowserOnClick = {
     }
   },
 
   receiveMessage: function (msg) {
     switch (msg.name) {
       case "Browser:CertExceptionError":
         this.onAboutCertError(msg.target, msg.data.elementId,
                               msg.data.isTopFrame, msg.data.location,
-                              msg.data.sslStatusAsString);
+                              msg.data.securityInfoAsString);
       break;
       case "Browser:SiteBlockedError":
         this.onAboutBlocked(msg.data.elementId, msg.data.reason,
                             msg.data.isTopFrame, msg.data.location);
       break;
       case "Browser:EnableOnlineMode":
         if (Services.io.offline) {
           // Reset network state and refresh the page.
@@ -2782,29 +2782,16 @@ var BrowserOnClick = {
      * - Error type (e.g. Pinning, domain mismatch, etc)
      * - Cert chain (at minimum, same data to distrust each cert in the
      *   chain)
      * - Request data (e.g. User Agent, IP, Timestamp)
      *
      * The request data should be added to the report by the receiving server.
      */
 
-    // TODO: can we pull this in from pippki.js isntead of duplicating it
-    // here?
-    function getDERString(cert)
-    {
-      var length = {};
-      var derArray = cert.getRawDER(length);
-      var derString = '';
-      for (var i = 0; i < derArray.length; i++) {
-        derString += String.fromCharCode(derArray[i]);
-      }
-      return derString;
-    }
-
     // Convert the nsIX509CertList into a format that can be parsed into
     // JSON
     let asciiCertChain = [];
 
     if (transportSecurityInfo.failedCertChain) {
       let certs = transportSecurityInfo.failedCertChain.getEnumerator();
       while (certs.hasMoreElements()) {
         let cert = certs.getNext();
@@ -2851,29 +2838,30 @@ var BrowserOnClick = {
       } else {
         showReportStatus("complete");
       }
     };
 
     xhr.send(JSON.stringify(report));
   },
 
-  onAboutCertError: function (browser, elementId, isTopFrame, location, sslStatusAsString) {
+  onAboutCertError: function (browser, elementId, isTopFrame, location, securityInfoAsString) {
     let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
 
     switch (elementId) {
       case "exceptionDialogButton":
         if (isTopFrame) {
           secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_CLICK_ADD_EXCEPTION);
         }
 
         let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                            .getService(Ci.nsISerializationHelper);
-        let sslStatus = serhelper.deserializeObject(sslStatusAsString);
-        sslStatus.QueryInterface(Components.interfaces.nsISSLStatus);
+        let securityInfo = serhelper.deserializeObject(securityInfoAsString);
+        let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
+                                    .SSLStatus;
         let params = { exceptionAdded : false,
                        sslStatus : sslStatus };
 
         try {
           switch (Services.prefs.getIntPref("browser.ssl_override_behavior")) {
             case 2 : // Pre-fetch & pre-populate
               params.prefetchCert = true;
             case 1 : // Pre-populate
@@ -2898,16 +2886,29 @@ var BrowserOnClick = {
         }
         goBackFromErrorPage();
         break;
 
       case "advancedButton":
         if (isTopFrame) {
           secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_UNDERSTAND_RISKS);
         }
+
+        let errorInfo = getDetailedCertErrorInfo(location,
+                                                 securityInfoAsString);
+        browser.messageManager.sendAsyncMessage("AboutCertErrorDetails",
+                                                { info: errorInfo });
+        break;
+
+      case "copyToClipboard":
+        const gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"]
+                                    .getService(Ci.nsIClipboardHelper);
+        let detailedInfo = getDetailedCertErrorInfo(location,
+                                                    securityInfoAsString);
+        gClipboardHelper.copyString(detailedInfo);
         break;
 
     }
   },
 
   onAboutBlocked: function (elementId, reason, isTopFrame, location) {
     // Depending on what page we are displaying here (malware/phishing/unwanted)
     // use the right strings and links for each.
@@ -3152,16 +3153,86 @@ function BrowserReloadWithFlags(reloadFl
 
   gBrowser.selectedBrowser
           .messageManager
           .sendAsyncMessage("Browser:Reload",
                             { flags: reloadFlags,
                               handlingUserInput: windowUtils.isHandlingUserInput });
 }
 
+/**
+ * Returns a string with detailed information about the certificate validation
+ * failure from the specified URI that can be used to send a report.
+ */
+function getDetailedCertErrorInfo(location, securityInfoAsString) {
+  if (!securityInfoAsString)
+    return "";
+
+  let details = [];
+  details.push(location);
+
+  const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
+                       .getService(Ci.nsISerializationHelper);
+  let securityInfo = serhelper.deserializeObject(securityInfoAsString);
+  securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
+
+  let errors = Cc["@mozilla.org/nss_errors_service;1"]
+                  .getService(Ci.nsINSSErrorsService);
+  let code = securityInfo.errorCode;
+  details.push(errors.getErrorMessage(errors.getXPCOMFromNSSError(code)));
+
+  const sss = Cc["@mozilla.org/ssservice;1"]
+                 .getService(Ci.nsISiteSecurityService);
+  // SiteSecurityService uses different storage if the channel is
+  // private. Thus we must give isSecureHost correct flags or we
+  // might get incorrect results.
+  let flags = PrivateBrowsingUtils.isWindowPrivate(window) ?
+              Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
+
+  let uri = Services.io.newURI(location, null, null);
+  details.push(sss.isSecureHost(sss.HEADER_HSTS, uri.host, flags));
+  details.push(sss.isSecureHost(sss.HEADER_HPKP, uri.host, flags));
+
+  let certChain = "";
+  if (securityInfo.failedCertChain) {
+    let certs = securityInfo.failedCertChain.getEnumerator();
+    while (certs.hasMoreElements()) {
+      let cert = certs.getNext();
+      cert.QueryInterface(Ci.nsIX509Cert);
+      certChain += getPEMString(cert);
+    }
+  }
+  details.push(certChain);
+  return gNavigatorBundle.getFormattedString("certErrorDetails.label", details, 5);
+}
+
+// TODO: can we pull getDERString and getPEMString in from pippki.js instead of
+// duplicating them here?
+function getDERString(cert)
+{
+  var length = {};
+  var derArray = cert.getRawDER(length);
+  var derString = '';
+  for (var i = 0; i < derArray.length; i++) {
+    derString += String.fromCharCode(derArray[i]);
+  }
+  return derString;
+}
+
+function getPEMString(cert)
+{
+  var derb64 = btoa(getDERString(cert));
+  // Wrap the Base64 string into lines of 64 characters,
+  // with CRLF line breaks (as specified in RFC 1421).
+  var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
+  return "-----BEGIN CERTIFICATE-----\r\n"
+         + wrapped
+         + "\r\n-----END CERTIFICATE-----\r\n";
+}
+
 var PrintPreviewListener = {
   _printPreviewTab: null,
   _tabBeforePrintPreview: null,
 
   getPrintPreviewBrowser: function () {
     if (!this._printPreviewTab) {
       let browser = gBrowser.selectedTab.linkedBrowser;
       let forceNotRemote = gMultiProcessBrowser && !browser.isRemoteBrowser;
@@ -5318,20 +5389,24 @@ function hrefAndLinkNodeForClickEvent(ev
 
   if (node)
     return [node.href, node];
 
   // If there is no linkNode, try simple XLink.
   let href, baseURI;
   node = event.target;
   while (node && !href) {
-    if (node.nodeType == Node.ELEMENT_NODE) {
+    if (node.nodeType == Node.ELEMENT_NODE &&
+        (node.localName == "a" ||
+         node.namespaceURI == "http://www.w3.org/1998/Math/MathML")) {
       href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
-      if (href)
+      if (href) {
         baseURI = node.baseURI;
+        break;
+      }
     }
     node = node.parentNode;
   }
 
   // In case of XLink, we don't return the node we got href from since
   // callers expect <a>-like elements.
   return [href ? makeURLAbsolute(baseURI, href) : null, null];
 }
@@ -7936,9 +8011,8 @@ TabModalPromptBox.prototype = {
   get browser() {
     let browser = this._weakBrowserRef.get();
     if (!browser) {
       throw "Stale promptbox! The associated browser is gone.";
     }
     return browser;
   },
 };
-
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -311,17 +311,16 @@ var AboutNetErrorListener = {
           reportSendingMsg.style.display = "none";
           sendAsyncMessage("Browser:SSLErrorReportTelemetry",
                            {reportStatus: TLS_ERROR_REPORT_TELEMETRY_SUCCESS});
           break;
         }
       }
     });
 
-    let failedChannel = docShell.failedChannel;
     let location = contentDoc.location.href;
 
     let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                      .getService(Ci.nsISerializationHelper);
 
     let serializable =  docShell.failedChannel.securityInfo
                                 .QueryInterface(Ci.nsITransportSecurityInfo)
                                 .QueryInterface(Ci.nsISerializable);
@@ -431,31 +430,31 @@ var ClickEventHandler = {
   },
 
   onAboutCertError: function (targetElement, ownerDoc) {
     let docshell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
                                        .getInterface(Ci.nsIWebNavigation)
                                        .QueryInterface(Ci.nsIDocShell);
     let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                      .getService(Ci.nsISerializationHelper);
-    let serializedSSLStatus = "";
+    let serializedSecurityInfo = "";
 
     try {
       let serializable =  docShell.failedChannel.securityInfo
-                                  .QueryInterface(Ci.nsISSLStatusProvider)
-                                  .SSLStatus
+                                  .QueryInterface(Ci.nsITransportSecurityInfo)
                                   .QueryInterface(Ci.nsISerializable);
-      serializedSSLStatus = serhelper.serializeToString(serializable);
+
+      serializedSecurityInfo = serhelper.serializeToString(serializable);
     } catch (e) { }
 
     sendAsyncMessage("Browser:CertExceptionError", {
       location: ownerDoc.location.href,
       elementId: targetElement.getAttribute("id"),
       isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
-      sslStatusAsString: serializedSSLStatus
+      securityInfoAsString: serializedSecurityInfo
     });
   },
 
   onAboutBlocked: function (targetElement, ownerDoc) {
     var reason = 'phishing';
     if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
       reason = 'malware';
     } else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
@@ -515,17 +514,19 @@ var ClickEventHandler = {
 
     if (node)
       return [node.href, node, node.ownerDocument.nodePrincipal];
 
     // If there is no linkNode, try simple XLink.
     let href, baseURI;
     node = event.target;
     while (node && !href) {
-      if (node.nodeType == content.Node.ELEMENT_NODE) {
+      if (node.nodeType == content.Node.ELEMENT_NODE &&
+          (node.localName == "a" ||
+           node.namespaceURI == "http://www.w3.org/1998/Math/MathML")) {
         href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
         if (href) {
           baseURI = node.ownerDocument.baseURIObject;
           break;
         }
       }
       node = node.parentNode;
     }
@@ -547,16 +548,27 @@ var pluginContent = new PluginContent(gl
 addEventListener("DOMWebNotificationClicked", function(event) {
   sendAsyncMessage("DOMWebNotificationClicked", {});
 }, false);
 
 addEventListener("DOMServiceWorkerFocusClient", function(event) {
   sendAsyncMessage("DOMServiceWorkerFocusClient", {});
 }, false);
 
+addEventListener("AboutCertErrorLoad", function(event) {
+  let originalTarget = event.originalTarget;
+  let ownerDoc = originalTarget.ownerDocument;
+  ClickEventHandler.onAboutCertError(originalTarget, ownerDoc);
+}, false, true);
+
+addMessageListener("AboutCertErrorDetails", function(message) {
+  let div = content.document.getElementById("certificateErrorText");
+  div.textContent = message.data.info;
+});
+
 ContentWebRTC.init();
 addMessageListener("rtcpeer:Allow", ContentWebRTC);
 addMessageListener("rtcpeer:Deny", ContentWebRTC);
 addMessageListener("webrtc:Allow", ContentWebRTC);
 addMessageListener("webrtc:Deny", ContentWebRTC);
 addMessageListener("webrtc:StopSharing", ContentWebRTC);
 addMessageListener("webrtc:StartBrowserSharing", () => {
   let windowID = content.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/browser/base/content/test/general/browser_aboutCertError.js
+++ b/browser/base/content/test/general/browser_aboutCertError.js
@@ -1,13 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// This is testing the aboutCertError page (Bug 1207107).  It's a start,
-// but should be expanded to include cert_domain_link
+// This is testing the aboutCertError page (Bug 1207107).
 
 const GOOD_PAGE = "https://example.com/";
 const BAD_CERT = "https://expired.example.com/";
 const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
 const {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
 const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
 add_task(function* checkReturnToAboutHome() {
@@ -98,17 +97,186 @@ add_task(function* checkBadStsCert() {
     let exceptionButton = doc.getElementById("exceptionDialogButton");
     return exceptionButton.hidden;
   });
   ok(exceptionButtonHidden, "Exception button is hidden");
 
   gBrowser.removeCurrentTab();
 });
 
+add_task(function* checkAdvancedDetails() {
+  info("Loading a bad cert page and verifying the advanced details section");
+  let browser;
+  let certErrorLoaded;
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+    gBrowser.selectedTab = gBrowser.addTab(BAD_CERT);
+    browser = gBrowser.selectedBrowser;
+    certErrorLoaded = waitForCertErrorLoad(browser);
+  }, false);
+
+  info("Loading and waiting for the cert error");
+  yield certErrorLoaded;
+
+  let message = yield ContentTask.spawn(browser, null, function* () {
+    let doc = content.document;
+    let advancedButton = doc.getElementById("advancedButton");
+    advancedButton.click();
+    let el = doc.getElementById("errorCode");
+    return { textContent: el.textContent, tagName: el.tagName };
+  });
+  is(message.textContent, "SEC_ERROR_EXPIRED_CERTIFICATE",
+     "Correct error message found");
+  is(message.tagName, "a", "Error message is a link");
+
+  message = yield ContentTask.spawn(browser, null, function* () {
+    let doc = content.document;
+    let errorCode = doc.getElementById("errorCode");
+    errorCode.click();
+    let div = doc.getElementById("certificateErrorDebugInformation");
+    let text = doc.getElementById("certificateErrorText");
+
+    let docshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
+                          .getInterface(Ci.nsIWebNavigation)
+                          .QueryInterface(Ci.nsIDocShell);
+    let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
+                     .getService(Ci.nsISerializationHelper);
+    let serializable =  docShell.failedChannel.securityInfo
+                                .QueryInterface(Ci.nsITransportSecurityInfo)
+                                .QueryInterface(Ci.nsISerializable);
+    let serializedSecurityInfo = serhelper.serializeToString(serializable);
+    return {
+      divDisplay: div.style.display,
+      text: text.textContent,
+      securityInfoAsString: serializedSecurityInfo
+    };
+  });
+  is(message.divDisplay, "block", "Debug information is visible");
+  ok(message.text.contains(BAD_CERT), "Correct URL found");
+  ok(message.text.contains("Certificate has expired"),
+     "Correct error message found");
+  ok(message.text.contains("HTTP Strict Transport Security: false"),
+     "Correct HSTS value found");
+  ok(message.text.contains("HTTP Public Key Pinning: false"),
+     "Correct HPKP value found");
+  let certChain = getCertChain(message.securityInfoAsString);
+  ok(message.text.contains(certChain), "Found certificate chain");
+
+  gBrowser.removeCurrentTab();
+});
+
+add_task(function* checkAdvancedDetailsForHSTS() {
+  info("Loading a bad STS cert page and verifying the advanced details section");
+  let browser;
+  let certErrorLoaded;
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+    gBrowser.selectedTab = gBrowser.addTab(BAD_STS_CERT);
+    browser = gBrowser.selectedBrowser;
+    certErrorLoaded = waitForCertErrorLoad(browser);
+  }, false);
+
+  info("Loading and waiting for the cert error");
+  yield certErrorLoaded;
+
+  let message = yield ContentTask.spawn(browser, null, function* () {
+    let doc = content.document;
+    let advancedButton = doc.getElementById("advancedButton");
+    advancedButton.click();
+    let ec = doc.getElementById("errorCode");
+    let cdl = doc.getElementById("cert_domain_link");
+    return {
+      ecTextContent: ec.textContent,
+      ecTagName: ec.tagName,
+      cdlTextContent: cdl.textContent,
+      cdlTagName: cdl.tagName
+    };
+  });
+
+  const badStsUri = Services.io.newURI(BAD_STS_CERT, null, null);
+  is(message.ecTextContent, "SSL_ERROR_BAD_CERT_DOMAIN",
+     "Correct error message found");
+  is(message.ecTagName, "a", "Error message is a link");
+  const url = badStsUri.prePath.slice(badStsUri.prePath.indexOf(".") + 1);
+  is(message.cdlTextContent, url,
+     "Correct cert_domain_link contents found");
+  is(message.cdlTagName, "a", "cert_domain_link is a link");
+
+  message = yield ContentTask.spawn(browser, null, function* () {
+    let doc = content.document;
+    let errorCode = doc.getElementById("errorCode");
+    errorCode.click();
+    let div = doc.getElementById("certificateErrorDebugInformation");
+    let text = doc.getElementById("certificateErrorText");
+
+    let docshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
+                          .getInterface(Ci.nsIWebNavigation)
+                          .QueryInterface(Ci.nsIDocShell);
+    let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
+                     .getService(Ci.nsISerializationHelper);
+    let serializable =  docShell.failedChannel.securityInfo
+                                .QueryInterface(Ci.nsITransportSecurityInfo)
+                                .QueryInterface(Ci.nsISerializable);
+    let serializedSecurityInfo = serhelper.serializeToString(serializable);
+    return {
+      divDisplay: div.style.display,
+      text: text.textContent,
+      securityInfoAsString: serializedSecurityInfo
+    };
+  });
+  is(message.divDisplay, "block", "Debug information is visible");
+  ok(message.text.contains(badStsUri.spec), "Correct URL found");
+  ok(message.text.contains("requested domain name does not match the server's certificate"),
+     "Correct error message found");
+  ok(message.text.contains("HTTP Strict Transport Security: false"),
+     "Correct HSTS value found");
+  ok(message.text.contains("HTTP Public Key Pinning: true"),
+     "Correct HPKP value found");
+  let certChain = getCertChain(message.securityInfoAsString);
+  ok(message.text.contains(certChain), "Found certificate chain");
+
+  gBrowser.removeCurrentTab();
+});
+
 function waitForCertErrorLoad(browser) {
   return new Promise(resolve => {
     info("Waiting for DOMContentLoaded event");
     browser.addEventListener("DOMContentLoaded", function load() {
       browser.removeEventListener("DOMContentLoaded", load, false, true);
       resolve();
     }, false, true);
   });
 }
+
+function getCertChain(securityInfoAsString) {
+  let certChain = "";
+  const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
+                       .getService(Ci.nsISerializationHelper);
+  let securityInfo = serhelper.deserializeObject(securityInfoAsString);
+  securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
+  let certs = securityInfo.failedCertChain.getEnumerator();
+  while (certs.hasMoreElements()) {
+    let cert = certs.getNext();
+    cert.QueryInterface(Ci.nsIX509Cert);
+    certChain += getPEMString(cert);
+  }
+  return certChain;
+}
+
+function getDERString(cert)
+{
+  var length = {};
+  var derArray = cert.getRawDER(length);
+  var derString = '';
+  for (var i = 0; i < derArray.length; i++) {
+    derString += String.fromCharCode(derArray[i]);
+  }
+  return derString;
+}
+
+function getPEMString(cert)
+{
+  var derb64 = btoa(getDERString(cert));
+  // Wrap the Base64 string into lines of 64 characters,
+  // with CRLF line breaks (as specified in RFC 1421).
+  var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
+  return "-----BEGIN CERTIFICATE-----\r\n"
+         + wrapped
+         + "\r\n-----END CERTIFICATE-----\r\n";
+}
--- a/browser/base/content/test/general/browser_blockHPKP.js
+++ b/browser/base/content/test/general/browser_blockHPKP.js
@@ -68,17 +68,17 @@ var successfulPinningPageListener = {
 
 // The browser should load about:neterror, when this happens, proceed
 // to load the pinning domain again, this time removing the pinning information
 var certErrorProgressListener = {
   onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
     if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
       let textElement = content.document.getElementById("errorShortDescText");
       let text = textElement.innerHTML;
-      ok(text.indexOf("mozilla_pkix_error_key_pinning_failure") > 0,
+      ok(text.indexOf("MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE") > 0,
          "Got a pinning error page");
       gBrowser.removeProgressListener(this);
       gBrowser.selectedBrowser.addEventListener("load",
                                                 successfulPinningRemovalPageListener,
                                                 true);
       gBrowser.selectedBrowser.loadURI("https://" + kPinningDomain + kURLPath + "zeromaxagevalid");
     }
   }
--- a/browser/branding/aurora/branding.nsi
+++ b/browser/branding/aurora/branding.nsi
@@ -15,17 +15,17 @@
 !define HelpLink              "https://support.mozilla.org"
 
 !define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-aurora-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=aurora&installer_lang=${AB_CD}"
 !define Channel "aurora"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
-!define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
+!define CertIssuerDownload "DigiCert Assured ID Code Signing CA-1"
 
 # Dialog units are used so the UI displays correctly with the system's DPI
 # settings.
 # The dialog units for the bitmap's dimensions should match exactly with the
 # bitmap's width and height in pixels.
 !define APPNAME_BMP_WIDTH_DU 108u
 !define APPNAME_BMP_HEIGHT_DU 48u
 !define INTRO_BLURB_WIDTH_DU "232u"
--- a/browser/branding/nightly/branding.nsi
+++ b/browser/branding/nightly/branding.nsi
@@ -14,17 +14,17 @@
 !define HelpLink              "https://support.mozilla.org"
 
 !define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-nightly-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=nightly&installer_lang=${AB_CD}"
 !define Channel "nightly"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
-!define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
+!define CertIssuerDownload "DigiCert Assured ID Code Signing CA-1"
 
 # Dialog units are used so the UI displays correctly with the system's DPI
 # settings.
 # The dialog units for the bitmap's dimensions should match exactly with the
 # bitmap's width and height in pixels.
 !define APPNAME_BMP_WIDTH_DU 159u
 !define APPNAME_BMP_HEIGHT_DU 28u
 !define INTRO_BLURB_WIDTH_DU "230u"
--- a/browser/branding/official/branding.nsi
+++ b/browser/branding/official/branding.nsi
@@ -19,17 +19,17 @@
 ; set the update channel to beta.
 !define OFFICIAL
 !define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}"
 !define Channel "release"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
-!define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
+!define CertIssuerDownload "DigiCert Assured ID Code Signing CA-1"
 
 # Dialog units are used so the UI displays correctly with the system's DPI
 # settings.
 # The dialog units for the bitmap's dimensions should match exactly with the
 # bitmap's width and height in pixels.
 !define APPNAME_BMP_WIDTH_DU "134u"
 !define APPNAME_BMP_HEIGHT_DU "36u"
 !define INTRO_BLURB_WIDTH_DU "258u"
--- a/browser/branding/unofficial/branding.nsi
+++ b/browser/branding/unofficial/branding.nsi
@@ -14,17 +14,17 @@
 !define HelpLink              "https://support.mozilla.org"
 
 !define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}"
 !define Channel "unofficial"
 
 # The installer's certificate name and issuer expected by the stub installer
 !define CertNameDownload   "Mozilla Corporation"
-!define CertIssuerDownload "DigiCert SHA2 Assured ID Code Signing CA"
+!define CertIssuerDownload "Thawte Code Signing CA - G2"
 
 # Dialog units are used so the UI displays correctly with the system's DPI
 # settings.
 # The dialog units for the bitmap's dimensions should match exactly with the
 # bitmap's width and height in pixels.
 !define APPNAME_BMP_WIDTH_DU 159u
 !define APPNAME_BMP_HEIGHT_DU 50u
 !define INTRO_BLURB_WIDTH_DU "230u"
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -34,16 +34,19 @@ const kNSXUL = "http://www.mozilla.org/k
 const kSpecialWidgetPfx = "customizableui-special-";
 
 const kPrefCustomizationState        = "browser.uiCustomization.state";
 const kPrefCustomizationAutoAdd      = "browser.uiCustomization.autoAdd";
 const kPrefCustomizationDebug        = "browser.uiCustomization.debug";
 const kPrefDrawInTitlebar            = "browser.tabs.drawInTitlebar";
 const kPrefWebIDEInNavbar            = "devtools.webide.widget.inNavbarByDefault";
 
+const kExpectedWindowURL = "chrome://browser/content/browser.xul";
+
+
 /**
  * The keys are the handlers that are fired when the event type (the value)
  * is fired on the subview. A widget that provides a subview has the option
  * of providing onViewShowing and onViewHiding event handlers.
  */
 const kSubviewEvents = [
   "ViewShowing",
   "ViewHiding"
@@ -1295,16 +1298,19 @@ var CustomizableUIInternal = {
           return node;
         }
       }
     }
     return null;
   },
 
   buildWidget: function(aDocument, aWidget) {
+    if (aDocument.documentURI != kExpectedWindowURL) {
+      throw new Error("buildWidget was called for a non-browser window!");
+    }
     if (typeof aWidget == "string") {
       aWidget = gPalette.get(aWidget);
     }
     if (!aWidget) {
       throw new Error("buildWidget was passed a non-widget to build.");
     }
 
     LOG("Building " + aWidget.id + " of type " + aWidget.type);
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/.eslintrc
@@ -0,0 +1,16 @@
+{
+  "extends": "../../../toolkit/components/extensions/.eslintrc",
+
+  "globals": {
+    "currentWindow": true,
+    "EventEmitter": true,
+    "IconDetails": true,
+    "openPanel": true,
+    "makeWidgetId": true,
+    "TabContext": true,
+    "AllWindowEvents": true,
+    "WindowEventManager": true,
+    "WindowListManager": true,
+    "WindowManager": true,
+  },
+}
--- a/browser/components/extensions/ext-bookmarks.js
+++ b/browser/components/extensions/ext-bookmarks.js
@@ -1,16 +1,19 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 var Bookmarks = PlacesUtils.bookmarks;
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
-  EventManager,
   runSafe,
 } = ExtensionUtils;
 
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
 
 function getTree(rootGuid, onlyChildren) {
   function convert(node, parent) {
@@ -35,21 +38,22 @@ function getTree(rootGuid, onlyChildren)
         treenode.children = node.children.map(child => convert(child, node));
       }
     }
 
     return treenode;
   }
 
   return PlacesUtils.promiseBookmarksTree(rootGuid, {
-    excludeItemsCallback: aItem => {
-      if (aItem.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR)
+    excludeItemsCallback: item => {
+      if (item.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR) {
         return true;
-      return aItem.annos &&
-             aItem.annos.find(a => a.name == PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
+      }
+      return item.annos &&
+             item.annos.find(a => a.name == PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
     },
   }).then(root => {
     if (onlyChildren) {
       let children = root.children || [];
       return children.map(child => convert(child, root));
     } else {
       // It seems like the array always just contains the root node.
       return [convert(root, null)];
@@ -163,24 +167,24 @@ extensions.registerPrivilegedAPI("bookma
         };
 
         try {
           Bookmarks.insert(info).then(result => {
             if (callback) {
               runSafe(context, callback, convert(result));
             }
           }, failure);
-        } catch(e) {
+        } catch (e) {
           failure(e);
         }
       },
 
       move: function(id, destination, callback) {
         let info = {
-          guid: id
+          guid: id,
         };
 
         if ("parentId" in destination) {
           info.parentGuid = destination.parentId;
         }
         if ("index" in destination) {
           info.index = destination.index;
         }
@@ -199,17 +203,17 @@ extensions.registerPrivilegedAPI("bookma
           }, failure);
         } catch (e) {
           failure(e);
         }
       },
 
       update: function(id, changes, callback) {
         let info = {
-          guid: id
+          guid: id,
         };
 
         if ("title" in changes) {
           info.title = changes.title;
         }
         if ("url" in changes) {
           info.url = changes.url;
         }
@@ -228,17 +232,17 @@ extensions.registerPrivilegedAPI("bookma
           }, failure);
         } catch (e) {
           failure(e);
         }
       },
 
       remove: function(id, callback) {
         let info = {
-          guid: id
+          guid: id,
         };
 
         let failure = reason => {
           if (callback) {
             runSafe(context, callback, null);
           }
         };
 
@@ -247,14 +251,14 @@ extensions.registerPrivilegedAPI("bookma
             if (callback) {
               // The API doesn't give you the old bookmark at the moment
               runSafe(context, callback);
             }
           }, failure);
         } catch (e) {
           failure(e);
         }
-      }
-    }
+      },
+    },
   };
 });
 
 
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -5,34 +5,29 @@
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
                                   "resource:///modules/CustomizableUI.jsm");
 
 Cu.import("resource://devtools/shared/event-emitter.js");
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   EventManager,
-  DefaultWeakMap,
   runSafe,
 } = ExtensionUtils;
 
 // WeakMap[Extension -> BrowserAction]
 var browserActionMap = new WeakMap();
 
-function browserActionOf(extension)
-{
+function browserActionOf(extension) {
   return browserActionMap.get(extension);
 }
 
-var nextActionId = 0;
-
 // Responsible for the browser_action section of the manifest as well
 // as the associated popup.
-function BrowserAction(options, extension)
-{
+function BrowserAction(options, extension) {
   this.extension = extension;
   this.id = makeWidgetId(extension.id) + "-browser-action";
   this.widget = null;
 
   this.tabManager = TabManager.for(extension);
 
   let title = extension.localize(options.default_title || "");
   let popup = extension.localize(options.default_popup || "");
@@ -68,33 +63,33 @@ BrowserAction.prototype = {
         node.id = this.id;
         node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional badged-button");
         node.setAttribute("constrain-size", "true");
 
         this.updateButton(node, this.defaults);
 
         let tabbrowser = document.defaultView.gBrowser;
 
-        node.addEventListener("command", event => {
+        node.addEventListener("command", event => { // eslint-disable-line mozilla/balanced-listeners
           let tab = tabbrowser.selectedTab;
           let popup = this.getProperty(tab, "popup");
           this.tabManager.addActiveTabPermission(tab);
           if (popup) {
             this.togglePopup(node, popup);
           } else {
             this.emit("click");
           }
         });
 
         return node;
       },
     });
 
-    this.tabContext.on("tab-select",
-                       (evt, tab) => { this.updateWindow(tab.ownerDocument.defaultView); })
+    this.tabContext.on("tab-select", // eslint-disable-line mozilla/balanced-listeners
+                       (evt, tab) => { this.updateWindow(tab.ownerDocument.defaultView); });
 
     this.widget = widget;
   },
 
   togglePopup(node, popupResource) {
     openPanel(node, popupResource, this.extension);
   },
 
@@ -119,17 +114,17 @@ BrowserAction.prototype = {
 
     if (tabData.enabled) {
       node.removeAttribute("disabled");
     } else {
       node.setAttribute("disabled", "true");
     }
 
     let badgeNode = node.ownerDocument.getAnonymousElementByAttribute(node,
-                                        'class', 'toolbarbutton-badge');
+                                        "class", "toolbarbutton-badge");
     if (badgeNode) {
       let color = tabData.badgeBackgroundColor;
       if (Array.isArray(color)) {
         color = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
       }
       badgeNode.style.backgroundColor = color || "";
     }
 
@@ -185,28 +180,30 @@ BrowserAction.prototype = {
   },
 
   shutdown() {
     this.tabContext.shutdown();
     CustomizableUI.destroyWidget(this.id);
   },
 };
 
+/* eslint-disable mozilla/balanced-listeners */
 extensions.on("manifest_browser_action", (type, directive, extension, manifest) => {
   let browserAction = new BrowserAction(manifest.browser_action, extension);
   browserAction.build();
   browserActionMap.set(extension, browserAction);
 });
 
 extensions.on("shutdown", (type, extension) => {
   if (browserActionMap.has(extension)) {
     browserActionMap.get(extension).shutdown();
     browserActionMap.delete(extension);
   }
 });
+/* eslint-enable mozilla/balanced-listeners */
 
 extensions.registerAPI((extension, context) => {
   return {
     browserAction: {
       onClicked: new EventManager(context, "browserAction.onClicked", fire => {
         let listener = () => {
           let tab = TabManager.activeTab;
           fire(TabManager.convert(extension, tab));
@@ -268,21 +265,20 @@ extensions.registerAPI((extension, conte
 
       getPopup: function(details, callback) {
         let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
         let popup = browserActionOf(extension).getProperty(tab, "popup");
         runSafe(context, callback, popup);
       },
 
       setBadgeBackgroundColor: function(details) {
-        let color = details.color;
         let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
         browserActionOf(extension).setProperty(tab, "badgeBackgroundColor", details.color);
       },
 
       getBadgeBackgroundColor: function(details, callback) {
         let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
         let color = browserActionOf(extension).getProperty(tab, "badgeBackgroundColor");
         runSafe(context, callback, color);
       },
-    }
+    },
   };
 });
--- a/browser/components/extensions/ext-contextMenus.js
+++ b/browser/components/extensions/ext-contextMenus.js
@@ -1,36 +1,34 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 Cu.import("resource://gre/modules/MatchPattern.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 var {
   EventManager,
-  contextMenuItems,
-  runSafe
+  runSafe,
 } = ExtensionUtils;
 
 
 // Map[Extension -> Map[ID -> MenuItem]]
 // Note: we want to enumerate all the menu items so
 // this cannot be a weak map.
 var contextMenuMap = new Map();
 
 // Not really used yet, will be used for event pages.
 var onClickedCallbacksMap = new WeakMap();
 
 // If id is not specified for an item we use an integer.
 var nextID = 0;
 
-function contextMenuObserver(subject, topic, data) {
-  subject = subject.wrappedJSObject;
-  menuBuilder.build(subject);
-}
-
 // When a new contextMenu is opened, this function is called and
 // we populate the |xulMenu| with all the items from extensions
 // to be displayed. We always clear all the items again when
 // popuphidden fires. Since most of the info we need is already
 // calculated in nsContextMenu.jsm we simple reuse its flags here.
 // For remote processes there is a gContextMenuContentData where all
 // the important info is stored from the child process. We get
 // this data in |contextData|.
@@ -77,17 +75,17 @@ var menuBuilder = {
             // If parentId is set we have to look up its parent
             // and appened to its menupopup.
             let parentElement = parentMap.get(parentId);
             parentElement.appendChild(element);
           } else {
             topLevelItems.add(element);
           }
 
-          element.addEventListener("command", event => {
+          element.addEventListener("command", event => { // eslint-disable-line mozilla/balanced-listeners
             item.tabManager.addActiveTabPermission();
             if (item.onclick) {
               let clickData = item.getClickData(contextData, event);
               runSafe(item.extContext, item.onclick, clickData);
             }
           });
         }
       }
@@ -119,68 +117,72 @@ var menuBuilder = {
     for (let item of this._itemsToCleanUp) {
       target.removeChild(item);
     }
     // Let's detach the top level items.
     this._itemsToCleanUp.clear();
   },
 
   _itemsToCleanUp: new Set(),
+};
+
+function contextMenuObserver(subject, topic, data) {
+  subject = subject.wrappedJSObject;
+  menuBuilder.build(subject);
 }
 
 function getContexts(contextData) {
   let contexts = new Set(["all"]);
 
   contexts.add("page");
 
   if (contextData.inFrame) {
-    contexts.add("frame")
+    contexts.add("frame");
   }
 
   if (contextData.isTextSelected) {
-    contexts.add("selection")
+    contexts.add("selection");
   }
 
   if (contextData.onLink) {
-    contexts.add("link")
+    contexts.add("link");
   }
 
   if (contextData.onEditableArea) {
-    contexts.add("editable")
+    contexts.add("editable");
   }
 
   if (contextData.onImage) {
-    contexts.add("image")
+    contexts.add("image");
   }
 
   if (contextData.onVideo) {
-    contexts.add("video")
+    contexts.add("video");
   }
 
   if (contextData.onAudio) {
-    contexts.add("audio")
+    contexts.add("audio");
   }
 
   return contexts;
 }
 
-function MenuItem(extension, extContext, createProperties)
-{
+function MenuItem(extension, extContext, createProperties) {
   this.extension = extension;
   this.extContext = extContext;
 
   this.tabManager = TabManager.for(extension);
 
   this.init(createProperties);
 }
 
 MenuItem.prototype = {
   // init is called from the MenuItem ctor and from update. The |update|
   // flag is for the later case.
-  init(createProperties, update=false) {
+  init(createProperties, update = false) {
     let item = this;
     // return true if the prop was set on |this|
     function parseProp(propName, defaultValue = null) {
       if (propName in createProperties) {
         item[propName] = createProperties[propName];
         return true;
       } else if (!update && defaultValue !== null) {
         item[propName] = defaultValue;
@@ -209,18 +211,18 @@ MenuItem.prototype = {
     if ("onclick" in createProperties.wrappedJSObject) {
       this.onclick = createProperties.wrappedJSObject.onclick;
     }
 
     if (parseProp("parentId")) {
       let found = false;
       let menuMap = contextMenuMap.get(this.extension);
       if (menuMap.has(this.parentId)) {
-          found = true;
-          menuMap.get(this.parentId).isMenu = true;
+        found = true;
+        menuMap.get(this.parentId).isMenu = true;
       }
       if (!found) {
         throw new Error("MenuItem with this parentId not found");
       }
     } else {
       this.parentId = undefined;
     }
 
@@ -260,17 +262,17 @@ MenuItem.prototype = {
       }
       let rv = hasAncestorWithId(parent, id);
       checked.set(item, rv);
       return rv;
     }
 
     let toRemove = new Set();
     toRemove.add(this.id);
-    for (let [id, item] of menuMap) {
+    for (let [, item] of menuMap) {
       if (hasAncestorWithId(item, this.id)) {
         toRemove.add(item.id);
       }
     }
     for (let id of toRemove) {
       menuMap.delete(id);
     }
   },
@@ -283,17 +285,17 @@ MenuItem.prototype = {
     if (contextData.onAudio) {
       mediaType = "audio";
     }
     if (contextData.onImage) {
       mediaType = "image";
     }
 
     let clickData = {
-      menuItemId: this.id
+      menuItemId: this.id,
     };
 
     function setIfDefined(argName, value) {
       if (value) {
         clickData[argName] = value;
       }
     }
 
@@ -313,17 +315,17 @@ MenuItem.prototype = {
   },
 
   enabledForContext(contextData) {
     let enabled = false;
     let contexts = getContexts(contextData);
     for (let c of this.contexts) {
       if (contexts.has(c)) {
         enabled = true;
-        break
+        break;
       }
     }
     if (!enabled) {
       return false;
     }
 
     if (this.documentUrlMatchPattern &&
         !this.documentUrlMatchPattern.matches(contextData.documentURIObject)) {
@@ -337,32 +339,34 @@ MenuItem.prototype = {
       return false;
     }
 
     return true;
   },
 };
 
 var extCount = 0;
+/* eslint-disable mozilla/balanced-listeners */
 extensions.on("startup", (type, extension) => {
   contextMenuMap.set(extension, new Map());
   if (++extCount == 1) {
     Services.obs.addObserver(contextMenuObserver,
                              "on-build-contextmenu",
                              false);
   }
 });
 
 extensions.on("shutdown", (type, extension) => {
   contextMenuMap.delete(extension);
   if (--extCount == 0) {
     Services.obs.removeObserver(contextMenuObserver,
                                 "on-build-contextmenu");
   }
 });
+/* eslint-enable mozilla/balanced-listeners */
 
 extensions.registerPrivilegedAPI("contextMenus", (extension, context) => {
   return {
     contextMenus: {
       create: function(createProperties, callback) {
         let menuItem = new MenuItem(extension, context, createProperties);
         contextMenuMap.get(extension).set(menuItem.id, menuItem);
         if (callback) {
@@ -387,17 +391,17 @@ extensions.registerPrivilegedAPI("contex
           menuItem.remove();
         }
         if (callback) {
           runSafe(context, callback);
         }
       },
 
       removeAll: function(callback) {
-        for (let [id, menuItem] of contextMenuMap.get(extension)) {
+        for (let [, menuItem] of contextMenuMap.get(extension)) {
           menuItem.remove();
         }
         if (callback) {
           runSafe(context, callback);
         }
       },
 
       // TODO: implement this once event pages are ready.
--- a/browser/components/extensions/ext-pageAction.js
+++ b/browser/components/extensions/ext-pageAction.js
@@ -1,27 +1,25 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   EventManager,
-  DefaultWeakMap,
   runSafe,
 } = ExtensionUtils;
 
 // WeakMap[Extension -> PageAction]
 var pageActionMap = new WeakMap();
 
 
 // Handles URL bar icons, including the |page_action| manifest entry
 // and associated API.
-function PageAction(options, extension)
-{
+function PageAction(options, extension) {
   this.extension = extension;
   this.id = makeWidgetId(extension.id) + "-page-action";
 
   this.tabManager = TabManager.for(extension);
 
   let title = extension.localize(options.default_title || "");
   let popup = extension.localize(options.default_popup || "");
   if (popup) {
@@ -34,17 +32,17 @@ function PageAction(options, extension)
     icon: IconDetails.normalize({ path: options.default_icon }, extension,
                                 null, true),
     popup: popup && extension.baseURI.resolve(popup),
   };
 
   this.tabContext = new TabContext(tab => Object.create(this.defaults),
                                    extension);
 
-  this.tabContext.on("location-change", this.handleLocationChange.bind(this));
+  this.tabContext.on("location-change", this.handleLocationChange.bind(this)); // eslint-disable-line mozilla/balanced-listeners
 
   // WeakMap[ChromeWindow -> <xul:image>]
   this.buttons = new WeakMap();
 
   EventEmitter.decorate(this);
 }
 
 PageAction.prototype = {
@@ -105,17 +103,17 @@ PageAction.prototype = {
   // container in the given window.
   addButton(window) {
     let document = window.document;
 
     let button = document.createElement("image");
     button.id = this.id;
     button.setAttribute("class", "urlbar-icon");
 
-    button.addEventListener("click", event => {
+    button.addEventListener("click", event => { // eslint-disable-line mozilla/balanced-listeners
       if (event.button == 0) {
         this.handleClick(window);
       }
     });
 
     document.getElementById("urlbar-icons").appendChild(button);
 
     return button;
@@ -168,27 +166,29 @@ PageAction.prototype = {
   },
 };
 
 PageAction.for = extension => {
   return pageActionMap.get(extension);
 };
 
 
+/* eslint-disable mozilla/balanced-listeners */
 extensions.on("manifest_page_action", (type, directive, extension, manifest) => {
   let pageAction = new PageAction(manifest.page_action, extension);
   pageActionMap.set(extension, pageAction);
 });
 
 extensions.on("shutdown", (type, extension) => {
   if (pageActionMap.has(extension)) {
     pageActionMap.get(extension).shutdown();
     pageActionMap.delete(extension);
   }
 });
+/* eslint-enable mozilla/balanced-listeners */
 
 
 extensions.registerAPI((extension, context) => {
   return {
     pageAction: {
       onClicked: new EventManager(context, "pageAction.onClicked", fire => {
         let listener = (evt, tab) => {
           fire(TabManager.convert(extension, tab));
@@ -239,11 +239,11 @@ extensions.registerAPI((extension, conte
         PageAction.for(extension).setProperty(tab, "popup", url);
       },
 
       getPopup(details, callback) {
         let tab = TabManager.getTab(details.tabId);
         let popup = PageAction.for(extension).getProperty(tab, "popup");
         runSafe(context, callback, popup);
       },
-    }
+    },
   };
 });
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -1,57 +1,59 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 
 XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
                                   "resource://gre/modules/MatchPattern.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
+/* globals aboutNewTabService */
+
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 
 var {
   EventManager,
   ignoreEvent,
   runSafe,
 } = ExtensionUtils;
 
 // This function is pretty tightly tied to Extension.jsm.
 // Its job is to fill in the |tab| property of the sender.
-function getSender(context, target, sender)
-{
+function getSender(context, target, sender) {
   // The message was sent from a content script to a <browser> element.
   // We can just get the |tab| from |target|.
   if (target instanceof Ci.nsIDOMXULElement) {
     // The message came from a content script.
     let tabbrowser = target.ownerDocument.defaultView.gBrowser;
     if (!tabbrowser) {
       return;
     }
     let tab = tabbrowser.getTabForBrowser(target);
 
     sender.tab = TabManager.convert(context.extension, tab);
-  } else {
+  } else if ("tabId" in sender) {
     // The message came from an ExtensionPage. In that case, it should
     // include a tabId property (which is filled in by the page-open
     // listener below).
-    if ("tabId" in sender) {
-      sender.tab = TabManager.convert(context.extension, TabManager.getTab(sender.tabId));
-      delete sender.tabId;
-    }
+    sender.tab = TabManager.convert(context.extension, TabManager.getTab(sender.tabId));
+    delete sender.tabId;
   }
 }
 
 // WeakMap[ExtensionPage -> {tab, parentWindow}]
 var pageDataMap = new WeakMap();
 
+/* eslint-disable mozilla/balanced-listeners */
 // This listener fires whenever an extension page opens in a tab
 // (either initiated by the extension or the user). Its job is to fill
 // in some tab-specific details and keep data around about the
 // ExtensionPage.
 extensions.on("page-load", (type, page, params, sender, delegate) => {
   if (params.type == "tab" || params.type == "popup") {
     let browser = params.docShell.chromeEventHandler;
 
@@ -90,25 +92,25 @@ extensions.on("fill-browser-data", (type
   let tabId = TabManager.getBrowserId(browser);
   if (tabId == -1) {
     result.cancel = true;
     return;
   }
 
   data.tabId = tabId;
 });
+/* eslint-enable mozilla/balanced-listeners */
 
-global.currentWindow = function(context)
-{
+global.currentWindow = function(context) {
   let pageData = pageDataMap.get(context);
   if (pageData) {
     return pageData.parentWindow;
   }
   return WindowManager.topWindow;
-}
+};
 
 // TODO: activeTab permission
 
 extensions.registerAPI((extension, context) => {
   let self = {
     tabs: {
       onActivated: new WindowEventManager(context, "tabs.onActivated", "TabSelect", (fire, event) => {
         let tab = event.originalTarget;
@@ -206,17 +208,17 @@ extensions.registerAPI((extension, conte
             if (!webProgress.isTopLevel) {
               return;
             }
             let gBrowser = browser.ownerDocument.defaultView.gBrowser;
             let tab = gBrowser.getTabForBrowser(browser);
             let tabId = TabManager.getId(tab);
             let [needed, changeInfo] = sanitize(extension, {
               status: webProgress.isLoadingDocument ? "loading" : "complete",
-              url: locationURI.spec
+              url: locationURI.spec,
             });
             if (needed) {
               fire(tabId, changeInfo, TabManager.convert(extension, tab));
             }
           },
         };
 
         AllWindowEvents.addListener("progress", progressListener);
@@ -384,17 +386,17 @@ extensions.registerAPI((extension, conte
           tab = TabManager.convert(extension, TabManager.getTab(context.tabId));
         }
         runSafe(context, callback, tab);
       },
 
       getAllInWindow: function(...args) {
         let window, callback;
         if (args.length == 1) {
-          callbacks = args[0];
+          callback = args[0];
         } else {
           window = WindowManager.getWindow(args[0]);
           callback = args[1];
         }
 
         if (!window) {
           window = WindowManager.topWindow;
         }
@@ -430,20 +432,18 @@ extensions.registerAPI((extension, conte
             return false;
           }
 
           if ("windowId" in queryInfo) {
             if (queryInfo.windowId == WindowManager.WINDOW_ID_CURRENT) {
               if (currentWindow(context) != window) {
                 return false;
               }
-            } else {
-              if (queryInfo.windowId != tab.windowId) {
-                return false;
-              }
+            } else if (queryInfo.windowId != tab.windowId) {
+              return false;
             }
           }
 
           if ("currentWindow" in queryInfo) {
             let eq = window == currentWindow(context);
             if (queryInfo.currentWindow != eq) {
               return false;
             }
@@ -490,17 +490,17 @@ extensions.registerAPI((extension, conte
           // If we have the "activeTab" permission for this tab, ignore
           // the host whitelist.
           options.matchesHost = ["<all_urls>"];
         } else {
           options.matchesHost = extension.whiteListedHosts.serialize();
         }
 
         if (details.code) {
-          options[kind + 'Code'] = details.code;
+          options[kind + "Code"] = details.code;
         }
         if (details.file) {
           let url = context.uri.resolve(details.file);
           if (extension.isExtensionURL(url)) {
             // We should really set |lastError| here, and go straight to
             // the callback, but we don't have |lastError| yet.
             options[kind].push(url);
           }
@@ -517,27 +517,27 @@ extensions.registerAPI((extension, conte
         mm.sendAsyncMessage("Extension:Execute",
                             {extensionId: extension.id, options});
 
         // TODO: Call the callback with the result (which is what???).
       },
 
       executeScript: function(...args) {
         if (args.length == 1) {
-          self.tabs._execute(undefined, args[0], 'js', undefined);
+          self.tabs._execute(undefined, args[0], "js", undefined);
         } else {
-          self.tabs._execute(args[0], args[1], 'js', args[2]);
+          self.tabs._execute(args[0], args[1], "js", args[2]);
         }
       },
 
-      insertCss: function(tabId, details, callback) {
+      insertCss: function(...args) {
         if (args.length == 1) {
-          self.tabs._execute(undefined, args[0], 'css', undefined);
+          self.tabs._execute(undefined, args[0], "css", undefined);
         } else {
-          self.tabs._execute(args[0], args[1], 'css', args[2]);
+          self.tabs._execute(args[0], args[1], "css", args[2]);
         }
       },
 
       connect: function(tabId, connectInfo) {
         let tab = TabManager.getTab(tabId);
         let mm = tab.linkedBrowser.messageManager;
 
         let name = connectInfo.name || "";
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -26,17 +26,17 @@ global.IconDetails = {
   // with icon size as key and icon URL as value.
   //
   // If a context is specified (function is called from an extension):
   // Throws an error if an invalid icon size was provided or the
   // extension is not allowed to load the specified resources.
   //
   // If no context is specified, instead of throwing an error, this
   // function simply logs a warning message.
-  normalize(details, extension, context=null, localize=false) {
+  normalize(details, extension, context = null, localize = false) {
     let result = {};
 
     try {
       if (details.imageData) {
         let imageData = details.imageData;
 
         if (imageData instanceof Cu.getGlobalForObject(imageData).ImageData) {
           imageData = {"19": imageData};
@@ -107,24 +107,24 @@ global.IconDetails = {
   convertImageDataToPNG(imageData, context) {
     let document = context.contentWindow.document;
     let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     canvas.width = imageData.width;
     canvas.height = imageData.height;
     canvas.getContext("2d").putImageData(imageData, 0, 0);
 
     return canvas.toDataURL("image/png");
-  }
+  },
 };
 
 global.makeWidgetId = id => {
   id = id.toLowerCase();
   // FIXME: This allows for collisions.
   return id.replace(/[^a-z0-9_-]/g, "_");
-}
+};
 
 // Open a panel anchored to the given node, containing a browser opened
 // to the given URL, owned by the given extension. If |popupURL| is not
 // an absolute URL, it is resolved relative to the given extension's
 // base URL.
 global.openPanel = (node, popupURL, extension) => {
   let document = node.ownerDocument;
 
@@ -156,24 +156,26 @@ global.openPanel = (node, popupURL, exte
   const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
   let browser = document.createElementNS(XUL_NS, "browser");
   browser.setAttribute("type", "content");
   browser.setAttribute("disableglobalhistory", "true");
   panel.appendChild(browser);
 
   let titleChangedListener = () => {
     panel.setAttribute("aria-label", browser.contentTitle);
-  }
+  };
 
   let context;
-  panel.addEventListener("popuphidden", () => {
+  let popuphidden = () => {
+    panel.removeEventListener("popuphidden", popuphidden);
     browser.removeEventListener("DOMTitleChanged", titleChangedListener, true);
     context.unload();
     panel.remove();
-  });
+  };
+  panel.addEventListener("popuphidden", popuphidden);
 
   let loadListener = () => {
     panel.removeEventListener("load", loadListener);
 
     context = new ExtensionPage(extension, {
       type: "popup",
       contentWindow: browser.contentWindow,
       uri: popupURI,
@@ -211,31 +213,31 @@ global.openPanel = (node, popupURL, exte
     };
     browser.addEventListener("load", contentLoadListener, true);
 
     browser.addEventListener("DOMTitleChanged", titleChangedListener, true);
   };
   panel.addEventListener("load", loadListener);
 
   return panel;
-}
+};
 
 // Manages tab-specific context data, and dispatching tab select events
 // across all windows.
 global.TabContext = function TabContext(getDefaults, extension) {
   this.extension = extension;
   this.getDefaults = getDefaults;
 
   this.tabData = new WeakMap();
 
   AllWindowEvents.addListener("progress", this);
   AllWindowEvents.addListener("TabSelect", this);
 
   EventEmitter.decorate(this);
-}
+};
 
 TabContext.prototype = {
   get(tab) {
     if (!this.tabData.has(tab)) {
       this.tabData.set(tab, this.getDefaults(tab));
     }
 
     return this.tabData.get(tab);
@@ -306,17 +308,16 @@ ExtensionTabManager.prototype = {
   },
 
   hasTabPermission(tab) {
     return this.extension.hasPermission("tabs") || this.hasActiveTabPermission(tab);
   },
 
   convert(tab) {
     let window = tab.ownerDocument.defaultView;
-    let windowActive = window == WindowManager.topWindow;
 
     let result = {
       id: TabManager.getId(tab),
       index: tab._tPos,
       windowId: WindowManager.getId(window),
       selected: tab.selected,
       highlighted: tab.selected,
       active: tab.selected,
@@ -406,26 +407,28 @@ global.TabManager = {
   },
 };
 
 // WeakMap[Extension -> ExtensionTabManager]
 let tabManagers = new WeakMap();
 
 // Returns the extension-specific tab manager for the given extension, or
 // creates one if it doesn't already exist.
-TabManager.for = function (extension) {
+TabManager.for = function(extension) {
   if (!tabManagers.has(extension)) {
     tabManagers.set(extension, new ExtensionTabManager(extension));
   }
   return tabManagers.get(extension);
 };
 
+/* eslint-disable mozilla/balanced-listeners */
 extensions.on("shutdown", (type, extension) => {
   tabManagers.delete(extension);
 });
+/* eslint-enable mozilla/balanced-listeners */
 
 // Manages mapping between XUL windows and extension window IDs.
 global.WindowManager = {
   _windows: new WeakMap(),
   _nextId: 0,
 
   WINDOW_ID_NONE: -1,
   WINDOW_ID_CURRENT: -2,
@@ -484,17 +487,17 @@ global.WindowManager = {
 // considered open when the "load" event fires on it. A window is
 // closed when a "domwindowclosed" notification fires for it.
 global.WindowListManager = {
   _openListeners: new Set(),
   _closeListeners: new Set(),
 
   // Returns an iterator for all browser windows. Unless |includeIncomplete| is
   // true, only fully-loaded windows are returned.
-  *browserWindows(includeIncomplete = false) {
+  * browserWindows(includeIncomplete = false) {
     // The window type parameter is only available once the window's document
     // element has been created. This means that, when looking for incomplete
     // browser windows, we need to ignore the type entirely for windows which
     // haven't finished loading, since we would otherwise skip browser windows
     // in their early loading stages.
     // This is particularly important given that the "domwindowcreated" event
     // fires for browser windows when they're in that in-between state, and just
     // before we register our own "domwindowcreated" listener.
@@ -649,20 +652,19 @@ global.AllWindowEvents = {
     }
   },
 };
 
 AllWindowEvents.openListener = AllWindowEvents.openListener.bind(AllWindowEvents);
 
 // Subclass of EventManager where we just need to call
 // add/removeEventListener on each XUL window.
-global.WindowEventManager = function(context, name, event, listener)
-{
+global.WindowEventManager = function(context, name, event, listener) {
   EventManager.call(this, context, name, fire => {
     let listener2 = (...args) => listener(fire, ...args);
     AllWindowEvents.addListener(event, listener2);
     return () => {
       AllWindowEvents.removeListener(event, listener2);
-    }
+    };
   });
-}
+};
 
 WindowEventManager.prototype = Object.create(EventManager.prototype);
--- a/browser/components/extensions/ext-windows.js
+++ b/browser/components/extensions/ext-windows.js
@@ -1,12 +1,18 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 
+/* globals aboutNewTabService */
+
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 var {
   EventManager,
   runSafe,
 } = ExtensionUtils;
 
 extensions.registerAPI((extension, context) => {
   return {
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/.eslintrc
@@ -0,0 +1,43 @@
+{
+  "extends": "../../.eslintrc",
+
+  "globals": {
+    // DOM window globals
+    "CustomEvent": false,
+    "document": false,
+    "ImageData": false,
+    "MouseEvent": false,
+    "window": false,
+    "XMLHttpRequest": false,
+
+    "gBrowser": false,
+
+    "sendAsyncMessage": false,
+
+    "NetUtil": true,
+    "XPCOMUtils": true,
+    "Task": true,
+
+    "browser": false,
+
+    // Test harness globals
+    "add_task": false,
+    "BrowserTestUtils": false,
+    "ContentTask": false,
+    "EventUtils": false,
+    "ExtensionTestUtils": false,
+    "info": false,
+    "is": false,
+    "ok": false,
+    "registerCleanupFunction": false,
+    "SimpleTest": false,
+    "SpecialPowers": false,
+    "waitForFocus": false,
+
+    "clickBrowserAction": true,
+    "clickPageAction": true,
+    "CustomizableUI": true,
+    "focusWindow": true,
+    "makeWidgetId": true,
+  }
+}
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_context.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_context.js
@@ -1,26 +1,25 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 add_task(function* testTabSwitchContext() {
-
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "browser_action": {
         "default_icon": "default.png",
         "default_popup": "default.html",
         "default_title": "Default Title",
       },
       "permissions": ["tabs"],
     },
 
-    background: function () {
-      var details = [
+    background: function() {
+      let details = [
         { "icon": browser.runtime.getURL("default.png"),
           "popup": browser.runtime.getURL("default.html"),
           "title": "Default Title",
           "badge": "",
           "badgeBackgroundColor": null },
         { "icon": browser.runtime.getURL("1.png"),
           "popup": browser.runtime.getURL("default.html"),
           "title": "Default Title",
@@ -46,19 +45,20 @@ add_task(function* testTabSwitchContext(
           "disabled": false },
         { "icon": browser.runtime.getURL("default-2.png"),
           "popup": browser.runtime.getURL("default-2.html"),
           "title": "Default Title 2",
           "badge": "d2",
           "badgeBackgroundColor": [0, 0xff, 0] },
       ];
 
-      var tabs = [];
+      let tabs = [];
 
-      var tests = [
+      let expectDefaults;
+      let tests = [
         expect => {
           browser.test.log("Initial state, expect default properties.");
           expectDefaults(details[0]).then(() => {
             expect(details[0]);
           });
         },
         expect => {
           browser.test.log("Change the icon in the current tab. Expect default properties excluding the icon.");
@@ -73,17 +73,17 @@ add_task(function* testTabSwitchContext(
             tabs.push(tab.id);
             expectDefaults(details[0]).then(() => {
               expect(details[0]);
             });
           });
         },
         expect => {
           browser.test.log("Change properties. Expect new properties.");
-          var tabId = tabs[1];
+          let tabId = tabs[1];
           browser.browserAction.setIcon({ tabId, path: "2.png" });
           browser.browserAction.setPopup({ tabId, popup: "2.html" });
           browser.browserAction.setTitle({ tabId, title: "Title 2" });
           browser.browserAction.setBadgeText({ tabId, text: "2" });
           browser.browserAction.setBadgeBackgroundColor({ tabId, color: [0xff, 0, 0] });
           browser.browserAction.disable(tabId);
 
           expectDefaults(details[0]).then(() => {
@@ -186,24 +186,24 @@ add_task(function* testTabSwitchContext(
                                 "expected value from getBadge");
 
           browser.test.assertEq(String(expecting.badgeBackgroundColor),
                                 String(details.badgeBackgroundColor),
                                 "expected value from getBadgeBackgroundColor");
         });
       }
 
-      function expectDefaults(expecting) {
+      expectDefaults = expecting => {
         return checkDetails(expecting);
-      }
+      };
 
       // Runs the next test in the `tests` array, checks the results,
       // and passes control back to the outer test scope.
       function nextTest() {
-        var test = tests.shift();
+        let test = tests.shift();
 
         test(expecting => {
           // Check that the API returns the expected values, and then
           // run the next test.
           new Promise(resolve => {
             return browser.tabs.query({ active: true, currentWindow: true }, resolve);
           }).then(tabs => {
             return checkDetails(expecting, tabs[0].id);
@@ -242,35 +242,35 @@ add_task(function* testTabSwitchContext(
     is(button.getAttribute("tooltiptext"), details.title, "image title is correct");
     is(button.getAttribute("label"), details.title, "image label is correct");
     is(button.getAttribute("aria-label"), details.title, "image aria-label is correct");
     is(button.getAttribute("badge"), details.badge, "badge text is correct");
     is(button.getAttribute("disabled") == "true", Boolean(details.disabled), "disabled state is correct");
 
     if (details.badge && details.badgeBackgroundColor) {
       let badge = button.ownerDocument.getAnonymousElementByAttribute(
-        button, 'class', 'toolbarbutton-badge');
+        button, "class", "toolbarbutton-badge");
 
       let badgeColor = window.getComputedStyle(badge).backgroundColor;
       let color = details.badgeBackgroundColor;
-      let expectedColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`
+      let expectedColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
 
       is(badgeColor, expectedColor, "badge color is correct");
     }
 
 
     // TODO: Popup URL.
   }
 
   let awaitFinish = new Promise(resolve => {
     extension.onMessage("nextTest", (expecting, testsRemaining) => {
       checkDetails(expecting);
 
       if (testsRemaining) {
-        extension.sendMessage("runNextTest")
+        extension.sendMessage("runNextTest");
       } else {
         resolve();
       }
     });
   });
 
   yield extension.startup();
 
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_disabled.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_disabled.js
@@ -1,21 +1,20 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 add_task(function* testDisabled() {
-
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "browser_action": {}
+      "browser_action": {},
     },
 
-    background: function () {
-      var clicked = false;
+    background: function() {
+      let clicked = false;
 
       browser.browserAction.onClicked.addListener(() => {
         browser.test.log("Got click event");
         clicked = true;
       });
 
       browser.test.onMessage.addListener((msg, expectClick) => {
         if (msg == "enable") {
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_pageAction_icon.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_pageAction_icon.js
@@ -3,37 +3,38 @@
 "use strict";
 
 // Test that various combinations of icon details specs, for both paths
 // and ImageData objects, result in the correct image being displayed in
 // all display resolutions.
 add_task(function* testDetailsObjects() {
   function background() {
     function getImageData(color) {
-      var canvas = document.createElement("canvas");
+      let canvas = document.createElement("canvas");
       canvas.width = 2;
       canvas.height = 2;
-      var canvasContext = canvas.getContext("2d");
+      let canvasContext = canvas.getContext("2d");
 
       canvasContext.clearRect(0, 0, canvas.width, canvas.height);
       canvasContext.fillStyle = color;
       canvasContext.fillRect(0, 0, 1, 1);
 
       return {
         url: canvas.toDataURL("image/png"),
         imageData: canvasContext.getImageData(0, 0, canvas.width, canvas.height),
       };
     }
 
-    var imageData = {
+    let imageData = {
       red: getImageData("red"),
       green: getImageData("green"),
     };
 
-    var iconDetails = [
+    /* eslint-disable comma-dangle, indent */
+    let iconDetails = [
       // Only paths.
       { details: { "path": "a.png" },
         resolutions: {
           "1": browser.runtime.getURL("data/a.png"),
           "2": browser.runtime.getURL("data/a.png"), } },
       { details: { "path": "/a.png" },
         resolutions: {
           "1": browser.runtime.getURL("a.png"),
@@ -124,28 +125,28 @@ add_task(function* testDetailsObjects() 
         resolutions: {
           "1": browser.runtime.getURL("data/18.png"),
           "2": browser.runtime.getURL("data/48.png"), } },
     ];
 
     // Allow serializing ImageData objects for logging.
     ImageData.prototype.toJSON = () => "<ImageData>";
 
-    var tabId;
+    let tabId;
 
     browser.test.onMessage.addListener((msg, test) => {
       if (msg != "setIcon") {
         browser.test.fail("expecting 'setIcon' message");
       }
 
-      var details = iconDetails[test.index];
-      var expectedURL = details.resolutions[test.resolution];
+      let details = iconDetails[test.index];
+      let expectedURL = details.resolutions[test.resolution];
 
-      var detailString = JSON.stringify(details);
-      browser.test.log(`Setting browerAction/pageAction to ${detailString} expecting URL ${expectedURL}`)
+      let detailString = JSON.stringify(details);
+      browser.test.log(`Setting browerAction/pageAction to ${detailString} expecting URL ${expectedURL}`);
 
       browser.browserAction.setIcon(Object.assign({tabId}, details.details));
       browser.pageAction.setIcon(Object.assign({tabId}, details.details));
 
       browser.test.sendMessage("imageURL", expectedURL);
     });
 
     // Generate a list of tests and resolutions to send back to the test
@@ -153,19 +154,19 @@ add_task(function* testDetailsObjects() 
     //
     // This process is a bit convoluted, because the outer test context needs
     // to handle checking the button nodes and changing the screen resolution,
     // but it can't pass us icon definitions with ImageData objects. This
     // shouldn't be a problem, since structured clones should handle ImageData
     // objects without issue. Unfortunately, |cloneInto| implements a slightly
     // different algorithm than we use in web APIs, and does not handle them
     // correctly.
-    var tests = [];
-    for (var [idx, icon] of iconDetails.entries()) {
-      for (var res of Object.keys(icon.resolutions)) {
+    let tests = [];
+    for (let [idx, icon] of iconDetails.entries()) {
+      for (let res of Object.keys(icon.resolutions)) {
         tests.push({ index: idx, resolution: Number(res) });
       }
     }
 
     // Sort by resolution, so we don't needlessly switch back and forth
     // between each test.
     tests.sort(test => test.resolution);
 
@@ -216,45 +217,44 @@ add_task(function* testDetailsObjects() 
     let pageActionImage = document.getElementById(pageActionId);
     is(pageActionImage.src, imageURL, "page action has the correct image");
   }
 
   yield extension.unload();
 });
 
 // Test that an error is thrown when providing invalid icon sizes
-add_task(function *testInvalidIconSizes() {
-
+add_task(function* testInvalidIconSizes() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "browser_action": {},
       "page_action": {},
     },
 
-    background: function () {
+    background: function() {
       browser.tabs.query({ active: true, currentWindow: true }, tabs => {
-        var tabId = tabs[0].id;
+        let tabId = tabs[0].id;
 
-        for (var api of ["pageAction", "browserAction"]) {
+        for (let api of ["pageAction", "browserAction"]) {
           // helper function to run setIcon and check if it fails
           let assertSetIconThrows = function(detail, error, message) {
             try {
               detail.tabId = tabId;
               browser[api].setIcon(detail);
 
               browser.test.fail("Expected an error on invalid icon size.");
               browser.test.notifyFail("setIcon with invalid icon size");
               return;
             } catch (e) {
               browser.test.succeed("setIcon with invalid icon size");
             }
-          }
+          };
 
           // test invalid icon size inputs
-          for (var type of ["path", "imageData"]) {
+          for (let type of ["path", "imageData"]) {
             assertSetIconThrows({ [type]: { "abcdef": "test.png" } });
             assertSetIconThrows({ [type]: { "48px": "test.png" } });
             assertSetIconThrows({ [type]: { "20.5": "test.png" } });
             assertSetIconThrows({ [type]: { "5.0": "test.png" } });
             assertSetIconThrows({ [type]: { "-300": "test.png" } });
             assertSetIconThrows({ [type]: {
               "abc": "test.png",
               "5": "test.png"
@@ -273,17 +273,17 @@ add_task(function *testInvalidIconSizes(
   yield Promise.all([extension.startup(), extension.awaitFinish("setIcon with invalid icon size")]);
 
   yield extension.unload();
 });
 
 
 // Test that default icon details in the manifest.json file are handled
 // correctly.
-add_task(function *testDefaultDetails() {
+add_task(function* testDefaultDetails() {
   // TODO: Test localized variants.
   let icons = [
     "foo/bar.png",
     "/foo/bar.png",
     { "19": "foo/bar.png" },
     { "38": "foo/bar.png" },
     { "19": "foo/bar.png", "38": "baz/quux.png" },
   ];
@@ -292,19 +292,19 @@ add_task(function *testDefaultDetails() 
 
   for (let icon of icons) {
     let extension = ExtensionTestUtils.loadExtension({
       manifest: {
         "browser_action": { "default_icon": icon },
         "page_action": { "default_icon": icon },
       },
 
-      background: function () {
+      background: function() {
         browser.tabs.query({ active: true, currentWindow: true }, tabs => {
-          var tabId = tabs[0].id;
+          let tabId = tabs[0].id;
 
           browser.pageAction.show(tabId);
           browser.test.sendMessage("ready");
         });
       }
     });
 
     yield Promise.all([extension.startup(), extension.awaitMessage("ready")]);
@@ -327,34 +327,33 @@ add_task(function *testDefaultDetails() 
     let node = document.getElementById(pageActionId);
     is(node, undefined, "pageAction image removed from document");
   }
 });
 
 
 // Check that attempts to load a privileged URL as an icon image fail.
 add_task(function* testSecureURLsDenied() {
-
   // Test URLs passed to setIcon.
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "browser_action": {},
       "page_action": {},
     },
 
-    background: function () {
+    background: function() {
       browser.tabs.query({ active: true, currentWindow: true }, tabs => {
-        var tabId = tabs[0].id;
+        let tabId = tabs[0].id;
 
-        var urls = ["chrome://browser/content/browser.xul",
+        let urls = ["chrome://browser/content/browser.xul",
                     "javascript:true"];
 
-        for (var url of urls) {
-          for (var api of ["pageAction", "browserAction"]) {
+        for (let url of urls) {
+          for (let api of ["pageAction", "browserAction"]) {
             try {
               browser[api].setIcon({tabId, path: url});
 
               browser.test.fail(`Load of '${url}' succeeded. Expected failure.`);
               browser.test.notifyFail("setIcon security tests");
               return;
             } catch (e) {
               // We can't actually inspect the error here, since the
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
@@ -15,38 +15,39 @@ function promisePopupShown(popup) {
     }
   });
 }
 
 add_task(function* testPageActionPopup() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "background": {
-        "page": "data/background.html"
+        "page": "data/background.html",
       },
       "browser_action": {
-        "default_popup": "popup-a.html"
-      }
+        "default_popup": "popup-a.html",
+      },
     },
 
     files: {
       "popup-a.html": `<script src="popup-a.js"></script>`,
       "popup-a.js": function() {
         browser.runtime.sendMessage("from-popup-a");
       },
 
       "data/popup-b.html": `<script src="popup-b.js"></script>`,
       "data/popup-b.js": function() {
         browser.runtime.sendMessage("from-popup-b");
       },
 
       "data/background.html": `<script src="background.js"></script>`,
 
       "data/background.js": function() {
-        var tests = [
+        let sendClick;
+        let tests = [
           () => {
             sendClick({ expectEvent: false, expectPopup: "a" });
           },
           () => {
             sendClick({ expectEvent: false, expectPopup: "a" });
           },
           () => {
             browser.browserAction.setPopup({ popup: "popup-b.html" });
@@ -63,21 +64,21 @@ add_task(function* testPageActionPopup()
             sendClick({ expectEvent: true, expectPopup: null });
           },
           () => {
             browser.browserAction.setPopup({ popup: "/popup-a.html" });
             sendClick({ expectEvent: false, expectPopup: "a" });
           },
         ];
 
-        var expect = {};
-        function sendClick({ expectEvent, expectPopup }) {
+        let expect = {};
+        sendClick = ({ expectEvent, expectPopup }) => {
           expect = { event: expectEvent, popup: expectPopup };
           browser.test.sendMessage("send-click");
-        }
+        };
 
         browser.runtime.onMessage.addListener(msg => {
           if (expect.popup) {
             browser.test.assertEq(msg, `from-popup-${expect.popup}`,
                                   "expected popup opened");
           } else {
             browser.test.fail("unexpected popup");
           }
@@ -98,17 +99,17 @@ add_task(function* testPageActionPopup()
         });
 
         browser.test.onMessage.addListener((msg) => {
           if (msg != "next-test") {
             browser.test.fail("Expecting 'next-test' message");
           }
 
           if (tests.length) {
-            var test = tests.shift();
+            let test = tests.shift();
             test();
           } else {
             browser.test.notifyPass("browseraction-tests-done");
           }
         });
 
         browser.test.sendMessage("next-test");
       },
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_simple.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_simple.js
@@ -1,27 +1,31 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "browser_action": {
-        "default_popup": "popup.html"
-      }
+        "default_popup": "popup.html",
+      },
     },
 
     files: {
       "popup.html": `
       <!DOCTYPE html>
       <html><body>
       <script src="popup.js"></script>
       </body></html>
       `,
 
       "popup.js": function() {
         browser.runtime.sendMessage("from-popup");
-      }
+      },
     },
 
     background: function() {
       browser.runtime.onMessage.addListener(msg => {
         browser.test.assertEq(msg, "from-popup", "correct message received");
         browser.test.sendMessage("popup");
       });
     },
@@ -31,17 +35,17 @@ add_task(function* () {
 
   let widgetId = makeWidgetId(extension.id) + "-browser-action";
   let node = CustomizableUI.getWidget(widgetId).forWindow(window).node;
 
   // Do this a few times to make sure the pop-up is reloaded each time.
   for (let i = 0; i < 3; i++) {
     let evt = new CustomEvent("command", {
       bubbles: true,
-      cancelable: true
+      cancelable: true,
     });
     node.dispatchEvent(evt);
 
     yield extension.awaitMessage("popup");
 
     let panel = node.querySelector("panel");
     if (panel) {
       panel.hidePopup();
--- a/browser/components/extensions/test/browser/browser_ext_contentscript_connect.js
+++ b/browser/components/extensions/test/browser/browser_ext_contentscript_connect.js
@@ -1,58 +1,62 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["http://mochi.test/"]
+      "permissions": ["http://mochi.test/"],
     },
 
     background: function() {
-      var ports_received = 0;
-      var port_messages_received = 0;
+      let ports_received = 0;
+      let port_messages_received = 0;
 
       browser.runtime.onConnect.addListener((port) => {
         browser.test.assertTrue(!!port, "port1 received");
 
         ports_received++;
         browser.test.assertEq(1, ports_received, "1 port received");
 
         port.onMessage.addListener((msg, sender) => {
           browser.test.assertEq("port message", msg, "listener1 port message received");
 
-          port_messages_received++
+          port_messages_received++;
           browser.test.assertEq(1, port_messages_received, "1 port message received");
-        })
+        });
       });
       browser.runtime.onConnect.addListener((port) => {
         browser.test.assertTrue(!!port, "port2 received");
 
         ports_received++;
         browser.test.assertEq(2, ports_received, "2 ports received");
 
         port.onMessage.addListener((msg, sender) => {
           browser.test.assertEq("port message", msg, "listener2 port message received");
 
-          port_messages_received++
+          port_messages_received++;
           browser.test.assertEq(2, port_messages_received, "2 port messages received");
 
           browser.test.notifyPass("contentscript_connect.pass");
         });
       });
 
       browser.tabs.executeScript({ file: "script.js" });
     },
 
     files: {
       "script.js": function() {
-        var port = browser.runtime.connect();
+        let port = browser.runtime.connect();
         port.postMessage("port message");
-      }
-    }
+      },
+    },
   });
 
   yield extension.startup();
   yield extension.awaitFinish("contentscript_connect.pass");
   yield extension.unload();
 
   yield BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/extensions/test/browser/browser_ext_contextMenus.js
+++ b/browser/components/extensions/test/browser/browser_ext_contextMenus.js
@@ -1,48 +1,55 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+/* globals content */
+/* eslint-disable mozilla/no-cpows-in-tests */
+
 add_task(function* () {
   let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
     "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
 
   gBrowser.selectedTab = tab1;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["contextMenus"]
+      "permissions": ["contextMenus"],
     },
 
     background: function() {
       // A generic onclick callback function.
       function genericOnClick(info) {
         browser.test.sendMessage("menuItemClick", JSON.stringify(info));
       }
 
       browser.contextMenus.create({ "contexts": ["all"], "type": "separator" });
 
-      var contexts = ["page", "selection", "image"];
-      for (var i = 0; i < contexts.length; i++) {
-        var context = contexts[i];
-        var title = context;
-        var id = browser.contextMenus.create({ "title": title, "contexts": [context], "id": "ext-" + context,
-                                               "onclick": genericOnClick });
+      let contexts = ["page", "selection", "image"];
+      for (let i = 0; i < contexts.length; i++) {
+        let context = contexts[i];
+        let title = context;
+        browser.contextMenus.create({ "title": title, "contexts": [context], "id": "ext-" + context,
+                                      "onclick": genericOnClick });
         if (context == "selection") {
           browser.contextMenus.update("ext-selection", { "title": "selection-edited" });
         }
       }
 
-      var parent = browser.contextMenus.create({ "title": "parent" });
-      var child1 = browser.contextMenus.create(
+      let parent = browser.contextMenus.create({ "title": "parent" });
+      browser.contextMenus.create(
         { "title": "child1", "parentId": parent, "onclick": genericOnClick });
-      var child2 = browser.contextMenus.create(
+      browser.contextMenus.create(
         { "title": "child2", "parentId": parent, "onclick": genericOnClick });
 
-      var parentToDel = browser.contextMenus.create({ "title": "parentToDel" });
-      var child1ToDel = browser.contextMenus.create(
+      let parentToDel = browser.contextMenus.create({ "title": "parentToDel" });
+      browser.contextMenus.create(
         { "title": "child1", "parentId": parentToDel, "onclick": genericOnClick });
-      var child2ToDel = browser.contextMenus.create(
+      browser.contextMenus.create(
         { "title": "child2", "parentId": parentToDel, "onclick": genericOnClick });
       browser.contextMenus.remove(parentToDel);
 
       browser.test.notifyPass();
     },
   });
 
   let expectedClickInfo;
@@ -79,17 +86,17 @@ add_task(function* () {
   is(items.length, 0, "contextMenu item for selection was not found (context=image)");
 
   items = top.getElementsByAttribute("label", "parentToDel");
   is(items.length, 0, "contextMenu item for removed parent was not found (context=image)");
 
   items = top.getElementsByAttribute("label", "parent");
   is(items.length, 1, "contextMenu item for parent was found (context=image)");
 
-  is(items.item(0).childNodes[0].childNodes.length, 2, "child items for parent were found (context=image)")
+  is(items.item(0).childNodes[0].childNodes.length, 2, "child items for parent were found (context=image)");
 
   // Click on ext-image item and check the results
   let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
   expectedClickInfo = {
     menuItemId: "ext-image",
     mediaType: "image",
     srcUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/ctxmenu-image.png",
     pageUrl: "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html",
--- a/browser/components/extensions/test/browser/browser_ext_currentWindow.js
+++ b/browser/components/extensions/test/browser/browser_ext_currentWindow.js
@@ -1,42 +1,45 @@
-function genericChecker()
-{
-  var kind = "background";
-  var path = window.location.pathname;
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+function genericChecker() {
+  let kind = "background";
+  let path = window.location.pathname;
   if (path.indexOf("popup") != -1) {
     kind = "popup";
   } else if (path.indexOf("page") != -1) {
     kind = "page";
   }
 
   browser.test.onMessage.addListener((msg, ...args) => {
     if (msg == kind + "-check-current1") {
       browser.tabs.query({
-        currentWindow: true
+        currentWindow: true,
       }, function(tabs) {
         browser.test.sendMessage("result", tabs[0].windowId);
       });
     } else if (msg == kind + "-check-current2") {
       browser.tabs.query({
-        windowId: browser.windows.WINDOW_ID_CURRENT
+        windowId: browser.windows.WINDOW_ID_CURRENT,
       }, function(tabs) {
         browser.test.sendMessage("result", tabs[0].windowId);
       });
     } else if (msg == kind + "-check-current3") {
       browser.windows.getCurrent(function(window) {
         browser.test.sendMessage("result", window.id);
       });
     } else if (msg == kind + "-open-page") {
-      browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("page.html")});
+      browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("page.html")});
     } else if (msg == kind + "-close-page") {
       browser.tabs.query({
         windowId: args[0],
       }, tabs => {
-        var tab = tabs.find(tab => tab.url.indexOf("page.html") != -1);
+        let tab = tabs.find(tab => tab.url.indexOf("page.html") != -1);
         browser.tabs.remove(tab.id, () => {
           browser.test.sendMessage("closed");
         });
       });
     }
   });
   browser.test.sendMessage(kind + "-ready");
 }
@@ -53,17 +56,17 @@ add_task(function* () {
   yield BrowserTestUtils.loadURI(win2.gBrowser.selectedBrowser, "about:config");
   yield BrowserTestUtils.browserLoaded(win2.gBrowser.selectedBrowser);
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
 
       "browser_action": {
-        "default_popup": "popup.html"
+        "default_popup": "popup.html",
       },
     },
 
     files: {
       "page.html": `
       <!DOCTYPE html>
       <html><body>
       <script src="page.js"></script>
@@ -82,17 +85,17 @@ add_task(function* () {
       "popup.js": genericChecker,
     },
 
     background: genericChecker,
   });
 
   yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
 
-  let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
+  let {WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
 
   let winId1 = WindowManager.getId(win1);
   let winId2 = WindowManager.getId(win2);
 
   function* checkWindow(kind, winId, name) {
     extension.sendMessage(kind + "-check-current1");
     is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 1) [${kind}]`);
     extension.sendMessage(kind + "-check-current2");
@@ -107,17 +110,17 @@ add_task(function* () {
   yield checkWindow("background", winId2, "win2");
 
   function* triggerPopup(win, callback) {
     let widgetId = makeWidgetId(extension.id) + "-browser-action";
     let node = CustomizableUI.getWidget(widgetId).forWindow(win).node;
 
     let evt = new CustomEvent("command", {
       bubbles: true,
-      cancelable: true
+      cancelable: true,
     });
     node.dispatchEvent(evt);
 
     yield extension.awaitMessage("popup-ready");
 
     yield callback();
 
     let panel = node.querySelector("panel");
--- a/browser/components/extensions/test/browser/browser_ext_getViews.js
+++ b/browser/components/extensions/test/browser/browser_ext_getViews.js
@@ -1,44 +1,47 @@
-function genericChecker()
-{
-  var kind = "background";
-  var path = window.location.pathname;
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+function genericChecker() {
+  let kind = "background";
+  let path = window.location.pathname;
   if (path.indexOf("popup") != -1) {
     kind = "popup";
   } else if (path.indexOf("tab") != -1) {
     kind = "tab";
   }
   window.kind = kind;
 
   browser.test.onMessage.addListener((msg, ...args) => {
     if (msg == kind + "-check-views") {
-      var views = browser.extension.getViews();
-      var counts = {
+      let views = browser.extension.getViews();
+      let counts = {
         "background": 0,
         "tab": 0,
-        "popup": 0
+        "popup": 0,
       };
-      for (var i = 0; i < views.length; i++) {
-        var view = views[i];
+      for (let i = 0; i < views.length; i++) {
+        let view = views[i];
         browser.test.assertTrue(view.kind in counts, "view type is valid");
         counts[view.kind]++;
         if (view.kind == "background") {
           browser.test.assertTrue(view === browser.extension.getBackgroundPage(),
                                   "background page is correct");
         }
       }
       browser.test.sendMessage("counts", counts);
     } else if (msg == kind + "-open-tab") {
-      browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("tab.html")});
+      browser.tabs.create({windowId: args[0], url: browser.runtime.getURL("tab.html")});
     } else if (msg == kind + "-close-tab") {
       browser.tabs.query({
         windowId: args[0],
       }, tabs => {
-        var tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
+        let tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
         browser.tabs.remove(tab.id, () => {
           browser.test.sendMessage("closed");
         });
       });
     }
   });
   browser.test.sendMessage(kind + "-ready");
 }
@@ -47,17 +50,17 @@ add_task(function* () {
   let win1 = yield BrowserTestUtils.openNewBrowserWindow();
   let win2 = yield BrowserTestUtils.openNewBrowserWindow();
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
 
       "browser_action": {
-        "default_popup": "popup.html"
+        "default_popup": "popup.html",
       },
     },
 
     files: {
       "tab.html": `
       <!DOCTYPE html>
       <html><body>
       <script src="tab.js"></script>
@@ -78,17 +81,17 @@ add_task(function* () {
 
     background: genericChecker,
   });
 
   yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
 
   info("started");
 
-  let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
+  let {WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
 
   let winId1 = WindowManager.getId(win1);
   let winId2 = WindowManager.getId(win2);
 
   function* openTab(winId) {
     extension.sendMessage("background-open-tab", winId);
     yield extension.awaitMessage("tab-ready");
   }
@@ -113,17 +116,17 @@ add_task(function* () {
   yield checkViews("background", 2, 0);
 
   function* triggerPopup(win, callback) {
     let widgetId = makeWidgetId(extension.id) + "-browser-action";
     let node = CustomizableUI.getWidget(widgetId).forWindow(win).node;
 
     let evt = new CustomEvent("command", {
       bubbles: true,
-      cancelable: true
+      cancelable: true,
     });
     node.dispatchEvent(evt);
 
     yield extension.awaitMessage("popup-ready");
 
     yield callback();
 
     let panel = node.querySelector("panel");
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_context.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_context.js
@@ -1,40 +1,39 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 add_task(function* testTabSwitchContext() {
-
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "page_action": {
         "default_icon": "default.png",
         "default_popup": "default.html",
         "default_title": "Default Title",
       },
       "permissions": ["tabs"],
     },
 
-    background: function () {
-      var details = [
+    background: function() {
+      let details = [
         { "icon": browser.runtime.getURL("default.png"),
           "popup": browser.runtime.getURL("default.html"),
           "title": "Default Title" },
         { "icon": browser.runtime.getURL("1.png"),
           "popup": browser.runtime.getURL("default.html"),
           "title": "Default Title" },
         { "icon": browser.runtime.getURL("2.png"),
           "popup": browser.runtime.getURL("2.html"),
           "title": "Title 2" },
       ];
 
-      var tabs;
-      var tests;
-      var allTests = [
+      let tabs;
+      let tests;
+      let allTests = [
         expect => {
           browser.test.log("Initial state. No icon visible.");
           expect(null);
         },
         expect => {
           browser.test.log("Show the icon on the first tab, expect default properties.");
           browser.pageAction.show(tabs[0]);
           expect(details[0]);
@@ -48,17 +47,17 @@ add_task(function* testTabSwitchContext(
           browser.test.log("Create a new tab. No icon visible.");
           browser.tabs.create({ active: true, url: "about:blank?0" }, tab => {
             tabs.push(tab.id);
             expect(null);
           });
         },
         expect => {
           browser.test.log("Change properties. Expect new properties.");
-          var tabId = tabs[1];
+          let tabId = tabs[1];
           browser.pageAction.show(tabId);
           browser.pageAction.setIcon({ tabId, path: "2.png" });
           browser.pageAction.setPopup({ tabId, popup: "2.html" });
           browser.pageAction.setTitle({ tabId, title: "Title 2" });
 
           expect(details[2]);
         },
         expect => {
@@ -107,31 +106,31 @@ add_task(function* testTabSwitchContext(
       ];
 
       // Gets the current details of the page action, and returns a
       // promise that resolves to an object containing them.
       function getDetails() {
         return new Promise(resolve => {
           return browser.tabs.query({ active: true, currentWindow: true }, resolve);
         }).then(tabs => {
-          var tabId = tabs[0].id;
+          let tabId = tabs[0].id;
           return Promise.all([
             new Promise(resolve => browser.pageAction.getTitle({tabId}, resolve)),
-            new Promise(resolve => browser.pageAction.getPopup({tabId}, resolve))])
+            new Promise(resolve => browser.pageAction.getPopup({tabId}, resolve))]);
         }).then(details => {
           return Promise.resolve({ title: details[0],
                                    popup: details[1] });
         });
       }
 
 
       // Runs the next test in the `tests` array, checks the results,
       // and passes control back to the outer test scope.
       function nextTest() {
-        var test = tests.shift();
+        let test = tests.shift();
 
         test(expecting => {
           function finish() {
             // Check that the actual icon has the expected values, then
             // run the next test.
             browser.test.sendMessage("nextTest", expecting, tests.length);
           }
 
@@ -148,37 +147,37 @@ add_task(function* testTabSwitchContext(
               finish();
             });
           } else {
             finish();
           }
         });
       }
 
-      browser.test.onMessage.addListener((msg) => {
-        if (msg == "runTests") {
-          runTests();
-        } else if (msg == "runNextTest") {
-          nextTest();
-        } else {
-          browser.test.fail(`Unexpected message: ${msg}`);
-        }
-      });
-
       function runTests() {
         tabs = [];
         tests = allTests.slice();
 
         browser.tabs.query({ active: true, currentWindow: true }, resultTabs => {
           tabs[0] = resultTabs[0].id;
 
           nextTest();
         });
       }
 
+      browser.test.onMessage.addListener((msg) => {
+        if (msg == "runTests") {
+          runTests();
+        } else if (msg == "runNextTest") {
+          nextTest();
+        } else {
+          browser.test.fail(`Unexpected message: ${msg}`);
+        }
+      });
+
       runTests();
     },
   });
 
   let pageActionId = makeWidgetId(extension.id) + "-page-action";
   let currentWindow = window;
   let windows = [];
 
@@ -198,26 +197,26 @@ add_task(function* testTabSwitchContext(
 
   let testNewWindows = 1;
 
   let awaitFinish = new Promise(resolve => {
     extension.onMessage("nextTest", (expecting, testsRemaining) => {
       checkDetails(expecting);
 
       if (testsRemaining) {
-        extension.sendMessage("runNextTest")
+        extension.sendMessage("runNextTest");
       } else if (testNewWindows) {
         testNewWindows--;
 
         BrowserTestUtils.openNewBrowserWindow().then(window => {
           windows.push(window);
           currentWindow = window;
           return focusWindow(window);
         }).then(() => {
-          extension.sendMessage("runTests")
+          extension.sendMessage("runTests");
         });
       } else {
         resolve();
       }
     });
   });
 
   yield extension.startup();
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
@@ -15,40 +15,41 @@ function promisePopupShown(popup) {
     }
   });
 }
 
 add_task(function* testPageActionPopup() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "background": {
-        "page": "data/background.html"
+        "page": "data/background.html",
       },
       "page_action": {
-        "default_popup": "popup-a.html"
-      }
+        "default_popup": "popup-a.html",
+      },
     },
 
     files: {
       "popup-a.html": `<script src="popup-a.js"></script>`,
       "popup-a.js": function() {
         browser.runtime.sendMessage("from-popup-a");
       },
 
       "data/popup-b.html": `<script src="popup-b.js"></script>`,
       "data/popup-b.js": function() {
         browser.runtime.sendMessage("from-popup-b");
       },
 
       "data/background.html": `<script src="background.js"></script>`,
 
       "data/background.js": function() {
-        var tabId;
+        let tabId;
 
-        var tests = [
+        let sendClick;
+        let tests = [
           () => {
             sendClick({ expectEvent: false, expectPopup: "a" });
           },
           () => {
             sendClick({ expectEvent: false, expectPopup: "a" });
           },
           () => {
             browser.pageAction.setPopup({ tabId, popup: "popup-b.html" });
@@ -65,21 +66,21 @@ add_task(function* testPageActionPopup()
             sendClick({ expectEvent: true, expectPopup: null });
           },
           () => {
             browser.pageAction.setPopup({ tabId, popup: "/popup-a.html" });
             sendClick({ expectEvent: false, expectPopup: "a" });
           },
         ];
 
-        var expect = {};
-        function sendClick({ expectEvent, expectPopup }) {
+        let expect = {};
+        sendClick = ({ expectEvent, expectPopup }) => {
           expect = { event: expectEvent, popup: expectPopup };
           browser.test.sendMessage("send-click");
-        }
+        };
 
         browser.runtime.onMessage.addListener(msg => {
           if (expect.popup) {
             browser.test.assertEq(msg, `from-popup-${expect.popup}`,
                                   "expected popup opened");
           } else {
             browser.test.fail("unexpected popup");
           }
@@ -100,17 +101,17 @@ add_task(function* testPageActionPopup()
         });
 
         browser.test.onMessage.addListener((msg) => {
           if (msg != "next-test") {
             browser.test.fail("Expecting 'next-test' message");
           }
 
           if (tests.length) {
-            var test = tests.shift();
+            let test = tests.shift();
             test();
           } else {
             browser.test.notifyPass("pageaction-tests-done");
           }
         });
 
         browser.tabs.query({ active: true, currentWindow: true }, tabs => {
           tabId = tabs[0].id;
@@ -154,20 +155,16 @@ add_task(function* testPageActionPopup()
   let panel = document.getElementById(panelId);
   is(panel, undefined, "pageAction panel removed from document");
 });
 
 
 add_task(function* testPageActionSecurity() {
   const URL = "chrome://browser/content/browser.xul";
 
-  let matchURLForbidden = url => ({
-    message: new RegExp(`Loading extension.*Access to.*'${URL}' denied`),
-  });
-
   let messages = [/Access to restricted URI denied/,
                   /Access to restricted URI denied/];
 
   let waitForConsole = new Promise(resolve => {
     // Not necessary in browser-chrome tests, but monitorConsole gripes
     // if we don't call it.
     SimpleTest.waitForExplicitFinish();
 
@@ -175,19 +172,19 @@ add_task(function* testPageActionSecurit
   });
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "browser_action": { "default_popup": URL },
       "page_action": { "default_popup": URL },
     },
 
-    background: function () {
+    background: function() {
       browser.tabs.query({ active: true, currentWindow: true }, tabs => {
-        var tabId = tabs[0].id;
+        let tabId = tabs[0].id;
 
         browser.pageAction.show(tabId);
         browser.test.sendMessage("ready");
       });
     },
   });
 
   yield extension.startup();
--- a/browser/components/extensions/test/browser/browser_ext_popup_api_injection.js
+++ b/browser/components/extensions/test/browser/browser_ext_popup_api_injection.js
@@ -21,17 +21,17 @@ add_task(function* testPageActionPopup()
       </script></head></html>`,
 
       "popup-b.html": String.raw`<html><head><meta charset="utf-8"><script type="application/javascript">
         browser.test.sendMessage("from-popup-b");
       </script></head></html>`,
     },
 
     background: function() {
-      let tabId
+      let tabId;
       browser.tabs.query({ active: true, currentWindow: true }, tabs => {
         tabId = tabs[0].id;
         browser.pageAction.show(tabId);
         browser.test.sendMessage("ready");
       });
 
       browser.test.onMessage.addListener(() => {
         browser.browserAction.setPopup({ popup: "/popup-a.html" });
@@ -48,17 +48,17 @@ add_task(function* testPageActionPopup()
   function openPopup(buttonId) {
     let button = document.getElementById(buttonId);
     if (buttonId == pageActionId) {
       // TODO: I don't know why a proper synthesized event doesn't work here.
       button.dispatchEvent(new MouseEvent("click", {}));
     } else {
       EventUtils.synthesizeMouseAtCenter(button, {}, window);
     }
-  };
+  }
 
   let promiseConsoleMessage = pattern => new Promise(resolve => {
     Services.console.registerListener(function listener(msg) {
       if (pattern.test(msg.message)) {
         resolve(msg.message);
         Services.console.unregisterListener(listener);
       }
     });
--- a/browser/components/extensions/test/browser/browser_ext_simple.js
+++ b/browser/components/extensions/test/browser/browser_ext_simple.js
@@ -1,16 +1,20 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* test_simple() {
   let extensionData = {
     manifest: {
       "name": "Simple extension test",
       "version": "1.0",
       "manifest_version": 2,
-      "description": ""
-    }
+      "description": "",
+    },
   };
 
   let extension = ExtensionTestUtils.loadExtension(extensionData);
   info("load complete");
   yield extension.startup();
   info("startup complete");
   yield extension.unload();
   info("extension unloaded successfully");
@@ -31,18 +35,18 @@ add_task(function* test_background() {
   }
 
   let extensionData = {
     background: "(" + backgroundScript.toString() + ")()",
     manifest: {
       "name": "Simple extension test",
       "version": "1.0",
       "manifest_version": 2,
-      "description": ""
-    }
+      "description": "",
+    },
   };
 
   let extension = ExtensionTestUtils.loadExtension(extensionData);
   info("load complete");
   let [, x] = yield Promise.all([extension.startup(), extension.awaitMessage("running")]);
   is(x, 1, "got correct value from extension");
   info("startup complete");
   extension.sendMessage(10, 20);
--- a/browser/components/extensions/test/browser/browser_ext_tab_runtimeConnect.js
+++ b/browser/components/extensions/test/browser/browser_ext_tab_runtimeConnect.js
@@ -1,24 +1,28 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
-      var messages_received = [];
+      let messages_received = [];
 
-      var tabId;
+      let tabId;
 
       browser.runtime.onConnect.addListener((port) => {
         browser.test.assertTrue(!!port, "tab to background port received");
-        browser.test.assertEq("tab-connection-name", port.name, "port name should be defined and equal to connectInfo.name")
+        browser.test.assertEq("tab-connection-name", port.name, "port name should be defined and equal to connectInfo.name");
         browser.test.assertTrue(!!port.sender.tab, "port.sender.tab should be defined");
         browser.test.assertEq(tabId, port.sender.tab.id, "port.sender.tab.id should be equal to the expected tabId");
 
         port.onMessage.addListener((msg) => {
           messages_received.push(msg);
 
           if (messages_received.length == 1) {
             browser.test.assertEq("tab to background port message", msg, "'tab to background' port message received");
@@ -26,27 +30,26 @@ add_task(function* () {
           }
 
           if (messages_received.length == 2) {
             browser.test.assertTrue(!!msg.tabReceived, "'background to tab' reply port message received");
             browser.test.assertEq("background to tab port message", msg.tabReceived, "reply port content contains the message received");
 
             browser.test.notifyPass("tabRuntimeConnect.pass");
           }
-        })
+        });
       });
 
-      browser.tabs.create({
-        url: "tab.html"
-      }, (tab) => { tabId = tab.id });
+      browser.tabs.create({ url: "tab.html" },
+                          (tab) => { tabId = tab.id; });
     },
 
     files: {
       "tab.js": function() {
-        var port = browser.runtime.connect({ name: "tab-connection-name"});
+        let port = browser.runtime.connect({ name: "tab-connection-name"});
         port.postMessage("tab to background port message");
         port.onMessage.addListener((msg) => {
           port.postMessage({ tabReceived: msg });
         });
       },
       "tab.html": `
         <!DOCTYPE html>
         <html>
@@ -54,18 +57,18 @@ add_task(function* () {
             <title>test tab extension page</title>
             <meta charset="utf-8">
             <script src="tab.js" async></script>
           </head>
           <body>
             <h1>test tab extension page</h1>
           </body>
         </html>
-      `
-    }
+      `,
+    },
   });
 
   yield extension.startup();
   yield extension.awaitFinish("tabRuntimeConnect.pass");
   yield extension.unload();
 
   yield BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/extensions/test/browser/browser_ext_tabs_executeScript_bad.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_executeScript_bad.js
@@ -1,57 +1,59 @@
 "use strict";
 
 // This is a pretty terrible hack, but it's the best we can do until we
 // support |executeScript| callbacks and |lastError|.
 function* testHasNoPermission(params) {
   let contentSetup = params.contentSetup || (() => Promise.resolve());
 
+  function background(contentSetup) {
+    browser.runtime.onMessage.addListener((msg, sender) => {
+      browser.test.assertEq(msg, "second script ran", "second script ran");
+      browser.test.notifyPass("executeScript");
+    });
+
+    browser.test.onMessage.addListener(msg => {
+      browser.test.assertEq(msg, "execute-script");
+
+      browser.tabs.query({ activeWindow: true }, tabs => {
+        browser.tabs.executeScript({
+          file: "script.js",
+        });
+
+        // Execute a script we know we have permissions for in the
+        // second tab, in the hopes that it will execute after the
+        // first one. This has intermittent failure written all over
+        // it, but it's just about the best we can do until we
+        // support callbacks for executeScript.
+        browser.tabs.executeScript(tabs[1].id, {
+          file: "second-script.js",
+        });
+      });
+    });
+
+    contentSetup().then(() => {
+      browser.test.sendMessage("ready");
+    });
+  }
+
   let extension = ExtensionTestUtils.loadExtension({
     manifest: params.manifest,
 
-    background: `(${function(contentSetup) {
-      browser.runtime.onMessage.addListener((msg, sender) => {
-        browser.test.assertEq(msg, "second script ran", "second script ran");
-        browser.test.notifyPass("executeScript");
-      });
-
-      browser.test.onMessage.addListener(msg => {
-        browser.test.assertEq(msg, "execute-script");
-
-        browser.tabs.query({ activeWindow: true }, tabs => {
-          browser.tabs.executeScript({
-            file: "script.js"
-          });
-
-          // Execute a script we know we have permissions for in the
-          // second tab, in the hopes that it will execute after the
-          // first one. This has intermittent failure written all over
-          // it, but it's just about the best we can do until we
-          // support callbacks for executeScript.
-          browser.tabs.executeScript(tabs[1].id, {
-            file: "second-script.js"
-          });
-        });
-      });
-
-      contentSetup().then(() => {
-        browser.test.sendMessage("ready");
-      });
-    }})(${contentSetup})`,
+    background: `(${background})(${contentSetup})`,
 
     files: {
       "script.js": function() {
         browser.runtime.sendMessage("first script ran");
       },
 
       "second-script.js": function() {
         browser.runtime.sendMessage("second script ran");
-      }
-    }
+      },
+    },
   });
 
   yield extension.startup();
   yield extension.awaitMessage("ready");
 
   if (params.setup) {
     yield params.setup(extension);
   }
@@ -63,22 +65,22 @@ function* testHasNoPermission(params) {
 }
 
 add_task(function* testBadPermissions() {
   let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
   let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
 
   info("Test no special permissions");
   yield testHasNoPermission({
-    manifest: { "permissions": ["http://example.com/"] }
+    manifest: { "permissions": ["http://example.com/"] },
   });
 
   info("Test tabs permissions");
   yield testHasNoPermission({
-    manifest: { "permissions": ["http://example.com/", "tabs"] }
+    manifest: { "permissions": ["http://example.com/", "tabs"] },
   });
 
   info("Test active tab, browser action, no click");
   yield testHasNoPermission({
     manifest: {
       "permissions": ["http://example.com/", "activeTab"],
       "browser_action": {},
     },
@@ -92,17 +94,17 @@ add_task(function* testBadPermissions() 
     },
     contentSetup() {
       return new Promise(resolve => {
         browser.tabs.query({ active: true, currentWindow: true }, tabs => {
           browser.pageAction.show(tabs[0].id);
           resolve();
         });
       });
-    }
+    },
   });
 
   yield BrowserTestUtils.removeTab(tab2);
   yield BrowserTestUtils.removeTab(tab1);
 });
 
 // TODO: Test that |executeScript| fails if the tab has navigated to a
 // new page, and no longer matches our expected state. This involves
--- a/browser/components/extensions/test/browser/browser_ext_tabs_executeScript_good.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_executeScript_good.js
@@ -1,40 +1,44 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 function* testHasPermission(params) {
   let contentSetup = params.contentSetup || (() => Promise.resolve());
 
+  function background(contentSetup) {
+    browser.runtime.onMessage.addListener((msg, sender) => {
+      browser.test.assertEq(msg, "script ran", "script ran");
+      browser.test.notifyPass("executeScript");
+    });
+
+    browser.test.onMessage.addListener(msg => {
+      browser.test.assertEq(msg, "execute-script");
+
+      browser.tabs.executeScript({
+        file: "script.js",
+      });
+    });
+
+    contentSetup().then(() => {
+      browser.test.sendMessage("ready");
+    });
+  }
+
   let extension = ExtensionTestUtils.loadExtension({
     manifest: params.manifest,
 
-    background: `(${function(contentSetup) {
-      browser.runtime.onMessage.addListener((msg, sender) => {
-        browser.test.assertEq(msg, "script ran", "script ran");
-        browser.test.notifyPass("executeScript");
-      });
-
-      browser.test.onMessage.addListener(msg => {
-        browser.test.assertEq(msg, "execute-script");
-
-        browser.tabs.executeScript({
-          file: "script.js"
-        });
-      });
-
-      contentSetup().then(() => {
-        browser.test.sendMessage("ready");
-      });
-    }})(${contentSetup})`,
+    background: `(${background})(${contentSetup})`,
 
     files: {
       "script.js": function() {
         browser.runtime.sendMessage("script ran");
-      }
-    }
+      },
+    },
   });
 
   yield extension.startup();
   yield extension.awaitMessage("ready");
 
   if (params.setup) {
     yield params.setup(extension);
   }
@@ -45,27 +49,27 @@ function* testHasPermission(params) {
   yield extension.unload();
 }
 
 add_task(function* testGoodPermissions() {
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
 
   info("Test explicit host permission");
   yield testHasPermission({
-    manifest: { "permissions": ["http://mochi.test/"] }
+    manifest: { "permissions": ["http://mochi.test/"] },
   });
 
   info("Test explicit host subdomain permission");
   yield testHasPermission({
-    manifest: { "permissions": ["http://*.mochi.test/"] }
+    manifest: { "permissions": ["http://*.mochi.test/"] },
   });
 
   info("Test explicit <all_urls> permission");
   yield testHasPermission({
-    manifest: { "permissions": ["<all_urls>"] }
+    manifest: { "permissions": ["<all_urls>"] },
   });
 
   info("Test activeTab permission with a browser action click");
   yield testHasPermission({
     manifest: {
       "permissions": ["activeTab"],
       "browser_action": {},
     },
--- a/browser/components/extensions/test/browser/browser_ext_tabs_getCurrent.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_getCurrent.js
@@ -1,8 +1,10 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 add_task(function* () {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
 
       "browser_action": { "default_popup": "popup.html" },
--- a/browser/components/extensions/test/browser/browser_ext_tabs_onUpdated.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_onUpdated.js
@@ -1,103 +1,107 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
   let win1 = yield BrowserTestUtils.openNewBrowserWindow();
 
   yield focusWindow(win1);
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
       "content_scripts": [{
         "matches": ["http://mochi.test/*/context_tabs_onUpdated_page.html"],
         "js": ["content-script.js"],
-        "run_at": "document_start"
-      },],
+        "run_at": "document_start",
+      }],
     },
 
     background: function() {
-      var pageURL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context_tabs_onUpdated_page.html";
+      let pageURL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context_tabs_onUpdated_page.html";
 
-      var expectedSequence = [
+      let expectedSequence = [
         { status: "loading" },
         { status: "loading", url: pageURL },
-        { status: "complete" }
+        { status: "complete" },
       ];
-      var collectedSequence = [];
+      let collectedSequence = [];
 
-      browser.tabs.onUpdated.addListener(function (tabId, updatedInfo) {
+      browser.tabs.onUpdated.addListener(function(tabId, updatedInfo) {
         collectedSequence.push(updatedInfo);
       });
 
-      browser.runtime.onMessage.addListener(function () {
-          if (collectedSequence.length !== expectedSequence.length) {
+      browser.runtime.onMessage.addListener(function() {
+        if (collectedSequence.length !== expectedSequence.length) {
+          browser.test.assertEq(
+            JSON.stringify(expectedSequence),
+            JSON.stringify(collectedSequence),
+            "got unexpected number of updateInfo data"
+          );
+        } else {
+          for (let i = 0; i < expectedSequence.length; i++) {
             browser.test.assertEq(
-              JSON.stringify(expectedSequence),
-              JSON.stringify(collectedSequence),
-              "got unexpected number of updateInfo data"
+              expectedSequence[i].status,
+              collectedSequence[i].status,
+              "check updatedInfo status"
             );
-          } else {
-            for (var i = 0; i < expectedSequence.length; i++) {
+            if (expectedSequence[i].url || collectedSequence[i].url) {
               browser.test.assertEq(
-                expectedSequence[i].status,
-                collectedSequence[i].status,
-                "check updatedInfo status"
+                expectedSequence[i].url,
+                collectedSequence[i].url,
+                "check updatedInfo url"
               );
-              if (expectedSequence[i].url || collectedSequence[i].url) {
-                browser.test.assertEq(
-                  expectedSequence[i].url,
-                  collectedSequence[i].url,
-                  "check updatedInfo url"
-                );
-              }
             }
           }
+        }
 
-          browser.test.notifyPass("tabs.onUpdated");
+        browser.test.notifyPass("tabs.onUpdated");
       });
 
       browser.tabs.create({ url: pageURL });
     },
     files: {
       "content-script.js": `
         window.addEventListener("message", function(evt) {
           if (evt.data == "frame-updated") {
             browser.runtime.sendMessage("load-completed");
           }
         }, true);
       `,
-    }
+    },
   });
 
   yield Promise.all([
     extension.startup(),
-    extension.awaitFinish("tabs.onUpdated")
+    extension.awaitFinish("tabs.onUpdated"),
   ]);
 
   yield extension.unload();
 
   yield BrowserTestUtils.closeWindow(win1);
 });
 
 function* do_test_update(background) {
   let win1 = yield BrowserTestUtils.openNewBrowserWindow();
 
   yield focusWindow(win1);
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: background,
   });
 
   yield Promise.all([
     yield extension.startup(),
-    yield extension.awaitFinish("finish")
+    yield extension.awaitFinish("finish"),
   ]);
 
   yield extension.unload();
 
   yield BrowserTestUtils.closeWindow(win1);
 }
 
 add_task(function* test_pinned() {
--- a/browser/components/extensions/test/browser/browser_ext_tabs_query.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_query.js
@@ -1,26 +1,30 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
   let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
   let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
 
   gBrowser.selectedTab = tab1;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
       browser.tabs.query({
-        lastFocusedWindow: true
+        lastFocusedWindow: true,
       }, function(tabs) {
         browser.test.assertEq(tabs.length, 3, "should have three tabs");
 
-        tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
+        tabs.sort((tab1, tab2) => tab1.index - tab2.index);
 
         browser.test.assertEq(tabs[0].url, "about:blank", "first tab blank");
         tabs.shift();
 
         browser.test.assertTrue(tabs[0].active, "tab 0 active");
         browser.test.assertFalse(tabs[1].active, "tab 1 inactive");
 
         browser.test.assertFalse(tabs[0].pinned, "tab 0 unpinned");
@@ -48,26 +52,26 @@ add_task(function* () {
 
   tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
   tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
   let tab3 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://test1.example.org/MochiKit/");
 
   // test simple queries
   extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
       browser.tabs.query({
-        url: "<all_urls>"
+        url: "<all_urls>",
       }, function(tabs) {
         browser.test.assertEq(tabs.length, 3, "should have three tabs");
 
-        tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
+        tabs.sort((tab1, tab2) => tab1.index - tab2.index);
 
         browser.test.assertEq(tabs[0].url, "http://example.com/", "tab 0 url correct");
         browser.test.assertEq(tabs[1].url, "http://example.net/", "tab 1 url correct");
         browser.test.assertEq(tabs[2].url, "http://test1.example.org/MochiKit/", "tab 2 url correct");
 
         browser.test.notifyPass("tabs.query");
       });
     },
@@ -75,22 +79,22 @@ add_task(function* () {
 
   yield extension.startup();
   yield extension.awaitFinish("tabs.query");
   yield extension.unload();
 
   // match pattern
   extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
       browser.tabs.query({
-        url: "http://*/MochiKit*"
+        url: "http://*/MochiKit*",
       }, function(tabs) {
         browser.test.assertEq(tabs.length, 1, "should have one tab");
 
         browser.test.assertEq(tabs[0].url, "http://test1.example.org/MochiKit/", "tab 0 url correct");
 
         browser.test.notifyPass("tabs.query");
       });
     },
@@ -98,26 +102,26 @@ add_task(function* () {
 
   yield extension.startup();
   yield extension.awaitFinish("tabs.query");
   yield extension.unload();
 
   // match array of patterns
   extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
       browser.tabs.query({
-        url: ["http://*/MochiKit*", "http://*.com/*"]
+        url: ["http://*/MochiKit*", "http://*.com/*"],
       }, function(tabs) {
         browser.test.assertEq(tabs.length, 2, "should have two tabs");
 
-        tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
+        tabs.sort((tab1, tab2) => tab1.index - tab2.index);
 
         browser.test.assertEq(tabs[0].url, "http://example.com/", "tab 0 url correct");
         browser.test.assertEq(tabs[1].url, "http://test1.example.org/MochiKit/", "tab 1 url correct");
 
         browser.test.notifyPass("tabs.query");
       });
     },
   });
--- a/browser/components/extensions/test/browser/browser_ext_tabs_sendMessage.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_sendMessage.js
@@ -1,31 +1,35 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* tabsSendMessageNoExceptionOnNonExistentTab() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
-      chrome.tabs.create({ url: "about:robots"}, function (tab) {
-        var exception;
+      browser.tabs.create({ url: "about:robots"}, tab => {
+        let exception;
         try {
           browser.tabs.sendMessage(tab.id, "message");
           browser.tabs.sendMessage(tab.id + 100, "message");
-        } catch(e) {
+        } catch (e) {
           exception = e;
         }
 
         browser.test.assertEq(undefined, exception, "no exception should be raised on tabs.sendMessage to unexistent tabs");
-        chrome.tabs.remove(tab.id, function() {
+        browser.tabs.remove(tab.id, function() {
           browser.test.notifyPass("tabs.sendMessage");
-        })
-      })
+        });
+      });
     },
   });
 
   yield Promise.all([
     extension.startup(),
-    extension.awaitFinish("tabs.sendMessage")
+    extension.awaitFinish("tabs.sendMessage"),
   ]);
 
   yield extension.unload();
 });
--- a/browser/components/extensions/test/browser/browser_ext_tabs_update.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_update.js
@@ -1,26 +1,30 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
   let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
   let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
 
   gBrowser.selectedTab = tab1;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["tabs"]
+      "permissions": ["tabs"],
     },
 
     background: function() {
       browser.tabs.query({
         lastFocusedWindow: true,
       }, function(tabs) {
         browser.test.assertEq(tabs.length, 3, "should have three tabs");
 
-        tabs.sort(function (tab1, tab2) { return tab1.index - tab2.index; });
+        tabs.sort((tab1, tab2) => tab1.index - tab2.index);
 
         browser.test.assertEq(tabs[0].url, "about:blank", "first tab blank");
         tabs.shift();
 
         browser.test.assertTrue(tabs[0].active, "tab 0 active");
         browser.test.assertFalse(tabs[1].active, "tab 1 inactive");
 
         browser.tabs.update(tabs[1].id, {active: true}, function() {
--- a/browser/components/extensions/test/browser/browser_ext_windows_update.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows_update.js
@@ -1,27 +1,31 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
 add_task(function* () {
-  function promiseWaitForFocus(aWindow) {
-    return new Promise(function(aResolve, aReject) {
+  function promiseWaitForFocus(window) {
+    return new Promise(resolve => {
       waitForFocus(function() {
-        ok(Services.focus.activeWindow === aWindow, "correct window focused");
-        aResolve();
-      }, aWindow);
+        ok(Services.focus.activeWindow === window, "correct window focused");
+        resolve();
+      }, window);
     });
   }
 
   let window1 = window;
   let window2 = yield BrowserTestUtils.openNewBrowserWindow();
 
   Services.focus.activeWindow = window2;
   yield promiseWaitForFocus(window2);
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "permissions": ["windows"]
+      "permissions": ["windows"],
     },
 
     background: function() {
       browser.windows.getAll(undefined, function(wins) {
         browser.test.assertEq(wins.length, 2, "should have two windows");
 
         // Sort the unfocused window to the lower index.
         wins.sort(function(win1, win2) {
@@ -30,17 +34,16 @@ add_task(function* () {
           }
 
           return win1.focused ? 1 : -1;
         });
 
         browser.windows.update(wins[0].id, {focused: true}, function() {
           browser.test.sendMessage("check");
         });
-
       });
     },
   });
 
   yield Promise.all([extension.startup(), extension.awaitMessage("check")]);
 
   yield promiseWaitForFocus(window1);
 
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -1,18 +1,22 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+/* exported CustomizableUI makeWidgetId focusWindow clickBrowserAction clickPageAction */
+
 var {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
 
-function makeWidgetId(id)
-{
+function makeWidgetId(id) {
   id = id.toLowerCase();
   return id.replace(/[^a-z0-9_-]/g, "_");
 }
 
-var focusWindow = Task.async(function* focusWindow(win)
-{
+var focusWindow = Task.async(function* focusWindow(win) {
   let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
   if (fm.activeWindow == win) {
     return;
   }
 
   let promise = new Promise(resolve => {
     win.addEventListener("focus", function listener() {
       win.removeEventListener("focus", listener, true);
@@ -34,16 +38,17 @@ function clickBrowserAction(extension, w
 
 function clickPageAction(extension, win = window) {
   // This would normally be set automatically on navigation, and cleared
   // when the user types a value into the URL bar, to show and hide page
   // identity info and icons such as page action buttons.
   //
   // Unfortunately, that doesn't happen automatically in browser chrome
   // tests.
+  /* globals SetPageProxyState */
   SetPageProxyState("valid");
 
   let pageActionId = makeWidgetId(extension.id) + "-page-action";
   let elem = win.document.getElementById(pageActionId);
 
   EventUtils.synthesizeMouseAtCenter(elem, {}, win);
   return new Promise(SimpleTest.executeSoon);
 }
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -1288,18 +1288,17 @@ PlacesController.prototype = {
     } catch(ex) {
       // No supported data exists or nodes unwrap failed, just bail out.
       return;
     }
 
     let itemsToSelect = [];
     if (PlacesUIUtils.useAsyncTransactions) {
       if (ip.isTag) {
-        let uris = [for (item of items) if ("uri" in item)
-                    NetUtil.newURI(item.uri)];
+        let uris = items.filter(item => "uri" in item).map(item => NetUtil.newURI(item.uri));
         yield PlacesTransactions.Tag({ uris: uris, tag: ip.tagName }).transact();
       }
       else {
         yield PlacesTransactions.batch(function* () {
           let insertionIndex = ip.index;
           let parent = yield ip.promiseGuid();
 
           for (let item of items) {
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -668,17 +668,17 @@ var PlacesOrganizer = {
 
       gEditItemOverlay.initPanel({ node: selectedNode
                                  , hiddenRows: ["folderPicker"] });
 
       this._detectAndSetDetailsPaneMinimalState(selectedNode);
     }
     else if (!selectedNode && aNodeList[0]) {
       if (aNodeList.every(PlacesUtils.nodeIsURI)) {
-        let uris = [for (node of aNodeList) PlacesUtils._uri(node.uri)];
+        let uris = aNodeList.map(node => PlacesUtils._uri(node.uri));
         detailsDeck.selectedIndex = 1;
         gEditItemOverlay.initPanel({ uris
                                    , hiddenRows: ["folderPicker",
                                                   "loadInSidebar",
                                                   "location",
                                                   "keyword",
                                                   "description",
                                                   "name"]});
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -149,17 +149,17 @@ PlacesTreeView.prototype = {
   _getRowForNode:
   function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) {
     if (aNode == this._rootNode)
       throw new Error("The root node is never visible");
 
     // A node is removed form the view either if it has no parent or if its
     // root-ancestor is not the root node (in which case that's the node
     // for which nodeRemoved was called).
-    let ancestors = [x for (x of PlacesUtils.nodeAncestors(aNode))];
+    let ancestors = Array.from(PlacesUtils.nodeAncestors(aNode));
     if (ancestors.length == 0 ||
         ancestors[ancestors.length - 1] != this._rootNode) {
       throw new Error("Removed node passed to _getRowForNode");
     }
 
     // Ensure that the entire chain is open, otherwise that node is invisible.
     for (let ancestor of ancestors) {
       if (!ancestor.containerOpen)
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -396,16 +396,30 @@ var SessionStoreInternal = {
   // properly handle final update message.
   _closedTabs: new WeakMap(),
 
   // A map (xul:browser -> object) that maps a browser associated with a
   // recently closed tab due to a window closure to the tab state information
   // that is being stored in _closedWindows for that tab.
   _closedWindowTabs: new WeakMap(),
 
+  // A set of window data that has the potential to be saved in the _closedWindows
+  // array for the session. We will remove window data from this set whenever
+  // forgetClosedWindow is called for the window, or when session history is
+  // purged, so that we don't accidentally save that data after the flush has
+  // completed. Closed tabs use a more complicated mechanism for this particular
+  // problem. When forgetClosedTab is called, the browser is removed from the
+  // _closedTabs map, so its data is not recorded. In the purge history case,
+  // the closedTabs array per window is overwritten so that once the flush is
+  // complete, the tab would only ever add itself to an array that SessionStore
+  // no longer cares about. Bug 1230636 has been filed to make the tab case
+  // work more like the window case, which is more explicit, and easier to
+  // reason about.
+  _saveableClosedWindowData: new WeakSet(),
+
   // A map (xul:browser -> object) that maps a browser that is switching
   // remoteness via navigateAndRestore, to the loadArguments that were
   // most recently passed when calling navigateAndRestore.
   _remotenessChangingBrowsers: new WeakMap(),
 
   // whether a setBrowserState call is in progress
   _browserSetState: false,
 
@@ -1265,16 +1279,20 @@ var SessionStoreInternal = {
       // we explicitly allow saving an "empty" window state.
       let isLastWindow =
         Object.keys(this._windows).length == 1 &&
         !this._closedWindows.some(win => win._shouldRestore || false);
 
       // clear this window from the list, since it has definitely been closed.
       delete this._windows[aWindow.__SSi];
 
+      // This window has the potential to be saved in the _closedWindows
+      // array (maybeSaveClosedWindows gets the final call on that).
+      this._saveableClosedWindowData.add(winData);
+
       // Now we have to figure out if this window is worth saving in the _closedWindows
       // Object.
       //
       // We're about to flush the tabs from this window, but it's possible that we
       // might never hear back from the content process(es) in time before the user
       // chooses to restore the closed window. So we do the following:
       //
       // 1) Use the tab state cache to determine synchronously if the window is
@@ -1347,16 +1365,17 @@ var SessionStoreInternal = {
     }
 
     // Cache the window state until it is completely gone.
     DyingWindowCache.set(aWindow, winData);
 
     let mm = aWindow.getGroupMessageManager("browsers");
     MESSAGES.forEach(msg => mm.removeMessageListener(msg, this));
 
+    this._saveableClosedWindowData.delete(winData);
     delete aWindow.__SSi;
   },
 
   /**
    * Decides whether or not a closed window should be put into the
    * _closedWindows Object. This might be called multiple times per
    * window, and will do the right thing of moving the window data
    * in or out of _closedWindows if the winData indicates that our
@@ -1368,17 +1387,19 @@ var SessionStoreInternal = {
    *        Whether or not the window being closed is the last
    *        browser window. Callers of this function should pass
    *        in the value of SessionStoreInternal.atLastWindow for
    *        this argument, and pass in the same value if they happen
    *        to call this method again asynchronously (for example, after
    *        a window flush).
    */
   maybeSaveClosedWindow(winData, isLastWindow) {
-    if (RunState.isRunning) {
+    // Make sure SessionStore is still running, and make sure that we
+    // haven't chosen to forget this window.
+    if (RunState.isRunning && this._saveableClosedWindowData.has(winData)) {
       // Determine whether the window has any tabs worth saving.
       let hasSaveableTabs = winData.tabs.some(this._shouldSaveTabState);
 
       // Note that we might already have this window stored in
       // _closedWindows from a previous call to this function.
       let winIndex = this._closedWindows.indexOf(winData);
       let alreadyStored = (winIndex != -1);
       let shouldStore = (hasSaveableTabs || isLastWindow);
@@ -1541,16 +1562,17 @@ var SessionStoreInternal = {
     var win = this._getMostRecentBrowserWindow();
     if (win) {
       win.setTimeout(() => SessionSaver.run(), 0);
     } else if (RunState.isRunning) {
       SessionSaver.run();
     }
 
     this._clearRestoringWindows();
+    this._saveableClosedWindowData.clear();
   },
 
   /**
    * On purge of domain data
    * @param aData
    *        String domain data
    */
   onPurgeDomainData: function ssi_onPurgeDomainData(aData) {
@@ -2185,17 +2207,19 @@ var SessionStoreInternal = {
   forgetClosedWindow: function ssi_forgetClosedWindow(aIndex) {
     // default to the most-recently closed window
     aIndex = aIndex || 0;
     if (!(aIndex in this._closedWindows)) {
       throw Components.Exception("Invalid index: not in the closed windows", Cr.NS_ERROR_INVALID_ARG);
     }
 
     // remove closed window from the array
+    let winData = this._closedWindows[aIndex];
     this._closedWindows.splice(aIndex, 1);
+    this._saveableClosedWindowData.delete(winData);
   },
 
   getWindowValue: function ssi_getWindowValue(aWindow, aKey) {
     if ("__SSi" in aWindow) {
       var data = this._windows[aWindow.__SSi].extData || {};
       return data[aKey] || "";
     }
 
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -213,8 +213,9 @@ skip-if = true
 [browser_625016.js]
 skip-if = os == "mac"
 
 [browser_911547.js]
 [browser_send_async_message_oom.js]
 [browser_multiple_navigateAndRestore.js]
 run-if = e10s
 [browser_async_window_flushing.js]
+[browser_forget_async_closings.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_forget_async_closings.js
@@ -0,0 +1,144 @@
+"use strict";
+
+const PAGE = "http://example.com/";
+
+/**
+ * Creates a tab in the current window worth storing in the
+ * closedTabs array, and then closes it. Runs a synchronous
+ * forgetFn passed in that should cause us to forget the tab,
+ * and then ensures that after the tab has sent its final
+ * update message that we didn't accidentally store it in
+ * the closedTabs array.
+ *
+ * @param forgetFn (function)
+ *        A synchronous function that should cause the tab
+ *        to be forgotten.
+ * @returns Promise
+ */
+let forgetTabHelper = Task.async(function*(forgetFn) {
+  // We want to suppress all non-final updates from the browser tabs
+  // so as to eliminate any racy-ness with this test.
+  yield pushPrefs(["browser.sessionstore.debug.no_auto_updates", true]);
+
+  // Forget any previous closed tabs from other tests that may have
+  // run in the same session.
+  Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
+
+  is(ss.getClosedTabCount(window), 0,
+     "We should have 0 closed tabs being stored.");
+
+  // Create a tab worth remembering.
+  let tab = gBrowser.addTab(PAGE);
+  let browser = tab.linkedBrowser;
+  yield BrowserTestUtils.browserLoaded(browser, false, PAGE);
+  yield TabStateFlusher.flush(browser);
+
+  // Now close the tab, and immediately choose to forget it.
+  let promise = BrowserTestUtils.removeTab(tab);
+
+  // At this point, the tab will have closed, but the final update
+  // to SessionStore hasn't come up yet. Now do the operation that
+  // should cause us to forget the tab.
+  forgetFn();
+
+  is(ss.getClosedTabCount(window), 0, "Should have forgotten the closed tab");
+
+  // Now wait for the final update to come up.
+  yield promise;
+
+  is(ss.getClosedTabCount(window), 0,
+     "Should not have stored the forgotten closed tab");
+});
+
+/**
+ * Creates a new window worth storing in the closeWIndows array,
+ * and then closes it. Runs a synchronous forgetFn passed in that
+ * should cause us to forget the window, and then ensures that after
+ * the window has sent its final update message that we didn't
+ * accidentally store it in the closedWindows array.
+ *
+ * @param forgetFn (function)
+ *        A synchronous function that should cause the window
+ *        to be forgotten.
+ * @returns Promise
+ */
+let forgetWinHelper = Task.async(function*(forgetFn) {
+  // We want to suppress all non-final updates from the browser tabs
+  // so as to eliminate any racy-ness with this test.
+  yield pushPrefs(["browser.sessionstore.debug.no_auto_updates", true]);
+
+  // Forget any previous closed windows from other tests that may have
+  // run in the same session.
+  Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
+
+  is(ss.getClosedWindowCount(), 0, "We should have 0 closed windows being stored.");
+
+  let newWin = yield BrowserTestUtils.openNewBrowserWindow();
+
+  // Create a tab worth remembering.
+  let tab = newWin.gBrowser.selectedTab;
+  let browser = tab.linkedBrowser;
+  browser.loadURI(PAGE);
+  yield BrowserTestUtils.browserLoaded(browser, false, PAGE);
+  yield TabStateFlusher.flush(browser);
+
+  // Now close the window and immediately choose to forget it.
+  let windowClosed = BrowserTestUtils.windowClosed(newWin);
+  let domWindowClosed = BrowserTestUtils.domWindowClosed(newWin);
+
+  newWin.close();
+  yield domWindowClosed;
+
+  // At this point, the window will have closed and the onClose handler
+  // has run, but the final update  to SessionStore hasn't come up yet.
+  // Now do the oepration that should cause us to forget the window.
+  forgetFn();
+
+  is(ss.getClosedWindowCount(), 0, "Should have forgotten the closed window");
+
+  // Now wait for the final update to come up.
+  yield windowClosed;
+
+  is(ss.getClosedWindowCount(), 0, "Should not have stored the closed window");
+});
+
+/**
+ * Tests that if we choose to forget a tab while waiting for its
+ * final flush to complete, we don't accidentally store it.
+ */
+add_task(function* test_forget_closed_tab() {
+  yield forgetTabHelper(() => {
+    ss.forgetClosedTab(window, 0);
+  });
+});
+
+/**
+ * Tests that if we choose to forget a tab while waiting for its
+ * final flush to complete, we don't accidentally store it.
+ */
+add_task(function* test_forget_closed_window() {
+  yield forgetWinHelper(() => {
+    ss.forgetClosedWindow(0);
+  });
+});
+
+/**
+ * Tests that if we choose to purge history while waiting for a
+ * final flush of a tab to complete, we don't accidentally store it.
+ */
+add_task(function* test_forget_purged_tab() {
+  yield forgetTabHelper(() => {
+    Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
+  });
+});
+
+/**
+ * Tests that if we choose to purge history while waiting for a
+ * final flush of a window to complete, we don't accidentally
+ * store it.
+ */
+add_task(function* test_forget_purged_window() {
+  yield forgetWinHelper(() => {
+    Services.obs.notifyObservers(null, "browser:purge-session-history", 0);
+  });
+});
--- a/browser/extensions/loop/test/desktop-local/conversation_test.js
+++ b/browser/extensions/loop/test/desktop-local/conversation_test.js
@@ -24,16 +24,17 @@ describe("loop.conversation", function()
       },
       GetLocale: function() {
         return "en-US";
       },
       SetLoopPref: setLoopPrefStub,
       GetLoopPref: function(prefName) {
         switch (prefName) {
           case "debug.sdk":
+          case "debug.dispatcher":
             return false;
           default:
             return "http://fake";
         }
       },
       GetAllConstants: function() {
         return {
           LOOP_SESSION_TYPE: {
--- a/browser/extensions/loop/test/desktop-local/panel_test.js
+++ b/browser/extensions/loop/test/desktop-local/panel_test.js
@@ -51,17 +51,21 @@ describe("loop.panel", function() {
       },
       GetAllConstants: function() { return {}; },
       GetLocale: function() {
         return "en-US";
       },
       GetPluralRule: sinon.stub(),
       SetLoopPref: sinon.stub(),
       GetLoopPref: function(prefName) {
-        return "unseen";
+        if (prefName === "gettingStarted.seen") {
+          return "unseen";
+        }
+
+        return false;
       },
       GetPluralForm: function() {
         return "fakeText";
       },
       "Rooms:GetAll": function(version) {
         return [];
       },
       "Rooms:PushSubscription": sinon.stub(),
--- a/browser/extensions/loop/test/desktop-local/roomStore_test.js
+++ b/browser/extensions/loop/test/desktop-local/roomStore_test.js
@@ -45,18 +45,20 @@ describe("loop.store.RoomStore", functio
           },
           ROOM_CONTEXT_ADD: {
             ADD_FROM_PANEL: 0,
             ADD_FROM_CONVERSATION: 1
           }
         };
       },
       CopyString: sinon.stub(),
-      GetLoopPref: function(pref) {
-        return pref;
+      GetLoopPref: function(prefName) {
+        if (prefName === "debug.dispatcher") {
+          return false;
+        }
       },
       NotifyUITour: function() {},
       "Rooms:Create": sinon.stub().returns({ roomToken: "fakeToken" }),
       "Rooms:Delete": sinon.stub(),
       "Rooms:GetAll": sinon.stub(),
       "Rooms:Open": sinon.stub(),
       "Rooms:Rename": sinon.stub(),
       "Rooms:PushSubscription": sinon.stub(),
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,3 +1,3 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 1.3.42
+Current extension version is: 1.3.56
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -15,18 +15,18 @@
 /*jshint globalstrict: false */
 /* globals PDFJS */
 
 // Initializing PDFJS global object (if still undefined)
 if (typeof PDFJS === 'undefined') {
   (typeof window !== 'undefined' ? window : this).PDFJS = {};
 }
 
-PDFJS.version = '1.3.42';
-PDFJS.build = '84a47f8';
+PDFJS.version = '1.3.56';
+PDFJS.build = 'e2aca38';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
 
 
 var globalScope = (typeof window === 'undefined') ? this : window;
@@ -243,17 +243,16 @@ function deprecated(details) {
 
 // Fatal errors that should trigger the fallback UI and halt execution by
 // throwing an exception.
 function error(msg) {
   if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) {
     console.log('Error: ' + msg);
     console.log(backtrace());
   }
-  UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
   throw new Error(msg);
 }
 
 function backtrace() {
   try {
     throw new Error();
   } catch (e) {
     return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
@@ -270,32 +269,16 @@ var UNSUPPORTED_FEATURES = PDFJS.UNSUPPO
   unknown: 'unknown',
   forms: 'forms',
   javaScript: 'javaScript',
   smask: 'smask',
   shadingPattern: 'shadingPattern',
   font: 'font'
 };
 
-var UnsupportedManager = PDFJS.UnsupportedManager =
-  (function UnsupportedManagerClosure() {
-  var listeners = [];
-  return {
-    listen: function (cb) {
-      listeners.push(cb);
-    },
-    notify: function (featureId) {
-      warn('Unsupported feature "' + featureId + '"');
-      for (var i = 0, ii = listeners.length; i < ii; i++) {
-        listeners[i](featureId);
-      }
-    }
-  };
-})();
-
 // Combines two URLs. The baseUrl shall be absolute URL. If the url is an
 // absolute URL, it will be returned as is.
 function combineUrl(baseUrl, url) {
   if (!url) {
     return baseUrl;
   }
   if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) {
     return url;
@@ -1767,16 +1750,22 @@ var PDFDocumentLoadingTask = (function P
     this.onPassword = null;
 
     /**
      * Callback to be able to monitor the loading progress of the PDF file
      * (necessary to implement e.g. a loading bar). The callback receives
      * an {Object} with the properties: {number} loaded and {number} total.
      */
     this.onProgress = null;
+
+    /**
+     * Callback to when unsupported feature is used. The callback receives
+     * an {PDFJS.UNSUPPORTED_FEATURES} argument.
+     */
+    this.onUnsupportedFeature = null;
   }
 
   PDFDocumentLoadingTask.prototype =
       /** @lends PDFDocumentLoadingTask.prototype */ {
     /**
      * @return {Promise}
      */
     get promise() {
@@ -2525,19 +2514,16 @@ var PDFWorker = (function PDFWorkerClosu
           }.bind(this));
 
           messageHandler.on('console_log', function (data) {
             console.log.apply(console, data);
           });
           messageHandler.on('console_error', function (data) {
             console.error.apply(console, data);
           });
-          messageHandler.on('_unsupported_feature', function (data) {
-            UnsupportedManager.notify(data);
-          });
 
           var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
           // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
           // typed array. Also, checking if we can use transfers.
           try {
             messageHandler.send('test', testObj, [testObj.buffer]);
           } catch (ex) {
             info('Cannot use postMessage transfers');
@@ -2894,16 +2880,29 @@ var WorkerTransport = (function WorkerTr
         var intentState = page.intentStates[data.intent];
         if (intentState.displayReadyCapability) {
           intentState.displayReadyCapability.reject(data.error);
         } else {
           error(data.error);
         }
       }, this);
 
+      messageHandler.on('UnsupportedFeature',
+          function transportUnsupportedFeature(data) {
+        if (this.destroyed) {
+          return; // Ignore any pending requests if the worker was terminated.
+        }
+        var featureId = data.featureId;
+        var loadingTask = this.loadingTask;
+        if (loadingTask.onUnsupportedFeature) {
+          loadingTask.onUnsupportedFeature(featureId);
+        }
+        PDFJS.UnsupportedManager.notify(featureId);
+      }, this);
+
       messageHandler.on('JpegDecode', function(data) {
         if (this.destroyed) {
           return Promise.reject('Worker was terminated');
         }
 
         var imageUrl = data[0];
         var components = data[1];
         if (components !== 3 && components !== 1) {
@@ -3311,16 +3310,36 @@ var InternalRenderTask = (function Inter
       }
     }
 
   };
 
   return InternalRenderTask;
 })();
 
+/**
+ * (Deprecated) Global observer of unsupported feature usages. Use
+ * onUnsupportedFeature callback of the {PDFDocumentLoadingTask} instance.
+ */
+PDFJS.UnsupportedManager = (function UnsupportedManagerClosure() {
+  var listeners = [];
+  return {
+    listen: function (cb) {
+      deprecated('Global UnsupportedManager.listen is used: ' +
+                 ' use PDFDocumentLoadingTask.onUnsupportedFeature instead');
+      listeners.push(cb);
+    },
+    notify: function (featureId) {
+      for (var i = 0, ii = listeners.length; i < ii; i++) {
+        listeners[i](featureId);
+      }
+    }
+  };
+})();
+
 
 var Metadata = PDFJS.Metadata = (function MetadataClosure() {
   function fixMetadata(meta) {
     return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
       var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
                                 function(code, d1, d2, d3) {
         return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
       });
@@ -4347,16 +4366,17 @@ var CanvasGraphics = (function CanvasGra
     },
     endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
       var groupCtx = this.ctx;
       this.groupLevel--;
       this.ctx = this.groupStack.pop();
 
       composeSMask(this.ctx, this.current.activeSMask, groupCtx);
       this.ctx.restore();
+      copyCtxState(groupCtx, this.ctx);
     },
     save: function CanvasGraphics_save() {
       this.ctx.save();
       var old = this.current;
       this.stateStack.push(old);
       this.current = old.clone();
       this.current.activeSMask = null;
     },
@@ -5466,17 +5486,16 @@ var CanvasGraphics = (function CanvasGra
     },
 
     paintSolidColorImageMask:
       function CanvasGraphics_paintSolidColorImageMask() {
         this.ctx.fillRect(0, 0, 1, 1);
     },
 
     paintXObject: function CanvasGraphics_paintXObject() {
-      UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
       warn('Unsupported \'paintXObject\' command.');
     },
 
     // Marked content
 
     markPoint: function CanvasGraphics_markPoint(tag) {
       // TODO Marked content.
     },
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -15,18 +15,18 @@
 /*jshint globalstrict: false */
 /* globals PDFJS */
 
 // Initializing PDFJS global object (if still undefined)
 if (typeof PDFJS === 'undefined') {
   (typeof window !== 'undefined' ? window : this).PDFJS = {};
 }
 
-PDFJS.version = '1.3.42';
-PDFJS.build = '84a47f8';
+PDFJS.version = '1.3.56';
+PDFJS.build = 'e2aca38';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
 
 
 var globalScope = (typeof window === 'undefined') ? this : window;
@@ -243,17 +243,16 @@ function deprecated(details) {
 
 // Fatal errors that should trigger the fallback UI and halt execution by
 // throwing an exception.
 function error(msg) {
   if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) {
     console.log('Error: ' + msg);
     console.log(backtrace());
   }
-  UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
   throw new Error(msg);
 }
 
 function backtrace() {
   try {
     throw new Error();
   } catch (e) {
     return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
@@ -270,32 +269,16 @@ var UNSUPPORTED_FEATURES = PDFJS.UNSUPPO
   unknown: 'unknown',
   forms: 'forms',
   javaScript: 'javaScript',
   smask: 'smask',
   shadingPattern: 'shadingPattern',
   font: 'font'
 };
 
-var UnsupportedManager = PDFJS.UnsupportedManager =
-  (function UnsupportedManagerClosure() {
-  var listeners = [];
-  return {
-    listen: function (cb) {
-      listeners.push(cb);
-    },
-    notify: function (featureId) {
-      warn('Unsupported feature "' + featureId + '"');
-      for (var i = 0, ii = listeners.length; i < ii; i++) {
-        listeners[i](featureId);
-      }
-    }
-  };
-})();
-
 // Combines two URLs. The baseUrl shall be absolute URL. If the url is an
 // absolute URL, it will be returned as is.
 function combineUrl(baseUrl, url) {
   if (!url) {
     return baseUrl;
   }
   if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) {
     return url;
@@ -1871,17 +1854,16 @@ var ChunkedStreamManager = (function Chu
       }
     }
   };
 
   return ChunkedStreamManager;
 })();
 
 
-// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available
 var BasePdfManager = (function BasePdfManagerClosure() {
   function BasePdfManager() {
     throw new Error('Cannot initialize BaseManagerManager');
   }
 
   BasePdfManager.prototype = {
     get docId() {
       return this._docId;
@@ -1898,29 +1880,29 @@ var BasePdfManager = (function BasePdfMa
     ensureXRef: function BasePdfManager_ensureXRef(prop, args) {
       return this.ensure(this.pdfDocument.xref, prop, args);
     },
 
     ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) {
       return this.ensure(this.pdfDocument.catalog, prop, args);
     },
 
-    getPage: function BasePdfManager_pagePage(pageIndex) {
+    getPage: function BasePdfManager_getPage(pageIndex) {
       return this.pdfDocument.getPage(pageIndex);
     },
 
     cleanup: function BasePdfManager_cleanup() {
       return this.pdfDocument.cleanup();
     },
 
     ensure: function BasePdfManager_ensure(obj, prop, args) {
       return new NotImplementedException();
     },
 
-    requestRange: function BasePdfManager_ensure(begin, end) {
+    requestRange: function BasePdfManager_requestRange(begin, end) {
       return new NotImplementedException();
     },
 
     requestLoadedStream: function BasePdfManager_requestLoadedStream() {
       return new NotImplementedException();
     },
 
     sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) {
@@ -1951,55 +1933,50 @@ var LocalPdfManager = (function LocalPdf
   function LocalPdfManager(docId, data, password) {
     this._docId = docId;
     var stream = new Stream(data);
     this.pdfDocument = new PDFDocument(this, stream, password);
     this._loadedStreamCapability = createPromiseCapability();
     this._loadedStreamCapability.resolve(stream);
   }
 
-  LocalPdfManager.prototype = Object.create(BasePdfManager.prototype);
-  LocalPdfManager.prototype.constructor = LocalPdfManager;
-
-  LocalPdfManager.prototype.ensure =
-      function LocalPdfManager_ensure(obj, prop, args) {
-    return new Promise(function (resolve, reject) {
-      try {
-        var value = obj[prop];
-        var result;
-        if (typeof value === 'function') {
-          result = value.apply(obj, args);
-        } else {
-          result = value;
-        }
-        resolve(result);
-      } catch (e) {
-        reject(e);
-      }
-    });
-  };
-
-  LocalPdfManager.prototype.requestRange =
-      function LocalPdfManager_requestRange(begin, end) {
-    return Promise.resolve();
-  };
-
-  LocalPdfManager.prototype.requestLoadedStream =
-      function LocalPdfManager_requestLoadedStream() {
-  };
-
-  LocalPdfManager.prototype.onLoadedStream =
-      function LocalPdfManager_getLoadedStream() {
-    return this._loadedStreamCapability.promise;
-  };
-
-  LocalPdfManager.prototype.terminate =
-      function LocalPdfManager_terminate() {
-    return;
-  };
+  Util.inherit(LocalPdfManager, BasePdfManager, {
+    ensure: function LocalPdfManager_ensure(obj, prop, args) {
+      return new Promise(function (resolve, reject) {
+        try {
+          var value = obj[prop];
+          var result;
+          if (typeof value === 'function') {
+            result = value.apply(obj, args);
+          } else {
+            result = value;
+          }
+          resolve(result);
+        } catch (e) {
+          reject(e);
+        }
+      });
+    },
+
+    requestRange: function LocalPdfManager_requestRange(begin, end) {
+      return Promise.resolve();
+    },
+
+    requestLoadedStream: function LocalPdfManager_requestLoadedStream() {
+      return;
+    },
+
+    onLoadedStream: function LocalPdfManager_onLoadedStream() {
+      return this._loadedStreamCapability.promise;
+    },
+
+    terminate: function LocalPdfManager_terminate() {
+      return;
+    }
+  });
 
   return LocalPdfManager;
 })();
 
 var NetworkPdfManager = (function NetworkPdfManagerClosure() {
   function NetworkPdfManager(docId, args, msgHandler) {
     this._docId = docId;
     this.msgHandler = msgHandler;
@@ -2010,77 +1987,70 @@ var NetworkPdfManager = (function Networ
       withCredentials: args.withCredentials,
       chunkedViewerLoading: args.chunkedViewerLoading,
       disableAutoFetch: args.disableAutoFetch,
       initialData: args.initialData
     };
     this.streamManager = new ChunkedStreamManager(args.length,
                                                   args.rangeChunkSize,
                                                   args.url, params);
-
     this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(),
-                                    args.password);
-  }
-
-  NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype);
-  NetworkPdfManager.prototype.constructor = NetworkPdfManager;
-
-  NetworkPdfManager.prototype.ensure =
-      function NetworkPdfManager_ensure(obj, prop, args) {
-    var pdfManager = this;
-
-    return new Promise(function (resolve, reject) {
-      function ensureHelper() {
-        try {
-          var result;
-          var value = obj[prop];
-          if (typeof value === 'function') {
-            result = value.apply(obj, args);
-          } else {
-            result = value;
-          }
-          resolve(result);
-        } catch(e) {
-          if (!(e instanceof MissingDataException)) {
-            reject(e);
-            return;
-          }
-          pdfManager.streamManager.requestRange(e.begin, e.end).
-            then(ensureHelper, reject);
-        }
-      }
-
-      ensureHelper();
-    });
-  };
-
-  NetworkPdfManager.prototype.requestRange =
-      function NetworkPdfManager_requestRange(begin, end) {
-    return this.streamManager.requestRange(begin, end);
-  };
-
-  NetworkPdfManager.prototype.requestLoadedStream =
-      function NetworkPdfManager_requestLoadedStream() {
-    this.streamManager.requestAllChunks();
-  };
-
-  NetworkPdfManager.prototype.sendProgressiveData =
-      function NetworkPdfManager_sendProgressiveData(chunk) {
-    this.streamManager.onReceiveData({ chunk: chunk });
-  };
-
-  NetworkPdfManager.prototype.onLoadedStream =
-      function NetworkPdfManager_getLoadedStream() {
-    return this.streamManager.onLoadedStream();
-  };
-
-  NetworkPdfManager.prototype.terminate =
-      function NetworkPdfManager_terminate() {
-    this.streamManager.abort();
-  };
+                                       args.password);
+  }
+
+  Util.inherit(NetworkPdfManager, BasePdfManager, {
+    ensure: function NetworkPdfManager_ensure(obj, prop, args) {
+      var pdfManager = this;
+
+      return new Promise(function (resolve, reject) {
+        function ensureHelper() {
+          try {
+            var result;
+            var value = obj[prop];
+            if (typeof value === 'function') {
+              result = value.apply(obj, args);
+            } else {
+              result = value;
+            }
+            resolve(result);
+          } catch(e) {
+            if (!(e instanceof MissingDataException)) {
+              reject(e);
+              return;
+            }
+            pdfManager.streamManager.requestRange(e.begin, e.end).
+              then(ensureHelper, reject);
+          }
+        }
+
+        ensureHelper();
+      });
+    },
+
+    requestRange: function NetworkPdfManager_requestRange(begin, end) {
+      return this.streamManager.requestRange(begin, end);
+    },
+
+    requestLoadedStream: function NetworkPdfManager_requestLoadedStream() {
+      this.streamManager.requestAllChunks();
+    },
+
+    sendProgressiveData:
+        function NetworkPdfManager_sendProgressiveData(chunk) {
+      this.streamManager.onReceiveData({ chunk: chunk });
+    },
+
+    onLoadedStream: function NetworkPdfManager_onLoadedStream() {
+      return this.streamManager.onLoadedStream();
+    },
+
+    terminate: function NetworkPdfManager_terminate() {
+      this.streamManager.abort();
+    }
+  });
 
   return NetworkPdfManager;
 })();
 
 
 var Page = (function PageClosure() {
 
   var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
@@ -2265,17 +2235,17 @@ var Page = (function PageClosure() {
         var annotations = datas[1];
 
         if (annotations.length === 0) {
           pageOpList.flush(true);
           return pageOpList;
         }
 
         var annotationsReadyPromise = Annotation.appendToOperatorList(
-          annotations, pageOpList, pdfManager, partialEvaluator, task, intent);
+          annotations, pageOpList, partialEvaluator, task, intent);
         return annotationsReadyPromise.then(function () {
           pageOpList.flush(true);
           return pageOpList;
         });
       });
     },
 
     extractTextContent: function Page_extractTextContent(task,
@@ -4538,35 +4508,32 @@ var Annotation = (function AnnotationClo
     } else {
       appearance = appearances;
     }
     return appearance;
   }
 
   function Annotation(params) {
     var dict = params.dict;
-    var data = this.data = {};
-
-    data.subtype = dict.get('Subtype').name;
 
     this.setFlags(dict.get('F'));
-    data.annotationFlags = this.flags;
-
     this.setRectangle(dict.get('Rect'));
-    data.rect = this.rectangle;
-
     this.setColor(dict.get('C'));
-    data.color = this.color;
-
-    this.borderStyle = data.borderStyle = new AnnotationBorderStyle();
     this.setBorderStyle(dict);
-
     this.appearance = getDefaultAppearance(dict);
-    data.hasAppearance = !!this.appearance;
-    data.id = params.ref.num;
+
+    // Expose public properties using a data object.
+    this.data = {};
+    this.data.id = params.ref.num;
+    this.data.subtype = dict.get('Subtype').name;
+    this.data.annotationFlags = this.flags;
+    this.data.rect = this.rectangle;
+    this.data.color = this.color;
+    this.data.borderStyle = this.borderStyle;
+    this.data.hasAppearance = !!this.appearance;
   }
 
   Annotation.prototype = {
     /**
      * @return {boolean}
      */
     get viewable() {
       if (this.flags) {
@@ -4683,16 +4650,17 @@ var Annotation = (function AnnotationClo
     /**
      * Set the border style (as AnnotationBorderStyle object).
      *
      * @public
      * @memberof Annotation
      * @param {Dict} borderStyle - The border style dictionary
      */
     setBorderStyle: function Annotation_setBorderStyle(borderStyle) {
+      this.borderStyle = new AnnotationBorderStyle();
       if (!isDict(borderStyle)) {
         return;
       }
       if (borderStyle.has('BS')) {
         var dict = borderStyle.get('BS');
         var dictType;
 
         if (!dict.has('Type') || (isName(dictType = dict.get('Type')) &&
@@ -4735,23 +4703,21 @@ var Annotation = (function AnnotationClo
           objectLoader.load().then(function() {
             resolve(resources);
           }, reject);
         }, reject);
       }.bind(this));
     },
 
     getOperatorList: function Annotation_getOperatorList(evaluator, task) {
-
       if (!this.appearance) {
         return Promise.resolve(new OperatorList());
       }
 
       var data = this.data;
-
       var appearanceDict = this.appearance.dict;
       var resourcesPromise = this.loadResources([
         'ExtGState',
         'ColorSpace',
         'Pattern',
         'Shading',
         'XObject',
         'Font'
@@ -4773,43 +4739,32 @@ var Annotation = (function AnnotationClo
               self.appearance.reset();
               return opList;
             });
         });
     }
   };
 
   Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
-      annotations, opList, pdfManager, partialEvaluator, task, intent) {
-
-    function reject(e) {
-      annotationsReadyCapability.reject(e);
-    }
-
-    var annotationsReadyCapability = createPromiseCapability();
-
+      annotations, opList, partialEvaluator, task, intent) {
     var annotationPromises = [];
     for (var i = 0, n = annotations.length; i < n; ++i) {
-      if (intent === 'display' && annotations[i].viewable ||
-          intent === 'print' && annotations[i].printable) {
+      if ((intent === 'display' && annotations[i].viewable) ||
+          (intent === 'print' && annotations[i].printable)) {
         annotationPromises.push(
           annotations[i].getOperatorList(partialEvaluator, task));
       }
     }
-    Promise.all(annotationPromises).then(function(datas) {
+    return Promise.all(annotationPromises).then(function(operatorLists) {
       opList.addOp(OPS.beginAnnotations, []);
-      for (var i = 0, n = datas.length; i < n; ++i) {
-        var annotOpList = datas[i];
-        opList.addOpList(annotOpList);
+      for (var i = 0, n = operatorLists.length; i < n; ++i) {
+        opList.addOpList(operatorLists[i]);
       }
       opList.addOp(OPS.endAnnotations, []);
-      annotationsReadyCapability.resolve();
-    }, reject);
-
-    return annotationsReadyCapability.promise;
+    });
   };
 
   return Annotation;
 })();
 
 /**
  * Contains all data regarding an annotation's border style.
  *
@@ -4944,17 +4899,16 @@ var AnnotationBorderStyle = (function An
       }
     }
   };
 
   return AnnotationBorderStyle;
 })();
 
 var WidgetAnnotation = (function WidgetAnnotationClosure() {
-
   function WidgetAnnotation(params) {
     Annotation.call(this, params);
 
     var dict = params.dict;
     var data = this.data;
 
     data.fieldValue = stringToPDFString(
       Util.getInheritableProperty(dict, 'V') || '');
@@ -5068,17 +5022,17 @@ var TextAnnotation = (function TextAnnot
       data.name = dict.has('Name') ? dict.get('Name').name : 'Note';
     }
 
     if (dict.has('C')) {
       data.hasBgColor = true;
     }
   }
 
-  Util.inherit(TextAnnotation, Annotation, { });
+  Util.inherit(TextAnnotation, Annotation, {});
 
   return TextAnnotation;
 })();
 
 var LinkAnnotation = (function LinkAnnotationClosure() {
   function LinkAnnotation(params) {
     Annotation.call(this, params);
 
@@ -5144,17 +5098,17 @@ var LinkAnnotation = (function LinkAnnot
   // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
   function addDefaultProtocolToUrl(url) {
     if (url && url.indexOf('www.') === 0) {
       return ('http://' + url);
     }
     return url;
   }
 
-  Util.inherit(LinkAnnotation, Annotation, { });
+  Util.inherit(LinkAnnotation, Annotation, {});
 
   return LinkAnnotation;
 })();
 
 
 var PDFFunction = (function PDFFunctionClosure() {
   var CONSTRUCT_SAMPLED = 0;
   var CONSTRUCT_INTERPOLATED = 2;
@@ -9562,17 +9516,17 @@ var Pattern = (function PatternClosure()
     // Input: current Canvas context
     // Output: the appropriate fillStyle or strokeStyle
     getPattern: function Pattern_getPattern(ctx) {
       error('Should not call Pattern.getStyle: ' + ctx);
     }
   };
 
   Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
-                                                       res) {
+                                                       res, handler) {
 
     var dict = isStream(shading) ? shading.dict : shading;
     var type = dict.get('ShadingType');
 
     try {
       switch (type) {
         case ShadingType.AXIAL:
         case ShadingType.RADIAL:
@@ -9585,17 +9539,18 @@ var Pattern = (function PatternClosure()
           return new Shadings.Mesh(shading, matrix, xref, res);
         default:
           throw new Error('Unsupported ShadingType: ' + type);
       }
     } catch (ex) {
       if (ex instanceof MissingDataException) {
         throw ex;
       }
-      UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
+      handler.send('UnsupportedFeature',
+                   {featureId: UNSUPPORTED_FEATURES.shadingPattern});
       warn(ex);
       return new Shadings.Dummy();
     }
   };
   return Pattern;
 })();
 
 var Shadings = {};
@@ -10623,16 +10578,19 @@ var PartialEvaluator = (function Partial
           function (translated) {
         if (!translated.font.isType3Font) {
           return translated;
         }
         return translated.loadType3Data(self, resources, operatorList, task).
           then(function () {
           return translated;
         }, function (reason) {
+          // Error in the font data -- sending unsupported feature notification.
+          self.handler.send('UnsupportedFeature',
+                            {featureId: UNSUPPORTED_FEATURES.font});
           return new TranslatedFont('g_font_error',
             new ErrorFont('Type3 font load error: ' + reason), translated.font);
         });
       }).then(function (translated) {
         state.font = translated.font;
         translated.send(self.handler);
         return translated.loadedName;
       });
@@ -10847,27 +10805,30 @@ var PartialEvaluator = (function Partial
       var translatedPromise;
       try {
         translatedPromise = Promise.resolve(
           this.translateFont(preEvaluatedFont, xref));
       } catch (e) {
         translatedPromise = Promise.reject(e);
       }
 
+      var self = this;
       translatedPromise.then(function (translatedFont) {
         if (translatedFont.fontType !== undefined) {
           var xrefFontStats = xref.stats.fontTypes;
           xrefFontStats[translatedFont.fontType] = true;
         }
 
         fontCapability.resolve(new TranslatedFont(font.loadedName,
           translatedFont, font));
       }, function (reason) {
         // TODO fontCapability.reject?
-        UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
+        // Error in the font data -- sending unsupported feature notification.
+        self.handler.send('UnsupportedFeature',
+                          {featureId: UNSUPPORTED_FEATURES.font});
 
         try {
           // error, but it's still nice to have font type reported
           var descriptor = preEvaluatedFont.descriptor;
           var fontFile3 = descriptor && descriptor.get('FontFile3');
           var subtype = fontFile3 && fontFile3.get('Subtype');
           var fontType = getFontType(preEvaluatedFont.type,
                                      subtype && subtype.name);
@@ -10910,17 +10871,18 @@ var PartialEvaluator = (function Partial
 
         if (typeNum === TILING_PATTERN) {
           var color = cs.base ? cs.base.getRgb(args, 0) : null;
           return this.handleTilingType(fn, color, resources, pattern,
                                        dict, operatorList, task);
         } else if (typeNum === SHADING_PATTERN) {
           var shading = dict.get('Shading');
           var matrix = dict.get('Matrix');
-          pattern = Pattern.parseShading(shading, matrix, xref, resources);
+          pattern = Pattern.parseShading(shading, matrix, xref, resources,
+                                         this.handler);
           operatorList.addOp(fn, pattern.getIR());
           return Promise.resolve();
         } else {
           return Promise.reject('Unknown PatternType: ' + typeNum);
         }
       }
       // TODO shall we fail here?
       operatorList.addOp(fn, args);
@@ -11147,17 +11109,17 @@ var PartialEvaluator = (function Partial
               }
 
               var shading = shadingRes.get(args[0].name);
               if (!shading) {
                 error('No shading object found');
               }
 
               var shadingFill = Pattern.parseShading(shading, null, xref,
-                resources);
+                resources, self.handler);
               var patternIR = shadingFill.getIR();
               args = [patternIR];
               fn = OPS.shadingFill;
               break;
             case OPS.setGState:
               var dictName = args[0];
               var extGState = resources.get('ExtGState');
 
@@ -16924,21 +16886,25 @@ var Font = (function FontClosure() {
     }
     return {
       toFontChar: toFontChar,
       charCodeToGlyphId: newMap,
       nextAvailableFontCharCode: nextAvailableFontCharCode
     };
   }
 
-  function getRanges(glyphs) {
+  function getRanges(glyphs, numGlyphs) {
     // Array.sort() sorts by characters, not numerically, so convert to an
     // array of characters.
     var codes = [];
     for (var charCode in glyphs) {
+      // Remove an invalid glyph ID mappings to make OTS happy.
+      if (glyphs[charCode] >= numGlyphs) {
+        continue;
+      }
       codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] });
     }
     codes.sort(function fontGetRangesSort(a, b) {
       return a.fontCharCode - b.fontCharCode;
     });
 
     // Split the sorted codes into ranges.
     var ranges = [];
@@ -16957,18 +16923,18 @@ var Font = (function FontClosure() {
         }
       }
       ranges.push([start, end, codeIndices]);
     }
 
     return ranges;
   }
 
-  function createCmapTable(glyphs) {
-    var ranges = getRanges(glyphs);
+  function createCmapTable(glyphs, numGlyphs) {
+    var ranges = getRanges(glyphs, numGlyphs);
     var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
     var cmap = '\x00\x00' + // version
                string16(numTables) +  // numTables
                '\x00\x03' + // platformID
                '\x00\x01' + // encodingID
                string32(4 + numTables * 8); // start of the table record
 
     var i, ii, j, jj;
@@ -18461,17 +18427,17 @@ var Font = (function FontClosure() {
         charCodeToGlyphId[0] = 0;
       }
 
       // Converting glyphs and ids into font's cmap table
       var newMapping = adjustMapping(charCodeToGlyphId, properties);
       this.toFontChar = newMapping.toFontChar;
       tables.cmap = {
         tag: 'cmap',
-        data: createCmapTable(newMapping.charCodeToGlyphId)
+        data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphs)
       };
 
       if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
         tables['OS/2'] = {
           tag: 'OS/2',
           data: createOS2Table(properties, newMapping.charCodeToGlyphId,
                                metricsOverride)
         };
@@ -18599,17 +18565,18 @@ var Font = (function FontClosure() {
 
       var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F');
       // PostScript Font Program
       builder.addTable('CFF ', font.data);
       // OS/2 and Windows Specific metrics
       builder.addTable('OS/2', createOS2Table(properties,
                                               newMapping.charCodeToGlyphId));
       // Character to glyphs mapping
-      builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId));
+      builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId,
+                       numGlyphs));
       // Font header
       builder.addTable('head',
             '\x00\x01\x00\x00' + // Version number
             '\x00\x00\x10\x00' + // fontRevision
             '\x00\x00\x00\x00' + // checksumAdjustement
             '\x5F\x0F\x3C\xF5' + // magicNumber
             '\x00\x00' + // Flags
             safeString16(unitsPerEm) + // unitsPerEM
@@ -31002,27 +30969,42 @@ var Lexer = (function LexerClosure() {
         }
         if (!charBuffered) {
           ch = this.nextChar();
         }
       }
       return strBuf.join('');
     },
     getName: function Lexer_getName() {
-      var ch;
+      var ch, previousCh;
       var strBuf = this.strBuf;
       strBuf.length = 0;
       while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
         if (ch === 0x23) { // '#'
           ch = this.nextChar();
+          if (specialChars[ch]) {
+            warn('Lexer_getName: ' +
+                 'NUMBER SIGN (#) should be followed by a hexadecimal number.');
+            strBuf.push('#');
+            break;
+          }
           var x = toHexDigit(ch);
           if (x !== -1) {
-            var x2 = toHexDigit(this.nextChar());
+            previousCh = ch;
+            ch = this.nextChar();
+            var x2 = toHexDigit(ch);
             if (x2 === -1) {
-              error('Illegal digit in hex char in name: ' + x2);
+              warn('Lexer_getName: Illegal digit (' +
+                   String.fromCharCode(ch) +') in hexadecimal number.');
+              strBuf.push('#', String.fromCharCode(previousCh));
+              if (specialChars[ch]) {
+                break;
+              }
+              strBuf.push(String.fromCharCode(ch));
+              continue;
             }
             strBuf.push(String.fromCharCode((x << 4) | x2));
           } else {
             strBuf.push('#', String.fromCharCode(ch));
           }
         } else {
           strBuf.push(String.fromCharCode(ch));
         }
@@ -34346,16 +34328,21 @@ var WorkerMessageHandler = PDFJS.WorkerM
           info('page=' + pageNum + ' - getOperatorList: time=' +
                (Date.now() - start) + 'ms, len=' + operatorList.totalLength);
         }, function(e) {
           finishWorkerTask(task);
           if (task.terminated) {
             return; // ignoring errors from the terminated thread
           }
 
+          // For compatibility with older behavior, generating unknown
+          // unsupported feature notification on errors.
+          handler.send('UnsupportedFeature',
+                       {featureId: UNSUPPORTED_FEATURES.unknown});
+
           var minimumStackMessage =
             'worker.js: while trying to getPage() and getOperatorList()';
 
           var wrappedException;
 
           // Turn the error into an obj that can be serialized
           if (typeof e === 'string') {
             wrappedException = {
@@ -34480,25 +34467,16 @@ var workerConsole = {
 
 
 // Worker thread?
 if (typeof window === 'undefined') {
   if (!('console' in globalScope)) {
     globalScope.console = workerConsole;
   }
 
-  // Listen for unsupported features so we can pass them on to the main thread.
-  PDFJS.UnsupportedManager.listen(function (msg) {
-    globalScope.postMessage({
-      targetName: 'main',
-      action: '_unsupported_feature',
-      data: msg
-    });
-  });
-
   var handler = new MessageHandler('worker', 'main', this);
   WorkerMessageHandler.setup(handler, this);
 }
 
 
 /* This class implements the QM Coder decoding as defined in
  *   JPEG 2000 Part I Final Committee Draft Version 1.0
  *   Annex C.3 Arithmetic decoding procedure
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -16,16 +16,17 @@
 .textLayer {
   position: absolute;
   left: 0;
   top: 0;
   right: 0;
   bottom: 0;
   overflow: hidden;
   opacity: 0.2;
+  line-height: 1.0;
 }
 
 .textLayer > div {
   color: transparent;
   position: absolute;
   white-space: pre;
   cursor: text;
   -moz-transform-origin: 0% 0%;
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -6508,16 +6508,19 @@ var PDFViewerApplication = {
       PasswordPrompt.reason = reason;
       PasswordPrompt.open();
     };
 
     loadingTask.onProgress = function getDocumentProgress(progressData) {
       self.progress(progressData.loaded / progressData.total);
     };
 
+    // Listen for unsupported features to trigger the fallback UI.
+    loadingTask.onUnsupportedFeature = this.fallback.bind(this);
+
     var result = loadingTask.promise.then(
       function getDocumentCallback(pdfDocument) {
         self.load(pdfDocument, scale);
       },
       function getDocumentError(exception) {
         var message = exception && exception.message;
         var loadingErrorMessage = mozL10n.get('loading_error', null,
           'An error occurred while loading the PDF.');
@@ -7243,20 +7246,16 @@ function webViewerInitialized() {
     document.getElementById('secondaryPresentationMode').
       classList.add('hidden');
   }
 
   if (PDFViewerApplication.supportsIntegratedFind) {
     document.getElementById('viewFind').classList.add('hidden');
   }
 
-  // Listen for unsupported features to trigger the fallback UI.
-  PDFJS.UnsupportedManager.listen(
-    PDFViewerApplication.fallback.bind(PDFViewerApplication));
-
   // Suppress context menus for some controls
   document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler;
 
   var mainContainer = document.getElementById('mainContainer');
   var outerContainer = document.getElementById('outerContainer');
   mainContainer.addEventListener('transitionend', function(e) {
     if (e.target === mainContainer) {
       var event = document.createEvent('UIEvents');
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -32,17 +32,17 @@
 !define AppRegName            "Firefox"
 
 !ifndef DEV_EDITION
 !define BrandShortName        "@MOZ_APP_DISPLAYNAME@"
 !endif
 !define BrandFullName         "${BrandFullNameInternal}"
 
 !define CERTIFICATE_NAME      "Mozilla Corporation"
-!define CERTIFICATE_ISSUER    "DigiCert SHA2 Assured ID Code Signing CA"
+!define CERTIFICATE_ISSUER    "DigiCert Assured ID Code Signing CA-1"
 
 # LSP_CATEGORIES is the permitted LSP categories for the application. Each LSP
 # category value is ANDed together to set multiple permitted categories.
 # See http://msdn.microsoft.com/en-us/library/ms742253%28VS.85%29.aspx
 # The value below removes all LSP categories previously set.
 !define LSP_CATEGORIES "0x00000000"
 
 !if "@MOZ_UPDATE_CHANNEL@" == ""
--- a/browser/installer/windows/nsis/maintenanceservice_installer.nsi
+++ b/browser/installer/windows/nsis/maintenanceservice_installer.nsi
@@ -215,17 +215,17 @@ Section "MaintenanceService"
   WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1
   WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Installed" 1
   DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled"
 
   ; Included here for debug purposes only.  
   ; These keys are used to bypass the installation dir is a valid installation
   ; check from the service so that tests can be run.
   ; WriteRegStr HKLM "${FallbackKey}\0" "name" "Mozilla Corporation"
-  ; WriteRegStr HKLM "${FallbackKey}\0" "issuer" "DigiCert SHA2 Assured ID Code Signing CA"
+  ; WriteRegStr HKLM "${FallbackKey}\0" "issuer" "DigiCert Assured ID Code Signing CA-1"
   ${If} ${RunningX64}
     SetRegView lastused
   ${EndIf}
 SectionEnd
 
 ; By renaming before deleting we improve things slightly in case
 ; there is a file in use error. In this case a new install can happen.
 Function un.RenameDelete
--- a/browser/locales/en-US/chrome/browser/aboutCertError.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutCertError.dtd
@@ -28,8 +28,9 @@ certificate.">
 
 <!ENTITY certerror.expert.content "If you understand what's going on, you
 can tell &brandShortName; to start trusting this site's identification.
 <b>Even if you trust the site, this error could mean that someone is
 tampering with your connection.</b>">
 <!ENTITY certerror.expert.contentPara2 "Don't add an exception unless
 you know there's a good reason why this site doesn't use trusted identification.">
 <!ENTITY certerror.addException.label "Add Exception…">
+<!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -796,14 +796,21 @@ muteTab.label = Mute Tab
 muteTab.accesskey = M
 unmuteTab.label = Unmute Tab
 unmuteTab.accesskey = M
 
 # LOCALIZATION NOTE (weakCryptoOverriding.message): %S is brandShortName
 weakCryptoOverriding.message = %S recommends that you don't enter your password, credit card and other personal information on this website.
 revokeOverride.label = Don't Trust This Website
 revokeOverride.accesskey = D
+# LOCALIZATION NOTE (certErrorDetails.label): This is a text string that
+# appears in the about:certerror page, so that the user can copy and send it to
+# the server administrators for troubleshooting. %1$S is the visited URL, %2$S
+# is the error message, %3$S is true or false, depending on whether the server
+# supports HSTS, %4$S is true or false, depending on whether the server
+# supports HPKP, %5$S is the certificate chain in PEM format.
+certErrorDetails.label = %1$S\r\n\r\n%2$S\r\n\r\nHTTP Strict Transport Security: %3$S\r\nHTTP Public Key Pinning: %4$S\r\n\r\nCertificate chain:\r\n\r\n%5$S
 
 # LOCALIZATION NOTE (tabgroups.migration.anonGroup):
 # %S is the group number/ID
 tabgroups.migration.anonGroup = Group %S
 tabgroups.migration.tabGroupBookmarkFolderName = Bookmarked Tab Groups
 
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -210,19 +210,19 @@ functionality specific to firefox. -->
 <!ENTITY errorReporting.sent "Report sent">
 <!ENTITY errorReporting.report "Report">
 <!ENTITY errorReporting.tryAgain "Try again">
 
 <!ENTITY remoteXUL.title "Remote XUL">
 <!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">
 
 <!ENTITY sslv3Used.title "Unable to Connect Securely">
-<!-- LOCALIZATION NOTE (sslv3Used.longDesc) - Do not translate
-     "ssl_error_unsupported_version". -->
-<!ENTITY sslv3Used.longDesc "Advanced info: ssl_error_unsupported_version">
+<!-- LOCALIZATION NOTE (sslv3Used.longDesc2) - Do not translate
+     "SSL_ERROR_UNSUPPORTED_VERSION". -->
+<!ENTITY sslv3Used.longDesc2 "Advanced info: SSL_ERROR_UNSUPPORTED_VERSION">
 
 <!ENTITY weakCryptoUsed.title "Your connection is not secure">
-<!-- LOCALIZATION NOTE (weakCryptoUsed.longDesc) - Do not translate
-     "ssl_error_no_cypher_overlap". -->
-<!ENTITY weakCryptoUsed.longDesc "Advanced info: ssl_error_no_cypher_overlap">
+<!-- LOCALIZATION NOTE (weakCryptoUsed.longDesc2) - Do not translate
+     "SSL_ERROR_NO_CYPHER_OVERLAP". -->
+<!ENTITY weakCryptoUsed.longDesc2 "Advanced info: SSL_ERROR_NO_CYPHER_OVERLAP">
 <!ENTITY weakCryptoAdvanced.title "Advanced">
 <!ENTITY weakCryptoAdvanced.longDesc "<span class='hostname'></span> uses security technology that is outdated and vulnerable to attack. An attacker could easily reveal information which you thought to be safe.">
 <!ENTITY weakCryptoAdvanced.override "(Not secure) Try loading <span class='hostname'></span> using outdated security">
--- a/browser/themes/shared/aboutCertError.css
+++ b/browser/themes/shared/aboutCertError.css
@@ -48,16 +48,37 @@ body {
   display: flex;
   flex-flow: row wrap;
 }
 
 #buttonSpacer {
   flex: 1;
 }
 
+#certificateErrorDebugInformation {
+  display: none;
+  background-color: var(--in-content-box-background-hover) !important;
+  border-top: 1px solid var(--in-content-border-color);
+  position: absolute;
+  left: 0%;
+  top: 100%;
+  width: 65%;
+  padding: 1em 17.5%;
+}
+
+#certificateErrorText {
+  font-family: monospace;
+  white-space: pre-wrap;
+  padding: 1em 0;
+}
+
+#errorCode {
+  white-space: nowrap;
+}
+
 #returnButton {
   background-color: var(--in-content-primary-button-background);
   border: none;
   color: var(--in-content-selected-text);
   min-width: 250px;
   margin-inline-start: 0;
 }
 
--- a/browser/themes/shared/aboutNetError.css
+++ b/browser/themes/shared/aboutNetError.css
@@ -168,8 +168,14 @@ div#weakCryptoAdvancedPanel {
 
 span#hostname {
   font-weight: bold;
 }
 
 #automaticallyReportInFuture {
   cursor: pointer;
 }
+
+#errorCode {
+  color: var(--in-content-page-color);
+  cursor: text;
+  text-decoration: none;
+}
--- a/mobile/android/base/resources/values-v21/themes.xml
+++ b/mobile/android/base/resources/values-v21/themes.xml
@@ -11,25 +11,30 @@
     <style name="GeckoBase" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="colorPrimary">@color/text_and_tabs_tray_grey</item>
         <item name="colorPrimaryDark">@color/text_and_tabs_tray_grey</item>
         <item name="windowActionBar">false</item>
         <item name="windowNoTitle">true</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:actionBarStyle">@style/GeckoActionBar</item>
         <!-- TODO (bug 1220863): Once we extend AppCompatActivity, set actionBarStyle. -->
+        <item name="android:alertDialogTheme">@style/GeckoAlertDialog</item>
     </style>
 
     <style name="GeckoPreferencesBase" parent="Gecko">
         <item name="android:windowActionBar">true</item>
         <item name="android:windowNoTitle">false</item>
         <item name="android:actionBarStyle">@style/ActionBar.GeckoPreferences</item>
         <item name="android:actionBarTheme">@style/ActionBarThemeGeckoPreferences</item>
     </style>
 
+    <style name="GeckoAlertDialog" parent="@android:style/Theme.Material.Light.Dialog.Alert">
+        <item name="android:colorAccent">@color/fennec_ui_orange</item>
+    </style>
+
     <style name="ActionBar.FxAccountStatusActivity" parent="@android:style/Widget.Material.ActionBar.Solid">
         <item name="android:displayOptions">homeAsUp|showTitle</item>
         <item name="android:titleTextStyle">@style/ActionBarTitleTextStyle</item>
     </style>
 
     <style name="ActionBar.GeckoPreferences" parent="@android:style/Widget.Material.ActionBar.Solid">
         <item name="android:titleTextStyle">@style/ActionBarTitleTextStyle</item>
     </style>
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -287,17 +287,18 @@ certErrorMismatchSinglePlain=The certifi
 certErrorMismatchMultiple=The certificate is only valid for the following names:
 certErrorMismatchNoNames=The certificate is not valid for any server names.
 
 # LOCALIZATION NOTE (certErrorExpiredNow): Do not translate %1$S (date+time of expired certificate) or %2$S (current date+time)
 certErrorExpiredNow=The certificate expired on %1$S. The current time is %2$S.
 # LOCALIZATION NOTE (certErrorNotYetValidNow): Do not translate %1$S (date+time certificate will become valid) or %2$S (current date+time)
 certErrorNotYetValidNow=The certificate will not be valid until %1$S. The current time is %2$S.
 
-certErrorCodePrefix=(Error code: %S)
+# LOCALIZATION NOTE (certErrorCodePrefix2): Do not translate <a id="errorCode" title="%1$S">%1$S</a>
+certErrorCodePrefix2=Error code: <a id="errorCode" title="%1$S">%1$S</a>
 
 CertInfoIssuedFor=Issued to:
 CertInfoIssuedBy=Issued by:
 CertInfoValid=Valid
 CertInfoFrom=from
 CertInfoTo=to
 CertInfoPurposes=Purposes
 CertInfoEmail=Email
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -1222,9 +1222,9 @@ static const TransportSecurityPreload kP
   { "za.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
   { "zh.search.yahoo.com", false, true, false, -1, &kPinset_yahoo },
 };
 
 // Pinning Preload List Length = 450;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1457563757796000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1457783716013000);
--- a/security/manager/ssl/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/TransportSecurityInfo.cpp
@@ -877,25 +877,24 @@ static void
 AppendErrorTextCode(PRErrorCode errorCodeToReport,
                     nsINSSComponent *component,
                     nsString &returnedMessage)
 {
   const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport);
   if (codeName)
   {
     nsCString error_id(codeName);
-    ToLowerCase(error_id);
     NS_ConvertASCIItoUTF16 idU(error_id);
 
     const char16_t *params[1];
     params[0] = idU.get();
 
     nsString formattedString;
     nsresult rv;
-    rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix", 
+    rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix2",
                                                   params, 1, 
                                                   formattedString);
     if (NS_SUCCEEDED(rv)) {
       returnedMessage.Append('\n');
       returnedMessage.Append(formattedString);
       returnedMessage.Append('\n');
     }
     else {
--- a/security/manager/ssl/nsNSSErrors.cpp
+++ b/security/manager/ssl/nsNSSErrors.cpp
@@ -73,24 +73,23 @@ nsNSSErrors::getErrorMessageFromCode(PRE
     returnedMessage.AppendASCII(PR_ErrorToString(err, PR_LANGUAGE_EN));
     returnedMessage.Append('\n');
   }
   
   if (nss_error_id_str)
   {
     nsresult rv;
     nsCString error_id(nss_error_id_str);
-    ToLowerCase(error_id);
     NS_ConvertASCIItoUTF16 idU(error_id);
 
     const char16_t *params[1];
     params[0] = idU.get();
 
     nsString formattedString;
-    rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix", 
+    rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix2",
                                                   params, 1, 
                                                   formattedString);
     if (NS_SUCCEEDED(rv)) {
       returnedMessage.Append('\n');
       returnedMessage.Append(formattedString);
       returnedMessage.Append('\n');
     }
     else {
--- a/security/manager/ssl/nsSTSPreloadList.errors
+++ b/security/manager/ssl/nsSTSPreloadList.errors
@@ -11,17 +11,16 @@ ad-notam.fr: did not receive HSTS header
 ad-notam.it: did not receive HSTS header
 ad-notam.us: did not receive HSTS header
 ada.is: max-age too low: 7776000
 adhs-chaoten.net: did not receive HSTS header
 admin.google.com: did not receive HSTS header (error ignored - included regardless)
 adsfund.org: could not connect to host
 aerolog.co: did not receive HSTS header
 aes256.ru: could not connect to host
-aevpn.net: could not connect to host
 aeyoun.com: did not receive HSTS header
 afp548.tk: could not connect to host
 agrimap.com: did not receive HSTS header
 agrios.de: did not receive HSTS header
 airbnb.com: did not receive HSTS header
 aiticon.de: did not receive HSTS header
 akclinics.org: did not receive HSTS header
 akselimedia.fi: did not receive HSTS header
@@ -44,17 +43,16 @@ api.mega.co.nz: could not connect to hos
 api.recurly.com: did not receive HSTS header
 apibot.de: could not connect to host
 apis.google.com: did not receive HSTS header (error ignored - included regardless)
 app.manilla.com: could not connect to host
 appengine.google.com: did not receive HSTS header (error ignored - included regardless)
 apps-for-fishing.com: could not connect to host
 appseccalifornia.org: did not receive HSTS header
 arrayify.com: max-age too low: 0
-artegusto.ru: could not connect to host
 at.search.yahoo.com: max-age too low: 172800
 atavio.at: could not connect to host
 atavio.ch: could not connect to host
 atavio.de: did not receive HSTS header
 au.search.yahoo.com: max-age too low: 172800
 aurainfosec.com: could not connect to host
 auraredeye.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 auraredshield.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
@@ -77,24 +75,24 @@ beautykat.ru: did not receive HSTS heade
 bedeta.de: could not connect to host
 belairsewvac.com: did not receive HSTS header
 beneffy.com: could not connect to host
 betnet.fr: could not connect to host
 bevapehappy.com: did not receive HSTS header
 bhatia.at: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 bi.search.yahoo.com: did not receive HSTS header
 bidon.ca: did not receive HSTS header
+bigbrownpromotions.com.au: could not connect to host
 bigdinosaur.org: did not receive HSTS header
 bigshinylock.minazo.net: could not connect to host
 bitfactory.ws: could not connect to host
 bitfarm-archiv.com: did not receive HSTS header
 bitfarm-archiv.de: did not receive HSTS header
 bitvigor.com: did not receive HSTS header
 bizon.sk: did not receive HSTS header
-bjornjohansen.no: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 blacklane.com: did not receive HSTS header
 blog.lookout.com: did not receive HSTS header
 blubbablasen.de: could not connect to host
 bluetenmeer.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 bochs.info: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 bodo-wolff.de: did not receive HSTS header
 bonigo.de: did not receive HSTS header
 bonitabrazilian.co.nz: did not receive HSTS header
@@ -151,18 +149,18 @@ clycat.ru: could not connect to host
 cn.search.yahoo.com: did not receive HSTS header
 co.search.yahoo.com: max-age too low: 172800
 code.google.com: did not receive HSTS header (error ignored - included regardless)
 codereview.chromium.org: did not receive HSTS header (error ignored - included regardless)
 coding.net: did not receive HSTS header
 coffeeetc.co.uk: could not connect to host
 coffeestrategies.com: did not receive HSTS header
 coindam.com: could not connect to host
+colognegaming.net: could not connect to host
 comdurav.com: did not receive HSTS header
-comssa.org.au: could not connect to host
 conformal.com: could not connect to host
 console.python.org: did not receive HSTS header
 cordial-restaurant.com: did not receive HSTS header
 core.mx: could not connect to host
 coursella.com: did not receive HSTS header
 cr.search.yahoo.com: did not receive HSTS header
 crate.io: did not receive HSTS header
 crbug.com: did not receive HSTS header
@@ -197,16 +195,17 @@ derevtsov.com: did not receive HSTS head
 derhil.de: did not receive HSTS header
 devh.de: did not receive HSTS header
 diablotine.rocks: could not connect to host
 diasp.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 digitaldaddy.net: could not connect to host
 digitalskillswap.com: could not connect to host
 dinamoelektrik.com: max-age too low: 0
 discovery.lookout.com: did not receive HSTS header
+dixmag.com: did not receive HSTS header
 dk.search.yahoo.com: max-age too low: 172800
 dl.google.com: did not receive HSTS header (error ignored - included regardless)
 do.search.yahoo.com: did not receive HSTS header
 docs.google.com: did not receive HSTS header (error ignored - included regardless)
 dohosting.ru: could not connect to host
 domaris.de: did not receive HSTS header
 dotadata.me: could not connect to host
 download.jitsi.org: did not receive HSTS header
@@ -224,17 +223,17 @@ ebaymotorssucks.com: max-age too low: 0
 ecake.in: could not connect to host
 ecdn.cz: could not connect to host
 ecg.fr: could not connect to host
 edelsteincosmetic.com: did not receive HSTS header
 edmodo.com: did not receive HSTS header
 egit.co: could not connect to host
 electromc.com: could not connect to host
 elimdengelen.com: did not receive HSTS header
-elmermx.ch: could not connect to host
+elitefishtank.com: did not receive HSTS header
 elnutricionista.es: did not receive HSTS header
 email.lookout.com: could not connect to host
 en-maktoob.search.yahoo.com: did not receive HSTS header
 encrypted.google.com: did not receive HSTS header (error ignored - included regardless)
 enterdev.co: did not receive HSTS header
 epoxate.com: did not receive HSTS header
 eroticen.com: did not receive HSTS header
 erotische-aanbiedingen.nl: did not receive HSTS header
@@ -263,30 +262,31 @@ fj.search.yahoo.com: did not receive HST
 floweslawncare.com: did not receive HSTS header
 fm83.nl: did not receive HSTS header
 fonetiq.io: could not connect to host
 food4health.guide: could not connect to host
 foreignexchangeresource.com: did not receive HSTS header
 fotiu.com: could not connect to host
 fr.search.yahoo.com: max-age too low: 172800
 fr33d0m.link: did not receive HSTS header
-freifunk-luenen.de: did not receive HSTS header
 froggstack.de: did not receive HSTS header
 frusky.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 g2g.com: did not receive HSTS header
 g4w.co: could not connect to host
 g4w.co: could not connect to host (error ignored - included regardless)
 gamenected.com: could not connect to host
 gamenected.de: could not connect to host
 gamesdepartment.co.uk: did not receive HSTS header
 gaptek.id: did not receive HSTS header
 geekandi.com: max-age too low: 7776000
 geekcast.co.uk: did not receive HSTS header
 getable.com: did not receive HSTS header
 getlantern.org: did not receive HSTS header
+getsport.mobi: did not receive HSTS header
+gfournier.ca: could not connect to host
 gfwsb.ml: could not connect to host
 gigacloud.org: could not connect to host
 gizzo.sk: could not connect to host
 gl.search.yahoo.com: did not receive HSTS header
 glass.google.com: did not receive HSTS header (error ignored - included regardless)
 glws.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 gm.search.yahoo.com: did not receive HSTS header
 gmail.com: did not receive HSTS header (error ignored - included regardless)
@@ -313,39 +313,40 @@ groups.google.com: did not receive HSTS 
 gtanda.tk: could not connect to host
 gtraxapp.com: could not connect to host
 gurusupe.com: could not connect to host
 gvt2.com: could not connect to host
 gvt2.com: could not connect to host (error ignored - included regardless)
 gvt3.com: could not connect to host
 gvt3.com: could not connect to host (error ignored - included regardless)
 gwijaya.com: did not receive HSTS header
+gyboche.com: could not connect to host
 gyboche.science: could not connect to host
 haber1903.com: did not receive HSTS header
 hack.li: could not connect to host
-hao2taiwan.com: max-age too low: 0
+hao2taiwan.com: did not receive HSTS header
 happyfabric.me: did not receive HSTS header
 hasilocke.de: did not receive HSTS header
 haste.ch: could not connect to host
 hatoko.net: could not connect to host
 haveeruexaminer.com: could not connect to host
 heart.ge: max-age too low: 0
 heftkaufen.de: did not receive HSTS header
 helpadmin.net: could not connect to host
 helpium.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 henriknoerr.com: could not connect to host
-herpaderp.net: could not connect to host
+herpaderp.net: did not receive HSTS header
 herzbotschaft.de: max-age too low: 0
 hexony.com: did not receive HSTS header
 hicn.gq: could not connect to host
 hk.search.yahoo.com: max-age too low: 172800
 hledejlevne.cz: did not receive HSTS header
 hn.search.yahoo.com: did not receive HSTS header
 hoerbuecher-und-hoerspiele.de: did not receive HSTS header
-homa.website: did not receive HSTS header
+homa.website: could not connect to host
 honeytracks.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 hookandloom.com: did not receive HSTS header
 horosho.in: could not connect to host
 horseboners.xxx: did not receive HSTS header
 hostedtalkgadget.google.com: did not receive HSTS header (error ignored - included regardless)
 howrandom.org: could not connect to host
 hsts.date: could not connect to host
 hstspreload.appspot.com: did not receive HSTS header
@@ -354,23 +355,25 @@ iban.is: could not connect to host
 id-co.in: could not connect to host
 id-conf.com: did not receive HSTS header
 id.search.yahoo.com: max-age too low: 172800
 identitylabs.uk: did not receive HSTS header
 ie.search.yahoo.com: did not receive HSTS header
 ilikerainbows.co.uk: could not connect to host
 illjinx.info: did not receive HSTS header
 ilmconpm.de: did not receive HSTS header
+imouto.my: max-age too low: 5184000
 in.search.yahoo.com: max-age too low: 172800
 inb4.us: could not connect to host
 inertianetworks.com: did not receive HSTS header
 infogrfx.com: max-age too low: 0
 inksupply.com: did not receive HSTS header
 inleaked.com: could not connect to host
 inmyarea.com: did not receive HSTS header
+instacart.com: did not receive HSTS header
 intercom.io: did not receive HSTS header
 interserved.com: did not receive HSTS header
 ionas-law.ro: did not receive HSTS header
 iop.intuit.com: max-age too low: 86400
 iostips.ru: could not connect to host
 ipmimagazine.com: did not receive HSTS header
 iraqidinar.org: did not receive HSTS header
 irccloud.com: did not receive HSTS header
@@ -380,17 +383,18 @@ it.search.yahoo.com: max-age too low: 17
 itshost.ru: could not connect to host
 ivk.website: could not connect to host
 izdiwho.com: could not connect to host
 j0s.at: did not receive HSTS header
 jamesdoylephoto.com: did not receive HSTS header
 janus-engineering.de: did not receive HSTS header
 jayblock.com: did not receive HSTS header
 jetaprices.com: max-age too low: 0
-jettshome.org: could not connect to host
+jhburton.co.uk: could not connect to host
+jimshaver.net: could not connect to host
 jkb.pics: could not connect to host
 jkbuster.com: could not connect to host
 jmdekker.it: could not connect to host
 johners.me: could not connect to host
 jonas-keidel.de: did not receive HSTS header
 jonathan.ir: did not receive HSTS header
 jottit.com: could not connect to host
 julian-kipka.de: did not receive HSTS header
@@ -410,22 +414,21 @@ kickass.al: could not connect to host
 kingmanhall.org: could not connect to host
 kirkforcongress.com: could not connect to host
 kirkforsenate.com: did not receive HSTS header
 kirkpatrickdavis.com: max-age too low: 3153600
 kitsta.com: could not connect to host
 kiwiirc.com: max-age too low: 5256000
 klaxn.com: could not connect to host
 klaxn.org: could not connect to host
-koerperimpuls.ch: could not connect to host
 komandakovalchuk.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 koop-bremen.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 koordinate.net: did not receive HSTS header
 korni22.org: did not receive HSTS header
-kpvpn.com: could not connect to host
+kpvpn.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 kr.search.yahoo.com: did not receive HSTS header
 krouzkyliduska.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 kryptera.se: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 kweddingplanning.com: did not receive HSTS header
 kz.search.yahoo.com: did not receive HSTS header
 labina.com.tr: did not receive HSTS header
 lachlankidson.net: did not receive HSTS header
 laf.in.net: did not receive HSTS header
@@ -476,16 +479,18 @@ megaplan.cz: did not receive HSTS header
 megashur.se: did not receive HSTS header
 megaxchange.com: did not receive HSTS header
 meinebo.it: could not connect to host
 members.mayfirst.org: did not receive HSTS header
 meta-db.com: could not connect to host
 miconcinemas.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 micropple.net: could not connect to host
 mijn-email.org: could not connect to host
+miku.hatsune.my: max-age too low: 5184000
+milanpala.cz: could not connect to host
 mindoktor.se: did not receive HSTS header
 minikneet.nl: could not connect to host
 minnesotadata.com: could not connect to host
 mirindadomo.ru: did not receive HSTS header
 mirrorx.com: did not receive HSTS header
 mitchellrenouf.ca: could not connect to host
 mnemotiv.com: could not connect to host
 mobilethreat.net: could not connect to host
@@ -496,17 +501,16 @@ moparisthebest.info: could not connect t
 moriz.net: did not receive HSTS header
 mp3gratuiti.com: did not receive HSTS header
 mp3juices.is: could not connect to host
 mqas.net: could not connect to host
 msc-seereisen.net: did not receive HSTS header
 mt.search.yahoo.com: did not receive HSTS header
 mu.search.yahoo.com: did not receive HSTS header
 musi.cx: did not receive HSTS header
-musikkfondene.no: could not connect to host
 mustika.cf: max-age too low: 0
 mutamatic.com: could not connect to host
 mw.search.yahoo.com: did not receive HSTS header
 mx.search.yahoo.com: max-age too low: 172800
 my.alfresco.com: did not receive HSTS header
 my.swedbank.se: max-age too low: 3024000
 mydigipass.com: did not receive HSTS header
 mygov.scot: could not connect to host
@@ -538,50 +542,48 @@ noexpect.org: could not connect to host
 noworrywp.com: did not receive HSTS header
 np.search.yahoo.com: did not receive HSTS header
 nu3.co.uk: did not receive HSTS header
 numericacu.com: did not receive HSTS header
 nutsandboltsmedia.com: did not receive HSTS header
 nz.search.yahoo.com: max-age too low: 172800
 nzb.cat: did not receive HSTS header
 ocrami.us: could not connect to host
-onixcco.com.br: did not receive HSTS header
 online.swedbank.se: max-age too low: 3024000
 ooonja.de: could not connect to host
 open-to-repair.fr: did not receive HSTS header
 opendesk.cc: did not receive HSTS header
 opennippon.com: could not connect to host
 openshift.redhat.com: did not receive HSTS header
 orhideous.name: could not connect to host
 ottospora.nl: could not connect to host
 ourbank.com: max-age too low: 604800
 ouvirmusica.com.br: did not receive HSTS header
-override.io: did not receive HSTS header
+override.io: could not connect to host
 ownmovies.fr: could not connect to host
 p.linode.com: could not connect to host
 p8r.de: could not connect to host
 pa.search.yahoo.com: did not receive HSTS header
-pantsu.cat: could not connect to host
+pantsu.cat: did not receive HSTS header
 partyvan.it: could not connect to host
 partyvan.nl: could not connect to host
 partyvan.se: could not connect to host
 passwordbox.com: did not receive HSTS header
 passwords.google.com: did not receive HSTS header (error ignored - included regardless)
 paste.linode.com: could not connect to host
 pastebin.linode.com: could not connect to host
 patterson.mp: could not connect to host
 pbprint.ru: max-age too low: 0
 pctonic.net: did not receive HSTS header
 pe.search.yahoo.com: max-age too low: 172800
 perfectionis.me: could not connect to host
 personaldatabasen.no: could not connect to host
 petersmark.com: did not receive HSTS header
 petrolplus.ru: did not receive HSTS header
 pfd-nz.com: did not receive HSTS header
-pgmann.cf: could not connect to host
 ph.search.yahoo.com: max-age too low: 172800
 phongmay24h.com: could not connect to host
 phurl.de: could not connect to host
 picksin.club: could not connect to host
 pinesandneedles.com: did not receive HSTS header
 piratenlogin.de: could not connect to host
 pirati.cz: max-age too low: 604800
 pisidia.de: did not receive HSTS header
@@ -596,63 +598,64 @@ pol.in.th: could not connect to host
 popcorntime.ws: did not receive HSTS header
 pr.search.yahoo.com: did not receive HSTS header
 preissler.co.uk: could not connect to host
 pressfreedomfoundation.org: did not receive HSTS header
 prodpad.com: did not receive HSTS header
 production.vn: did not receive HSTS header
 promecon-gmbh.de: did not receive HSTS header
 prontolight.com: did not receive HSTS header
+proximato.com: could not connect to host
 proxybay.club: did not receive HSTS header
 proxybay.info: did not receive HSTS header
 pult.co: could not connect to host
 punchr-kamikazee.rhcloud.com: did not receive HSTS header
 py.search.yahoo.com: did not receive HSTS header
 qc.search.yahoo.com: max-age too low: 172800
 qingxuan.info: did not receive HSTS header
 qvitoo.com: did not receive HSTS header
 raiseyourflag.com: did not receive HSTS header
 rapidresearch.me: could not connect to host
 rasing.me: could not connect to host
-raspass.me: could not connect to host
 ravchat.com: did not receive HSTS header
 rawstorieslondon.com: could not connect to host
 raydobe.me: could not connect to host
-realmofespionage.com: could not connect to host
 reddiseals.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 redlatam.org: did not receive HSTS header
-redports.org: did not receive HSTS header
+redports.org: could not connect to host
 regenerescence.com: did not receive HSTS header
 renem.net: max-age too low: 0
-renuo.ch: did not receive HSTS header
 reserve-online.net: did not receive HSTS header
+reviews.anime.my: max-age too low: 5184000
 rika.me: could not connect to host
 rippleunion.com: did not receive HSTS header
+rme.li: did not receive HSTS header
 ro.search.yahoo.com: max-age too low: 172800
 roan24.pl: did not receive HSTS header
 roddis.net: did not receive HSTS header
 romans-place.me.uk: did not receive HSTS header
 ronvandordt.info: could not connect to host
 roosterpgplus.nl: did not receive HSTS header
 rr.in.th: could not connect to host
 ru-sprachstudio.ch: could not connect to host
 ru.search.yahoo.com: max-age too low: 172800
 rudloff.pro: did not receive HSTS header
 rugirlfriend.com: did not receive HSTS header
 rusl.me: did not receive HSTS header
 rw.search.yahoo.com: did not receive HSTS header
 sah3.net: could not connect to host
+sakaki.anime.my: max-age too low: 5184000
 salserocafe.com: could not connect to host
 salserototal.com: did not receive HSTS header
-sanhei.ch: could not connect to host
 saturngames.co.uk: could not connect to host
 savetheinternet.eu: did not receive HSTS header
 schallert.com: did not receive HSTS header
 schnell-gold.com: could not connect to host
 schoop.me: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
+schorel.ovh: could not connect to host
 schreiber-netzwerk.eu: did not receive HSTS header
 scrambl.is: could not connect to host
 scrambler.in: could not connect to host
 screenlight.tv: did not receive HSTS header
 scribe.systems: could not connect to host
 script.google.com: did not receive HSTS header (error ignored - included regardless)
 sdsl-speedtest.de: could not connect to host
 se.search.yahoo.com: max-age too low: 172800
@@ -661,17 +664,17 @@ security.google.com: did not receive HST
 selectel.ru: did not receive HSTS header
 sello.com: did not receive HSTS header
 semenkovich.com: did not receive HSTS header
 seomobo.com: did not receive HSTS header
 seowarp.net: max-age too low: 1576800
 serverdensity.io: did not receive HSTS header
 servergno.me: did not receive HSTS header
 sg.search.yahoo.com: max-age too low: 172800
-shamka.ru: could not connect to host
+shamka.ru: max-age too low: 0
 shanewadleigh.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 shiinko.com: could not connect to host
 shoprose.ru: did not receive HSTS header
 shops.neonisi.com: could not connect to host
 siammedia.co: did not receive HSTS header
 sifls.com: could not connect to host
 silentcircle.org: could not connect to host
 simon.butcher.name: max-age too low: 2629743
@@ -697,42 +700,42 @@ spreadsheets.google.com: did not receive
 ssl.google-analytics.com: did not receive HSTS header (error ignored - included regardless)
 ssl.panoramio.com: did not receive HSTS header
 stassi.ch: did not receive HSTS header
 stillyarts.com: did not receive HSTS header
 stocktrade.de: could not connect to host
 streamingmagazin.de: could not connect to host
 strongest-privacy.com: could not connect to host
 studydrive.net: did not receive HSTS header
+stupus.com: could not connect to host
 subrosa.io: could not connect to host
 suite73.org: could not connect to host
 sunshinepress.org: could not connect to host
 support.mayfirst.org: did not receive HSTS header
 surfeasy.com: did not receive HSTS header
 suzukikenichi.com: did not receive HSTS header
 sv.search.yahoo.com: did not receive HSTS header
-sweetll.me: could not connect to host
 syncer.jp: did not receive HSTS header
-szaydon.me: could not connect to host
 t.facebook.com: did not receive HSTS header
 tablet.facebook.com: did not receive HSTS header
 tafoma.com: did not receive HSTS header
 tageau.com: did not receive HSTS header
 taglondon.org: did not receive HSTS header
 talk.google.com: could not connect to host
 talk.google.com: could not connect to host (error ignored - included regardless)
 tallshoe.com: could not connect to host
 tandarts-haarlem.nl: did not receive HSTS header
 tanzhijun.com: did not receive HSTS header
 tapka.cz: did not receive HSTS header
 tazemama.biz: did not receive HSTS header
 tbarter.com: did not receive HSTS header
 techhub.ml: could not connect to host
 technotonic.com.au: did not receive HSTS header
 tegelsensanitaironline.nl: did not receive HSTS header
+tekshrek.com: did not receive HSTS header
 tektoria.de: did not receive HSTS header
 temehu.com: did not receive HSTS header
 terrax.berlin: could not connect to host
 terrax.info: could not connect to host
 terrty.net: could not connect to host
 th.search.yahoo.com: max-age too low: 172800
 the-sky-of-valkyries.com: could not connect to host
 thecoffeehouse.xyz: could not connect to host
@@ -741,118 +744,126 @@ therapyportal.com: did not receive HSTS 
 thorncreek.net: did not receive HSTS header
 thumbtack.com: did not receive HSTS header
 timotrans.de: did not receive HSTS header
 timotrans.eu: did not receive HSTS header
 tinyvpn.net: could not connect to host
 tinyvpn.org: could not connect to host
 tirex.media: did not receive HSTS header
 titties.ml: could not connect to host
-tls.li: could not connect to host
+tlo.xyz: did not receive HSTS header
 tm-solutions.eu: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 tollmanz.com: did not receive HSTS header
 tollsjekk.no: did not receive HSTS header
 tomfisher.eu: could not connect to host
+tomrichards.net: did not receive HSTS header
 topbargains.com.au: did not receive HSTS header
 topodin.com: did not receive HSTS header
 topshelfguild.com: could not connect to host
+tosecure.link: could not connect to host
 totem-eshop.cz: could not connect to host
 tr.search.yahoo.com: max-age too low: 172800
 track.plus: did not receive HSTS header
+tracktivity.com.au: could not connect to host
 tradingcentre.com.au: did not receive HSTS header
 translate.googleapis.com: did not receive HSTS header (error ignored - included regardless)
 translatoruk.co.uk: did not receive HSTS header
 trendberry.ru: did not receive HSTS header
 trinitycore.org: max-age too low: 2592000
 trybind.com: could not connect to host
 tuturulianda.com: could not connect to host
 tv.search.yahoo.com: could not connect to host
 tw.search.yahoo.com: max-age too low: 172800
 twist.party: could not connect to host
 ua.search.yahoo.com: did not receive HSTS header
 ubicv.com: max-age too low: 0
 uega.net: did not receive HSTS header
 uk.search.yahoo.com: max-age too low: 172800
-ukas.com: did not receive HSTS header
+ukas.com: could not connect to host
 unapp.me: could not connect to host
 unbanthe.net: did not receive HSTS header
 univz.com: could not connect to host
 uonstaffhub.com: could not connect to host
 upay.ru: did not receive HSTS header
 uprotect.it: could not connect to host
 urandom.eu.org: could not connect to host
 ustr.gov: max-age too low: 86400
 uy.search.yahoo.com: did not receive HSTS header
 uz.search.yahoo.com: did not receive HSTS header
 vaddder.com: could not connect to host
 vallis.net: could not connect to host
+vasanth.org: could not connect to host
 vbhelp.org: could not connect to host
 vbulletin-russia.com: could not connect to host
 vbulletinrussia.com: could not connect to host
 ve.search.yahoo.com: max-age too low: 172800
 vermontcareergateway.org: did not receive HSTS header
 vhost.co.id: could not connect to host
 viennan.net: could not connect to host
 vmrdev.com: could not connect to host
 vn.search.yahoo.com: max-age too low: 172800
 voliere-info.nl: did not receive HSTS header
 vortexhobbies.com: did not receive HSTS header
 votocek.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 votockova.cz: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 vyncke.org: max-age too low: 2678400
 vzk.io: could not connect to host
 waze.com: max-age too low: 0
-webandwords.com.au: could not connect to host
 webassadors.com: could not connect to host
 webeau.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 webmail.mayfirst.org: did not receive HSTS header
 webmaniabr.com: did not receive HSTS header
 webswitch.io: could not connect to host
 werdeeintimo.de: did not receive HSTS header
 wevahoo.com: could not connect to host
 when-release.com: did not receive HSTS header
 whitestagforge.com: did not receive HSTS header
 wholebites.com: did not receive HSTS header
+whyworldhot.com: did not receive HSTS header
 wikidsystems.com: did not receive HSTS header
 wilf1rst.com: could not connect to host
 withgoogle.com: did not receive HSTS header (error ignored - included regardless)
 withustrading.com: could not connect to host
 withyoutube.com: did not receive HSTS header (error ignored - included regardless)
 wiz.biz: could not connect to host
 wohnungsbau-ludwigsburg.de: did not receive HSTS header
+woima.fi: max-age too low: 604800
 wover.me: did not receive HSTS header
 www.apollo-auto.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 www.calyxinstitute.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 www.cueup.com: could not connect to host
 www.developer.mydigipass.com: could not connect to host
 www.elanex.biz: did not receive HSTS header
 www.gmail.com: did not receive HSTS header (error ignored - included regardless)
 www.googlemail.com: did not receive HSTS header (error ignored - included regardless)
 www.greplin.com: could not connect to host
 www.jitsi.org: did not receive HSTS header
 www.ledgerscope.net: max-age too low: 86400
 www.logentries.com: did not receive HSTS header
 www.moneybookers.com: did not receive HSTS header
 www.neonisi.com: could not connect to host
 www.paycheckrecords.com: max-age too low: 86400
+www.rme.li: did not receive HSTS header
 www.sandbox.mydigipass.com: could not connect to host
 www.surfeasy.com: did not receive HSTS header
 xa.search.yahoo.com: did not receive HSTS header
 xavierbarroso.com: did not receive HSTS header
 xellos.ml: could not connect to host
 xiaody.me: could not connect to host
 xplore-dna.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
 xtream-hosting.com: could not connect to host
 xtream-hosting.de: could not connect to host
 xtream-hosting.eu: could not connect to host
 xtreamhosting.eu: could not connect to host
 y-o-w.com: did not receive HSTS header
+yaporn.tv: max-age too low: 0
 yenniferallulli.moda: could not connect to host
 yetii.net: did not receive HSTS header
 yingyj.com: did not receive HSTS header
+yobst.tk: could not connect to host
 yokeepo.com: max-age too low: 0
 yoloprod.fr: could not connect to host
 yoloseo.com: could not connect to host
 za.search.yahoo.com: did not receive HSTS header
 zachborboa.com: did not receive HSTS header
 zarooba.com: did not receive HSTS header
 zeitpunkt-kulturmagazin.de: did not receive HSTS header
 zenpayroll.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 134"  data: no]
--- a/security/manager/ssl/nsSTSPreloadList.inc
+++ b/security/manager/ssl/nsSTSPreloadList.inc
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsSiteSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
 #include <stdint.h>
-const PRTime gPreloadListExpirationTime = INT64_C(1459982816394000);
+const PRTime gPreloadListExpirationTime = INT64_C(1460202777312000);
 
 class nsSTSPreload
 {
   public:
     const char *mHost;
     const bool mIncludeSubdomains;
 };
 
@@ -176,17 +176,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "anonym-surfen.de", true },
   { "another.ch", true },
   { "ansdell.net", true },
   { "antipolygraph.org", true },
   { "antoniomarques.eu", true },
   { "anzeiger.ag", true },
   { "aojf.fr", true },
   { "apachehaus.de", false },
-  { "apadvantage.com", false },
+  { "apadvantage.com", true },
   { "api.intercom.io", false },
   { "api.lookout.com", false },
   { "api.simple.com", false },
   { "api.xero.com", false },
   { "apibot.de", true },
   { "apis.google.com", true },
   { "apn-einstellungen.de", true },
   { "apnakliyat.com", true },
@@ -773,17 +773,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "dime-staging.com", true },
   { "dirkwolf.de", true },
   { "discoveringdocker.com", true },
   { "disking.co.uk", true },
   { "disorderboutique.com", true },
   { "dissimulo.me", true },
   { "dist.torproject.org", false },
   { "diversityflags.com", true },
-  { "dixmag.com", false },
   { "dl.google.com", true },
   { "dlc.viasinc.com", true },
   { "dlscomputers.com.au", true },
   { "dm.lookout.com", false },
   { "dm.mylookout.com", false },
   { "dn42.us", true },
   { "dnmlab.it", true },
   { "dnscrypt.org", true },
@@ -880,17 +879,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "ehipaa.com", true },
   { "ehipaadev.com", true },
   { "eksisozluk.com", true },
   { "electronic-ignition-system.com", true },
   { "eleicoes2016.com.br", true },
   { "elenag.ga", true },
   { "elephpant.cz", true },
   { "elisa.ee", true },
-  { "elitefishtank.com", true },
   { "elitegameservers.net", true },
   { "elitehosting.de", true },
   { "ellegaard.dk", true },
   { "elliquiy.com", true },
   { "ellsinger.me", true },
   { "elmermx.ch", true },
   { "elsitar.com", true },
   { "elvidence.com.au", true },
@@ -1025,17 +1023,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "firma-offshore.com", true },
   { "firmapi.com", true },
   { "firstlook.org", true },
   { "fischer-its.com", true },
   { "fish-hook.ru", true },
   { "fitkram.cz", true },
   { "fj.simple.com", false },
   { "flagspot.net", true },
-  { "flamer-scene.com", true },
+  { "flamer-scene.com", false },
   { "flamewall.net", false },
   { "flamingkeys.com", true },
   { "fleximus.org", false },
   { "flipagram.com", false },
   { "flirchi.com", false },
   { "floobits.com", true },
   { "florian-lillpopp.de", true },
   { "florianlillpopp.de", true },
@@ -1068,16 +1066,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "freelance.boutique", true },
   { "freenetproject.org", true },
   { "freeshell.de", true },
   { "freesounding.com", true },
   { "freesounding.ru", true },
   { "freethought.org.au", true },
   { "freeweibo.com", true },
   { "freifunk-essen.de", true },
+  { "freifunk-luenen.de", false },
   { "fresh-hotel.org", true },
   { "fretscha.com", true },
   { "friendica.ch", true },
   { "frillip.com", true },
   { "fronteers.nl", true },
   { "frtr.gov", true },
   { "fruchthof24.de", true },
   { "fruitusers.com", true },
@@ -1132,17 +1131,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "getdash.io", true },
   { "getdigitized.net", true },
   { "getfedora.org", true },
   { "getfittedstore.com", true },
   { "getmango.com", true },
   { "getnikola.com", true },
   { "getsello.com", true },
   { "getspire.com", true },
-  { "getsport.mobi", true },
   { "gfournier.ca", true },
   { "ggp2.com", true },
   { "gheorghesarcov.ga", true },
   { "ghostblog.info", true },
   { "giacomopelagatti.it", true },
   { "giftservices.nl", true },
   { "gigacloud.org", true },
   { "gipsamsfashion.com", true },
@@ -1281,17 +1279,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "helpadmin.net", true },
   { "helpium.de", true },
   { "hemlockhillscabinrentals.com", true },
   { "hencagon.com", true },
   { "henriknoerr.com", true },
   { "heppler.net", true },
   { "herbert.io", true },
   { "herocentral.de", true },
-  { "herpaderp.net", true },
   { "hetmer.com", true },
   { "heute-kaufen.de", true },
   { "heutger.net", true },
   { "hex2013.com", true },
   { "hg.python.org", true },
   { "hicn.gq", true },
   { "hicoria.com", true },
   { "hilahdih.cz", true },
@@ -1374,17 +1371,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "imagr.io", true },
   { "imbrian.org", true },
   { "imgg.es", true },
   { "imirhil.fr", true },
   { "immoverkauf24.at", true },
   { "immoverkauf24.de", true },
   { "immunicity.info", true },
   { "imoni-blog.net", true },
-  { "imouto.my", false },
   { "impex.com.bd", true },
   { "in.xero.com", false },
   { "inb4.us", true },
   { "inbitcoin.it", true },
   { "inbounder.io", true },
   { "inbox.google.com", true },
   { "incparadise.net", true },
   { "indiecert.net", true },
@@ -1398,17 +1394,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "inkbunny.net", true },
   { "inleaked.com", true },
   { "innophate-security.com", true },
   { "innophate-security.nl", true },
   { "insideaudit.com", true },
   { "insighti.org", true },
   { "insouciant.org", true },
   { "inspiroinc.com", true },
-  { "instacart.com", true },
   { "instant-hack.com", true },
   { "instasex.ch", true },
   { "instela.com", true },
   { "institutolancaster.com", true },
   { "intarweb.ca", true },
   { "integrationinc.com", false },
   { "integromat.com", true },
   { "interasistmen.se", true },
@@ -1471,17 +1466,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "jaroslavtrsek.cz", true },
   { "jav-collective.com", true },
   { "jbn.mx", true },
   { "jeff393.com", true },
   { "jelmer.co.uk", true },
   { "jelmer.uk", true },
   { "jennedebleser.com", true },
   { "jeremyness.com", true },
-  { "jettshome.org", true },
+  { "jettshome.org", false },
   { "jfreitag.de", true },
   { "jgid.de", true },
   { "jh-media.eu", false },
   { "jhalderm.com", true },
   { "jhburton.co.uk", true },
   { "jimshaver.net", true },
   { "jinbo123.com", true },
   { "jira.com", true },
@@ -1865,17 +1860,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "miconcinemas.com", true },
   { "micro-rain-systems.com", true },
   { "mig5.net", true },
   { "mijn-email.org", true },
   { "mikaela.info", true },
   { "mike-bland.com", true },
   { "miketabor.com", true },
   { "mikewest.org", true },
-  { "miku.hatsune.my", false },
   { "milahendri.com", false },
   { "milanpala.cz", true },
   { "millistream.com", true },
   { "mim.properties", true },
   { "mimeit.de", true },
   { "mimovrste.com", true },
   { "mindcoding.ro", true },
   { "minecraftforum.de", true },
@@ -1987,17 +1981,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "mylookout.com", false },
   { "myni.io", true },
   { "mynigma.org", true },
   { "mypagella.com", true },
   { "mypagella.eu", true },
   { "mypagella.it", true },
   { "myplaceonline.com", true },
   { "myprintcard.de", true },
-  { "myraytech.net", true },
+  { "myraytech.net", false },
   { "mysecretcase.com", true },
   { "mysecretrewards.com", true },
   { "myvirtualserver.com", true },
   { "n-pix.com", false },
   { "nachsendeauftrag.net", true },
   { "nachsenden.info", true },
   { "nagb.gov", true },
   { "nagb.org", true },
@@ -2119,16 +2113,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "omacostudio.com", true },
   { "omitech.co.uk", true },
   { "onedot.nl", true },
   { "onedrive.com", true },
   { "onedrive.live.com", false },
   { "onespiritinc.com", true },
   { "onet.space", true },
   { "onewpst.com", false },
+  { "onixcco.com.br", true },
   { "only-roses.com", true },
   { "onsitemassageco.com", true },
   { "ontimestamp.com", true },
   { "ooonja.de", true },
   { "oopsmycase.com", true },
   { "openacademies.com", true },
   { "openkvk.nl", true },
   { "opennippon.com", true },
@@ -2161,17 +2156,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "pacoda.de", true },
   { "pactf.com", true },
   { "pagure.io", true },
   { "pagure.org", true },
   { "pajonzeck.de", true },
   { "palava.tv", true },
   { "panoti.com", true },
   { "panthur.com.au", false },
-  { "pantsu.cat", true },
   { "pap.la", false },
   { "parasitologyclub.org", true },
   { "paratlan.hu", true },
   { "parent5446.us", true },
   { "parsemail.org", true },
   { "partyvan.eu", true },
   { "partyvan.it", true },
   { "partyvan.nl", true },
@@ -2407,30 +2401,30 @@ static const nsSTSPreload kSTSPreloadLis
   { "regar42.fr", false },
   { "reishunger.de", true },
   { "release-monitoring.org", true },
   { "reliable-mail.de", true },
   { "remotestance.com", true },
   { "remoteutilities.com", true },
   { "renlong.org", true },
   { "rentinsingapore.com.sg", true },
+  { "renuo.ch", true },
   { "repaxan.com", true },
   { "report-uri.com", true },
   { "report-uri.io", true },
   { "reporturi.com", true },
   { "reporturi.io", true },
   { "research.facebook.com", false },
   { "research.md", true },
   { "residentsinsurance.co.uk", true },
   { "resources.flowfinity.com", true },
   { "respice.xyz", true },
   { "retroarms.com", true },
   { "retroarms.cz", true },
   { "reucon.com", true },
-  { "reviews.anime.my", true },
   { "rewardstock.com", true },
   { "riccy.org", true },
   { "richardwarrender.com", true },
   { "richiemail.net", true },
   { "ricki-z.com", true },
   { "ricochet.im", true },
   { "rid-wan.com", true },
   { "rideworks.com", true },
@@ -2443,17 +2437,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "rischard.org", true },
   { "riseup.net", true },
   { "riskmitigation.ch", true },
   { "ristioja.ee", true },
   { "rivy.org", true },
   { "rj.gg", true },
   { "rlalique.com", true },
   { "rmb.li", true },
-  { "rme.li", false },
   { "rmmanfredi.com", true },
   { "rngmeme.com", true },
   { "robandjanine.com", true },
   { "robertglastra.com", true },
   { "roberthurlbut.com", true },
   { "robertof.ovh", true },
   { "robi-net.it", true },
   { "robinadr.com", true },
@@ -2511,17 +2504,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "s-c.se", true },
   { "sabahattin-gucukoglu.com", true },
   { "safar.sk", true },
   { "safematix.com", true },
   { "safescan.com", true },
   { "sagerus.com", true },
   { "sageth.com", true },
   { "saintsrobotics.com", true },
-  { "sakaki.anime.my", true },
   { "salaervergleich.com", true },
   { "sale4ru.ru", true },
   { "salserocafe.com", true },
   { "samba.org", true },
   { "sambeso.net", true },
   { "samegoal.com", true },
   { "samegoal.org", true },
   { "samfunnet.no", false },
@@ -2862,17 +2854,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "techandtux.de", true },
   { "techcentric.com", false },
   { "techhipster.net", true },
   { "techhub.ml", true },
   { "techllage.com", true },
   { "techloaner.com", true },
   { "techvalue.gr", true },
   { "tehrabbitt.com", true },
-  { "tekshrek.com", true },
   { "temp.pm", true },
   { "tempus-aquilae.de", true },
   { "tent.io", true },
   { "terraelectronica.ru", true },
   { "terraweb.net", true },
   { "terrax.info", true },
   { "terrax.net", true },
   { "terrty.net", true },
@@ -2932,17 +2923,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "tinte24.de", true },
   { "tintenfix.net", true },
   { "tinyvpn.net", true },
   { "tinyvpn.org", true },
   { "tipps-fuer-den-haushalt.de", true },
   { "tipsyk.ru", true },
   { "tittelbach.at", true },
   { "tlo.link", true },
-  { "tlo.xyz", true },
   { "tls.li", true },
   { "tls1914.org", true },
   { "tm-solutions.eu", true },
   { "tmtopup.com", true },
   { "tncnanet.com.br", true },
   { "tno.io", true },
   { "tobias-kluge.de", true },
   { "tobiassachs.de", true },
@@ -2951,17 +2941,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "tokke.dk", true },
   { "tom.horse", true },
   { "tomasjacik.cz", true },
   { "tomfisher.eu", true },
   { "tomharling.co.uk", true },
   { "tomharling.uk", true },
   { "tomli.me", true },
   { "tomo.gr", false },
-  { "tomrichards.net", true },
   { "tomvote.com", true },
   { "toner24.at", true },
   { "toner24.co.uk", true },
   { "toner24.es", true },
   { "toner24.fr", true },
   { "toner24.it", true },
   { "toner24.nl", true },
   { "toner24.pl", true },
@@ -3205,17 +3194,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "when-release.ru", false },
   { "when.fm", true },
   { "wherephoto.com", true },
   { "whey-protein.ch", true },
   { "whispeer.de", true },
   { "whitehouse.gov", true },
   { "whocalld.com", true },
   { "whonix.org", true },
-  { "whyworldhot.com", true },
   { "widememory.com", true },
   { "wieninternational.at", true },
   { "wifirst.net", true },
   { "wiire.me", true },
   { "wiki.python.org", true },
   { "wikibooks.org", true },
   { "wikidata.org", true },
   { "wikimediafoundation.org", true },
@@ -3240,17 +3228,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "witae.com", true },
   { "withgoogle.com", true },
   { "withinsecurity.com", true },
   { "withyoutube.com", true },
   { "wjglerum.nl", true },
   { "wm-talk.net", true },
   { "wo2forum.nl", true },
   { "wohnsitz-ausland.com", true },
-  { "woima.fi", false },
   { "wolfemg.com", true },
   { "wonderhost.info", true },
   { "wondershift.biz", true },
   { "woodlandschurch.net", true },
   { "woodlandsmetro.church", true },
   { "wootton95.com", true },
   { "worcesterfestival.co.uk", true },
   { "wordsmart.it", true },
@@ -3305,17 +3292,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "www.lookout.com", false },
   { "www.makeyourlaws.org", true },
   { "www.mydigipass.com", false },
   { "www.mylookout.com", false },
   { "www.noisebridge.net", false },
   { "www.opsmate.com", true },
   { "www.paypal.com", false },
   { "www.python.org", true },
-  { "www.rme.li", false },
   { "www.roddis.net", true },
   { "www.schokokeks.org", true },
   { "www.simbolo.co.uk", false },
   { "www.simple.com", false },
   { "www.therapynotes.com", true },
   { "www.tinfoilsecurity.com", false },
   { "www.torproject.org", false },
   { "www.twitter.com", false },
@@ -3366,17 +3352,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "xtremegaming.it", true },
   { "xtrim.ru", true },
   { "xunn.io", true },
   { "xuntier.ch", true },
   { "yafuoku.ru", true },
   { "yahvehyireh.com", true },
   { "yamaken.jp", true },
   { "yanovich.net", true },
-  { "yaporn.tv", false },
   { "yello.website", true },
   { "yenniferallulli.com", true },
   { "yenniferallulli.de", true },
   { "yenniferallulli.es", true },
   { "yenniferallulli.moda", true },
   { "yenniferallulli.nl", true },
   { "yetcore.io", true },
   { "yippie.nl", true },
copy from browser/.eslintrc
copy to storage/.eslintrc
--- a/storage/test/unit/head_storage.js
+++ b/storage/test/unit/head_storage.js
@@ -11,16 +11,18 @@ Cu.import("resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
     "resource://gre/modules/Promise.jsm");
 
 
 do_get_profile();
 var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties);
 
+var gDBConn = null;
+
 function getTestDB()
 {
   var db = dirSvc.get("ProfD", Ci.nsIFile);
   db.append("test_storage.sqlite");
   return db;
 }
 
 /**
@@ -48,54 +50,52 @@ function cleanup()
   // we need to null out the database variable to get a new connection the next
   // time getOpenedDatabase is called
   gDBConn = null;
 
   // removing test db
   print("*** Storage Tests: Trying to remove file!");
   var dbFile = getTestDB();
   if (dbFile.exists())
-    try { dbFile.remove(false); } catch(e) { /* stupid windows box */ }
+    try { dbFile.remove(false); } catch (e) { /* stupid windows box */ }
 }
 
 /**
  * Use asyncClose to cleanup a connection.  Synchronous by means of internally
  * spinning an event loop.
  */
 function asyncCleanup()
 {
   let closed = false;
 
   // close the connection
   print("*** Storage Tests: Trying to asyncClose!");
-  getOpenedDatabase().asyncClose(function() { closed = true; });
+  getOpenedDatabase().asyncClose(function () { closed = true; });
 
   let curThread = Components.classes["@mozilla.org/thread-manager;1"]
                             .getService().currentThread;
   while (!closed)
     curThread.processNextEvent(true);
 
   // we need to null out the database variable to get a new connection the next
   // time getOpenedDatabase is called
   gDBConn = null;
 
   // removing test db
   print("*** Storage Tests: Trying to remove file!");
   var dbFile = getTestDB();
   if (dbFile.exists())
-    try { dbFile.remove(false); } catch(e) { /* stupid windows box */ }
+    try { dbFile.remove(false); } catch (e) { /* stupid windows box */ }
 }
 
 function getService()
 {
   return Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService);
 }
 
-var gDBConn = null;
-
 /**
  * Get a connection to the test database.  Creates and caches the connection
  * if necessary, otherwise reuses the existing cached connection. This
  * connection shares its cache.
  *
  * @returns the mozIStorageConnection for the file.
  */
 function getOpenedDatabase()
@@ -164,17 +164,17 @@ function createAsyncStatement(aSQL)
  *        The function to invoke and expect an XPCOM-style error from.
  */
 function expectError(aErrorCode, aFunction)
 {
   let exceptionCaught = false;
   try {
     aFunction();
   }
-  catch(e) {
+  catch (e) {
     if (e.result != aErrorCode) {
       do_throw("Got an exception, but the result code was not the expected " +
                "one.  Expected " + aErrorCode + ", got " + e.result);
     }
     exceptionCaught = true;
   }
   if (!exceptionCaught)
     do_throw(aFunction + " should have thrown an exception but did not!");
@@ -203,27 +203,27 @@ function verifyQuery(aSQLString, aBind, 
                "there are only " + aResults.length + "!");
     for (let iCol = 0; iCol < nCols; iCol++) {
       let expectedVal = aResults[iCol];
       let valType = stmt.getTypeOfIndex(iCol);
       if (expectedVal === null) {
         do_check_eq(stmt.VALUE_TYPE_NULL, valType);
         do_check_true(stmt.getIsNull(iCol));
       }
-      else if (typeof(expectedVal) == "number") {
+      else if (typeof expectedVal == "number") {
         if (Math.floor(expectedVal) == expectedVal) {
           do_check_eq(stmt.VALUE_TYPE_INTEGER, valType);
           do_check_eq(expectedVal, stmt.getInt32(iCol));
         }
         else {
           do_check_eq(stmt.VALUE_TYPE_FLOAT, valType);
           do_check_eq(expectedVal, stmt.getDouble(iCol));
         }
       }
-      else if (typeof(expectedVal) == "string") {
+      else if (typeof expectedVal == "string") {
         do_check_eq(stmt.VALUE_TYPE_TEXT, valType);
         do_check_eq(expectedVal, stmt.getUTF8String(iCol));
       }
       else { // blob
         do_check_eq(stmt.VALUE_TYPE_BLOB, valType);
         let count = { value: 0 }, blob = { value: null };
         stmt.getBlob(iCol, count, blob);
         do_check_eq(count.value, expectedVal.length);
--- a/storage/test/unit/test_bug-365166.js
+++ b/storage/test/unit/test_bug-365166.js
@@ -1,27 +1,24 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/  */ 
-
 // Testcase for bug 365166 - crash [@ strlen] calling
 // mozIStorageStatement::getColumnName of a statement created with
 // "PRAGMA user_version" or "PRAGMA schema_version"
 function run_test() {
   test('user');
   test('schema');
 
   function test(param)
   {
     var colName = param + "_version";
     var sql = "PRAGMA " + colName;
 
     var file = getTestDB();
     var storageService = Components.classes["@mozilla.org/storage/service;1"].
                          getService(Components.interfaces.mozIStorageService);
-    var conn = storageService.openDatabase(file); 
+    var conn = storageService.openDatabase(file);
     var statement = conn.createStatement(sql);
     try {
       // This shouldn't crash:
       do_check_eq(statement.getColumnName(0), colName);
     } finally {
       statement.reset();
       statement.finalize();
     }
--- a/storage/test/unit/test_bug-393952.js
+++ b/storage/test/unit/test_bug-393952.js
@@ -1,14 +1,14 @@
 /* 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/. */
 
 // Testcase for bug 393952:  crash when I try to VACUUM and one of the tables
-// has a UNIQUE text column.   StorageUnicodeFunctions::likeFunction() 
+// has a UNIQUE text column.   StorageUnicodeFunctions::likeFunction()
 // needs to handle null aArgv[0] and aArgv[1]
 
 function setup()
 {
   getOpenedDatabase().createTable("t1", "x TEXT UNIQUE");
 
   var stmt = createStatement("INSERT INTO t1 (x) VALUES ('a')");
   stmt.execute();
@@ -27,12 +27,12 @@ function test_vacuum()
 var tests = [test_vacuum];
 
 function run_test()
 {
   setup();
 
   for (var i = 0; i < tests.length; i++)
     tests[i]();
-    
+
   cleanup();
 }
 
--- a/storage/test/unit/test_bug-429521.js
+++ b/storage/test/unit/test_bug-429521.js
@@ -1,49 +1,46 @@
 /* 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/. */
 
-function setup() 
-{
-    getOpenedDatabase().createTable("t1", "x TEXT");
+function setup() {
+  getOpenedDatabase().createTable("t1", "x TEXT");
 
-    var stmt = createStatement("INSERT INTO t1 (x) VALUES ('/mozilla.org/20070129_1/Europe/Berlin')");
-    stmt.execute();
-    stmt.finalize();
+  var stmt = createStatement("INSERT INTO t1 (x) VALUES ('/mozilla.org/20070129_1/Europe/Berlin')");
+  stmt.execute();
+  stmt.finalize();
 }
 
-function test_bug429521() 
-{
-    var stmt = createStatement(
-        "SELECT DISTINCT(zone) FROM ("+
-            "SELECT x AS zone FROM t1 WHERE x LIKE '/mozilla.org%'" +
-        ");");
+function test_bug429521() {
+  var stmt = createStatement(
+    "SELECT DISTINCT(zone) FROM (" +
+        "SELECT x AS zone FROM t1 WHERE x LIKE '/mozilla.org%'" +
+    ");");
 
-    print("*** test_bug429521: started");
+  print("*** test_bug429521: started");
 
-    try {
-        while (stmt.executeStep()) {
-            print("*** test_bug429521: step() Read wrapper.row.zone");
+  try {
+    while (stmt.executeStep()) {
+      print("*** test_bug429521: step() Read wrapper.row.zone");
 
-            // BUG: the print commands after the following statement
-            // are never executed. Script stops immediately.
-            var tzId = stmt.row.zone;
+      // BUG: the print commands after the following statement
+      // are never executed. Script stops immediately.
+      var tzId = stmt.row.zone;
 
-            print("*** test_bug429521: step() Read wrapper.row.zone finished");
-        }
-    } catch (e) {
-        print("*** test_bug429521: " + e);
+      print("*** test_bug429521: step() Read wrapper.row.zone finished");
     }
+  } catch (e) {
+    print("*** test_bug429521: " + e);
+  }
 
-    print("*** test_bug429521: finished");
+  print("*** test_bug429521: finished");
 
-    stmt.finalize();
+  stmt.finalize();
 }
 
-function run_test()
-{
+function run_test() {
   setup();
 
   test_bug429521();
-    
+
   cleanup();
 }
--- a/storage/test/unit/test_bug-444233.js
+++ b/storage/test/unit/test_bug-444233.js
@@ -1,51 +1,51 @@
 /* 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/. */
 
 function setup() {
-    // Create the table
-    getOpenedDatabase().createTable("test_bug444233",
-                                    "id INTEGER PRIMARY KEY, value TEXT");
+  // Create the table
+  getOpenedDatabase().createTable("test_bug444233",
+                                  "id INTEGER PRIMARY KEY, value TEXT");
 
-    // Insert dummy data, using wrapper methods
-    var stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
-    stmt.params.value = "value1"
-    stmt.execute();
-    stmt.finalize();
-    
-    stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
-    stmt.params.value = "value2"
-    stmt.execute();
-    stmt.finalize();
+  // Insert dummy data, using wrapper methods
+  var stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
+  stmt.params.value = "value1";
+  stmt.execute();
+  stmt.finalize();
+
+  stmt = createStatement("INSERT INTO test_bug444233 (value) VALUES (:value)");
+  stmt.params.value = "value2";
+  stmt.execute();
+  stmt.finalize();
 }
 
 function test_bug444233() {
-    print("*** test_bug444233: started");
-    
-    // Check that there are 2 results
-    var stmt = createStatement("SELECT COUNT(*) AS number FROM test_bug444233");
-    do_check_true(stmt.executeStep());
-    do_check_eq(2, stmt.row.number);
-    stmt.reset();
-    stmt.finalize();
+  print("*** test_bug444233: started");
+
+  // Check that there are 2 results
+  var stmt = createStatement("SELECT COUNT(*) AS number FROM test_bug444233");
+  do_check_true(stmt.executeStep());
+  do_check_eq(2, stmt.row.number);
+  stmt.reset();
+  stmt.finalize();
+
+  print("*** test_bug444233: doing delete");
 
-    print("*** test_bug444233: doing delete");
-    
-    // Now try to delete using IN
-    // Cheating since we know ids are 1,2
-    try {
-        var ids = [1, 2];
-        stmt = createStatement("DELETE FROM test_bug444233 WHERE id IN (:ids)");
-        stmt.params.ids = ids;
-    } catch (e) {
-        print("*** test_bug444233: successfully caught exception");
-    }
-    stmt.finalize();
+  // Now try to delete using IN
+  // Cheating since we know ids are 1,2
+  try {
+    var ids = [1, 2];
+    stmt = createStatement("DELETE FROM test_bug444233 WHERE id IN (:ids)");
+    stmt.params.ids = ids;
+  } catch (e) {
+    print("*** test_bug444233: successfully caught exception");
+  }
+  stmt.finalize();
 }
 
 function run_test() {
-    setup();
-    test_bug444233();
-    cleanup();
+  setup();
+  test_bug444233();
+  cleanup();
 }
 
--- a/storage/test/unit/test_chunk_growth.js
+++ b/storage/test/unit/test_chunk_growth.js
@@ -1,55 +1,52 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
 // This file tests SQLITE_FCNTL_CHUNK_SIZE behaves as expected
 
 function run_sql(d, sql) {
-  var stmt = d.createStatement(sql)
-  stmt.execute()
+  var stmt = d.createStatement(sql);
+  stmt.execute();
   stmt.finalize();
 }
 
-function new_file(name)
-{
+function new_file(name) {
   var file = dirSvc.get("ProfD", Ci.nsIFile);
   file.append(name);
   return file;
 }
 
 function get_size(name) {
-  return new_file(name).fileSize
+  return new_file(name).fileSize;
 }
 
-function run_test()
-{
+function run_test() {
   const filename = "chunked.sqlite";
   const CHUNK_SIZE = 512 * 1024;
   var d = getDatabase(new_file(filename));
   try {
     d.setGrowthIncrement(CHUNK_SIZE, "");
-  } catch (e if e.result == Cr.NS_ERROR_FILE_TOO_BIG) {
+  } catch (e) {
+    if (e.result != Cr.NS_ERROR_FILE_TOO_BIG) {
+      throw e;
+    }
     print("Too little free space to set CHUNK_SIZE!");
     return;
   }
   run_sql(d, "CREATE TABLE bloat(data varchar)");
 
   var orig_size = get_size(filename);
   /* Dump in at least 32K worth of data.
    * While writing ensure that the file size growth in chunksize set above.
    */
   const str1024 = new Array(1024).join("T");
-  for(var i = 0; i < 32; i++) {
+  for (var i = 0; i < 32; i++) {
     run_sql(d, "INSERT INTO bloat VALUES('" + str1024 + "')");
-    var size = get_size(filename)
+    var size = get_size(filename);
     // Must not grow in small increments.
     do_check_true(size == orig_size || size >= CHUNK_SIZE);
   }
   /* In addition to growing in chunk-size increments, the db
    * should shrink in chunk-size increments too.
    */
-  run_sql(d, "DELETE FROM bloat")
-  run_sql(d, "VACUUM")
-  do_check_true(get_size(filename) >= CHUNK_SIZE)
+  run_sql(d, "DELETE FROM bloat");
+  run_sql(d, "VACUUM");
+  do_check_true(get_size(filename) >= CHUNK_SIZE);
 }
 
--- a/storage/test/unit/test_connection_executeAsync.js
+++ b/storage/test/unit/test_connection_executeAsync.js
@@ -7,18 +7,17 @@
  * both mozIStorageStatement and mozIStorageAsyncStatement.
  */
 
 const INTEGER = 1;
 const TEXT = "this is test text";
 const REAL = 3.23;
 const BLOB = [1, 2];
 
-function test_create_and_add()
-{
+add_test(function test_create_and_add() {
   getOpenedDatabase().executeSimpleSQL(
     "CREATE TABLE test (" +
       "id INTEGER, " +
       "string TEXT, " +
       "number REAL, " +
       "nuller NULL, " +
       "blober BLOB" +
     ")"
@@ -37,29 +36,27 @@ function test_create_and_add()
     "INSERT INTO test (string, number, nuller, blober) VALUES (?, ?, ?, ?)"
   );
   stmts[1].bindByIndex(0, TEXT);
   stmts[1].bindByIndex(1, REAL);
   stmts[1].bindByIndex(2, null);
   stmts[1].bindBlobByIndex(3, BLOB, BLOB.length);
 
   getOpenedDatabase().executeAsync(stmts, stmts.length, {
-    handleResult: function(aResultSet)
-    {
-      dump("handleResult("+aResultSet+")\n");
+    handleResult: function (aResultSet) {
+      dump("handleResult(" + aResultSet + ")\n");
       do_throw("unexpected results obtained!");
     },
-    handleError: function(aError)
+    handleError: function (aError)
     {
-      dump("handleError("+aError.result+")\n");
+      dump("handleError(" + aError.result + ")\n");
       do_throw("unexpected error!");
     },
-    handleCompletion: function(aReason)
-    {
-      dump("handleCompletion("+aReason+")\n");
+    handleCompletion: function (aReason) {
+      dump("handleCompletion(" + aReason + ")\n");
       do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
 
       // Check that the result is in the table
       let stmt = getOpenedDatabase().createStatement(
         "SELECT string, number, nuller, blober FROM test WHERE id = ?"
       );
       stmt.bindByIndex(0, INTEGER);
       try {
@@ -91,20 +88,19 @@ function test_create_and_add()
       }
 
       // Run the next test.
       run_next_test();
     }
   });
   stmts[0].finalize();
   stmts[1].finalize();
-}
+});
 
-function test_multiple_bindings_on_statements()
-{
+add_test(function test_multiple_bindings_on_statements() {
   // This tests to make sure that we pass all the statements multiply bound
   // parameters when we call executeAsync.
   const AMOUNT_TO_ADD = 5;
   const ITERATIONS = 5;
 
   let stmts = [];
   let db = getOpenedDatabase();
   let sqlString = "INSERT INTO test (id, string, number, nuller, blober) " +
@@ -140,28 +136,25 @@ function test_multiple_bindings_on_state
     currentRows = countStmt.row.count;
   }
   finally {
     countStmt.reset();
   }
 
   // Execute asynchronously.
   getOpenedDatabase().executeAsync(stmts, stmts.length, {
-    handleResult: function(aResultSet)
-    {
+    handleResult: function (aResultSet) {
       do_throw("Unexpected call to handleResult!");
     },
-    handleError: function(aError)
-    {
+    handleError: function (aError) {
       print("Error code " + aError.result + " with message '" +
             aError.message + "' returned.");
       do_throw("Unexpected error!");
     },
-    handleCompletion: function(aReason)
-    {
+    handleCompletion: function (aReason) {
       print("handleCompletion(" + aReason +
             ") for test_multiple_bindings_on_statements");
       do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
 
       // Check to make sure we added all of our rows.
       try {
         do_check_true(countStmt.executeStep());
         do_check_eq(currentRows + (ITERATIONS * AMOUNT_TO_ADD),
@@ -171,90 +164,72 @@ function test_multiple_bindings_on_state
         countStmt.finalize();
       }
 
       // Run the next test.
       run_next_test();
     }
   });
   stmts.forEach(stmt => stmt.finalize());
-}
+});
 
-function test_asyncClose_does_not_complete_before_statements()
-{
+add_test(function test_asyncClose_does_not_complete_before_statements() {
   let stmt = createStatement("SELECT * FROM sqlite_master");
   let executed = false;
   stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-    },
-    handleError: function(aError)
-    {
+    handleResult(aResultSet) {},
+    handleError(aError) {
       print("Error code " + aError.result + " with message '" +
             aError.message + "' returned.");
       do_throw("Unexpected error!");
     },
-    handleCompletion: function(aReason)
-    {
+    handleCompletion(aReason) {
       print("handleCompletion(" + aReason +
             ") for test_asyncClose_does_not_complete_before_statements");
       do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason);
       executed = true;
     }
   });
   stmt.finalize();
 
-  getOpenedDatabase().asyncClose(function() {
+  getOpenedDatabase().asyncClose(function () {
     // Ensure that the statement executed to completion.
     do_check_true(executed);
 
     // Reset gDBConn so that later tests will get a new connection object.
     gDBConn = null;
     run_next_test();
   });
-}
+});
 
-function test_asyncClose_does_not_throw_no_callback()
-{
+add_test(function test_asyncClose_does_not_throw_no_callback() {
   getOpenedDatabase().asyncClose();
 
   // Reset gDBConn so that later tests will get a new connection object.
   gDBConn = null;
   run_next_test();
-}
+});
 
-function test_double_asyncClose_throws()
-{
+add_test(function test_double_asyncClose_throws() {
   let conn = getOpenedDatabase();
   conn.asyncClose();
   try {
     conn.asyncClose();
     do_throw("should have thrown");
     // There is a small race condition here, which can cause either of
     // Cr.NS_ERROR_NOT_INITIALIZED or Cr.NS_ERROR_UNEXPECTED to be thrown.
-  } catch (e if "result" in e && e.result == Cr.NS_ERROR_NOT_INITIALIZED) {
-    do_print("NS_ERROR_NOT_INITIALIZED");
-  } catch (e if "result" in e && e.result == Cr.NS_ERROR_UNEXPECTED) {
-    do_print("NS_ERROR_UNEXPECTED");
   } catch (e) {
+    if ("result" in e && e.result == Cr.NS_ERROR_NOT_INITIALIZED) {
+      do_print("NS_ERROR_NOT_INITIALIZED");
+    } else if ("result" in e && e.result == Cr.NS_ERROR_UNEXPECTED) {
+      do_print("NS_ERROR_UNEXPECTED");
+    }
   }
 
   // Reset gDBConn so that later tests will get a new connection object.
   gDBConn = null;
   run_next_test();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// Test Runner
+});
 
-[
-  test_create_and_add,
-  test_multiple_bindings_on_statements,
-  test_asyncClose_does_not_complete_before_statements,
-  test_asyncClose_does_not_throw_no_callback,
-  test_double_asyncClose_throws,
-].forEach(add_test);
-
-function run_test()
-{
+function run_test() {
   cleanup();
   run_next_test();
 }
--- a/storage/test/unit/test_connection_executeSimpleSQLAsync.js
+++ b/storage/test/unit/test_connection_executeSimpleSQLAsync.js
@@ -8,59 +8,59 @@
  */
 
 const INTEGER = 1;
 const TEXT = "this is test text";
 const REAL = 3.23;
 
 function asyncClose(db) {
   let deferred = Promise.defer();
-  db.asyncClose(function(status) {
+  db.asyncClose(function (status) {
     if (Components.isSuccessCode(status)) {
       deferred.resolve();
     } else {
       deferred.reject(status);
     }
   });
   return deferred.promise;
 }
 
 function openAsyncDatabase(file) {
   let deferred = Promise.defer();
-  getService().openAsyncDatabase(file, null, function(status, db) {
+  getService().openAsyncDatabase(file, null, function (status, db) {
     if (Components.isSuccessCode(status)) {
       deferred.resolve(db.QueryInterface(Ci.mozIStorageAsyncConnection));
     } else {
       deferred.reject(status);
     }
   });
   return deferred.promise;
 }
 
 function executeSimpleSQLAsync(db, query, onResult) {
   let deferred = Promise.defer();
   db.executeSimpleSQLAsync(query, {
-    handleError: function(error) {
+    handleError(error) {
       deferred.reject(error);
     },
-    handleResult: function(result) {
+    handleResult(result) {
       if (onResult) {
         onResult(result);
       } else {
         do_throw("No results were expected");
       }
     },
-    handleCompletion: function(result) {
+    handleCompletion(result) {
       deferred.resolve(result);
     }
   });
   return deferred.promise;
 }
 
-add_task(function test_create_and_add() {
+add_task(function* test_create_and_add() {
   let adb = yield openAsyncDatabase(getTestDB());
 
   let completion = yield executeSimpleSQLAsync(adb,
     "CREATE TABLE test (id INTEGER, string TEXT, number REAL)");
 
   do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, completion);
 
   completion = yield executeSimpleSQLAsync(adb,
@@ -68,46 +68,46 @@ add_task(function test_create_and_add() 
     "VALUES (" + INTEGER + ", \"" + TEXT + "\", " + REAL + ")");
 
   do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, completion);
 
   let result = null;
 
   completion = yield executeSimpleSQLAsync(adb,
     "SELECT string, number FROM test WHERE id = 1",
-    function(aResultSet) {
+    function (aResultSet) {
       result = aResultSet.getNextRow();
       do_check_eq(2, result.numEntries);
       do_check_eq(TEXT, result.getString(0));
       do_check_eq(REAL, result.getDouble(1));
     }
   );
 
   do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, completion);
   do_check_neq(result, null);
   result = null;
 
   yield executeSimpleSQLAsync(adb, "SELECT COUNT(0) FROM test",
-    function(aResultSet) {
+    function (aResultSet) {
       result = aResultSet.getNextRow();
       do_check_eq(1, result.getInt32(0));
     });
 
   do_check_neq(result, null);
 
   yield asyncClose(adb);
 });
 
 
-add_task(function test_asyncClose_does_not_complete_before_statement() {
+add_task(function* test_asyncClose_does_not_complete_before_statement() {
   let adb = yield openAsyncDatabase(getTestDB());
   let executed = false;
 
   let reason = yield executeSimpleSQLAsync(adb, "SELECT * FROM test",
-    function(aResultSet) {
+    function (aResultSet) {
       let result = aResultSet.getNextRow();
 
       do_check_neq(result, null);
       do_check_eq(3, result.numEntries);
       do_check_eq(INTEGER, result.getInt32(0));
       do_check_eq(TEXT, result.getString(1));
       do_check_eq(REAL, result.getDouble(2));
       executed = true;
@@ -116,16 +116,8 @@ add_task(function test_asyncClose_does_n
 
   do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, reason);
 
   // Ensure that the statement executed to completion.
   do_check_true(executed);
 
   yield asyncClose(adb);
 });
-
-////////////////////////////////////////////////////////////////////////////////
-//// Test Runner
-
-function run_test()
-{
-  run_next_test();
-}
--- a/storage/test/unit/test_js_helpers.js
+++ b/storage/test/unit/test_js_helpers.js
@@ -18,17 +18,17 @@ function test_params_enumerate()
     "SELECT * FROM test WHERE id IN (:a, :b, :c)"
   );
 
   // Make sure they are right.
   let expected = ["a", "b", "c"];
   let index = 0;
   for (let name in stmt.params) {
     if (name == "QueryInterface")
-        continue;
+      continue;
     do_check_eq(name, expected[index++]);
   }
 }
 
 function test_params_prototype()
 {
   let stmt = createStatement(
     "SELECT * FROM sqlite_master"
--- a/storage/test/unit/test_levenshtein.js
+++ b/storage/test/unit/test_levenshtein.js
@@ -25,18 +25,17 @@ function createUtf16Database()
 function check_levenshtein(db, s, t, expectedDistance)
 {
   var stmt = db.createStatement("SELECT levenshteinDistance(:s, :t) AS result");
   stmt.params.s = s;
   stmt.params.t = t;
   try {
     do_check_true(stmt.executeStep());
     do_check_eq(expectedDistance, stmt.row.result);
-  } 
-  finally {
+  } finally {
     stmt.reset();
     stmt.finalize();
   }
 }
 
 function testLevenshtein(db)
 {
   // Basic tests.
@@ -51,17 +50,17 @@ function testLevenshtein(db)
   check_levenshtein(db, "kitten", "sitting", 3);
   check_levenshtein(db, "Saturday", "Sunday", 3);
   check_levenshtein(db, "YHCQPGK", "LAHYQQKPGKA", 6);
 
   // Test SQL NULL handling.
   check_levenshtein(db, "foo", null, null);
   check_levenshtein(db, null, "bar", null);
   check_levenshtein(db, null, null, null);
-  
+
   // The levenshteinDistance function allocates temporary memory on the stack
   // if it can.  Test some strings long enough to force a heap allocation.
   var dots1000 = Array(1001).join(".");
   var dashes1000 = Array(1001).join("-");
   check_levenshtein(db, dots1000, dashes1000, 1000);
 }
 
 function run_test()
--- a/storage/test/unit/test_like.js
+++ b/storage/test/unit/test_like.js
@@ -88,31 +88,31 @@ function test_like_2()
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_false(stmt.executeStep());
   stmt.reset();
   stmt.finalize();
 }
-    
+
 function test_like_3()
 {
   var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?;");
   stmt.bindByIndex(0, 'aBc');
   var solutions = ["abc", "ABC"];
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_false(stmt.executeStep());
   stmt.reset();
   stmt.finalize();
 }
-   
+
 function test_like_4()
 {
   var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?;");
   stmt.bindByIndex(0, 'abc%');
   var solutions = ["abc", "abcd", "ABC", "ABC abc xyz"];
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_true(stmt.executeStep());
@@ -148,17 +148,17 @@ function test_like_6()
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_false(stmt.executeStep());
   stmt.reset();
   stmt.finalize();
 }
-    
+
 function test_like_7()
 {
   var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?;");
   stmt.bindByIndex(0, 'a_c%');
   var solutions = ["abc", "abcd", "ABC", "ABC abc xyz"];
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_true(stmt.executeStep());
@@ -180,22 +180,23 @@ function test_like_8()
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_true(stmt.executeStep());
   do_check_true(solutions.indexOf(stmt.getString(0)) != -1);
   do_check_false(stmt.executeStep());
   stmt.reset();
   stmt.finalize();
 }
-    
-var tests = [test_count, test_like_1, test_like_2, test_like_3, test_like_4, 
+
+var tests = [test_count, test_like_1, test_like_2, test_like_3, test_like_4,
              test_like_5, test_like_6, test_like_7, test_like_8];
 
 function run_test()
 {
   setup();
 
-  for (var i = 0; i < tests.length; i++)
+  for (var i = 0; i < tests.length; i++) {
     tests[i]();
-    
+  }
+
   cleanup();
 }
 
--- a/storage/test/unit/test_like_escape.js
+++ b/storage/test/unit/test_like_escape.js
@@ -1,38 +1,38 @@
 /* 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 LATIN1_AE = "\xc6";
-const LATIN1_ae = "\xe6"; 
+const LATIN1_ae = "\xe6";
 
 function setup()
 {
   getOpenedDatabase().createTable("t1", "x TEXT");
 
   var stmt = createStatement("INSERT INTO t1 (x) VALUES ('foo/bar_baz%20cheese')");
   stmt.execute();
   stmt.finalize();
 
   stmt = createStatement("INSERT INTO t1 (x) VALUES (?1)");
   // insert LATIN_ae, but search on LATIN_AE
   stmt.bindByIndex(0, "foo%20" + LATIN1_ae + "/_bar");
   stmt.execute();
   stmt.finalize();
 }
-    
+
 function test_escape_for_like_ascii()
 {
   var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?1 ESCAPE '/'");
   var paramForLike = stmt.escapeStringForLIKE("oo/bar_baz%20chees", '/');
   // verify that we escaped / _ and %
   do_check_eq(paramForLike, "oo//bar/_baz/%20chees");
   // prepend and append with % for "contains"
-  stmt.bindByIndex(0, "%" + paramForLike + "%"); 
+  stmt.bindByIndex(0, "%" + paramForLike + "%");
   stmt.executeStep();
   do_check_eq("foo/bar_baz%20cheese", stmt.getString(0));
   stmt.finalize();
 }
 
 function test_escape_for_like_non_ascii()
 {
   var stmt = createStatement("SELECT x FROM t1 WHERE x LIKE ?1 ESCAPE '/'");
@@ -47,13 +47,14 @@ function test_escape_for_like_non_ascii(
 }
 
 var tests = [test_escape_for_like_ascii, test_escape_for_like_non_ascii];
 
 function run_test()
 {
   setup();
 
-  for (var i = 0; i < tests.length; i++)
+  for (var i = 0; i < tests.length; i++) {
     tests[i]();
-    
+  }
+
   cleanup();
 }
--- a/storage/test/unit/test_locale_collation.js
+++ b/storage/test/unit/test_locale_collation.js
@@ -135,31 +135,31 @@ function initTableWithStrings(aStrings, 
  *         strength is computed from this value.
  * @return A function to use as a sorting callback.
  */
 function localeCompare(aCollation)
 {
   var strength;
 
   switch (aCollation) {
-  case "locale":
-    strength = Ci.nsICollation.kCollationCaseInSensitive;
-    break;
-  case "locale_case_sensitive":
-    strength = Ci.nsICollation.kCollationAccentInsenstive;
-    break;
-  case "locale_accent_sensitive":
-    strength = Ci.nsICollation.kCollationCaseInsensitiveAscii;
-    break;
-  case "locale_case_accent_sensitive":
-    strength = Ci.nsICollation.kCollationCaseSensitive;
-    break;
-  default:
-    do_throw("Error in test: unknown collation '" + aCollation + "'");
-    break;
+    case "locale":
+      strength = Ci.nsICollation.kCollationCaseInSensitive;
+      break;
+    case "locale_case_sensitive":
+      strength = Ci.nsICollation.kCollationAccentInsenstive;
+      break;
+    case "locale_accent_sensitive":
+      strength = Ci.nsICollation.kCollationCaseInsensitiveAscii;
+      break;
+    case "locale_case_accent_sensitive":
+      strength = Ci.nsICollation.kCollationCaseSensitive;
+      break;
+    default:
+      do_throw("Error in test: unknown collation '" + aCollation + "'");
+      break;
   }
   return function (aStr1, aStr2) {
     return gLocaleCollation.compareString(strength, aStr1, aStr2);
   };
 }
 
 /**
  * Reads in the test data from the file DATA_BASENAME and returns it as an array
@@ -175,18 +175,19 @@ function readTestData()
 
   let istream = Cc["@mozilla.org/network/file-input-stream;1"].
                 createInstance(Ci.nsIFileInputStream);
   istream.init(file, -1, -1, 0);
   istream.QueryInterface(Components.interfaces.nsILineInputStream);
 
   let line = {};
   let lines = [];
-  while (istream.readLine(line))
-    lines.push(line.value); 
+  while (istream.readLine(line)) {
+    lines.push(line.value);
+  }
   istream.close();
 
   return lines;
 }
 
 /**
  * Gets the results from the given database using the given collation and
  * ensures that they match gStrings sorted by the same collation.
--- a/storage/test/unit/test_sqlite_secure_delete.js
+++ b/storage/test/unit/test_sqlite_secure_delete.js
@@ -29,18 +29,17 @@ function getFileContents(aFile)
                 createInstance(Ci.nsIBinaryInputStream);
   bstream.setInputStream(fstream);
   return bstream.readBytes(bstream.available());
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Tests
 
-function test_delete_removes_data()
-{
+add_test(function test_delete_removes_data() {
   const TEST_STRING = "SomeRandomStringToFind";
 
   let file = getTestDB();
   let db = getService().openDatabase(file);
 
   // Create the table and insert the data.
   db.createTable("test", "data TEXT");
   let stmt = db.createStatement("INSERT INTO test VALUES(:data)");
@@ -69,22 +68,15 @@ function test_delete_removes_data()
   }
   db.close();
 
   // Check the file to see if the string can be found.
   contents = getFileContents(file);
   do_check_eq(-1, contents.indexOf(TEST_STRING));
 
   run_next_test();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//// Test Runner
-
-[
-  test_delete_removes_data,
- ].forEach(add_test);
+});
 
 function run_test()
 {
   cleanup();
   run_next_test();
 }
--- a/storage/test/unit/test_statement_executeAsync.js
+++ b/storage/test/unit/test_statement_executeAsync.js
@@ -48,25 +48,25 @@ function execAsync(aStmt, aOptions, aRes
   if (aOptions == null)
     aOptions = {};
 
   let resultsExpected;
   let resultsChecker;
   if (aResults == null) {
     resultsExpected = 0;
   }
-  else if (typeof(aResults) == "number") {
+  else if (typeof aResults == "number") {
     resultsExpected = aResults;
   }
-  else if (typeof(aResults) == "function") {
+  else if (typeof aResults == "function") {
     resultsChecker = aResults;
   }
   else { // array
     resultsExpected = aResults.length;
-    resultsChecker = function(aResultNum, aTup, aCaller) {
+    resultsChecker = function (aResultNum, aTup, aCaller) {
       aResults[aResultNum](aTup, aCaller);
     };
   }
   let resultsSeen = 0;
 
   let errorCodeExpected = false;
   let reasonExpected = Ci.mozIStorageStatementCallback.REASON_FINISHED;
   let altReasonExpected = null;
@@ -78,36 +78,36 @@ function execAsync(aStmt, aOptions, aRes
   let errorCodeSeen = false;
 
   if ("cancel" in aOptions && aOptions.cancel)
     altReasonExpected = Ci.mozIStorageStatementCallback.REASON_CANCELED;
 
   let completed = false;
 
   let listener = {
-    handleResult: function(aResultSet)
+    handleResult(aResultSet)
     {
       let row, resultsSeenThisCall = 0;
       while ((row = aResultSet.getNextRow()) != null) {
         if (resultsChecker)
           resultsChecker(resultsSeen, row, caller);
         resultsSeen++;
         resultsSeenThisCall++;
       }
 
       if (!resultsSeenThisCall)
         do_throw("handleResult invoked with 0 result rows!");
     },
-    handleError: function(aError)
+    handleError(aError)
     {
       if (errorCodeSeen != false)
         do_throw("handleError called when we already had an error!");
       errorCodeSeen = aError.result;
     },
-    handleCompletion: function(aReason)
+    handleCompletion(aReason)
     {
       if (completed) // paranoia check
         do_throw("Received a second handleCompletion notification!", caller);
 
       if (resultsSeen != resultsExpected)
         do_throw("Expected " + resultsExpected + " rows of results but " +
                  "got " + resultsSeen + " rows!", caller);
 
@@ -221,18 +221,17 @@ function test_add_data()
 
 function test_get_data()
 {
   var stmt = makeTestStatement(
     "SELECT string, number, nuller, blober, id FROM test WHERE id = ?"
   );
   stmt.bindByIndex(0, INTEGER);
   execAsync(stmt, {}, [
-    function(tuple)
-    {
+    function (tuple) {
       do_check_neq(null, tuple);
 
       // Check that it's what we expect
       do_check_false(tuple.getIsNull(0));
       do_check_eq(tuple.getResultByName("string"), tuple.getResultByIndex(0));
       do_check_eq(TEXT, tuple.getResultByName("string"));
       do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_TEXT,
                   tuple.getTypeOfIndex(0));
@@ -249,25 +248,25 @@ function test_get_data()
       do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_NULL,
                   tuple.getTypeOfIndex(2));
 
       do_check_false(tuple.getIsNull(3));
       var blobByName = tuple.getResultByName("blober");
       do_check_eq(BLOB.length, blobByName.length);
       var blobByIndex = tuple.getResultByIndex(3);
       do_check_eq(BLOB.length, blobByIndex.length);
-      for (var i = 0; i < BLOB.length; i++) {
+      for (let i = 0; i < BLOB.length; i++) {
         do_check_eq(BLOB[i], blobByName[i]);
         do_check_eq(BLOB[i], blobByIndex[i]);
       }
       var count = { value: 0 };
       var blob = { value: null };
       tuple.getBlob(3, count, blob);
       do_check_eq(BLOB.length, count.value);
-      for (var i = 0; i < BLOB.length; i++)
+      for (let i = 0; i < BLOB.length; i++)
         do_check_eq(BLOB[i], blob.value[i]);
       do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_BLOB,
                   tuple.getTypeOfIndex(3));
 
       do_check_false(tuple.getIsNull(4));
       do_check_eq(tuple.getResultByName("id"), tuple.getResultByIndex(4));
       do_check_eq(INTEGER, tuple.getResultByName("id"));
       do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER,
@@ -278,17 +277,17 @@ function test_get_data()
 }
 
 function test_tuple_out_of_bounds()
 {
   var stmt = makeTestStatement(
     "SELECT string FROM test"
   );
   execAsync(stmt, {}, [
-    function(tuple) {
+    function (tuple) {
       do_check_neq(null, tuple);
 
       // Check all out of bounds - should throw
       var methods = [
         "getTypeOfIndex",
         "getInt32",
         "getInt64",
         "getDouble",
@@ -362,29 +361,23 @@ function test_no_listener_works_on_error
 
 function test_partial_listener_works()
 {
   var stmt = makeTestStatement(
     "DELETE FROM test WHERE id = ?"
   );
   stmt.bindByIndex(0, 0);
   stmt.executeAsync({
-    handleResult: function(aResultSet)
-    {
-    }
+    handleResult(aResultSet) {}
   });
   stmt.executeAsync({
-    handleError: function(aError)
-    {
-    }
+    handleError(aError) {}
   });
   stmt.executeAsync({
-    handleCompletion: function(aReason)
-    {
-    }
+    handleCompletion(aReason) {}
   });
   stmt.finalize();
 
   // Run the next test.
   run_next_test();
 }
 
 /**
@@ -462,18 +455,19 @@ function test_finalized_statement_does_n
 {
   var stmt = makeTestStatement(
     "SELECT * FROM TEST"
   );
   stmt.finalize();
   // we are concerned about a crash here; an error is fine.
   try {
     stmt.executeAsync();
+  } catch (ex) {
+    // Do nothing.
   }
-  catch (ex) {}
 
   // Run the next test.
   run_next_test();
 }
 
 /**
  * Bind by mozIStorageBindingParams on the mozIStorageBaseStatement by index.
  */
@@ -900,24 +894,23 @@ var testPass = TEST_PASS_SYNC;
 /**
  * Create a statement of the type under test per testPass.
  *
  * @param aSQL
  *        The SQL string from which to build a statement.
  * @return a statement of the type under test per testPass.
  */
 function makeTestStatement(aSQL) {
-  if (testPass == TEST_PASS_SYNC)
+  if (testPass == TEST_PASS_SYNC) {
     return getOpenedDatabase().createStatement(aSQL);
-  else
-    return getOpenedDatabase().createAsyncStatement(aSQL);
+  }
+  return getOpenedDatabase().createAsyncStatement(aSQL);
 }
 
-var tests =
-[
+var tests = [
   test_illegal_sql_async_deferred,
   test_create_table,
   test_add_data,
   test_get_data,
   test_tuple_out_of_bounds,
   test_no_listener_works_on_success,
   test_no_listener_works_on_results,
   test_no_listener_works_on_error,
--- a/storage/test/unit/test_statement_wrapper_automatically.js
+++ b/storage/test/unit/test_statement_wrapper_automatically.js
@@ -124,22 +124,19 @@ function insertAndCheckMultipleParams(aV
  * A convenience function that prints out a description of aVal using
  * aVal.toString and aVal.toSource.  Output is useful when the test fails.
  *
  * @param aVal
  *        a value inserted or to be inserted into our test table
  */
 function printValDesc(aVal)
 {
-  try
-  {
+  try {
     var toSource = aVal.toSource();
-  }
-  catch (exc)
-  {
+  } catch (ex) {
     toSource = "";
   }
   print("Testing value: toString=" + aVal +
         (toSource ? " toSource=" + toSource : ""));
 }
 
 function run_test()
 {
@@ -158,13 +155,13 @@ function run_test()
   ];
 
   vals.forEach(function (val)
   {
     printValDesc(val);
     print("Single parameter");
     insertAndCheckSingleParam(val);
     print("Multiple parameters");
-    insertAndCheckMultipleParams(val)
+    insertAndCheckMultipleParams(val);
   });
 
   cleanup();
 }
--- a/storage/test/unit/test_storage_aggregates.js
+++ b/storage/test/unit/test_storage_aggregates.js
@@ -6,39 +6,39 @@
 
 var testNums = [1, 2, 3, 4];
 
 function setup()
 {
   getOpenedDatabase().createTable("function_tests", "id INTEGER PRIMARY KEY");
 
   var stmt = createStatement("INSERT INTO function_tests (id) VALUES(?1)");
-  for(var i = 0; i < testNums.length; ++i) {
+  for (let i = 0; i < testNums.length; ++i) {
     stmt.bindByIndex(0, testNums[i]);
     stmt.execute();
   }
   stmt.reset();
   stmt.finalize();
 }
 
 var testSquareAndSumFunction = {
   calls: 0,
   _sas: 0,
 
-  reset: function() {
+  reset() {
     this.calls = 0;
-    this._sas  = 0;
+    this._sas = 0;
   },
 
-  onStep: function(val) {
+  onStep(val) {
     ++this.calls;
     this._sas += val.getInt32(0) * val.getInt32(0);
   },
 
-  onFinal: function() {
+  onFinal() {
     var retval = this._sas;
     this._sas = 0; // Prepare for next group
     return retval;
   }
 };
 
 function test_aggregate_registration()
 {
@@ -74,26 +74,28 @@ function test_aggregate_no_aliases()
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_FAILURE, e.result);
   }
 }
 
 function test_aggregate_call()
 {
   var stmt = createStatement("SELECT test_sas_aggr(id) FROM function_tests");
-  while(stmt.executeStep());
+  while (stmt.executeStep()) {
+    // Do nothing.
+  }
   do_check_eq(testNums.length, testSquareAndSumFunction.calls);
   testSquareAndSumFunction.reset();
   stmt.finalize();
 }
 
 function test_aggregate_result()
 {
   var sas = 0;
-  for(var i = 0; i < testNums.length; ++i) {
+  for (var i = 0; i < testNums.length; ++i) {
     sas += testNums[i] * testNums[i];
   }
   var stmt = createStatement("SELECT test_sas_aggr(id) FROM function_tests");
   stmt.executeStep();
   do_check_eq(sas, stmt.getInt32(0));
   testSquareAndSumFunction.reset();
   stmt.finalize();
 }
--- a/storage/test/unit/test_storage_connection.js
+++ b/storage/test/unit/test_storage_connection.js
@@ -4,29 +4,29 @@
 
 // This file tests the functions of mozIStorageConnection
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Test Functions
 
 function asyncClone(db, readOnly) {
   let deferred = Promise.defer();
-  db.asyncClone(readOnly, function(status, db2) {
+  db.asyncClone(readOnly, function (status, db2) {
     if (Components.isSuccessCode(status)) {
       deferred.resolve(db2);
     } else {
       deferred.reject(status);
     }
   });
   return deferred.promise;
 }
 
 function asyncClose(db) {
   let deferred = Promise.defer();
-  db.asyncClose(function(status) {
+  db.asyncClose(function (status) {
     if (Components.isSuccessCode(status)) {
       deferred.resolve();
     } else {
       deferred.reject(status);
     }
   });
   return deferred.promise;
 }
@@ -36,270 +36,259 @@ function openAsyncDatabase(file, options
   let properties;
   if (options) {
     properties = Cc["@mozilla.org/hash-property-bag;1"].
         createInstance(Ci.nsIWritablePropertyBag);
     for (let k in options) {
       properties.setProperty(k, options[k]);
     }
   }
-  getService().openAsyncDatabase(file, properties, function(status, db) {
+  getService().openAsyncDatabase(file, properties, function (status, db) {
     if (Components.isSuccessCode(status)) {
       deferred.resolve(db.QueryInterface(Ci.mozIStorageAsyncConnection));
     } else {
       deferred.reject(status);
     }
   });
   return deferred.promise;
 }
 
 function executeAsync(statement, onResult) {
   let deferred = Promise.defer();
   statement.executeAsync({
-    handleError: function(error) {
+    handleError: function (error) {
       deferred.reject(error);
     },
-    handleResult: function(result) {
+    handleResult: function (result) {
       if (onResult) {
         onResult(result);
       }
     },
-    handleCompletion: function(result) {
+    handleCompletion: function (result) {
       deferred.resolve(result);
     }
   });
   return deferred.promise;
 }
 
-add_task(function test_connectionReady_open()
-{
+add_task(function* test_connectionReady_open() {
   // there doesn't seem to be a way for the connection to not be ready (unless
   // we close it with mozIStorageConnection::Close(), but we don't for this).
   // It can only fail if GetPath fails on the database file, or if we run out
   // of memory trying to use an in-memory database
 
   var msc = getOpenedDatabase();
   do_check_true(msc.connectionReady);
 });
 
-add_task(function test_connectionReady_closed()
-{
+add_task(function* test_connectionReady_closed() {
   // This also tests mozIStorageConnection::Close()
 
   var msc = getOpenedDatabase();
   msc.close();
   do_check_false(msc.connectionReady);
   gDBConn = null; // this is so later tests don't start to fail.
 });
 
-add_task(function test_databaseFile()
-{
+add_task(function* test_databaseFile() {
   var msc = getOpenedDatabase();
   do_check_true(getTestDB().equals(msc.databaseFile));
 });
 
-add_task(function test_tableExists_not_created()
-{
+add_task(function* test_tableExists_not_created() {
   var msc = getOpenedDatabase();
   do_check_false(msc.tableExists("foo"));
 });
 
-add_task(function test_indexExists_not_created()
-{
+add_task(function* test_indexExists_not_created() {
   var msc = getOpenedDatabase();
   do_check_false(msc.indexExists("foo"));
 });
 
-add_task(function test_temp_tableExists_and_indexExists()
-{
+add_task(function* test_temp_tableExists_and_indexExists() {
   var msc = getOpenedDatabase();
   msc.executeSimpleSQL("CREATE TEMP TABLE test_temp(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)");
   do_check_true(msc.tableExists("test_temp"));
 
   msc.executeSimpleSQL("CREATE INDEX test_temp_ind ON test_temp (name)");
   do_check_true(msc.indexExists("test_temp_ind"));
 
   msc.executeSimpleSQL("DROP INDEX test_temp_ind");
   msc.executeSimpleSQL("DROP TABLE test_temp");
 });
 
-add_task(function test_createTable_not_created()
-{
+add_task(function* test_createTable_not_created() {
   var msc = getOpenedDatabase();
   msc.createTable("test", "id INTEGER PRIMARY KEY, name TEXT");
   do_check_true(msc.tableExists("test"));
 });
 
-add_task(function test_indexExists_created()
-{
+add_task(function* test_indexExists_created() {
   var msc = getOpenedDatabase();
   msc.executeSimpleSQL("CREATE INDEX name_ind ON test (name)");
   do_check_true(msc.indexExists("name_ind"));
 });
 
-add_task(function test_createTable_already_created()
-{
+add_task(function* test_createTable_already_created() {
   var msc = getOpenedDatabase();
   do_check_true(msc.tableExists("test"));
   try {
     msc.createTable("test", "id INTEGER PRIMARY KEY, name TEXT");
     do_throw("We shouldn't get here!");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_FAILURE, e.result);
   }
 });
 
-add_task(function test_attach_createTable_tableExists_indexExists()
-{
+add_task(function* test_attach_createTable_tableExists_indexExists() {
   var msc = getOpenedDatabase();
   var file = do_get_file("storage_attach.sqlite", true);
   var msc2 = getDatabase(file);
   msc.executeSimpleSQL("ATTACH DATABASE '" + file.path + "' AS sample");
 
   do_check_false(msc.tableExists("sample.test"));
   msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
   do_check_true(msc.tableExists("sample.test"));
   try {
     msc.createTable("sample.test", "id INTEGER PRIMARY KEY, name TEXT");
     do_throw("We shouldn't get here!");
-  } catch (e if e.result == Components.results.NS_ERROR_FAILURE) {
+  } catch (e) {
+    if (e.result != Components.results.NS_ERROR_FAILURE) {
+      throw e;
+    }
     // we expect to fail because this table should exist already.
   }
 
   do_check_false(msc.indexExists("sample.test_ind"));
   msc.executeSimpleSQL("CREATE INDEX sample.test_ind ON test (name)");
   do_check_true(msc.indexExists("sample.test_ind"));
 
   msc.executeSimpleSQL("DETACH DATABASE sample");
   msc2.close();
-  try { file.remove(false); } catch(e) { }
+  try {
+    file.remove(false);
+  } catch (e) {
+    // Do nothing.
+  }
 });
 
-add_task(function test_lastInsertRowID()
-{
+add_task(function* test_lastInsertRowID() {
   var msc = getOpenedDatabase();
   msc.executeSimpleSQL("INSERT INTO test (name) VALUES ('foo')");
   do_check_eq(1, msc.lastInsertRowID);
 });
 
-add_task(function test_transactionInProgress_no()
-{
+add_task(function* test_transactionInProgress_no() {
   var msc = getOpenedDatabase();
   do_check_false(msc.transactionInProgress);
 });
 
-add_task(function test_transactionInProgress_yes()
-{
+add_task(function* test_transactionInProgress_yes() {
   var msc = getOpenedDatabase();
   msc.beginTransaction();
   do_check_true(msc.transactionInProgress);
   msc.commitTransaction();
   do_check_false(msc.transactionInProgress);
 
   msc.beginTransaction();
   do_check_true(msc.transactionInProgress);
   msc.rollbackTransaction();
   do_check_false(msc.transactionInProgress);
 });
 
-add_task(function test_commitTransaction_no_transaction()
-{
+add_task(function* test_commitTransaction_no_transaction() {
   var msc = getOpenedDatabase();
   do_check_false(msc.transactionInProgress);
   try {
     msc.commitTransaction();
     do_throw("We should not get here!");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_UNEXPECTED, e.result);
   }
 });
 
-add_task(function test_rollbackTransaction_no_transaction()
-{
+add_task(function* test_rollbackTransaction_no_transaction() {
   var msc = getOpenedDatabase();
   do_check_false(msc.transactionInProgress);
   try {
     msc.rollbackTransaction();
     do_throw("We should not get here!");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_UNEXPECTED, e.result);
   }
 });
 
-add_task(function test_get_schemaVersion_not_set()
-{
+add_task(function* test_get_schemaVersion_not_set() {
   do_check_eq(0, getOpenedDatabase().schemaVersion);
 });
 
-add_task(function test_set_schemaVersion()
-{
+add_task(function* test_set_schemaVersion() {
   var msc = getOpenedDatabase();
   const version = 1;
   msc.schemaVersion = version;
   do_check_eq(version, msc.schemaVersion);
 });
 
-add_task(function test_set_schemaVersion_same()
-{
+add_task(function* test_set_schemaVersion_same() {
   var msc = getOpenedDatabase();
   const version = 1;
   msc.schemaVersion = version; // should still work ok
   do_check_eq(version, msc.schemaVersion);
 });
 
-add_task(function test_set_schemaVersion_negative()
-{
+add_task(function* test_set_schemaVersion_negative() {
   var msc = getOpenedDatabase();
   const version = -1;
   msc.schemaVersion = version;
   do_check_eq(version, msc.schemaVersion);
 });
 
-add_task(function test_createTable(){
+add_task(function* test_createTable() {
   var temp = getTestDB().parent;
   temp.append("test_db_table");
   try {
     var con = getService().openDatabase(temp);
-    con.createTable("a","");
+    con.createTable("a", "");
   } catch (e) {
-    if (temp.exists()) try {
-      temp.remove(false);
-    } catch (e2) {}
-    do_check_true(e.result==Cr.NS_ERROR_NOT_INITIALIZED ||
-                  e.result==Cr.NS_ERROR_FAILURE);
+    if (temp.exists()) {
+      try {
+        temp.remove(false);
+      } catch (e2) {
+        // Do nothing.
+      }
+    }
+    do_check_true(e.result == Cr.NS_ERROR_NOT_INITIALIZED ||
+                  e.result == Cr.NS_ERROR_FAILURE);
   } finally {
     if (con) {
       con.close();
     }
   }
 });
 
-add_task(function test_defaultSynchronousAtNormal()
-{
+add_task(function* test_defaultSynchronousAtNormal() {
   var msc = getOpenedDatabase();
   var stmt = createStatement("PRAGMA synchronous;");
   try {
     stmt.executeStep();
     do_check_eq(1, stmt.getInt32(0));
   }
   finally {
     stmt.reset();
     stmt.finalize();
   }
 });
 
 // must be ran before executeAsync tests
-add_task(function test_close_does_not_spin_event_loop()
-{
+add_task(function* test_close_does_not_spin_event_loop() {
   // We want to make sure that the event loop on the calling thread does not
   // spin when close is called.
   let event = {
     ran: false,
-    run: function()
-    {
+    run() {
       this.ran = true;
     },
   };
 
   // Post the event before we call close, so it would run if the event loop was
   // spun during close.
   let thread = Cc["@mozilla.org/thread-manager;1"].
                getService(Ci.nsIThreadManager).
@@ -310,88 +299,85 @@ add_task(function test_close_does_not_sp
   do_check_false(event.ran);
   getOpenedDatabase().close();
   do_check_false(event.ran);
 
   // Reset gDBConn so that later tests will get a new connection object.
   gDBConn = null;
 });
 
-add_task(function test_asyncClose_succeeds_with_finalized_async_statement()
-{
+add_task(function* test_asyncClose_succeeds_with_finalized_async_statement() {
   // XXX this test isn't perfect since we can't totally control when events will
   //     run.  If this paticular function fails randomly, it means we have a
   //     real bug.
 
   // We want to make sure we create a cached async statement to make sure that
   // when we finalize our statement, we end up finalizing the async one too so
   // close will succeed.
   let stmt = createStatement("SELECT * FROM test");
   stmt.executeAsync();
   stmt.finalize();
 
   yield asyncClose(getOpenedDatabase());
   // Reset gDBConn so that later tests will get a new connection object.
   gDBConn = null;
 });
 
-add_task(function test_close_then_release_statement() {
+add_task(function* test_close_then_release_statement() {
   // Testing the behavior in presence of a bad client that finalizes
   // statements after the database has been closed (typically by
   // letting the gc finalize the statement).
   let db = getOpenedDatabase();
   let stmt = createStatement("SELECT * FROM test -- test_close_then_release_statement");
   db.close();
   stmt.finalize(); // Finalize too late - this should not crash
 
   // Reset gDBConn so that later tests will get a new connection object.
   gDBConn = null;
 });
 
-add_task(function test_asyncClose_then_release_statement() {
+add_task(function* test_asyncClose_then_release_statement() {
   // Testing the behavior in presence of a bad client that finalizes
   // statements after the database has been async closed (typically by
   // letting the gc finalize the statement).
   let db = getOpenedDatabase();
   let stmt = createStatement("SELECT * FROM test -- test_asyncClose_then_release_statement");
   yield asyncClose(db);
   stmt.finalize(); // Finalize too late - this should not crash
 
   // Reset gDBConn so that later tests will get a new connection object.
   gDBConn = null;
 });
 
-add_task(function test_close_fails_with_async_statement_ran()
-{
+add_task(function* test_close_fails_with_async_statement_ran() {
   let deferred = Promise.defer();
   let stmt = createStatement("SELECT * FROM test");
   stmt.executeAsync();
   stmt.finalize();
 
   let db = getOpenedDatabase();
   try {
     db.close();
     do_throw("should have thrown");
   }
   catch (e) {
     do_check_eq(e.result, Cr.NS_ERROR_UNEXPECTED);
   }
   finally {
     // Clean up after ourselves.
-    db.asyncClose(function() {
+    db.asyncClose(function () {
       // Reset gDBConn so that later tests will get a new connection object.
       gDBConn = null;
       deferred.resolve();
     });
   }
   yield deferred.promise;
 });
 
-add_task(function test_clone_optional_param()
-{
+add_task(function* test_clone_optional_param() {
   let db1 = getService().openUnsharedDatabase(getTestDB());
   let db2 = db1.clone();
   do_check_true(db2.connectionReady);
 
   // A write statement should not fail here.
   let stmt = db2.createStatement("INSERT INTO test (name) VALUES (:name)");
   stmt.params.name = "dwitte";
   stmt.execute();
@@ -404,17 +390,17 @@ add_task(function test_clone_optional_pa
 
   // Additionally check that it is a connection on the same database.
   do_check_true(db1.databaseFile.equals(db2.databaseFile));
 
   db1.close();
   db2.close();
 });
 
-function standardAsyncTest(promisedDB, name, shouldInit = false) {
+function* standardAsyncTest(promisedDB, name, shouldInit = false) {
   do_print("Performing standard async test " + name);
 
   let adb = yield promisedDB;
   do_check_true(adb instanceof Ci.mozIStorageAsyncConnection);
   do_check_false(adb instanceof Ci.mozIStorageConnection);
 
   if (shouldInit) {
     let stmt = adb.createAsyncStatement("CREATE TABLE test(name TEXT)");
@@ -429,34 +415,33 @@ function standardAsyncTest(promisedDB, n
   stmt.params.name = name;
   let result = yield executeAsync(stmt);
   do_print("Request complete");
   stmt.finalize();
   do_check_true(Components.isSuccessCode(result));
   do_print("Extracting data");
   stmt = adb.createAsyncStatement("SELECT * FROM test");
   let found = false;
-  yield executeAsync(stmt, function(result) {
+  yield executeAsync(stmt, function (results) {
     do_print("Data has been extracted");
-
-    for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
+    for (let row = results.getNextRow(); row != null; row = results.getNextRow()) {
       if (row.getResultByName("name") == name) {
         found = true;
-      break;
+        break;
       }
     }
   });
   do_check_true(found);
   stmt.finalize();
   yield asyncClose(adb);
 
   do_print("Standard async test " + name + " complete");
 }
 
-add_task(function test_open_async() {
+add_task(function* test_open_async() {
   yield standardAsyncTest(openAsyncDatabase(getTestDB(), null), "default");
   yield standardAsyncTest(openAsyncDatabase(getTestDB()), "no optional arg");
   yield standardAsyncTest(openAsyncDatabase(getTestDB(),
     {shared: false, growthIncrement: 54}), "non-default options");
   yield standardAsyncTest(openAsyncDatabase("memory"),
     "in-memory database", true);
   yield standardAsyncTest(openAsyncDatabase("memory",
     {shared: false, growthIncrement: 54}),
@@ -487,59 +472,56 @@ add_task(function test_open_async() {
     if (adb) {
       yield asyncClose(adb);
     }
   }
   do_check_true(raised);
 });
 
 
-add_task(function test_async_open_with_shared_cache() {
+add_task(function* test_async_open_with_shared_cache() {
   do_print("Testing that opening with a shared cache doesn't break stuff");
   let adb = yield openAsyncDatabase(getTestDB(), {shared: true});
 
   let stmt = adb.createAsyncStatement("INSERT INTO test (name) VALUES (:name)");
   stmt.params.name = "clockworker";
   let result = yield executeAsync(stmt);
   do_print("Request complete");
   stmt.finalize();
   do_check_true(Components.isSuccessCode(result));
   do_print("Extracting data");
   stmt = adb.createAsyncStatement("SELECT * FROM test");
   let found = false;
-  yield executeAsync(stmt, function(result) {
+  yield executeAsync(stmt, function (results) {
     do_print("Data has been extracted");
-
-    for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
+    for (let row = results.getNextRow(); row != null; row = results.getNextRow()) {
       if (row.getResultByName("name") == "clockworker") {
         found = true;
-      break;
+        break;
       }
     }
   });
   do_check_true(found);
   stmt.finalize();
   yield asyncClose(adb);
 });
 
-add_task(function test_clone_trivial_async()
-{
+add_task(function* test_clone_trivial_async() {
   let db1 = getService().openDatabase(getTestDB());
   do_print("Opened adb1");
   do_check_true(db1 instanceof Ci.mozIStorageAsyncConnection);
   let adb2 = yield asyncClone(db1, true);
   do_check_true(adb2 instanceof Ci.mozIStorageAsyncConnection);
   do_print("Cloned to adb2");
   db1.close();
   do_print("Closed db1");
   yield asyncClose(adb2);
 });
 
-add_task(function test_clone_no_optional_param_async()
-{
+add_task(function* test_clone_no_optional_param_async() {
   "use strict";
   do_print("Testing async cloning");
   let adb1 = yield openAsyncDatabase(getTestDB(), null);
   do_check_true(adb1 instanceof Ci.mozIStorageAsyncConnection);
 
   do_print("Cloning database");
 
   let adb2 = yield asyncClone(adb1);
@@ -555,38 +537,36 @@ add_task(function test_clone_no_optional
   stmt.params.name = "yoric";
   let result = yield executeAsync(stmt);
   do_print("Request complete");
   stmt.finalize();
   do_check_true(Components.isSuccessCode(result));
   do_print("Extracting data from clone db");
   stmt = adb2.createAsyncStatement("SELECT * FROM test");
   let found = false;
-  yield executeAsync(stmt, function(result) {
+  yield executeAsync(stmt, function (results) {
     do_print("Data has been extracted");
-
-    for (let row = result.getNextRow(); row != null; row = result.getNextRow()) {
+    for (let row = results.getNextRow(); row != null; row = results.getNextRow()) {
       if (row.getResultByName("name") == "yoric") {
         found = true;
-      break;
+        break;
       }
     }
   });
   do_check_true(found);
   stmt.finalize();
   do_print("Closing databases");
   yield asyncClose(adb2);
   do_print("First db closed");
 
   yield asyncClose(adb1);
   do_print("Second db closed");
 });
 
-add_task(function test_clone_readonly()
-{
+add_task(function* test_clone_readonly() {
   let db1 = getService().openUnsharedDatabase(getTestDB());
   let db2 = db1.clone(true);
   do_check_true(db2.connectionReady);
 
   // A write statement should fail here.
   let stmt = db2.createStatement("INSERT INTO test (name) VALUES (:name)");
   stmt.params.name = "reed";
   expectError(Cr.NS_ERROR_FILE_READ_ONLY, () => stmt.execute());
@@ -596,18 +576,17 @@ add_task(function test_clone_readonly()
   stmt = db2.createStatement("SELECT * FROM test");
   do_check_true(stmt.executeStep());
   stmt.finalize();
 
   db1.close();
   db2.close();
 });
 
-add_task(function test_clone_shared_readonly()
-{
+add_task(function* test_clone_shared_readonly() {
   let db1 = getService().openDatabase(getTestDB());
   let db2 = db1.clone(true);
   do_check_true(db2.connectionReady);
 
   let stmt = db2.createStatement("INSERT INTO test (name) VALUES (:name)");
   stmt.params.name = "parker";
   // TODO currently SQLite does not actually work correctly here.  The behavior
   //      we want is commented out, and the current behavior is being tested
@@ -621,50 +600,47 @@ add_task(function test_clone_shared_read
   stmt = db2.createStatement("SELECT * FROM test");
   do_check_true(stmt.executeStep());
   stmt.finalize();
 
   db1.close();
   db2.close();
 });
 
-add_task(function test_close_clone_fails()
-{
+add_task(function* test_close_clone_fails() {
   let calls = [
     "openDatabase",
     "openUnsharedDatabase",
   ];
-  calls.forEach(function(methodName) {
+  calls.forEach(function (methodName) {
     let db = getService()[methodName](getTestDB());
     db.close();
     expectError(Cr.NS_ERROR_NOT_INITIALIZED, () => db.clone());
   });
 });
 
-add_task(function test_memory_clone_fails()
-{
+add_task(function* test_memory_clone_fails() {
   let db = getService().openSpecialDatabase("memory");
   db.close();
   expectError(Cr.NS_ERROR_NOT_INITIALIZED, () => db.clone());
 });
 
-add_task(function test_clone_copies_functions()
-{
+add_task(function* test_clone_copies_functions() {
   const FUNC_NAME = "test_func";
   let calls = [
     "openDatabase",
     "openUnsharedDatabase",
   ];
   let functionMethods = [
     "createFunction",
     "createAggregateFunction",
   ];
-  calls.forEach(function(methodName) {
-    [true, false].forEach(function(readOnly) {
-      functionMethods.forEach(function(functionMethod) {
+  calls.forEach(function (methodName) {
+    [true, false].forEach(function (readOnly) {
+      functionMethods.forEach(function (functionMethod) {
         let db1 = getService()[methodName](getTestDB());
         // Create a function for db1.
         db1[functionMethod](FUNC_NAME, 1, {
           onFunctionCall: () => 0,
           onStep: () => 0,
           onFinal: () => 0,
         });
 
@@ -675,43 +651,42 @@ add_task(function test_clone_copies_func
         stmt.finalize();
         db1.close();
         db2.close();
       });
     });
   });
 });
 
-add_task(function test_clone_copies_overridden_functions()
-{
+add_task(function* test_clone_copies_overridden_functions() {
   const FUNC_NAME = "lower";
   function test_func() {
     this.called = false;
   }
   test_func.prototype = {
-    onFunctionCall: function() {
+    onFunctionCall() {
       this.called = true;
     },
-    onStep: function() {
+    onStep() {
       this.called = true;
     },
     onFinal: () => 0,
   };
 
   let calls = [
     "openDatabase",
     "openUnsharedDatabase",
   ];
   let functionMethods = [
     "createFunction",
     "createAggregateFunction",
   ];
-  calls.forEach(function(methodName) {
-    [true, false].forEach(function(readOnly) {
-      functionMethods.forEach(function(functionMethod) {
+  calls.forEach(function (methodName) {
+    [true, false].forEach(function (readOnly) {
+      functionMethods.forEach(function (functionMethod) {
         let db1 = getService()[methodName](getTestDB());
         // Create a function for db1.
         let func = new test_func();
         db1[functionMethod](FUNC_NAME, 1, func);
         do_check_false(func.called);
 
         // Clone it, and make sure the function gets called.
         let db2 = db1.clone(readOnly);
@@ -721,18 +696,17 @@ add_task(function test_clone_copies_over
         stmt.finalize();
         db1.close();
         db2.close();
       });
     });
   });
 });
 
-add_task(function test_clone_copies_pragmas()
-{
+add_task(function* test_clone_copies_pragmas() {
   const PRAGMAS = [
     { name: "cache_size", value: 500, copied: true },
     { name: "temp_store", value: 2, copied: true },
     { name: "foreign_keys", value: 1, copied: true },
     { name: "journal_size_limit", value: 524288, copied: true },
     { name: "synchronous", value: 2, copied: true },
     { name: "wal_autocheckpoint", value: 16, copied: true },
     { name: "busy_timeout", value: 50, copied: true },
@@ -764,18 +738,17 @@ add_task(function test_clone_copies_prag
     validate(pragma.value, stmt.getInt32(0));
     stmt.finalize();
   });
 
   db1.close();
   db2.close();
 });
 
-add_task(function test_readonly_clone_copies_pragmas()
-{
+add_task(function* test_readonly_clone_copies_pragmas() {
   const PRAGMAS = [
     { name: "cache_size", value: 500, copied: true },
     { name: "temp_store", value: 2, copied: true },
     { name: "foreign_keys", value: 1, copied: false },
     { name: "journal_size_limit", value: 524288, copied: false },
     { name: "synchronous", value: 2, copied: false },
     { name: "wal_autocheckpoint", value: 16, copied: false },
     { name: "busy_timeout", value: 50, copied: false },
@@ -807,26 +780,24 @@ add_task(function test_readonly_clone_co
     validate(pragma.value, stmt.getInt32(0));
     stmt.finalize();
   });
 
   db1.close();
   db2.close();
 });
 
-add_task(function test_getInterface()
-{
+add_task(function* test_getInterface() {
   let db = getOpenedDatabase();
   let target = db.QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIEventTarget);
   // Just check that target is non-null.  Other tests will ensure that it has
   // the correct value.
   do_check_true(target != null);
 
   yield asyncClose(db);
   gDBConn = null;
 });
 
 
-function run_test()
-{
+function run_test() {
   run_next_test();
 }
--- a/storage/test/unit/test_storage_function.js
+++ b/storage/test/unit/test_storage_function.js
@@ -6,28 +6,28 @@
 
 var testNums = [1, 2, 3, 4];
 
 function setup()
 {
   getOpenedDatabase().createTable("function_tests", "id INTEGER PRIMARY KEY");
 
   var stmt = createStatement("INSERT INTO function_tests (id) VALUES(?1)");
-  for(var i = 0; i < testNums.length; ++i) {
+  for (let i = 0; i < testNums.length; ++i) {
     stmt.bindByIndex(0, testNums[i]);
     stmt.execute();
   }
   stmt.reset();
   stmt.finalize();
 }
 
 var testSquareFunction = {
   calls: 0,
 
-  onFunctionCall: function(val) {
+  onFunctionCall(val) {
     ++this.calls;
     return val.getInt32(0) * val.getInt32(0);
   }
 };
 
 function test_function_registration()
 {
   var msc = getOpenedDatabase();
@@ -57,27 +57,29 @@ function test_function_aliases()
 {
   var msc = getOpenedDatabase();
   msc.createFunction("test_square2", 1, testSquareFunction);
 }
 
 function test_function_call()
 {
   var stmt = createStatement("SELECT test_square(id) FROM function_tests");
-  while(stmt.executeStep());
+  while (stmt.executeStep()) {
+    // Do nothing.
+  }
   do_check_eq(testNums.length, testSquareFunction.calls);
   testSquareFunction.calls = 0;
   stmt.finalize();
 }
 
 function test_function_result()
 {
   var stmt = createStatement("SELECT test_square(42) FROM function_tests");
   stmt.executeStep();
-  do_check_eq(42*42, stmt.getInt32(0));
+  do_check_eq(42 * 42, stmt.getInt32(0));
   testSquareFunction.calls = 0;
   stmt.finalize();
 }
 
 var tests = [test_function_registration, test_function_no_double_registration,
              test_function_removal, test_function_aliases, test_function_call,
              test_function_result];
 
--- a/storage/test/unit/test_storage_progresshandler.js
+++ b/storage/test/unit/test_storage_progresshandler.js
@@ -6,31 +6,31 @@
 
 function setup()
 {
   var msc = getOpenedDatabase();
   msc.createTable("handler_tests", "id INTEGER PRIMARY KEY, num INTEGER");
   msc.beginTransaction();
 
   var stmt = createStatement("INSERT INTO handler_tests (id, num) VALUES(?1, ?2)");
-  for(var i = 0; i < 100; ++i) {
+  for (let i = 0; i < 100; ++i) {
     stmt.bindByIndex(0, i);
-    stmt.bindByIndex(1, Math.floor(Math.random()*1000));
+    stmt.bindByIndex(1, Math.floor(Math.random() * 1000));
     stmt.execute();
   }
   stmt.reset();
   msc.commitTransaction();
   stmt.finalize();
 }
 
 var testProgressHandler = {
   calls: 0,
   abort: false,
 
-  onProgress: function(comm) {
+  onProgress(comm) {
     ++this.calls;
     return this.abort;
   }
 };
 
 function test_handler_registration()
 {
   var msc = getOpenedDatabase();
@@ -54,33 +54,37 @@ function test_handler_removal()
 
 function test_handler_call()
 {
   var msc = getOpenedDatabase();
   msc.setProgressHandler(50, testProgressHandler);
   // Some long-executing request
   var stmt = createStatement(
     "SELECT SUM(t1.num * t2.num) FROM handler_tests AS t1, handler_tests AS t2");
-  while(stmt.executeStep());
+  while (stmt.executeStep()) {
+    // Do nothing.
+  }
   do_check_true(testProgressHandler.calls > 0);
   stmt.finalize();
 }
 
 function test_handler_abort()
 {
   var msc = getOpenedDatabase();
   testProgressHandler.abort = true;
   msc.setProgressHandler(50, testProgressHandler);
   // Some long-executing request
   var stmt = createStatement(
     "SELECT SUM(t1.num * t2.num) FROM handler_tests AS t1, handler_tests AS t2");
 
   const SQLITE_INTERRUPT = 9;
   try {
-    while(stmt.executeStep());
+    while (stmt.executeStep()) {
+      // Do nothing.
+    }
     do_throw("We shouldn't get here!");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_ABORT, e.result);
     do_check_eq(SQLITE_INTERRUPT, msc.lastError);
   }
   try {
     stmt.finalize();
     do_throw("We shouldn't get here!");
--- a/storage/test/unit/test_storage_service.js
+++ b/storage/test/unit/test_storage_service.js
@@ -92,27 +92,27 @@ function test_backup_not_new_filename()
 
   backup.remove(false);
 }
 
 function test_backup_new_filename()
 {
   var backup = getService().backupDatabaseFile(getTestDB(), BACKUP_FILE_NAME);
   do_check_eq(BACKUP_FILE_NAME, backup.leafName);
-  
+
   backup.remove(false);
 }
 
 function test_backup_new_folder()
 {
   var parentDir = getTestDB().parent;
   parentDir.append("test_storage_temp");
   if (parentDir.exists())
     parentDir.remove(true);
-  parentDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+  parentDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
   do_check_true(parentDir.exists());
 
   var backup = getService().backupDatabaseFile(getTestDB(), BACKUP_FILE_NAME,
                                                parentDir);
   do_check_eq(BACKUP_FILE_NAME, backup.leafName);
   do_check_true(parentDir.equals(backup.parent));
 
   parentDir.remove(true);
@@ -128,14 +128,15 @@ var tests = [
   test_fake_db_throws_with_openDatabase,
   test_backup_not_new_filename,
   test_backup_new_filename,
   test_backup_new_folder,
 ];
 
 function run_test()
 {
-  for (var i = 0; i < tests.length; i++)
+  for (var i = 0; i < tests.length; i++) {
     tests[i]();
-    
+  }
+
   cleanup();
 }
 
--- a/storage/test/unit/test_storage_service_unshared.js
+++ b/storage/test/unit/test_storage_service_unshared.js
@@ -24,12 +24,12 @@ function test_openUnsharedDatabase_file_
 
 var tests = [test_openUnsharedDatabase_file_DNE,
              test_openUnsharedDatabase_file_exists];
 
 function run_test()
 {
   for (var i = 0; i < tests.length; i++)
     tests[i]();
-    
+
   cleanup();
 }
 
--- a/storage/test/unit/test_storage_statement.js
+++ b/storage/test/unit/test_storage_statement.js
@@ -81,17 +81,17 @@ function test_getColumnIndex_different_c
   var stmt = createStatement("SELECT name, id FROM test");
   try {
     do_check_eq(0, stmt.getColumnIndex("NaMe"));
     do_throw("should not get here");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_INVALID_ARG, e.result);
   }
   try {
-  do_check_eq(1, stmt.getColumnIndex("Id"));
+    do_check_eq(1, stmt.getColumnIndex("Id"));
     do_throw("should not get here");
   } catch (e) {
     do_check_eq(Cr.NS_ERROR_INVALID_ARG, e.result);
   }
   stmt.reset();
   stmt.finalize();
 }
 
@@ -174,14 +174,15 @@ var tests = [test_parameterCount_none, t
              test_getColumnDecltype,
              test_failed_execute,
 ];
 
 function run_test()
 {
   setup();
 
-  for (var i = 0; i < tests.length; i++)
+  for (var i = 0; i < tests.length; i++) {
     tests[i]();
-    
+  }
+
   cleanup();
 }
 
--- a/storage/test/unit/test_storage_value_array.js
+++ b/storage/test/unit/test_storage_value_array.js
@@ -3,39 +3,39 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // This file tests the functions of mozIStorageValueArray
 
 function setup()
 {
   getOpenedDatabase().createTable("test", "id INTEGER PRIMARY KEY, name TEXT," +
                                           "number REAL, nuller NULL, blobber BLOB");
-  
+
   var stmt = createStatement("INSERT INTO test (name, number, blobber) " +
                              "VALUES (?1, ?2, ?3)");
   stmt.bindByIndex(0, "foo");
   stmt.bindByIndex(1, 2.34);
   stmt.bindBlobByIndex(2, [], 0);
   stmt.execute();
-  
+
   stmt.bindByIndex(0, "");
   stmt.bindByIndex(1, 1.23);
   stmt.bindBlobByIndex(2, [1, 2], 2);
   stmt.execute();
 
   stmt.reset();
   stmt.finalize();
 }
 
 function test_getIsNull_for_null()
 {
   var stmt = createStatement("SELECT nuller, blobber FROM test WHERE id = ?1");
   stmt.bindByIndex(0, 1);
   do_check_true(stmt.executeStep());
-  
+
   do_check_true(stmt.getIsNull(0)); // null field
   do_check_true(stmt.getIsNull(1)); // data is null if size is 0
   stmt.reset();
   stmt.finalize();
 }
 
 function test_getIsNull_for_non_null()
 {
@@ -197,14 +197,15 @@ var tests = [test_getIsNull_for_null, te
              test_value_type_float, test_value_type_text, test_value_type_blob,
              test_numEntries_one, test_numEntries_all, test_getInt,
              test_getDouble, test_getUTF8String, test_getString, test_getBlob];
 
 function run_test()
 {
   setup();
 
-  for (var i = 0; i < tests.length; i++)
+  for (var i = 0; i < tests.length; i++) {
     tests[i]();
-    
+  }
+
   cleanup();
 }
 
--- a/storage/test/unit/test_telemetry_vfs.js
+++ b/storage/test/unit/test_telemetry_vfs.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Make sure that there are telemetry entries created by sqlite io
 
 function run_sql(d, sql) {
-  var stmt = d.createStatement(sql)
-  stmt.execute()
+  var stmt = d.createStatement(sql);
+  stmt.execute();
   stmt.finalize();
 }
 
 function new_file(name)
 {
   var file = dirSvc.get("ProfD", Ci.nsIFile);
   file.append(name);
   return file;
@@ -19,12 +19,12 @@ function new_file(name)
 function run_test()
 {
   const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
   let read_hgram = Telemetry.getHistogramById("MOZ_SQLITE_OTHER_READ_B");
   let old_sum = read_hgram.snapshot().sum;
   const file = new_file("telemetry.sqlite");
   var d = getDatabase(file);
   run_sql(d, "CREATE TABLE bloat(data varchar)");
-  run_sql(d, "DROP TABLE bloat")
-  do_check_true(read_hgram.snapshot().sum > old_sum)
+  run_sql(d, "DROP TABLE bloat");
+  do_check_true(read_hgram.snapshot().sum > old_sum);
 }
 
--- a/storage/test/unit/test_unicode.js
+++ b/storage/test/unit/test_unicode.js
@@ -90,14 +90,15 @@ function test_like_search_same()
 var tests = [test_upper_ascii, test_upper_non_ascii, test_lower_ascii,
              test_lower_non_ascii, test_like_search_different,
              test_like_search_same];
 
 function run_test()
 {
   setup();
 
-  for (var i = 0; i < tests.length; i++)
+  for (var i = 0; i < tests.length; i++) {
     tests[i]();
-    
+  }
+
   cleanup();
 }
 
--- a/storage/test/unit/test_vacuum.js
+++ b/storage/test/unit/test_vacuum.js
@@ -82,254 +82,254 @@ function run_test()
     stmt.finalize();
   }
 
   load_test_vacuum_component();
 
   run_next_test();
 }
 
+const TESTS = [
+
+  function test_common_vacuum()
+  {
+    print("\n*** Test that a VACUUM correctly happens and all notifications are fired.");
+    // Wait for VACUUM begin.
+    let beginVacuumReceived = false;
+    Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
+      Services.obs.removeObserver(onVacuum, aTopic);
+      beginVacuumReceived = true;
+    }, "test-begin-vacuum", false);
+
+    // Wait for heavy IO notifications.
+    let heavyIOTaskBeginReceived = false;
+    let heavyIOTaskEndReceived = false;
+    Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
+      if (heavyIOTaskBeginReceived && heavyIOTaskEndReceived) {
+        Services.obs.removeObserver(onVacuum, aTopic);
+      }
+
+      if (aData == "vacuum-begin") {
+        heavyIOTaskBeginReceived = true;
+      }
+      else if (aData == "vacuum-end") {
+        heavyIOTaskEndReceived = true;
+      }
+    }, "heavy-io-task", false);
+
+    // Wait for VACUUM end.
+    Services.obs.addObserver(function onVacuum(aSubject, aTopic, aData) {
+      Services.obs.removeObserver(onVacuum, aTopic);
+      print("Check we received onBeginVacuum");
+      do_check_true(beginVacuumReceived);
+      print("Check we received heavy-io-task notifications");
+      do_check_true(heavyIOTaskBeginReceived);
+      do_check_true(heavyIOTaskEndReceived);
+      print("Received onEndVacuum");
+      run_next_test();
+    }, "test-end-vacuum", false);
+
+    synthesize_idle_daily();
+  },
+
+  function test_skipped_if_recent_vacuum()
+  {
+    print("\n*** Test that a VACUUM is skipped if it was run recently.");
+    Services.prefs.setIntPref("storage.vacuum.last.testVacuum.sqlite",
+                              parseInt(Date.now() / 1000));
+
+    // Wait for VACUUM begin.
+    let vacuumObserver = {
+      gotNotification: false,
+      observe: function VO_observe(aSubject, aTopic, aData) {
+        this.gotNotification = true;
+      },
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
+    };
+    Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
+
+    // Check after a couple seconds that no VACUUM has been run.
+    do_timeout(2000, function () {
+      print("Check VACUUM did not run.");
+      do_check_false(vacuumObserver.gotNotification);
+      Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
+      run_next_test();
+    });
+
+    synthesize_idle_daily();
+  },
+
+  function test_page_size_change()
+  {
+    print("\n*** Test that a VACUUM changes page_size");
+
+    // We did setup the database with a small page size, the previous vacuum
+    // should have updated it.
+    print("Check that page size was updated.");
+    let conn = getDatabase(new_db_file("testVacuum"));
+    let stmt = conn.createStatement("PRAGMA page_size");
+    try {
+      while (stmt.executeStep()) {
+        do_check_eq(stmt.row.page_size, conn.defaultPageSize);
+      }
+    }
+    finally {
+      stmt.finalize();
+    }
+
+    run_next_test();
+  },
+
+  function test_skipped_optout_vacuum()
+  {
+    print("\n*** Test that a VACUUM is skipped if the participant wants to opt-out.");
+    Services.obs.notifyObservers(null, "test-options", "opt-out");
+
+    // Wait for VACUUM begin.
+    let vacuumObserver = {
+      gotNotification: false,
+      observe: function VO_observe(aSubject, aTopic, aData) {
+        this.gotNotification = true;
+      },
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
+    };
+    Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
+
+    // Check after a couple seconds that no VACUUM has been run.
+    do_timeout(2000, function () {
+      print("Check VACUUM did not run.");
+      do_check_false(vacuumObserver.gotNotification);
+      Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
+      run_next_test();
+    });
+
+    synthesize_idle_daily();
+  },
+
+  /* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
+  function test_page_size_change_with_wal()
+  {
+    print("\n*** Test that a VACUUM changes page_size with WAL mode");
+    Services.obs.notifyObservers(null, "test-options", "wal");
+
+    // Set a small page size.
+    let conn = getDatabase(new_db_file("testVacuum2"));
+    conn.executeSimpleSQL("PRAGMA page_size = 1024");
+    let stmt = conn.createStatement("PRAGMA page_size");
+    try {
+      while (stmt.executeStep()) {
+        do_check_eq(stmt.row.page_size, 1024);
+      }
+    }
+    finally {
+      stmt.finalize();
+    }
+
+    // Use WAL journal mode.
+    conn.executeSimpleSQL("PRAGMA journal_mode = WAL");
+    stmt = conn.createStatement("PRAGMA journal_mode");
+    try {
+      while (stmt.executeStep()) {
+        do_check_eq(stmt.row.journal_mode, "wal");
+      }
+    }
+    finally {
+      stmt.finalize();
+    }
+
+    // Wait for VACUUM end.
+    let vacuumObserver = {
+      observe: function VO_observe(aSubject, aTopic, aData) {
+        Services.obs.removeObserver(this, aTopic);
+        print("Check page size has been updated.");
+        let stmt = conn.createStatement("PRAGMA page_size");
+        try {
+          while (stmt.executeStep()) {
+            do_check_eq(stmt.row.page_size, Ci.mozIStorageConnection.DEFAULT_PAGE_SIZE);
+          }
+        }
+        finally {
+          stmt.finalize();
+        }
+
+        print("Check journal mode has been restored.");
+        stmt = conn.createStatement("PRAGMA journal_mode");
+        try {
+          while (stmt.executeStep()) {
+            do_check_eq(stmt.row.journal_mode, "wal");
+          }
+        }
+        finally {
+          stmt.finalize();
+        }
+
+        run_next_test();
+      },
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
+    }
+    Services.obs.addObserver(vacuumObserver, "test-end-vacuum", false);
+
+    synthesize_idle_daily();
+  },
+  */
+
+  function test_memory_database_crash()
+  {
+    print("\n*** Test that we don't crash trying to vacuum a memory database");
+    Services.obs.notifyObservers(null, "test-options", "memory");
+
+    // Wait for VACUUM begin.
+    let vacuumObserver = {
+      gotNotification: false,
+      observe: function VO_observe(aSubject, aTopic, aData) {
+        this.gotNotification = true;
+      },
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver])
+    };
+    Services.obs.addObserver(vacuumObserver, "test-begin-vacuum", false);
+
+    // Check after a couple seconds that no VACUUM has been run.
+    do_timeout(2000, function () {
+      print("Check VACUUM did not run.");
+      do_check_false(vacuumObserver.gotNotification);
+      Services.obs.removeObserver(vacuumObserver, "test-begin-vacuum");
+      run_next_test();
+    });
+
+    synthesize_idle_daily();
+  },
+
+  /* Changing page size on WAL is not supported till Bug 634374 is properly fixed.
+  function test_wal_restore_fail()
+  {
+    print("\n*** Test that a failing WAL restoration notifies failure");