Merge m-c to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 01 Oct 2015 14:15:17 +0200
changeset 265617 aa0ca170be6f9292bbb3c49bad796863b964f3a8
parent 265616 0420833dbe12cf310782ff0772ff0c84fb6c42f4 (current diff)
parent 265494 2c1fb007137dcb68b1862a79553b53f1a34c99c3 (diff)
child 265618 bf38814617d728e9db39749d018cde81b33dd5a3
push id15472
push usercbook@mozilla.com
push dateFri, 02 Oct 2015 11:51:34 +0000
treeherderfx-team@2c33ef6b27e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone44.0a1
Merge m-c to mozilla-inbound
browser/components/loop/content/shared/img/svg/glyph-account-16x16.svg
browser/components/loop/content/shared/img/svg/glyph-signin-16x16.svg
browser/components/loop/content/shared/img/svg/glyph-signout-16x16.svg
new file mode 100644
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,5 @@
+{
+  "plugins": [
+    "mozilla"
+  ]
+}
--- a/.gitignore
+++ b/.gitignore
@@ -66,8 +66,11 @@ GRTAGS
 GSYMS
 GPATH
 
 # Git clone directory for updating web-platform-tests
 testing/web-platform/sync/
 
 # Android Gradle artifacts.
 mobile/android/gradle/.gradle
+
+# Ignore node_modules from eslint-plugin-mozilla
+testing/eslint-plugin-mozilla/node_modules/
--- a/.hgignore
+++ b/.hgignore
@@ -88,8 +88,11 @@ GPATH
 
 # XCode project cruft
 ^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/project.xcworkspace/xcuserdata
 ^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/xcuserdata
 
 # Ignore mozharness execution files
 ^testing/mozharness/logs/
 ^testing/mozharness/build/
+
+# Ignore node_modules from eslint-plugin-mozilla
+^testing/eslint-plugin-mozilla/node_modules/
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,20 +10,20 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <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="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,20 +10,20 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <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="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12ff7481566587aa4198cf1287598acb3a999973"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,18 +12,18 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,19 +10,19 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,19 +10,19 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12ff7481566587aa4198cf1287598acb3a999973"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,20 +10,20 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <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="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "be2da974ba076e06e2ff96cd3ac911769d3067a3", 
+        "git_revision": "bd8ff00faac97ad6a2df5a6217910b8d295d56a3", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "2194f873784f9366087ee7899640b58c7150dff4", 
+    "revision": "69bb3f2fc1245710dbca570a4dfaedf57d39f56b", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-kk/sources.xml
@@ -10,20 +10,20 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <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="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -13,18 +13,18 @@
   <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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,20 +10,20 @@
   <!--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="be2da974ba076e06e2ff96cd3ac911769d3067a3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bd8ff00faac97ad6a2df5a6217910b8d295d56a3"/>
   <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="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
   <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="f004530b30a63c08a16d82536858600446b2abf5"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7323,22 +7323,29 @@ var gIdentityHandler = {
     menulist.setAttribute("oncommand", "gIdentityHandler.setPermission('" +
                                        aPermission + "', this.value)");
     menulist.setAttribute("id", "identity-popup-permission:" + aPermission);
 
     let label = document.createElement("label");
     label.setAttribute("flex", "1");
     label.setAttribute("class", "identity-popup-permission-label");
     label.setAttribute("control", menulist.getAttribute("id"));
-    label.setAttribute("value", SitePermissions.getPermissionLabel(aPermission));
+    label.textContent = SitePermissions.getPermissionLabel(aPermission);
 
     let container = document.createElement("hbox");
     container.setAttribute("align", "center");
     container.appendChild(label);
     container.appendChild(menulist);
+
+    // The menuitem text can be long and we don't want the dropdown
+    // to expand to the width of unselected labels.
+    // Need to set this attribute after it's appended, otherwise it gets
+    // overridden with sizetopopup="pref".
+    menulist.setAttribute("sizetopopup", "none");
+
     return container;
   }
 };
 
 function getNotificationBox(aWindow) {
   var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document);
   if (foundBrowser)
     return gBrowser.getNotificationBox(foundBrowser)
--- a/browser/base/content/test/general/browser_permissions.js
+++ b/browser/base/content/test/general/browser_permissions.js
@@ -25,16 +25,21 @@ add_task(function* testMainViewVisible()
   ok(!is_hidden(emptyLabel), "List of permissions is empty");
   gIdentityHandler._identityPopup.hidden = true;
 
   gIdentityHandler.setPermission("install", 1);
 
   gIdentityHandler._identityBox.click();
   ok(is_hidden(emptyLabel), "List of permissions is not empty");
 
+  let labelText = SitePermissions.getPermissionLabel("install");
+  let labels = permissionsList.querySelectorAll(".identity-popup-permission-label");
+  is(labels.length, 1, "One permission visible in main view");
+  is(labels[0].textContent, labelText, "Correct value");
+
   let menulists = permissionsList.querySelectorAll("menulist");
   is(menulists.length, 1, "One permission visible in main view");
   is(menulists[0].id, "identity-popup-permission:install", "Install permission visible");
   is(menulists[0].value, "1", "Correct value on install menulist");
   gIdentityHandler._identityPopup.hidden = true;
 
   gIdentityHandler.setPermission("install", SitePermissions.getDefault("install"));
 
--- a/browser/components/loop/content/css/panel.css
+++ b/browser/components/loop/content/css/panel.css
@@ -886,46 +886,16 @@ html[dir="rtl"] .user-details .dropdown-
 html[dir="rtl"] .settings-menu .dropdown-menu {
   /* This is specified separately rather than using -moz-margin-start etc, as
      we need to override .dropdown-menu's values which can't use the gecko
      specific extensions. */
   left: 14px;
   right: auto;
 }
 
-.settings-menu .icon {
-  background-size: contain;
-  background-repeat: no-repeat;
-  background-position: center;
-  width: 12px;
-  height: 12px;
-  -moz-margin-end: 1em;
-  margin-top: 2px;
-}
-
-.settings-menu .icon-tour {
-  background-image: url("../shared/img/icons-16x16.svg#tour");
-}
-
-.settings-menu .icon-account {
-  background-image: url(../shared/img/svg/glyph-account-16x16.svg);
-}
-
-.settings-menu .icon-signin {
-  background-image: url(../shared/img/svg/glyph-signin-16x16.svg);
-}
-
-.settings-menu .icon-signout {
-  background-image: url(../shared/img/svg/glyph-signout-16x16.svg);
-}
-
-.settings-menu .icon-help {
-  background-image: url(../shared/img/svg/glyph-help-16x16.svg);
-}
-
 /* Footer */
 
 .footer {
   display: flex;
   flex-direction: row;
   flex-wrap: nowrap;
   justify-content: space-between;
   align-content: stretch;
--- a/browser/components/loop/content/shared/img/icons-16x16.svg
+++ b/browser/components/loop/content/shared/img/icons-16x16.svg
@@ -66,17 +66,16 @@
       <rect x="7.75" y="7.542" fill="#fff" width="0.5" height="4"/>
       <polyline fill="#fff" points="9.25,7.542 8.75,7.542 8.75,11.542 9.25,11.542  "/>
       <rect x="6.75" y="7.542" fill="#fff" width="0.5" height="4"/>
     </g>
     <g id="leave-shape">
       <polygon fill="#fff" points="2.08,11.52 2.08,4 8,4 8,2.24 0.32,2.24 0.32,13.28 8,13.28 8,11.52"/>
       <polygon fill="#fff" points="15.66816,7.77344 9.6,2.27456 9.6,5.6 3.68,5.6 3.68,9.92 9.6,9.92 9.6,13.27232"/>
     </g>
-    <path id="tour-shape" fill="#5a5a5a" d="M8,0C4.831,0,2.262,2.674,2.262,5.972c0,1.393,1.023,3.398,2.206,5.249l0.571, 0.866C6.504,14.245,8,16,8,16 s1.496-1.755,2.961-3.912l0.571-0.866c1.182-1.852,2.206-3.856,2.206-5.249C13.738,2.674, 11.169,0,8,0z M8,7.645 c-0.603,0-1.146-0.262-1.534-0.681C6.098,6.566,5.87,6.025,5.87,5.428c0-1.224,0.954-2.217, 2.13-2.217s2.13,0.992,2.13,2.217 C10.13,6.653,9.177,7.645,8,7.645z"/>
     <g id="delete-shape">
       <path fill="#ccc" d="M14.191,4.579c0-1.149-0.832-2.08-1.857-2.08h-0.902V1.997C11.432,0.894,10.633,0,9.648,0H6.352 C5.367,0,4.568,0.894,4.568,1.997v0.502H3.666c-1.026,0-1.857,0.932-1.857,2.08v1.389h1.064l0.785,8.416 C3.742,15.29,4.499,16,5.383,16h5.231c0.883,0,1.64-0.709,1.724-1.614l0.788-8.417h1.064V4.579z M5.535,2.218V2.065 c0-0.58,0.42-1.05,0.938-1.05h3.055c0.518,0,0.937,0.47,0.937,1.05v0.153c0,0.098-0.016,0.191-0.038,0.281H5.573 C5.55,2.409,5.535,2.316,5.535,2.218z M11.184,14.277c-0.029,0.305-0.29,0.562-0.57,0.562H5.383c-0.281,0-0.541-0.257-0.57-0.562 L4.038,5.969h7.924L11.184,14.277z"/>
       <rect x="7.612" y="7.291" fill="#ccc" width="0.774" height="6.191"/>
       <polyline fill="#ccc" points="9.934,7.291 9.16,7.291 9.16,13.482 9.934,13.482  "/>
       <rect x="6.065" y="7.291" fill="#ccc" width="0.774" height="6.191"/>
     </g>
     <g id="globe-shape" transform="translate(-40.000000, -40.000000)" fill-rule="evenodd">
       <path d="M48,56 C52.418278,56 56,52.418278 56,48 C56,43.581722 52.418278,40 48,40 C43.581722,40 40,43.581722 40,48 C40,52.418278 43.581722,56 48,56 Z M42.630492,47.0453156 C42.5321586,46.9747601 42.3116031,46.9575379 42.3388253,46.7925379 C42.3560475,46.6919823 42.4593808,46.613649 42.5438253,46.5642045 C42.6538253,46.5003156 42.7766031,46.4980934 42.9010475,46.5092045 C42.9310475,46.5119823 42.9866031,46.5069823 43.0021586,46.5297601 C43.010492,46.5425379 43.0277142,46.5492045 43.0416031,46.553649 C43.0743808,46.563649 43.1088253,46.5642045 43.1427142,46.5703156 C43.1932697,46.5803156 43.2288253,46.6247601 43.280492,46.588649 C43.3388253,46.5469823 43.3482697,46.5392045 43.4188253,46.5475379 C43.4827142,46.5553156 43.520492,46.5064268 43.5743808,46.5108712 C43.5910475,46.5125379 43.605492,46.5158712 43.6182697,46.5208712 C43.6238253,46.5030934 43.6316031,46.4869823 43.6427142,46.483649 C43.6693808,46.4753156 43.7282697,46.5403156 43.755492,46.5458712 C43.825492,46.5597601 43.8210475,46.5114268 43.8266031,46.4608712 C43.8616031,46.4542045 43.8782697,46.5030934 43.910492,46.4725379 C43.9093808,46.4825379 43.915492,46.4964268 43.9149364,46.5069823 C43.9221586,46.5114268 43.9288253,46.5114268 43.9360475,46.5064268 C43.9388253,46.5003156 43.9393808,46.4947601 43.9377142,46.488649 C43.9543808,46.4942045 43.9632697,46.4819823 43.965492,46.4614268 C43.9777142,46.4630934 43.9982697,46.4553156 44.0110475,46.4575379 C44.0199364,46.4208712 44.0416031,46.3730934 44.0149364,46.3397601 C44.0221586,46.3380934 44.0288253,46.3369823 44.0360475,46.3347601 C44.0366031,46.2997601 44.060492,46.2830934 44.0616031,46.253649 C44.0232697,46.248649 43.9816031,46.2508712 43.9421586,46.2519823 C43.965492,46.2303156 44.0216031,46.1830934 44.0271586,46.1542045 C44.0371586,46.103649 43.9699364,46.0719823 43.975492,46.0114268 C43.9816031,46.043649 44.0182697,46.1169823 44.0521586,46.1280934 C44.1282697,46.153649 44.1066031,46.0775379 44.1121586,46.0380934 C44.130492,45.9130934 44.2432697,46.0164268 44.2449364,46.0819823 C44.2782697,46.0064268 44.3599364,46.0897601 44.3232697,46.1542045 C44.3049364,46.1858712 44.2799364,46.173649 44.3021586,46.2147601 C44.3182697,46.243649 44.3416031,46.2447601 44.3749364,46.2369823 C44.3843808,46.2197601 44.3921586,46.2003156 44.3916031,46.1803156 C44.4499364,46.1619823 44.4877142,46.2314268 44.4538253,46.273649 C44.4971586,46.2497601 44.5421586,46.2269823 44.5888253,46.2153156 C44.560492,46.1197601 44.5327142,46.0253156 44.5510475,45.9219823 C44.5549364,45.8997601 44.5582697,45.873649 44.5749364,45.8564268 C44.5966031,45.8342045 44.5693808,45.8430934 44.5671586,45.8280934 C44.5616031,45.7825379 44.6093808,45.7369823 44.6271586,45.6969823 C44.5766031,45.6853156 44.6232697,45.5869823 44.6560475,45.5703156 C44.6916031,45.5519823 44.7982697,45.5814268 44.8049364,45.5530934 C44.8260475,45.5653156 44.8460475,45.5819823 44.8721586,45.5825379 C44.9299364,45.5830934 44.9693808,45.5842045 45.0093808,45.6314268 C45.030492,45.6553156 45.0593808,45.7103156 45.0960475,45.7142045 C45.0949364,45.7547601 45.1416031,45.7853156 45.0927142,45.8197601 C45.0543808,45.8464268 45.0010475,45.8397601 44.9849364,45.8914268 C44.9749364,45.923649 44.9443808,45.9380934 44.990492,45.9608712 C45.0116031,45.9708712 45.0360475,45.973649 45.0588253,45.9730934 C45.0638253,46.0053156 45.0793808,46.0458712 45.1199364,46.0408712 C45.1988253,46.0314268 45.2149364,45.9330934 45.2782697,45.8997601 C45.3793808,45.8464268 45.3632697,46.0780934 45.4521586,46.0192045 C45.4732697,46.0058712 45.4732697,45.9469823 45.4832697,45.9247601 C45.5043808,45.8769823 45.5299364,45.8297601 45.560492,45.7869823 C45.5988253,45.7342045 45.6477142,45.678649 45.6310475,45.608649 C45.6221586,45.5703156 45.5477142,45.5542045 45.5138253,45.5269823 C45.4727142,45.4942045 45.4343808,45.458649 45.4093808,45.4125379 C45.3949364,45.3853156 45.3860475,45.3747601 45.4099364,45.3619823 C45.4238253,45.3542045 45.4188253,45.338649 45.4138253,45.3280934 C45.3888253,45.2742045 45.3193808,45.1792045 45.4160475,45.1464268 C45.4371586,45.1392045 45.4821586,45.0703156 45.4849364,45.0430934 C45.4899364,44.9980934 45.4221586,44.9580934 45.4527142,44.9130934 C45.475492,44.8792045 45.5310475,44.858649 45.560492,44.8247601 C45.5738253,44.8092045 45.5899364,44.7953156 45.6110475,44.7908712 C45.6127142,44.7725379 45.6166031,44.7525379 45.6321586,44.7403156 C45.6582697,44.7214268 45.6982697,44.7303156 45.7277142,44.7214268 C45.7760475,44.7064268 45.7977142,44.6558712 45.8360475,44.6275379 C45.8671586,44.6042045 45.9038253,44.6125379 45.9371586,44.5964268 C45.955492,44.5875379 45.9632697,44.5680934 45.9810475,44.5597601 C46.025492,44.5380934 46.0760475,44.5725379 46.0960475,44.6103156 C46.1443808,44.7003156 46.2038253,44.838649 46.3399364,44.8025379 C46.3943808,44.7875379 46.435492,44.7425379 46.4527142,44.6908712 C46.4693808,44.6419823 46.4499364,44.6014268 46.4527142,44.5525379 C46.4571586,44.4680934 46.5416031,44.413649 46.5499364,44.328649 C46.4866031,44.3297601 46.5193808,44.2897601 46.4988253,44.2542045 C46.475492,44.2130934 46.4221586,44.2430934 46.3866031,44.2364268 C46.4227142,44.1503156 46.4227142,44.1192045 46.3377142,44.0780934 C46.3010475,44.0597601 46.2393808,43.973649 46.2116031,43.9769823 C46.2349364,43.9447601 46.2899364,43.998649 46.3066031,44.0142045 C46.3432697,44.0492045 46.3760475,44.0653156 46.4282697,44.0692045 C46.4138253,44.0464268 46.4060475,44.0058712 46.4160475,43.9803156 C46.425492,43.9564268 46.4016031,43.9319823 46.4038253,43.9019823 C46.4632697,43.9780934 46.4532697,44.0653156 46.4877142,44.148649 C46.5021586,44.1842045 46.5360475,44.2075379 46.5510475,44.243649 C46.570492,44.2892045 46.5582697,44.2892045 46.5988253,44.3169823 C46.6227142,44.3330934 46.6310475,44.363649 46.635492,44.3903156 C46.6427142,44.4375379 46.6599364,44.4169823 46.6849364,44.443649 C46.6999364,44.4597601 46.7382697,44.4625379 46.730492,44.4953156 C46.725492,44.518649 46.7099364,44.538649 46.7066031,44.5619823 C46.6966031,44.633649 46.8360475,44.5375379 46.8493808,44.5275379 C46.8788253,44.5053156 46.9277142,44.5003156 46.9516031,44.473649 C46.975492,44.4458712 46.9699364,44.4058712 46.9960475,44.3792045 C47.0277142,44.3469823 47.0582697,44.3692045 47.0971586,44.3625379 C47.1410475,44.3558712 47.1793808,44.3208712 47.2121586,44.293649 C47.2821586,44.2353156 47.3260475,44.1708712 47.3849364,44.103649 C47.3599364,44.1097601 47.2721586,44.1730934 47.2677142,44.1147601 C47.2338253,44.113649 47.1582697,44.108649 47.1460475,44.0719823 C47.1371586,44.0453156 47.140492,44.0164268 47.1399364,43.988649 C47.1393808,43.9603156 47.1043808,43.9697601 47.0810475,43.9547601 C47.0343808,43.9242045 47.0110475,43.8697601 46.9610475,43.8430934 C46.8816031,43.8014268 46.8332697,43.7347601 46.7860475,43.6630934 C46.7582697,43.6208712 46.6610475,43.5358712 46.6677142,43.4853156 C46.6727142,43.4525379 46.6999364,43.4169823 46.6982697,43.383649 C46.6966031,43.3547601 46.6732697,43.338649 46.6760475,43.3053156 C46.6799364,43.2664268 46.5860475,43.1992045 46.6677142,43.1914268 C46.6943808,43.1892045 46.6977142,43.158649 46.7260475,43.1414268 C46.7582697,43.1219823 46.7510475,43.1053156 46.7860475,43.1147601 C46.8421586,43.1308712 46.8816031,43.0697601 46.9199364,43.0364268 C46.985492,42.978649 46.880492,42.9769823 46.8749364,42.9342045 C46.8693808,42.8897601 46.8438253,42.8575379 46.8371586,42.8064268 C46.8327142,42.7692045 46.7977142,42.783649 46.7777142,42.7930934 C46.7499364,42.8058712 46.7227142,42.7869823 46.6960475,42.7814268 C46.6710475,42.7764268 46.6510475,42.7358712 46.6221586,42.748649 C46.5999364,42.758649 46.600492,42.7864268 46.5688253,42.7830934 C46.5449364,42.7803156 46.530492,42.7575379 46.5066031,42.7542045 C46.4710475,42.7492045 46.5027142,42.7830934 46.4627142,42.7869823 C46.4338253,42.788649 46.3421586,42.7497601 46.3399364,42.7869823 C46.310492,42.7375379 46.2993808,42.8208712 46.2682697,42.8297601 C46.2349364,42.8397601 46.1982697,42.8303156 46.1649364,42.843649 C46.0910475,42.873649 46.1143808,42.9475379 46.1860475,42.958649 C46.2432697,42.9680934 46.1688253,43.0069823 46.1877142,43.0458712 C46.2043808,43.0803156 46.2099364,43.103649 46.2471586,43.1175379 C46.3093808,43.1403156 46.3749364,43.158649 46.3532697,43.2380934 C46.325492,43.3364268 46.2566031,43.4292045 46.1599364,43.4742045 C46.0677142,43.5169823 46.0427142,43.3997601 45.9727142,43.3703156 C45.9293808,43.3525379 45.8799364,43.358649 45.8349364,43.3642045 C45.8266031,43.3758712 45.8988253,43.3975379 45.9099364,43.418649 C45.9316031,43.4603156 45.8732697,43.4553156 45.8688253,43.4864268 C45.8643808,43.513649 45.8293808,43.5330934 45.8482697,43.5603156 C45.8282697,43.5347601 45.7888253,43.568649 45.775492,43.5830934 C45.755492,43.6053156 45.7593808,43.618649 45.7677142,43.6453156 C45.7849364,43.7003156 45.7027142,43.7569823 45.6532697,43.7497601 C45.6121586,43.7442045 45.5727142,43.7469823 45.5338253,43.7280934 C45.4866031,43.7053156 45.5032697,43.7192045 45.4932697,43.6664268 C45.4838253,43.6175379 45.4160475,43.5964268 45.4560475,43.5353156 C45.4843808,43.4897601 45.4710475,43.4947601 45.465492,43.4514268 C45.4593808,43.4064268 45.4799364,43.4008712 45.515492,43.393649 C45.5543808,43.3858712 45.5716031,43.3175379 45.595492,43.283649 C45.6010475,43.2758712 45.6243808,43.2142045 45.5871586,43.2303156 C45.5649364,43.2392045 45.5816031,43.2658712 45.5488253,43.2714268 C45.5243808,43.2747601 45.5016031,43.2592045 45.4777142,43.2592045 C45.4499364,43.2592045 45.420492,43.2730934 45.395492,43.2553156 C45.4077142,43.2403156 45.4999364,43.1664268 45.4271586,43.1503156 C45.3982697,43.1442045 45.4227142,43.1914268 45.3843808,43.1853156 C45.3760475,43.2230934 45.3310475,43.218649 45.3088253,43.2430934 C45.3177142,43.2030934 45.4027142,43.173649 45.3749364,43.1414268 C45.4349364,43.0880934 45.4471586,43.0792045 45.365492,43.0503156 C45.2371586,43.0053156 45.2471586,42.8742045 45.335492,42.7942045 C45.4160475,42.7214268 45.5488253,42.6292045 45.6266031,42.7503156 C45.710492,42.8797601 45.7638253,42.7858712 45.8327142,42.7025379 C45.8093808,42.6925379 45.830492,42.6864268 45.8227142,42.6580934 C45.7466031,42.688649 45.6788253,42.5903156 45.7310475,42.5308712 C45.7621586,42.4958712 45.8116031,42.5058712 45.8532697,42.4953156 C45.8916031,42.4853156 45.9249364,42.4480934 45.940492,42.4147601 C45.9088253,42.4230934 45.9127142,42.403649 45.9249364,42.3892045 C45.905492,42.3875379 45.8849364,42.3792045 45.8688253,42.373649 C45.8232697,42.3580934 45.8260475,42.3225379 45.7782697,42.3158712 C45.6621586,42.298649 45.8982697,42.1664268 45.7827142,42.1658712 C45.7460475,42.1653156 45.7121586,42.108649 45.6849364,42.1197601 C45.665492,42.1275379 45.6616031,42.1425379 45.6377142,42.1325379 C45.6216031,42.1258712 45.6021586,42.1119823 45.5838253,42.1230934 C45.5416031,42.1492045 45.5338253,42.1175379 45.4932697,42.1303156 C45.4610475,42.1403156 45.4421586,42.1719823 45.4043808,42.163649 C45.4421586,42.1125379 45.4888253,42.0703156 45.5227142,42.0158712 C45.545492,41.9797601 45.5721586,41.9469823 45.6099364,41.9247601 C45.6299364,41.9119823 45.6871586,41.9008712 45.690492,41.8725379 C45.695492,41.8269823 45.6666031,41.8303156 45.6349364,41.8492045 C45.5527142,41.898649 45.4671586,41.9514268 45.3860475,42.003649 C45.3377142,42.0347601 45.2988253,42.0614268 45.2382697,42.0525379 C45.1921586,42.0453156 45.1732697,42.0969823 45.1360475,42.0919823 C45.1182697,42.0208712 44.7199364,42.2808712 44.6716031,42.3025379 C44.5943808,42.3375379 44.5066031,42.3964268 44.4243808,42.4164268 C44.3899364,42.4247601 44.3193808,42.5047601 44.3232697,42.4164268 C44.2816031,42.4114268 44.2499364,42.453649 44.2210475,42.4758712 C44.1810475,42.5069823 44.1327142,42.5253156 44.0899364,42.5525379 C43.9960475,42.6125379 43.9082697,42.683649 43.8210475,42.7514268 C43.7382697,42.8158712 43.655492,42.8908712 43.5688253,42.948649 C43.5388253,42.968649 43.4293808,43.0247601 43.4332697,43.0664268 C43.5110475,43.0808712 43.7743808,42.7508712 43.8482697,42.8403156 C43.8671586,42.8630934 43.7366031,42.9292045 43.7143808,42.9419823 C43.6966031,42.9519823 43.675492,42.9514268 43.6582697,42.9608712 C43.6338253,42.973649 43.6193808,42.9975379 43.5966031,43.0125379 C43.5382697,43.0503156 43.4882697,43.098649 43.4449364,43.1525379 C43.4132697,43.1919823 43.3910475,43.2425379 43.3577142,43.2792045 C43.3632697,43.2408712 43.355492,43.2130934 43.3566031,43.1758712 C43.3127142,43.2030934 43.2949364,43.2508712 43.2343808,43.2369823 C43.1799364,43.2247601 43.1360475,43.2803156 43.0966031,43.3103156 C43.005492,43.3797601 42.9443808,43.4569823 42.8677142,43.538649 C42.825492,43.5842045 42.7799364,43.6164268 42.7532697,43.673649 C42.7249364,43.7342045 42.6843808,43.7892045 42.6466031,43.8453156 C42.5766031,43.9492045 42.4949364,44.0447601 42.4243808,44.148649 C42.2816031,44.3614268 42.1871586,44.6058712 42.0699364,44.8319823 C42.0082697,44.9497601 41.9499364,45.0664268 41.9260475,45.1969823 C41.9043808,45.3108712 41.9032697,45.4269823 41.9066031,45.5419823 C41.970492,45.4914268 41.9671586,45.5975379 41.9510475,45.6280934 C41.9260475,45.6764268 41.9171586,45.7308712 41.9088253,45.783649 C41.8982697,45.853649 41.8860475,45.923649 41.8860475,45.9942045 C41.8866031,46.053649 41.8671586,46.1097601 41.865492,46.1675379 C41.8427142,46.1508712 41.8916031,46.0780934 41.8488253,46.0880934 C41.8277142,46.0930934 41.8266031,46.1247601 41.8216031,46.1403156 C41.8043808,46.1958712 41.7288253,46.1908712 41.7177142,46.253649 C41.710492,46.2930934 41.7066031,46.3147601 41.680492,46.3464268 C41.6616031,46.3697601 41.6799364,46.3803156 41.6838253,46.403649 C41.6938253,46.4603156 41.6216031,46.5369823 41.6410475,46.5819823 C41.6593808,46.6253156 41.6460475,46.6747601 41.6660475,46.7164268 C41.6766031,46.7380934 41.7010475,46.7658712 41.6910475,46.7925379 C41.6466031,46.8014268 41.7043808,46.9058712 41.7082697,46.9380934 C41.7149364,46.9908712 41.7610475,47.1553156 41.8127142,47.178649 C41.8760475,47.2769823 41.9627142,47.4125379 42.0749364,47.4614268 C42.1549364,47.4958712 42.1838253,47.393649 42.2282697,47.3503156 C42.2849364,47.2947601 42.3571586,47.2597601 42.4321586,47.233649 C42.4949364,47.2114268 42.7560475,47.1353156 42.630492,47.0453156 Z M48.0699364,48.1330934 C48.0499364,48.1330934 48.0143808,48.1469823 47.9982697,48.1608712 C47.9660475,48.1880934 48.0343808,48.2047601 48.0610475,48.2125379 C48.090492,48.2292045 48.1321586,48.2380934 48.1616031,48.2547601 C48.1860475,48.2725379 48.2027142,48.2975379 48.230492,48.3097601 C48.2643808,48.3253156 48.310492,48.3330934 48.3477142,48.3430934 C48.3643808,48.348649 48.3882697,48.3469823 48.4093808,48.3514268 C48.4327142,48.3647601 48.4432697,48.3864268 48.4621586,48.4008712 C48.4949364,48.4314268 48.5416031,48.438649 48.585492,48.4375379 C48.6266031,48.4414268 48.6577142,48.4480934 48.6949364,48.438649 C48.7366031,48.4280934 48.7671586,48.4497601 48.8066031,48.4492045 C48.8216031,48.4503156 48.8377142,48.4364268 48.8527142,48.4375379 C48.8727142,48.4375379 48.8749364,48.4464268 48.8843808,48.4630934 C48.9010475,48.4880934 48.945492,48.5253156 48.975492,48.5275379 C48.9949364,48.5269823 49.0093808,48.523649 49.025492,48.5292045 C49.0427142,48.5392045 49.050492,48.5397601 49.0632697,48.5508712 C49.085492,48.5597601 49.1043808,48.5669823 49.1143808,48.583649 C49.1316031,48.6130934 49.1310475,48.6469823 49.1566031,48.6697601 C49.175492,48.6842045 49.1938253,48.6992045 49.2127142,48.713649 C49.225492,48.7247601 49.2149364,48.7225379 49.2343808,48.7225379 C49.245492,48.7247601 49.2649364,48.7242045 49.2788253,48.7208712 C49.3321586,48.7169823 49.3027142,48.6425379 49.2866031,48.6175379 C49.275492,48.5958712 49.2660475,48.5792045 49.2710475,48.558649 C49.2738253,48.533649 49.2849364,48.5169823 49.2693808,48.4964268 C49.2610475,48.4842045 49.2493808,48.4775379 49.2377142,48.4708712 C49.2310475,48.4630934 49.2282697,48.453649 49.220492,48.4414268 C49.2049364,48.4208712 49.1738253,48.4147601 49.1538253,48.3953156 C49.1193808,48.3603156 49.1021586,48.3119823 49.0588253,48.2792045 C49.035492,48.2658712 49.0132697,48.2764268 48.985492,48.2642045 C48.9738253,48.2575379 48.9671586,48.2497601 48.950492,48.2442045 C48.9343808,48.238649 48.9199364,48.2419823 48.905492,48.2408712 C48.8749364,48.238649 48.8482697,48.2119823 48.8188253,48.2147601 C48.785492,48.2180934 48.7799364,48.2530934 48.7599364,48.2725379 C48.7438253,48.2864268 48.7238253,48.2864268 48.7182697,48.2642045 C48.715492,48.2358712 48.7260475,48.218649 48.7410475,48.2003156 C48.7643808,48.1753156 48.7410475,48.1619823 48.710492,48.1597601 C48.6710475,48.1603156 48.6643808,48.1908712 48.6482697,48.223649 C48.6227142,48.2592045 48.6060475,48.2342045 48.570492,48.228649 C48.5460475,48.2303156 48.5288253,48.2397601 48.5066031,48.2303156 C48.4899364,48.2253156 48.4866031,48.2114268 48.4749364,48.2047601 C48.4577142,48.1947601 48.4432697,48.1980934 48.430492,48.2064268 C48.4121586,48.2108712 48.4121586,48.2108712 48.3943808,48.2008712 C48.3782697,48.1953156 48.3749364,48.1814268 48.3538253,48.1775379 C48.3227142,48.1708712 48.2899364,48.1980934 48.2632697,48.1903156 C48.2516031,48.183649 48.2421586,48.1669823 48.2260475,48.1614268 C48.2082697,48.1514268 48.2110475,48.1603156 48.1993808,48.1730934 C48.1799364,48.1925379 48.1516031,48.1992045 48.1327142,48.1847601 C48.1088253,48.1669823 48.1060475,48.138649 48.0699364,48.1330934 Z M48.8121586,48.8430934 C48.805492,48.8297601 48.8127142,48.8164268 48.8127142,48.803649 C48.8093808,48.7803156 48.8027142,48.773649 48.8066031,48.7508712 C48.8132697,48.7375379 48.8132697,48.7175379 48.8099364,48.7008712 C48.8038253,48.6875379 48.7938253,48.6780934 48.7832697,48.6680934 C48.7838253,48.6614268 48.780492,48.6514268 48.7738253,48.6447601 C48.7599364,48.6314268 48.7466031,48.6508712 48.7327142,48.6575379 C48.7227142,48.6675379 48.7021586,48.673649 48.6982697,48.683649 C48.6882697,48.7003156 48.6949364,48.713649 48.6949364,48.7269823 L48.6977142,48.7430934 C48.6738253,48.7664268 48.6971586,48.8292045 48.6932697,48.8525379 C48.6932697,48.878649 48.655492,48.9542045 48.7066031,48.9314268 C48.7199364,48.9247601 48.730492,48.9153156 48.7438253,48.908649 C48.7610475,48.898649 48.7810475,48.8992045 48.8016031,48.8925379 C48.8082697,48.8925379 48.845492,48.8897601 48.845492,48.8830934 C48.8460475,48.8697601 48.815492,48.8597601 48.8121586,48.8430934 Z M49.2532697,49.4003156 C49.2616031,49.3942045 49.2743808,49.4003156 49.2810475,49.3980934 C49.2982697,49.3953156 49.3066031,49.378649 49.3216031,49.3808712 C49.3388253,49.3780934 49.3299364,49.3947601 49.3410475,49.4053156 C49.3521586,49.4153156 49.3627142,49.4153156 49.3732697,49.4153156 C49.3927142,49.4192045 49.4293808,49.4203156 49.4371586,49.403649 C49.445492,49.3764268 49.400492,49.3708712 49.3899364,49.3497601 C49.3782697,49.3192045 49.4032697,49.2892045 49.4116031,49.2619823 C49.4238253,49.2258712 49.3788253,49.2103156 49.3827142,49.1808712 C49.3816031,49.1492045 49.4032697,49.138649 49.3960475,49.1097601 C49.3916031,49.0869823 49.3716031,49.0619823 49.3588253,49.0453156 C49.345492,49.0292045 49.3216031,49.0125379 49.3232697,48.9875379 C49.3249364,48.9625379 49.3721586,48.963649 49.350492,48.9325379 C49.3371586,48.9058712 49.3027142,48.9108712 49.2727142,48.9069823 C49.2621586,48.9069823 49.2516031,48.9075379 49.240492,48.8969823 C49.2316031,48.8825379 49.235492,48.8742045 49.235492,48.863649 C49.2288253,48.8347601 49.2071586,48.8247601 49.1810475,48.8125379 C49.1721586,48.808649 49.1599364,48.8025379 49.1549364,48.7903156 C49.150492,48.7775379 49.1632697,48.7730934 49.1588253,48.7608712 C49.145492,48.733649 49.0949364,48.7725379 49.0732697,48.7619823 C49.0582697,48.7603156 49.0599364,48.7458712 49.0510475,48.7308712 L49.025492,48.7192045 C48.990492,48.7030934 48.9760475,48.7325379 48.9832697,48.7614268 C48.9993808,48.8258712 49.0471586,48.8692045 49.0416031,48.9342045 C49.0443808,48.9614268 49.0488253,48.973649 49.0577142,48.998649 C49.0671586,49.0342045 49.0766031,49.0514268 49.060492,49.0853156 C49.0349364,49.1042045 49.0577142,49.1280934 49.0671586,49.1530934 C49.0716031,49.1864268 49.080492,49.2114268 49.0788253,49.2469823 C49.0738253,49.3119823 49.0532697,49.3747601 49.0588253,49.4397601 C49.0616031,49.4664268 49.0593808,49.4919823 49.0688253,49.5169823 C49.0738253,49.5497601 49.0993808,49.5619823 49.1277142,49.5803156 C49.1538253,49.6030934 49.2771586,49.6758712 49.2410475,49.5869823 C49.2299364,49.5658712 49.2127142,49.5369823 49.2077142,49.5142045 C49.1988253,49.4892045 49.2288253,49.4719823 49.230492,49.4469823 C49.2338253,49.4175379 49.2127142,49.4075379 49.2532697,49.4003156 Z M48.2932697,41.9630934 C48.3249364,41.9964268 48.3632697,42.0064268 48.3560475,42.0603156 C48.3971586,42.0653156 48.4227142,42.0808712 48.4460475,42.0464268 C48.4599364,42.0247601 48.4827142,42.0080934 48.5066031,41.9992045 C48.5366031,41.9875379 48.6588253,41.988649 48.6532697,42.0380934 C48.650492,42.0630934 48.6349364,42.0853156 48.6310475,42.1092045 C48.6260475,42.1430934 48.6621586,42.118649 48.6793808,42.1275379 C48.660492,42.1397601 48.6382697,42.1480934 48.6160475,42.153649 C48.6260475,42.1592045 48.6316031,42.1680934 48.6332697,42.1792045 C48.605492,42.1858712 48.5916031,42.2625379 48.5432697,42.2775379 C48.5132697,42.2869823 48.470492,42.2669823 48.440492,42.2630934 C48.405492,42.258649 48.3788253,42.248649 48.3438253,42.2464268 C48.3093808,42.2442045 48.3371586,42.1997601 48.2949364,42.2080934 C48.2871586,42.2375379 48.3027142,42.3142045 48.3071586,42.343649 C48.3132697,42.3814268 48.3443808,42.4030934 48.3816031,42.4092045 C48.4332697,42.4175379 48.4582697,42.4347601 48.5027142,42.4597601 C48.5377142,42.4797601 48.5771586,42.4680934 48.615492,42.4714268 C48.6399364,42.473649 48.6616031,42.483649 48.680492,42.498649 C48.6766031,42.5108712 48.6677142,42.5303156 48.6732697,42.5430934 C48.6810475,42.5597601 48.7349364,42.5403156 48.7482697,42.5392045 C48.7860475,42.5353156 48.8216031,42.493649 48.8577142,42.4992045 C48.8716031,42.5014268 48.935492,42.5208712 48.9327142,42.5364268 C48.8982697,42.5225379 48.8760475,42.5647601 48.8499364,42.5414268 C48.8260475,42.5208712 48.7632697,42.5392045 48.8038253,42.5675379 C48.8077142,42.5703156 48.8182697,42.6508712 48.8171586,42.6592045 C48.8143808,42.6897601 48.760492,42.7214268 48.7643808,42.7408712 C48.7716031,42.7419823 48.820492,42.7458712 48.8316031,42.7547601 C48.8349364,42.7414268 48.8249364,42.7364268 48.8549364,42.7280934 C48.8771586,42.7214268 48.9032697,42.7192045 48.925492,42.7297601 C48.9349364,42.7669823 48.9071586,42.8058712 48.9588253,42.7964268 C49.0077142,42.7869823 49.0288253,42.818649 49.0799364,42.7858712 C49.1110475,42.7664268 49.1460475,42.7703156 49.1732697,42.7969823 C49.2099364,42.8342045 49.1349364,42.8842045 49.1777142,42.9192045 C49.1949364,42.933649 49.2088253,42.9764268 49.225492,42.9842045 C49.2371586,42.9892045 49.3010475,42.9669823 49.3127142,42.9608712 C49.3327142,42.9980934 49.3510475,42.9425379 49.3677142,42.938649 C49.3727142,42.9158712 49.4027142,42.8880934 49.4316031,42.8853156 C49.4743808,42.8814268 49.4749364,42.888649 49.5038253,42.908649 C49.5871586,42.9669823 49.575492,42.8253156 49.6193808,42.7892045 C49.6982697,42.7247601 49.7371586,42.6642045 49.7910475,42.5808712 C49.8338253,42.5153156 49.8927142,42.498649 49.9677142,42.4869823 C50.0277142,42.4775379 50.1182697,42.463649 50.1427142,42.3997601 C50.1716031,42.3247601 50.1032697,42.283649 50.0421586,42.2614268 C49.9743808,42.2375379 49.8977142,42.2119823 49.9277142,42.1264268 C49.9627142,42.0269823 49.9321586,41.9692045 49.8266031,41.9369823 C49.6027142,41.8675379 49.4010475,41.7503156 49.1732697,41.6864268 C48.9716031,41.6303156 48.7682697,41.6092045 48.5610475,41.5980934 C48.4688253,41.5664268 48.2743808,41.5630934 48.2177142,41.6414268 C48.1810475,41.6919823 48.2277142,41.7358712 48.2232697,41.788649 C48.2177142,41.8514268 48.2488253,41.9158712 48.2932697,41.9630934 Z M47.8549364,50.1964268 C47.8977142,50.2175379 47.9710475,50.1764268 48.0121586,50.1630934 C48.0627142,50.1475379 48.1432697,50.0942045 48.195492,50.123649 C48.2166031,50.1353156 48.2266031,50.1597601 48.2499364,50.1697601 C48.2771586,50.1814268 48.3099364,50.1708712 48.3371586,50.1647601 C48.3660475,50.1580934 48.3982697,50.153649 48.4249364,50.1408712 C48.4482697,50.1297601 48.4632697,50.1103156 48.4832697,50.0947601 C48.5360475,50.0558712 48.580492,50.0925379 48.6377142,50.0842045 C48.6699364,50.0797601 48.700492,50.063649 48.7327142,50.0558712 C48.7560475,50.0497601 48.7971586,50.0503156 48.815492,50.0330934 C48.8360475,50.013649 48.8266031,49.9719823 48.8260475,49.9475379 C48.8249364,49.9142045 48.8277142,49.8803156 48.815492,49.848649 C48.7921586,49.7875379 48.7077142,49.7158712 48.7949364,49.6680934 C48.8121586,49.5608712 48.6877142,49.5792045 48.6516031,49.5019823 C48.6282697,49.4514268 48.620492,49.4130934 48.5538253,49.4075379 C48.4966031,49.4025379 48.4638253,49.4319823 48.4143808,49.4514268 C48.3593808,49.4725379 48.3171586,49.4542045 48.2693808,49.4269823 C48.2410475,49.4108712 48.1799364,49.373649 48.1682697,49.4230934 C48.1582697,49.4658712 48.1988253,49.5075379 48.1649364,49.5458712 C48.135492,49.5797601 48.0838253,49.5953156 48.0410475,49.6047601 C47.9488253,49.6242045 47.8766031,49.6942045 47.8099364,49.7553156 L47.8166031,49.7619823 C47.790492,49.7614268 47.750492,49.8314268 47.7493808,49.8530934 C47.7599364,49.8558712 47.770492,49.8592045 47.7816031,49.8625379 C47.7799364,49.8992045 47.8221586,49.8747601 47.8243808,49.848649 C47.8332697,49.8503156 47.8421586,49.8558712 47.850492,49.8575379 C47.8577142,49.8592045 47.8738253,49.858649 47.8810475,49.8614268 C47.8982697,49.8692045 47.9016031,49.8864268 47.9243808,49.888649 C47.9110475,49.9442045 47.9227142,50.0030934 47.895492,50.0547601 C47.8788253,50.0875379 47.7927142,50.1669823 47.8549364,50.1964268 Z M42.7410475,50.5614268 C42.7532697,50.5408712 42.7432697,50.4858712 42.720492,50.4675379 C42.6638253,50.4208712 42.6421586,50.5319823 42.6777142,50.5647601 C42.6916031,50.5997601 42.7249364,50.588649 42.7410475,50.5614268 Z M45.9971586,42.3703156 C45.9777142,42.3692045 45.9566031,42.3708712 45.9388253,42.378649 C45.9343808,42.3803156 45.9288253,42.3847601 45.9249364,42.3892045 C45.9316031,42.3903156 45.9382697,42.3903156 45.9443808,42.388649 C45.9632697,42.3847601 45.9777142,42.3714268 45.9971586,42.3703156 Z M48.0010475,41.6769823 C48.0016031,41.6792045 48.0021586,41.6819823 48.0027142,41.6842045 C48.035492,41.6769823 48.0677142,41.6869823 48.0988253,41.6747601 C48.1149364,41.6680934 48.1660475,41.6497601 48.1632697,41.628649 C48.1577142,41.5892045 47.9893808,41.6147601 47.9621586,41.6264268 C47.9532697,41.6508712 47.9793808,41.6703156 48.0010475,41.6769823 Z M45.9310475,42.053649 C45.9727142,42.0225379 45.995492,41.9653156 46.0621586,41.9769823 C46.0599364,42.0342045 46.1160475,42.0414268 46.1571586,42.0630934 C46.1443808,42.0969823 46.0982697,42.0958712 46.0777142,42.1225379 C46.0521586,42.1553156 46.0982697,42.1847601 46.1216031,42.1992045 C46.1671586,42.2275379 46.1427142,42.258649 46.1332697,42.2992045 C46.120492,42.3547601 46.2410475,42.3397601 46.2671586,42.338649 C46.3132697,42.3358712 46.385492,42.3442045 46.4282697,42.3219823 C46.475492,42.2969823 46.4999364,42.2397601 46.5482697,42.2119823 C46.5882697,42.1892045 46.645492,42.1758712 46.690492,42.1919823 C46.7371586,42.2080934 46.7316031,42.2675379 46.7693808,42.293649 C46.8149364,42.3242045 46.8627142,42.3342045 46.9016031,42.2880934 C46.925492,42.258649 46.980492,42.2225379 46.9827142,42.1919823 C46.9866031,42.1375379 47.0021586,42.0942045 47.0632697,42.0825379 C47.1110475,42.0730934 47.1010475,42.1203156 47.1349364,42.128649 C47.2093808,42.1475379 47.245492,41.918649 47.3277142,41.9864268 C47.3471586,42.0025379 47.3527142,42.0642045 47.3849364,42.0592045 C47.4188253,42.053649 47.4199364,42.003649 47.4566031,42.0030934 C47.4682697,42.0369823 47.3932697,42.0775379 47.3832697,42.1130934 C47.4293808,42.0758712 47.4516031,42.0808712 47.5038253,42.0758712 C47.5177142,42.1114268 47.415492,42.168649 47.3893808,42.1753156 C47.3521586,42.183649 47.3299364,42.1630934 47.3016031,42.1825379 C47.2788253,42.198649 47.2482697,42.1969823 47.2221586,42.1997601 C47.1843808,42.2030934 47.1149364,42.2525379 47.115492,42.293649 C47.115492,42.3097601 47.1282697,42.3458712 47.1149364,42.3592045 C47.1016031,42.3725379 47.0716031,42.3597601 47.0677142,42.3458712 C47.035492,42.3930934 46.9949364,42.3108712 46.9682697,42.3769823 C47.0110475,42.3869823 47.0493808,42.428649 47.0977142,42.4403156 C47.1449364,42.4519823 47.190492,42.4630934 47.2371586,42.4769823 C47.3138253,42.5003156 47.4293808,42.4075379 47.4893808,42.3619823 C47.5449364,42.3203156 47.6160475,42.2258712 47.6310475,42.1580934 C47.6477142,42.0853156 47.7288253,42.0003156 47.7121586,41.9269823 C47.6966031,41.8592045 47.6860475,41.8264268 47.7632697,41.8025379 C47.7966031,41.7919823 47.875492,41.7747601 47.8871586,41.7364268 C47.9043808,41.6808712 47.7299364,41.6958712 47.7032697,41.683649 C47.6149364,41.6442045 47.5771586,41.5997601 47.475492,41.6392045 C47.4221586,41.6597601 47.3699364,41.6769823 47.3149364,41.6919823 C47.2860475,41.6997601 47.2571586,41.7019823 47.2416031,41.7258712 C47.235492,41.7358712 47.2271586,41.743649 47.2166031,41.748649 C47.1710475,41.7664268 47.2271586,41.6803156 47.2321586,41.6747601 C47.2471586,41.6580934 47.2716031,41.6053156 47.2238253,41.6164268 C47.1538253,41.6330934 47.1032697,41.7403156 47.0271586,41.7458712 C46.9699364,41.7497601 46.9882697,41.6992045 47.0038253,41.6703156 C47.0316031,41.6180934 46.9499364,41.6119823 46.9138253,41.6114268 C46.8638253,41.6114268 46.8249364,41.6403156 46.7766031,41.6453156 C46.7310475,41.6503156 46.6782697,41.6592045 46.6327142,41.6575379 C46.540492,41.6542045 46.480492,41.7075379 46.3899364,41.6775379 C46.2949364,41.6464268 46.1916031,41.7258712 46.0999364,41.7369823 C46.0693808,41.7408712 46.0243808,41.7342045 46.0121586,41.7708712 C46.0016031,41.8008712 46.0121586,41.8475379 46.035492,41.8697601 L46.0427142,41.863649 C46.0227142,41.8830934 46.0199364,41.9119823 45.9910475,41.9225379 C45.9621586,41.9330934 45.9332697,41.9703156 45.9182697,41.9953156 C45.9066031,42.0158712 45.8738253,42.0953156 45.9310475,42.053649 Z M46.0216031,43.2903156 C46.045492,43.2597601 45.9877142,43.2325379 45.9543808,43.2358712 C45.9632697,43.1980934 46.010492,43.178649 45.9982697,43.1314268 C45.9860475,43.0825379 45.9271586,43.0919823 45.895492,43.118649 C45.8660475,43.143649 45.8510475,43.1864268 45.8266031,43.2147601 C45.8132697,43.2314268 45.7882697,43.2364268 45.7788253,43.2564268 C45.7699364,43.2747601 45.780492,43.3053156 45.7799364,43.3253156 C45.8188253,43.3303156 45.860492,43.318649 45.8888253,43.2908712 L45.9077142,43.2819823 C45.9038253,43.2858712 45.9010475,43.293649 45.8993808,43.2975379 C45.9182697,43.3214268 46.0032697,43.3147601 46.0216031,43.2903156 Z M43.5977142,52.0842045 C43.6038253,52.0658712 43.575492,52.0453156 43.5560475,52.0469823 C43.5388253,52.0480934 43.5232697,52.0708712 43.5160475,52.083649 C43.4960475,52.1214268 43.5193808,52.1719823 43.5682697,52.1719823 C43.5793808,52.1514268 43.5749364,52.1114268 43.605492,52.108649 C43.6038253,52.0992045 43.5971586,52.0958712 43.5882697,52.0925379 L43.5977142,52.0842045 Z M53.2532697,50.4553156 C53.2510475,50.4464268 53.2488253,50.4369823 53.2471586,50.4275379 C53.2038253,50.4147601 53.175492,50.4603156 53.135492,50.4269823 C53.0582697,50.478649 53.1410475,50.583649 53.0138253,50.5764268 C53.035492,50.6030934 53.0332697,50.633649 53.0232697,50.6642045 C53.0066031,50.7130934 52.9949364,50.708649 52.9616031,50.7142045 C52.8932697,50.7258712 52.8593808,50.6825379 52.8388253,50.6253156 C52.7710475,50.6264268 52.6777142,50.7319823 52.6238253,50.7647601 C52.6110475,50.7730934 52.5860475,50.7953156 52.5710475,50.8042045 C52.5593808,50.8114268 52.5310475,50.8253156 52.5160475,50.8330934 C52.480492,50.8519823 52.4027142,50.8764268 52.3982697,50.9169823 C52.380492,50.9142045 52.3527142,50.9247601 52.335492,50.9225379 C52.3293808,50.9314268 52.3293808,50.9408712 52.335492,50.9497601 C52.4177142,50.9642045 52.4610475,50.9364268 52.530492,50.9058712 C52.6043808,50.873649 52.6832697,50.8803156 52.7516031,50.8547601 C52.7843808,50.8430934 52.785492,50.8064268 52.8393808,50.828649 C52.8627142,50.838649 52.8910475,50.8730934 52.8960475,50.8969823 C52.9066031,50.9503156 52.850492,51.0292045 52.7943808,51.0330934 C52.7810475,50.9997601 52.7999364,50.9658712 52.8060475,50.938649 C52.7327142,50.913649 52.610492,51.018649 52.5899364,51.0808712 C52.6671586,51.0964268 52.6982697,51.208649 52.6577142,51.2692045 C52.6438253,51.2842045 52.6282697,51.303649 52.6010475,51.3119823 C52.5577142,51.3247601 52.5371586,51.2847601 52.4949364,51.3164268 C52.4393808,51.3580934 52.500492,51.4725379 52.4688253,51.5369823 C52.4443808,51.5858712 52.4027142,51.6042045 52.3682697,51.638649 C52.3443808,51.6630934 52.3310475,51.6897601 52.2988253,51.7114268 C52.2571586,51.7392045 52.1566031,51.798649 52.165492,51.8569823 C52.2560475,51.8875379 52.4449364,51.7292045 52.5238253,51.6769823 C52.5738253,51.643649 52.6038253,51.5919823 52.6549364,51.5597601 C52.7121586,51.523649 52.7877142,51.5058712 52.8249364,51.4419823 C52.8460475,51.4064268 52.8293808,51.3742045 52.8421586,51.3380934 C52.8532697,51.3058712 52.8760475,51.2953156 52.8971586,51.2703156 C52.9360475,51.2230934 52.9727142,51.208649 53.0171586,51.1692045 C53.0721586,51.1203156 53.0593808,51.0430934 53.0843808,50.9780934 C53.1066031,50.9208712 53.150492,50.8780934 53.180492,50.8247601 C53.2288253,50.7392045 53.3538253,50.5375379 53.3016031,50.4430934 C53.2882697,50.4530934 53.2643808,50.4508712 53.2532697,50.4553156 Z M51.8121586,51.8869823 L51.810492,51.8853156 C51.8138253,51.8914268 51.8127142,51.9003156 51.8132697,51.9080934 C51.8549364,51.9080934 51.8727142,51.9453156 51.9171586,51.9319823 C51.9632697,51.918649 51.9888253,51.8753156 51.9527142,51.8392045 C51.9216031,51.8075379 51.8938253,51.7814268 51.8466031,51.7897601 C51.7921586,51.8003156 51.8043808,51.8442045 51.8121586,51.8869823 Z M42.780492,47.3764268 C42.7943808,47.3864268 42.8127142,47.3953156 42.8266031,47.4047601 C42.840492,47.4147601 42.8621586,47.4319823 42.8788253,47.4364268 C42.9177142,47.4575379 42.9777142,47.4814268 43.0066031,47.4364268 C43.015492,47.4180934 43.0210475,47.4064268 43.010492,47.3908712 C42.9988253,47.3747601 42.9821586,47.3703156 42.9777142,47.3575379 C42.9727142,47.3442045 42.9843808,47.3347601 42.970492,47.3247601 C42.9549364,47.3108712 42.9432697,47.3197601 42.9421586,47.2903156 C42.9432697,47.2653156 42.9449364,47.2147601 42.9110475,47.2469823 C42.9021586,47.2497601 42.9143808,47.2553156 42.900492,47.2603156 C42.8916031,47.263649 42.8838253,47.2564268 42.8777142,47.2530934 C42.8593808,47.2453156 42.8482697,47.243649 42.835492,47.2630934 C42.8249364,47.2769823 42.825492,47.2914268 42.8088253,47.3025379 L42.7821586,47.3114268 C42.7727142,47.3147601 42.7443808,47.3347601 42.7432697,47.3447601 C42.7388253,47.3614268 42.7638253,47.3725379 42.780492,47.3764268 Z M52.1093808,51.7808712 C52.115492,51.7503156 52.1788253,51.6397601 52.1199364,51.623649 C52.0988253,51.6175379 52.080492,51.6503156 52.0610475,51.6558712 C52.0360475,51.663649 52.0088253,51.6475379 51.9849364,51.6603156 C51.9632697,51.6714268 51.9438253,51.7058712 51.9310475,51.7253156 C51.9149364,51.7492045 51.9210475,51.7580934 51.9466031,51.7714268 C51.9727142,51.7853156 52.005492,51.7919823 52.0199364,51.8197601 C52.0332697,51.8447601 52.0266031,51.8769823 52.0227142,51.9030934 C52.0238253,51.9014268 52.0271586,51.8980934 52.0282697,51.893649 C52.0327142,51.8925379 52.0399364,51.8914268 52.0443808,51.8925379 L52.0388253,51.903649 C52.1071586,51.9130934 52.1016031,51.8253156 52.1093808,51.7808712 Z M54.3488253,48.1230934 C54.3282697,48.0014268 54.3982697,47.8325379 54.335492,47.7158712 C54.3082697,47.6647601 54.3499364,47.5169823 54.3493808,47.4564268 C54.3482697,47.3442045 54.3149364,47.258649 54.2993808,47.153649 C54.2888253,47.0558712 54.2760475,46.7947601 54.3116031,46.7058712 C54.3621586,46.5803156 54.1143808,46.3680934 54.100492,46.2325379 C54.0882697,46.1153156 54.0210475,46.003649 53.9249364,45.9358712 C53.885492,45.9075379 53.800492,45.5192045 53.750492,45.5369823 C53.725492,45.548649 53.7771586,45.6342045 53.7738253,45.6608712 C53.760492,45.7558712 53.7127142,45.6614268 53.6621586,45.6825379 C53.570492,45.7203156 53.4732697,45.8080934 53.4610475,45.8997601 C53.4171586,46.2369823 53.1782697,45.888649 53.1971586,45.8742045 C53.250492,45.8330934 53.2693808,45.8458712 53.3310475,45.8369823 C53.400492,45.8125379 53.2932697,45.763649 53.4021586,45.7530934 C53.3766031,45.6842045 53.4332697,45.6614268 53.405492,45.6064268 C53.3643808,45.5264268 53.3349364,45.5358712 53.3766031,45.4497601 C53.3943808,45.4019823 53.2866031,45.253649 53.2777142,45.1964268 C53.2688253,45.1408712 53.2677142,45.068649 53.260492,45.0064268 C53.2560475,44.9669823 53.3210475,44.928649 53.3099364,44.8980934 C53.3071586,44.7875379 53.3316031,44.6680934 53.2927142,44.5619823 C53.265492,44.488649 53.2338253,44.3930934 53.1871586,44.3308712 C53.170492,44.308649 53.120492,44.1980934 53.1160475,44.1680934 C53.1027142,44.0992045 53.0721586,44.1253156 53.0332697,44.0975379 C53.0121586,44.0714268 52.9166031,43.9825379 52.8888253,43.9697601 C52.8638253,43.9580934 52.6793808,43.7897601 52.6749364,43.7764268 C52.6599364,43.7275379 52.5560475,43.6903156 52.5671586,43.6380934 C52.5843808,43.5580934 52.3071586,43.3525379 52.2299364,43.3397601 C52.1799364,43.3308712 52.3827142,43.5719823 52.3816031,43.5675379 C52.3849364,43.5814268 52.5121586,43.7425379 52.5116031,43.7425379 C52.5410475,43.7525379 52.610492,43.9503156 52.6082697,43.9758712 C52.600492,44.0514268 52.4066031,43.8530934 52.3921586,43.8264268 C52.2971586,43.7092045 52.1232697,43.6153156 52.0143808,43.5369823 C51.9371586,43.4658712 51.975492,43.4247601 51.8432697,43.3642045 C51.7938253,43.3414268 51.6616031,43.2325379 51.620492,43.2308712 C51.570492,43.2275379 51.6271586,43.3330934 51.6288253,43.3447601 C51.6366031,43.4197601 51.7182697,43.4253156 51.7666031,43.4747601 C51.8060475,43.5147601 51.840492,43.5653156 51.8066031,43.6097601 C51.8060475,43.6103156 51.745492,43.7214268 51.7421586,43.7114268 C51.7593808,43.758649 51.8999364,43.8630934 51.9349364,43.9019823 C51.9288253,43.8914268 52.1199364,44.1408712 52.1360475,44.008649 C52.1421586,43.9608712 52.0882697,43.9025379 52.095492,43.8614268 C52.100492,43.8347601 52.3138253,44.103649 52.3249364,44.1275379 C52.3777142,44.2697601 52.3732697,44.1058712 52.4271586,44.1225379 C52.4721586,44.1369823 52.5916031,44.2853156 52.4927142,44.2914268 C52.3399364,44.3019823 52.5199364,44.433649 52.5621586,44.453649 C52.650492,44.4964268 52.7099364,44.5958712 52.8021586,44.6330934 C52.9449364,44.6914268 52.9149364,44.7942045 52.9877142,44.8992045 C53.010492,44.9325379 52.5760475,44.898649 52.5416031,44.918649 C52.4843808,44.9625379 52.7599364,45.2708712 52.7616031,45.3169823 C52.7638253,45.4130934 52.8182697,45.483649 52.8327142,45.5803156 C52.8421586,45.6692045 52.8310475,45.7858712 52.8893808,45.8575379 C52.9371586,45.9014268 52.9816031,45.7847601 53.0566031,45.853649 C53.0843808,45.8664268 53.1238253,45.8975379 53.1327142,45.9214268 C53.1571586,45.9875379 53.3016031,46.393649 53.1288253,46.3630934 C53.0527142,46.3497601 53.0960475,46.6819823 53.1010475,46.7303156 C53.125492,46.8353156 53.1671586,46.8275379 53.1399364,46.9597601 C53.1427142,47.0703156 53.0532697,47.1258712 52.990492,47.2047601 C52.9610475,47.2408712 52.9416031,47.283649 52.9271586,47.3297601 C52.8921586,47.2958712 52.875492,47.2414268 52.8271586,47.2230934 C52.7738253,47.2030934 52.6571586,47.2664268 52.610492,47.2897601 C52.4977142,47.3458712 52.580492,47.448649 52.5366031,47.5375379 C52.5049364,47.6025379 52.4088253,47.6347601 52.3471586,47.6669823 C52.2716031,47.7053156 52.1710475,47.7464268 52.0960475,47.6847601 C52.0327142,47.6325379 52.060492,47.5292045 51.9932697,47.4842045 C51.9177142,47.433649 51.9110475,47.5464268 51.8938253,47.5908712 C51.8610475,47.6758712 51.7627142,47.7047601 51.7877142,47.8108712 C51.7982697,47.8542045 51.820492,47.893649 51.8293808,47.9375379 C51.8399364,47.9925379 51.8127142,48.0419823 51.8088253,48.0964268 C51.8032697,48.1892045 51.8999364,48.2108712 51.9260475,48.2875379 C51.9482697,48.3547601 51.9249364,48.4614268 51.8482697,48.4875379 C51.7666031,48.5158712 51.6766031,48.4419823 51.5960475,48.433649 C51.5149364,48.4253156 51.4127142,48.4480934 51.3971586,48.5397601 C51.3832697,48.6214268 51.4666031,48.6875379 51.4266031,48.7708712 C51.4093808,48.8058712 51.3799364,48.833649 51.3577142,48.8658712 C51.3210475,48.9192045 51.300492,48.9819823 51.265492,49.0364268 C51.3066031,49.0375379 51.3027142,49.0119823 51.3393808,49.0197601 C51.3788253,49.0275379 51.4132697,48.988649 51.4466031,48.9753156 C51.4521586,49.0008712 51.4493808,49.0275379 51.4527142,49.053649 C51.4799364,49.0619823 51.5077142,49.0508712 51.5321586,49.0414268 C51.535492,49.0642045 51.5249364,49.0903156 51.5343808,49.1125379 C51.5421586,49.1319823 51.5638253,49.1380934 51.5766031,49.1530934 C51.6099364,49.1930934 51.5693808,49.2580934 51.5460475,49.2919823 C51.4788253,49.3903156 51.3649364,49.4453156 51.290492,49.5369823 C51.220492,49.6230934 51.2138253,49.7264268 51.1621586,49.8197601 C51.1443808,49.8514268 51.1260475,49.8953156 51.1743808,49.9108712 C51.1838253,49.893649 51.2010475,49.8797601 51.2221586,49.8797601 C51.255492,49.8792045 51.2432697,49.9030934 51.2593808,49.9230934 C51.3288253,50.0103156 51.4021586,49.8653156 51.4310475,49.823649 C51.4616031,49.7797601 51.5843808,49.7119823 51.6188253,49.7869823 C51.6449364,49.843649 51.6143808,49.9242045 51.5877142,49.9753156 C51.6316031,49.9953156 51.6193808,50.0275379 51.6293808,50.0658712 C51.6432697,50.1192045 51.6927142,50.153649 51.6927142,50.2119823 C51.6927142,50.2830934 51.5377142,50.4242045 51.5977142,50.4769823 C51.6732697,50.5430934 51.7627142,50.3597601 51.7916031,50.3203156 C51.8482697,50.2442045 51.9766031,50.233649 52.0077142,50.1397601 C52.0432697,50.0342045 52.0310475,49.9714268 52.1732697,49.9680934 C52.2327142,49.9669823 52.275492,49.928649 52.3316031,49.9175379 C52.3932697,49.9053156 52.420492,49.898649 52.4599364,49.8514268 C52.5166031,49.7847601 52.5666031,49.8647601 52.5693808,49.9180934 C52.5716031,49.9730934 52.5471586,50.0419823 52.580492,50.0903156 C52.6221586,50.1508712 52.6682697,50.0708712 52.7099364,50.0330934 C52.7060475,50.0730934 52.760492,50.0969823 52.7916031,50.1097601 C52.8410475,50.0764268 52.8716031,50.0219823 52.9238253,49.9919823 C52.9482697,49.978649 52.975492,49.9730934 53.0027142,49.9680934 C53.010492,50.0119823 53.0177142,50.0592045 53.0571586,50.0808712 C53.1132697,50.1130934 53.0443808,50.1442045 53.1182697,50.178649 C53.2110475,50.213649 53.2416031,50.3069823 53.2866031,50.3819823 C53.3071586,50.4158712 53.4999364,50.2080934 53.5749364,50.1997601 C53.820492,50.1719823 53.9482697,49.8525379 54.0399364,49.6625379 C54.1716031,49.3919823 54.230492,49.0908712 54.2649364,48.8108712 C54.3488253,48.6392045 54.3827142,48.323649 54.3488253,48.1230934 Z M52.9038253,50.4425379 C52.9049364,50.4747601 52.9399364,50.4703156 52.9643808,50.4625379 C52.9849364,50.4558712 52.9988253,50.4375379 53.0121586,50.4208712 C53.0316031,50.3969823 53.0427142,50.3719823 53.0266031,50.343649 C53.0088253,50.3130934 52.9982697,50.2914268 52.9899364,50.2564268 C52.9760475,50.2642045 52.9593808,50.2764268 52.9449364,50.2819823 C52.9293808,50.2869823 52.9277142,50.2825379 52.9110475,50.2819823 C52.8716031,50.2797601 52.8793808,50.3103156 52.8627142,50.3347601 C52.8488253,50.3558712 52.8182697,50.3647601 52.8299364,50.3925379 C52.8388253,50.413649 52.8738253,50.4325379 52.8932697,50.4414268 L52.8988253,50.4358712 C52.8977142,50.4369823 52.8966031,50.438649 52.895492,50.4403156 C52.8982697,50.4414268 52.9010475,50.4419823 52.9038253,50.4425379 Z M42.7499364,50.8092045 C42.7449364,50.7747601 42.7316031,50.7530934 42.705492,50.7330934 C42.7043808,50.7358712 42.7032697,50.738649 42.7032697,50.7425379 C42.6677142,50.7247601 42.6627142,50.6564268 42.6149364,50.6614268 C42.5743808,50.5975379 42.4716031,50.6258712 42.440492,50.6853156 C42.4193808,50.7247601 42.4443808,50.7419823 42.4682697,50.7714268 C42.4977142,50.8075379 42.4921586,50.8353156 42.5027142,50.8780934 C42.5293808,50.9858712 42.6193808,50.9114268 42.6832697,50.9542045 C42.7071586,50.9692045 42.7177142,51.0158712 42.7527142,51.0075379 C42.7932697,50.998649 42.7910475,50.938649 42.780492,50.9114268 C42.7660475,50.8730934 42.755492,50.8508712 42.7499364,50.8092045 Z M42.6960475,50.7253156 C42.6993808,50.7280934 42.7027142,50.7303156 42.705492,50.7330934 C42.7082697,50.7275379 42.7121586,50.723649 42.7143808,50.7164268 L42.6960475,50.7253156 Z M52.7827142,52.1864268 C52.740492,52.2058712 52.665492,52.1958712 52.6321586,52.2269823 C52.6138253,52.243649 52.6188253,52.263649 52.6110475,52.2842045 C52.6010475,52.308649 52.5638253,52.3175379 52.5438253,52.3308712 C52.5116031,52.3519823 52.5010475,52.3992045 52.4666031,52.4114268 C52.4516031,52.3892045 52.4288253,52.3253156 52.3988253,52.3808712 C52.3799364,52.4153156 52.3927142,52.4503156 52.3632697,52.4830934 C52.335492,52.513649 52.3371586,52.5497601 52.3171586,52.5830934 C52.2860475,52.6353156 52.2560475,52.6664268 52.2038253,52.6975379 C52.1616031,52.7225379 52.1538253,52.7675379 52.1238253,52.8025379 C52.0916031,52.8392045 52.0438253,52.853649 51.9999364,52.8725379 C51.9693808,52.8858712 51.9182697,52.9225379 51.8838253,52.9014268 C51.8360475,52.8725379 51.900492,52.8214268 51.9227142,52.8030934 C51.9432697,52.7858712 52.0438253,52.7253156 52.0210475,52.6908712 C52.005492,52.668649 51.9471586,52.6714268 51.9243808,52.673649 C51.8771586,52.678649 51.840492,52.7264268 51.800492,52.7497601 C51.755492,52.7753156 51.7160475,52.7969823 51.6666031,52.8142045 C51.6088253,52.8342045 51.6038253,52.8875379 51.5588253,52.9203156 C51.5221586,52.9475379 51.4766031,52.9692045 51.4293808,52.9692045 C51.3677142,52.968649 51.3710475,52.9180934 51.3532697,52.8753156 C51.3299364,52.8780934 51.3093808,52.908649 51.2877142,52.9180934 C51.2510475,52.9330934 51.2282697,52.9492045 51.2432697,52.9897601 C51.2588253,53.0297601 51.0943808,53.0680934 51.0660475,53.0880934 C51.0588253,53.0680934 51.0910475,53.0458712 51.1038253,53.0347601 C51.0527142,53.0303156 50.9960475,53.0742045 50.9443808,53.0814268 C50.8943808,53.088649 50.8327142,53.1219823 50.825492,53.1742045 C50.8199364,53.2142045 50.7649364,53.213649 50.7316031,53.2275379 C50.675492,53.2503156 50.6988253,53.2842045 50.6877142,53.3292045 C50.6666031,53.4142045 50.4899364,53.3492045 50.5799364,53.2369823 C50.6116031,53.1975379 50.6593808,53.1719823 50.6882697,53.1308712 C50.7210475,53.0842045 50.7260475,53.0247601 50.7516031,52.9742045 C50.695492,52.9903156 50.6527142,53.0225379 50.6049364,53.053649 C50.5510475,53.0892045 50.505492,53.0808712 50.445492,53.068649 C50.375492,53.053649 50.3271586,53.0892045 50.2621586,53.1047601 C50.220492,53.1147601 50.1282697,53.1114268 50.1232697,53.1714268 C50.1199364,53.2097601 50.1866031,53.2180934 50.2088253,53.2403156 C50.2421586,53.2742045 50.2771586,53.3247601 50.305492,53.3630934 C50.3282697,53.393649 50.410492,53.4353156 50.405492,53.473649 C50.3960475,53.5480934 50.3027142,53.5353156 50.2510475,53.548649 C50.1999364,53.5614268 50.1927142,53.6069823 50.155492,53.6347601 C50.1138253,53.6653156 50.0566031,53.6297601 50.0093808,53.648649 C49.9616031,53.6675379 49.9277142,53.7092045 49.8860475,53.7380934 C49.8160475,53.7853156 49.7710475,53.7330934 49.6988253,53.7303156 C49.6410475,53.7280934 49.5871586,53.7542045 49.5321586,53.7664268 C49.4821586,53.7775379 49.4227142,53.7858712 49.3832697,53.8214268 C49.300492,53.8958712 49.5699364,53.8764268 49.5943808,53.873649 C49.5832697,53.9169823 49.5721586,53.9669823 49.5327142,53.9953156 C49.4838253,54.0303156 49.4149364,54.0219823 49.3588253,54.0347601 C49.3149364,54.0447601 49.2543808,54.093649 49.3182697,54.1269823 C49.3749364,54.1564268 49.4488253,54.1408712 49.505492,54.1208712 C49.5716031,54.0980934 49.6332697,54.0630934 49.7021586,54.048649 C49.7743808,54.0325379 49.8493808,54.0397601 49.9221586,54.0264268 C49.9993808,54.0125379 50.0671586,53.9697601 50.1388253,53.9408712 C50.2077142,53.9130934 50.2793808,53.9030934 50.3538253,53.9003156 C50.3382697,53.9269823 50.2660475,53.9258712 50.2388253,53.9308712 C50.1843808,53.9419823 50.1477142,53.9892045 50.0910475,53.9864268 C50.0277142,53.983649 50.035492,54.0292045 49.9893808,54.0397601 C49.9599364,54.0464268 49.8893808,54.1153156 49.8671586,54.0730934 C49.8499364,54.0397601 49.8177142,54.0464268 49.8066031,54.0864268 C49.7982697,54.1164268 49.815492,54.1275379 49.7743808,54.1280934 C49.7416031,54.1280934 49.7277142,54.1153156 49.6982697,54.1080934 C49.6416031,54.093649 49.6160475,54.1519823 49.575492,54.1669823 C49.5160475,54.1892045 49.4527142,54.1825379 49.3960475,54.2197601 C49.3627142,54.2414268 49.3266031,54.2475379 49.2877142,54.2592045 C49.2160475,54.2808712 49.1493808,54.308649 49.0788253,54.3325379 C49.0232697,54.3508712 48.9682697,54.3742045 48.9088253,54.3753156 C48.8843808,54.3758712 48.7877142,54.3592045 48.7716031,54.3875379 C48.7416031,54.4408712 48.8327142,54.4208712 48.8521586,54.4103156 C48.9060475,54.3814268 48.9710475,54.3980934 49.0316031,54.3980934 C49.1060475,54.3980934 49.1682697,54.3830934 49.2343808,54.348649 C49.2527142,54.3397601 49.3727142,54.313649 49.3782697,54.3280934 C49.3893808,54.3342045 49.4693808,54.3053156 49.4827142,54.3019823 C49.5471586,54.2875379 49.6116031,54.2730934 49.6749364,54.2569823 C49.8710475,54.2064268 50.0643808,54.1303156 50.2560475,54.0653156 C50.6366031,53.9364268 50.9866031,53.7197601 51.3166031,53.4992045 C51.4666031,53.3992045 51.5882697,53.268649 51.750492,53.1875379 C51.9138253,53.1058712 52.0599364,52.9980934 52.2099364,52.8964268 C52.3566031,52.7964268 52.4677142,52.6597601 52.5893808,52.5342045 C52.7121586,52.4075379 52.8166031,52.2869823 52.8710475,52.1180934 C52.8399364,52.1114268 52.8082697,52.1742045 52.7827142,52.1864268 Z M48.9610475,53.198649 C49.0593808,53.0614268 48.9949364,52.8830934 49.075492,52.7403156 C49.1149364,52.6708712 49.1843808,52.6269823 49.2466031,52.578649 C49.3221586,52.5208712 49.3888253,52.453649 49.4488253,52.3803156 C49.4138253,52.3719823 49.4116031,52.3380934 49.3899364,52.3169823 C49.355492,52.283649 49.3038253,52.3058712 49.2960475,52.2553156 C49.2888253,52.2103156 49.2516031,52.2003156 49.215492,52.1819823 C49.1327142,52.1408712 49.0988253,52.0597601 49.0321586,52.0025379 C48.9582697,51.938649 48.8588253,51.9603156 48.770492,51.9425379 C48.6916031,51.9269823 48.6121586,51.8025379 48.5282697,51.8558712 C48.475492,51.888649 48.450492,51.9742045 48.4866031,52.0258712 C48.5149364,52.0669823 48.5643808,52.0869823 48.5838253,52.1353156 C48.5549364,52.1614268 48.5482697,52.1792045 48.5827142,52.203649 C48.6243808,52.2330934 48.7043808,52.2625379 48.6843808,52.3264268 C48.6732697,52.3603156 48.6449364,52.3930934 48.6077142,52.4003156 C48.580492,52.4053156 48.5160475,52.3897601 48.5299364,52.438649 C48.500492,52.358649 48.4166031,52.4825379 48.3716031,52.4180934 C48.3343808,52.3653156 48.3110475,52.318649 48.2527142,52.2830934 C48.1766031,52.2364268 48.2827142,52.1925379 48.2699364,52.1219823 C48.2510475,52.0203156 48.1271586,52.0480934 48.0821586,51.973649 C48.0566031,51.9303156 48.0927142,51.8964268 48.1093808,51.858649 C48.1260475,51.8203156 48.1721586,51.8508712 48.1960475,51.8625379 C48.275492,51.8997601 48.3927142,51.8864268 48.4593808,51.8308712 C48.490492,51.8053156 48.5582697,51.6864268 48.4716031,51.6875379 C48.4121586,51.6875379 48.3666031,51.7397601 48.310492,51.7430934 C48.3021586,51.6753156 48.2710475,51.5603156 48.3432697,51.5158712 C48.4088253,51.4753156 48.5466031,51.4280934 48.4877142,51.3225379 C48.4671586,51.2864268 48.4299364,51.3464268 48.3993808,51.3203156 C48.3860475,51.308649 48.3949364,51.2842045 48.3999364,51.2725379 C48.3793808,51.253649 48.360492,51.2319823 48.3499364,51.2064268 C48.3032697,51.0930934 48.4410475,51.003649 48.3832697,50.8842045 C48.3588253,50.833649 48.3171586,50.803649 48.2716031,50.7719823 C48.2260475,50.7403156 48.2238253,50.7003156 48.2071586,50.6519823 C48.1977142,50.6247601 48.1538253,50.5619823 48.115492,50.5775379 C48.0827142,50.5908712 48.0727142,50.6469823 48.0482697,50.6708712 C47.990492,50.7269823 47.870492,50.7475379 47.7927142,50.7297601 C47.7321586,50.7164268 47.7349364,50.6925379 47.705492,50.6514268 C47.695492,50.6369823 47.6743808,50.6353156 47.6588253,50.6292045 C47.630492,50.618649 47.6282697,50.5942045 47.6216031,50.5692045 C47.5960475,50.4764268 47.4110475,50.5914268 47.3827142,50.4614268 C47.3766031,50.4314268 47.3866031,50.3803156 47.3438253,50.373649 C47.2943808,50.3658712 47.2927142,50.318649 47.2927142,50.2792045 C47.2921586,50.2469823 47.295492,50.2019823 47.2610475,50.183649 C47.2171586,50.1603156 47.2066031,50.1708712 47.1932697,50.1214268 C47.1766031,50.0580934 47.1332697,50.1242045 47.0977142,50.1103156 C47.0216031,50.0814268 47.0349364,50.118649 46.9738253,50.1508712 C46.8688253,50.2058712 46.8577142,49.9480934 46.820492,49.8975379 C46.750492,49.8014268 46.7693808,50.0169823 46.7216031,50.043649 C46.6771586,50.0675379 46.6321586,50.0119823 46.6166031,49.978649 C46.6071586,49.958649 46.6010475,49.9375379 46.5893808,49.9180934 C46.5721586,49.8903156 46.5399364,49.878649 46.5221586,49.8508712 C46.5066031,49.8258712 46.4849364,49.7969823 46.4743808,49.7703156 C46.4649364,49.7469823 46.4666031,49.7169823 46.4488253,49.6975379 C46.4266031,49.673649 46.4532697,49.6325379 46.4699364,49.6014268 C46.4977142,49.5914268 46.5388253,49.6125379 46.5588253,49.6297601 C46.6088253,49.6725379 46.6843808,49.8547601 46.7710475,49.8214268 C46.7532697,49.7975379 46.7643808,49.768649 46.7516031,49.7430934 C46.7388253,49.7164268 46.7116031,49.7003156 46.6921586,49.6780934 C46.6466031,49.6269823 46.5977142,49.5764268 46.5682697,49.5142045 C46.5427142,49.4597601 46.5310475,49.403649 46.4788253,49.3664268 C46.4349364,49.3342045 46.3449364,49.3042045 46.3688253,49.2342045 C46.4049364,49.2408712 46.4299364,49.2692045 46.4560475,49.2919823 C46.4932697,49.323649 46.540492,49.3403156 46.5843808,49.3614268 C46.6643808,49.4003156 46.7560475,49.4275379 46.8243808,49.4858712 C46.8660475,49.5219823 46.8443808,49.5997601 46.8971586,49.6442045 C46.9360475,49.6764268 46.995492,49.7847601 47.0666031,49.7419823 C47.0938253,49.7253156 47.1049364,49.6942045 47.1310475,49.6764268 C47.1599364,49.6564268 47.2082697,49.6375379 47.240492,49.6225379 C47.2610475,49.613649 47.2943808,49.6158712 47.3110475,49.5997601 C47.3360475,49.5758712 47.275492,49.5053156 47.2616031,49.4869823 C47.2077142,49.4175379 47.1582697,49.3419823 47.0860475,49.2892045 C47.0488253,49.2619823 47.0127142,49.2330934 46.9699364,49.2153156 C46.945492,49.2058712 46.9049364,49.2069823 46.8999364,49.1742045 C46.9116031,49.1819823 46.9188253,49.1797601 46.9210475,49.1680934 C46.9199364,49.1464268 46.8888253,49.1458712 46.8738253,49.1414268 C46.8382697,49.1314268 46.8138253,49.1314268 46.7993808,49.1019823 C46.7816031,49.0647601 46.7177142,49.0664268 46.6838253,49.0575379 C46.6327142,49.0447601 46.5927142,49.0064268 46.5443808,48.9875379 C46.4866031,48.9653156 46.4432697,48.988649 46.3877142,49.0008712 C46.3310475,49.0130934 46.1093808,49.553649 46.0532697,49.5675379 C45.9982697,49.5814268 45.9193808,49.5358712 45.9116031,49.4530934 C45.9371586,49.4880934 45.7666031,49.263649 45.7738253,49.2503156 C45.4832697,49.7653156 45.785492,49.4464268 45.7871586,49.4192045 C45.7882697,49.3897601 45.880492,49.2375379 46.0571586,48.8608712 C46.0943808,48.7797601 46.0116031,49.6203156 45.9282697,49.6592045 C45.8593808,49.6914268 45.7871586,49.6364268 45.7066031,49.6203156 C45.6610475,49.6114268 45.6943808,49.2264268 45.6438253,49.2580934 C45.315492,49.4669823 45.6538253,49.7625379 45.5893808,49.7697601 C45.4888253,49.7803156 45.1749364,49.8158712 45.0710475,49.8030934 C45.0243808,49.7975379 45.0349364,49.6919823 44.8871586,49.4608712 C44.8682697,49.4314268 44.7827142,49.1308712 44.765492,49.1625379 C44.7427142,49.2025379 44.6332697,49.5842045 44.6243808,49.5475379 C44.5832697,49.5797601 44.6849364,48.9958712 44.5910475,49.1125379 C44.5688253,49.1403156 44.2343808,49.5142045 44.2010475,49.5169823 C44.1766031,49.5197601 44.4682697,49.1347601 44.4482697,49.1419823 C44.3988253,49.1592045 44.0688253,49.6108712 44.0277142,49.6403156 C43.9721586,49.6803156 44.0288253,49.4903156 43.9616031,49.543649 C43.9016031,49.5919823 44.0810475,49.3692045 44.0249364,49.4214268 C43.9860475,49.4569823 43.9099364,49.4997601 43.9038253,49.5569823 C43.8977142,49.6214268 43.930492,49.6658712 43.8827142,49.7258712 C43.8638253,49.7492045 43.8416031,49.7697601 43.8243808,49.7942045 C43.810492,49.8142045 43.8071586,49.8475379 43.7832697,49.8597601 C43.7182697,49.893649 43.7349364,49.913649 43.7543808,49.9842045 C43.7710475,50.043649 43.7649364,50.1553156 43.7510475,50.2164268 C43.7410475,50.2630934 43.6938253,50.3764268 43.6366031,50.3492045 C43.6066031,50.3353156 43.5749364,50.323649 43.5471586,50.3503156 C43.5349364,50.3625379 43.5266031,50.3769823 43.5227142,50.393649 C43.5032697,50.3942045 43.4843808,50.3964268 43.465492,50.4008712 C43.4299364,50.4080934 43.3910475,50.4169823 43.3566031,50.4019823 C43.3216031,50.3869823 43.275492,50.3580934 43.2360475,50.3708712 C43.2027142,50.3819823 43.1377142,50.4103156 43.1238253,50.4447601 C43.1182697,50.4603156 43.1382697,50.4997601 43.1377142,50.5197601 C43.1371586,50.5564268 43.1660475,50.6108712 43.1543808,50.6447601 C43.1271586,50.6308712 43.0882697,50.6264268 43.0699364,50.6008712 C43.0527142,50.5775379 43.0277142,50.5825379 43.0088253,50.5592045 C43.0043808,50.6003156 42.9893808,50.6564268 42.9416031,50.6675379 C42.8938253,50.678649 42.8482697,50.6408712 42.800492,50.6530934 C42.6760475,50.6858712 42.8760475,50.8419823 42.9027142,50.8725379 C42.9471586,50.9225379 42.9627142,50.988649 42.995492,51.0458712 C43.030492,51.1075379 43.105492,51.128649 43.1488253,51.1830934 C43.1849364,51.228649 43.1927142,51.2914268 43.2438253,51.3253156 C43.3016031,51.3642045 43.3532697,51.4003156 43.3771586,51.4675379 C43.4016031,51.443649 43.4521586,51.5547601 43.5038253,51.4658712 C43.5321586,51.4175379 43.5799364,51.3758712 43.6110475,51.4547601 C43.6371586,51.5214268 43.6116031,51.5653156 43.6688253,51.623649 C43.7143808,51.6692045 43.7116031,51.723649 43.635492,51.7192045 C43.6482697,51.753649 43.6688253,51.7869823 43.6360475,51.8180934 C43.620492,51.8330934 43.5782697,51.8642045 43.6093808,51.8858712 C43.6438253,51.8697601 43.6816031,51.8603156 43.7160475,51.8447601 C43.7538253,51.8280934 43.7916031,51.7892045 43.835492,51.7903156 C43.8388253,51.8042045 43.7771586,51.8458712 43.8149364,51.848649 C43.8466031,51.8514268 43.8916031,51.8180934 43.9177142,51.8458712 C43.9466031,51.8764268 43.910492,51.9219823 43.9271586,51.9558712 C43.9438253,51.9897601 44.0010475,51.9642045 44.0293808,51.9692045 C44.0166031,51.9992045 43.9727142,51.993649 43.9488253,52.0053156 C44.0049364,52.0742045 43.9316031,52.1753156 43.8499364,52.1764268 C43.810492,52.1769823 43.6710475,52.0180934 43.665492,52.1203156 C43.6638253,52.1508712 43.6732697,52.1875379 43.6832697,52.2164268 C43.6960475,52.253649 43.7877142,52.2380934 43.8199364,52.2519823 C43.8671586,52.2714268 43.9232697,52.3169823 43.9416031,52.3647601 C43.960492,52.4142045 44.0016031,52.4464268 44.0177142,52.4942045 C44.0471586,52.5814268 44.1316031,52.5930934 44.2188253,52.618649 C44.3349364,52.6530934 44.2777142,52.8325379 44.2716031,52.9180934 C44.2660475,53.0025379 44.385492,53.0225379 44.4399364,53.0703156 C44.4999364,53.1225379 44.5099364,53.2247601 44.4093808,53.2330934 C44.3582697,53.2375379 44.2738253,53.2142045 44.2549364,53.2792045 C44.2277142,53.3719823 44.3677142,53.3614268 44.4282697,53.3825379 C44.4571586,53.3919823 44.5727142,53.4042045 44.5832697,53.4308712 C44.5993808,53.4719823 44.5860475,53.528649 44.6010475,53.573649 C44.6371586,53.6847601 44.7421586,53.7603156 44.8421586,53.8158712 C45.0582697,53.9364268 45.3149364,54.0130934 45.5527142,54.0808712 C45.6849364,54.118649 45.8199364,54.1480934 45.9560475,54.1669823 C46.0866031,54.1847601 46.2032697,54.173649 46.3149364,54.2469823 C46.3921586,54.2969823 46.4416031,54.2597601 46.5210475,54.2730934 C46.5549364,54.2792045 46.5699364,54.3103156 46.5949364,54.3292045 C46.6238253,54.3508712 46.6566031,54.3225379 46.6877142,54.3342045 C46.6921586,54.3142045 46.6899364,54.2942045 46.6810475,54.2753156 C46.7410475,54.2975379 46.815492,54.3619823 46.8788253,54.3103156 C46.910492,54.2847601 46.9321586,54.2492045 46.9649364,54.2247601 C47.0038253,54.2275379 47.0427142,54.2297601 47.0816031,54.2303156 C47.2466031,54.2308712 47.3760475,54.1553156 47.5071586,54.0675379 C47.6477142,53.973649 47.8177142,53.9714268 47.9810475,53.9558712 C48.1538253,53.9392045 48.3377142,53.9169823 48.4949364,53.8414268 C48.6332697,53.7753156 48.6682697,53.6542045 48.7071586,53.5203156 C48.7493808,53.3747601 48.8771586,53.3158712 48.9610475,53.198649 Z M51.5738253,52.108649 C51.6182697,52.1203156 51.6893808,52.0925379 51.7171586,52.0553156 C51.7549364,52.0042045 51.7232697,51.9369823 51.6577142,51.9753156 C51.6332697,51.9897601 51.6360475,52.0169823 51.6177142,52.0342045 C51.5966031,52.0525379 51.5943808,52.0308712 51.5749364,52.0264268 C51.545492,52.0197601 51.4993808,52.0580934 51.4899364,52.083649 C51.450492,52.0825379 51.415492,52.1264268 51.4338253,52.1614268 C51.485492,52.1419823 51.5171586,52.0930934 51.5738253,52.108649 Z"/>
@@ -112,13 +111,12 @@
   <use id="tag" xlink:href="#tag-shape"/>
   <use id="tag-hover" xlink:href="#tag-shape"/>
   <use id="tag-active" xlink:href="#tag-shape"/>
   <use id="trash" xlink:href="#trash-shape"/>
   <use id="unblock" xlink:href="#unblock-shape"/>
   <use id="unblock-hover" xlink:href="#unblock-shape"/>
   <use id="unblock-active" xlink:href="#unblock-shape"/>
   <use id="video" xlink:href="#video-shape"/>
-  <use id="tour" xlink:href="#tour-shape"/>
   <use id="delete" xlink:href="#delete-shape"/>
   <use id="status-available" xlink:href="#status-available-shape"/>
   <use id="status-unavailable" xlink:href="#status-unavailable-shape"/>
 </svg>
deleted file mode 100644
--- a/browser/components/loop/content/shared/img/svg/glyph-account-16x16.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
-  <path fill-rule="evenodd" fill="#231f20" d="M8,6.526c1.802,0,3.263-1.461,3.263-3.263 C11.263,1.461,9.802,0,8,0C6.198,0,4.737,1.461,4.737,3.263C4.737,5.066,6.198,6.526,8,6.526z M14.067,11.421c0,0,0-0.001,0-0.001 c0-1.676-1.397-3.119-3.419-3.807L8.001,10.26L5.354,7.613C3.331,8.3,1.933,9.744,1.933,11.42v0.001H1.93 c0,1.679,0.328,3.246,0.896,4.579h10.348c0.568-1.333,0.896-2.9,0.896-4.579H14.067z"/>
-</svg>
deleted file mode 100644
--- a/browser/components/loop/content/shared/img/svg/glyph-signin-16x16.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
-  <path fill-rule="evenodd" fill="#231f20" d="M9.921,8.415c0.105-0.11,0.146-0.265,0.13-0.432 c0.016-0.166-0.025-0.321-0.13-0.429L9.305,6.938l-2.6-2.65C6.402,3.973,5.973,3.906,5.748,4.139L5.238,4.68 c-0.225,0.233-0.16,0.679,0.144,0.995L6.44,6.754H0.608C0.272,6.754,0,7.026,0,7.361l0,1.215c0,0.335,0.272,0.607,0.608,0.607H6.47 l-1.136,1.155c-0.305,0.313-0.369,0.756-0.144,0.987L5.7,11.861c0.225,0.233,0.654,0.166,0.959-0.149l2.619-2.663L9.921,8.415z"/>
-  <path fill-rule="evenodd" fill="#231f20" d="M14,0H5.558c-0.331,0-0.6,0.269-0.6,0.6v0.8 c0,0.331,0.269,0.6,0.6,0.6H12.5C13.328,2,14,2.672,14,3.5v9c0,0.828-0.672,1.5-1.5,1.5H5.558c-0.331,0-0.6,0.269-0.6,0.6v0.8 c0,0.331,0.269,0.6,0.6,0.6H14c1.105,0,2-0.895,2-2V2C16,0.895,15.105,0,14,0z"/>
-</svg>
deleted file mode 100644
--- a/browser/components/loop/content/shared/img/svg/glyph-signout-16x16.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
-  <path fill-rule="evenodd" fill="#231f20" d="M14,0H5.558c-0.331,0-0.6,0.269-0.6,0.6v0.8 c0,0.331,0.269,0.6,0.6,0.6H12.5C13.328,2,14,2.672,14,3.5v9c0,0.828-0.672,1.5-1.5,1.5H5.558c-0.331,0-0.6,0.269-0.6,0.6v0.8 c0,0.331,0.269,0.6,0.6,0.6H14c1.105,0,2-0.895,2-2V2C16,0.895,15.105,0,14,0z"/>
-  <path fill-rule="evenodd" fill="#231f20" d="M0.133,7.585c-0.105,0.11-0.146,0.265-0.13,0.432 c-0.016,0.166,0.025,0.321,0.13,0.429l0.616,0.615l2.6,2.65c0.304,0.315,0.732,0.382,0.958,0.149l0.51-0.541 c0.225-0.233,0.16-0.679-0.144-0.995L3.615,9.246h5.832c0.335,0,0.608-0.272,0.608-0.607V7.424c0-0.335-0.272-0.607-0.608-0.607 H3.585L4.72,5.662c0.305-0.313,0.369-0.756,0.144-0.987L4.355,4.139C4.13,3.906,3.701,3.973,3.396,4.287L0.777,6.951L0.133,7.585z"/>
-</svg>
--- a/browser/components/loop/jar.mn
+++ b/browser/components/loop/jar.mn
@@ -50,19 +50,16 @@ browser.jar:
   content/browser/loop/shared/img/hangup-inverse-14x14.png      (content/shared/img/hangup-inverse-14x14.png)
   content/browser/loop/shared/img/hangup-inverse-14x14@2x.png   (content/shared/img/hangup-inverse-14x14@2x.png)
   content/browser/loop/shared/img/mute-inverse-14x14.png        (content/shared/img/mute-inverse-14x14.png)
   content/browser/loop/shared/img/mute-inverse-14x14@2x.png     (content/shared/img/mute-inverse-14x14@2x.png)
   content/browser/loop/shared/img/video-inverse-14x14.png       (content/shared/img/video-inverse-14x14.png)
   content/browser/loop/shared/img/video-inverse-14x14@2x.png    (content/shared/img/video-inverse-14x14@2x.png)
   content/browser/loop/shared/img/dropdown-inverse.png          (content/shared/img/dropdown-inverse.png)
   content/browser/loop/shared/img/dropdown-inverse@2x.png       (content/shared/img/dropdown-inverse@2x.png)
-  content/browser/loop/shared/img/svg/glyph-account-16x16.svg   (content/shared/img/svg/glyph-account-16x16.svg)
-  content/browser/loop/shared/img/svg/glyph-signin-16x16.svg    (content/shared/img/svg/glyph-signin-16x16.svg)
-  content/browser/loop/shared/img/svg/glyph-signout-16x16.svg   (content/shared/img/svg/glyph-signout-16x16.svg)
   content/browser/loop/shared/img/svg/glyph-help-16x16.svg      (content/shared/img/svg/glyph-help-16x16.svg)
   content/browser/loop/shared/img/svg/exit.svg                  (content/shared/img/svg/exit.svg)
   content/browser/loop/shared/img/svg/audio.svg                 (content/shared/img/svg/audio.svg)
   content/browser/loop/shared/img/svg/audio-hover.svg           (content/shared/img/svg/audio-hover.svg)
   content/browser/loop/shared/img/svg/audio-mute.svg            (content/shared/img/svg/audio-mute.svg)
   content/browser/loop/shared/img/svg/audio-mute-hover.svg      (content/shared/img/svg/audio-mute-hover.svg)
   content/browser/loop/shared/img/svg/video.svg                 (content/shared/img/svg/video.svg)
   content/browser/loop/shared/img/svg/video-hover.svg           (content/shared/img/svg/video-hover.svg)
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -477,20 +477,26 @@ loop.standaloneRoomViews = (function(moz
      * user media access.
      *
      * @param  {Object} nextProps (Unused)
      * @param  {Object} nextState Next state object.
      */
     componentWillUpdate: function(nextProps, nextState) {
       if (this.state.roomState !== ROOM_STATES.READY &&
           nextState.roomState === ROOM_STATES.READY) {
-        this.setTitle(mozL10n.get("standalone_title_with_room_name", {
-          roomName: nextState.roomName || this.state.roomName,
-          clientShortname: mozL10n.get("clientShortname2")
-        }));
+        var roomName = nextState.roomName || this.state.roomName;
+
+        if (roomName) {
+          this.setTitle(mozL10n.get("standalone_title_with_room_name", {
+            roomName: roomName,
+            clientShortname: mozL10n.get("clientShortname2")
+          }));
+        } else {
+          this.setTitle(mozL10n.get("clientShortname2"));
+        }
       }
 
       if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
           nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
         this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
           publisherConfig: this.getDefaultPublisherConfig({publishVideo: true})
         }));
       }
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -477,20 +477,26 @@ loop.standaloneRoomViews = (function(moz
      * user media access.
      *
      * @param  {Object} nextProps (Unused)
      * @param  {Object} nextState Next state object.
      */
     componentWillUpdate: function(nextProps, nextState) {
       if (this.state.roomState !== ROOM_STATES.READY &&
           nextState.roomState === ROOM_STATES.READY) {
-        this.setTitle(mozL10n.get("standalone_title_with_room_name", {
-          roomName: nextState.roomName || this.state.roomName,
-          clientShortname: mozL10n.get("clientShortname2")
-        }));
+        var roomName = nextState.roomName || this.state.roomName;
+
+        if (roomName) {
+          this.setTitle(mozL10n.get("standalone_title_with_room_name", {
+            roomName: roomName,
+            clientShortname: mozL10n.get("clientShortname2")
+          }));
+        } else {
+          this.setTitle(mozL10n.get("clientShortname2"));
+        }
       }
 
       if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
           nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
         this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
           publisherConfig: this.getDefaultPublisherConfig({publishVideo: true})
         }));
       }
--- a/browser/components/loop/standalone/package.json
+++ b/browser/components/loop/standalone/package.json
@@ -9,16 +9,17 @@
   "engines": {
     "node": "0.10.x",
     "npm": "1.3.x"
   },
   "dependencies": {},
   "devDependencies": {
     "compression": "1.5.x",
     "eslint": "1.2.x",
+    "eslint-plugin-mozilla": "../../../../testing/eslint-plugin-mozilla",
     "eslint-plugin-react": "3.2.x",
     "exports-loader": "0.6.x",
     "express": "4.x",
     "imports-loader": "0.6.x",
     "script-loader": "0.6.x",
     "webpack": "1.12.x"
   },
   "scripts": {
--- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js
+++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js
@@ -367,16 +367,24 @@ describe("loop.standaloneRoomViews", fun
       it("should set document.title to roomName and brand name when the READY state is dispatched", function() {
         activeRoomStore.setStoreState({roomName: "fakeName", roomState: ROOM_STATES.INIT});
         view = mountTestComponent();
         activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
 
         expect(fakeWindow.document.title).to.equal("fakeName — clientShortname2");
       });
 
+      it("should set document.title brand name when there is no context available", function() {
+        activeRoomStore.setStoreState({roomState: ROOM_STATES.INIT});
+        view = mountTestComponent();
+        activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
+
+        expect(fakeWindow.document.title).to.equal("clientShortname2");
+      });
+
       it("should dispatch a `SetupStreamElements` action when the MEDIA_WAIT state " +
         "is entered", function() {
           activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
           view = mountTestComponent();
 
           activeRoomStore.setStoreState({roomState: ROOM_STATES.MEDIA_WAIT});
 
           expectActionDispatched(view);
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -599,17 +599,17 @@
         "volume-disabled", "clear", "magnifier"
       ],
       "16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
         "block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
         "contacts-active", "copy", "checkmark", "delete", "globe", "google", "google-hover",
         "google-active", "history", "history-hover", "history-active", "leave",
         "screen-white", "screenmute-white", "settings", "settings-hover", "settings-active",
         "share-darkgrey", "tag", "tag-hover", "tag-active", "trash", "unblock",
-        "unblock-hover", "unblock-active", "video", "video-hover", "video-active", "tour",
+        "unblock-hover", "unblock-active", "video", "video-hover", "video-active",
         "status-available", "status-unavailable"
       ]
     },
 
     render: function() {
       var icons = this.shapes[this.props.size].map(function(shapeId, i) {
         return (
           React.createElement("li", {className: "svg-icon-entry", key: this.props.size + "-" + i}, 
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -599,17 +599,17 @@
         "volume-disabled", "clear", "magnifier"
       ],
       "16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
         "block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
         "contacts-active", "copy", "checkmark", "delete", "globe", "google", "google-hover",
         "google-active", "history", "history-hover", "history-active", "leave",
         "screen-white", "screenmute-white", "settings", "settings-hover", "settings-active",
         "share-darkgrey", "tag", "tag-hover", "tag-active", "trash", "unblock",
-        "unblock-hover", "unblock-active", "video", "video-hover", "video-active", "tour",
+        "unblock-hover", "unblock-active", "video", "video-hover", "video-active",
         "status-available", "status-unavailable"
       ]
     },
 
     render: function() {
       var icons = this.shapes[this.props.size].map(function(shapeId, i) {
         return (
           <li className="svg-icon-entry" key={this.props.size + "-" + i}>
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -284,20 +284,25 @@ description#identity-popup-content-verif
 }
 
 /* PERMISSIONS */
 
 #identity-popup-permissions-content {
   background-image: url(chrome://browser/skin/controlcenter/permissions.svg);
 }
 
+#identity-popup-permission-list menulist {
+  min-width: 60px;
+}
+
 #identity-popup-permission-list:not(:empty) {
   margin-top: 5px;
 }
 
 #identity-popup-permission-list:not(:empty) + description {
   display: none;
 }
 
 .identity-popup-permission-label {
   -moz-margin-start: 0;
+  word-wrap: break-word;
 }
 
--- a/devtools/.eslintrc
+++ b/devtools/.eslintrc
@@ -20,16 +20,21 @@
     "Task": true,
     "XPCNativeWrapper": true,
     "XPCOMUtils": true,
   },
   "rules": {
     // These are the rules that have been configured so far to match the
     // devtools coding style.
 
+    // Rules from the mozilla plugin
+    "mozilla/components-imports": 1,
+    "mozilla/import-headjs-globals": 1,
+    "mozilla/mark-test-function-used": 1,
+
     // Disallow using variables outside the blocks they are defined (especially
     // since only let and const are used, see "no-var").
     "block-scoped-var": 2,
     // Enforce one true brace style (opening brace on the same line) and avoid
     // start and end braces on the same line.
     "brace-style": [2, "1tbs", {"allowSingleLine": false}],
     // Require camel case names
     "camelcase": 2,
--- a/devtools/.eslintrc.mochitests
+++ b/devtools/.eslintrc.mochitests
@@ -1,26 +1,20 @@
 // Parent config file for all devtools browser mochitest files.
 {
   "rules": {
-    // Only disallow non-global unused vars, so that things like the test
-    // function do not produce errors.
-    "no-unused-vars": [2, {"vars": "local"}],
-    // Allow using undefined variables so that tests can refer to functions
-    // and variables defined in head.js files, without having to maintain a
-    // list of globals in each .eslintrc file.
-    // Note that bug 1168340 will eventually help auto-registering globals
-    // from head.js files.
-    "no-undef": 0,
-    "block-scoped-var": 0
+    // Only disallow non-global unused vars, so that head.js does not produce
+    // errors.
+    "no-unused-vars": [2, {"vars": "local"}]
   },
   // All globals made available in the test environment.
   "globals": {
     "add_task": true,
     "Assert": true,
+    "BrowserTestUtils": true,
     "content": true,
     "document": true,
     "EventUtils": true,
     "executeSoon": true,
     "export_assertions": true,
     "finish": true,
     "gBrowser": true,
     "gDevTools": true,
@@ -33,18 +27,17 @@
     "navigator": true,
     "ok": true,
     "promise": true,
     "registerCleanupFunction": true,
     "requestLongerTimeout": true,
     "setTimeout": true,
     "SimpleTest": true,
     "SpecialPowers": true,
-    "test": true,
     "todo": true,
     "todo_is": true,
     "todo_isnot": true,
     "waitForClipboard": true,
     "waitForExplicitFinish": true,
     "waitForFocus": true,
     "window": true,
   }
-}
\ No newline at end of file
+}
--- a/devtools/client/animationinspector/animation-controller.js
+++ b/devtools/client/animationinspector/animation-controller.js
@@ -1,15 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* globals ViewHelpers, Task, AnimationsPanel, promise, EventEmitter,
-   AnimationsFront */
+/* globals AnimationsPanel */
 
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/Task.jsm");
 var { loader, require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm");
 Cu.import("resource://gre/modules/devtools/shared/Console.jsm");
--- a/devtools/client/animationinspector/components.js
+++ b/devtools/client/animationinspector/components.js
@@ -1,14 +1,13 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* globals ViewHelpers */
 
 "use strict";
 
 // Set of reusable UI components for the animation-inspector UI.
 // All components in this module share a common API:
 // 1. construct the component:
 //    let c = new ComponentName();
 // 2. initialize the markup of the component in a given parent node:
--- a/devtools/client/framework/toolbox-hosts.js
+++ b/devtools/client/framework/toolbox-hosts.js
@@ -1,12 +1,11 @@
 /* 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/. */
-/* globals DOMHelpers, Services */
 
 "use strict";
 
 const {Cu} = require("chrome");
 const EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/devtools/client/shared/DOMHelpers.jsm");
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -1,14 +1,11 @@
 /* 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/. */
-/* globals gDevTools, DOMHelpers, toolboxStrings, InspectorFront, Selection,
-   CommandUtils, DevToolsUtils, Hosts, osString, showDoorhanger,
-   getHighlighterUtils, createPerformanceFront */
 
 "use strict";
 
 const MAX_ORDINAL = 99;
 const ZOOM_PREF = "devtools.toolbox.zoomValue";
 const SPLITCONSOLE_ENABLED_PREF = "devtools.toolbox.splitconsoleEnabled";
 const SPLITCONSOLE_HEIGHT_PREF = "devtools.toolbox.splitconsoleHeight";
 const MIN_ZOOM = 0.5;
--- a/devtools/client/layoutview/view.js
+++ b/devtools/client/layoutview/view.js
@@ -1,14 +1,13 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* globals ViewHelpers, window, document */
 
 "use strict";
 
 const {utils: Cu, interfaces: Ci, classes: Cc} = Components;
 
 Cu.import("resource://gre/modules/Task.jsm");
 const {require} = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
 Cu.import("resource://gre/modules/devtools/shared/Console.jsm");
--- a/devtools/client/markupview/markup-view.js
+++ b/devtools/client/markupview/markup-view.js
@@ -8,17 +8,16 @@ const {Cc, Cu, Ci} = require("chrome");
 
 // Page size for pageup/pagedown
 const PAGE_SIZE = 10;
 const DEFAULT_MAX_CHILDREN = 100;
 const COLLAPSE_ATTRIBUTE_LENGTH = 120;
 const COLLAPSE_DATA_URL_REGEX = /^data.+base64/;
 const COLLAPSE_DATA_URL_LENGTH = 60;
 const NEW_SELECTION_HIGHLIGHTER_TIMER = 1000;
-const GRAB_DELAY = 400;
 const DRAG_DROP_AUTOSCROLL_EDGE_DISTANCE = 50;
 const DRAG_DROP_MIN_AUTOSCROLL_SPEED = 5;
 const DRAG_DROP_MAX_AUTOSCROLL_SPEED = 15;
 const AUTOCOMPLETE_POPUP_PANEL_ID = "markupview_autoCompletePopup";
 
 const {UndoStack} = require("devtools/client/shared/undo");
 const {editableField, InplaceEditor} = require("devtools/client/shared/inplace-editor");
 const {gDevTools} = Cu.import("resource:///modules/devtools/client/framework/gDevTools.jsm", {});
@@ -129,16 +128,21 @@ function MarkupView(aInspector, aFrame, 
 
 exports.MarkupView = MarkupView;
 
 MarkupView.prototype = {
   /**
    * How long does a node flash when it mutates (in ms).
    */
   CONTAINER_FLASHING_DURATION: 500,
+  /**
+   * How long do you have to hold the mouse down before a drag
+   * starts (in ms).
+   */
+  GRAB_DELAY: 400,
 
   _selectedContainer: null,
 
   _initTooltips: function() {
     this.tooltip = new Tooltip(this._inspector.panelDoc);
     this._makeTooltipPersistent(false);
 
     this._elt.addEventListener("click", this._onMouseClick, false);
@@ -825,17 +829,17 @@ MarkupView.prototype = {
       }
       if (type === "attributes" || type === "characterData") {
         container.update();
 
         // Auto refresh style properties on selected node when they change.
         if (type === "attributes" && container.selected) {
           requiresLayoutChange = true;
         }
-      } else if (type === "childList") {
+      } else if (type === "childList" || type === "nativeAnonymousChildList") {
         container.childrenDirty = true;
         // Update the children to take care of changes in the markup view DOM.
         this._updateChildren(container, {flash: true});
       } else if (type === "pseudoClassLock") {
         container.update();
       }
     }
 
@@ -1920,17 +1924,17 @@ MarkupContainer.prototype = {
       this.isDragging = true;
 
       this._dragStartY = event.pageY;
       this.markup.indicateDropTarget(this.elt);
 
       // If this is the last child, use the closing <div.tag-line> of parent as indicator
       this.markup.indicateDragTarget(this.elt.nextElementSibling ||
                                      this.markup.getContainer(this.node.parentNode()).closeTagLine);
-    }, GRAB_DELAY);
+    }, this.GRAB_DELAY);
   },
 
   /**
    * On mouse up, stop dragging.
    */
   _onMouseUp: Task.async(function*() {
     this._isMouseDown = false;
 
--- a/devtools/client/markupview/test/browser_markupview_dragdrop_reorder.js
+++ b/devtools/client/markupview/test/browser_markupview_dragdrop_reorder.js
@@ -2,20 +2,21 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test different kinds of drag and drop node re-ordering
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_dragdrop.html";
-const GRAB_DELAY = 400;
+const GRAB_DELAY = 5;
 
 add_task(function*() {
   let {inspector} = yield addTab(TEST_URL).then(openInspector);
+  inspector.markup.GRAB_DELAY = GRAB_DELAY;
 
   info("Expanding #test");
   let parentFront = yield getNodeFront("#test", inspector);
   let parent = yield getNode("#test");
   let parentContainer = yield getContainerForNodeFront(parentFront, inspector);
 
   yield inspector.markup.expandNode(parentFront);
   yield waitForMultipleChildrenUpdates(inspector);
--- a/devtools/client/markupview/test/browser_markupview_mutation_01.js
+++ b/devtools/client/markupview/test/browser_markupview_mutation_01.js
@@ -5,16 +5,18 @@
 "use strict";
 
 // Tests that various mutations to the dom update the markup view correctly.
 
 const TEST_URL = TEST_URL_ROOT + "doc_markup_mutation.html";
 
 // Mutation tests. Each entry in the array has the following properties:
 // - desc: for logging only
+// - numMutations: how many mutations are expected to come happen due to the
+//   test case.  Defaults to 1 if not set.
 // - test: a function supposed to mutate the DOM
 // - check: a function supposed to test that the mutation was handled
 const TEST_DATA = [
   {
     desc: "Adding an attribute",
     test: () => {
       let node1 = getNode("#node1");
       node1.setAttribute("newattr", "newattrval");
@@ -61,16 +63,41 @@ const TEST_DATA = [
     check: function*(inspector) {
       let {editor} = yield getContainerForSelector("#node1", inspector);
       ok([...editor.attrList.querySelectorAll(".attreditor")].some(attr => {
         return attr.textContent.trim() === "newattr=\"newattrchanged\"";
       }), "newattr attribute found");
     }
   },
   {
+    desc: "Adding ::after element",
+    numMutations: 2,
+    test: () => {
+      let node1 = getNode("#node1");
+      node1.classList.add("pseudo");
+    },
+    check: function*(inspector) {
+      let {children} = yield getContainerForSelector("#node1", inspector);
+      is(children.childNodes.length, 2,
+        "Node1 now has 2 children (text child and ::after");
+    }
+  },
+  {
+    desc: "Removing ::after element",
+    numMutations: 2,
+    test: () => {
+      let node1 = getNode("#node1");
+      node1.classList.remove("pseudo");
+    },
+    check: function*(inspector) {
+      let container = yield getContainerForSelector("#node1", inspector);
+      ok(container.singleTextChild, "Has single text child.");
+    }
+  },
+  {
     desc: "Updating the text-content",
     test: () => {
       let node1 = getNode("#node1");
       node1.textContent = "newtext";
     },
     check: function*(inspector) {
       let container = yield getContainerForSelector("#node1", inspector);
       ok(container.singleTextChild, "Has single text child.");
@@ -236,23 +263,38 @@ const TEST_DATA = [
 ];
 
 add_task(function*() {
   let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
 
   info("Expanding all markup-view nodes");
   yield inspector.markup.expandAll();
 
-  for (let {desc, test, check} of TEST_DATA) {
+  for (let {desc, test, check, numMutations} of TEST_DATA) {
     info("Starting test: " + desc);
 
+    numMutations = numMutations || 1;
+
     info("Executing the test markup mutation");
-    let onMutation = inspector.once("markupmutation");
-    test();
-    yield onMutation;
+    yield new Promise((resolve) => {
+      // If a test expects more than one mutation it may come through in a
+      // single event or possibly in multiples.
+      let seenMutations = 0;
+      inspector.on("markupmutation", function onmutation(e, mutations) {
+        seenMutations += mutations.length;
+        info("Receieved " + seenMutations +
+             " mutations, expecting at least " + numMutations);
+        if (seenMutations >= numMutations) {
+          inspector.off("markupmutation", onmutation);
+          resolve();
+        }
+      });
+
+      test();
+    })
 
     info("Expanding all markup-view nodes to make sure new nodes are imported");
     yield inspector.markup.expandAll();
 
     info("Checking the markup-view content");
     yield check(inspector);
   }
 });
--- a/devtools/client/markupview/test/doc_markup_mutation.html
+++ b/devtools/client/markupview/test/doc_markup_mutation.html
@@ -1,11 +1,16 @@
 <!DOCTYPE html>
 
 <html class="html">
+  <style type="text/css">
+    #node1.pseudo::after {
+      content: "after";
+    }
+  </style>
 
   <body class="body">
     <div class="node0">
       <div id="node1" class="node1">line1</div>
       <div id="node2" class="node2">line2</div>
       <p class="node3">line3</p>
       <!-- A comment -->
       <p id="node4" class="node4">line4
--- a/devtools/client/promisedebugger/promise-controller.js
+++ b/devtools/client/promisedebugger/promise-controller.js
@@ -1,15 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* global promise, PromisesPanel, PromisesFront, DevToolsUtils */
+/* global PromisesPanel */
 
 "use strict";
 
 const { utils: Cu } = Components;
 const { loader, require } =
   Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
 
 const { Task } = require("resource://gre/modules/Task.jsm");
--- a/devtools/client/shared/inplace-editor.js
+++ b/devtools/client/shared/inplace-editor.js
@@ -1,16 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* globals focusManager, CSSPropertyList, domUtils */
-
 /**
  * Basic use:
  * let spanToEdit = document.getElementById("somespan");
  *
  * editableField({
  *   element: spanToEdit,
  *   done: function(value, commit, direction) {
  *     if (commit) {
--- a/devtools/client/shared/widgets/Tooltip.js
+++ b/devtools/client/shared/widgets/Tooltip.js
@@ -1,17 +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/. */
 
 "use strict";
 
-/* globals beautify, setNamedTimeout, clearNamedTimeout, VariablesView,
-   VariablesViewController, Task */
-
 const {Cu, Ci} = require("chrome");
 const promise = require("promise");
 const {Spectrum} = require("devtools/client/shared/widgets/Spectrum");
 const {CubicBezierWidget} =
       require("devtools/client/shared/widgets/CubicBezierWidget");
 const {MdnDocsWidget} = require("devtools/client/shared/widgets/MdnDocsWidget");
 const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
 const EventEmitter = require("devtools/shared/event-emitter");
--- a/devtools/client/styleinspector/computed-view.js
+++ b/devtools/client/styleinspector/computed-view.js
@@ -1,16 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* globals overlays, StyleInspectorMenu, loader, clipboardHelper,
-  _Iterator, StopIteration */
+/* globals _Iterator, StopIteration */
 
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 
 const ToolDefinitions = require("devtools/client/main").Tools;
 const {CssLogic} = require("devtools/shared/styleinspector/css-logic");
 const {ELEMENT_STYLE} = require("devtools/server/actors/styles");
--- a/devtools/client/styleinspector/rule-view.js
+++ b/devtools/client/styleinspector/rule-view.js
@@ -1,18 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* globals overlays, Services, EventEmitter, StyleInspectorMenu,
-   clipboardHelper, _strings, domUtils, AutocompletePopup, loader,
-   osString */
-
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 const promise = require("promise");
 const {setTimeout, clearTimeout} =
       Cu.import("resource://gre/modules/Timer.jsm", {});
 const {CssLogic} = require("devtools/shared/styleinspector/css-logic");
 const {InplaceEditor, editableField, editableItem} =
--- a/devtools/client/styleinspector/style-inspector-menu.js
+++ b/devtools/client/styleinspector/style-inspector-menu.js
@@ -1,16 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* globals overlays, Services, clipboardHelper, _strings */
-
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 
 loader.lazyRequireGetter(this, "overlays",
   "devtools/client/styleinspector/style-inspector-overlays");
 loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
--- a/devtools/client/styleinspector/style-inspector.js
+++ b/devtools/client/styleinspector/style-inspector.js
@@ -1,16 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* globals RuleView, ComputedView, gDevTools */
-
 "use strict";
 
 const {Cc, Cu, Ci} = require("chrome");
 const promise = require("promise");
 const {Tools} = require("devtools/client/main");
 Cu.import("resource://gre/modules/Services.jsm");
 const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 
--- a/devtools/client/styleinspector/utils.js
+++ b/devtools/client/styleinspector/utils.js
@@ -1,16 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/* global domUtils */
-
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 const {setTimeout, clearTimeout} =
       Cu.import("resource://gre/modules/Timer.jsm", {});
 const {parseDeclarations} =
       require("devtools/client/styleinspector/css-parsing-utils");
 const promise = require("promise");
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -1,12 +1,11 @@
 /* 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/. */
-/* globals DevToolsUtils, DOMParser, eventListenerService, CssLogic */
 
 "use strict";
 
 /**
  * Here's the server side of the remote inspector.
  *
  * The WalkerActor is the client's view of the debuggee's DOM.  It's gives
  * the client a tree of NodeActor objects.
@@ -321,16 +320,17 @@ var NodeActor = exports.NodeActor = prot
    */
   watchDocument: function(callback) {
     let node = this.rawNode;
     // Create the observer on the node's actor.  The node will make sure
     // the observer is cleaned up when the actor is released.
     let observer = new node.defaultView.MutationObserver(callback);
     observer.mergeAttributeRecords = true;
     observer.observe(node, {
+      nativeAnonymousChildList: true,
       attributes: true,
       characterData: true,
       childList: true,
       subtree: true
     });
     this.mutationObserver = observer;
   },
 
@@ -2808,35 +2808,36 @@ var WalkerActor = protocol.ActorClass({
    */
   onMutations: function(mutations) {
     for (let change of mutations) {
       let targetActor = this._refMap.get(change.target);
       if (!targetActor) {
         continue;
       }
       let targetNode = change.target;
+      let type = change.type;
       let mutation = {
-        type: change.type,
+        type: type,
         target: targetActor.actorID,
       };
 
-      if (mutation.type === "attributes") {
+      if (type === "attributes") {
         mutation.attributeName = change.attributeName;
         mutation.attributeNamespace = change.attributeNamespace || undefined;
         mutation.newValue = targetNode.hasAttribute(mutation.attributeName) ?
                             targetNode.getAttribute(mutation.attributeName)
                             : null;
-      } else if (mutation.type === "characterData") {
+      } else if (type === "characterData") {
         if (targetNode.nodeValue.length > gValueSummaryLength) {
           mutation.newValue = targetNode.nodeValue.substring(0, gValueSummaryLength);
           mutation.incompleteValue = true;
         } else {
           mutation.newValue = targetNode.nodeValue;
         }
-      } else if (mutation.type === "childList") {
+      } else if (type === "childList" || type === "nativeAnonymousChildList") {
         // Get the list of removed and added actors that the client has seen
         // so that it can keep its ownership tree up to date.
         let removedActors = [];
         let addedActors = [];
         for (let removed of change.removedNodes) {
           let removedActor = this._refMap.get(removed);
           if (!removedActor) {
             // If the client never encountered this actor we don't need to
@@ -3328,17 +3329,17 @@ var WalkerFront = exports.WalkerFront = 
 
         if (!targetFront) {
           console.trace("Got a mutation for an unexpected actor: " + targetID + ", please file a bug on bugzilla.mozilla.org!");
           continue;
         }
 
         let emittedMutation = object.merge(change, { target: targetFront });
 
-        if (change.type === "childList") {
+        if (change.type === "childList" || change.type === "nativeAnonymousChildList") {
           // Update the ownership tree according to the mutation record.
           let addedFronts = [];
           let removedFronts = [];
           for (let removed of change.removed) {
             let removedFront = this.get(removed);
             if (!removedFront) {
               console.error("Got a removal of an actor we didn't know about: " + removed);
               continue;
--- a/devtools/server/actors/promises.js
+++ b/devtools/server/actors/promises.js
@@ -7,18 +7,16 @@
 const protocol = require("devtools/server/protocol");
 const { method, RetVal, Arg, types } = protocol;
 const { expectState, ActorPool } = require("devtools/server/actors/common");
 const { ObjectActor,
         createValueGrip } = require("devtools/server/actors/object");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "events", "sdk/event/core");
 
-/* global events */
-
 // Teach protocol.js how to deal with legacy actor types
 types.addType("ObjectActor", {
   write: actor => actor.grip(),
   read: grip => grip
 });
 
 /**
  * The Promises Actor provides support for getting the list of live promises and
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -1,12 +1,12 @@
 /* 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/. */
-/* globals CssLogic, DOMUtils, CSS */
+/* globals CSS */
 
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 const promise = require("promise");
 const protocol = require("devtools/server/protocol");
 const {Arg, Option, method, RetVal, types} = protocol;
 const events = require("sdk/event/core");
--- a/devtools/shared/gcli/commands/highlight.js
+++ b/devtools/shared/gcli/commands/highlight.js
@@ -1,12 +1,11 @@
 /* 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/. */
-/* globals nodesSelected, PluralForm */
 
 "use strict";
 
 const l10n = require("gcli/l10n");
 require("devtools/server/actors/inspector");
 const {
   BoxModelHighlighter,
   HighlighterEnvironment
--- a/devtools/shared/output-parser.js
+++ b/devtools/shared/output-parser.js
@@ -1,14 +1,12 @@
 /* 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/. */
 
-/* globals DOMUtils */
-
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 const {colorUtils} = require("devtools/shared/css-color");
 const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -1,13 +1,11 @@
 /* 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/. */
-/* globals NetworkHelper, Services, DevToolsUtils, NetUtil,
-   gActivityDistributor */
 
 "use strict";
 
 const {Cc, Ci, Cu, Cr} = require("chrome");
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 loader.lazyRequireGetter(this, "NetworkHelper",
--- a/mobile/android/base/home/HistoryPanel.java
+++ b/mobile/android/base/home/HistoryPanel.java
@@ -106,17 +106,17 @@ public class HistoryPanel extends HomeFr
         YESTERDAY,
         WEEK,
         THIS_MONTH,
         MONTH_AGO,
         TWO_MONTHS_AGO,
         THREE_MONTHS_AGO,
         FOUR_MONTHS_AGO,
         FIVE_MONTHS_AGO,
-        MostRecentSection, OLDER_THAN_SIX_MONTHS
+        OLDER_THAN_SIX_MONTHS
     };
 
     protected interface HistoryUrlProvider {
         public String getURL(int position);
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -403,25 +403,25 @@ public class HistoryPanel extends HomeFr
         recentSectionTimeOffsetList.add(MostRecentSection.WEEK.ordinal(),
                 new MostRecentSectionRange(cal.getTimeInMillis() - MS_PER_WEEK, now, context.getString(R.string.history_week_section)));
 
         // Update the calendar to start of next month.
         cal.add(Calendar.MONTH, 1);
         cal.set(Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DAY_OF_MONTH));
 
         // Iterate over the remaining MostRecentSections, to find the start, end and display text.
-        for (int i = MostRecentSection.THIS_MONTH.ordinal(); i <= MostRecentSection.OLDER_THAN_SIX_MONTHS.ordinal(); i++) {
+        for (int i = MostRecentSection.THIS_MONTH.ordinal(); i < MostRecentSection.OLDER_THAN_SIX_MONTHS.ordinal(); i++) {
             final long end = cal.getTimeInMillis();
             cal.add(Calendar.MONTH, -1);
             final long start = cal.getTimeInMillis();
-            final String displayName = (i != MostRecentSection.OLDER_THAN_SIX_MONTHS.ordinal())
-                    ? cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault())
-                    : context.getString(R.string.history_older_section);
+            final String displayName = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
             recentSectionTimeOffsetList.add(i, new MostRecentSectionRange(start, end, displayName));
         }
+        recentSectionTimeOffsetList.add(MostRecentSection.OLDER_THAN_SIX_MONTHS.ordinal(),
+                new MostRecentSectionRange(0L, cal.getTimeInMillis(), context.getString(R.string.history_older_section)));
     }
 
     private static class HistoryCursorLoader extends SimpleCursorLoader {
         // Max number of history results
         private static final int HISTORY_LIMIT = 100;
         private final BrowserDB mDB;
 
         public HistoryCursorLoader(Context context) {
--- a/mobile/android/base/preferences/GeckoPreferences.java
+++ b/mobile/android/base/preferences/GeckoPreferences.java
@@ -132,16 +132,17 @@ OnSharedPreferenceChangeListener
     public static final String PREFS_QRCODE_ENABLED = NON_PREF_PREFIX + "qrcode_enabled";
     private static final String PREFS_DEVTOOLS = NON_PREF_PREFIX + "devtools.enabled";
     private static final String PREFS_DISPLAY = NON_PREF_PREFIX + "display.enabled";
     private static final String PREFS_CUSTOMIZE_HOME = NON_PREF_PREFIX + "customize_home";
     private static final String PREFS_CUSTOMIZE_IMAGE_BLOCKING = "browser.image_blocking.enabled";
     private static final String PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING = "privacy.trackingprotection.pbmode.enabled";
     private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
     private static final String PREFS_CATEGORY_PRIVATE_DATA = NON_PREF_PREFIX + "category_private_data";
+    private static final String PREFS_CATEGORY_HOMEPAGE = NON_PREF_PREFIX + "category_homepage";
     public static final String PREFS_HOMEPAGE = NON_PREF_PREFIX + "homepage";
     public static final String PREFS_HISTORY_SAVED_SEARCH = NON_PREF_PREFIX + "search.search_history.enabled";
 
     private static final String ACTION_STUMBLER_UPLOAD_PREF = AppConstants.ANDROID_PACKAGE_NAME + ".STUMBLER_PREF";
 
 
     // This isn't a Gecko pref, even if it looks like one.
     private static final String PREFS_BROWSER_LOCALE = "locale";
@@ -728,17 +729,24 @@ OnSharedPreferenceChangeListener
                 }
                 if (PREFS_CATEGORY_PRIVATE_DATA.equals(key)) {
                     if (!RestrictedProfiles.isAllowed(this, Restriction.DISALLOW_CLEAR_HISTORY)) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
                     }
                 }
-
+                if (PREFS_CATEGORY_HOMEPAGE.equals(key)) {
+                    // Only enable the home page setting on Nightly.
+                    if (!AppConstants.NIGHTLY_BUILD) {
+                        preferences.removePreference(pref);
+                        i--;
+                        continue;
+                    }
+                }
                 setupPreferences((PreferenceGroup) pref, prefs);
             } else {
                 pref.setOnPreferenceChangeListener(this);
                 if (PREFS_UPDATER_AUTODOWNLOAD.equals(key)) {
                     if (!AppConstants.MOZ_UPDATER) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
--- a/mobile/android/base/resources/xml/preferences_home.xml
+++ b/mobile/android/base/resources/xml/preferences_home.xml
@@ -2,17 +2,18 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                   android:title="@string/pref_category_home"
                   android:enabled="false">
 
-    <PreferenceCategory android:title="@string/pref_category_home_homepage">
+    <PreferenceCategory android:title="@string/pref_category_home_homepage"
+                        android:key="android.not_a_preference.category_homepage">
 
         <org.mozilla.gecko.preferences.SetHomepagePreference
                 android:key="android.not_a_preference.homepage"
                 android:title="@string/home_homepage_title" />
 
     </PreferenceCategory>
 
     <org.mozilla.gecko.preferences.PanelsPreferenceCategory
--- a/mobile/android/chrome/content/PrintHelper.js
+++ b/mobile/android/chrome/content/PrintHelper.js
@@ -40,16 +40,22 @@ var PrintHelper = {
     printSettings.printFrameType = Ci.nsIPrintSettings.kFramesAsIs;
     printSettings.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF;
 
     let webBrowserPrint = aBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebBrowserPrint);
 
     return new Promise((resolve, reject) => {
       webBrowserPrint.print(printSettings, {
         onStateChange: function(webProgress, request, stateFlags, status) {
+          // We get two STATE_START calls, one for STATE_IS_DOCUMENT and one for STATE_IS_NETWORK
+          if (stateFlags & Ci.nsIWebProgressListener.STATE_START && stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
+            // Let the user know something is happening. Generating the PDF can take some time.
+            NativeWindow.toast.show(Strings.browser.GetStringFromName("alertPrintjobToast"), "long");
+          }
+
           // We get two STATE_STOP calls, one for STATE_IS_DOCUMENT and one for STATE_IS_NETWORK
           if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP && stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
             if (Components.isSuccessCode(status)) {
               // Send the details to Java
               resolve({ file: file.path, title: fileName });
             } else {
               reject();
             }
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -33,16 +33,18 @@ alertFullScreenToast=Press BACK to leave
 
 # LOCALIZATION NOTE (alertSearchEngineAddedToast, alertSearchEngineErrorToast, alertSearchEngineDuplicateToast)
 # %S will be replaced by the name of the search engine (exposed by the current page)
 # that has been added; for example, 'Google'.
 alertSearchEngineAddedToast='%S' has been added as a search engine
 alertSearchEngineErrorToast=Couldn't add '%S' as a search engine
 alertSearchEngineDuplicateToast='%S' is already one of your search engines
 
+alertPrintjobToast=Printing…
+
 downloadCancelPromptTitle=Cancel Download
 downloadCancelPromptMessage=Do you want to cancel this download?
 
 addonError.titleError=Error
 addonError.titleBlocked=Blocked add-on
 addonError.learnMore=Learn more
 
 # LOCALIZATION NOTE (unsignedAddonsDisabled.title, unsignedAddonsDisabled.message):
--- a/python/mach_commands.py
+++ b/python/mach_commands.py
@@ -3,39 +3,71 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import argparse
 import logging
 import mozpack.path as mozpath
 import os
+import platform
+import subprocess
+import sys
 import which
 
 from mozbuild.base import (
     MachCommandBase,
 )
 
 from mach.decorators import (
     CommandArgument,
     CommandProvider,
     Command,
 )
 
-
 ESLINT_NOT_FOUND_MESSAGE = '''
 Could not find eslint!  We looked at the --binary option, at the ESLINT
 environment variable, and then at your path.  Install eslint and needed plugins
 with
 
-npm install -g eslint eslint-plugin-react
+mach eslint --setup
 
 and try again.
 '''.strip()
 
+NODE_NOT_FOUND_MESSAGE = '''
+nodejs is either not installed or is installed to a non-standard path.
+Please install nodejs from https://nodejs.org and try again.
+
+Valid installation paths:
+'''.strip()
+
+NPM_NOT_FOUND_MESSAGE = '''
+Node Package Manager (npm) is either not installed or installed to a
+non-standard path. Please install npm from https://nodejs.org (it comes as an
+option in the node installation) and try again.
+
+Valid installation paths:
+'''.strip()
+
+ESLINT_PROMPT = '''
+Would you like to use eslint
+'''.strip()
+
+ESLINT_PLUGIN_MOZILLA_PROMPT = '''
+eslint-plugin-mozilla is an eslint plugin containing rules that help enforce
+JavaScript coding standards in the Mozilla project. Would you like to use this
+plugin
+'''.strip()
+
+ESLINT_PLUGIN_REACT_PROMPT = '''
+eslint-plugin-react is an eslint plugin containing rules that help React
+developers follow strict guidelines. Would you like to install it
+'''.strip()
+
 
 @CommandProvider
 class MachCommands(MachCommandBase):
     @Command('python', category='devenv',
         description='Run Python.')
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def python(self, args):
         # Avoid logging the command
@@ -127,29 +159,35 @@ class MachCommands(MachCommandBase):
                 else:
                     self.log(logging.INFO, 'python-test', {'file': f},
                              'Test passed: {file}')
             if stop and return_code > 0:
                 return 1
 
         return 0 if return_code == 0 else 1
 
-    @Command('eslint', category='devenv')
+    @Command('eslint', category='devenv',
+        description='Run eslint or help configure eslint for optimal development.')
+    @CommandArgument('-s', '--setup', default=False, action='store_true',
+        help='configure eslint for optimal development.')
     @CommandArgument('path', nargs='?', default='.',
         help='Path to files to lint, like "browser/components/loop" '
             'or "mobile/android". '
             'Defaults to the current directory if not given.')
     @CommandArgument('-e', '--ext', default='[.js,.jsm,.jsx]',
         help='Filename extensions to lint, default: "[.js,.jsm,.jsx]".')
     @CommandArgument('-b', '--binary', default=None,
         help='Path to eslint binary.')
     @CommandArgument('args', nargs=argparse.REMAINDER)  # Passed through to eslint.
-    def eslint(self, path, ext=None, binary=None, args=[]):
+    def eslint(self, setup, path, ext=None, binary=None, args=[]):
         '''Run eslint.'''
 
+        if setup:
+            return self.eslint_setup()
+
         if not binary:
             binary = os.environ.get('ESLINT', None)
             if not binary:
                 try:
                     binary = which.which('eslint')
                 except which.WhichError:
                     pass
 
@@ -177,8 +215,105 @@ class MachCommands(MachCommandBase):
         # Path must come after arguments.  Path is '.' due to cwd below.
         cmd_args += ['.']
 
         return self.run_process(cmd_args,
             cwd=path,
             pass_thru=True,  # Allow user to run eslint interactively.
             ensure_exit_code=False,  # Don't throw on non-zero exit code.
         )
+    def eslint_setup(self, update_only=False):
+        """Ensure eslint is optimally configured.
+
+        This command will inspect your eslint configuration and
+        guide you through an interactive wizard helping you configure
+        eslint for optimal use on Mozilla projects.
+        """
+        sys.path.append(os.path.dirname(__file__))
+
+        # At the very least we need node installed.
+        nodePath = self.getNodeOrNpmPath("node")
+        if not nodePath:
+            return 1
+
+        npmPath = self.getNodeOrNpmPath("npm")
+        if not npmPath:
+            return 1
+
+        # Install eslint.
+        print("Installing eslint...")
+        with open(os.devnull, "w") as fnull:
+            subprocess.call([npmPath, "install", "eslint", "-g"],
+                            stdout=fnull, stderr=fnull)
+
+        # Install eslint-plugin-mozilla.
+        print("")
+        print("Installing eslint-plugin-mozilla...")
+        with open(os.devnull, "w") as fnull:
+            subprocess.call([npmPath, "link"],
+                            cwd="testing/eslint-plugin-mozilla",
+                            stdout=fnull, stderr=fnull)
+
+        # Install eslint-plugin-react.
+        print("")
+        print("Installing eslint-plugin-react...")
+        with open(os.devnull, "w") as fnull:
+            subprocess.call([npmPath, "install", "-g", "eslint-plugin-react"],
+                            stdout=fnull, stderr=fnull)
+
+    def getPossibleNodePathsWin(self):
+        """
+        Return possible nodejs paths on Windows.
+        """
+        if platform.system() != "Windows":
+            return []
+
+        return {
+            "%s\\nodejs" % os.environ.get("SystemDrive"),
+            os.path.join(os.environ.get("ProgramFiles"), "nodejs"),
+            os.path.join(os.environ.get("PROGRAMW6432"), "nodejs"),
+            os.path.join(os.environ.get("PROGRAMFILES"), "nodejs")
+        }
+
+    def getNodeOrNpmPath(self, filename):
+        """
+        Return the nodejs or npm path.
+        """
+        try:
+            appPath = which.which(filename)
+            return appPath
+        except which.WhichError:
+            pass
+
+        if platform.system() == "Windows":
+            try:
+                for ext in ["", ".cmd", ".exe"]:
+                    nodeOrNpmPath = which.which(filename + ext,
+                                                path=self.getPossibleNodePathsWin())
+                    if self.is_valid(nodeOrNpmPath):
+                        return nodeOrNpmPath
+            except which.WhichError:
+                pass
+
+        if filename == "node":
+            print(NODE_NOT_FOUND_MESSAGE)
+        elif filename == "npm":
+            print(NPM_NOT_FOUND_MESSAGE)
+
+        if platform.system() == "Windows":
+            appPaths = self.getPossibleNodePathsWin()
+
+            for p in appPaths:
+                print("  - " + p)
+        elif platform.system() == "Darwin":
+            print("  - /usr/local/bin/node")
+        elif platform.system() == "Linux":
+            print("  - /usr/bin/nodejs")
+
+        return None
+
+    def is_valid(self, path):
+        try:
+            with open(os.devnull, "w") as fnull:
+                subprocess.check_call([path, "--version"], stdout=fnull)
+                return True
+        except subprocess.CalledProcessError:
+            return False
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/LICENSE
@@ -0,0 +1,363 @@
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+     means each individual or legal entity that creates, contributes to the
+     creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+     means the combination of the Contributions of others (if any) used by a
+     Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+     means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+     means Source Code Form to which the initial Contributor has attached the
+     notice in Exhibit A, the Executable Form of such Source Code Form, and
+     Modifications of such Source Code Form, in each case including portions
+     thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+     means
+
+     a. that the initial Contributor has attached the notice described in
+        Exhibit B to the Covered Software; or
+
+     b. that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the terms of
+        a Secondary License.
+
+1.6. "Executable Form"
+
+     means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+     means a work that combines Covered Software with other material, in a
+     separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+     means this document.
+
+1.9. "Licensable"
+
+     means having the right to grant, to the maximum extent possible, whether
+     at the time of the initial grant or subsequently, any and all of the
+     rights conveyed by this License.
+
+1.10. "Modifications"
+
+     means any of the following:
+
+     a. any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered Software; or
+
+     b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+      means any patent claim(s), including without limitation, method,
+      process, and apparatus claims, in any patent Licensable by such
+      Contributor that would be infringed, but for the grant of the License,
+      by the making, using, selling, offering for sale, having made, import,
+      or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+      means either the GNU General Public License, Version 2.0, the GNU Lesser
+      General Public License, Version 2.1, the GNU Affero General Public
+      License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+      means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+      means an individual or a legal entity exercising rights under this
+      License. For legal entities, "You" includes any entity that controls, is
+      controlled by, or is under common control with You. For purposes of this
+      definition, "control" means (a) the power, direct or indirect, to cause
+      the direction or management of such entity, whether by contract or
+      otherwise, or (b) ownership of more than fifty percent (50%) of the
+      outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+     Each Contributor hereby grants You a world-wide, royalty-free,
+     non-exclusive license:
+
+     a. under intellectual property rights (other than patent or trademark)
+        Licensable by such Contributor to use, reproduce, make available,
+        modify, display, perform, distribute, and otherwise exploit its
+        Contributions, either on an unmodified basis, with Modifications, or
+        as part of a Larger Work; and
+
+     b. under Patent Claims of such Contributor to make, use, sell, offer for
+        sale, have made, import, and otherwise transfer either its
+        Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+     The licenses granted in Section 2.1 with respect to any Contribution
+     become effective for each Contribution on the date the Contributor first
+     distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+     The licenses granted in this Section 2 are the only rights granted under
+     this License. No additional rights or licenses will be implied from the
+     distribution or licensing of Covered Software under this License.
+     Notwithstanding Section 2.1(b) above, no patent license is granted by a
+     Contributor:
+
+     a. for any code that a Contributor has removed from Covered Software; or
+
+     b. for infringements caused by: (i) Your and any other third party's
+        modifications of Covered Software, or (ii) the combination of its
+        Contributions with other software (except as part of its Contributor
+        Version); or
+
+     c. under Patent Claims infringed by Covered Software in the absence of
+        its Contributions.
+
+     This License does not grant any rights in the trademarks, service marks,
+     or logos of any Contributor (except as may be necessary to comply with
+     the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+     No Contributor makes additional grants as a result of Your choice to
+     distribute the Covered Software under a subsequent version of this
+     License (see Section 10.2) or under the terms of a Secondary License (if
+     permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+     Each Contributor represents that the Contributor believes its
+     Contributions are its original creation(s) or it has sufficient rights to
+     grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+     This License is not intended to limit any rights You have under
+     applicable copyright doctrines of fair use, fair dealing, or other
+     equivalents.
+
+2.7. Conditions
+
+     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+     Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+     All distribution of Covered Software in Source Code Form, including any
+     Modifications that You create or to which You contribute, must be under
+     the terms of this License. You must inform recipients that the Source
+     Code Form of the Covered Software is governed by the terms of this
+     License, and how they can obtain a copy of this License. You may not
+     attempt to alter or restrict the recipients' rights in the Source Code
+     Form.
+
+3.2. Distribution of Executable Form
+
+     If You distribute Covered Software in Executable Form then:
+
+     a. such Covered Software must also be made available in Source Code Form,
+        as described in Section 3.1, and You must inform recipients of the
+        Executable Form how they can obtain a copy of such Source Code Form by
+        reasonable means in a timely manner, at a charge no more than the cost
+        of distribution to the recipient; and
+
+     b. You may distribute such Executable Form under the terms of this
+        License, or sublicense it under different terms, provided that the
+        license for the Executable Form does not attempt to limit or alter the
+        recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+     You may create and distribute a Larger Work under terms of Your choice,
+     provided that You also comply with the requirements of this License for
+     the Covered Software. If the Larger Work is a combination of Covered
+     Software with a work governed by one or more Secondary Licenses, and the
+     Covered Software is not Incompatible With Secondary Licenses, this
+     License permits You to additionally distribute such Covered Software
+     under the terms of such Secondary License(s), so that the recipient of
+     the Larger Work may, at their option, further distribute the Covered
+     Software under the terms of either this License or such Secondary
+     License(s).
+
+3.4. Notices
+
+     You may not remove or alter the substance of any license notices
+     (including copyright notices, patent notices, disclaimers of warranty, or
+     limitations of liability) contained within the Source Code Form of the
+     Covered Software, except that You may alter any license notices to the
+     extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+     You may choose to offer, and to charge a fee for, warranty, support,
+     indemnity or liability obligations to one or more recipients of Covered
+     Software. However, You may do so only on Your own behalf, and not on
+     behalf of any Contributor. You must make it absolutely clear that any
+     such warranty, support, indemnity, or liability obligation is offered by
+     You alone, and You hereby agree to indemnify every Contributor for any
+     liability incurred by such Contributor as a result of warranty, support,
+     indemnity or liability terms You offer. You may include additional
+     disclaimers of warranty and limitations of liability specific to any
+     jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+   If it is impossible for You to comply with any of the terms of this License
+   with respect to some or all of the Covered Software due to statute,
+   judicial order, or regulation then You must: (a) comply with the terms of
+   this License to the maximum extent possible; and (b) describe the
+   limitations and the code they affect. Such description must be placed in a
+   text file included with all distributions of the Covered Software under
+   this License. Except to the extent prohibited by statute or regulation,
+   such description must be sufficiently detailed for a recipient of ordinary
+   skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+     fail to comply with any of its terms. However, if You become compliant,
+     then the rights granted under this License from a particular Contributor
+     are reinstated (a) provisionally, unless and until such Contributor
+     explicitly and finally terminates Your grants, and (b) on an ongoing
+     basis, if such Contributor fails to notify You of the non-compliance by
+     some reasonable means prior to 60 days after You have come back into
+     compliance. Moreover, Your grants from a particular Contributor are
+     reinstated on an ongoing basis if such Contributor notifies You of the
+     non-compliance by some reasonable means, this is the first time You have
+     received notice of non-compliance with this License from such
+     Contributor, and You become compliant prior to 30 days after Your receipt
+     of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+     infringement claim (excluding declaratory judgment actions,
+     counter-claims, and cross-claims) alleging that a Contributor Version
+     directly or indirectly infringes any patent, then the rights granted to
+     You by any and all Contributors for the Covered Software under Section
+     2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+     license agreements (excluding distributors and resellers) which have been
+     validly granted by You or Your distributors under this License prior to
+     termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+   Covered Software is provided under this License on an "as is" basis,
+   without warranty of any kind, either expressed, implied, or statutory,
+   including, without limitation, warranties that the Covered Software is free
+   of defects, merchantable, fit for a particular purpose or non-infringing.
+   The entire risk as to the quality and performance of the Covered Software
+   is with You. Should any Covered Software prove defective in any respect,
+   You (not any Contributor) assume the cost of any necessary servicing,
+   repair, or correction. This disclaimer of warranty constitutes an essential
+   part of this License. No use of  any Covered Software is authorized under
+   this License except under this disclaimer.
+
+7. Limitation of Liability
+
+   Under no circumstances and under no legal theory, whether tort (including
+   negligence), contract, or otherwise, shall any Contributor, or anyone who
+   distributes Covered Software as permitted above, be liable to You for any
+   direct, indirect, special, incidental, or consequential damages of any
+   character including, without limitation, damages for lost profits, loss of
+   goodwill, work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses, even if such party shall have been
+   informed of the possibility of such damages. This limitation of liability
+   shall not apply to liability for death or personal injury resulting from
+   such party's negligence to the extent applicable law prohibits such
+   limitation. Some jurisdictions do not allow the exclusion or limitation of
+   incidental or consequential damages, so this exclusion and limitation may
+   not apply to You.
+
+8. Litigation
+
+   Any litigation relating to this License may be brought only in the courts
+   of a jurisdiction where the defendant maintains its principal place of
+   business and such litigation shall be governed by laws of that
+   jurisdiction, without reference to its conflict-of-law provisions. Nothing
+   in this Section shall prevent a party's ability to bring cross-claims or
+   counter-claims.
+
+9. Miscellaneous
+
+   This License represents the complete agreement concerning the subject
+   matter hereof. If any provision of this License is held to be
+   unenforceable, such provision shall be reformed only to the extent
+   necessary to make it enforceable. Any law or regulation which provides that
+   the language of a contract shall be construed against the drafter shall not
+   be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+      Mozilla Foundation is the license steward. Except as provided in Section
+      10.3, no one other than the license steward has the right to modify or
+      publish new versions of this License. Each version will be given a
+      distinguishing version number.
+
+10.2. Effect of New Versions
+
+      You may distribute the Covered Software under the terms of the version
+      of the License under which You originally received the Covered Software,
+      or under the terms of any subsequent version published by the license
+      steward.
+
+10.3. Modified Versions
+
+      If you create software not governed by this License, and you want to
+      create a new license for such software, you may create and use a
+      modified version of this License if you rename the license and remove
+      any references to the name of the license steward (except to note that
+      such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+      Licenses If You choose to distribute Source Code Form that is
+      Incompatible With Secondary Licenses under the terms of this version of
+      the License, the notice described in Exhibit B of this License must be
+      attached.
+
+Exhibit A - Source Code Form License Notice
+
+      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/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+      This Source Code Form is "Incompatible
+      With Secondary Licenses", as defined by
+      the Mozilla Public License, v. 2.0.
+
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/docs/components-imports.rst
@@ -0,0 +1,21 @@
+.. _components-imports:
+
+==================
+components-imports
+==================
+
+Rule Details
+------------
+
+Adds the filename of imported files e.g.
+``Cu.import("some/path/Blah.jsm")`` adds Blah to the global scope.
+
+The following patterns are supported:
+
+-  ``Cu.import("resource:///modules/devtools/ViewHelpers.jsm");``
+-  ``loader.lazyImporter(this, "name1");``
+-  ``loader.lazyRequireGetter(this, "name2"``
+-  ``loader.lazyServiceGetter(this, "name3"``
+-  ``XPCOMUtils.defineLazyModuleGetter(this, "setNamedTimeout", ...)``
+-  ``loader.lazyGetter(this, "toolboxStrings"``
+-  ``XPCOMUtils.defineLazyGetter(this, "clipboardHelper"``
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/docs/import-headjs-globals.rst
@@ -0,0 +1,31 @@
+.. _import-headjs-globals:
+
+=====================
+import-headjs-globals
+=====================
+
+Rule Details
+------------
+
+Import globals from head.js and from any files that were imported by
+head.js (as far as we can correctly resolve the path).
+
+The following file import patterns are supported:
+
+-  ``Services.scriptloader.loadSubScript(path)``
+-  ``loader.loadSubScript(path)``
+-  ``loadSubScript(path)``
+-  ``loadHelperScript(path)``
+
+If path does not exist because it is generated e.g.
+``testdir + "/somefile.js"`` we do our best to resolve it.
+
+The following patterns are supported:
+
+-  ``Cu.import("resource:///modules/devtools/ViewHelpers.jsm");``
+-  ``loader.lazyImporter(this, "name1");``
+-  ``loader.lazyRequireGetter(this, "name2"``
+-  ``loader.lazyServiceGetter(this, "name3"``
+-  ``XPCOMUtils.defineLazyModuleGetter(this, "setNamedTimeout", ...)``
+-  ``loader.lazyGetter(this, "toolboxStrings"``
+-  ``XPCOMUtils.defineLazyGetter(this, "clipboardHelper"``
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/docs/index.rst
@@ -0,0 +1,41 @@
+.. _index:
+
+=====================
+Mozilla ESLint Plugin
+=====================
+
+``components-imports`` adds the filename of imported files e.g.
+``Cu.import("some/path/Blah.jsm")`` adds Blah to the global scope.
+
+``import-headjs-globals`` imports globals from head.js and from any files that
+should be imported by head.js (as far as we can correctly resolve the path).
+
+``mark-test-function-used`` simply marks test (the test method) as used. This
+avoids ESLint telling us that the function is never called.
+
++-------+-----------------------+
+| Possible values for all rules |
++-------+-----------------------+
+| Value | Meaning               |
++-------+-----------------------+
+| 0     | Deactivated           |
++-------+-----------------------+
+| 1     | Warning               |
++-------+-----------------------+
+| 2     | Error                 |
++-------+-----------------------+
+
+Example configuration::
+
+   "rules": {
+     "mozilla/components-imports": 1,
+     "mozilla/import-headjs-globals": 1,
+     "mozilla/mark-test-function-used": 1,
+   }
+
+.. toctree::
+   :maxdepth: 1
+
+   components-imports
+   import-headjs-globals
+   mark-test-function-used
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/docs/mark-test-function-used.rst
@@ -0,0 +1,11 @@
+.. _mark-test-function-used:
+
+=======================
+mark-test-function-used
+=======================
+
+Rule Details
+------------
+
+Simply marks test (the test method) as used. This avoids ESLint telling
+us that the function is never called.
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/lib/helpers.js
@@ -0,0 +1,193 @@
+/**
+ * @fileoverview A collection of helper functions.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+var escope = require("eslint/node_modules/escope");
+var espree = require("eslint/node_modules/espree");
+
+var regexes = [
+  /^(?:Cu|Components\.utils)\.import\(".*\/(.*?)\.jsm?"\);?$/,
+  /^loader\.lazyImporter\(\w+, "(\w+)"/,
+  /^loader\.lazyRequireGetter\(\w+, "(\w+)"/,
+  /^loader\.lazyServiceGetter\(\w+, "(\w+)"/,
+  /^XPCOMUtils\.defineLazyModuleGetter\(\w+, "(\w+)"/,
+  /^loader\.lazyGetter\(\w+, "(\w+)"/,
+  /^XPCOMUtils\.defineLazyGetter\(\w+, "(\w+)"/
+];
+
+module.exports = {
+  /**
+   * Gets the abstract syntax tree (AST) of the JavaScript source code contained
+   * in sourceText.
+   *
+   * @param  {String} sourceText
+   *         Text containing valid JavaScript.
+   *
+   * @return {Object}
+   *         The resulting AST.
+   */
+  getAST: function(sourceText) {
+    // Use a permissive config file to allow parsing of anything that Espree
+    // can parse.
+    var config = this.getPermissiveConfig();
+
+    return espree.parse(sourceText, config);
+  },
+
+  /**
+   * Gets the source text of an AST node.
+   *
+   * @param  {ASTNode} node
+   *         The AST node representing the source text.
+   * @param  {ASTContext} context
+   *         The current context.
+   *
+   * @return {String}
+   *         The source text representing the AST node.
+   */
+  getSource: function(node, context) {
+    return context.getSource(node).replace(/[\r\n]+\s*/g, " ")
+                                  .replace(/\s*=\s*/g, " = ")
+                                  .replace(/\s+\./g, ".")
+                                  .replace(/,\s+/g, ", ")
+                                  .replace(/;\n(\d+)/g, ";$1")
+                                  .replace(/\s+/g, " ");
+  },
+
+  /**
+   * Gets the variable name from an import source
+   * e.g. Cu.import("path/to/someName") will return "someName."
+   *
+   * Some valid input strings:
+   *  - Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
+   *  - loader.lazyImporter(this, "name1");
+   *  - loader.lazyRequireGetter(this, "name2"
+   *  - loader.lazyServiceGetter(this, "name3"
+   *  - XPCOMUtils.defineLazyModuleGetter(this, "setNamedTimeout", ...)
+   *  - loader.lazyGetter(this, "toolboxStrings"
+   *  - XPCOMUtils.defineLazyGetter(this, "clipboardHelper"
+   *
+   * @param  {String} source
+   *         The source representing an import statement.
+   *
+   * @return {String}
+   *         The variable name imported.
+   */
+  getVarNameFromImportSource: function(source) {
+    for (var i = 0; i < regexes.length; i++) {
+      var regex = regexes[i];
+      var matches = source.match(regex);
+
+      if (matches) {
+        var name = matches[1];
+
+        return name;
+      }
+    }
+  },
+
+  /**
+   * Get an array of globals from an AST.
+   *
+   * @param  {Object} ast
+   *         The AST for which the globals are to be returned.
+   *
+   * @return {Array}
+   *         An array of variable names.
+   */
+  getGlobals: function(ast) {
+    var scopeManager = escope.analyze(ast);
+    var globalScope = scopeManager.acquire(ast);
+    var result = [];
+
+    for (var variable in globalScope.variables) {
+      var name = globalScope.variables[variable].name;
+      result.push(name);
+    }
+
+    return result;
+  },
+
+  /**
+   * Add a variable to the current scope.
+   * HACK: This relies on eslint internals so it could break at any time.
+   *
+   * @param {String} name
+   *        The variable name to add to the current scope.
+   * @param {ASTContext} context
+   *        The current context.
+   */
+  addVarToScope: function(name, context) {
+    var scope = context.getScope();
+    var variables = scope.variables;
+    var variable = new escope.Variable(name, scope);
+
+    variable.eslintExplicitGlobal = false;
+    variable.writeable = true;
+    variables.push(variable);
+  },
+
+  /**
+   * Get the single line text represented by a particular AST node.
+   *
+   * @param  {ASTNode} node
+   *         The AST node representing the source text.
+   * @param  {String} text
+   *         The text representing the AST node.
+   *
+   * @return {String}
+   *         A single line version of the string represented by node.
+   */
+  getTextForNode: function(node, text) {
+    var source = text.substr(node.range[0], node.range[1] - node.range[0]);
+
+    return source.replace(/[\r\n]+\s*/g, "")
+                 .replace(/\s*=\s*/g, " = ")
+                 .replace(/\s+\./g, ".")
+                 .replace(/,\s+/g, ", ")
+                 .replace(/;\n(\d+)/g, ";$1");
+  },
+
+  /**
+   * To allow espree to parse almost any JavaScript we need as many features as
+   * possible turned on. This method returns that config.
+   *
+   * @return {Object}
+   *         Espree compatible permissive config.
+   */
+  getPermissiveConfig: function() {
+    return {
+      range: true,
+      loc: true,
+      tolerant: true,
+      ecmaFeatures: {
+        arrowFunctions: true,
+        blockBindings: true,
+        destructuring: true,
+        regexYFlag: true,
+        regexUFlag: true,
+        templateStrings: true,
+        binaryLiterals: true,
+        octalLiterals: true,
+        unicodeCodePointEscapes: true,
+        defaultParams: true,
+        restParams: true,
+        forOf: true,
+        objectLiteralComputedProperties: true,
+        objectLiteralShorthandMethods: true,
+        objectLiteralShorthandProperties: true,
+        objectLiteralDuplicateProperties: true,
+        generators: true,
+        spread: true,
+        superInFunctions: true,
+        classes: true,
+        modules: true,
+        globalReturn: true
+      }
+    };
+  }
+};
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/lib/index.js
@@ -0,0 +1,25 @@
+/**
+ * @fileoverview A collection of rules that help enforce JavaScript coding
+ * standard and avoid common errors in the Mozilla project.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Plugin Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+  rules: {
+    "components-imports": require("../lib/rules/components-imports"),
+    "import-headjs-globals": require("../lib/rules/import-headjs-globals"),
+    "mark-test-function-used": require("../lib/rules/mark-test-function-used")
+  },
+  rulesConfig: {
+    "components-imports": 0,
+    "import-headjs-globals": 0,
+    "mark-test-function-used": 0
+  }
+};
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/lib/rules/components-imports.js
@@ -0,0 +1,33 @@
+/**
+ * @fileoverview Adds the filename of imported files e.g.
+ * Cu.import("some/path/Blah.jsm") adds Blah to the current scope.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+var path = require("path");
+var helpers = require("../helpers");
+
+module.exports = function(context) {
+  //--------------------------------------------------------------------------
+  // Public
+  //--------------------------------------------------------------------------
+
+  return {
+    ExpressionStatement: function(node) {
+      var source = helpers.getSource(node, context);
+      var name = helpers.getVarNameFromImportSource(source);
+
+      if (name) {
+        helpers.addVarToScope(name, context);
+      }
+    }
+  };
+};
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js
@@ -0,0 +1,100 @@
+/**
+ * @fileoverview Import globals from head.js and from any files that were
+ * imported by head.js (as far as we can correctly resolve the path).
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+var fs = require("fs");
+var path = require("path");
+var helpers = require("../helpers");
+
+module.exports = function(context) {
+  //--------------------------------------------------------------------------
+  // Helpers
+  //--------------------------------------------------------------------------
+
+  function checkFile(fileArray, context) {
+    var filePath = fileArray.pop();
+
+    while (filePath) {
+      var headText;
+
+      try {
+        headText = fs.readFileSync(filePath, "utf8");
+      } catch(e) {
+        // Couldn't find file, continue.
+        filePath = fileArray.pop();
+        continue;
+      }
+
+      var ast = helpers.getAST(headText);
+      var globalVars = helpers.getGlobals(ast);
+
+      for (var i = 0; i < globalVars.length; i++) {
+        var name = globalVars[i];
+        helpers.addVarToScope(name, context);
+      }
+
+      for (var index in ast.body) {
+        var node = ast.body[index];
+        var source = helpers.getTextForNode(node, headText);
+        var name = helpers.getVarNameFromImportSource(source);
+
+        if (name) {
+          helpers.addVarToScope(name, context);
+          continue;
+        }
+
+        // Scripts loaded using loadSubScript or loadHelperScript
+        var matches =
+          source.match(/^(?:Services\.scriptloader\.|loader)?loadSubScript\((.+)[",]/);
+        if (!matches) {
+          matches = source.match(/^loadHelperScript\((.+)[",]/);
+        }
+        if (matches) {
+          var cwd = process.cwd();
+
+          filePath = matches[1];
+          filePath = filePath.replace("chrome://mochitests/content/browser", cwd + "/../../../..");
+          filePath = filePath.replace(/testdir\s*\+\s*["']/gi, cwd + "/");
+          filePath = filePath.replace(/test_dir\s*\+\s*["']/gi, cwd);
+          filePath = filePath.replace(/["']/gi, "");
+          filePath = path.normalize(filePath);
+
+          fileArray.push(filePath);
+        }
+      }
+
+      filePath = fileArray.pop();
+    }
+  }
+
+  //--------------------------------------------------------------------------
+  // Public
+  //--------------------------------------------------------------------------
+
+  return {
+    Program: function(node) {
+      var pathAndFilename = this.getFilename();
+      var processPath = process.cwd();
+      var isTest = /.*\/browser_.+\.js$/.test(pathAndFilename);
+
+      if (!isTest) {
+        return;
+      }
+
+      var testFilename = path.basename(pathAndFilename);
+      var testPath = path.join(processPath, testFilename);
+      var headjs = path.join(processPath, "head.js");
+      checkFile([testPath, headjs], context);
+    }
+  };
+};
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js
@@ -0,0 +1,25 @@
+/**
+ * @fileoverview Simply marks test (the test method) as used. This avoids ESLint
+ * telling us that the function is never called..
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+  //--------------------------------------------------------------------------
+  // Public
+  //--------------------------------------------------------------------------
+
+  return {
+    Program: function(node) {
+      context.markVariableAsUsed("test");
+    }
+  };
+};
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SPHINX_TREES['eslint-plugin-mozilla'] = 'docs'
new file mode 100644
--- /dev/null
+++ b/testing/eslint-plugin-mozilla/package.json
@@ -0,0 +1,25 @@
+{
+  "name": "eslint-plugin-mozilla",
+  "version": "0.0.2",
+  "description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
+  "keywords": [
+    "eslint",
+    "eslintplugin",
+    "eslint-plugin",
+    "mozilla",
+    "firefox"
+  ],
+  "bugs": {
+    "url": "https://bugzilla.mozilla.org/enter_bug.cgi?product=Firefox&component=Developer%20Tools"
+  },
+  "homepage": "https://bugzilla.mozilla.org/show_bug.cgi?id=1203520",
+  "author": "Mike Ratcliffe",
+  "main": "lib/index.js",
+  "devDependencies": {
+    "eslint": "~1.2.0"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "license": "MPL-2.0"
+}
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -342,16 +342,22 @@ function findMatchingStaticBlocklistItem
           (aAddon.selectedLocale && aAddon.selectedLocale.creator == item.creator)) {
         return item;
       }
     }
   }
   return null;
 }
 
+/**
+ * Converts an iterable of addon objects into a map with the add-on's ID as key.
+ */
+function addonMap(addons) {
+  return new Map([for (a of addons) [a.id, a]]);
+}
 
 /**
  * Sets permissions on a file
  *
  * @param  aFile
  *         The file or directory to operate on.
  * @param  aPermissions
  *         The permisions to set
@@ -2797,71 +2803,128 @@ this.XPIProvider = {
     let addonList = yield ProductAddonChecker.getProductAddonList(url);
 
     // If there was no list then do nothing.
     if (!addonList) {
       logger.info("No system add-ons list was returned.");
       return;
     }
 
-    addonList = [for (spec of addonList) { spec, path: null, addon: null }];
-
-    // Bug 1204159: If this matches the current set in the profile or app locations
-    // then just switch to those
+    addonList = new Map([for (spec of addonList) [spec.id, { spec, path: null, addon: null }]]);
+
+    let getAddonsInLocation = (location) => {
+      return new Promise(resolve => {
+        XPIDatabase.getAddonsInLocation(location, resolve);
+      });
+    };
+
+    let setMatches = (wanted, existing) => {
+      if (wanted.size != existing.size)
+        return false;
+
+      for (let [id, addon] of existing) {
+        let wantedInfo = wanted.get(id);
+
+        if (!wantedInfo)
+          return false;
+        if (wantedInfo.spec.version != addon.version)
+          return false;
+      }
+
+      return true;
+    };
 
     let systemAddonLocation = XPIProvider.installLocationsByName[KEY_APP_SYSTEM_ADDONS];
 
+    // If this matches the current set in the profile location then do nothing.
+    let updatedAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_ADDONS));
+    if (setMatches(addonList, updatedAddons)) {
+      logger.info("Retaining existing updated system add-ons.");
+      return;
+    }
+
+    // If this matches the current set in the default location then reset the
+    // updated set.
+    let defaultAddons = addonMap(yield getAddonsInLocation(KEY_APP_SYSTEM_DEFAULTS));
+    if (setMatches(addonList, defaultAddons)) {
+      logger.info("Resetting system add-ons.");
+      systemAddonLocation.resetAddonSet();
+      return;
+    }
+
     // Download all the add-ons
     // Bug 1204158: If we already have some of these locally then just use those
     let downloadAddon = Task.async(function*(item) {
       try {
-        item.path = yield ProductAddonChecker.downloadAddon(item.spec);
+        let sourceAddon = updatedAddons.get(item.spec.id);
+        if (sourceAddon && sourceAddon.version == item.spec.version) {
+          // Copying the file to a temporary location has some benefits. If the
+          // file is locked and cannot be read then we'll fall back to
+          // downloading a fresh copy. It also means we don't have to remember
+          // whether to delete the temporary copy later.
+          try {
+            let path = OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon");
+            let unique = yield OS.File.openUnique(path);
+            unique.file.close();
+            yield OS.File.copy(sourceAddon._sourceBundle.path, unique.path);
+            // Make sure to update file modification times so this is detected
+            // as a new add-on.
+            yield OS.File.setDates(unique.path);
+            item.path = unique.path;
+          }
+          catch (e) {
+            logger.warn(`Failed make temporary copy of ${sourceAddon._sourceBundle.path}.`, e);
+          }
+        }
+        if (!item.path) {
+          item.path = yield ProductAddonChecker.downloadAddon(item.spec);
+        }
         item.addon = yield loadManifestFromFile(nsIFile(item.path), systemAddonLocation);
       }
       catch (e) {
         logger.error(`Failed to download system add-on ${item.spec.id}`, e);
       }
     });
-    yield Promise.all([for (item of addonList) downloadAddon(item)]);
+    yield Promise.all([for (item of addonList.values()) downloadAddon(item)]);
 
     // The download promises all resolve regardless, now check if they all
     // succeeded
     let validateAddon = (item) => {
       if (item.spec.id != item.addon.id) {
         logger.warn(`Downloaded system add-on expected to be ${item.spec.id} but was ${item.addon.id}.`);
         return false;
       }
 
       if (item.spec.version != item.addon.version) {
-        logger.warn(`Expected system add-on ${item.spec.id} to be version ${item.version} but was ${item.addon.version}.`);
+        logger.warn(`Expected system add-on ${item.spec.id} to be version ${item.spec.version} but was ${item.addon.version}.`);
         return false;
       }
 
       if (!systemAddonLocation.isValidAddon(item.addon))
         return false;
 
       return true;
     }
 
     try {
-      if (!addonList.every(item => item.path && item.addon && validateAddon(item))) {
+      if (!Array.from(addonList.values()).every(item => item.path && item.addon && validateAddon(item))) {
         throw new Error("Rejecting updated system add-on set that either could not " +
                         "be downloaded or contained unusable add-ons.");
       }
 
       // Install into the install location
       logger.info("Installing new system add-on set");
-      yield systemAddonLocation.installAddonSet([for (item of addonList) item.addon]);
+      yield systemAddonLocation.installAddonSet([for (item of addonList.values()) item.addon]);
 
       // Bug 1204156: Switch to the new system add-ons without requiring a restart
     }
     finally {
       // Delete the temporary files
       logger.info("Deleting temporary files");
-      for (let item of addonList) {
+      for (let item of addonList.values()) {
         // If this item downloaded delete the temporary file.
         if (item.path) {
           try {
             yield OS.File.remove(item.path);
           }
           catch (e) {
             logger.warn(`Failed to remove temporary file ${item.path}.`, e);
           }
@@ -7409,23 +7472,20 @@ Object.assign(MutableDirectoryInstallLoc
  * @param  aScope
  *         The scope of add-ons installed in this location
  * @param  aResetSet
  *         True to throw away the current add-on set
  */
 function SystemAddonInstallLocation(aName, aDirectory, aScope, aResetSet) {
   this._baseDir = aDirectory;
 
-  if (aResetSet) {
-    this._addonSet = { schema: 1, addons: {} };
-    this._saveAddonSet(this._addonSet);
-  }
-  else {
-    this._addonSet = this._loadAddonSet();
-  }
+  if (aResetSet)
+    this.resetAddonSet();
+
+  this._addonSet = this._loadAddonSet();
 
   this._directory = null;
   if (this._addonSet.directory) {
     this._directory = aDirectory.clone();
     this._directory.append(this._addonSet.directory);
     logger.info("SystemAddonInstallLocation scanning directory " + this._directory.path);
   }
   else {
@@ -7521,16 +7581,23 @@ Object.assign(SystemAddonInstallLocation
       if (!this.isValidAddon(addon))
         return false;
     }
 
     return true;
   },
 
   /**
+   * Resets the add-on set so on the next startup the default set will be used.
+   */
+  resetAddonSet: function() {
+    this._saveAddonSet({ schema: 1, addons: {} });
+  },
+
+  /**
    * Installs a new set of system add-ons into the location and updates the
    * add-on set in prefs. We wait to switch state until a restart.
    */
   installAddonSet: Task.async(function(aAddons) {
     // Make sure the base dir exists
     yield OS.File.makeDir(this._baseDir.path, { ignoreExisting: true });
 
     let newDir = this._baseDir.clone();
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -1121,16 +1121,28 @@ this.XPIDatabase = {
    */
   getAddonInLocation: function XPIDB_getAddonInLocation(aId, aLocation, aCallback) {
     this.asyncLoadDB().then(
         addonDB => getRepositoryAddon(addonDB.get(aLocation + ":" + aId),
                                       makeSafe(aCallback)));
   },
 
   /**
+   * Asynchronously get all the add-ons in a particular install location.
+   *
+   * @param  aLocation
+   *         The name of the install location
+   * @param  aCallback
+   *         A callback to pass the array of DBAddonInternals to
+   */
+  getAddonsInLocation: function XPIDB_getAddonsInLocation(aLocation, aCallback) {
+    this.getAddonList(aAddon => aAddon._installLocation.name == aLocation, aCallback);
+  },
+
+  /**
    * Asynchronously gets the add-on with the specified ID that is visible.
    *
    * @param  aId
    *         The ID of the add-on to retrieve
    * @param  aCallback
    *         A callback to pass the DBAddonInternal to
    */
   getVisibleAddonForID: function XPIDB_getVisibleAddonForID(aId, aCallback) {
@@ -2043,21 +2055,21 @@ this.XPIDatabaseReconcile = {
           // This is an add-on that has changed, either the metadata was reloaded
           // or the version in a different location has become visible
           AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED, id);
 
           let installReason = Services.vc.compare(previousAddon.version, currentAddon.version) < 0 ?
                               BOOTSTRAP_REASONS.ADDON_UPGRADE :
                               BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
 
-          // If the previous add-on was in a different location, bootstrapped
+          // If the previous add-on was in a different path, bootstrapped
           // and still exists then call its uninstall method.
           if (previousAddon.bootstrap && previousAddon._installLocation &&
-              currentAddon._installLocation != previousAddon._installLocation &&
-              previousAddon._sourceBundle.exists()) {
+              previousAddon._sourceBundle.exists() &&
+              currentAddon._sourceBundle.path != previousAddon._sourceBundle.path) {
 
             XPIProvider.callBootstrapMethod(previousAddon, previousAddon._sourceBundle,
                                             "uninstall", installReason,
                                             { newVersion: currentAddon.version });
             XPIProvider.unloadBootstrapScope(previousAddon.id);
           }
 
           // Make sure to flush the cache when an old add-on has gone away
@@ -2101,17 +2113,28 @@ this.XPIDatabaseReconcile = {
 
     // Pass over the set of previously visible add-ons that have now gone away
     // and record the change.
     for (let [id, previousAddon] of previousVisible) {
       if (currentVisible.has(id))
         continue;
 
       // This add-on vanished
+
+      // If the previous add-on was bootstrapped and still exists then call its
+      // uninstall method.
+      if (previousAddon.bootstrap && previousAddon._sourceBundle.exists()) {
+        XPIProvider.callBootstrapMethod(previousAddon, previousAddon._sourceBundle,
+                                        "uninstall", BOOTSTRAP_REASONS.ADDON_UNINSTALL);
+        XPIProvider.unloadBootstrapScope(previousAddon.id);
+      }
       AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_UNINSTALLED, id);
+
+      // Make sure to flush the cache when an old add-on has gone away
+      flushStartupCache();
     }
 
     // Make sure add-ons from hidden locations are marked invisible and inactive
     let locationAddonMap = currentAddons.get(hideLocation);
     if (locationAddonMap) {
       for (let addon of locationAddonMap.values()) {
         addon.visible = false;
         addon.active = false;
--- a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js
+++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_1/bootstrap.js
@@ -1,32 +1,1 @@
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-// Test steps chain from pref observers on *_reason,
-// so always set that last
-function install(data, reason) {
-  Components.utils.import(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.installed_version", VERSION);
-  Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion);
-  Components.utils.unload(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.install_reason", reason);
-}
-
-function startup(data, reason) {
-  Components.utils.reportError("bootstrap startup");
-  Components.utils.import(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.active_version", VERSION);
-  Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion);
-  Components.utils.unload(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.startup_reason", reason);
-}
-
-function shutdown(data, reason) {
-  Services.prefs.setIntPref("bootstraptest.active_version", 0);
-  Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion);
-  Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason);
-}
-
-function uninstall(data, reason) {
-  Services.prefs.setIntPref("bootstraptest.installed_version", 0);
-  Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion);
-  Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason);
-}
+Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this);
--- a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js
+++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_2/bootstrap.js
@@ -1,31 +1,1 @@
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-// Test steps chain from pref observers on *_reason,
-// so always set that last
-function install(data, reason) {
-  Components.utils.import(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.installed_version", VERSION);
-  Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion);
-  Components.utils.unload(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.install_reason", reason);
-}
-
-function startup(data, reason) {
-  Components.utils.import(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.active_version", VERSION);
-  Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion);
-  Components.utils.unload(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.startup_reason", reason);
-}
-
-function shutdown(data, reason) {
-  Services.prefs.setIntPref("bootstraptest.active_version", 0);
-  Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion);
-  Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason);
-}
-
-function uninstall(data, reason) {
-  Services.prefs.setIntPref("bootstraptest.installed_version", 0);
-  Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion);
-  Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason);
-}
+Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this);
--- a/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js
+++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap1_3/bootstrap.js
@@ -1,31 +1,1 @@
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-// Test steps chain from pref observers on *_reason,
-// so always set that last
-function install(data, reason) {
-  Components.utils.import(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.installed_version", VERSION);
-  Services.prefs.setIntPref("bootstraptest.install_oldversion", data.oldVersion);
-  Components.utils.unload(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.install_reason", reason);
-}
-
-function startup(data, reason) {
-  Components.utils.import(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.active_version", VERSION);
-  Services.prefs.setIntPref("bootstraptest.startup_oldversion", data.oldVersion);
-  Components.utils.unload(data.resourceURI.spec + "version.jsm");
-  Services.prefs.setIntPref("bootstraptest.startup_reason", reason);
-}
-
-function shutdown(data, reason) {
-  Services.prefs.setIntPref("bootstraptest.active_version", 0);
-  Services.prefs.setIntPref("bootstraptest.shutdown_newversion", data.newVersion);
-  Services.prefs.setIntPref("bootstraptest.shutdown_reason", reason);
-}
-
-function uninstall(data, reason) {
-  Services.prefs.setIntPref("bootstraptest.installed_version", 0);
-  Services.prefs.setIntPref("bootstraptest.uninstall_newversion", data.newVersion);
-  Services.prefs.setIntPref("bootstraptest.uninstall_reason", reason);
-}
+Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this);
--- a/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js
+++ b/toolkit/mozapps/extensions/test/addons/test_bootstrap2_1/bootstrap.js
@@ -1,17 +1,1 @@
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-function install(data, reason) {
-  Services.prefs.setIntPref("bootstraptest2.installed_version", 1);
-}
-
-function startup(data, reason) {
-  Services.prefs.setIntPref("bootstraptest2.active_version", 1);
-}
-
-function shutdown(data, reason) {
-  Services.prefs.setIntPref("bootstraptest2.active_version", 0);
-}
-
-function uninstall(data, reason) {
-  Services.prefs.setIntPref("bootstraptest2.installed_version", 0);
-}
+Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this);
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/BootstrapMonitor.jsm
@@ -0,0 +1,28 @@
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+this.EXPORTED_SYMBOLS = [ "monitor" ];
+
+function notify(event, originalMethod, data, reason) {
+  let info = {
+    event,
+    data: Object.assign({}, data, {
+      installPath: data.installPath.path,
+      resourceURI: data.resourceURI.spec,
+    }),
+    reason
+  };
+
+  Services.obs.notifyObservers(null, "bootstrapmonitor-event", JSON.stringify(info));
+
+  // If the bootstrap scope already declares a method call it
+  if (originalMethod)
+    originalMethod(data, reason);
+}
+
+// Allows a simple one-line bootstrap script:
+// Components.utils.import("resource://xpcshelldata/bootstrapmonitor.jsm").monitor(this);
+this.monitor = function(scope) {
+  for (let event of ["install", "startup", "shutdown", "uninstall"]) {
+    scope[event] = notify.bind(null, event, scope[event]);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/system_addons/bootstrap.js
@@ -0,0 +1,1 @@
+Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this);
index d04bca194bd05f9b4802bdb5eae81ab58de2dd19..31724aec5ad71776db9f5539fcdb0665bda96d55
GIT binary patch
literal 4674
zc$|$`XHXML*ABge5|A!Zf`CW|k=_Z#fFNCwCLKcyEi~z!D2Cp<NK-n3G*JQs2_2*h
zic$q32$%>j-kERi_d55^yt}hM&d%<0&Y82%&OFBmN<zv6001Zf;ucam+1CArcp3n}
z76btN-Zg-js*CE~))x2h3U-6R?8V@|_DdE)a#JC!vNb!HZZ8Jpsw|r${Sc}EEK4Ja
zmU2K_g5Ba$F~%BBv~!JD@0uj&wi@5i)n#aO6k+I^>S_zw!w=wR@tvcGXUBK~_8{N4
z`)erH7jV7uQvRl0vk#8rasorX!MYN;kv#GZ4=9PuF6u342UO3KLS%PZL5g|S7(itD
zK{|rEJ&Tqoy4Ox_5UwOY479_W0N*t_Xu086NgvS1`bO@0-06$>C}#I%O-e9kEi_DW
zjhqyv8X3d;i4u_xj#$iS^d2JcD#JX5JR#tGI=>Y&P+PzKcR3~V#hGZP7~f;H5<tH-
z31wF8dC{%Gh@xA%fhojaaBjpZYH#)`Wyy%Cl8uSd&uE@fy%WB&KWPR)edLZfsXCvu
z*`pT@jN<0O48&=W#2am0lerOLuGmgu7FayL2P)Poi2+0wz1hQO<QAzC?L`Vw5V|Nk
z0mou?pC3pIlCBN0aoP~%uzYO&4JKXO{gK>f3<KQeA+LJL<L{s%PM+LvCnLs^rYaMR
zf*qd#4pvYk&+UeKx&f4EKuMH5Tfmugbd?=Q(|;>j{a0s{G*GmvMp?kTOSI$r<rmex
zzG5=C*t~*j+Mi%CO{@~=JPghIh(Gb=!35-4UPrEBre_bKj*7xuuhsq;pf<67rCDaP
zNOG4e*vx}17Kz*TtH7jRqfng97{8Q0u5q>xNFAg7I$WDmUlT8u7gH{KbxvrtRHJNd
zt}Vvm8ezl_9f6XO`}VDJ!~#4t`xa=S`=M3NVsZ;9?tci~dge8j!R&SC4BLBu-+RKp
z)Jh=DXObt4^TYLmMuT~tN^{jINP4(S$j+5nEQ`@rM^0DH%qj#YaD3!uy0B}u<uJ2f
zI7%n$f{B#k7}T}%v$;Df-B2<aTA`v+t5;AiqJM8@a8uD`CZ3*4B3QPlb0f8|`PpIT
z>BJWP=O{PuGFR_RhzgFz;CdNn4b#^STVxDZGQ!}zuW3kSMMHFLxSZi+S^R}n`SP3k
zGUF&08`%BZA7kVy!jV&XaUD#U7OMMB$1Sd~AD=nt13l)VZ_62F3UqAjsuSLascovk
z))GeDC?XYav@|W@zDf~eA(d~d-CGqA&3G!rq~ffq{S#F)!@;m)@32LhooF8ugQ~En
zsjfT{S3i)#b1&^@wYYLVh<56rU{xk-ovL8e|43ab(#p-H=!JJxR@>o5#6?$q*|gyh
zDCBzz>sc0!3-K@G6kD`&L`~=U>cFCSdC139otYXJ*h0v=?T1n98=KDL!&V}9E2Z2=
zPqHSp+u)D&GFAdM+H=r@PTb%8909UoQX$o69hr$AQ(=Mmp73X+dx-4q*mmb5M%Ejy
zohjHFCCWm*#gvYD80VhP06JD#8=2T+A8Pu`*(gK0phou|-t6$;6vM?O&?&v=hqQo4
z)_Whea0r$~z_SCo69!Ptbl8Skae2Y!*g3~IZ6!I0(2Bcps=@&FZDQ()J;c55VTe;A
zm*ccF3+_t@soQ=Uf^EbUG-WqxKiyDeKDq4T`Ge7+Lm{?%jG1p!hjnUxvCltKQyo!q
z_68^U&O1zMO}FUIE4ugN4Ucuy&vv^T#~Ed=_B=?WGPD_G$RR(!6yGHxxYklz%zC8M
zuZ8Gp4bEE`zg26iGjpd_zCkdXC7t_7MbN-HueQ21?B?XvvJ8zc@}Y;xSUV)klq4L?
zdO1zU3b9MjV3FMs7<=v3nayt~%wQo1{1N`#Pv2V2N4qeaU3}uHO8l`PUF{X$R`l!Q
zY@lK*T&5_aoSm4wJB_;-xpJ#Z<pXKaGmqs!(EzHreGX*pj?0=i(tS5>Q=e0hg|D&a
zaq(1>U8N_)Y&^wKK@7=Z`^tE$vNyC58ek<F&3^GeA7rg}Z+%OMn<a&Iw`rMOdT&?i
zm(g;p|MJ@a&rgW{H4;hp0RE@#i7p(x`Lg6jt9bzCpJ#$OnsV&D;k%48R|M$KUoy6{
z@f@TL2I-L!2gP?h4d?Ys;a&|SHrK8a5-Q6uO%I^7bYrb1(4Bj+jD$bf&lGdI*RtR3
z<6MQ#BmQ<e*(w=DGz5nV`5M-<qgSy0%Aa>#^>O!2gc#XFEiC+J7dk&omr5eGGJ}GE
zr6FnujN9IQ)sMbR$-XzJGnIfg=cc$p`J-n9L@517HR&3xKip28k9q9fW$%G$vC0Jb
zf0D~k1cmaeC{7{tK37HLgvIIN>vSM0F$aeC)_AXcw-r<ApuMgrXshB8LK8x}_eg1R
zyW9TL4VF?A^U1Bv>Ice!?%7QZ5qm!bqYTa(Q%?BF+AX_LB;p%2dphE^EswJiogS#k
zhl`KglpMouFZVcbjf}+_86MnVT%jKq`YcD+o@D(zmAZ~tUP?RG^R5D^9<JbA?G9(~
zorR#cB@5BUPc8>H@pFuWm3qCHhn>V(j#_M97b#`PAC5sh7;@fSX{Csy%Wx=9dsTh_
zHLEdq(DSm<!5;_Rm+o5M1gl;ye8(j)r>GEiyb((MaPc`>+w0^=*I*O{AHYxuBhf-h
zmz~YEq+31;=Du*zSt48T7fY@b0%0!|+&86eCOqN(Rre~#>B%@UlIW(-uVlj!-eY~I
z7t@ZmbUz&zw1MdYzBt1GEmx#%Qd3n`i44nhYk(^$Trye&oYo3wP$!~8PC&%v3#kLU
zl=6NoLkM<mN$!ii1zuAowp`pptEP0;X9Q~}kozkEm8<O(8CL@wTSq9V;(B+d;Z?<&
z0OlBS%fMXY7$7wX56@U&L>Q~jPN;f`q5};DBCr7`=1i8o8UpeL(V!_K32ZV90oTOS
z^Fn806~n>jTX_7V{XQVLIxh4<1E9j&LX51!kt99kaPgQME0+pIf9ItThE7yy0hiWI
z9>TAscP5-m@*Ao1sIg-|b9m4s+00U?mq>Nuy9OP@X(9dLMcR<Slv2eZi#IE8_qgBv
zaQKx$r$QGlO<=EJgumchEm^X}B;?e-T`;G@A2N4xCa!cX&EnsMPL;z1$a%CovaRO(
zd`qafkEp-CSvl?SE2H_=V|pEQk45`oc8nU$FlGu0`?*I8UO*#olz3Wxg5N-;fZX()
zKbgXj@M+=u!IiiJRaDB{YxV6Zjm3JU!{TR5!4;jt-=R3!l_n$wM5|~1UNb3GRnJ-s
zNW)P?s!ofVe8oyc-dQM^l>)hB<x@SGFwEw<`o@YkT2LATUu~xhgt{-Aobhhu=zb~d
z&deLv2%-w9`ce>cI-rbUe;Wh2m-#;JGiIDXym{i4SDWu@u+3+N7Q@Z>K4IWql@;JY
zC63Eak9%kz9gl5>jv=8~u0npzR(O+1MeV-mO{|WE=Xe**dOV{ujU^wedVfnxaZ;W?
zMe{&ROr-z^E2-+&B3H#}|AwS>dBrEVmdn*zVX}hVVtFAnHs9@&LV%i<Sw9|K(Znu_
zbru!{siJj)N2Q7o(fi2hPk{%ApJV%eN&&|2l)WzNkax<uw3I12FmG_Au#no)mi+F8
zl)Q@T#73~ivkr8+G!vIcDp`(7bGJMLaC@94X)xWLYHF@VkpL^Wnbl&b66(a^CO$tF
zQ0?DdCQ2$8(Pp)W<fLN4pa7*h+kPL(j689}`||^Xb5?$=M*bsLMot`)sYAd7+9YcE
z2H)Wi-#C>46?^ASIfS6}Uma_WhD3xOPIaSj<t@OfEhAgfCvH}Ho+BtVWY=4#VQE6i
z$Kj^7)#ht1bA`<ydOhPU?i%1NGHE*%DA(6iY38c}ZRp8HqcWK#*8=*{qm#Gu1Jl?d
zd7<>Tq09C%C_@`W4D6@l%ISBR^4ENhtsy`cfrf-!KJ<KQ>#l}H^|QwHnwjC2fvz48
zIn1c74=C;B%VAm?NR{dhoN$%V!%*i(2atJ_=+i0}v}8S{@!bASLYR~J;$3g1f}n-1
zefH`4!c><AOd4vsF4KkL6y*}?r!e=ySC`}sNyhVKi}JX+y)SbdUm)6PuL9DBPUriJ
zY3MN{b!J$NN)%3q(`#=s?EMNec&snbDmY|wzA=4D+frMB)w|JTLnYCk&a~J{IL?i;
zimwOugt-8o?Bbhsc)!v`VDSD_$AHbN#eCeiPn!wA<uJdQ>7B9~o})Xb(+^PTkyXk|
z<yp?)?5z$%A0oFLHjU291+}Ie@IZ7sxJnr(yLx6`B?NnFdq39dgm*ptfwPU|HrtDw
ztljUvC3XG^<6m+uap{J|X$9E4Wb5MF@n;-M$!m}KoS_L#niDVw7OmWL7suR4cL+aN
z&pv#(B{~w<&JbGr^cD2<p7?^m$d8ma6I(5{mSv^7XKtn_auxi}N1IjtUnkEM16Z3K
z={%ZmHP84xhuJo)$8~S?#Ui3_);njZ+G-cAg?b)P)kum9U;Q8suXV^bTb^z=SJQ>i
z<rGx*aJ_7Ao2=rK`(hq<)&ns5ODqvzh$X%NaUHd9XVZ5sM3Uvjq5-f09(Z~A`TD`_
zy~W&p%}mJvB*v%{Gk*jSKt%e32mts?X7LY5(navl0D6~PB!=wf{3qvhKrjtjqlwIS
zUmvb{1bXi-*5~v|T&Koa!vdl(nv5@am6YAk#+kzRXcU{O^mYVgrC46ID9|6Rz;dR%
zCV_v46z>SsNe}ZFmALTbPYeJ6FG6zj^!2lc!NlN>&VNNzcN_C(M6sw5&pruI%-$nv
z*?eSLvoa{w=qjcz%X}-0mt5pjurW&jxA~BUiYGPK%DHE*Aki4BP`B~K+vc9ML8DLZ
z`|BE*(SB51;`d3%_zz6^Z61oAMFTS)K{s>s5xIv-E-#iP!X+rLNIyyk1&5Y4fPSKD
zc3+xOuSF>t*uEOmIle~q^_nPa-^&7+#Jl49#*lo05SOH;np8C3wf-Ay?F?Me+lVTr
zj#U43dahXPvV=b2r~*|KL8KyEr!g+Ky+UE<BpU2DX1ehMEXA6bUoVK>n7A8_TbjaY
z@`wN;r2_6cs3mU+qe~AvoJ-7DvigbG<w)C@<-9ofXCpLG3-l8YHCJBT#TOWD74>y#
zLJyaYANOW>12ty1UkdJnaqTD8^|~t8G`?-1;?JwW;YR-@n7c~jmC+X#6Vac7+1}I5
z*~!;W%)=QuV&D}e0YHBbQHAVjr+c8)`-paLa%$S>KVPV$tzZ&z@}M0zR7K8-y+(wf
zz7`P}Cz5m76-9GyY8<Kf703guz&Z2~FOf|J9Sa$?DBGs`Pq%;zx}V;XihdNMw)SS9
zT-bXXrqJ1C(h;tlya-Jmnl;H=SEB4~A=Hea@u|(#L2Rs=*ESEcA4zvzX8-i&<?W0{
zw7ZmCU3=b3ZVQ7`&~RT(CZcr+C4d=MJxhR|YU~#?1}2UNw|cup8y>a<o^<Z3{&(J+
zNy?7y7go^4y7W(t0$*n!R(}*KA|!finieX09s7Q?$yj1a`s0DW<h1{gzM-ht_>sZ;
zVSN&*TBgQZCe^6JD>Z#dmrRnSi2J%Q8k*oq50CaJWlmbj3|5^JJh@h;d9XXHg0r(C
zxg~ilS)S=Sley{XJlu!qf|f+YOeFu_#rVGwK?L}hp2lwkE|Pzz_V4lga(SdEE#QA5
z`u|7#CuaVQ*n5HaKk)R=B>#MQe<vwP|IhF6PlP{f_&0(O=pQR;1SKQ?eSqv@x?Z?_
I2l{RO2QL0kr2qf`
index d6a8e727a1b8b54188b6407bfd7b8643ecb085c1..e7e50c8ea878f93c70bcc209fd28acacdf5afc9b
GIT binary patch
literal 4808
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
M`tw5~hF{kI07wpD?EnA(
index b95192c26fabe6adb4a541eb4731caef4d414fad..b32544487303ca14a653cc5541c1700d8339bbc8
GIT binary patch
literal 4675
zc$|$`cQhPa(_dYJ5S?gIq6NF6w<tmMRiXs3O7u>2i`835^pYT~5-k#SSMS0qVbw%k
zC8ET}A_T8I=X~e+-kj$-=bd}*A9K&WznQr+^T%(%S_Fi&004j#AZjA2j`AEOIU@%E
ztf&Bh-={jNMoK~&x@sbB9zjm7uGYfdKGt8d0;Q(T76wo@J2Cw)L#yDRkb&GJ?T4IN
z6r9|ppi<!b{bAD&X|_Y7b^GR==8fE(bY=!dnT{{yKc>iR`i=%(1Y88wY$BkSp-W4_
zEeZ?gh}v6)?{j(>pGP~zy1ftI>XbHW^Z{h(+#<)f&IS-O3MJ6tZ@}Sr*-+^S@A44>
zK*rH+#po%FVkZZXkytca!#N#bdV$3U?UE4Tem%qo#dK3aY~^Cum*uIFNTb;L@?1SU
zlBWu#WcBl_Er)2;lgPsr-ihAkzNmlw>7F99jA0Gp<_(tA0MVfrI}ept<45=G@NY)q
z+1<eBh%43&lP<D^$`oCj{xoe;YrtYz!V0xdE0szEV#9Z=wCn(0@yK7=>#$O(mO|+1
zWzxVolWL(90QUJVBatGL4@+@LI37lLSF10y;xLvFrVI=LjE(iNpEih-@Fs9gOrX~b
zVmpaESx99F6WRJu6X@KXII-I_^1$!slV@I1?+ouxA2`s;<5ziI=fdX*+sTL==o{|K
z*b47zp|-TRtdkDEPXF_aBHYo5!w8sfe|euP`#SN2HdE~AP#27*xTp|UoXl@T?IqX5
zm~wlqfi;K(-v=A!)2n;m1t%3|r4k{)lF8db<#eF&#Fj<pVlWSs)I4&=uaxZ`1%=9j
zDvKe(iA~d5u8Mug0^|5=L^6_?n{2me>khEVCv#AJlH{BWSxO&bziq=9_~11$g|<?C
zK^TQ!**>{M{FzI23=N!ll-cEJW5c_%km-~;h+`PhXgs#fM)?s`jgi(<+S^u%%=gyY
zcJcPn#M}u&tC~DwGiMsi*lTG!JGWnlv~pj35Zf!9_ndq`4dUn|c6yk_`zrZOEmPxF
zaNRc#_Q390Ys+s^9j%iO%3?QYVY*%$IZLT4%?iBrT{tmXO`BC@Ha2vFRoU+mJ*s!;
z{9%>OlbxRaxqD*Odz&48<#ALQ`x)KUYiVGbHSS3L+ds5N-m?#J@<I$@7Z20R96D!u
zJY-oy25i1{)T+um!7s6*KZJuovXZZGN<=be*!s49?c1!Dcf7rqz4fRk?sE<KB6dfR
z8>0sy`DxRVD?7R^1BX3~URFVif=?gOX9*nAld|7y&N@$j?pMt{f40T9)*8JtsrM~?
z4l7bdZ<T~>)8M){<q}b68;7g0+r6M_Z%^!z0H`M2>~-{OHq(BGLKD3hN5Cd-|B!}j
zEIk=M$<1eaf#+T3)(fO>e{GKi^^QAHHW0*wJ1Snj)gSEYQ6yPuPzuQ43^X79Vj+k&
z`X1sX*;cRk=JQ=$%pz}~&Te8LTcehcri_UR7g_z*9&Ytxb)b<lZTsB}m5xaF6Jh^0
zqrJA#tl?4qoZ5WIDQT%xzrETBlFhkcz4)MfdFU}UOxqCDxD#Sg0C`GR<~WYrkxEI{
zH#QDsw*9_CKb4PrXcNzg!dC!)2O1A}+8nc`aI{ozkGi)Ol12tgJ7rXze{vYDglqQj
z1_o8tyN(CtDb7Idw2zNchua?URt6vU#jz$#3Z7o*x{1d*;a|uhxhXW*+2rEn$Ks96
zo31f@9?=Y2$Wc7qvnrgYTciP+-5iqoimFI050{nCm*ZR=t!<?4STkNZYY7qwlz3#(
zmQ2b}KFHgvMf*6aTfWuVPyZyT>4dvtAGf(l;Q9)PAwvv&HfbQ4X){9WV9idOXb~Mw
zsg^&ygirKS=QB2sBWbxjTkGmoJl&e$Q}x8t-7TY18%owS%ag|-p03FW^GWCs-guOj
zw@t>8;h4W9o8_?Rua}g2eWB~QPx(1{5SvX}^W);OiQmxRgeGMPGv=QgFWLL<HE``2
zP%u2J5Ms@<8Is<$P_JxjdqiS=I8fiDHc5N`;pYvd_Z|rWWN*<tx%bBCv9@`;c=oy#
z)?=CDe*J!%*yD;6X;}5D>-)LJsPsr@o1@&<`!wv01mGeMXg5o@8o|Yxp!Fhe%hDzP
zU^F12fMe6U6l`%kk$iD$yqc9S3}AYrm|L)nLr?@s37I3{zl{A=>m+u0t4o#y)4%_n
zJ=dDntqrBZXWAM21Hr9P!!6?fLbSpEoaAxy>Eksw$#pHl{wLz-EUQVuwl_=Lpn@6`
zbUZT)UA)cfqy_L;?ova0vJT$8Xnu_?-|0^ff5$H%@dp}H$Ezf?6Rcabt3*EP?Gta`
z6;gZ_4V&V+BQanetXi0*J|ktgtQ2HE^h^`YN&j_@;cVUBoUQzm)mvx0u;;$RFCeQ9
zCS`L7McAMNQa(*5-D%_DK}!|N_A>N^cM;?fJ`;}+Q<tS5W@x@Y@9Q{fui`^*7VFFA
z>3yzwn$2@~{;7h%IC<f7-dX3{eH^@rD|b>Kd@6I+-w#S<vWz>HBrx<}S?Tmw5~b1G
zJ1Wb$K^>VpL?hCEjo25P!X}ZV$Ve9LDp{%U?A2J%k`4Tj=~d^7N{Yev%o1}SwK#es
zzG;sKQXK(o8)Dk6@HBT9o(4=-=Qfw9SQ{9+VJqr`IgGDWfp!p8&SpN!K}%FMIr9#O
zpv7B@Dlrpq?>_(B&a-7ZG0{i4)B!!8HQPzQ*?ITBIaHu&GoIh#BQrR+uVpJyQ(rZ<
z)vZ6{Y<Kvq^O^4A(9H_qcSiuLY`YfVGW2DyoyMJ1Efwn7-4v3JOmwOY7$R-W3WM}Y
z;*#mGrmF94Fpew2Xsp)RR|^U0eKch-))tJ?!9<bD-%;8+G)SRmCXZkeTsKtu2%swg
z0Qc`};t{6PhleW$1HMJT_QRBl&YqGJG~cK{iLfVTv_9lxjLXctf&WwA8NUiF%okf(
zOQ+uDs<fIXLt^Sx9{%P|6PS?7C<MX~O}q|J%86ikCbX|(Ic(1&pMuVO8h4$Zro@2R
zClUswJPA|7rz6D2K*&wH>y@m{w>kKXU|J)iX!O^pq>;-iH6~aCdDq;N`S`8xBJa)}
z!{}^xp(1zgLoo8^XRD8sp782@WfKpb6LMuSMG>VeA=PG?=@B*DLDqh>Z{YT?YCd-C
zuu8@XUXU)Xv4P1Z%5S|8S~Xuck@A|Rd1Gc4*t*j_nG5nAbJ1l{)i#_}a<hkK?n+fM
z>vaSP`OgGb$Zf4iyzo4#T{|~5%8f8lu_Y2Kb>_IxnyqQ`_y)r3a%+W_$u1o@xKbsQ
zML{!*6enhHozs1A&2fS6)w)ch@^l~AKlk&NVSXdOXm7mHgViS_*xql8<t=~GmE^EP
z;n#fvO|dQ8#u+L!-p?G)F9~5A%iPj@`%0LPI_1k3YkNbmbQt2vf^+pk2dg-VR$g>m
zZ|wTwwQm#7HTr|gG0<d$cD+zur<O3v1lZGF_pYI@q;}3pQ>V9W26E$qT%awO!6+2@
zHE!EQ;o|4qv|cOwb>Sn^8=tEjf_gvlLj`pXVi3vF$DPs4%t%vqrXw4@4Z5S<nXTi%
zz79G&bhH&inbo@5;+oz9kpJ$9Wx|+)6b)7Wv_OIJaCOr2CNuGXb48MwrO5U?6VCKO
z$n?0E&GIAo>K&E6D64EW2|J}g7Y7O0QC&i?Vy0u+f`(tiP^|gd@LX)kuW5$ye%Nu)
zU8Kobklc{mb2W37E<^W_xo*W--$@PAo9Qanz5DL6LHwbp>%L`mU>*sLj`<Vf9io`)
zEzS3bmycuFI2=zp;5om<)6a8Pz3)c!bWke+!`Qb07gqF-$$zoar2OJhJj|j?m~)6N
zA)+~wDTaGh*IeeU#b*}jEw1=pq7j8gz~sj;DUj${jI0d;C$^X-lJfKv=X2`=Uu~7t
zbGNa84N@DY7>(PUK#%s_C{{!5wvzGlVu~65Lxo70r^VwHNev%}&7h11E!QF39)<fM
z^zWZk9yzf*7G7oL>X=+XrYZ0X<+&?~s>K}-G=R0%z=NtwJki-xID>&whQ}GF6mV2E
zk%xdL635_)X3&oXVi(q(Emr!~-={|xXb>*6%D>E}(47()Km4fKGM<5jBQWq*J^>G|
zqGyUR!A7g4_R;UmNG}~ojy8Y1(czX%&$X)a`=FQAyt!IYnXxmc;s5zqVGq9^mQWy2
z>~VBY&M7#0m#SGku)>4T+2^}uoxHy)M>m~_r2T`8gkN|3abAL!tre0*NV9V5@V5+>
zCZQ>P_%ytAbIV}?NDvZ}ryMedrTP|57qR6YQrGm}k6!<0e11sFhWwIt-DnG6Eue@l
zAf+Y|7y5z4$@y(O3RuKB?Y`|-u(_x$b?ab?RCm%)?DAvHQy{7jbc1W<u|M;4>4<H$
zyi##=$cH&S_XwC-w;^WUQJ0YTb^06&$Zt<TT20-)MGSqyvr~Dl$#1}36C=(yIl}~h
zU@um6f5?@3THO`lSsKrdvb=TJ*H0XpDYNbGUbh0CX~<36&sx-J2NyIrSi74;AIfCd
zIUd`vxkP>(FF)OxeLX8nXd#Hev4j62OZZo0iOWw!U2*RMt$#(5Os_UMfDvHh;o<A!
z>uv2R?CkT%hzLMn@bcu*vj8#x9^nxl0Pq*h;u!$l2<IRNbbfIF4ngLgP0p!PxhhkD
zKV|lAx~#hSd+vUIm(vXtxPEBq>IeI%LS1uPPTr~CAXD%$x$K7ujU8S|QTpZv8A{xe
zYtEF%B-!6CCD@Uvhh(>kh+f%xh7SOcUAg4s?&E9i>MHDQXaAQ+^|~Mb^eFlz$~_WD
z6}1n&o|T^*(HP62%pAWlttE)tBjl~au-l15AAbFotw_yd&;mL`?UBDRJ<?odcYg&8
zx(WB97Sf7J7;{cOe}Gi=1vq+ZB5M+no3pd>I-5VFbwqQY_D;*LK4&)7tIty<EqDzX
zX+aza{17a$vsTLF7D=y63#R|+!^lAAZ!XCE9Rys+rl;3;c?R`cSC)ksQ1{i(dXX$X
zLl}8xBqDs(Ni5(V%e;H121+Cl*qF}nUEOZikb>}J&~oSdQo;pnrv<kdL@#Q&L7e$J
zvgUw<#25t0P90`O(Ta2^-)(*CvT6>uHe)P|C$K+eG1lSg%j`<W97QJ0Pc?Zo?sdX{
zm3`j=D~A;X-?&{9WuA&FzK{uLupUv}hY?|wZu+V-OkJAroDzWli!u+(lLhu&X|#BM
zQf6y+C;O*9zQS(y$tdL29|NLSzUZwmkY;hf6m2-N`Sda6(S(T;;dnHW6}wM9m3h2*
zYl-lc{qz$~Iho_Ho%d)ceZ%{Cp^G#if2)^s(7~;oD$`juJm7MWdP1uY1^h~CgXys;
zXkJz@UJ4_mv|$iNJA9>;`MzWXJ<^rfU1OB{xU?PliY&@QBe=n=v0W?>_x{EHE7Sfv
z7ZWc0$r1^|)8&^a|3yE(nE`&vh49%}Ub&ru3HFPObVIcv&bnJv>GSR8l$ec@l?KEQ
ztN#vrZFc6u`AQ4C+BE+(De$o;8`U1uy2~%5iKfsJ5*QsB`(OZ^y0?sd20}j@($*6a
zp1|ph3~LjJR?*fAio!mnB^y|ZV#!#@KGjcJ)LZ@{aC2*c$+J*^GI(?714>RZ2seVV
zR2dnb#$f1>Qqpv^xes#b7redj0AMXVd|HBkA7lKVgyRAJWvKBRfsNqbd;7Qieq0hE
zL;?7pI{p76{!?rIjo5jG_&+r2pF#dvcz*|ZkMf_(@K1z4bNDxc0M$Qc6s$!={QCmY
N)pEQt+eh_V`ww?fZ2SNK
index a4d7f4d18e71702b384c759874919c7560b6bd15..af5e5cb21f7a67065082536bcc3700d9fef65074
GIT binary patch
literal 4669
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
DwT@o}
index 7af871d36dec992e405752bc9db49e6dae4ea085..aefc9a96aa60808b377f0069a2236bef055ddbcf
GIT binary patch
literal 4672
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
G(SHE9^=7O9
index 5c8570dcc4086cb1a3e9270a2f8ef64e28899c02..49369ad2f51c7ea33688d53c8e97f7d642625a2d
GIT binary patch
literal 4672
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
D2DMvl
index 60bcde626ffd9307c052b3cecc45812f716c5c0d..d43bde916d9f09f3bb9598ab7d19fc8d9c4bf3c0
GIT binary patch
literal 4671
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
E15(UTZU6uP
index 5b50b8556dcf426f67b134cfc084672e08bb5b53..873e34c95de694f8be9445477f4cad72265a382b
GIT binary patch
literal 4674
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
K&-Rf1j{XC+W>{tb
index 91a7d9ffc1e848636ef732a8864a6d4cb0ee8869..3a3c4f3e08ece5390970625041e005e0dfcd1d84
GIT binary patch
literal 4670
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
F{RjTOI>i70
index a11a8eb494f1cb2e25f1016a71b43bc7f9c936cd..060b4e8400f1099bb0be6123157028da96c0004c
GIT binary patch
literal 4667
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
DP)BVh
index f4e07bf300d17fb2306c1dc189b5fafea56a952a..ec2d39b623bfa29183f32c3663a72de08cf165a8
GIT binary patch
literal 4671
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
GqyGT^PE>;c
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -56,16 +56,133 @@ var gInternalManager = null;
 var gAppInfo = null;
 var gAddonsList;
 
 var gPort = null;
 var gUrlToFileMap = {};
 
 var TEST_UNPACKED = false;
 
+// Map resource://xpcshell-data/ to the data directory
+let resHandler = Services.io.getProtocolHandler("resource")
+                         .QueryInterface(AM_Ci.nsISubstitutingProtocolHandler);
+// Allow non-existent files because of bug 1207735
+let dataURI = NetUtil.newURI(do_get_file("data", true));
+resHandler.setSubstitution("xpcshell-data", dataURI);
+
+// Listens to messages from bootstrap.js telling us what add-ons were started
+// and stopped etc. and performs some sanity checks that only installed add-ons
+// are started etc.
+this.BootstrapMonitor = {
+  // Contain the current state of add-ons in the system
+  installed: new Map(),
+  started: new Map(),
+
+  // Contain the last state of shutdown and uninstall calls for an add-on
+  stopped: new Map(),
+  uninstalled: new Map(),
+
+  startupPromises: [],
+  installPromises: [],
+
+  init() {
+    Services.obs.addObserver(this, "bootstrapmonitor-event", false);
+  },
+
+  clear(id) {
+    this.installed.delete(id);
+    this.started.delete(id);
+    this.stopped.delete(id);
+    this.uninstalled.delete(id);
+  },
+
+  promiseAddonStartup(id) {
+    return new Promise(resolve => {
+      this.startupPromises.push(resolve);
+    });
+  },
+
+  promiseAddonInstall(id) {
+    return new Promise(resolve => {
+      this.installPromises.push(resolve);
+    });
+  },
+
+  checkMatches(cached, current) {
+    do_check_neq(cached, undefined);
+    do_check_eq(current.data.version, cached.data.version);
+    do_check_eq(current.data.installPath, cached.data.installPath);
+    do_check_eq(current.data.resourceURI, cached.data.resourceURI);
+  },
+
+  checkAddonStarted(id, version = undefined) {
+    let started = this.started.get(id);
+    do_check_neq(started, undefined);
+    if (version != undefined)
+      do_check_eq(started.data.version, version);
+  },
+
+  checkAddonNotStarted(id) {
+    do_check_false(this.started.has(id));
+  },
+
+  checkAddonInstalled(id, version = undefined) {
+    let installed = this.installed.get(id);
+    do_check_neq(installed, undefined);
+    if (version != undefined)
+      do_check_eq(installed.data.version, version);
+  },
+
+  checkAddonNotInstalled(id) {
+    do_check_false(this.installed.has(id));
+  },
+
+  observe(subject, topic, data) {
+    let info = JSON.parse(data);
+    let id = info.data.id;
+
+    // If this is the install event the add-ons shouldn't already be installed
+    if (info.event == "install") {
+      this.checkAddonNotInstalled(id);
+
+      this.installed.set(id, info);
+
+      for (let resolve of this.installPromises)
+        resolve();
+      this.installPromises = [];
+    }
+    else {
+      this.checkMatches(this.installed.get(id), info);
+    }
+
+    // If this is the shutdown event than the add-on should already be started
+    if (info.event == "shutdown") {
+      this.checkMatches(this.started.get(id), info);
+
+      this.started.delete(id);
+      this.stopped.set(id, info);
+    }
+    else {
+      this.checkAddonNotStarted(id);
+    }
+
+    if (info.event == "uninstall") {
+      this.installed.delete(id);
+      this.uninstalled.set(id, info)
+    }
+    else if (info.event == "startup") {
+      this.started.set(id, info);
+
+      for (let resolve of this.startupPromises)
+        resolve();
+      this.startupPromises = [];
+    }
+  }
+}
+
 function isNightlyChannel() {
   var channel = "default";
   try {
     channel = Services.prefs.getCharPref("app.update.channel");
   }
   catch (e) { }
 
   return channel != "aurora" && channel != "beta" && channel != "release" && channel != "esr";
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
@@ -6,128 +6,83 @@ const APP_STARTUP                     = 
 const APP_SHUTDOWN                    = 2;
 const ADDON_ENABLE                    = 3;
 const ADDON_DISABLE                   = 4;
 const ADDON_INSTALL                   = 5;
 const ADDON_UNINSTALL                 = 6;
 const ADDON_UPGRADE                   = 7;
 const ADDON_DOWNGRADE                 = 8;
 
+const ID1 = "bootstrap1@tests.mozilla.org";
+const ID2 = "bootstrap2@tests.mozilla.org";
+
 // This verifies that bootstrappable add-ons can be used without restarts.
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/Promise.jsm");
 
 // Enable loading extensions from the user scopes
 Services.prefs.setIntPref("extensions.enabledScopes",
                           AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER);
 
+BootstrapMonitor.init();
+
 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
 const profileDir = gProfD.clone();
 profileDir.append("extensions");
 const userExtDir = gProfD.clone();
 userExtDir.append("extensions2");
 userExtDir.append(gAppInfo.ID);
 registerDirectory("XREUSysExt", userExtDir.parent);
 
 Components.utils.import("resource://testing-common/httpd.js");
 var testserver = new HttpServer();
-testserver.start(-1);
+testserver.start(undefined);
 gPort = testserver.identity.primaryPort;
 
 testserver.registerDirectory("/addons/", do_get_file("addons"));
 
-function resetPrefs() {
-  Services.prefs.setIntPref("bootstraptest.active_version", -1);
-  Services.prefs.setIntPref("bootstraptest.installed_version", -1);
-  Services.prefs.setIntPref("bootstraptest2.active_version", -1);
-  Services.prefs.setIntPref("bootstraptest2.installed_version", -1);
-  Services.prefs.setIntPref("bootstraptest.startup_reason", -1);
-  Services.prefs.setIntPref("bootstraptest.shutdown_reason", -1);
-  Services.prefs.setIntPref("bootstraptest.install_reason", -1);
-  Services.prefs.setIntPref("bootstraptest.uninstall_reason", -1);
-  Services.prefs.setIntPref("bootstraptest.startup_oldversion", -1);
-  Services.prefs.setIntPref("bootstraptest.shutdown_newversion", -1);
-  Services.prefs.setIntPref("bootstraptest.install_oldversion", -1);
-  Services.prefs.setIntPref("bootstraptest.uninstall_newversion", -1);
-}
-
-function waitForPref(aPref, aCallback) {
-  function prefChanged() {
-    Services.prefs.removeObserver(aPref, prefChanged);
-    // Always let whoever set the preference keep running
-    do_execute_soon(aCallback);
-  }
-  Services.prefs.addObserver(aPref, prefChanged, false);
-}
-
-function promisePref(aPref) {
-  let deferred = Promise.defer();
-
-  waitForPref(aPref, deferred.resolve.bind(deferred));
-
-  return deferred.promise;
-}
-
-function promiseInstall(aFiles) {
-  let deferred = Promise.defer();
-
-  installAllFiles(aFiles, function() {
-    deferred.resolve();
-  });
-
-  return deferred.promise;
-}
-
-function getActiveVersion() {
-  return Services.prefs.getIntPref("bootstraptest.active_version");
-}
-
-function getInstalledVersion() {
-  return Services.prefs.getIntPref("bootstraptest.installed_version");
-}
-
-function getActiveVersion2() {
-  return Services.prefs.getIntPref("bootstraptest2.active_version");
-}
-
-function getInstalledVersion2() {
-  return Services.prefs.getIntPref("bootstraptest2.installed_version");
-}
-
 function getStartupReason() {
-  return Services.prefs.getIntPref("bootstraptest.startup_reason");
+  let info = BootstrapMonitor.started.get(ID1);
+  return info ? info.reason : undefined;
 }
 
 function getShutdownReason() {
-  return Services.prefs.getIntPref("bootstraptest.shutdown_reason");
+  let info = BootstrapMonitor.stopped.get(ID1);
+  return info ? info.reason : undefined;
 }
 
 function getInstallReason() {
-  return Services.prefs.getIntPref("bootstraptest.install_reason");
+  let info = BootstrapMonitor.installed.get(ID1);
+  return info ? info.reason : undefined;
 }
 
 function getUninstallReason() {
-  return Services.prefs.getIntPref("bootstraptest.uninstall_reason");
+  let info = BootstrapMonitor.uninstalled.get(ID1);
+  return info ? info.reason : undefined;
 }
 
 function getStartupOldVersion() {
-  return Services.prefs.getIntPref("bootstraptest.startup_oldversion");
+  let info = BootstrapMonitor.started.get(ID1);
+  return info ? info.data.oldVersion : undefined;
 }
 
 function getShutdownNewVersion() {
-  return Services.prefs.getIntPref("bootstraptest.shutdown_newversion");
+  let info = BootstrapMonitor.stopped.get(ID1);
+  return info ? info.data.newVersion : undefined;
 }
 
 function getInstallOldVersion() {
-  return Services.prefs.getIntPref("bootstraptest.install_oldversion");
+  let info = BootstrapMonitor.installed.get(ID1);
+  return info ? info.data.oldVersion : undefined;
 }
 
 function getUninstallNewVersion() {
-  return Services.prefs.getIntPref("bootstraptest.uninstall_newversion");
+  let info = BootstrapMonitor.uninstalled.get(ID1);
+  return info ? info.data.newVersion : undefined;
 }
 
 function do_check_bootstrappedPref(aCallback) {
   let data = Services.prefs.getCharPref("extensions.bootstrappedAddons");
   data = JSON.parse(data);
 
   AddonManager.getAddonsByTypes(["extension"], function(aAddons) {
     for (let addon of aAddons) {
@@ -152,18 +107,16 @@ function do_check_bootstrappedPref(aCall
     do_execute_soon(aCallback);
   });
 }
 
 
 function run_test() {
   do_test_pending();
 
-  resetPrefs();
-
   startupManager();
 
   do_check_false(gExtensionsJSON.exists());
 
   do_check_false(gExtensionsINI.exists());
 
   run_test_1();
 }
@@ -183,173 +136,173 @@ function run_test_1() {
     do_check_eq(install.name, "Test Bootstrap 1");
     do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
     do_check_neq(install.addon.syncGUID, null);
     do_check_true(install.addon.hasResource("install.rdf"));
     do_check_true(install.addon.hasResource("bootstrap.js"));
     do_check_false(install.addon.hasResource("foo.bar"));
     do_check_eq(install.addon.operationsRequiringRestart &
                 AddonManager.OP_NEEDS_RESTART_INSTALL, 0);
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_not_in_crash_annotation(ID1, "1.0");
 
     let addon = install.addon;
 
-    waitForPref("bootstraptest.startup_reason", function() {
+    BootstrapMonitor.promiseAddonStartup(ID1).then(function() {
       do_check_bootstrappedPref(function() {
         check_test_1(addon.syncGUID);
       });
     });
 
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], function() {
       do_check_true(addon.hasResource("install.rdf"));
 
       // startup should not have been called yet.
-      do_check_eq(getActiveVersion(), -1);
+      BootstrapMonitor.checkAddonNotStarted(ID1);
     });
     install.install();
   });
 }
 
 function check_test_1(installSyncGUID) {
   do_check_false(gExtensionsINI.exists());
 
   AddonManager.getAllInstalls(function(installs) {
     // There should be no active installs now since the install completed and
     // doesn't require a restart.
     do_check_eq(installs.length, 0);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID(ID1, function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "1.0");
       do_check_neq(b1.syncGUID, null);
       do_check_eq(b1.syncGUID, installSyncGUID);
       do_check_false(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_true(b1.isActive);
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 1);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "1.0");
       do_check_eq(getStartupReason(), ADDON_INSTALL);
-      do_check_eq(getStartupOldVersion(), 0);
+      do_check_eq(getStartupOldVersion(), undefined);
       do_check_true(b1.hasResource("install.rdf"));
       do_check_true(b1.hasResource("bootstrap.js"));
       do_check_false(b1.hasResource("foo.bar"));
-      do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+      do_check_in_crash_annotation(ID1, "1.0");
 
-      let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org");
+      let dir = do_get_addon_root_uri(profileDir, ID1);
       do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js");
 
       AddonManager.getAddonsWithOperationsByTypes(null, function(list) {
         do_check_eq(list.length, 0);
 
         do_execute_soon(run_test_2);
       });
     });
   });
 }
 
 // Tests that disabling doesn't require a restart
 function run_test_2() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onDisabling", false],
         "onDisabled"
       ]
     });
 
     do_check_eq(b1.operationsRequiringRestart &
                 AddonManager.OP_NEEDS_RESTART_DISABLE, 0);
     b1.userDisabled = true;
     ensure_test_completed();
 
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_true(b1.userDisabled);
     do_check_false(b1.isActive);
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 0);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonNotStarted(ID1);
     do_check_eq(getShutdownReason(), ADDON_DISABLE);
-    do_check_eq(getShutdownNewVersion(), 0);
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_eq(getShutdownNewVersion(), undefined);
+    do_check_not_in_crash_annotation(ID1, "1.0");
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
+    AddonManager.getAddonByID(ID1, function(newb1) {
       do_check_neq(newb1, null);
       do_check_eq(newb1.version, "1.0");
       do_check_false(newb1.appDisabled);
       do_check_true(newb1.userDisabled);
       do_check_false(newb1.isActive);
 
       do_check_bootstrappedPref(run_test_3);
     });
   });
 }
 
 // Test that restarting doesn't accidentally re-enable
 function run_test_3() {
   shutdownManager();
-  do_check_eq(getInstalledVersion(), 1);
-  do_check_eq(getActiveVersion(), 0);
+  BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+  BootstrapMonitor.checkAddonNotStarted(ID1);
   do_check_eq(getShutdownReason(), ADDON_DISABLE);
-  do_check_eq(getShutdownNewVersion(), 0);
+  do_check_eq(getShutdownNewVersion(), undefined);
   startupManager(false);
-  do_check_eq(getInstalledVersion(), 1);
-  do_check_eq(getActiveVersion(), 0);
+  BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+  BootstrapMonitor.checkAddonNotStarted(ID1);
   do_check_eq(getShutdownReason(), ADDON_DISABLE);
-  do_check_eq(getShutdownNewVersion(), 0);
-  do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+  do_check_eq(getShutdownNewVersion(), undefined);
+  do_check_not_in_crash_annotation(ID1, "1.0");
 
   do_check_false(gExtensionsINI.exists());
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_true(b1.userDisabled);
     do_check_false(b1.isActive);
 
     do_check_bootstrappedPref(run_test_4);
   });
 }
 
 // Tests that enabling doesn't require a restart
 function run_test_4() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onEnabling", false],
         "onEnabled"
       ]
     });
 
     do_check_eq(b1.operationsRequiringRestart &
                 AddonManager.OP_NEEDS_RESTART_ENABLE, 0);
     b1.userDisabled = false;
     ensure_test_completed();
 
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_eq(getStartupReason(), ADDON_ENABLE);
-    do_check_eq(getStartupOldVersion(), 0);
-    do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_eq(getStartupOldVersion(), undefined);
+    do_check_in_crash_annotation(ID1, "1.0");
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
+    AddonManager.getAddonByID(ID1, function(newb1) {
       do_check_neq(newb1, null);
       do_check_eq(newb1.version, "1.0");
       do_check_false(newb1.appDisabled);
       do_check_false(newb1.userDisabled);
       do_check_true(newb1.isActive);
 
       do_check_bootstrappedPref(run_test_5);
     });
@@ -357,29 +310,29 @@ function run_test_4() {
 }
 
 // Tests that a restart shuts down and restarts the add-on
 function run_test_5() {
   shutdownManager();
   // By the time we've shut down, the database must have been written
   do_check_true(gExtensionsJSON.exists());
 
-  do_check_eq(getInstalledVersion(), 1);
-  do_check_eq(getActiveVersion(), 0);
+  BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+  BootstrapMonitor.checkAddonNotStarted(ID1);
   do_check_eq(getShutdownReason(), APP_SHUTDOWN);
-  do_check_eq(getShutdownNewVersion(), 0);
-  do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+  do_check_eq(getShutdownNewVersion(), undefined);
+  do_check_not_in_crash_annotation(ID1, "1.0");
   startupManager(false);
-  do_check_eq(getInstalledVersion(), 1);
-  do_check_eq(getActiveVersion(), 1);
+  BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+  BootstrapMonitor.checkAddonStarted(ID1, "1.0");
   do_check_eq(getStartupReason(), APP_STARTUP);
-  do_check_eq(getStartupOldVersion(), 0);
-  do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+  do_check_eq(getStartupOldVersion(), undefined);
+  do_check_in_crash_annotation(ID1, "1.0");
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
     do_check_false(isExtensionInAddonsList(profileDir, b1.id));
 
     do_check_bootstrappedPref(run_test_6);
@@ -396,293 +349,293 @@ function run_test_6() {
     ensure_test_completed();
 
     do_check_neq(install, null);
     do_check_eq(install.type, "extension");
     do_check_eq(install.version, "2.0");
     do_check_eq(install.name, "Test Bootstrap 1");
     do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
 
-    waitForPref("bootstraptest.startup_reason", check_test_6);
+    BootstrapMonitor.promiseAddonStartup(ID1).then(check_test_6);
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], function() {
     });
     install.install();
   });
 }
 
 function check_test_6() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "2.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
-    do_check_eq(getInstalledVersion(), 2);
-    do_check_eq(getActiveVersion(), 2);
+    BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "2.0");
     do_check_eq(getStartupReason(), ADDON_UPGRADE);
     do_check_eq(getInstallOldVersion(), 1);
     do_check_eq(getStartupOldVersion(), 1);
     do_check_eq(getShutdownReason(), ADDON_UPGRADE);
     do_check_eq(getShutdownNewVersion(), 2);
     do_check_eq(getUninstallNewVersion(), 2);
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
-    do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
+    do_check_not_in_crash_annotation(ID1, "1.0");
+    do_check_in_crash_annotation(ID1, "2.0");
 
     do_check_bootstrappedPref(run_test_7);
   });
 }
 
 // Tests that uninstalling doesn't require a restart
 function run_test_7() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onUninstalling", false],
         "onUninstalled"
       ]
     });
 
     do_check_eq(b1.operationsRequiringRestart &
                 AddonManager.OP_NEEDS_RESTART_UNINSTALL, 0);
     b1.uninstall();
 
     do_check_bootstrappedPref(check_test_7);
   });
 }
 
 function check_test_7() {
   ensure_test_completed();
-  do_check_eq(getInstalledVersion(), 0);
-  do_check_eq(getActiveVersion(), 0);
+  BootstrapMonitor.checkAddonNotInstalled(ID1);
+  BootstrapMonitor.checkAddonNotStarted(ID1);
   do_check_eq(getShutdownReason(), ADDON_UNINSTALL);
-  do_check_eq(getShutdownNewVersion(), 0);
-  do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
+  do_check_eq(getShutdownNewVersion(), undefined);
+  do_check_not_in_crash_annotation(ID1, "2.0");
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+  AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
     do_check_eq(b1, null);
 
     restartManager();
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
+    AddonManager.getAddonByID(ID1, function(newb1) {
       do_check_eq(newb1, null);
 
       do_check_bootstrappedPref(run_test_8);
     });
   }));
 }
 
 // Test that a bootstrapped extension dropped into the profile loads properly
 // on startup and doesn't cause an EM restart
 function run_test_8() {
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
-                  "bootstrap1@tests.mozilla.org");
+                  ID1);
 
   startupManager(false);
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_eq(getStartupReason(), ADDON_INSTALL);
-    do_check_eq(getStartupOldVersion(), 0);
-    do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_eq(getStartupOldVersion(), undefined);
+    do_check_in_crash_annotation(ID1, "1.0");
 
     do_check_bootstrappedPref(run_test_9);
   });
 }
 
 // Test that items detected as removed during startup get removed properly
 function run_test_9() {
   shutdownManager();
 
-  manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org");
+  manuallyUninstall(profileDir, ID1);
+  BootstrapMonitor.clear(ID1);
 
   startupManager(false);
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_eq(b1, null);
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_not_in_crash_annotation(ID1, "1.0");
 
     do_check_bootstrappedPref(run_test_10);
   });
 }
 
 
 // Tests that installing a downgrade sends the right reason
 function run_test_10() {
-  resetPrefs();
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
   AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), function(install) {
     ensure_test_completed();
 
     do_check_neq(install, null);
     do_check_eq(install.type, "extension");
     do_check_eq(install.version, "2.0");
     do_check_eq(install.name, "Test Bootstrap 1");
     do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
     do_check_true(install.addon.hasResource("install.rdf"));
     do_check_true(install.addon.hasResource("bootstrap.js"));
     do_check_false(install.addon.hasResource("foo.bar"));
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
+    do_check_not_in_crash_annotation(ID1, "2.0");
 
-    waitForPref("bootstraptest.startup_reason", check_test_10_pt1);
+    BootstrapMonitor.promiseAddonStartup(ID1).then(check_test_10_pt1);
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], function() {
       do_print("Waiting for startup of bootstrap1_2");
     });
     install.install();
   });
 }
 
 function check_test_10_pt1() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "2.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
-    do_check_eq(getInstalledVersion(), 2);
-    do_check_eq(getActiveVersion(), 2);
+    BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "2.0");
     do_check_eq(getStartupReason(), ADDON_INSTALL);
-    do_check_eq(getStartupOldVersion(), 0);
+    do_check_eq(getStartupOldVersion(), undefined);
     do_check_true(b1.hasResource("install.rdf"));
     do_check_true(b1.hasResource("bootstrap.js"));
     do_check_false(b1.hasResource("foo.bar"));
-    do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
+    do_check_in_crash_annotation(ID1, "2.0");
 
     prepare_test({ }, [
       "onNewInstall"
     ]);
 
     AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), function(install) {
       ensure_test_completed();
 
       do_check_neq(install, null);
       do_check_eq(install.type, "extension");
       do_check_eq(install.version, "1.0");
       do_check_eq(install.name, "Test Bootstrap 1");
       do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
 
-      waitForPref("bootstraptest.startup_reason", check_test_10_pt2);
+      BootstrapMonitor.promiseAddonStartup(ID1).then(check_test_10_pt2);
       prepare_test({
-        "bootstrap1@tests.mozilla.org": [
+        [ID1]: [
           ["onInstalling", false],
           "onInstalled"
         ]
       }, [
         "onInstallStarted",
         "onInstallEnded",
       ], function() { });
       install.install();
     });
   });
 }
 
 function check_test_10_pt2() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_eq(getStartupReason(), ADDON_DOWNGRADE);
     do_check_eq(getInstallOldVersion(), 2);
     do_check_eq(getStartupOldVersion(), 2);
     do_check_eq(getShutdownReason(), ADDON_DOWNGRADE);
     do_check_eq(getShutdownNewVersion(), 1);
     do_check_eq(getUninstallNewVersion(), 1);
-    do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
+    do_check_in_crash_annotation(ID1, "1.0");
+    do_check_not_in_crash_annotation(ID1, "2.0");
 
     do_check_bootstrappedPref(run_test_11);
   });
 }
 
 // Tests that uninstalling a disabled add-on still calls the uninstall method
 function run_test_11() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onDisabling", false],
         "onDisabled",
         ["onUninstalling", false],
         "onUninstalled"
       ]
     });
 
     b1.userDisabled = true;
 
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 0);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonNotStarted(ID1);
     do_check_eq(getShutdownReason(), ADDON_DISABLE);
-    do_check_eq(getShutdownNewVersion(), 0);
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_eq(getShutdownNewVersion(), undefined);
+    do_check_not_in_crash_annotation(ID1, "1.0");
 
     b1.uninstall();
 
     check_test_11();
   });
 }
 
 function check_test_11() {
   ensure_test_completed();
-  do_check_eq(getInstalledVersion(), 0);
-  do_check_eq(getActiveVersion(), 0);
-  do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+  BootstrapMonitor.checkAddonNotInstalled(ID1);
+  BootstrapMonitor.checkAddonNotStarted(ID1);
+  do_check_not_in_crash_annotation(ID1, "1.0");
 
   do_check_bootstrappedPref(run_test_12);
 }
 
 // Tests that bootstrapped extensions are correctly loaded even if the app is
 // upgraded at the same time
 function run_test_12() {
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
-                  "bootstrap1@tests.mozilla.org");
+                  ID1);
 
   startupManager(true);
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_eq(getStartupReason(), ADDON_INSTALL);
-    do_check_eq(getStartupOldVersion(), 0);
-    do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+    do_check_eq(getStartupOldVersion(), undefined);
+    do_check_in_crash_annotation(ID1, "1.0");
 
     b1.uninstall();
     do_execute_soon(test_12_restart);
   });
 }
 
 function test_12_restart() {
   restartManager();
@@ -700,20 +653,20 @@ function run_test_13() {
   AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_3"), function(install) {
     ensure_test_completed();
 
     do_check_neq(install, null);
     do_check_eq(install.type, "extension");
     do_check_eq(install.version, "3.0");
     do_check_eq(install.name, "Test Bootstrap 1");
     do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
+    do_check_not_in_crash_annotation(ID1, "3.0");
 
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], callback_soon(check_test_13));
     install.install();
@@ -721,237 +674,233 @@ function run_test_13() {
 }
 
 function check_test_13() {
   AddonManager.getAllInstalls(function(installs) {
     // There should be no active installs now since the install completed and
     // doesn't require a restart.
     do_check_eq(installs.length, 0);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID(ID1, function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "3.0");
       do_check_true(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_false(b1.isActive);
-      do_check_eq(getInstalledVersion(), 3);  // We call install even for disabled add-ons
-      do_check_eq(getActiveVersion(), 0);     // Should not have called startup though
-      do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
+      BootstrapMonitor.checkAddonInstalled(ID1, "3.0"); // We call install even for disabled add-ons
+      BootstrapMonitor.checkAddonNotStarted(ID1);       // Should not have called startup though
+      do_check_not_in_crash_annotation(ID1, "3.0");
 
       do_execute_soon(test_13_restart);
     });
   });
 }
 
 function test_13_restart() {
   restartManager();
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "3.0");
     do_check_true(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_false(b1.isActive);
-    do_check_eq(getInstalledVersion(), 3);  // We call install even for disabled add-ons
-    do_check_eq(getActiveVersion(), 0);     // Should not have called startup though
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
+    BootstrapMonitor.checkAddonInstalled(ID1, "3.0"); // We call install even for disabled add-ons
+    BootstrapMonitor.checkAddonNotStarted(ID1);       // Should not have called startup though
+    do_check_not_in_crash_annotation(ID1, "3.0");
 
     do_check_bootstrappedPref(function() {
       b1.uninstall();
       do_execute_soon(run_test_14);
     });
   });
 }
 
 // Tests that a bootstrapped extension with an invalid target application entry
 // does not get loaded when detected during startup
 function run_test_14() {
   restartManager();
 
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_bootstrap1_3"), profileDir,
-                  "bootstrap1@tests.mozilla.org");
+                  ID1);
 
   startupManager(false);
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "3.0");
     do_check_true(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_false(b1.isActive);
-    do_check_eq(getInstalledVersion(), 3);   // We call install even for disabled add-ons
-    do_check_eq(getActiveVersion(), 0);      // Should not have called startup though
-    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
+    BootstrapMonitor.checkAddonInstalled(ID1, "3.0"); // We call install even for disabled add-ons
+    BootstrapMonitor.checkAddonNotStarted(ID1);       // Should not have called startup though
+    do_check_not_in_crash_annotation(ID1, "3.0");
 
     do_check_bootstrappedPref(function() {
       b1.uninstall();
 
       run_test_15();
     });
   });
 }
 
 // Tests that upgrading a disabled bootstrapped extension still calls uninstall
 // and install but doesn't startup the new version
 function run_test_15() {
-  resetPrefs();
-  waitForPref("bootstraptest.startup_reason", function test_15_after_startup() {
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  BootstrapMonitor.promiseAddonStartup(ID1).then(function test_15_after_startup() {
+    AddonManager.getAddonByID(ID1, function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "1.0");
       do_check_false(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_true(b1.isActive);
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 1);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "1.0");
 
       b1.userDisabled = true;
       do_check_false(b1.isActive);
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 0);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonNotStarted(ID1);
 
       prepare_test({ }, [
         "onNewInstall"
       ]);
 
       AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_2"), function(install) {
         ensure_test_completed();
 
         do_check_neq(install, null);
         do_check_true(install.addon.userDisabled);
 
         prepare_test({
-          "bootstrap1@tests.mozilla.org": [
+          [ID1]: [
             ["onInstalling", false],
             "onInstalled"
           ]
         }, [
           "onInstallStarted",
           "onInstallEnded",
         ], callback_soon(check_test_15));
         install.install();
       });
     });
   });
   installAllFiles([do_get_addon("test_bootstrap1_1")], function test_15_addon_installed() { });
 }
 
 function check_test_15() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "2.0");
     do_check_false(b1.appDisabled);
     do_check_true(b1.userDisabled);
     do_check_false(b1.isActive);
-    do_check_eq(getInstalledVersion(), 2);
-    do_check_eq(getActiveVersion(), 0);
+    BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+    BootstrapMonitor.checkAddonNotStarted(ID1);
 
     do_check_bootstrappedPref(function() {
       restartManager();
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+      AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
         do_check_neq(b1, null);
         do_check_eq(b1.version, "2.0");
         do_check_false(b1.appDisabled);
         do_check_true(b1.userDisabled);
         do_check_false(b1.isActive);
-        do_check_eq(getInstalledVersion(), 2);
-        do_check_eq(getActiveVersion(), 0);
+        BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+        BootstrapMonitor.checkAddonNotStarted(ID1);
 
         b1.uninstall();
 
         run_test_16();
       }));
     });
   });
 }
 
 // Tests that bootstrapped extensions don't get loaded when in safe mode
 function run_test_16() {
-  resetPrefs();
-  waitForPref("bootstraptest.startup_reason", function test_16_after_startup() {
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+  BootstrapMonitor.promiseAddonStartup(ID1).then(function test_16_after_startup() {
+    AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
       // Should have installed and started
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 1);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "1.0");
       do_check_true(b1.isActive);
       do_check_eq(b1.iconURL, "chrome://foo/skin/icon.png");
       do_check_eq(b1.aboutURL, "chrome://foo/content/about.xul");
       do_check_eq(b1.optionsURL, "chrome://foo/content/options.xul");
 
       shutdownManager();
 
       // Should have stopped
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 0);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonNotStarted(ID1);
 
       gAppInfo.inSafeMode = true;
       startupManager(false);
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+      AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
         // Should still be stopped
-        do_check_eq(getInstalledVersion(), 1);
-        do_check_eq(getActiveVersion(), 0);
+        BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+        BootstrapMonitor.checkAddonNotStarted(ID1);
         do_check_false(b1.isActive);
         do_check_eq(b1.iconURL, null);
         do_check_eq(b1.aboutURL, null);
         do_check_eq(b1.optionsURL, null);
 
         shutdownManager();
         gAppInfo.inSafeMode = false;
         startupManager(false);
 
         // Should have started
-        do_check_eq(getInstalledVersion(), 1);
-        do_check_eq(getActiveVersion(), 1);
+        BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+        BootstrapMonitor.checkAddonStarted(ID1, "1.0");
 
-        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+        AddonManager.getAddonByID(ID1, function(b1) {
           b1.uninstall();
 
           do_execute_soon(run_test_17);
         });
       }));
     }));
   });
   installAllFiles([do_get_addon("test_bootstrap1_1")], function() { });
 }
 
 // Check that a bootstrapped extension in a non-profile location is loaded
 function run_test_17() {
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_bootstrap1_1"), userExtDir,
-                  "bootstrap1@tests.mozilla.org");
+                  ID1);
 
-  resetPrefs();
   startupManager();
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     // Should have installed and started
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_true(b1.isActive);
 
     do_check_bootstrappedPref(run_test_18);
   });
 }
 
 // Check that installing a new bootstrapped extension in the profile replaces
 // the existing one
 function run_test_18() {
-  resetPrefs();
-  waitForPref("bootstraptest.startup_reason", function test_18_after_startup() {
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  BootstrapMonitor.promiseAddonStartup(ID1).then(function test_18_after_startup() {
+    AddonManager.getAddonByID(ID1, function(b1) {
       // Should have installed and started
-      do_check_eq(getInstalledVersion(), 2);
-      do_check_eq(getActiveVersion(), 2);
+      BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "2.0");
       do_check_neq(b1, null);
       do_check_eq(b1.version, "2.0");
       do_check_true(b1.isActive);
 
       do_check_eq(getShutdownReason(), ADDON_UPGRADE);
       do_check_eq(getUninstallReason(), ADDON_UPGRADE);
       do_check_eq(getInstallReason(), ADDON_UPGRADE);
       do_check_eq(getStartupReason(), ADDON_UPGRADE);
@@ -964,178 +913,179 @@ function run_test_18() {
       do_check_bootstrappedPref(run_test_19);
     });
   });
   installAllFiles([do_get_addon("test_bootstrap1_2")], function() { });
 }
 
 // Check that uninstalling the profile version reveals the non-profile one
 function run_test_19() {
-  resetPrefs();
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     // The revealed add-on gets activated asynchronously
     prepare_test({
-      "bootstrap1@tests.mozilla.org": [
+      [ID1]: [
         ["onUninstalling", false],
         "onUninstalled",
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [], check_test_19);
 
     b1.uninstall();
   });
 }
 
 function check_test_19() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     // Should have reverted to the older version
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_true(b1.isActive);
 
     // TODO these reasons really should be ADDON_DOWNGRADE (bug 607818)
     do_check_eq(getShutdownReason(), ADDON_UNINSTALL);
     do_check_eq(getUninstallReason(), ADDON_UNINSTALL);
     do_check_eq(getInstallReason(), ADDON_INSTALL);
     do_check_eq(getStartupReason(), ADDON_INSTALL);
 
-    do_check_eq(getShutdownNewVersion(), 0);
-    do_check_eq(getUninstallNewVersion(), 0);
-    do_check_eq(getInstallOldVersion(), 0);
-    do_check_eq(getStartupOldVersion(), 0);
+    do_check_eq(getShutdownNewVersion(), undefined);
+    do_check_eq(getUninstallNewVersion(), undefined);
+    do_check_eq(getInstallOldVersion(), undefined);
+    do_check_eq(getStartupOldVersion(), undefined);
 
     do_check_bootstrappedPref(run_test_20);
   });
 }
 
 // Check that a new profile extension detected at startup replaces the non-profile
 // one
 function run_test_20() {
-  resetPrefs();
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir,
-                  "bootstrap1@tests.mozilla.org");
+                  ID1);
 
   startupManager();
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     // Should have installed and started
-    do_check_eq(getInstalledVersion(), 2);
-    do_check_eq(getActiveVersion(), 2);
+    BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "2.0");
     do_check_neq(b1, null);
     do_check_eq(b1.version, "2.0");
     do_check_true(b1.isActive);
 
     do_check_eq(getShutdownReason(), APP_SHUTDOWN);
     do_check_eq(getUninstallReason(), ADDON_UPGRADE);
     do_check_eq(getInstallReason(), ADDON_UPGRADE);
     do_check_eq(getStartupReason(), APP_STARTUP);
 
-    do_check_eq(getShutdownNewVersion(), 0);
+    do_check_eq(getShutdownNewVersion(), undefined);
     do_check_eq(getUninstallNewVersion(), 2);
     do_check_eq(getInstallOldVersion(), 1);
-    do_check_eq(getStartupOldVersion(), 0);
+    do_check_eq(getStartupOldVersion(), undefined);
 
     do_execute_soon(run_test_21);
   });
 }
 
 // Check that a detected removal reveals the non-profile one
 function run_test_21() {
-  resetPrefs();
   shutdownManager();
 
-  manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org");
+  do_check_eq(getShutdownReason(), APP_SHUTDOWN);
+  do_check_eq(getShutdownNewVersion(), undefined);
+
+  manuallyUninstall(profileDir, ID1);
+  BootstrapMonitor.clear(ID1);
 
   startupManager();
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     // Should have installed and started
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_true(b1.isActive);
 
-    do_check_eq(getShutdownReason(), APP_SHUTDOWN);
-    do_check_eq(getShutdownNewVersion(), 0);
-
     // This won't be set as the bootstrap script was gone so we couldn't
     // uninstall it properly
-    do_check_eq(getUninstallReason(), -1);
-    do_check_eq(getUninstallNewVersion(), -1);
+    do_check_eq(getUninstallReason(), undefined);
+    do_check_eq(getUninstallNewVersion(), undefined);
 
     do_check_eq(getInstallReason(), ADDON_DOWNGRADE);
     do_check_eq(getInstallOldVersion(), 2);
 
     do_check_eq(getStartupReason(), APP_STARTUP);
-    do_check_eq(getStartupOldVersion(), 0);
+    do_check_eq(getStartupOldVersion(), undefined);
 
     do_check_bootstrappedPref(function() {
-      manuallyUninstall(userExtDir, "bootstrap1@tests.mozilla.org");
+      shutdownManager();
 
-      restartManager();
+      manuallyUninstall(userExtDir, ID1);
+      BootstrapMonitor.clear(ID1);
+
+      startupManager(false);
       run_test_22();
     });
   });
 }
 
 // Check that an upgrade from the filesystem is detected and applied correctly
 function run_test_22() {
   shutdownManager();
 
   let file = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
-                             "bootstrap1@tests.mozilla.org");
+                             ID1);
 
   // Make it look old so changes are detected
   setExtensionModifiedTime(file, file.lastModifiedTime - 5000);
 
   startupManager();
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+  AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
     // Should have installed and started
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_true(b1.isActive);
 
-    resetPrefs();
     shutdownManager();
 
-    manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org");
+    do_check_eq(getShutdownReason(), APP_SHUTDOWN);
+    do_check_eq(getShutdownNewVersion(), undefined);
+
+    manuallyUninstall(profileDir, ID1);
+    BootstrapMonitor.clear(ID1);
     manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir,
-                    "bootstrap1@tests.mozilla.org");
+                    ID1);
 
     startupManager();
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID(ID1, function(b1) {
       // Should have installed and started
-      do_check_eq(getInstalledVersion(), 2);
-      do_check_eq(getActiveVersion(), 2);
+      BootstrapMonitor.checkAddonInstalled(ID1, "2.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "2.0");
       do_check_neq(b1, null);
       do_check_eq(b1.version, "2.0");
       do_check_true(b1.isActive);
 
-      do_check_eq(getShutdownReason(), APP_SHUTDOWN);
-      do_check_eq(getShutdownNewVersion(), 0);
-
       // This won't be set as the bootstrap script was gone so we couldn't
       // uninstall it properly
-      do_check_eq(getUninstallReason(), -1);
-      do_check_eq(getUninstallNewVersion(), -1);
+      do_check_eq(getUninstallReason(), undefined);
+      do_check_eq(getUninstallNewVersion(), undefined);
 
       do_check_eq(getInstallReason(), ADDON_UPGRADE);
       do_check_eq(getInstallOldVersion(), 1);
       do_check_eq(getStartupReason(), APP_STARTUP);
-      do_check_eq(getStartupOldVersion(), 0);
+      do_check_eq(getStartupOldVersion(), undefined);
 
       do_check_bootstrappedPref(function() {
         b1.uninstall();
 
         run_test_23();
       });
     });
   }));
@@ -1162,21 +1112,21 @@ function run_test_23() {
       do_check_eq(install.version, "1.0");
       do_check_eq(install.name, "Test Bootstrap 1");
       do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
       do_check_true(install.addon.hasResource("install.rdf"));
       do_check_true(install.addon.hasResource("bootstrap.js"));
       do_check_false(install.addon.hasResource("foo.bar"));
       do_check_eq(install.addon.operationsRequiringRestart &
                   AddonManager.OP_NEEDS_RESTART_INSTALL, 0);
-      do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+      do_check_not_in_crash_annotation(ID1, "1.0");
 
       let addon = install.addon;
       prepare_test({
-        "bootstrap1@tests.mozilla.org": [
+        [ID1]: [
           ["onInstalling", false],
           "onInstalled"
         ]
       }, [
         "onInstallStarted",
         "onInstallEnded",
       ], function() {
         do_check_true(addon.hasResource("install.rdf"));
@@ -1188,124 +1138,121 @@ function run_test_23() {
 }
 
 function check_test_23() {
   AddonManager.getAllInstalls(function(installs) {
     // There should be no active installs now since the install completed and
     // doesn't require a restart.
     do_check_eq(installs.length, 0);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID(ID1, function(b1) {
      do_execute_soon(function test_23_after_startup() {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "1.0");
       do_check_false(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_true(b1.isActive);
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 1);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "1.0");
       do_check_eq(getStartupReason(), ADDON_INSTALL);
-      do_check_eq(getStartupOldVersion(), 0);
+      do_check_eq(getStartupOldVersion(), undefined);
       do_check_true(b1.hasResource("install.rdf"));
       do_check_true(b1.hasResource("bootstrap.js"));
       do_check_false(b1.hasResource("foo.bar"));
-      do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
+      do_check_in_crash_annotation(ID1, "1.0");
 
-      let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org");
+      let dir = do_get_addon_root_uri(profileDir, ID1);
       do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js");
 
       AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) {
         do_check_eq(list.length, 0);
 
         restartManager();
-        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+        AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
           b1.uninstall();
           restartManager();
 
           testserver.stop(run_test_24);
         }));
       }));
      });
     });
   });
 }
 
 // Tests that we recover from a broken preference
 function run_test_24() {
-  resetPrefs();
   do_print("starting 24");
 
-  Promise.all([promisePref("bootstraptest2.active_version"),
-              promiseInstall([do_get_addon("test_bootstrap1_1"), do_get_addon("test_bootstrap2_1")])])
+  Promise.all([BootstrapMonitor.promiseAddonStartup(ID2),
+              promiseInstallAllFiles([do_get_addon("test_bootstrap1_1"), do_get_addon("test_bootstrap2_1")])])
          .then(function test_24_pref() {
     do_print("test 24 got prefs");
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 1);
-    do_check_eq(getInstalledVersion2(), 1);
-    do_check_eq(getActiveVersion2(), 1);
-
-    resetPrefs();
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
+    BootstrapMonitor.checkAddonInstalled(ID2, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID2, "1.0");
 
     restartManager();
 
-    do_check_eq(getInstalledVersion(), -1);
-    do_check_eq(getActiveVersion(), 1);
-    do_check_eq(getInstalledVersion2(), -1);
-    do_check_eq(getActiveVersion2(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
+    BootstrapMonitor.checkAddonInstalled(ID2, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID2, "1.0");
 
     shutdownManager();
 
-    do_check_eq(getInstalledVersion(), -1);
-    do_check_eq(getActiveVersion(), 0);
-    do_check_eq(getInstalledVersion2(), -1);
-    do_check_eq(getActiveVersion2(), 0);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonNotStarted(ID1);
+    BootstrapMonitor.checkAddonInstalled(ID2, "1.0");
+    BootstrapMonitor.checkAddonNotStarted(ID2);
 
-    // Break the preferece
+    // Break the preference
     let bootstrappedAddons = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons"));
-    bootstrappedAddons["bootstrap1@tests.mozilla.org"].descriptor += "foo";
+    bootstrappedAddons[ID1].descriptor += "foo";
     Services.prefs.setCharPref("extensions.bootstrappedAddons", JSON.stringify(bootstrappedAddons));
 
     startupManager(false);
 
-    do_check_eq(getInstalledVersion(), -1);
-    do_check_eq(getActiveVersion(), 1);
-    do_check_eq(getInstalledVersion2(), -1);
-    do_check_eq(getActiveVersion2(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID1, "1.0");
+    BootstrapMonitor.checkAddonInstalled(ID2, "1.0");
+    BootstrapMonitor.checkAddonStarted(ID2, "1.0");
 
     run_test_25();
   });
 }
 
 // Tests that updating from a bootstrappable add-on to a normal add-on calls
 // the uninstall method
 function run_test_25() {
-  waitForPref("bootstraptest.startup_reason", function test_25_after_pref() {
+  BootstrapMonitor.promiseAddonStartup(ID1).then(function test_25_after_pref() {
       do_print("test 25 pref change detected");
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 1);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonStarted(ID1, "1.0");
 
       installAllFiles([do_get_addon("test_bootstrap1_4")], function() {
         // Needs a restart to complete this so the old version stays running
-        do_check_eq(getInstalledVersion(), 1);
-        do_check_eq(getActiveVersion(), 1);
+        BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+        BootstrapMonitor.checkAddonStarted(ID1, "1.0");
 
-        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+        AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
           do_check_neq(b1, null);
           do_check_eq(b1.version, "1.0");
           do_check_true(b1.isActive);
           do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
 
           restartManager();
 
-          do_check_eq(getInstalledVersion(), 0);
+          BootstrapMonitor.checkAddonNotInstalled(ID1);
           do_check_eq(getUninstallReason(), ADDON_UPGRADE);
           do_check_eq(getUninstallNewVersion(), 4);
-          do_check_eq(getActiveVersion(), 0);
+          BootstrapMonitor.checkAddonNotStarted(ID1);
 
-          AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+          AddonManager.getAddonByID(ID1, function(b1) {
             do_check_neq(b1, null);
             do_check_eq(b1.version, "4.0");
             do_check_true(b1.isActive);
             do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
             do_check_bootstrappedPref(run_test_26);
           });
         }));
@@ -1316,75 +1263,75 @@ function run_test_25() {
   });
 }
 
 // Tests that updating from a normal add-on to a bootstrappable add-on calls
 // the install method
 function run_test_26() {
   installAllFiles([do_get_addon("test_bootstrap1_1")], function() {
     // Needs a restart to complete this
-    do_check_eq(getInstalledVersion(), 0);
-    do_check_eq(getActiveVersion(), 0);
+    BootstrapMonitor.checkAddonNotInstalled(ID1);
+    BootstrapMonitor.checkAddonNotStarted(ID1);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+    AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "4.0");
       do_check_true(b1.isActive);
       do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
 
       restartManager();
 
-      do_check_eq(getInstalledVersion(), 1);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
       do_check_eq(getInstallReason(), ADDON_DOWNGRADE);
       do_check_eq(getInstallOldVersion(), 4);
-      do_check_eq(getActiveVersion(), 1);
+      BootstrapMonitor.checkAddonStarted(ID1, "1.0");
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+      AddonManager.getAddonByID(ID1, function(b1) {
         do_check_neq(b1, null);
         do_check_eq(b1.version, "1.0");
         do_check_true(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
         do_check_bootstrappedPref(run_test_27);
       });
     }));
   });
 }
 
 // Tests that updating from a bootstrappable add-on to a normal add-on while
 // disabled calls the uninstall method
 function run_test_27() {
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID(ID1, function(b1) {
     do_check_neq(b1, null);
     b1.userDisabled = true;
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.isActive);
     do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
-    do_check_eq(getInstalledVersion(), 1);
-    do_check_eq(getActiveVersion(), 0);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+    BootstrapMonitor.checkAddonNotStarted(ID1);
 
     installAllFiles([do_get_addon("test_bootstrap1_4")], function() {
       // Updating disabled things happens immediately
-      do_check_eq(getInstalledVersion(), 0);
+      BootstrapMonitor.checkAddonNotInstalled(ID1);
       do_check_eq(getUninstallReason(), ADDON_UPGRADE);
       do_check_eq(getUninstallNewVersion(), 4);
-      do_check_eq(getActiveVersion(), 0);
+      BootstrapMonitor.checkAddonNotStarted(ID1);
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+      AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
         do_check_neq(b1, null);
         do_check_eq(b1.version, "4.0");
         do_check_false(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
         restartManager();
 
-        do_check_eq(getInstalledVersion(), 0);
-        do_check_eq(getActiveVersion(), 0);
+        BootstrapMonitor.checkAddonNotInstalled(ID1);
+        BootstrapMonitor.checkAddonNotStarted(ID1);
 
-        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+        AddonManager.getAddonByID(ID1, function(b1) {
           do_check_neq(b1, null);
           do_check_eq(b1.version, "4.0");
           do_check_false(b1.isActive);
           do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
           do_check_bootstrappedPref(run_test_28);
         });
       }));
@@ -1393,41 +1340,41 @@ function run_test_27() {
 }
 
 // Tests that updating from a normal add-on to a bootstrappable add-on when
 // disabled calls the install method but not the startup method
 function run_test_28() {
   installAllFiles([do_get_addon("test_bootstrap1_1")], function() {
    do_execute_soon(function bootstrap_disabled_downgrade_check() {
     // Doesn't need a restart to complete this
-    do_check_eq(getInstalledVersion(), 1);
+    BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
     do_check_eq(getInstallReason(), ADDON_DOWNGRADE);
     do_check_eq(getInstallOldVersion(), 4);
-    do_check_eq(getActiveVersion(), 0);
+    BootstrapMonitor.checkAddonNotStarted(ID1);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
+    AddonManager.getAddonByID(ID1, callback_soon(function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "1.0");
       do_check_false(b1.isActive);
       do_check_true(b1.userDisabled);
       do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
       restartManager();
 
-      do_check_eq(getInstalledVersion(), 1);
-      do_check_eq(getActiveVersion(), 0);
+      BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+      BootstrapMonitor.checkAddonNotStarted(ID1);
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+      AddonManager.getAddonByID(ID1, function(b1) {
         do_check_neq(b1, null);
         do_check_true(b1.userDisabled);
         b1.userDisabled = false;
         do_check_eq(b1.version, "1.0");
         do_check_true(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_eq(getInstalledVersion(), 1);
-        do_check_eq(getActiveVersion(), 1);
+        BootstrapMonitor.checkAddonInstalled(ID1, "1.0");
+        BootstrapMonitor.checkAddonStarted(ID1, "1.0");
 
         do_check_bootstrappedPref(do_test_finished);
       });
     }));
    });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
@@ -14,16 +14,18 @@ createAppInfo("xpcshell@tests.mozilla.or
 
 const profileDir = gProfD.clone();
 profileDir.append("extensions");
 const userExtDir = gProfD.clone();
 userExtDir.append("extensions2");
 userExtDir.append(gAppInfo.ID);
 registerDirectory("XREUSysExt", userExtDir.parent);
 
+BootstrapMonitor.init();
+
 function TestProvider(result) {
   this.result = result;
 }
 TestProvider.prototype = {
   uri: Services.io.newURI("hellow://world", null, null),
   id: "valid@id",
   startup: function() {},
   shutdown: function() {},
@@ -45,37 +47,23 @@ function check_mapping(uri, id) {
   do_check_eq(AddonManager.mapURIToAddonID(uri), id);
   let svc = Components.classes["@mozilla.org/addons/integration;1"].
             getService(Components.interfaces.amIAddonManager);
   let val = {};
   do_check_true(svc.mapURIToAddonID(uri, val));
   do_check_eq(val.value, id);
 }
 
-function resetPrefs() {
-  Services.prefs.setIntPref("bootstraptest.active_version", -1);
-}
-
-function waitForPref(aPref, aCallback) {
-  function prefChanged() {
-    Services.prefs.removeObserver(aPref, prefChanged);
-    aCallback();
-  }
-  Services.prefs.addObserver(aPref, prefChanged, false);
-}
-
 function getActiveVersion() {
   return Services.prefs.getIntPref("bootstraptest.active_version");
 }
 
 function run_test() {
   do_test_pending();
 
-  resetPrefs();
-
   run_test_early();
 }
 
 function run_test_early() {
   startupManager();
 
   installAllFiles([do_get_addon("test_chromemanifest_1")], function() {
     restartManager();
@@ -143,17 +131,17 @@ function run_test_1() {
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], function() {
       let uri = addon.getResourceURI(".");
       check_mapping(uri, addon.id);
 
-      waitForPref("bootstraptest.active_version", function() {
+      BootstrapMonitor.promiseAddonStartup("bootstrap1@tests.mozilla.org").then(function() {
         run_test_2(uri);
       });
     });
     install.install();
   });
 }
 
 // Tests that add-on URIs are still mappable, even after the add-on gets
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js
@@ -1,15 +1,17 @@
 // Tests that we reset to the default system add-ons correctly when switching
 // application versions
 const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet";
 
 // Enable signature checks for these tests
 Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true);
 
+BootstrapMonitor.init();
+
 const featureDir = FileUtils.getDir("ProfD", ["features"]);
 
 // Build the test sets
 let dir = FileUtils.getDir("ProfD", ["sysfeatures", "app1"], true);
 do_get_file("data/system_addons/system1_1.xpi").copyTo(dir, "system1@tests.mozilla.org.xpi");
 do_get_file("data/system_addons/system2_1.xpi").copyTo(dir, "system2@tests.mozilla.org.xpi");
 
 dir = FileUtils.getDir("ProfD", ["sysfeatures", "app2"], true);
@@ -56,35 +58,34 @@ function* check_installed(inProfile, ...
 
       let uri = addon.getResourceURI(null);
       do_check_true(uri instanceof AM_Ci.nsIFileURL);
       do_check_eq(uri.file.path, file.path);
 
       do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SYSTEM);
 
       // Verify the add-on actually started
-      let installed = Services.prefs.getCharPref("bootstraptest." + id + ".active_version");
-      do_check_eq(installed, versions[i]);
+      BootstrapMonitor.checkAddonStarted(id, versions[i]);
     }
     else {
       if (inProfile) {
         // Add-on should not be installed
         do_check_eq(addon, null);
       }
       else {
         // Either add-on should not be installed or it shouldn't be active
         do_check_true(!addon || !addon.isActive);
       }
 
-      try {
-        Services.prefs.getCharPref("bootstraptest." + id + ".active_version");
-        do_throw("Expected pref to be missing");
-      }
-      catch (e) {
-      }
+      BootstrapMonitor.checkAddonNotStarted(id);
+
+      if (addon)
+        BootstrapMonitor.checkAddonInstalled(id);
+      else
+        BootstrapMonitor.checkAddonNotInstalled(id);
     }
   }
 }
 
 // Test with a missing features directory
 add_task(function* test_missing_app_dir() {
   startupManager();
 
@@ -181,16 +182,19 @@ add_task(function* test_skips_additional
 
   yield promiseShutdownManager();
 });
 
 // Missing add-on should revert to the default set
 add_task(function* test_revert() {
   manuallyUninstall(featureDir, "system2@tests.mozilla.org");
 
+  // With the add-on physically gone from disk we won't see uninstall events
+  BootstrapMonitor.clear("system2@tests.mozilla.org");
+
   startupManager(false);
 
   // With system add-on 2 gone the updated set is now invalid so it reverts to
   // the default set which is system add-ons 1 and 2.
   yield check_installed(false, "1.0", "1.0", null);
 
   yield promiseShutdownManager();
 });
@@ -253,14 +257,14 @@ add_task(function* test_bad_profile_cert
 add_task(function* test_bad_app_cert() {
   gAppInfo.version = "3";
   distroDir.leafName = "app3";
   startupManager();
 
   // Add-on will still be present just not active
   let addon = yield promiseAddonByID("system1@tests.mozilla.org");
   do_check_neq(addon, null);
-  do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SIGNED);
+  do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_BROKEN);
 
   yield check_installed(false, null, null, "1.0");
 
   yield promiseShutdownManager();
 });
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
@@ -4,17 +4,19 @@ const PREF_SYSTEM_ADDON_SET           = 
 const PREF_SYSTEM_ADDON_UPDATE_URL    = "extensions.systemAddon.update.url";
 const PREF_XPI_STATE                  = "extensions.xpiState";
 const PREF_APP_UPDATE_ENABLED         = "app.update.enabled";
 
 Components.utils.import("resource://testing-common/httpd.js");
 const { computeHash } = Components.utils.import("resource://gre/modules/addons/ProductAddonChecker.jsm");
 
 // Enable signature checks for these tests
-//Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true);
+Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true);
+
+BootstrapMonitor.init();
 
 const featureDir = FileUtils.getDir("ProfD", ["features"]);
 
 function getCurrentFeatureDir() {
   let dir = featureDir.clone();
   let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET));
   dir.append(set.directory);
   return dir;
@@ -137,16 +139,18 @@ function* build_xml(addons) {
 function* check_installed(inProfile, ...versions) {
   let expectedDir = inProfile ? getCurrentFeatureDir() : distroDir;
 
   for (let i = 0; i < versions.length; i++) {
     let id = "system" + (i + 1) + "@tests.mozilla.org";
     let addon = yield promiseAddonByID(id);
 
     if (versions[i]) {
+      do_print(`Checking state of add-on ${id}, expecting version ${versions[i]}`);
+
       // Add-on should be installed
       do_check_neq(addon, null);
       do_check_eq(addon.version, versions[i]);
       do_check_true(addon.isActive);
       do_check_false(addon.foreignInstall);
       do_check_true(addon.hidden);
 
       // Verify the add-ons file is in the right place
@@ -154,38 +158,39 @@ function* check_installed(inProfile, ...
       file.append(id + ".xpi");
       do_check_true(file.exists());
       do_check_true(file.isFile());
 
       let uri = addon.getResourceURI(null);
       do_check_true(uri instanceof AM_Ci.nsIFileURL);
       do_check_eq(uri.file.path, file.path);
 
-      //do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SYSTEM);
+      do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_SYSTEM);
 
       // Verify the add-on actually started
-      let installed = Services.prefs.getCharPref("bootstraptest." + id + ".active_version");
-      do_check_eq(installed, versions[i]);
+      BootstrapMonitor.checkAddonStarted(id, versions[i]);
     }
     else {
+      do_print(`Checking state of add-on ${id}, expecting it to be missing`);
+
       if (inProfile) {
         // Add-on should not be installed
         do_check_eq(addon, null);
       }
       else {
         // Either add-on should not be installed or it shouldn't be active
         do_check_true(!addon || !addon.isActive);
       }
 
-      try {
-        Services.prefs.getCharPref("bootstraptest." + id + ".active_version");
-        do_throw("Expected pref to be missing");
-      }
-      catch (e) {
-      }
+      BootstrapMonitor.checkAddonNotStarted(id);
+
+      if (addon)
+        BootstrapMonitor.checkAddonInstalled(id);
+      else
+        BootstrapMonitor.checkAddonNotInstalled(id);
     }
   }
 }
 
 
 /**
  * Defines the set of initial conditions to run each test against. Each should
  * define the following properties:
@@ -323,36 +328,40 @@ const TESTS = {
       { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" },
       { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "205a4c49bd513ebd30594e380c19e86bba1f83e2" }
     ],
   },
 
   // Correct sizes and hashes should work
   checkSizeHash: {
     updateList: [
-      { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 858 },
-      { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "105a4c49bd513ebd30594e380c19e86bba1f83e2" },
-      { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi", size: 857, hashFunction: "sha1", hashValue: "664e9218be3c9acbb9029e715c1e5d2fbb4ea2cc" }
+      { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 4672 },
+      { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "2df604b37b13766c0e04f1b7f59800e038f46cd5" },
+      { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi", size: 4671, hashFunction: "sha1", hashValue: "f13dcaa8bfacaa222189bcbb0074972c05ceb621" }
     ],
     finalState: [true, null, "3.0", "3.0", null, "1.0"]
   },
 }
 
 add_task(function* setup() {
   // Initialise the profile
   startupManager();
   yield promiseShutdownManager();
 })
 
 function* setup_conditions(setup) {
+  do_print("Clearing existing database.");
+  Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
+  distroDir.leafName = "empty";
+  startupManager(false);
+  yield promiseShutdownManager();
+
   do_print("Setting up conditions.");
   yield setup.setup();
 
-  // Blow away the cache to force a rescan of the filesystem
-  Services.prefs.clearUserPref(PREF_XPI_STATE);
   startupManager(false);
 
   // Make sure the initial state is correct
   do_print("Checking initial state.");
   yield check_installed(...setup.initialState);
 }
 
 function* verify_state(finalState) {
@@ -430,43 +439,71 @@ add_task(function* test_app_update_disab
   ]));
   Services.prefs.clearUserPref(PREF_APP_UPDATE_ENABLED);
 
   yield verify_state(TEST_CONDITIONS.blank.initialState);
 
   yield promiseShutdownManager();
 });
 
+// Tests that a set that matches the default set does nothing
+add_task(function* test_match_default() {
+  yield setup_conditions(TEST_CONDITIONS.withAppSet);
+
+  yield install_system_addons(yield build_xml([
+    { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" },
+    { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" }
+  ]));
+
+  // Shouldn't have installed an updated set
+  yield verify_state(TEST_CONDITIONS.withAppSet.initialState);
+
+  yield promiseShutdownManager();
+});
+
 // Tests that a set that matches the hidden default set works
-add_task(function* test_match_default() {
+add_task(function* test_match_default_revert() {
   yield setup_conditions(TEST_CONDITIONS.withBothSets);
 
   yield install_system_addons(yield build_xml([
     { id: "system1@tests.mozilla.org", version: "1.0", path: "system1_1.xpi" },
     { id: "system2@tests.mozilla.org", version: "1.0", path: "system2_1.xpi" }
   ]));
 
-  // Bug 1204159: This should revert to the default set instead of installing
-  // new versions into the updated set.
-  //yield verify_state([false, "1.0", "1.0", null, null, null]);
-  yield verify_state([true, "1.0", "1.0", null, null, null]);
+  // This should revert to the default set instead of installing new versions
+  // into an updated set.
+  yield verify_state([false, "1.0", "1.0", null, null, null]);
 
   yield promiseShutdownManager();
 });
 
 // Tests that a set that matches the current set works
 add_task(function* test_match_current() {
   yield setup_conditions(TEST_CONDITIONS.withBothSets);
 
   yield install_system_addons(yield build_xml([
     { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" },
     { id: "system3@tests.mozilla.org", version: "2.0", path: "system3_2.xpi" }
   ]));
 
-  // Bug 1204159: This should remain with the current set instead of creating
-  // a new copy
-  //let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET));
-  //do_check_eq(set.directory, "prefilled");
+  // This should remain with the current set instead of creating a new copy
+  let set = JSON.parse(Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET));
+  do_check_eq(set.directory, "prefilled");
 
-  yield verify_state([true, null, "2.0", "2.0", null, null]);
+  yield verify_state(TEST_CONDITIONS.withBothSets.initialState);
 
   yield promiseShutdownManager();
 });
+
+// Tests that a set with a minor change doesn't re-download existing files
+add_task(function* test_no_download() {
+  yield setup_conditions(TEST_CONDITIONS.withBothSets);
+
+  // The missing file here is unneeded since there is a local version already
+  yield install_system_addons(yield build_xml([
+    { id: "system2@tests.mozilla.org", version: "2.0", path: "missing.xpi" },
+    { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }
+  ]));
+
+  yield verify_state([true, null, "2.0", null, "1.0", null]);
+
+  yield promiseShutdownManager();
+});