Merge m-c to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 19 Sep 2014 14:35:57 +0200
changeset 206223 92df0fb732367dd78b9270895b5a62279610e733
parent 206222 17d48ba5979bc7e7b03d1475f74a73031f2a4ba1 (current diff)
parent 206162 3475e6a1665a6339dcbdc220a06ebdcdd9a9293c (diff)
child 206224 8ac587fb9cdafba6e345b083ee17ec9a5ba44823
push id27516
push userryanvm@gmail.com
push dateFri, 19 Sep 2014 17:54:48 +0000
treeherdermozilla-central@b00bdb144e06 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to mozilla-inbound
browser/themes/linux/browser.css
browser/themes/linux/pluginInstall-16.png
browser/themes/linux/pluginInstall-64.png
browser/themes/osx/browser.css
browser/themes/osx/pluginInstall-16.png
browser/themes/osx/pluginInstall-16@2x.png
browser/themes/osx/pluginInstall-64.png
browser/themes/osx/pluginInstall-64@2x.png
browser/themes/windows/browser.css
browser/themes/windows/pluginInstall-16.png
browser/themes/windows/pluginInstall-64.png
toolkit/content/widgets/autocomplete.xml
toolkit/locales/en-US/chrome/global/xpinstall/xpinstall.properties
toolkit/locales/en-US/chrome/mozapps/plugins/plugins.properties
toolkit/mozapps/plugins/content/pluginInstallerDatasource.js
toolkit/mozapps/plugins/content/pluginInstallerService.js
toolkit/mozapps/plugins/content/pluginInstallerWizard.css
toolkit/mozapps/plugins/content/pluginInstallerWizard.js
toolkit/mozapps/plugins/content/pluginInstallerWizard.xul
toolkit/mozapps/plugins/service/PluginFinderService.java
toolkit/mozapps/plugins/service/PluginFinderService.php
toolkit/mozapps/plugins/service/PluginInfo.java
toolkit/mozapps/plugins/service/make.sh
toolkit/mozapps/plugins/tests/BadExtension.xpi
toolkit/mozapps/plugins/tests/BadPlugin.cpp
toolkit/mozapps/plugins/tests/GoodExtension.xpi
toolkit/mozapps/plugins/tests/GoodPlugin.cpp
toolkit/mozapps/plugins/tests/Makefile.in
toolkit/mozapps/plugins/tests/browser.ini
toolkit/mozapps/plugins/tests/browser_bug435788.js
toolkit/mozapps/plugins/tests/moz.build
toolkit/mozapps/plugins/tests/pfs_bug435788_1.rdf
toolkit/mozapps/plugins/tests/pfs_bug435788_2.rdf
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
@@ -130,23 +130,23 @@
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
   <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="6f72b9d7a2322043fd0c4ba889ad689b084081c5"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="893238eb1215f8fd4f3747169170cc5e1cc33969"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
-  <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="082a1f98422e6a6b56f61218d6fcf465e85d4c58"/>
+  <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="b2af89ae378a119819a9c86d9a12e573c7130459"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="c1814713bd2d07c2af0c236007badc8732a34324"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="6b58ab45e3e56c1fc20708cc39fa2264c52558df"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="a46a9f1ac0ed5662d614c277cbb14eb3f332f365"/>
-  <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="9982f697972cfab09379fd909307e993a6247ebf"/>
+  <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="7196881a0e9dd7bfbbcf0af64c8064e70f0fa094"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="8d7676dfb68ee0cd069affedd5d1e97316a184ba"/>
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="2a1ded216a91bf62a72b1640cf01ab4998f37028"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="e5a971282719907f73fb1da964ca40aad67a3be0"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="9883ea57b0668d8f60dba025d4522dfa69a1fbfa"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="a558dc844bf5144fc38603fd8f4df8d9557052a5"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "cc0cc3a29b940c3b2e7434540f0e7263458a925d", 
+    "revision": "98ad49da1fb006f0dcd8ed1af37382ab531ef016", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <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="bc2da39ccd2b82b67773f10c8da8fc8eedc483ab"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d170091ba1b5597b05f37fb259f6b8eb02568798"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f293787d4a86257c9e78a35bd3f73b31b706e2"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -659,18 +659,16 @@ pref("accessibility.typeaheadfind.flashB
 // plugin finder service url
 pref("pfs.datasource.url", "https://pfs.mozilla.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%&appID=%APP_ID%&appVersion=%APP_VERSION%&clientOS=%CLIENT_OS%&chromeLocale=%CHROME_LOCALE%&appRelease=%APP_RELEASE%");
 
 pref("plugins.update.url", "https://www.mozilla.org/%LOCALE%/plugincheck/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=plugincheck-update");
 pref("plugins.update.notifyUser", false);
 
 pref("plugins.click_to_play", true);
 
-pref("plugins.hideMissingPluginsNotification", false);
-
 pref("plugin.default.state", 1);
 
 // Plugins bundled in XPIs are enabled by default.
 pref("plugin.defaultXpi.state", 2);
 
 // Flash is enabled by default, and Java is click-to-activate by default on
 // all channels.
 pref("plugin.state.flash", 2);
@@ -840,19 +838,16 @@ pref("plugin.state.np_prsnl", 2);
 #endif
 #ifdef XP_MACOSX
 pref("plugin.state.personalplugin", 2);
 #endif
 #ifdef UNIX_BUT_NOT_MAC
 pref("plugin.state.libplugins", 2);
 #endif
 
-// display door hanger if flash not installed
-pref("plugins.notifyMissingFlash", true);
-
 #ifdef XP_MACOSX
 pref("browser.preferences.animateFadeIn", true);
 #else
 pref("browser.preferences.animateFadeIn", false);
 #endif
 
 // Toggles between the two Preferences implementations, pop-up window and in-content
 #ifdef NIGHTLY_BUILD
--- a/browser/base/content/browser-loop.js
+++ b/browser/base/content/browser-loop.js
@@ -27,16 +27,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
     openCallPanel: function(event) {
       let callback = iframe => {
         iframe.addEventListener("DOMContentLoaded", function documentDOMLoaded() {
           iframe.removeEventListener("DOMContentLoaded", documentDOMLoaded, true);
           injectLoopAPI(iframe.contentWindow);
         }, true);
       };
 
+      // Used to clear the temporary "login" state from the button.
+      Services.obs.notifyObservers(null, "loop-status-changed", null);
+
       PanelFrame.showPopup(window, event.target, "loop", null,
                            "about:looppanel", null, callback);
     },
 
     /**
      * Triggers the initialization of the loop service.  Called by
      * delayedStartup.
      */
@@ -64,22 +67,34 @@ XPCOMUtils.defineLazyModuleGetter(this, 
       Services.obs.removeObserver(this, "loop-status-changed");
     },
 
     // Implements nsIObserver
     observe: function(subject, topic, data) {
       if (topic != "loop-status-changed") {
         return;
       }
-      this.updateToolbarState();
+      this.updateToolbarState(data);
     },
 
-    updateToolbarState: function() {
+    /**
+     * Updates the toolbar/menu-button state to reflect Loop status.
+     *
+     * @param {string} [aReason] Some states are only shown if
+     *                           a related reason is provided.
+     *
+     *                 aReason="login": Used after a login is completed
+     *                   successfully. This is used so the state can be
+     *                   temporarily shown until the next state change.
+     */
+    updateToolbarState: function(aReason = null) {
       let state = "";
       if (MozLoopService.errors.size) {
         state = "error";
+      } else if (aReason == "login" && MozLoopService.userProfile) {
+        state = "active";
       } else if (MozLoopService.doNotDisturb) {
         state = "disabled";
       }
       this.toolbarButton.node.setAttribute("state", state);
     },
   };
 })();
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -1,16 +1,14 @@
 # -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 # 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/.
 
 var gPluginHandler = {
-  PREF_NOTIFY_MISSING_FLASH: "plugins.notifyMissingFlash",
-  PREF_HIDE_MISSING_PLUGINS_NOTIFICATION: "plugins.hideMissingPluginsNotification",
   PREF_SESSION_PERSIST_MINUTES: "plugin.sessionPermissionNow.intervalInMinutes",
   PREF_PERSISTENT_DAYS: "plugin.persistentPermissionAlways.intervalInDays",
   MESSAGES: [
     "PluginContent:ShowClickToPlayNotification",
     "PluginContent:RemoveNotification",
     "PluginContent:UpdateHiddenPluginUI",
     "PluginContent:HideNotificationBar",
     "PluginContent:ShowInstallNotification",
@@ -88,104 +86,16 @@ var gPluginHandler = {
 #ifdef MOZ_CRASHREPORTER
   get CrashSubmit() {
     delete this.CrashSubmit;
     Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
     return this.CrashSubmit;
   },
 #endif
 
-  supportedPlugins: {
-    "mimetypes": {
-      "application/x-shockwave-flash": "flash",
-      "application/futuresplash": "flash",
-      "application/x-java-.*": "java",
-      "application/x-director": "shockwave",
-      "application/(sdp|x-(mpeg|rtsp|sdp))": "quicktime",
-      "audio/(3gpp(2)?|AMR|aiff|basic|mid(i)?|mp4|mpeg|vnd\.qcelp|wav|x-(aiff|m4(a|b|p)|midi|mpeg|wav))": "quicktime",
-      "image/(pict|png|tiff|x-(macpaint|pict|png|quicktime|sgi|targa|tiff))": "quicktime",
-      "video/(3gpp(2)?|flc|mp4|mpeg|quicktime|sd-video|x-mpeg)": "quicktime",
-      "application/x-unknown": "test",
-    },
-
-    "plugins": {
-      "flash": {
-        "displayName": "Flash",
-        "installWINNT": true,
-        "installDarwin": true,
-        "installLinux": true,
-      },
-      "java": {
-        "displayName": "Java",
-        "installWINNT": true,
-        "installDarwin": true,
-        "installLinux": true,
-      },
-      "shockwave": {
-        "displayName": "Shockwave",
-        "installWINNT": true,
-        "installDarwin": true,
-      },
-      "quicktime": {
-        "displayName": "QuickTime",
-        "installWINNT": true,
-      },
-      "test": {
-        "displayName": "Test plugin",
-        "installWINNT": true,
-        "installLinux": true,
-        "installDarwin": true,
-      }
-    }
-  },
-
-  nameForSupportedPlugin: function (aMimeType) {
-    for (let type in this.supportedPlugins.mimetypes) {
-      let re = new RegExp(type);
-      if (re.test(aMimeType)) {
-        return this.supportedPlugins.mimetypes[type];
-      }
-    }
-    return null;
-  },
-
-  canInstallThisMimeType: function (aMimeType) {
-    let os = Services.appinfo.OS;
-    let pluginName = this.nameForSupportedPlugin(aMimeType);
-    if (pluginName && "install" + os in this.supportedPlugins.plugins[pluginName]) {
-      return true;
-    }
-    return false;
-  },
-
-  newPluginInstalled : function(event) {
-    // browser elements are anonymous so we can't just use target.
-    var browser = event.originalTarget;
-    // clear the plugin list, now that at least one plugin has been installed
-    browser.missingPlugins = null;
-
-    var notificationBox = gBrowser.getNotificationBox(browser);
-    var notification = notificationBox.getNotificationWithValue("missing-plugins");
-    if (notification)
-      notificationBox.removeNotification(notification);
-
-    // reload the browser to make the new plugin show.
-    browser.reload();
-  },
-
-  // Callback for user clicking on a missing (unsupported) plugin.
-  installSinglePlugin: function (pluginInfo) {
-    var missingPlugins = new Map();
-    missingPlugins.set(pluginInfo.mimetype, pluginInfo);
-
-    openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
-               "PFSWindow", "chrome,centerscreen,resizable=yes",
-               {plugins: missingPlugins, browser: gBrowser.selectedBrowser});
-  },
-
   // Callback for user clicking on a disabled plugin
   managePlugins: function () {
     BrowserOpenAddonsMgr("addons://list/plugin");
   },
 
   // Callback for user clicking on the link in a click-to-play plugin
   // (where the plugin has an update)
   openPluginUpdatePage: function () {
@@ -207,76 +117,16 @@ var gPluginHandler = {
     browser.reload();
   },
 
   // Callback for user clicking the help icon
   openHelpPage: function () {
     openHelpLink("plugin-crashed", false);
   },
 
-  showInstallNotification: function (browser, pluginInfo) {
-    let hideMissingPluginsNotification =
-      Services.prefs.getBoolPref(this.PREF_HIDE_MISSING_PLUGINS_NOTIFICATION);
-    if (hideMissingPluginsNotification) {
-      return false;
-    }
-
-    if (!browser.missingPlugins)
-      browser.missingPlugins = new Map();
-
-    browser.missingPlugins.set(pluginInfo.mimetype, pluginInfo);
-
-    // only show notification for small subset of plugins
-    let mimetype = pluginInfo.mimetype.split(";")[0];
-    if (!this.canInstallThisMimeType(mimetype))
-      return false;
-
-    let pluginIdentifier = this.nameForSupportedPlugin(mimetype);
-    if (!pluginIdentifier)
-      return false;
-
-    let displayName = this.supportedPlugins.plugins[pluginIdentifier].displayName;
-
-    // don't show several notifications
-    let notification = PopupNotifications.getNotification("plugins-not-found", browser);
-    if (notification)
-      return true;
-
-    let messageString = gNavigatorBundle.getString("installPlugin.message");
-    let mainAction = {
-      label: gNavigatorBundle.getFormattedString("installPlugin.button.label",
-                                                 [displayName]),
-      accessKey: gNavigatorBundle.getString("installPlugin.button.accesskey"),
-      callback: function () {
-        openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
-                   "PFSWindow", "chrome,centerscreen,resizable=yes",
-                   {plugins: browser.missingPlugins, browser: browser});
-      }
-    };
-    let secondaryActions = null;
-    let options = { dismissed: true };
-
-    let showForFlash = Services.prefs.getBoolPref(this.PREF_NOTIFY_MISSING_FLASH);
-    if (pluginIdentifier == "flash" && showForFlash) {
-      let prefNotifyMissingFlash = this.PREF_NOTIFY_MISSING_FLASH;
-      secondaryActions = [{
-        label: gNavigatorBundle.getString("installPlugin.ignoreButton.label"),
-        accessKey: gNavigatorBundle.getString("installPlugin.ignoreButton.accesskey"),
-        callback: function () {
-          Services.prefs.setBoolPref(prefNotifyMissingFlash, false);
-        }
-      }];
-      options.dismissed = false;
-    }
-    PopupNotifications.show(browser, "plugins-not-found",
-                            messageString, "plugin-install-notification-icon",
-                            mainAction, secondaryActions, options);
-    return true;
-  },
-
   _clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) {
     if (event == "showing") {
       Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_SHOWN")
         .add(!this.options.primaryPlugin);
       // Histograms always start at 0, even though our data starts at 1
       let histogramCount = this.options.pluginData.size - 1;
       if (histogramCount > 4) {
         histogramCount = 4;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -769,18 +769,16 @@ function gKeywordURIFixup({ target: brow
 var gBrowserInit = {
   delayedStartupFinished: false,
 
   onLoad: function() {
     var mustLoadSidebar = false;
 
     gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
 
-    gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
-
     Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
 
     window.addEventListener("AppCommand", HandleAppCommandEvent, true);
 
     // These routines add message listeners. They must run before
     // loading the frame script to ensure that we don't miss any
     // message sent between when the frame script is loaded and when
     // the listener is registered.
@@ -6075,18 +6073,20 @@ function GetSearchFieldBookmarkData(node
       }
     }
   }
 
   var postData;
 
   if (isURLEncoded)
     postData = formData.join("&");
-  else
-    spec += "?" + formData.join("&");
+  else {
+    let separator = spec.contains("?") ? "&" : "?";
+    spec += separator + formData.join("&");
+  }
 
   return {
     spec: spec,
     title: title,
     description: description,
     postData: postData,
     charSet: charset
   };
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -718,17 +718,16 @@
                 <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
-                <image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="bad-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="bad-content-unblocked-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webRTC-shareMicrophone-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webRTC-sharingMicrophone-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webRTC-shareScreen-notification-icon" class="notification-anchor-icon" role="button"/>
                 <image id="webRTC-sharingScreen-notification-icon" class="notification-anchor-icon" role="button"/>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -921,17 +921,17 @@ nsContextMenu.prototype = {
   },
 
   // Open clicked-in frame in the same window.
   showOnlyThisFrame: function() {
     var doc = this.target.ownerDocument;
     var frameURL = doc.location.href;
 
     urlSecurityCheck(frameURL,
-                     this._unremotePrincipal(this.browser.contentPrincipal),
+                     this.browser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     var referrer = doc.referrer;
     openUILinkIn(frameURL, "current", { disallowInheritPrincipal: true,
                                         referrerURI: referrer ? makeURI(referrer) : null });
   },
 
   reload: function(event) {
     if (this.onSocial) {
@@ -982,45 +982,45 @@ nsContextMenu.prototype = {
   viewImageInfo: function() {
     BrowserPageInfo(this.target.ownerDocument.defaultView.top.document,
                     "mediaTab", this.target);
   },
 
   viewImageDesc: function(e) {
     var doc = this.target.ownerDocument;
     urlSecurityCheck(this.imageDescURL,
-                     this._unremotePrincipal(this.browser.contentPrincipal),
+                     this.browser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     openUILink(this.imageDescURL, e, { disallowInheritPrincipal: true,
                              referrerURI: doc.documentURIObject });
   },
 
   viewFrameInfo: function() {
     BrowserPageInfo(this.target.ownerDocument);
   },
 
   reloadImage: function(e) {
     urlSecurityCheck(this.mediaURL,
-                     this._unremotePrincipal(this.browser.contentPrincipal),
+                     this.browser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
 
     if (this.target instanceof Ci.nsIImageLoadingContent)
       this.target.forceReload();
   },
 
   // Change current window to the URL of the image, video, or audio.
   viewMedia: function(e) {
     var viewURL;
 
     if (this.onCanvas)
       viewURL = this.target.toDataURL();
     else {
       viewURL = this.mediaURL;
       urlSecurityCheck(viewURL,
-                       this._unremotePrincipal(this.browser.contentPrincipal),
+                       this.browser.contentPrincipal,
                        Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     }
 
     var doc = this.target.ownerDocument;
     openUILink(viewURL, e, { disallowInheritPrincipal: true,
                              referrerURI: doc.documentURIObject });
   },
 
@@ -1053,17 +1053,17 @@ nsContextMenu.prototype = {
 
   leaveDOMFullScreen: function() {
     document.mozCancelFullScreen();
   },
 
   // Change current window to the URL of the background image.
   viewBGImage: function(e) {
     urlSecurityCheck(this.bgImageURL,
-                     this._unremotePrincipal(this.browser.contentPrincipal),
+                     this.browser.contentPrincipal,
                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
     var doc = this.target.ownerDocument;
     openUILink(this.bgImageURL, e, { disallowInheritPrincipal: true,
                                      referrerURI: doc.documentURIObject });
   },
 
   disableSetDesktopBackground: function() {
     // Disable the Set as Desktop Background menu item if we're still trying
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -757,20 +757,16 @@
                 // failed URI (particularly for SSL errors). However, don't clear the value
                 // if the error page's URI is about:blank, because that causes complete
                 // loss of urlbar contents for invalid URI errors (see bug 867957).
                 if (this.mBrowser.userTypedClear > 0 ||
                     ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
                      aLocation.spec != "about:blank"))
                   this.mBrowser.userTypedValue = null;
 
-                // Clear out the missing plugins list since it's related to the
-                // previous location.
-                this.mBrowser.missingPlugins = null;
-
                 if (this.mTabBrowser.isFindBarInitialized(this.mTab)) {
                   let findBar = this.mTabBrowser.getFindBar(this.mTab);
 
                   // Close the Find toolbar if we're in old-style TAF mode
                   if (findBar.findMode != findBar.FIND_NORMAL)
                     findBar.close();
 
                   // fix bug 253793 - turn off highlight when page changes
--- a/browser/base/content/test/general/browser_addKeywordSearch.js
+++ b/browser/base/content/test/general/browser_addKeywordSearch.js
@@ -29,16 +29,18 @@ function test() {
       doc.body.removeChild(form);
     }
 
     let testData = [
     /* baseURI, field name, expected */
       [ 'http://example.com/', 'q', 'http://example.com/?q=%s' ],
       [ 'http://example.com/new-path-here/', 'q', 'http://example.com/new-path-here/?q=%s' ],
       [ '', 'q', 'http://example.org/browser/browser/base/content/test/general/dummy_page.html?q=%s' ],
+      // Tests for proper behaviour when called on a form whose action contains a question mark.
+      [ 'http://example.com/search?oe=utf-8', 'q', 'http://example.com/search?oe=utf-8&q=%s' ],
     ]
 
     for (let data of testData) {
       check(data[0], data[1], data[2]);
     }
 
     // cleanup
     gBrowser.removeCurrentTab();
--- a/browser/base/content/test/plugins/browser_pluginnotification.js
+++ b/browser/base/content/test/plugins/browser_pluginnotification.js
@@ -56,17 +56,16 @@ TabOpenListener.prototype = {
 
 function test() {
   waitForExplicitFinish();
   SimpleTest.requestCompleteLog();
   requestLongerTimeout(2);
   registerCleanupFunction(function() {
     clearAllPluginPermissions();
     Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
-    Services.prefs.clearUserPref("plugins.hideMissingPluginsNotification");
   });
   Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
 
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in");
 
   var newTab = gBrowser.addTab();
   gBrowser.selectedTab = newTab;
@@ -107,58 +106,42 @@ function runAfterPluginBindingAttached(f
     }
     elems[0].clientTop;
     executeSoon(func);
   };
 }
 
 // Tests a page with an unknown plugin in it.
 function test1a() {
-  ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 1a, Should have displayed the missing plugin notification");
-  ok(gTestBrowser.missingPlugins, "Test 1a, Should be a missing plugin list");
-  ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 1a, Should know about application/x-unknown");
-  ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 1a, Should not know about application/x-test");
-
   var pluginNode = gTestBrowser.contentDocument.getElementById("unknown");
   ok(pluginNode, "Test 1a, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED, "Test 1a, plugin fallback type should be PLUGIN_UNSUPPORTED");
 
-  Services.prefs.setBoolPref("plugins.hideMissingPluginsNotification", true);
   prepareTest(runAfterPluginBindingAttached(test1b), gTestRoot + "plugin_unknown.html");
 }
 
 
 function test1b() {
-  ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 1b, Should not have displayed the missing plugin notification");
-  ok(!gTestBrowser.missingPlugins, "Test 1b, Should not be a missing plugin list");
-  Services.prefs.clearUserPref("plugins.hideMissingPluginsNotification");
-
   var plugin = getTestPlugin();
   ok(plugin, "Test 1b, Should have a test plugin");
   plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
   prepareTest(runAfterPluginBindingAttached(test2), gTestRoot + "plugin_test.html");
 }
 
 // Tests a page with a working plugin in it.
 function test2() {
-  ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 2, Should not have displayed the missing plugin notification");
-  ok(!gTestBrowser.missingPlugins, "Test 2, Should not be a missing plugin list");
-
   var plugin = getTestPlugin();
   ok(plugin, "Should have a test plugin");
   plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
   prepareTest(runAfterPluginBindingAttached(test3), gTestRoot + "plugin_test.html");
 }
 
 // Tests a page with a disabled plugin in it.
 function test3() {
-  ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 3, Should not have displayed the missing plugin notification");
-  ok(!gTestBrowser.missingPlugins, "Test 3, Should not be a missing plugin list");
-
   new TabOpenListener("about:addons", test4, prepareTest5);
 
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 3, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, "Test 3, plugin fallback type should be PLUGIN_DISABLED");
   var manageLink = gTestBrowser.contentDocument.getAnonymousElementByAttribute(pluginNode, "anonid", "managePluginsLink");
   ok(manageLink, "Test 3, found 'manage' link in plugin-problem binding");
@@ -180,64 +163,50 @@ function prepareTest5() {
       info("prepareTest5 callback");
       prepareTest(runAfterPluginBindingAttached(test5), gTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a page with a blocked plugin in it.
 function test5() {
   info("test5");
-  ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 5, Should not have displayed the missing plugin notification");
   let notification = PopupNotifications.getNotification("click-to-play-plugins");
   ok(notification, "Test 5: There should be a plugin notification for blocked plugins");
   ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default");
 
   notification.reshow();
   is(notification.options.pluginData.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
   ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
 
-  ok(!gTestBrowser.missingPlugins, "Test 5, Should not be a missing plugin list");
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 5, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED");
 
   prepareTest(runAfterPluginBindingAttached(test6), gTestRoot + "plugin_both.html");
 }
 
 // Tests a page with a blocked and unknown plugin in it.
 function test6() {
-  ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 6, Should have displayed the missing plugin notification");
-  ok(gTestBrowser.missingPlugins, "Test 6, Should be a missing plugin list");
-  ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 6, Should know about application/x-unknown");
-  ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 6, application/x-test should not be a missing plugin");
-
   prepareTest(runAfterPluginBindingAttached(test7), gTestRoot + "plugin_both2.html");
 }
 
 // Tests a page with a blocked and unknown plugin in it (alternate order to above).
 function test7() {
-  ok(PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 7, Should have displayed the missing plugin notification");
-  ok(gTestBrowser.missingPlugins, "Test 7, Should be a missing plugin list");
-  ok(gTestBrowser.missingPlugins.has("application/x-unknown"), "Test 7, Should know about application/x-unknown");
-  ok(!gTestBrowser.missingPlugins.has("application/x-test"), "Test 7, application/x-test should not be a missing plugin");
-
   var plugin = getTestPlugin();
   plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
   getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
     prepareTest(runAfterPluginBindingAttached(test8), gTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a page with a working plugin that is click-to-play
 function test8() {
-  ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 8, Should not have displayed the missing plugin notification");
-  ok(!gTestBrowser.missingPlugins, "Test 8, Should not be a missing plugin list");
   ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 8, Should have a click-to-play notification");
 
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 8, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 8, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
 
   prepareTest(runAfterPluginBindingAttached(test11a), gTestRoot + "plugin_test3.html");
@@ -344,18 +313,16 @@ function test15() {
 
 // Test 16 removed
 
 // Tests that mContentType is used for click-to-play plugins, and not the
 // inspected type.
 function test17() {
   var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(clickToPlayNotification, "Test 17, Should have a click-to-play notification");
-  var missingNotification = PopupNotifications.getNotification("missing-plugins", gTestBrowser);
-  ok(!missingNotification, "Test 17, Should not have a missing plugin notification");
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
   function() {
     prepareTest(runAfterPluginBindingAttached(test18a), gHttpTestRoot + "plugin_test.html");
   });
 }
 
 // Tests a vulnerable, updatable plugin
--- a/browser/base/content/test/plugins/browser_pluginplaypreview.js
+++ b/browser/base/content/test/plugins/browser_pluginplaypreview.js
@@ -183,17 +183,16 @@ function prepareTest(nextTest, url, skip
   gNextTest = nextTest;
   gNextTestSkip = skip;
   gTestBrowser.contentWindow.location = url;
 }
 
 // Tests a page with normal play preview registration (1/2)
 function test1a() {
   var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
-  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 1a, Should not have displayed the missing plugin notification");
   ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
 
   var pluginInfo = getTestPlugin();
   ok(pluginInfo, "Should have a test plugin");
 
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
--- a/browser/base/content/test/plugins/browser_pluginplaypreview2.js
+++ b/browser/base/content/test/plugins/browser_pluginplaypreview2.js
@@ -85,17 +85,16 @@ function prepareTest(nextTest, url, skip
   gNextTest = nextTest;
   gNextTestSkip = skip;
   gTestBrowser.contentWindow.location = url;
 }
 
 // Tests a page with normal play preview registration (1/2)
 function test1a() {
   var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
-  ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 1a, Should not have displayed the missing plugin notification");
   ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
 
   var pluginInfo = getTestPlugin();
   ok(pluginInfo, "Should have a test plugin");
 
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
--- a/browser/components/loop/LoopStorage.jsm
+++ b/browser/components/loop/LoopStorage.jsm
@@ -1,16 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
-Cu.importGlobalProperties(["indexedDB"]);
+// Make it possible to load LoopStorage.jsm in xpcshell tests
+try {
+  Cu.importGlobalProperties(["indexedDB"]);
+} catch (ex) {
+  // don't write this is out in xpcshell, since it's expected there
+  if (typeof window !== 'undefined' && "console" in window) {
+    console.log("Failed to import indexedDB; if this isn't a unit test," +
+                " something is wrong", ex);
+  }
+}
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
   const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
   return new EventEmitter();
 });
 
--- a/browser/components/loop/MozLoopAPI.jsm
+++ b/browser/components/loop/MozLoopAPI.jsm
@@ -110,16 +110,18 @@ function injectLoopAPI(targetWindow) {
   let ringerStopper;
   let appVersionInfo;
   let contactsAPI;
 
   let api = {
     /**
      * Gets an object with data that represents the currently
      * authenticated user's identity.
+     *
+     * @return null if user not logged in; profile object otherwise
      */
     userProfile: {
       enumerable: true,
       get: function() {
         if (!MozLoopService.userProfile)
           return null;
         let userProfile = Cu.cloneInto({
           email: MozLoopService.userProfile.email,
@@ -373,29 +375,31 @@ function injectLoopAPI(targetWindow) {
      *    {
      *      code: 401,
      *      errno: 401,
      *      error: "Request failed",
      *      message: "invalid token"
      *    }
      *  - {String} The body of the response.
      *
+     * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for
+     *                                        the request.  This is one of the
+     *                                        LOOP_SESSION_TYPE members
      * @param {String} path The path to make the request to.
      * @param {String} method The request method, e.g. 'POST', 'GET'.
      * @param {Object} payloadObj An object which is converted to JSON and
      *                            transmitted with the request.
      * @param {Function} callback Called when the request completes.
      */
     hawkRequest: {
       enumerable: true,
       writable: true,
-      value: function(path, method, payloadObj, callback) {
-        // XXX: Bug 1065153 - Should take a sessionType parameter instead of hard-coding GUEST
+      value: function(sessionType, path, method, payloadObj, callback) {
         // XXX Should really return a DOM promise here.
-        MozLoopService.hawkRequest(LOOP_SESSION_TYPE.GUEST, path, method, payloadObj).then((response) => {
+        MozLoopService.hawkRequest(sessionType, path, method, payloadObj).then((response) => {
           callback(null, response.body);
         }, hawkError => {
           // The hawkError.error property, while usually a string representing
           // an HTTP response status message, may also incorrectly be a native
           // error object that will cause the cloning function to fail.
           callback(Cu.cloneInto({
             error: (hawkError.error && typeof hawkError.error == "string")
                    ? hawkError.error : "Unexpected exception",
@@ -404,30 +408,37 @@ function injectLoopAPI(targetWindow) {
             errno: hawkError.errno,
           }, targetWindow));
         }).catch(Cu.reportError);
       }
     },
 
     LOOP_SESSION_TYPE: {
       enumerable: true,
-      writable: false,
-      value: function() {
-        return LOOP_SESSION_TYPE;
-      },
+      get: function() {
+        return Cu.cloneInto(LOOP_SESSION_TYPE, targetWindow);
+      }
     },
 
     logInToFxA: {
       enumerable: true,
       writable: true,
       value: function() {
         return MozLoopService.logInToFxA();
       }
     },
 
+    logOutFromFxA: {
+      enumerable: true,
+      writable: true,
+      value: function() {
+        return MozLoopService.logOutFromFxA();
+      }
+    },
+
     /**
      * Copies passed string onto the system clipboard.
      *
      * @param {String} str The string to copy
      */
     copyString: {
       enumerable: true,
       writable: true,
@@ -445,21 +456,31 @@ function injectLoopAPI(targetWindow) {
      *   - OS: The operating system the application is running on
      */
     appVersionInfo: {
       enumerable: true,
       get: function() {
         if (!appVersionInfo) {
           let defaults = Services.prefs.getDefaultBranch(null);
 
-          appVersionInfo = Cu.cloneInto({
-            channel: defaults.getCharPref("app.update.channel"),
-            version: appInfo.version,
-            OS: appInfo.OS
-          }, targetWindow);
+          // If the lazy getter explodes, we're probably loaded in xpcshell,
+          // which doesn't have what we need, so log an error.
+          try {
+            appVersionInfo = Cu.cloneInto({
+              channel: defaults.getCharPref("app.update.channel"),
+              version: appInfo.version,
+              OS: appInfo.OS
+            }, targetWindow);
+          } catch (ex) {
+            // only log outside of xpcshell to avoid extra message noise
+            if (typeof window !== 'undefined' && "console" in window) {
+              console.log("Failed to construct appVersionInfo; if this isn't " +
+                          "an xpcshell unit test, something is wrong", ex);
+            }
+          }
         }
         return appVersionInfo;
       }
     },
 
     /**
      * Composes an email via the external protocol service.
      *
@@ -505,27 +526,33 @@ function injectLoopAPI(targetWindow) {
 
   let contentObj = Cu.createObjectIn(targetWindow);
   Object.defineProperties(contentObj, api);
   Object.seal(contentObj);
   Cu.makeObjectPropsNormal(contentObj);
   Services.obs.addObserver(onStatusChanged, "loop-status-changed", false);
   Services.obs.addObserver(onDOMWindowDestroyed, "dom-window-destroyed", false);
 
-  targetWindow.navigator.wrappedJSObject.__defineGetter__("mozLoop", function() {
-    // We do this in a getter, so that we create these objects
-    // only on demand (this is a potential concern, since
-    // otherwise we might add one per iframe, and keep them
-    // alive for as long as the window is alive).
-    delete targetWindow.navigator.wrappedJSObject.mozLoop;
-    return targetWindow.navigator.wrappedJSObject.mozLoop = contentObj;
-  });
+  if ("navigator" in targetWindow) {
+    targetWindow.navigator.wrappedJSObject.__defineGetter__("mozLoop", function () {
+      // We do this in a getter, so that we create these objects
+      // only on demand (this is a potential concern, since
+      // otherwise we might add one per iframe, and keep them
+      // alive for as long as the window is alive).
+      delete targetWindow.navigator.wrappedJSObject.mozLoop;
+      return targetWindow.navigator.wrappedJSObject.mozLoop = contentObj;
+    });
 
-  // Handle window.close correctly on the panel and chatbox.
-  hookWindowCloseForPanelClose(targetWindow);
+    // Handle window.close correctly on the panel and chatbox.
+    hookWindowCloseForPanelClose(targetWindow);
+  } else {
+    // This isn't a window; but it should be a JS scope; used for testing
+    return targetWindow.mozLoop = contentObj;
+  }
+
 }
 
 function getChromeWindow(contentWin) {
   return contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
                    .getInterface(Ci.nsIWebNavigation)
                    .QueryInterface(Ci.nsIDocShellTreeItem)
                    .rootTreeItem
                    .QueryInterface(Ci.nsIInterfaceRequestor)
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -68,17 +68,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 
 // The current deferred for the registration process. This is set if in progress
 // or the registration was successful. This is null if a registration attempt was
 // unsuccessful.
 let gRegisteredDeferred = null;
 let gPushHandler = null;
 let gHawkClient = null;
-let gRegisteredLoopServer = false;
 let gLocalizedStrings =  null;
 let gInitializeTimer = null;
 let gFxAOAuthClientPromise = null;
 let gFxAOAuthClient = null;
 let gFxAOAuthTokenData = null;
 let gFxAOAuthProfile = null;
 let gErrors = new Map();
 
@@ -155,18 +154,18 @@ let MozLoopServiceInternal = {
    *
    * @param {Boolean} aFlag
    */
   set doNotDisturb(aFlag) {
     Services.prefs.setBoolPref("loop.do_not_disturb", Boolean(aFlag));
     this.notifyStatusChanged();
   },
 
-  notifyStatusChanged: function() {
-    Services.obs.notifyObservers(null, "loop-status-changed", null);
+  notifyStatusChanged: function(aReason = null) {
+    Services.obs.notifyObservers(null, "loop-status-changed", aReason);
   },
 
   /**
    * @param {String} errorType a key to identify the type of error. Only one
    *                           error of a type will be saved at a time.
    * @param {Object} error     an object describing the error in the format from Hawk errors
    */
   setError: function(errorType, error) {
@@ -287,16 +286,30 @@ let MozLoopServiceInternal = {
         gRegisteredDeferred.reject("session-token-wrong-size");
         gRegisteredDeferred = null;
         return false;
       }
     }
     return true;
   },
 
+
+  /**
+   * Clear the loop session token so we don't use it for Hawk Requests anymore.
+   *
+   * This should normally be used after unregistering with the server so it can
+   * clean up session state first.
+   *
+   * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request.
+   *                                        One of the LOOP_SESSION_TYPE members.
+   */
+  clearSessionToken: function(sessionType) {
+    Services.prefs.clearUserPref(this.getSessionTokenPrefName(sessionType));
+  },
+
   /**
    * Callback from MozLoopPushHandler - The push server has been registered
    * and has given us a push url.
    *
    * @param {String} pushUrl The push url given by the push server.
    */
   onPushRegistered: function(err, pushUrl) {
     if (err) {
@@ -309,17 +322,17 @@ let MozLoopServiceInternal = {
       // storeSessionToken could have rejected and nulled the promise if the token was malformed.
       if (!gRegisteredDeferred) {
         return;
       }
       gRegisteredDeferred.resolve();
       // No need to clear the promise here, everything was good, so we don't need
       // to re-register.
     }, (error) => {
-      Cu.reportError("Failed to register with Loop server: " + error.errno);
+      console.error("Failed to register with Loop server: ", error);
       gRegisteredDeferred.reject(error.errno);
       gRegisteredDeferred = null;
     });
   },
 
   /**
    * Registers with the Loop server either as a guest or a FxA user.
    *
@@ -344,31 +357,61 @@ let MozLoopServiceInternal = {
         if (error.code === 401 && error.errno === INVALID_AUTH_TOKEN) {
           if (this.urlExpiryTimeIsInFuture()) {
             // XXX Should this be reported to the user is a visible manner?
             Cu.reportError("Loop session token is invalid, all previously "
                            + "generated urls will no longer work.");
           }
 
           // Authorization failed, invalid token, we need to try again with a new token.
-          Services.prefs.clearUserPref(this.getSessionTokenPrefName(sessionType));
+          this.clearSessionToken(sessionType);
           if (retry) {
             return this.registerWithLoopServer(sessionType, pushUrl, false);
           }
         }
 
         // XXX Bubble the precise details up to the UI somehow (bug 1013248).
-        Cu.reportError("Failed to register with the loop server. error: " + error);
+        console.error("Failed to register with the loop server. Error: ", error);
         this.setError("registration", error);
         throw error;
       }
     );
   },
 
   /**
+   * Unregisters from the Loop server either as a guest or a FxA user.
+   *
+   * This is normally only wanted for FxA users as we normally want to keep the
+   * guest session with the device.
+   *
+   * @param {LOOP_SESSION_TYPE} sessionType The type of session e.g. guest or FxA
+   * @param {String} pushURL The push URL previously given by the push server.
+   *                         This may not be necessary to unregister in the future.
+   * @return {Promise} resolving when the unregistration request finishes
+   */
+  unregisterFromLoopServer: function(sessionType, pushURL) {
+    let unregisterURL = "/registration?simplePushURL=" + encodeURIComponent(pushURL);
+    return this.hawkRequest(sessionType, unregisterURL, "DELETE")
+      .then(() => {
+        MozLoopServiceInternal.clearSessionToken(sessionType);
+      },
+      error => {
+        // Always clear the registration token regardless of whether the server acknowledges the logout.
+        MozLoopServiceInternal.clearSessionToken(sessionType);
+        if (error.code === 401 && error.errno === INVALID_AUTH_TOKEN) {
+          // Authorization failed, invalid token. This is fine since it may mean we already logged out.
+          return;
+        }
+
+        console.error("Failed to unregister with the loop server. Error: ", error);
+        throw error;
+      });
+  },
+
+  /**
    * Callback from MozLoopPushHandler - A push notification has been received from
    * the server.
    *
    * @param {String} version The version information from the server.
    */
   onHandleNotification: function(version) {
     if (this.doNotDisturb) {
       return;
@@ -698,16 +741,21 @@ this.MozLoopService = {
     gInitializeTimerFunc = value;
   },
 
   /**
    * Initialized the loop service, and starts registration with the
    * push and loop servers.
    */
   initialize: function() {
+
+    // Do this here, rather than immediately after definition, so that we can
+    // stub out API functions for unit testing
+    Object.freeze(this);
+
     // Don't do anything if loop is not enabled.
     if (!Services.prefs.getBoolPref("loop.enabled") ||
         Services.prefs.getBoolPref("loop.throttled")) {
       return;
     }
 
     // If expiresTime is in the future then kick-off registration.
     if (MozLoopServiceInternal.urlExpiryTimeIsInFuture()) {
@@ -1014,31 +1062,55 @@ this.MozLoopService = {
       }));
     }).then(tokenData => {
       let client = new FxAccountsProfileClient({
         serverURL: gFxAOAuthClient.parameters.profile_uri,
         token: tokenData.access_token
       });
       client.fetchProfile().then(result => {
         gFxAOAuthProfile = result;
-        MozLoopServiceInternal.notifyStatusChanged();
+        MozLoopServiceInternal.notifyStatusChanged("login");
       }, error => {
         console.error("Failed to retrieve profile", error);
         gFxAOAuthProfile = null;
         MozLoopServiceInternal.notifyStatusChanged();
       });
       return tokenData;
     }).catch(error => {
       gFxAOAuthTokenData = null;
       gFxAOAuthProfile = null;
       throw error;
     });
   },
 
   /**
+   * Logs the user out from FxA.
+   *
+   * Gracefully handles if the user is already logged out.
+   *
+   * @return {Promise} that resolves when the FxA logout flow is complete.
+   */
+  logOutFromFxA: Task.async(function*() {
+    yield MozLoopServiceInternal.unregisterFromLoopServer(LOOP_SESSION_TYPE.FXA,
+                                                          gPushHandler.pushUrl);
+
+    gFxAOAuthTokenData = null;
+    gFxAOAuthProfile = null;
+
+    // Reset the client since the initial promiseFxAOAuthParameters() call is
+    // what creates a new session.
+    gFxAOAuthClient = null;
+    gFxAOAuthClientPromise = null;
+
+    // clearError calls notifyStatusChanged so should be done last when the
+    // state is clean.
+    MozLoopServiceInternal.clearError("registration");
+  }),
+
+  /**
    * Performs a hawk based request to the loop server.
    *
    * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request.
    *                                        One of the LOOP_SESSION_TYPE members.
    * @param {String} path The path to make the request to.
    * @param {String} method The request method, e.g. 'POST', 'GET'.
    * @param {Object} payloadObj An object which is converted to JSON and
    *                            transmitted with the request.
@@ -1047,9 +1119,8 @@ this.MozLoopService = {
    *        or is rejected with an error.  If the server response can be parsed
    *        as JSON and contains an 'error' property, the promise will be
    *        rejected with this JSON-parsed response.
    */
   hawkRequest: function(sessionType, path, method, payloadObj) {
     return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj);
   },
 };
-Object.freeze(this.MozLoopService);
--- a/browser/components/loop/content/js/client.js
+++ b/browser/components/loop/content/js/client.js
@@ -103,39 +103,47 @@ loop.Client = (function($) {
      * - callUrlData an object of the obtained call url data if successful:
      * -- callUrl: The url of the call
      * -- expiresAt: The amount of hours until expiry of the url
      *
      * @param  {string} nickname the nickname of the future caller
      * @param  {Function} cb Callback(err, callUrlData)
      */
     _requestCallUrlInternal: function(nickname, cb) {
-      this.mozLoop.hawkRequest("/call-url/", "POST", {callerId: nickname},
-                               function (error, responseText) {
-        if (error) {
-          this._telemetryAdd("LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS", false);
-          this._failureHandler(cb, error);
-          return;
-        }
-
-        try {
-          var urlData = JSON.parse(responseText);
+      var sessionType;
+      if (this.mozLoop.userProfile) {
+        sessionType = this.mozLoop.LOOP_SESSION_TYPE.FXA;
+      } else {
+        sessionType = this.mozLoop.LOOP_SESSION_TYPE.GUEST;
+      }
+      
+      this.mozLoop.hawkRequest(sessionType, "/call-url/", "POST",
+                               {callerId: nickname},
+        function (error, responseText) {
+          if (error) {
+            this._telemetryAdd("LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS", false);
+            this._failureHandler(cb, error);
+            return;
+          }
 
-          // This throws if the data is invalid, in which case only the failure
-          // telementry will be recorded.
-          var returnData = this._validate(urlData, expectedCallUrlProperties);
+          try {
+            var urlData = JSON.parse(responseText);
+
+            // This throws if the data is invalid, in which case only the failure
+            // telemetry will be recorded.
+            var returnData = this._validate(urlData, expectedCallUrlProperties);
 
-          this._telemetryAdd("LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS", true);
-          cb(null, returnData);
-        } catch (err) {
-          this._telemetryAdd("LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS", false);
-          console.log("Error requesting call info", err);
-          cb(err);
-        }
-      }.bind(this));
+            this._telemetryAdd("LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS", true);
+            cb(null, returnData);
+          } catch (err) {
+            this._telemetryAdd("LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS", false);
+            console.log("Error requesting call info", err);
+            cb(err);
+          }
+        }.bind(this));
     },
 
     /**
      * Block call URL based on the token identifier
      *
      * @param {string} token Conversation identifier used to block the URL
      * @param {function} cb Callback function used for handling an error
      *                      response. XXX The incoming call panel does not
@@ -149,35 +157,41 @@ loop.Client = (function($) {
           return;
         }
 
         this._deleteCallUrlInternal(token, cb);
       }.bind(this));
     },
 
     _deleteCallUrlInternal: function(token, cb) {
-      this.mozLoop.hawkRequest("/call-url/" + token, "DELETE", null,
-                               function (error, responseText) {
+      function deleteRequestCallback(error, responseText) {
         if (error) {
           this._failureHandler(cb, error);
           return;
         }
 
         try {
           cb(null);
         } catch (err) {
           console.log("Error deleting call info", err);
           cb(err);
         }
-      }.bind(this));
+      }
+
+      // XXX hard-coding of GUEST to be removed by 1065155
+      this.mozLoop.hawkRequest(this.mozLoop.LOOP_SESSION_TYPE.GUEST,
+                               "/call-url/" + token, "DELETE", null,
+                               deleteRequestCallback.bind(this));
     },
 
     /**
      * Requests a call URL from the Loop server. It will note the
-     * expiry time for the url with the mozLoop api.
+     * expiry time for the url with the mozLoop api.  It will select the
+     * appropriate hawk session to use based on whether or not the user
+     * is currently logged into a Firefox account profile.
      *
      * Callback parameters:
      * - err null on successful registration, non-null otherwise.
      * - callUrlData an object of the obtained call url data if successful:
      * -- callUrl: The url of the call
      * -- expiresAt: The amount of hours until expiry of the url
      *
      * @param  {String} simplepushUrl a registered Simple Push URL
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -216,17 +216,16 @@ loop.panel = (function(_, mozL10n) {
     },
 
     handleClickAccountEntry: function() {
       // XXX to be implemented
     },
 
     handleClickAuthEntry: function() {
       if (this._isSignedIn()) {
-        // XXX to be implemented - bug 979845
         navigator.mozLoop.logOutFromFxA();
       } else {
         navigator.mozLoop.logInToFxA();
       }
     },
 
     _isSignedIn: function() {
       return !!navigator.mozLoop.userProfile;
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -216,17 +216,16 @@ loop.panel = (function(_, mozL10n) {
     },
 
     handleClickAccountEntry: function() {
       // XXX to be implemented
     },
 
     handleClickAuthEntry: function() {
       if (this._isSignedIn()) {
-        // XXX to be implemented - bug 979845
         navigator.mozLoop.logOutFromFxA();
       } else {
         navigator.mozLoop.logInToFxA();
       }
     },
 
     _isSignedIn: function() {
       return !!navigator.mozLoop.userProfile;
--- a/browser/components/loop/test/desktop-local/client_test.js
+++ b/browser/components/loop/test/desktop-local/client_test.js
@@ -30,17 +30,22 @@ describe("loop.Client", function() {
     mozLoop = {
       getLoopCharPref: sandbox.stub()
         .returns(null)
         .withArgs("hawk-session-token")
         .returns(fakeToken),
       ensureRegistered: sinon.stub().callsArgWith(0, null),
       noteCallUrlExpiry: sinon.spy(),
       hawkRequest: sinon.stub(),
-      telemetryAdd: sinon.spy(),
+      LOOP_SESSION_TYPE: {
+        GUEST: 1,
+        FXA: 2
+      },
+      userProfile: null,
+      telemetryAdd: sinon.spy()
     };
     // Alias for clearer tests.
     hawkRequestStub = mozLoop.hawkRequest;
     client = new loop.Client({
       mozLoop: mozLoop
     });
   });
 
@@ -65,35 +70,36 @@ describe("loop.Client", function() {
         sinon.assert.calledWithExactly(callback, "offline");
       });
 
       it("should make a delete call to /call-url/{fakeToken}", function() {
         client.deleteCallUrl(fakeToken, callback);
 
         sinon.assert.calledOnce(hawkRequestStub);
         sinon.assert.calledWith(hawkRequestStub,
+                                mozLoop.LOOP_SESSION_TYPE.GUEST,
                                 "/call-url/" + fakeToken, "DELETE");
       });
 
       it("should call the callback with null when the request succeeds",
          function() {
 
            // Sets up the hawkRequest stub to trigger the callback with no error
            // and the url.
-           hawkRequestStub.callsArgWith(3, null);
+           hawkRequestStub.callsArgWith(4, null);
 
            client.deleteCallUrl(fakeToken, callback);
 
            sinon.assert.calledWithExactly(callback, null);
          });
 
       it("should send an error when the request fails", function() {
         // Sets up the hawkRequest stub to trigger the callback with
         // an error
-        hawkRequestStub.callsArgWith(3, fakeErrorRes);
+        hawkRequestStub.callsArgWith(4, fakeErrorRes);
 
         client.deleteCallUrl(fakeToken, callback);
 
         sinon.assert.calledOnce(callback);
         sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
           return /400.*invalid token/.test(err.message);
         }));
       });
@@ -114,64 +120,86 @@ describe("loop.Client", function() {
         sinon.assert.calledOnce(callback);
         sinon.assert.calledWithExactly(callback, "offline");
       });
 
       it("should post to /call-url/", function() {
         client.requestCallUrl("foo", callback);
 
         sinon.assert.calledOnce(hawkRequestStub);
-        sinon.assert.calledWith(hawkRequestStub,
-                                "/call-url/", "POST", {callerId: "foo"});
+        sinon.assert.calledWithExactly(hawkRequestStub, sinon.match.number,
+          "/call-url/", "POST", {callerId: "foo"}, sinon.match.func);
+      });
+
+      it("should send a sessionType of LOOP_SESSION_TYPE.GUEST when " +
+         "mozLoop.userProfile returns null", function() {
+        mozLoop.userProfile = null;
+
+        client.requestCallUrl("foo", callback);
+
+        sinon.assert.calledOnce(hawkRequestStub);
+        sinon.assert.calledWithExactly(hawkRequestStub,
+          mozLoop.LOOP_SESSION_TYPE.GUEST, "/call-url/", "POST",
+          {callerId: "foo"}, sinon.match.func);
+      });
+
+      it("should send a sessionType of LOOP_SESSION_TYPE.FXA when " +
+         "mozLoop.userProfile returns an object", function () {
+        mozLoop.userProfile = {};
+
+        client.requestCallUrl("foo", callback);
+
+        sinon.assert.calledOnce(hawkRequestStub);
+        sinon.assert.calledWithExactly(hawkRequestStub,
+          mozLoop.LOOP_SESSION_TYPE.FXA, "/call-url/", "POST",
+          {callerId: "foo"}, sinon.match.func);
       });
 
       it("should call the callback with the url when the request succeeds",
         function() {
           var callUrlData = {
             "callUrl": "fakeCallUrl",
             "expiresAt": 60
           };
 
           // Sets up the hawkRequest stub to trigger the callback with no error
           // and the url.
-          hawkRequestStub.callsArgWith(3, null,
-            JSON.stringify(callUrlData));
+          hawkRequestStub.callsArgWith(4, null, JSON.stringify(callUrlData));
 
           client.requestCallUrl("foo", callback);
 
           sinon.assert.calledWithExactly(callback, null, callUrlData);
         });
 
       it("should not update call url expiry when the request succeeds",
         function() {
           var callUrlData = {
             "callUrl": "fakeCallUrl",
             "expiresAt": 6000
           };
 
           // Sets up the hawkRequest stub to trigger the callback with no error
           // and the url.
-          hawkRequestStub.callsArgWith(3, null,
-            JSON.stringify(callUrlData));
+          hawkRequestStub.callsArgWith(4, null, JSON.stringify(callUrlData));
 
           client.requestCallUrl("foo", callback);
 
           sinon.assert.notCalled(mozLoop.noteCallUrlExpiry);
         });
 
       it("should call mozLoop.telemetryAdd when the request succeeds",
         function(done) {
           var callUrlData = {
             "callUrl": "fakeCallUrl",
             "expiresAt": 60
           };
 
           // Sets up the hawkRequest stub to trigger the callback with no error
           // and the url.
-          hawkRequestStub.callsArgWith(3, null,
+          hawkRequestStub.callsArgWith(4, null,
             JSON.stringify(callUrlData));
 
           client.requestCallUrl("foo", function(err) {
             expect(err).to.be.null;
 
             sinon.assert.calledOnce(mozLoop.telemetryAdd);
             sinon.assert.calledWith(mozLoop.telemetryAdd,
                                     "LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS",
@@ -179,44 +207,44 @@ describe("loop.Client", function() {
 
             done();
           });
         });
 
       it("should send an error when the request fails", function() {
         // Sets up the hawkRequest stub to trigger the callback with
         // an error
-        hawkRequestStub.callsArgWith(3, fakeErrorRes);
+        hawkRequestStub.callsArgWith(4, fakeErrorRes);
 
         client.requestCallUrl("foo", callback);
 
         sinon.assert.calledOnce(callback);
         sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
           return /400.*invalid token/.test(err.message);
         }));
       });
 
       it("should send an error if the data is not valid", function() {
         // Sets up the hawkRequest stub to trigger the callback with
         // an error
-        hawkRequestStub.callsArgWith(3, null, "{}");
+        hawkRequestStub.callsArgWith(4, null, "{}");
 
         client.requestCallUrl("foo", callback);
 
         sinon.assert.calledOnce(callback);
         sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
           return /Invalid data received/.test(err.message);
         }));
       });
 
       it("should call mozLoop.telemetryAdd when the request fails",
         function(done) {
           // Sets up the hawkRequest stub to trigger the callback with
           // an error
-          hawkRequestStub.callsArgWith(3, fakeErrorRes);
+          hawkRequestStub.callsArgWith(4, fakeErrorRes);
 
           client.requestCallUrl("foo", function(err) {
             expect(err).not.to.be.null;
 
             sinon.assert.calledOnce(mozLoop.telemetryAdd);
             sinon.assert.calledWith(mozLoop.telemetryAdd,
                                     "LOOP_CLIENT_CALL_URL_REQUESTS_SUCCESS",
                                     false);
--- a/browser/components/loop/test/mochitest/browser_fxa_login.js
+++ b/browser/components/loop/test/mochitest/browser_fxa_login.js
@@ -214,40 +214,66 @@ add_task(function* basicAuthorizationAnd
     oauth_uri: BASE_URL + "/oauth",
     profile_uri: BASE_URL + "/profile",
     state: "state",
   };
   yield promiseOAuthParamsSetup(BASE_URL, params);
 
   info("registering");
   mockPushHandler.pushUrl = "https://localhost/pushUrl/guest";
+  // Notification observed due to the error being cleared upon successful registration.
+  let statusChangedPromise = promiseObserverNotified("loop-status-changed");
   yield MozLoopService.register(mockPushHandler);
+  yield statusChangedPromise;
 
   // Normally the same pushUrl would be registered but we change it in the test
   // to be able to check for success on the second registration.
   mockPushHandler.pushUrl = "https://localhost/pushUrl/fxa";
 
+  statusChangedPromise = promiseObserverNotified("loop-status-changed");
   yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true});
+  yield statusChangedPromise;
   let loopDoc = document.getElementById("loop").contentDocument;
   let visibleEmail = loopDoc.getElementsByClassName("user-identity")[0];
   is(visibleEmail.textContent, "Guest", "Guest should be displayed on the panel when not logged in");
   is(MozLoopService.userProfile, null, "profile should be null before log-in");
+  let loopButton = document.getElementById("loop-call-button");
+  is(loopButton.getAttribute("state"), "", "state of loop button should be empty when not logged in");
 
   let tokenData = yield MozLoopService.logInToFxA();
-  yield promiseObserverNotified("loop-status-changed");
+  yield promiseObserverNotified("loop-status-changed", "login");
   ise(tokenData.access_token, "code1_access_token", "Check access_token");
   ise(tokenData.scope, "profile", "Check scope");
   ise(tokenData.token_type, "bearer", "Check token_type");
 
   is(MozLoopService.userProfile.email, "test@example.com", "email should exist in the profile data");
   is(MozLoopService.userProfile.uid, "1234abcd", "uid should exist in the profile data");
   is(visibleEmail.textContent, "test@example.com", "the email should be correct on the panel");
+  is(loopButton.getAttribute("state"), "active", "state of loop button should be active when logged in");
 
   let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
-  ise(registrationResponse.response.simplePushURL, "https://localhost/pushUrl/fxa", "Check registered push URL");
+  ise(registrationResponse.response.simplePushURL, "https://localhost/pushUrl/fxa",
+      "Check registered push URL");
+
+  let loopPanel = document.getElementById("loop-notification-panel");
+  loopPanel.hidePopup();
+  statusChangedPromise = promiseObserverNotified("loop-status-changed");
+  yield loadLoopPanel({loopURL: BASE_URL, stayOnline: true});
+  yield statusChangedPromise;
+  is(loopButton.getAttribute("state"), "", "state of loop button should return to empty after panel is opened");
+  loopPanel.hidePopup();
+
+  info("logout");
+  yield MozLoopService.logOutFromFxA();
+  checkLoggedOutState();
+  registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
+  ise(registrationResponse.response, null,
+      "Check registration was deleted on the server");
+  is(visibleEmail.textContent, "Guest", "Guest should be displayed on the panel again after logout");
+  is(MozLoopService.userProfile, null, "userProfile should be null after logout");
 });
 
 add_task(function* loginWithParams401() {
   resetFxA();
   let params = {
     client_id: "client_id",
     content_uri: BASE_URL + "/content",
     oauth_uri: BASE_URL + "/oauth",
@@ -263,16 +289,62 @@ add_task(function* loginWithParams401() 
     ok(false, "Promise should have rejected");
   },
   error => {
     ise(error.code, 401, "Check error code");
     ise(gFxAOAuthTokenData, null, "Check there is no saved token data");
   });
 });
 
+add_task(function* logoutWithIncorrectPushURL() {
+  resetFxA();
+  let pushURL = "http://www.example.com/";
+  mockPushHandler.pushUrl = pushURL;
+
+  // Create a fake FxA hawk session token
+  const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA);
+  Services.prefs.setCharPref(fxASessionPref, "X".repeat(HAWK_TOKEN_LENGTH));
+
+  yield MozLoopServiceInternal.registerWithLoopServer(LOOP_SESSION_TYPE.FXA, pushURL);
+  let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
+  ise(registrationResponse.response.simplePushURL, pushURL, "Check registered push URL");
+  mockPushHandler.pushUrl = "http://www.example.com/invalid";
+  let caught = false;
+  yield MozLoopService.logOutFromFxA().catch((error) => {
+    caught = true;
+  });
+  ok(caught, "Should have caught an error logging out with a mismatched push URL");
+  checkLoggedOutState();
+  registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
+  ise(registrationResponse.response.simplePushURL, pushURL, "Check registered push URL wasn't deleted");
+});
+
+add_task(function* logoutWithNoPushURL() {
+  resetFxA();
+  let pushURL = "http://www.example.com/";
+  mockPushHandler.pushUrl = pushURL;
+
+  // Create a fake FxA hawk session token
+  const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA);
+  Services.prefs.setCharPref(fxASessionPref, "X".repeat(HAWK_TOKEN_LENGTH));
+
+  yield MozLoopServiceInternal.registerWithLoopServer(LOOP_SESSION_TYPE.FXA, pushURL);
+  let registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
+  ise(registrationResponse.response.simplePushURL, pushURL, "Check registered push URL");
+  mockPushHandler.pushUrl = null;
+  let caught = false;
+  yield MozLoopService.logOutFromFxA().catch((error) => {
+    caught = true;
+  });
+  ok(caught, "Should have caught an error logging out without a push URL");
+  checkLoggedOutState();
+  registrationResponse = yield promiseOAuthGetRegistration(BASE_URL);
+  ise(registrationResponse.response.simplePushURL, pushURL, "Check registered push URL wasn't deleted");
+});
+
 add_task(function* loginWithRegistration401() {
   resetFxA();
   let params = {
     client_id: "client_id",
     content_uri: BASE_URL + "/content",
     oauth_uri: BASE_URL + "/oauth",
     profile_uri: BASE_URL + "/profile",
     state: "state",
--- a/browser/components/loop/test/mochitest/browser_toolbarbutton.js
+++ b/browser/components/loop/test/mochitest/browser_toolbarbutton.js
@@ -4,24 +4,74 @@
 /**
  * Test the toolbar button states.
  */
 
 "use strict";
 
 registerCleanupFunction(function*() {
   MozLoopService.doNotDisturb = false;
+  setInternalLoopGlobal("gFxAOAuthProfile", null);
   yield MozLoopServiceInternal.clearError("testing");
 });
 
 add_task(function* test_doNotDisturb() {
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
   yield MozLoopService.doNotDisturb = true;
   Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state");
   yield MozLoopService.doNotDisturb = false;
   Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is not in disabled state");
 });
 
+add_task(function* test_doNotDisturb_with_login() {
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+  yield MozLoopService.doNotDisturb = true;
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state");
+  setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
+  yield MozLoopServiceInternal.notifyStatusChanged("login");
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state");
+  yield loadLoopPanel();
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "disabled", "Check button is in disabled state after opening panel");
+  let loopPanel = document.getElementById("loop-notification-panel");
+  loopPanel.hidePopup();
+  yield MozLoopService.doNotDisturb = false;
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+  setInternalLoopGlobal("gFxAOAuthProfile", null);
+  yield MozLoopServiceInternal.notifyStatusChanged();
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+});
+
 add_task(function* test_error() {
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
   yield MozLoopServiceInternal.setError("testing", {});
   Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
   yield MozLoopServiceInternal.clearError("testing");
   Assert.notStrictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is not in error state");
 });
+
+add_task(function* test_error_with_login() {
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+  yield MozLoopServiceInternal.setError("testing", {});
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
+  setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
+  MozLoopServiceInternal.notifyStatusChanged("login");
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "error", "Check button is in error state");
+  yield MozLoopServiceInternal.clearError("testing");
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+  setInternalLoopGlobal("gFxAOAuthProfile", null);
+  MozLoopServiceInternal.notifyStatusChanged();
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+});
+
+add_task(function* test_active() {
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+  setInternalLoopGlobal("gFxAOAuthProfile", {email: "test@example.com", uid: "abcd1234"});
+  yield MozLoopServiceInternal.notifyStatusChanged("login");
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "active", "Check button is in active state");
+  yield loadLoopPanel();
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state after opening panel");
+  let loopPanel = document.getElementById("loop-notification-panel");
+  loopPanel.hidePopup();
+  setInternalLoopGlobal("gFxAOAuthProfile", null);
+  MozLoopServiceInternal.notifyStatusChanged();
+  Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state");
+});
+
--- a/browser/components/loop/test/mochitest/head.js
+++ b/browser/components/loop/test/mochitest/head.js
@@ -2,16 +2,21 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const HAWK_TOKEN_LENGTH = 64;
 const {
   LOOP_SESSION_TYPE,
   MozLoopServiceInternal,
 } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
 
+// Cache this value only once, at the beginning of a
+// test run, so that it doesn't pick up the offline=true
+// if offline mode is requested multiple times in a test run.
+const WAS_OFFLINE = Services.io.offline;
+
 var gMozLoopAPI;
 
 function promiseGetMozLoopAPI() {
   let deferred = Promise.defer();
   let loopPanel = document.getElementById("loop-notification-panel");
   let btn = document.getElementById("loop-call-button");
 
   // Wait for the popup to be shown, then we can get the iframe and
@@ -41,17 +46,21 @@ function promiseGetMozLoopAPI() {
   // Now we're setup, click the button.
   btn.click();
 
   // Remove the iframe after each test. This also avoids mochitest complaining
   // about leaks on shutdown as we intentionally hold the iframe open for the
   // life of the application.
   registerCleanupFunction(function() {
     loopPanel.hidePopup();
-    loopPanel.removeChild(document.getElementById(btn.getAttribute("notificationFrameId")));
+    let frameId = btn.getAttribute("notificationFrameId");
+    let frame = document.getElementById(frameId);
+    if (frame) {
+      loopPanel.removeChild(frame);
+    }
   });
 
   return deferred.promise;
 }
 
 /**
  * Loads the loop panel by clicking the button and waits for its open to complete.
  * It also registers
@@ -62,25 +71,24 @@ function loadLoopPanel(aOverrideOptions 
   // Set prefs to ensure we don't access the network externally.
   Services.prefs.setCharPref("services.push.serverURL", aOverrideOptions.pushURL || "ws://localhost/");
   Services.prefs.setCharPref("loop.server", aOverrideOptions.loopURL || "http://localhost/");
 
   // Turn off the network for loop tests, so that we don't
   // try to access the remote servers. If we want to turn this
   // back on in future, be careful to check for intermittent
   // failures.
-  let wasOffline = Services.io.offline;
   if (!aOverrideOptions.stayOnline) {
     Services.io.offline = true;
   }
 
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("services.push.serverURL");
     Services.prefs.clearUserPref("loop.server");
-    Services.io.offline = wasOffline;
+    Services.io.offline = WAS_OFFLINE;
   });
 
   // Turn off animations to make tests quicker.
   let loopPanel = document.getElementById("loop-notification-panel");
   loopPanel.setAttribute("animate", "false");
 
   // Now get the actual API.
   yield promiseGetMozLoopAPI();
@@ -105,34 +113,51 @@ function resetFxA() {
   global.gFxAOAuthClientPromise = null;
   global.gFxAOAuthClient = null;
   global.gFxAOAuthTokenData = null;
   global.gFxAOAuthProfile = null;
   const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA);
   Services.prefs.clearUserPref(fxASessionPref);
 }
 
+function setInternalLoopGlobal(aName, aValue) {
+  let global = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
+  global[aName] = aValue;
+}
+
+function checkLoggedOutState() {
+  let global = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
+  ise(global.gFxAOAuthClientPromise, null, "gFxAOAuthClientPromise should be cleared");
+  ise(global.gFxAOAuthProfile, null, "gFxAOAuthProfile should be cleared");
+  ise(global.gFxAOAuthClient, null, "gFxAOAuthClient should be cleared");
+  ise(global.gFxAOAuthTokenData, null, "gFxAOAuthTokenData should be cleared");
+  const fxASessionPref = MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.FXA);
+  ise(Services.prefs.getPrefType(fxASessionPref), Services.prefs.PREF_INVALID,
+      "FxA hawk session should be cleared anyways");
+}
+
 function promiseDeletedOAuthParams(baseURL) {
   let deferred = Promise.defer();
   let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
               createInstance(Ci.nsIXMLHttpRequest);
   xhr.open("DELETE", baseURL + "/setup_params", true);
   xhr.addEventListener("load", () => deferred.resolve(xhr));
   xhr.addEventListener("error", deferred.reject);
   xhr.send();
 
   return deferred.promise;
 }
 
-function promiseObserverNotified(aTopic) {
+function promiseObserverNotified(aTopic, aExpectedData = null) {
   let deferred = Promise.defer();
   Services.obs.addObserver(function onNotification(aSubject, aTopic, aData) {
     Services.obs.removeObserver(onNotification, aTopic);
-      deferred.resolve({subject: aSubject, data: aData});
-    }, aTopic, false);
+    is(aData, aExpectedData, "observer data should match expected data")
+    deferred.resolve({subject: aSubject, data: aData});
+  }, aTopic, false);
   return deferred.promise;
 }
 
 /**
  * Get the last registration on the test server.
  */
 function promiseOAuthGetRegistration(baseURL) {
   let deferred = Promise.defer();
--- a/browser/components/loop/test/mochitest/loop_fxa.sjs
+++ b/browser/components/loop/test/mochitest/loop_fxa.sjs
@@ -6,38 +6,44 @@
  */
 
 "use strict";
 
 const REQUIRED_PARAMS = ["client_id", "content_uri", "oauth_uri", "profile_uri", "state"];
 const HAWK_TOKEN_LENGTH = 64;
 
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.importGlobalProperties(["URL"]);
 
 /**
  * Entry point for HTTP requests.
  */
 function handleRequest(request, response) {
-  // Look at the query string but ignore past the encoded ? when deciding on the handler.
-  dump("loop_fxa.sjs request for: " + request.queryString + "\n");
-  switch (request.queryString.replace(/%3F.*/,"")) {
+  // Convert the query string to a path with a placeholder base of example.com
+  let url = new URL(request.queryString.replace(/%3F.*/,""), "http://www.example.com");
+  dump("loop_fxa.sjs request for: " + url.pathname + "\n");
+  switch (url.pathname) {
     case "/setup_params": // Test-only
       setup_params(request, response);
       return;
     case "/fxa-oauth/params":
       params(request, response);
       return;
-    case encodeURIComponent("/oauth/authorization"):
+    case "/" + encodeURIComponent("/oauth/authorization"):
       oauth_authorization(request, response);
       return;
     case "/fxa-oauth/token":
       token(request, response);
       return;
     case "/registration":
-      registration(request, response);
+      if (request.method == "DELETE") {
+        delete_registration(request, response);
+      } else {
+        registration(request, response);
+      }
       return;
     case "/get_registration": // Test-only
       get_registration(request, response);
       return;
     case "/profile/profile":
       profile(request, response);
       return;
   }
@@ -197,16 +203,41 @@ function registration(request, response)
     response.setStatusLine(request.httpVersion, 401, "Missing Hawk");
     response.write("401 Missing Hawk Authorization header");
     return;
   }
   setSharedState("/registration", body);
 }
 
 /**
+ * DELETE /registration
+ *
+ * Hawk Authorization headers are required.
+ */
+function delete_registration(request, response) {
+  if (!request.hasHeader("Authorization") ||
+      !request.getHeader("Authorization").startsWith("Hawk")) {
+    response.setStatusLine(request.httpVersion, 401, "Missing Hawk");
+    response.write("401 Missing Hawk Authorization header");
+    return;
+  }
+
+  // Do some query string munging due to the SJS file using a base with a trailing "?"
+  // making the path become a query parameter. This is because we aren't actually
+  // registering endpoints at the root of the hostname e.g. /registration.
+  let url = new URL(request.queryString.replace(/%3F.*/,""), "http://www.example.com");
+  let registration = JSON.parse(getSharedState("/registration"));
+  if (registration.simplePushURL == url.searchParams.get("simplePushURL")) {
+    setSharedState("/registration", "");
+  } else {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+  }
+}
+
+/**
  * GET /get_registration
  *
  * Used for testing purposes to check if registration succeeded by returning the POST body.
  */
 function get_registration(request, response) {
   response.setHeader("Content-Type", "application/json; charset=utf-8", false);
   response.write(getSharedState("/registration"));
 }
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/test/xpcshell/test_loopapi_hawk_request.js
@@ -0,0 +1,71 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Unit tests for the hawkRequest API
+ */
+
+"use strict";
+
+Cu.import("resource:///modules/loop/MozLoopAPI.jsm");
+
+let sandbox;
+function assertInSandbox(expr, msg_opt) {
+  Assert.ok(Cu.evalInSandbox(expr, sandbox), msg_opt);
+}
+
+sandbox = Cu.Sandbox("about:looppanel", { wantXrays: false } );
+injectLoopAPI(sandbox, true);
+
+add_task(function* hawk_session_scope_constants() {
+  assertInSandbox("typeof mozLoop.LOOP_SESSION_TYPE !== 'undefined'");
+
+  assertInSandbox("mozLoop.LOOP_SESSION_TYPE.GUEST === 1");
+
+  assertInSandbox("mozLoop.LOOP_SESSION_TYPE.FXA === 2");
+});
+
+function generateSessionTypeVerificationStub(desiredSessionType) {
+
+  function hawkRequestStub(sessionType, path, method, payloadObj, callback) {
+    return new Promise(function (resolve, reject) {
+      Assert.equal(desiredSessionType, sessionType);
+
+      resolve();
+    });
+  };
+
+  return hawkRequestStub;
+}
+
+const origHawkRequest = MozLoopService.oldHawkRequest;
+do_register_cleanup(function() {
+  MozLoopService.hawkRequest = origHawkRequest;
+});
+
+add_task(function* hawk_request_scope_passthrough() {
+
+  // add a stub that verifies the parameter we want
+  MozLoopService.hawkRequest =
+    generateSessionTypeVerificationStub(sandbox.mozLoop.LOOP_SESSION_TYPE.FXA);
+
+  // call mozLoop.hawkRequest, which calls MozLoopAPI.hawkRequest, which calls
+  // MozLoopService.hawkRequest
+  Cu.evalInSandbox(
+    "mozLoop.hawkRequest(mozLoop.LOOP_SESSION_TYPE.FXA," +
+                       " 'call-url/fakeToken', 'POST', {}, function() {})",
+    sandbox);
+
+  MozLoopService.hawkRequest =
+    generateSessionTypeVerificationStub(sandbox.mozLoop.LOOP_SESSION_TYPE.GUEST);
+
+  Cu.evalInSandbox(
+    "mozLoop.hawkRequest(mozLoop.LOOP_SESSION_TYPE.GUEST," +
+    " 'call-url/fakeToken', 'POST', {}, function() {})",
+    sandbox);
+
+});
+
+function run_test() {
+  run_next_test();
+}
--- a/browser/components/loop/test/xpcshell/xpcshell.ini
+++ b/browser/components/loop/test/xpcshell/xpcshell.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 head = head.js
 tail =
 firefox-appdir = browser
 
+[test_loopapi_hawk_request.js]
 [test_looppush_initialize.js]
 [test_loopservice_dnd.js]
 [test_loopservice_expiry.js]
 [test_loopservice_loop_prefs.js]
 [test_loopservice_initialize.js]
 [test_loopservice_locales.js]
 [test_loopservice_notification.js]
 [test_loopservice_registration.js]
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1475,21 +1475,17 @@ BrowserGlue.prototype = {
           currentset = currentset.replace(/(^|,)bookmarks-menu-button-container($|,)/,
                                           "$1bookmarks-menu-button$2");
           xulStore.setValue(BROWSER_DOCURL, "nav-bar", "currentset", currentset);
         }
       }
     }
 
     if (currentUIVersion < 13) {
-      try {
-        if (Services.prefs.getBoolPref("plugins.hide_infobar_for_missing_plugin"))
-          Services.prefs.setBoolPref("plugins.notifyMissingFlash", false);
-      }
-      catch (ex) {}
+      /* Obsolete */
     }
 
     if (currentUIVersion < 14) {
       // DOM Storage doesn't specially handle about: pages anymore.
       let path = OS.Path.join(OS.Constants.Path.profileDir,
                               "chromeappsstore.sqlite");
       OS.File.remove(path);
     }
--- a/browser/devtools/app-manager/app-projects.js
+++ b/browser/devtools/app-manager/app-projects.js
@@ -201,16 +201,24 @@ const AppProjects = {
       return store.object.projects[store.object.projects.length - 1];
     });
   },
 
   update: function (project) {
     return IDB.update(project);
   },
 
+  updateLocation: function(project, newLocation) {
+    return IDB.remove(project.location)
+              .then(() => {
+                project.location = newLocation;
+                return IDB.add(project);
+              });
+  },
+
   remove: function(location) {
     return IDB.remove(location).then(function () {
       let projects = store.object.projects;
       for (let i = 0; i < projects.length; i++) {
         if (projects[i].location == location) {
           projects.splice(i, 1);
           return;
         }
@@ -230,9 +238,8 @@ const AppProjects = {
   },
 
   store: store
 };
 
 EventEmitter.decorate(AppProjects);
 
 exports.AppProjects = AppProjects;
-
--- a/browser/devtools/app-manager/app-validator.js
+++ b/browser/devtools/app-manager/app-validator.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 let {Ci,Cu,CC} = require("chrome");
 const promise = require("devtools/toolkit/deprecated-sync-thenables");
 
 const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm");
 const {Services} = Cu.import("resource://gre/modules/Services.jsm");
+const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
 let XMLHttpRequest = CC("@mozilla.org/xmlextras/xmlhttprequest;1");
 let strings = Services.strings.createBundle("chrome://browser/locale/devtools/app-manager.properties");
 
 function AppValidator(project) {
   this.project = project;
   this.errors = [];
   this.warnings = [];
 }
@@ -46,50 +47,107 @@ AppValidator.prototype._getPackagedManif
 AppValidator.prototype._getPackagedManifestURL = function () {
   let manifestFile = this._getPackagedManifestFile();
   if (!manifestFile) {
     return null;
   }
   return Services.io.newFileURI(manifestFile).spec;
 };
 
+AppValidator.checkManifest = function(manifestURL) {
+  let deferred = promise.defer();
+  let error;
+
+  let req = new XMLHttpRequest();
+  req.overrideMimeType('text/plain');
+
+  try {
+    req.open("GET", manifestURL, true);
+  } catch(e) {
+    error = strings.formatStringFromName("validator.invalidManifestURL", [manifestURL], 1);
+    deferred.reject(error);
+    return deferred.promise;
+  }
+  req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
+
+  req.onload = function () {
+    let manifest = null;
+    try {
+      manifest = JSON.parse(req.responseText);
+    } catch(e) {
+      error = strings.formatStringFromName("validator.invalidManifestJSON", [e, manifestURL], 2);
+      deferred.reject(error);
+    }
+
+    deferred.resolve({manifest, manifestURL});
+  };
+
+  req.onerror = function () {
+    error = strings.formatStringFromName("validator.noAccessManifestURL", [req.statusText, manifestURL], 2);
+    deferred.reject(error);
+ };
+
+  try {
+    req.send(null);
+  } catch(e) {
+    error = strings.formatStringFromName("validator.noAccessManifestURL", [e, manifestURL], 2);
+    deferred.reject(error);
+  }
+
+  return deferred.promise;
+};
+
+AppValidator.findManifestAtOrigin = function(manifestURL) {
+  let fixedManifest = Services.io.newURI(manifestURL, null, null).prePath + '/manifest.webapp';
+  return AppValidator.checkManifest(fixedManifest);
+};
+
+AppValidator.findManifestPath = function(manifestURL) {
+  let deferred = promise.defer();
+
+  if (manifestURL.endsWith('manifest.webapp')) {
+    deferred.reject();
+  } else {
+    let fixedManifest = manifestURL + '/manifest.webapp';
+    deferred.resolve(AppValidator.checkManifest(fixedManifest));
+  }
+
+  return deferred.promise;
+};
+
+AppValidator.checkAlternateManifest = function(manifestURL) {
+  return Task.spawn(function*() {
+    let result;
+    try {
+      result = yield AppValidator.findManifestPath(manifestURL);
+    } catch(e) {
+      result = yield AppValidator.findManifestAtOrigin(manifestURL);
+    }
+
+    return result;
+  });
+};
+
 AppValidator.prototype._fetchManifest = function (manifestURL) {
   let deferred = promise.defer();
   this.manifestURL = manifestURL;
 
-  let req = new XMLHttpRequest();
-  req.overrideMimeType('text/plain');
-  try {
-    req.open("GET", manifestURL, true);
-  } catch(e) {
-    this.error(strings.formatStringFromName("validator.invalidManifestURL", [manifestURL], 1));
-    deferred.resolve(null);
-    return deferred.promise;
-  }
-  req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
-  req.onload = (function () {
-    let manifest = null;
-    try {
-      manifest = JSON.parse(req.responseText);
-    } catch(e) {
-      this.error(strings.formatStringFromName("validator.invalidManifestJSON", [e, manifestURL], 2));
-    }
-    deferred.resolve(manifest);
-  }).bind(this);
-  req.onerror = (function () {
-    this.error(strings.formatStringFromName("validator.noAccessManifestURL", [req.statusText, manifestURL], 2));
-    deferred.resolve(null);
-  }).bind(this);
-
-  try {
-    req.send(null);
-  } catch(e) {
-    this.error(strings.formatStringFromName("validator.noAccessManifestURL", [e, manifestURL], 2));
-    deferred.resolve();
-  }
+  AppValidator.checkManifest(manifestURL)
+              .then(({manifest, manifestURL}) => {
+                deferred.resolve(manifest);
+              }, error => {
+                AppValidator.checkAlternateManifest(manifestURL)
+                            .then(({manifest, manifestURL}) => {
+                              this.manifestURL = manifestURL;
+                              deferred.resolve(manifest);
+                            }, () => {
+                              this.error(error);
+                              deferred.resolve(null);
+                            });
+                });
 
   return deferred.promise;
 };
 
 AppValidator.prototype._getManifest = function () {
   let manifestURL;
   if (this.project.type == "packaged") {
     manifestURL = this._getPackagedManifestURL();
--- a/browser/devtools/app-manager/test/test_app_validator.html
+++ b/browser/devtools/app-manager/test/test_app_validator.html
@@ -35,22 +35,22 @@
 
       httpserver = new HttpServer();
       httpserver.start(-1);
       origin = "http://localhost:" + httpserver.identity.primaryPort + "/";
 
       next();
     }
 
-    function createHosted(path) {
+    function createHosted(path, manifestFile="/manifest.webapp") {
       let dirPath = getTestFilePath("validator/" + path);
       httpserver.registerDirectory("/", nsFile(dirPath));
       return new AppValidator({
         type: "hosted",
-        location: origin + "/manifest.webapp"
+        location: origin + manifestFile
       });
     }
 
     function createPackaged(path) {
       let dirPath = getTestFilePath("validator/" + path);
       return new AppValidator({
         type: "packaged",
         location: dirPath
@@ -149,16 +149,48 @@
           checkNoNameOrIcon(validator);
         });
       },
       function () {
         let validator = createPackaged("no-name-or-icon");
         validator.validate().then(() => {
           checkNoNameOrIcon(validator);
         });
+      },
+
+      // Test a regular URL instead of a direct link to the manifest
+      function () {
+        let validator = createHosted("valid", "/");
+        validator.validate().then(() => {
+          is(validator.warnings.length, 0, "manifest found got no warning");
+          is(validator.errors.length, 0, "manifest found got no error");
+
+          next();
+        });
+      },
+
+      // Test finding a manifest at origin's root
+      function () {
+        let validator = createHosted("valid", "/unexisting-dir");
+        validator.validate().then(() => {
+          is(validator.warnings.length, 0, "manifest found at origin root got no warning");
+          is(validator.errors.length, 0, "manifest found at origin root got no error");
+
+          next();
+        });
+      },
+
+      // Test priorization of manifest.webapp at provided location instead of a manifest located at origin's root
+      function() {
+        let validator = createHosted("valid", "/alsoValid");
+        validator.validate().then(() => {
+          is(validator.manifest.name, "valid at subfolder", "manifest at subfolder was used");
+
+          next();
+        });
       }
     ];
 
     function checkNoNameOrIcon(validator) {
       is(validator.errors.length, 1, "app with no name has an error");
       is(validator.errors[0],
          strings.GetStringFromName("validator.missNameManifestProperty"),
          "with expected message");
new file mode 100644
--- /dev/null
+++ b/browser/devtools/app-manager/test/validator/valid/alsoValid/manifest.webapp
@@ -0,0 +1,7 @@
+{
+  "name": "valid at subfolder",
+  "launch_path": "/home.html",
+  "icons": {
+    "128": "/icon.png"
+  }
+}
--- a/browser/devtools/projecteditor/lib/shells.js
+++ b/browser/devtools/projecteditor/lib/shells.js
@@ -28,16 +28,17 @@ var Shell = Class({
    * @param ProjectEditor host
    * @param Resource resource
    */
   initialize: function(host, resource) {
     this.host = host;
     this.doc = host.document;
     this.resource = resource;
     this.elt = this.doc.createElement("vbox");
+    this.elt.classList.add("view-project-detail");
     this.elt.shell = this;
 
     let constructor = this._editorTypeForResource();
 
     this.editor = constructor(this.host);
     this.editor.shell = this;
     this.editorAppended = this.editor.appended;
 
--- a/browser/devtools/timeline/test/browser_timeline_waterfall-generic.js
+++ b/browser/devtools/timeline/test/browser_timeline_waterfall-generic.js
@@ -46,23 +46,23 @@ let test = Task.async(function*() {
 
   ok($(".timeline-marker-container"),
     "A marker container should have been created.");
 
   // Test the markers sidebar (left).
 
   ok($$(".timeline-marker-sidebar").length,
     "Some marker sidebar nodes should have been created.");
-  ok($$(".timeline-marker-sidebar > .timeline-marker-bullet").length,
+  ok($$(".timeline-marker-sidebar:not(spacer) > .timeline-marker-bullet").length,
     "Some marker color bullets should have been created inside the sidebar.");
-  ok($$(".timeline-marker-sidebar > .timeline-marker-name").length,
+  ok($$(".timeline-marker-sidebar:not(spacer) > .timeline-marker-name").length,
     "Some marker name labels should have been created inside the sidebar.");
 
   // Test the markers waterfall (right).
 
   ok($$(".timeline-marker-waterfall").length,
     "Some marker waterfall nodes should have been created.");
-  ok($$(".timeline-marker-waterfall > .timeline-marker-bar").length,
+  ok($$(".timeline-marker-waterfall:not(spacer) > .timeline-marker-bar").length,
     "Some marker color bars should have been created inside the waterfall.");
 
   yield teardown(panel);
   finish();
 });
--- a/browser/devtools/webide/modules/app-manager.js
+++ b/browser/devtools/webide/modules/app-manager.js
@@ -614,17 +614,19 @@ exports.AppManager = AppManager = {
         project.errors = "";
         project.errorsCount = 0;
       }
 
       if (project.warningsCount && project.errorsCount) {
         project.validationStatus = "error warning";
       }
 
-      if (AppProjects.get(project.location)) {
+      if (project.type === "hosted" && project.location !== validation.manifestURL) {
+        yield AppProjects.updateLocation(project, validation.manifestURL);
+      } else if (AppProjects.get(project.location)) {
         yield AppProjects.update(project);
       }
 
       if (AppManager.selectedProject === project) {
         AppManager.update("project-validated");
       }
     });
   },
--- a/browser/devtools/webide/test/test_import.html
+++ b/browser/devtools/webide/test/test_import.html
@@ -40,24 +40,32 @@
 
             let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
             yield win.Cmds.importHostedApp(hostedAppManifest);
 
             project = win.AppManager.selectedProject;
             is(project.location, hostedAppManifest, "Location is valid");
             is(project.name, "hosted manifest name property", "name field has been updated");
 
+            yield nextTick();
+
+            hostedAppManifest = TEST_BASE + "/app";
+            yield win.Cmds.importHostedApp(hostedAppManifest);
+
+            project = win.AppManager.selectedProject;
+            ok(project.location.endsWith('manifest.webapp'), "The manifest was found and the project was updated");
+
             info("opening panel");
             yield win.Cmds.showProjectPanel();
             info("panel open");
 
             let panelNode = win.document.querySelector("#project-panel");
             let items = panelNode.querySelectorAll(".panel-item");
             // 3 controls, + 2 projects
-            is(items.length, 5, "5 projects in panel");
+            is(items.length, 6, "6 projects in panel");
             is(items[3].getAttribute("label"), "A name (in app directory)", "Panel label is correct");
             is(items[4].getAttribute("label"), "hosted manifest name property", "Panel label is correct");
 
             yield closeWebIDE(win);
 
             yield removeAllProjects();
 
             SimpleTest.finish();
@@ -66,9 +74,8 @@
           SimpleTest.finish();
         });
       }
 
 
     </script>
   </body>
 </html>
-
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -98,23 +98,16 @@ popupWarningDontShowFromMessage=Don't sh
 popupWarningDontShowFromLocationbar=Don't show info bar when pop-ups are blocked
 popupShowPopupPrefix=Show '%S'
 
 # Bad Content Blocker Doorhanger Notification
 # %S is brandShortName
 badContentBlocked.blocked.message=%S is blocking content on this page.
 badContentBlocked.notblocked.message=%S is not blocking any content on this page.
 
-# missing plugin installer
-installPlugin.message = Would you like to install the plugin needed to display the media on this page?
-installPlugin.button.label=Install %S
-installPlugin.button.accesskey=I
-installPlugin.ignoreButton.label=Don't ask again
-installPlugin.ignoreButton.accesskey=N
-
 crashedpluginsMessage.title=The %S plugin has crashed.
 crashedpluginsMessage.reloadButton.label=Reload page
 crashedpluginsMessage.reloadButton.accesskey=R
 crashedpluginsMessage.submitButton.label=Submit a crash report
 crashedpluginsMessage.submitButton.accesskey=S
 crashedpluginsMessage.learnMore=Learn More…
 
 # Keyword fixup messages
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -328,30 +328,17 @@ PluginContent.prototype = {
 
     let shouldShowNotification = false;
     switch (eventType) {
       case "PluginCrashed":
         this.pluginInstanceCrashed(plugin, event);
         break;
 
       case "PluginNotFound": {
-        let installable = this.showInstallNotification(plugin, eventType);
-        let contentWindow = plugin.ownerDocument.defaultView;
-        // For non-object plugin tags, register a click handler to install the
-        // plugin. Object tags can, and often do, deal with that themselves,
-        // so don't stomp on the page developers toes.
-        if (installable && !(plugin instanceof contentWindow.HTMLObjectElement)) {
-          let installStatus = this.getPluginUI(plugin, "installStatus");
-          installStatus.setAttribute("installable", "true");
-          let iconStatus = this.getPluginUI(plugin, "icon");
-          iconStatus.setAttribute("installable", "true");
-
-          let installLink = this.getPluginUI(plugin, "installPluginLink");
-          this.addLinkClickCallback(installLink, "installSinglePlugin", plugin);
-        }
+        /* NOP */
         break;
       }
 
       case "PluginBlocklisted":
       case "PluginOutdated":
         shouldShowNotification = true;
         break;
 
@@ -466,23 +453,16 @@ PluginContent.prototype = {
       return;
 
     if (playPlugin)
       objLoadingContent.playPlugin();
     else
       objLoadingContent.cancelPlayPreview();
   },
 
-  // Callback for user clicking on a missing (unsupported) plugin.
-  installSinglePlugin: function (plugin) {
-    this.global.sendAsyncMessage("PluginContent:InstallSinglePlugin", {
-      pluginInfo: this._getPluginInfo(plugin),
-    });
-  },
-
   // Forward a link click callback to the chrome process.
   forwardCallback: function (name) {
     this.global.sendAsyncMessage("PluginContent:LinkClickCallback", { name: name });
   },
 
 #ifdef MOZ_CRASHREPORTER
   submitReport: function submitReport(pluginDumpID, browserDumpID, plugin) {
     let keyVals = {};
@@ -501,23 +481,16 @@ PluginContent.prototype = {
     });
   },
 #endif
 
   reloadPage: function () {
     this.global.content.location.reload();
   },
 
-  showInstallNotification: function (plugin) {
-    let [shown] = this.global.sendSyncMessage("PluginContent:ShowInstallNotification", {
-      pluginInfo: this._getPluginInfo(plugin),
-    });
-    return shown;
-  },
-
   // Event listener for click-to-play plugins.
   _handleClickToPlayEvent: function (plugin) {
     let doc = plugin.ownerDocument;
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     // guard against giving pluginHost.getPermissionStringForType a type
     // not associated with any known plugin
     if (!this.isKnownPlugin(objLoadingContent))
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -11,16 +11,18 @@ const {classes: Cc, interfaces: Ci, util
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
   "resource://gre/modules/LightweightThemeManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
   "resource://gre/modules/PermissionsUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ResetProfile",
+  "resource://gre/modules/ResetProfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
   "resource://gre/modules/UITelemetry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
   "resource:///modules/BrowserUITelemetry.jsm");
 
 
@@ -422,16 +424,22 @@ this.UITour = {
 
       case "showFirefoxAccounts": {
         // 'signup' is the only action that makes sense currently, so we don't
         // accept arbitrary actions just to be safe...
         // We want to replace the current tab.
         contentDocument.location.href = "about:accounts?action=signup&entrypoint=uitour";
         break;
       }
+
+      case "resetFirefox": {
+        // Open a reset profile dialog window.
+        ResetProfile.openConfirmationDialog(window);
+        break;
+      }
     }
 
     if (!this.originTabs.has(window))
       this.originTabs.set(window, new Set());
 
     this.originTabs.get(window).add(tab);
     tab.addEventListener("TabClose", this);
     tab.addEventListener("TabBecomingWindow", this);
--- a/browser/modules/test/browser.ini
+++ b/browser/modules/test/browser.ini
@@ -29,11 +29,13 @@ skip-if = e10s # Bug 941428 - UITour.jsm
 [browser_UITour_annotation_size_attributes.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
 [browser_UITour_panel_close_annotation.js]
 skip-if = true # Disabled due to frequent failures, bugs 1026310 and 1032137
 [browser_UITour_registerPageID.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_sync.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
+[browser_UITour_resetProfile.js]
+skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_taskbar_preview.js]
 run-if = os == "win"
 skip-if = e10s # Bug 666808 - AeroPeek support for e10s
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/browser_UITour_resetProfile.js
@@ -0,0 +1,39 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let gTestTab;
+let gContentAPI;
+let gContentWindow;
+
+Components.utils.import("resource:///modules/UITour.jsm");
+
+function test() {
+  UITourTest();
+}
+
+let tests = [
+  // Test that a reset profile dialog appears when "resetFirefox" event is triggered
+  function test_resetFirefox(done) {
+    let winWatcher = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+                     getService(Ci.nsIWindowWatcher);
+    winWatcher.registerNotification(function onOpen(subj, topic, data) {
+      if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
+        subj.addEventListener("load", function onLoad() {
+          subj.removeEventListener("load", onLoad);
+          if (subj.document.documentURI ==
+              "chrome://global/content/resetProfile.xul") {
+            winWatcher.unregisterNotification(onOpen);
+            ok(true, "Observed search manager window open");
+            is(subj.opener, window,
+               "Reset Firefox event opened a reset profile window.");
+            subj.close();
+            done();
+          }
+        });
+      }
+    });
+    gContentAPI.resetFirefox();
+  },
+];
--- a/browser/modules/test/uitour.js
+++ b/browser/modules/test/uitour.js
@@ -174,9 +174,13 @@ if (typeof Mozilla == 'undefined') {
 			configuration: configName,
 		});
 	};
 
 	Mozilla.UITour.showFirefoxAccounts = function() {
 		_sendEvent('showFirefoxAccounts');
 	};
 
+	Mozilla.UITour.resetFirefox = function() {
+		_sendEvent('resetFirefox');
+	};
+
 })();
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1127,20 +1127,16 @@ toolbarbutton[sdk-button="true"][cui-are
   width: 32px;
   height: 32px;
 }
 
 .popup-notification-icon[popupid="click-to-play-plugins"] {
   list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
 }
 
-.popup-notification-icon[popupid="plugins-not-found"] {
-  list-style-image: url(chrome://browser/skin/pluginInstall-64.png);
-}
-
 .popup-notification-icon[popupid="web-notifications"] {
   list-style-image: url(chrome://browser/skin/notification-64.png);
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
 }
@@ -1296,20 +1292,16 @@ toolbarbutton[sdk-button="true"][cui-are
 #plugins-notification-icon:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 #plugins-notification-icon:active {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
-#plugin-install-notification-icon {
-  list-style-image: url(chrome://browser/skin/pluginInstall-16.png);
-}
-
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
 
 #plugins-notification-icon.plugin-blocked[showing] {
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -49,18 +49,16 @@ browser.jar:
   skin/classic/browser/bad-content-unblocked-64.png
   skin/classic/browser/monitor.png
   skin/classic/browser/monitor_16-10.png
   skin/classic/browser/notification-16.png
   skin/classic/browser/notification-64.png
 * skin/classic/browser/pageInfo.css
   skin/classic/browser/pageInfo.png
   skin/classic/browser/page-livemarks.png
-  skin/classic/browser/pluginInstall-16.png
-  skin/classic/browser/pluginInstall-64.png
   skin/classic/browser/pointerLock-16.png
   skin/classic/browser/pointerLock-64.png
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/privatebrowsing-mask.png
   skin/classic/browser/reload-stop-go.png
   skin/classic/browser/searchbar.css
   skin/classic/browser/Secure.png
   skin/classic/browser/Security-broken.png
deleted file mode 100644
index a72a2839c99b5ff619a7cf83d5fb196f1edf5864..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 6a41aa05963f69c5edcee028d34443ab3e1a31f3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3643,25 +3643,16 @@ toolbarbutton.chevron > .toolbarbutton-m
     -moz-image-region: rect(0, 64px, 32px, 32px);
   }
 
   #plugins-notification-icon:active {
     -moz-image-region: rect(0, 96px, 32px, 64px);
   }
 }
 
-#plugin-install-notification-icon {
-  list-style-image: url(chrome://browser/skin/pluginInstall-16.png);
-}
-@media (min-resolution: 2dppx) {
-  #plugin-install-notification-icon {
-    list-style-image: url(chrome://browser/skin/pluginInstall-16@2x.png);
-  }
-}
-
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
 
 #plugins-notification-icon.plugin-blocked[showing] {
@@ -3977,25 +3968,16 @@ menulist.translate-infobar-element > .me
   width: 32px;
   height: 32px;
 }
 
 .popup-notification-icon[popupid="click-to-play-plugins"] {
   list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
 }
 
-.popup-notification-icon[popupid="plugins-not-found"] {
-  list-style-image: url(chrome://browser/skin/pluginInstall-64.png);
-}
-@media (min-resolution: 2dppx) {
-  .popup-notification-icon[popupid="plugins-not-found"] {
-    list-style-image: url(chrome://browser/skin/pluginInstall-64\@2x.png);
-  }
-}
-
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
 }
 
 .popup-progress-label,
 .popup-progress-meter {
   -moz-margin-start: 0;
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -77,20 +77,16 @@ browser.jar:
   skin/classic/browser/panel-expander-closed.png
   skin/classic/browser/panel-expander-closed@2x.png
   skin/classic/browser/panel-expander-open.png
   skin/classic/browser/panel-expander-open@2x.png
   skin/classic/browser/panel-plus-sign.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/page-livemarks@2x.png
   skin/classic/browser/pageInfo.css
-  skin/classic/browser/pluginInstall-16.png
-  skin/classic/browser/pluginInstall-16@2x.png
-  skin/classic/browser/pluginInstall-64.png
-  skin/classic/browser/pluginInstall-64@2x.png
   skin/classic/browser/pointerLock-16.png
   skin/classic/browser/pointerLock-16@2x.png
   skin/classic/browser/pointerLock-64.png
   skin/classic/browser/pointerLock-64@2x.png
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/privatebrowsing-mask.png
   skin/classic/browser/privatebrowsing-mask@2x.png
   skin/classic/browser/privatebrowsing-mask-short.png
deleted file mode 100644
index a72a2839c99b5ff619a7cf83d5fb196f1edf5864..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 6d064a3153455783dbddec50d824f5ccd46f7e81..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 6a41aa05963f69c5edcee028d34443ab3e1a31f3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 564641bf6c21ce354fc6aaef598bcad284489bba..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/shared/devtools/projecteditor/projecteditor.css
+++ b/browser/themes/shared/devtools/projecteditor/projecteditor.css
@@ -2,16 +2,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
  :root {
   color: #18191a;
 }
 
+.view-project-detail {
+  overflow: auto;
+}
+
 .plugin-hidden {
   display: none;
 }
 
 .arrow {
   -moz-appearance: treetwisty;
   width: 20px;
   height: 20px;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2147,20 +2147,16 @@ toolbarbutton.bookmark-item[dragover="tr
   width: 32px;
   height: 32px;
 }
 
 .popup-notification-icon[popupid="click-to-play-plugins"] {
   list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
 }
 
-.popup-notification-icon[popupid="plugins-not-found"] {
-  list-style-image: url(chrome://browser/skin/pluginInstall-64.png);
-}
-
 .popup-notification-icon[popupid="web-notifications"] {
   list-style-image: url(chrome://browser/skin/notification-64.png);
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
 }
@@ -2318,20 +2314,16 @@ toolbarbutton.bookmark-item[dragover="tr
 #plugins-notification-icon:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 #plugins-notification-icon:active {
   -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
-#plugin-install-notification-icon {
-  list-style-image: url(chrome://browser/skin/pluginInstall-16.png);
-}
-
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
 
 #plugins-notification-icon.plugin-blocked[showing] {
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -59,18 +59,16 @@ browser.jar:
         skin/classic/browser/bad-content-unblocked-64.png
         skin/classic/browser/monitor.png
         skin/classic/browser/monitor_16-10.png
         skin/classic/browser/notification-16.png
         skin/classic/browser/notification-64.png
         skin/classic/browser/pageInfo.css
         skin/classic/browser/pageInfo.png
         skin/classic/browser/page-livemarks.png                      (feeds/feedIcon16.png)
-        skin/classic/browser/pluginInstall-16.png
-        skin/classic/browser/pluginInstall-64.png
         skin/classic/browser/pointerLock-16.png
         skin/classic/browser/pointerLock-64.png
         skin/classic/browser/Privacy-16.png
         skin/classic/browser/Privacy-32.png
         skin/classic/browser/Privacy-48.png
         skin/classic/browser/privatebrowsing-mask-tabstrip-XPVista7.png
         skin/classic/browser/privatebrowsing-mask-titlebar-XPVista7.png
         skin/classic/browser/privatebrowsing-mask-titlebar-XPVista7-tall.png
@@ -482,18 +480,16 @@ browser.jar:
         skin/classic/aero/browser/bad-content-unblocked-64.png
         skin/classic/aero/browser/monitor.png
         skin/classic/aero/browser/monitor_16-10.png
         skin/classic/aero/browser/notification-16.png
         skin/classic/aero/browser/notification-64.png
         skin/classic/aero/browser/pageInfo.css
         skin/classic/aero/browser/pageInfo.png                       (pageInfo-aero.png)
         skin/classic/aero/browser/page-livemarks.png                 (feeds/feedIcon16-aero.png)
-        skin/classic/aero/browser/pluginInstall-16.png
-        skin/classic/aero/browser/pluginInstall-64.png
         skin/classic/aero/browser/pointerLock-16.png
         skin/classic/aero/browser/pointerLock-64.png
         skin/classic/aero/browser/Privacy-16.png                     (Privacy-16-aero.png)
         skin/classic/aero/browser/Privacy-32.png                     (Privacy-32-aero.png)
         skin/classic/aero/browser/privatebrowsing-mask-tabstrip.png
         skin/classic/aero/browser/privatebrowsing-mask-tabstrip-XPVista7.png
         skin/classic/aero/browser/privatebrowsing-mask-titlebar.png
         skin/classic/aero/browser/privatebrowsing-mask-titlebar-XPVista7.png
deleted file mode 100644
index a72a2839c99b5ff619a7cf83d5fb196f1edf5864..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 6a41aa05963f69c5edcee028d34443ab3e1a31f3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -81,16 +81,24 @@ SettingsLock.prototype = {
   },
 
   get closed() {
     return !this._open;
   },
 
   _closeHelper: function() {
     if (DEBUG) debug("closing lock " + this._id);
+    // sendMessage can get queued to run later in a thread via
+    // _closeHelper, but the SettingsManager may have died in between
+    // the time it was scheduled and the time it runs. Make sure our
+    // window is valid before sending, otherwise just ignore.
+    if (!this._settingsManager._window) {
+      if (DEBUG) debug("SettingsManager died, cannot send " + aMessageName + " message window principal.");
+      return;
+    }
     this._open = false;
     this._closeCalled = false;
     if (!this._requests || Object.keys(this._requests).length == 0) {
       if (DEBUG) debug("Requests exhausted, finalizing " + this._id);
       this._settingsManager.unregisterLock(this._id);
       this.sendMessage("Settings:Finalize", {lockID: this._id});
     } else {
       if (DEBUG) debug("Requests left: " + Object.keys(this._requests).length);
@@ -259,17 +267,17 @@ SettingsManager.prototype = {
     this._locks.push(lock._id);
     return lock;
   },
 
   unregisterLock: function(aLockID) {
     let lock_index = this._locks.indexOf(aLockID);
     if (lock_index != -1) {
       if (DEBUG) debug("Unregistering lock " + aLockID);
-      this._locks.splice(lock_index, -1);
+      this._locks.splice(lock_index, 1);
     }
   },
   
   receiveMessage: function(aMessage) {
     if (DEBUG) debug("Settings::receiveMessage: " + aMessage.name);
     let msg = aMessage.json;
 
     switch (aMessage.name) {
--- a/dom/settings/SettingsRequestManager.jsm
+++ b/dom/settings/SettingsRequestManager.jsm
@@ -575,19 +575,21 @@ let SettingsRequestManager = {
       if (DEBUG) debug("Lock no longer alive, cannot run tasks");
       return;
     }
     let currentTask = lock.tasks.shift();
     let promises = [];
     while (currentTask) {
       if (DEBUG) debug("Running Operation " + currentTask.operation);
       if (lock.finalizing) {
+        // We should really never get to this point, but if we do,
+        // fail every task that happens.
         Cu.reportError("Settings lock trying to run more tasks after finalizing. Ignoring tasks, but this is bad. Lock: " + aLockID);
-        continue;
-      }
+        currentTask.defer.reject("Cannot call new task after finalizing");
+      } else {
       let p;
       switch (currentTask.operation) {
         case "get":
           p = this.taskGet(currentTask);
           break;
         case "set":
           p = this.taskSet(currentTask);
           break;
@@ -602,16 +604,17 @@ let SettingsRequestManager = {
           p.reject("Invalid operation: " + currentTask.operation);
       }
       p.then(function(ret) {
         ret.task.defer.resolve("results" in ret ? ret.results : null);
       }.bind(currentTask), function(ret) {
         ret.task.defer.reject(ret.error);
       });
       promises.push(p);
+      }
       currentTask = lock.tasks.shift();
     }
   },
 
   consumeTasks: function() {
     if (this.settingsLockQueue.length == 0) {
       if (DEBUG) debug("Nothing to run!");
       return;
@@ -703,29 +706,31 @@ let SettingsRequestManager = {
       this.children.splice(index, 1);
       this.mmPrincipals.delete(aMsgMgr);
     }
     if (DEBUG) debug("Principal/MessageManager pairs left: " + this.mmPrincipals.size);
   },
 
   removeLock: function(aLockID) {
     if (DEBUG) debug("Removing lock " + aLockID);
+    if (this.lockInfo[aLockID]) {
     let transaction = this.lockInfo[aLockID]._transaction;
     if (transaction) {
       try {
         transaction.abort();
       } catch (e) {
         if (e.name == "InvalidStateError") {
           if (DEBUG) debug("Transaction for " + aLockID + " closed already");
         } else {
           throw e;
         }
       }
     }
     delete this.lockInfo[aLockID];
+    }
     let index = this.settingsLockQueue.indexOf(aLockID);
     if (index > -1) {
       this.settingsLockQueue.splice(index, 1);
     }
     // If index is 0, the lock we just removed was at the head of
     // the queue, so possibly queue the next lock if it's
     // consumable.
     if (index == 0) {
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -138,17 +138,19 @@ endif
 
 # We touch the target file before invoking Proguard so that Proguard's
 # outputs are fresher than the target, preventing a subsequent
 # invocation from thinking Proguard's outputs are stale.  This is safe
 # because Make removes the target file if any recipe command fails.
 .proguard.deps: $(ALL_JARS)
 	$(REPORT_BUILD)
 	@$(TOUCH) $@
-	java -jar $(ANDROID_SDK_ROOT)/tools/proguard/lib/proguard.jar \
+	java \
+		-Xmx512m -Xms128m \
+		-jar $(ANDROID_SDK_ROOT)/tools/proguard/lib/proguard.jar \
 		@$(topsrcdir)/mobile/android/config/proguard.cfg \
 		-optimizationpasses $(PROGUARD_PASSES) \
 		-injars $(subst ::,:,$(subst $(NULL) ,:,$(strip $(ALL_JARS)))) \
 		-outjars jars-proguarded \
 		-libraryjars $(library_jars)
 
 CLASSES_WITH_JNI= \
     org.mozilla.gecko.ANRReporter \
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -533,17 +533,17 @@ moz_native_devices_sources = [
     'ChromeCast.java',
     'GeckoMediaPlayer.java',
     'MediaPlayerManager.java',
 ]
 if CONFIG['MOZ_NATIVE_DEVICES']:
     gbjar.extra_jars += moz_native_devices_jars
     gbjar.sources += moz_native_devices_sources
 
-gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough']
+gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough', '-J-Xmx512m', '-J-Xms128m']
 
 noajar = add_java_jar('nineoldandroids')
 noajar.sources += [ thirdparty_source_dir + f for f in [
     'com/nineoldandroids/animation/Animator.java',
     'com/nineoldandroids/animation/AnimatorInflater.java',
     'com/nineoldandroids/animation/AnimatorListenerAdapter.java',
     'com/nineoldandroids/animation/AnimatorSet.java',
     'com/nineoldandroids/animation/ArgbEvaluator.java',
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -49,17 +49,16 @@ relativesrcdir toolkit/locales:
   locale/@AB_CD@/browser/overrides/commonDialogs.properties        (%chrome/global/commonDialogs.properties)
   locale/@AB_CD@/browser/overrides/intl.properties                 (%chrome/global/intl.properties)
   locale/@AB_CD@/browser/overrides/intl.css                        (%chrome/global/intl.css)
   locale/@AB_CD@/browser/overrides/passwordmgr.properties          (%chrome/passwordmgr/passwordmgr.properties)
   locale/@AB_CD@/browser/overrides/search/search.properties        (%chrome/search/search.properties)
   locale/@AB_CD@/browser/overrides/update/updates.properties       (%chrome/mozapps/update/updates.properties)
 # plugins
   locale/@AB_CD@/browser/overrides/plugins/plugins.dtd             (%chrome/mozapps/plugins/plugins.dtd)
-  locale/@AB_CD@/browser/overrides/plugins/plugins.properties      (%chrome/mozapps/plugins/plugins.properties)
 # about:support
   locale/@AB_CD@/browser/overrides/global/aboutSupport.dtd         (%chrome/global/aboutSupport.dtd)
   locale/@AB_CD@/browser/overrides/global/aboutSupport.properties  (%chrome/global/aboutSupport.properties)
 #about:crashes
   locale/@AB_CD@/browser/overrides/crashreporter/crashes.dtd         (%crashreporter/crashes.dtd)
   locale/@AB_CD@/browser/overrides/crashreporter/crashes.properties  (%crashreporter/crashes.properties)
 #about:mozilla
   locale/@AB_CD@/browser/overrides/global/mozilla.dtd                (%chrome/global/mozilla.dtd)
@@ -74,17 +73,16 @@ relativesrcdir toolkit/locales:
 % override chrome://global/locale/commonDialogs.properties chrome://browser/locale/overrides/commonDialogs.properties
 % override chrome://mozapps/locale/handling/handling.properties chrome://browser/locale/handling.properties
 % override chrome://global/locale/intl.properties chrome://browser/locale/overrides/intl.properties
 % override chrome://global/locale/intl.css chrome://browser/locale/overrides/intl.css
 % override chrome://passwordmgr/locale/passwordmgr.properties chrome://browser/locale/overrides/passwordmgr/passwordmgr.properties
 % override chrome://global/locale/search/search.properties chrome://browser/locale/overrides/search/search.properties
 % override chrome://mozapps/locale/update/updates.properties chrome://browser/locale/overrides/update/updates.properties
 % override chrome://mozapps/locale/plugins/plugins.dtd chrome://browser/locale/overrides/plugins/plugins.dtd
-% override chrome://mozapps/locale/plugins/plugins.properties chrome://browser/locale/overrides/plugins/plugins.properties
 % override chrome://global/locale/aboutSupport.dtd chrome://browser/locale/overrides/global/aboutSupport.dtd
 % override chrome://global/locale/aboutSupport.properties chrome://browser/locale/overrides/global/aboutSupport.properties
 % override chrome://global/locale/crashes.dtd chrome://browser/locale/overrides/crashreporter/crashes.dtd
 % override chrome://global/locale/crashes.properties chrome://browser/locale/overrides/crashreporter/crashes.properties
 % override chrome://global/locale/mozilla.dtd chrome://browser/locale/overrides/global/mozilla.dtd
 % override chrome://global/locale/aboutTelemetry.dtd chrome://browser/locale/overrides/global/aboutTelemetry.dtd
 % override chrome://global/locale/aboutTelemetry.properties chrome://browser/locale/overrides/global/aboutTelemetry.properties
 
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -451,17 +451,17 @@ class MochiRemote(Mochitest):
             if message['action'] == 'test_start':
                 start_found = True
             if 'expected' in message:
                 fail_found = True
         result = 0
         if fail_found:
             result = 1
         if not end_found:
-            self.log.error("Automation Error: Missing end of test marker (process crashed?)")
+            self.log.info("PROCESS-CRASH | Automation Error: Missing end of test marker (process crashed?)")
             result = 1
         return result
 
     def printLog(self):
         passed = 0
         failed = 0
         todo = 0
         incr = 1
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -87,16 +87,17 @@ let WebProgressListener = {
     // These properties can change even for a sub-frame navigation.
     json.canGoBack = docShell.canGoBack;
     json.canGoForward = docShell.canGoForward;
 
     if (json.isTopLevel) {
       json.documentURI = content.document.documentURIObject.spec;
       json.charset = content.document.characterSet;
       json.mayEnableCharacterEncodingMenu = docShell.mayEnableCharacterEncodingMenu;
+      json.principal = content.document.nodePrincipal;
     }
 
     sendAsyncMessage("Content:LocationChange", json, objects);
   },
 
   onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
     let json = this._setupJSON(aWebProgress, aRequest);
     let objects = this._setupObjects(aWebProgress);
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -442,17 +442,17 @@
         ]]></setter>
       </property>
 
       <property name="mayEnableCharacterEncodingMenu"
                 onget="return this.docShell.mayEnableCharacterEncodingMenu;"
                 readonly="true"/>
 
       <property name="contentPrincipal"
-                onget="return this.contentDocumentAsCPOW.nodePrincipal;"
+                onget="return this.contentDocument.nodePrincipal;"
                 readonly="true"/>
 
       <property name="showWindowResizer"
                 onset="if (val) this.setAttribute('showresizer', 'true');
                        else this.removeAttribute('showresizer');
                        return val;"
                 onget="return this.getAttribute('showresizer') == 'true';"/>
 
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -130,16 +130,22 @@
       <property name="contentWindowAsCPOW"
                 onget="return this._contentWindow"
                 readonly="true"/>
 
       <property name="contentDocument"
                 onget="return null"
                 readonly="true"/>
 
+      <field name="_contentPrincipal">null</field>
+
+      <property name="contentPrincipal"
+                onget="return this._contentPrincipal"
+                readonly="true"/>
+
       <property name="contentDocumentAsCPOW"
                 onget="return this.contentWindowAsCPOW ? this.contentWindowAsCPOW.document : null"
                 readonly="true"/>
 
       <field name="_syncHandler">null</field>
 
       <property name="syncHandler"
                 onget="return this._syncHandler"
--- a/toolkit/devtools/server/actors/memory.js
+++ b/toolkit/devtools/server/actors/memory.js
@@ -1,18 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { Cc, Ci, Cu } = require("chrome");
 let protocol = require("devtools/server/protocol");
-let { method, RetVal } = protocol;
+let { method, RetVal, Arg } = protocol;
 const { reportException } = require("devtools/toolkit/DevToolsUtils");
+loader.lazyRequireGetter(this, "events", "sdk/event/core");
 
 /**
  * A method decorator that ensures the actor is in the expected state before
  * proceeding. If the actor is not in the expected state, the decorated method
  * returns a rejected promise.
  *
  * @param String expectedState
  *        The expected state.
@@ -54,55 +55,317 @@ let MemoryActor = protocol.ActorClass({
 
   initialize: function(conn, parent) {
     protocol.Actor.prototype.initialize.call(this, conn);
     this.parent = parent;
     this._mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
                   .getService(Ci.nsIMemoryReporterManager);
     this.state = "detached";
     this._dbg = null;
+    this._framesToCounts = null;
+    this._framesToIndices = null;
+    this._framesToForms = null;
+
+    this._onWindowReady = this._onWindowReady.bind(this);
+
+    events.on(this.parent, "window-ready", this._onWindowReady);
   },
 
   destroy: function() {
+    events.off(this.parent, "window-ready", this._onWindowReady);
+
     this._mgr = null;
     if (this.state === "attached") {
       this.detach();
     }
     protocol.Actor.prototype.destroy.call(this);
   },
 
   /**
    * Attach to this MemoryActor.
    */
   attach: method(expectState("detached", function() {
     this.dbg.addDebuggees();
-    this.dbg.enabled = true;
     this.state = "attached";
   }), {
     request: {},
     response: {
       type: "attached"
     }
   }),
 
   /**
    * Detach from this MemoryActor.
    */
   detach: method(expectState("attached", function() {
-    this.dbg.removeAllDebuggees();
+    this._clearDebuggees();
     this.dbg.enabled = false;
     this._dbg = null;
     this.state = "detached";
   }), {
     request: {},
     response: {
       type: "detached"
     }
   }),
 
+  _clearDebuggees: function() {
+    if (this._dbg) {
+      if (this.dbg.memory.trackingAllocationSites) {
+        this.dbg.memory.drainAllocationsLog();
+      }
+      this._clearFrames();
+      this.dbg.removeAllDebuggees();
+    }
+  },
+
+  _initFrames: function() {
+    this._framesToCounts = new Map();
+    this._framesToIndices = new Map();
+    this._framesToForms = new Map();
+  },
+
+  _clearFrames: function() {
+    if (this.dbg.memory.trackingAllocationSites) {
+      this._framesToCounts.clear();
+      this._framesToCounts = null;
+      this._framesToIndices.clear();
+      this._framesToIndices = null;
+      this._framesToForms.clear();
+      this._framesToForms = null;
+    }
+  },
+
+  /**
+   * Handler for the parent actor's "window-ready" event.
+   */
+  _onWindowReady: function({ isTopLevel }) {
+    if (this.state == "attached") {
+      if (isTopLevel && this.dbg.memory.trackingAllocationSites) {
+        this._clearDebuggees();
+        this._initFrames();
+      }
+      this.dbg.addDebuggees();
+    }
+  },
+
+  /**
+   * Take a census of the heap. See js/src/doc/Debugger/Debugger.Memory.md for
+   * more information.
+   */
+  takeCensus: method(expectState("attached", function() {
+    return this.dbg.memory.takeCensus();
+  }), {
+    request: {},
+    response: RetVal("json")
+  }),
+
+  /**
+   * Start recording allocation sites.
+   */
+  startRecordingAllocations: method(expectState("attached", function() {
+    this._initFrames();
+    this.dbg.memory.trackingAllocationSites = true;
+  }), {
+    request: {},
+    response: {}
+  }),
+
+  /**
+   * Stop recording allocation sites.
+   */
+  stopRecordingAllocations: method(expectState("attached", function(shouldRecord) {
+    this.dbg.memory.trackingAllocationSites = false;
+    this._clearFrames();
+  }), {
+    request: {},
+    response: {}
+  }),
+
+  /**
+   * Get a list of the most recent allocations since the last time we got
+   * allocations, as well as a summary of all allocations since we've been
+   * recording.
+   *
+   * @returns Object
+   *          An object of the form:
+   *
+   *            {
+   *              allocations: [<index into "frames" below> ...],
+   *              frames: [
+   *                {
+   *                  line: <line number for this frame>,
+   *                  column: <column number for this frame>,
+   *                  source: <filename string for this frame>,
+   *                  functionDisplayName: <this frame's inferred function name function or null>,
+   *                  parent: <index into "frames">
+   *                }
+   *                ...
+   *              ],
+   *              counts: [
+   *                <number of allocations in frames[0]>,
+   *                <number of allocations in frames[1]>,
+   *                <number of allocations in frames[2]>,
+   *                ...
+   *              ]
+   *            }
+   *
+   *          Subsequent `getAllocations` request within the same recording and
+   *          tab navigation will always place the same stack frames at the same
+   *          indices as previous `getAllocations` requests in the same
+   *          recording. In other words, it is safe to use the index as a
+   *          unique, persistent id for its frame.
+   *
+   *          Additionally, the root node (null) is always at index 0.
+   *
+   *          Note that the allocation counts include "self" allocations only,
+   *          and don't account for allocations in child frames.
+   *
+   *          We use the indices into the "frames" array to avoid repeating the
+   *          description of duplicate stack frames both when listing
+   *          allocations, and when many stacks share the same tail of older
+   *          frames. There shouldn't be any duplicates in the "frames" array,
+   *          as that would defeat the purpose of this compression trick.
+   *
+   *          In the future, we might want to split out a frame's "source" and
+   *          "functionDisplayName" properties out the same way we have split
+   *          frames out with the "frames" array. While this would further
+   *          compress the size of the response packet, it would increase CPU
+   *          usage to build the packet, and it should, of course, be guided by
+   *          profiling and done only when necessary.
+   */
+  getAllocations: method(expectState("attached", function() {
+    const allocations = this.dbg.memory.drainAllocationsLog()
+    const packet = {
+      allocations: []
+    };
+
+    for (let stack of allocations) {
+      if (stack && Cu.isDeadWrapper(stack)) {
+        continue;
+      }
+
+      // Safe because SavedFrames are frozen/immutable.
+      let waived = Cu.waiveXrays(stack);
+
+      // Ensure that we have a form, count, and index for new allocations
+      // because we potentially haven't seen some or all of them yet. After this
+      // loop, we can rely on the fact that every frame we deal with already has
+      // its metadata stored.
+      this._assignFrameIndices(waived);
+      this._createFrameForms(waived);
+      this._countFrame(waived);
+
+      packet.allocations.push(this._framesToIndices.get(waived));
+    }
+
+    // Now that we are guaranteed to have a form for every frame, we know the
+    // size the "frames" property's array must be. We use that information to
+    // create dense arrays even though we populate them out of order.
+    const size = this._framesToForms.size;
+    packet.frames = Array(size).fill(null);
+    packet.counts = Array(size).fill(0);
+
+    // Populate the "frames" and "counts" properties.
+    for (let [stack, index] of this._framesToIndices) {
+      packet.frames[index] = this._framesToForms.get(stack);
+      packet.counts[index] = this._framesToCounts.get(stack) || 0;
+    }
+
+    return packet;
+  }), {
+    request: {},
+    response: RetVal("json")
+  }),
+
+  /**
+   * Assigns an index to the given frame and its parents, if an index is not
+   * already assigned.
+   *
+   * @param SavedFrame frame
+   *        A frame to assign an index to.
+   */
+  _assignFrameIndices: function(frame) {
+    if (this._framesToIndices.has(frame)) {
+      return;
+    }
+
+    if (frame) {
+      this._assignFrameIndices(frame.parent);
+    }
+
+    const index = this._framesToIndices.size;
+    this._framesToIndices.set(frame, index);
+  },
+
+  /**
+   * Create the form for the given frame, if one doesn't already exist.
+   *
+   * @param SavedFrame frame
+   *        A frame to create a form for.
+   */
+  _createFrameForms: function(frame) {
+    if (this._framesToForms.has(frame)) {
+      return;
+    }
+
+    let form = null;
+    if (frame) {
+      form = {
+        line: frame.line,
+        column: frame.column,
+        source: frame.source,
+        functionDisplayName: frame.functionDisplayName,
+        parent: this._framesToIndices.get(frame.parent)
+      };
+      this._createFrameForms(frame.parent);
+    }
+
+    this._framesToForms.set(frame, form);
+  },
+
+  /**
+   * Increment the allocation count for the provided frame.
+   *
+   * @param SavedFrame frame
+   *        The frame whose allocation count should be incremented.
+   */
+  _countFrame: function(frame) {
+    if (!this._framesToCounts.has(frame)) {
+      this._framesToCounts.set(frame, 1);
+    } else {
+      let count = this._framesToCounts.get(frame);
+      this._framesToCounts.set(frame, count + 1);
+    }
+  },
+
+  /*
+   * Force a browser-wide GC.
+   */
+  forceGarbageCollection: method(function() {
+    for (let i = 0; i < 3; i++) {
+      Cu.forceGC();
+    }
+  }, {
+    request: {},
+    response: {}
+  }),
+
+  /**
+   * Force an XPCOM cycle collection. For more information on XPCOM cycle
+   * collection, see
+   * https://developer.mozilla.org/en-US/docs/Interfacing_with_the_XPCOM_cycle_collector#What_the_cycle_collector_does
+   */
+  forceCycleCollection: method(function() {
+    Cu.forceCC();
+  }, {
+    request: {},
+    response: {}
+  }),
+
   /**
    * A method that returns a detailed breakdown of the memory consumption of the
    * associated window.
    *
    * @returns object
    */
   measure: method(function() {
     let result = {};
--- a/toolkit/devtools/server/tests/mochitest/chrome.ini
+++ b/toolkit/devtools/server/tests/mochitest/chrome.ini
@@ -69,13 +69,18 @@ skip-if = buildapp == 'mulet'
 [test_styles-matched.html]
 [test_styles-modify.html]
 [test_styles-svg.html]
 [test_unsafeDereference.html]
 [test_evalInGlobal-outerized_this.html]
 [test_inspector_getImageData.html]
 skip-if = buildapp == 'mulet'
 [test_memory.html]
+[test_memory_allocations_01.html]
+[test_memory_allocations_02.html]
+[test_memory_allocations_03.html]
 [test_memory_attach_01.html]
 [test_memory_attach_02.html]
+[test_memory_census.html]
+[test_memory_gc_01.html]
 [test_preference.html]
 [test_connectToChild.html]
 skip-if = buildapp == 'mulet'
--- a/toolkit/devtools/server/tests/mochitest/memory-helpers.js
+++ b/toolkit/devtools/server/tests/mochitest/memory-helpers.js
@@ -47,8 +47,14 @@ function startServerAndGetSelectedTabMem
 }
 
 function destroyServerAndFinish(client) {
   client.close(() => {
     DebuggerServer.destroy();
     SimpleTest.finish()
   });
 }
+
+function waitForTime(ms) {
+  return new Promise((resolve, reject) => {
+    setTimeout(resolve, ms);
+  });
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/mochitest/test_memory_allocations_01.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Bug 1067491 - Test recording allocations.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Memory monitoring actor test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src="memory-helpers.js" type="application/javascript;version=1.8"></script>
+<script>
+window.onload = function() {
+  SimpleTest.waitForExplicitFinish();
+
+  Task.spawn(function* () {
+    var { memory, client } = yield startServerAndGetSelectedTabMemory();
+    yield memory.attach();
+
+    yield memory.startRecordingAllocations();
+    ok(true, "Can start recording allocations");
+
+    // Allocate some objects.
+
+    var alloc1, alloc2, alloc3;
+    (function outer() {
+      (function middle() {
+        (function inner() {
+          alloc1 = {};                alloc1.line = Error().lineNumber;
+          alloc2 = [];                alloc2.line = Error().lineNumber;
+          alloc3 = new function() {}; alloc3.line = Error().lineNumber;
+        }());
+      }());
+    }());
+
+    var response = yield memory.getAllocations();
+
+    yield memory.stopRecordingAllocations();
+    ok(true, "Can stop recording allocations");
+
+    // Filter out allocations by library and test code, and get only the
+    // allocations that occurred in our test case above.
+
+    function isTestAllocation(alloc) {
+      var frame = response.frames[alloc];
+      return frame
+        && frame.functionDisplayName === "inner"
+        && (frame.line === alloc1.line
+            || frame.line === alloc2.line
+            || frame.line === alloc3.line);
+    }
+
+    var testAllocations = response.allocations.filter(isTestAllocation);
+    ok(testAllocations.length >= 3,
+       "Should find our 3 test allocations (plus some allocations for the error "
+       + "objects used to get line numbers)");
+
+    // For each of the test case's allocations, ensure that the parent frame
+    // indices are correct. Also test that we did get an allocation at each
+    // line we expected (rather than a bunch on the first line and none on the
+    // others, etc).
+
+    var expectedLines = new Set([alloc1.line, alloc2.line, alloc3.line]);
+
+    for (var alloc of testAllocations) {
+      var innerFrame = response.frames[alloc];
+      ok(innerFrame, "Should get the inner frame");
+      is(innerFrame.functionDisplayName, "inner");
+      expectedLines.delete(innerFrame.line);
+
+      var middleFrame = response.frames[innerFrame.parent];
+      ok(middleFrame, "Should get the middle frame");
+      is(middleFrame.functionDisplayName, "middle");
+
+      var outerFrame = response.frames[middleFrame.parent];
+      ok(outerFrame, "Should get the outer frame");
+      is(outerFrame.functionDisplayName, "outer");
+
+      // Not going to test the rest of the frames because they are Task.jsm
+      // and promise frames and it gets gross. Plus, I wouldn't want this test
+      // to start failing if they changed their implementations in a way that
+      // added or removed stack frames here.
+    }
+
+    is(expectedLines.size, 0,
+       "Should have found all the expected lines");
+
+    yield memory.detach();
+    destroyServerAndFinish(client);
+  });
+};
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/mochitest/test_memory_allocations_02.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Bug 1067491 - Test aggregating allocation counts.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Memory monitoring actor test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src="memory-helpers.js" type="application/javascript;version=1.8"></script>
+<script>
+window.onload = function() {
+  SimpleTest.waitForExplicitFinish();
+
+  Task.spawn(function* () {
+    var { memory, client } = yield startServerAndGetSelectedTabMemory();
+    yield memory.attach();
+
+    yield memory.startRecordingAllocations();
+    ok(true, "Can start recording allocations");
+
+    // Allocate some objects.
+
+    var allocs = [];
+    (function allocator() {
+      for (var i = 0; i < 10; i++) {
+        allocs.push({});
+      }
+    }());
+
+    var response = yield memory.getAllocations();
+
+    yield memory.stopRecordingAllocations();
+    ok(true, "Can stop recording allocations");
+
+    // Find the index of our 10 allocations, and then assert that it is in the
+    // `allocator` frame.
+
+    var index = 0;
+    var found = false;
+    for (var count of response.counts) {
+      if (count === 10) {
+        found = true;
+        break;
+      }
+      index++;
+    }
+    ok(found, "Should find the 10 allocations.");
+
+    is(response.frames[index].functionDisplayName, "allocator",
+       "Should have found the allocator frame.");
+
+    yield memory.detach();
+    destroyServerAndFinish(client);
+  });
+};
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/mochitest/test_memory_allocations_03.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Bug 1067491 - Test that frames keep the same index while we are recording.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Memory monitoring actor test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src="memory-helpers.js" type="application/javascript;version=1.8"></script>
+<script>
+window.onload = function() {
+  SimpleTest.waitForExplicitFinish();
+
+  Task.spawn(function* () {
+    var { memory, client } = yield startServerAndGetSelectedTabMemory();
+    yield memory.attach();
+
+    yield memory.startRecordingAllocations();
+
+    // Allocate twice with the exact same stack (hence setTimeout rather than
+    // allocating directly in the generator), but with getAllocations() calls in
+    // between.
+
+    var allocs = [];
+    function allocator() {
+      allocs.push({});
+    }
+
+    setTimeout(allocator, 1);
+    yield waitForTime(2);
+    var first = yield memory.getAllocations();
+
+    setTimeout(allocator, 1);
+    yield waitForTime(2);
+    var second = yield memory.getAllocations();
+
+    yield memory.stopRecordingAllocations();
+
+    // Assert that each frame in the first response has the same index in the
+    // second response. This isn't commutative, so we don't check that all
+    // of the second response's frames are the same in the first response,
+    // because there might be new allocations that happen after the first query
+    // but before the second.
+
+    function assertSameFrame(a, b) {
+      info("Checking frames at index " + i + ":");
+      info("  First frame = " + JSON.stringify(a, null, 4));
+      info("  Second frame = " + JSON.stringify(b, null, 4));
+
+      is(!!a, !!b);
+      if (!a || !b) {
+        return;
+      }
+
+      is(a.source, b.source);
+      is(a.line, b.line);
+      is(a.column, b.column);
+      is(a.functionDisplayName, b.functionDisplayName);
+      is(a.parent, b.parent);
+    }
+
+    for (var i = 0; i < first.frames.length; i++) {
+      assertSameFrame(first.frames[i], second.frames[i]);
+    }
+
+    yield memory.detach();
+    destroyServerAndFinish(client);
+  });
+};
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/mochitest/test_memory_census.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Bug 1067491 - Test taking a census over the RDP.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Memory monitoring actor test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src="memory-helpers.js" type="application/javascript;version=1.8"></script>
+<script>
+window.onload = function() {
+  SimpleTest.waitForExplicitFinish();
+
+  Task.spawn(function* () {
+    var { memory, client } = yield startServerAndGetSelectedTabMemory();
+    yield memory.attach();
+
+    var census = yield memory.takeCensus();
+    is(typeof census, "object");
+
+    yield memory.detach();
+    destroyServerAndFinish(client);
+  });
+};
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/mochitest/test_memory_gc_01.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Bug 1067491 - Test forcing a gc.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Memory monitoring actor test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src="memory-helpers.js" type="application/javascript;version=1.8"></script>
+<script>
+window.onload = function() {
+  SimpleTest.waitForExplicitFinish();
+
+  Task.spawn(function* () {
+    var { memory, client } = yield startServerAndGetSelectedTabMemory();
+
+    var objects = [];
+    for (var i = 0; i < 1000; i++) {
+      var o = {};
+      o[Math.random] = 1;
+      objects.push(o);
+    }
+
+    objects = null;
+    var { total: beforeGC } = yield memory.measure();
+
+    yield memory.forceGarbageCollection();
+    var { total: afterGC } = yield memory.measure();
+
+    ok(beforeGC > afterGC);
+
+    destroyServerAndFinish(client);
+  });
+};
+</script>
+</pre>
+</body>
+</html>
deleted file mode 100644
--- a/toolkit/locales/en-US/chrome/global/xpinstall/xpinstall.properties
+++ /dev/null
@@ -1,95 +0,0 @@
-# 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/.
-
-#--------------------------------------------------------------------
-#   Install Actions
-#--------------------------------------------------------------------
-InstallFile=Installing: %s
-InstallSharedFile=Installing Shared File: %s
-ReplaceFile=Replacing: %s
-ReplaceSharedFile=Replacing Shared File: %s
-SkipFile=Skipping: %s
-SkipSharedFile=Skipping Shared File: %s
-
-DeleteFile=Deleting file: %s
-DeleteComponent=Deleting component: %s
-
-Execute=Executing: %s
-ExecuteWithArgs=Executing: %s with argument: %s
-
-CopyFile=Copy File: %s to %s
-ExecuteFile=Execute File: %s
-ExecuteFileWithArgs=Execute File: %s with argument: %s
-MoveFile=Move File: %s to %s
-RenameFile=Rename File: %s to %s
-CreateFolder=Create Folder: %s
-RemoveFolder=Remove Folder: %s
-RenameFolder=Rename Folder: %s to %s
-WindowsShortcut=Windows Shortcut: %s
-MacAlias=Mac Alias: %s
-WindowsRegisterServer=Windows Register Server: %s
-UnknownFileOpCommand=Unknown file operation command!
-
-Patch=Patching: %s
-
-Uninstall=Uninstalling: %s
-
-RegSkin=Register Skin: %s
-RegLocale=Register Locale: %s
-RegContent=Register Content: %s
-RegPackage=Register Package: %s
-
-#--------------------------------------------------------------------
-#   Dialog Messages
-#--------------------------------------------------------------------
-
-ApplyNowSkin=Use this theme
-ApplyNowLocale=Use this locale
-
-ConfirmSkin=Install the theme "%1$S" from %2$S?
-ConfirmLocale=Install the locale "%1$S" from %2$S?
-
-OK=Install
-
-progress.queued=Queued
-progress.downloading=Downloading…
-progress.downloaded=Downloaded
-progress.installing=Installing…
-
-Unsigned=Unsigned
-
-#--------------------------------------------------------------------
-#   Miscellaneous
-#--------------------------------------------------------------------
-ERROR=ERROR
-
-error0=Success
-error999=Restart to complete
-error-202=Access denied
-error-203=Unexpected installation error\nReview the Error Console log for more details.
-error-204=Install script not found
-error-207=Not a valid install package
-error-208=Invalid argument
-error-210=User canceled
-error-214=Required file does not exist
-error-215=Read only
-error-218=AppleSingle extraction error
-error-219=Invalid path
-error-225=EXTRACTION_FAILED
-error-227=Canceled
-error-228=Download error
-error-229=Script error
-error-230=Already exists
-error-235=Out of space
-error-239=Chrome registration failed
-error-240=Unfinished install
-error-244=Unsupported package
-error-260=Signing could not be verified.
-error-261=Invalid file hash (possible download corruption)
-error-262=Unknown or invalid file hash type
-error-299=Out of memory
-
-# there are other error codes, either rare or obsolete,
-# that are not worth translating at this time.
-unknown.error=Unexpected error %S
--- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
@@ -1,32 +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/. -->
-<!ENTITY pluginWizard.title                                  "Plugin Finder Service">
-<!ENTITY pluginWizard.firstPage.title                        "Welcome to the &pluginWizard.title;">
-
-<!ENTITY pluginWizard.checkingForPlugins.description.label   "&brandShortName; is now checking for available plugins…">
-
-<!ENTITY pluginWizard.availablePluginsPage.title             "Available Plugin Downloads">
-<!ENTITY pluginWizard.availablePluginsPage.description.label "The following plugins are available:">
-<!ENTITY pluginWizard.availablePluginsPage.continueMsg.label "Press Next to install these plugins.">
-<!ENTITY pluginWizard.availablePluginsPage.installerUI       "Some plugins may require additional information from you during installation.">
-
-<!ENTITY pluginWizard.licensePage.title                      "Plugin Licenses">
-<!ENTITY pluginWizard.licensePage.accept.label               "I agree.">
-<!ENTITY pluginWizard.licensePage.deny.label                 "I do not agree (plugin will not be installed).">
-
-<!ENTITY pluginWizard.installPluginsPage.title               "Installing Plugins">
-<!ENTITY pluginWizard.installPluginsPage.description.label   "&brandShortName; is installing plugins…">
-
-<!ENTITY pluginWizard.finalPage.description.label            "&brandShortName; finished installing the missing plugins:">
-
-<!ENTITY pluginWizard.finalPage.moreInfo.label               "Find out more about Plugins or manually find missing plugins.">
-<!ENTITY pluginWizard.finalPage.restart.label                "&brandShortName; needs to be restarted for the plugin(s) to work.">
 
 <!-- LOCALIZATION NOTE (unsupportedPlatform.pre): Mobile only. Flash (the only plugin available on mobile)
      is not supported on some devices. Include a trailing space as needed. -->
 <!ENTITY unsupportedPlatform.pre                             "We're very sorry, but &brandShortName; can't play Flash on this device. ">
 <!-- LOCALIZATION NOTE (unsupportedPlatform.learnMore): Mobile only. This text is used to link to a SUMO page explaining why Flash is not
      supported on this device. Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale. -->
 <!ENTITY unsupportedPlatform.learnMore                       "Learn More…">
 <!-- LOCALIZATION NOTE (unsupportedPlatform.post): Mobile only. Include text here if needed for your locale. -->
@@ -35,17 +14,16 @@
 <!ENTITY missingPlugin                                       "A plugin is needed to display this content.">
 <!-- LOCALIZATION NOTE (tapToPlayPlugin): Mobile (used for touch interfaces) only has one type of plugin possible. -->
 <!ENTITY tapToPlayPlugin                                     "Tap here to activate plugin.">
 <!ENTITY clickToActivatePlugin                               "Activate plugin.">
 <!ENTITY checkForUpdates                                     "Check for updates…">
 <!ENTITY disabledPlugin                                      "This plugin is disabled.">
 <!ENTITY blockedPlugin.label                                 "This plugin has been blocked for your protection.">
 <!ENTITY hidePluginBtn.label                                 "Hide plugin">
-<!ENTITY installPlugin                                       "Install plugin…">
 <!ENTITY managePlugins                                       "Manage plugins…">
 
 <!-- LOCALIZATION NOTE (reloadPlugin.pre): include a trailing space as needed -->
 <!-- LOCALIZATION NOTE (reloadPlugin.middle): avoid leading/trailing spaces, this text is a link -->
 <!-- LOCALIZATION NOTE (reloadPlugin.post): include a starting space as needed -->
 <!ENTITY reloadPlugin.pre                                    "">
 <!ENTITY reloadPlugin.middle                                 "Reload the page">
 <!ENTITY reloadPlugin.post                                   " to try again.">
deleted file mode 100644
--- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.properties
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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/.
-
-pluginLicenseAgreement.label=To install %S, you need to agree to the following:
-
-pluginInstallation.download.start=Downloading %S…
-pluginInstallation.download.finish=Finished downloading %S.
-
-pluginInstallation.install.start=Installing %S…
-pluginInstallation.install.finish=Successfully installed %S.
-pluginInstallation.install.error=Failed to install %S (%S).
-
-pluginInstallation.complete=Finished installing plugins.
-
-pluginInstallationSummary.success=Installed
-pluginInstallationSummary.failed=Failed
-pluginInstallationSummary.licenseNotAccepted=License not accepted
-pluginInstallationSummary.notAvailable=Not Available
-pluginInstallationSummary.manualInstall.label=Manual Install
-pluginInstallationSummary.manualInstall.tooltip=Manually install the plugin.
-
-pluginInstallation.noPluginsFound=No suitable plugins were found.
-pluginInstallation.noPluginsInstalled=No plugins were installed.
-pluginInstallation.unknownPlugin=Unknown Plugin (%S)
-
-pluginInstallation.restart.label=Restart %S
-pluginInstallation.restart.accesskey=R
-pluginInstallation.close.label=Close
-pluginInstallation.close.accesskey=C
--- a/toolkit/locales/jar.mn
+++ b/toolkit/locales/jar.mn
@@ -67,17 +67,16 @@
   locale/@AB_CD@/global/tree.dtd                        (%chrome/global/tree.dtd)
   locale/@AB_CD@/global/textcontext.dtd                 (%chrome/global/textcontext.dtd)
   locale/@AB_CD@/global/videocontrols.dtd               (%chrome/global/videocontrols.dtd)
   locale/@AB_CD@/global/viewSource.dtd                  (%chrome/global/viewSource.dtd)
   locale/@AB_CD@/global/viewSource.properties           (%chrome/global/viewSource.properties)
   locale/@AB_CD@/global/webapps.properties              (%chrome/global/webapps.properties)
   locale/@AB_CD@/global/wizard.dtd                      (%chrome/global/wizard.dtd)
   locale/@AB_CD@/global/wizard.properties               (%chrome/global/wizard.properties)
-  locale/@AB_CD@/global/xpinstall/xpinstall.properties  (%chrome/global/xpinstall/xpinstall.properties)
   locale/@AB_CD@/global/crashes.dtd                     (%crashreporter/crashes.dtd)
   locale/@AB_CD@/global/crashes.properties              (%crashreporter/crashes.properties)
 % locale global-region @AB_CD@ %locale/@AB_CD@/global-region/
   locale/@AB_CD@/global-region/region.properties        (%chrome/global-region/region.properties)
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/
   locale/@AB_CD@/global-platform/mac/platformKeys.properties  (%chrome/global-platform/mac/platformKeys.properties)
   locale/@AB_CD@/global-platform/unix/platformKeys.properties (%chrome/global-platform/unix/platformKeys.properties)
   locale/@AB_CD@/global-platform/win/platformKeys.properties  (%chrome/global-platform/win/platformKeys.properties)
@@ -98,17 +97,16 @@
   locale/@AB_CD@/mozapps/extensions/selectAddons.properties       (%chrome/mozapps/extensions/selectAddons.properties)
   locale/@AB_CD@/mozapps/extensions/update.dtd                    (%chrome/mozapps/extensions/update.dtd)
   locale/@AB_CD@/mozapps/extensions/update.properties             (%chrome/mozapps/extensions/update.properties)
   locale/@AB_CD@/mozapps/extensions/newaddon.dtd                  (%chrome/mozapps/extensions/newaddon.dtd)
   locale/@AB_CD@/mozapps/extensions/newaddon.properties           (%chrome/mozapps/extensions/newaddon.properties)
   locale/@AB_CD@/mozapps/handling/handling.dtd                    (%chrome/mozapps/handling/handling.dtd)
   locale/@AB_CD@/mozapps/handling/handling.properties             (%chrome/mozapps/handling/handling.properties)
   locale/@AB_CD@/mozapps/plugins/plugins.dtd                      (%chrome/mozapps/plugins/plugins.dtd)
-  locale/@AB_CD@/mozapps/plugins/plugins.properties               (%chrome/mozapps/plugins/plugins.properties)
   locale/@AB_CD@/mozapps/preferences/changemp.dtd                 (%chrome/mozapps/preferences/changemp.dtd)
   locale/@AB_CD@/mozapps/preferences/removemp.dtd                 (%chrome/mozapps/preferences/removemp.dtd)
   locale/@AB_CD@/mozapps/preferences/preferences.properties       (%chrome/mozapps/preferences/preferences.properties)
   locale/@AB_CD@/mozapps/profile/createProfileWizard.dtd          (%chrome/mozapps/profile/createProfileWizard.dtd)
   locale/@AB_CD@/mozapps/profile/profileSelection.properties      (%chrome/mozapps/profile/profileSelection.properties)
   locale/@AB_CD@/mozapps/profile/profileSelection.dtd             (%chrome/mozapps/profile/profileSelection.dtd)
   locale/@AB_CD@/mozapps/update/updates.dtd                       (%chrome/mozapps/update/updates.dtd)
   locale/@AB_CD@/mozapps/update/updates.properties                (%chrome/mozapps/update/updates.properties)
--- a/toolkit/modules/RemoteWebProgress.jsm
+++ b/toolkit/modules/RemoteWebProgress.jsm
@@ -171,16 +171,17 @@ RemoteWebProgressManager.prototype = {
       this._browser.webNavigation.canGoForward = json.canGoForward;
 
       if (json.isTopLevel) {
         this._browser.webNavigation._currentURI = location;
         this._browser._characterSet = json.charset;
         this._browser._documentURI = newURI(json.documentURI);
         this._browser._imageDocument = null;
         this._browser._mayEnableCharacterEncodingMenu = json.mayEnableCharacterEncodingMenu;
+        this._browser._contentPrincipal = json.principal;
       }
 
       this._callProgressListeners("onLocationChange", webProgress, request, location, flags);
       break;
 
     case "Content:SecurityChange":
       let [status, state] = this._fixSSLStatusAndState(json.status, json.state);
 
deleted file mode 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerDatasource.js
+++ /dev/null
@@ -1,150 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const PFS_NS = "http://www.mozilla.org/2004/pfs-rdf#";
-
-function nsRDFItemUpdater(aClientOS, aChromeLocale) {
-  this._rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
-                               .getService(Components.interfaces.nsIRDFService);
-  this._os = Components.classes["@mozilla.org/observer-service;1"]
-                       .getService(Components.interfaces.nsIObserverService);
-
-  var app = Components.classes["@mozilla.org/xre/app-info;1"]
-                      .getService(Components.interfaces.nsIXULAppInfo);
-  this.appID = app.ID;
-  this.buildID = app.platformBuildID;
-  this.appRelease = app.version;
-
-  this.clientOS = aClientOS;
-  this.chromeLocale = aChromeLocale;
-
-  var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
-                             .getService(Components.interfaces.nsIPrefBranch);
-  this.dsURI = prefBranch.getCharPref("pfs.datasource.url");
-}
-
-nsRDFItemUpdater.prototype = {
-  checkForPlugin: function (aPluginRequestItem) {
-    var dsURI = this.dsURI;
-    // escape the mimetype as mimetypes can contain '+', which will break pfs.
-    dsURI = dsURI.replace(/%PLUGIN_MIMETYPE%/g, encodeURIComponent(aPluginRequestItem.mimetype));
-    dsURI = dsURI.replace(/%APP_ID%/g, this.appID);
-    dsURI = dsURI.replace(/%APP_VERSION%/g, this.buildID);
-    dsURI = dsURI.replace(/%APP_RELEASE%/g, this.appRelease);
-    dsURI = dsURI.replace(/%CLIENT_OS%/g, this.clientOS);
-    dsURI = dsURI.replace(/%CHROME_LOCALE%/g, this.chromeLocale);
-
-    var ds = this._rdfService.GetDataSource(dsURI);
-    var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource)
-    if (rds.loaded)
-      this.onDatasourceLoaded(ds, aPluginRequestItem);
-    else {
-      var sink = ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
-      sink.addXMLSinkObserver(new nsPluginXMLRDFDSObserver(this, aPluginRequestItem));
-    }
-  },
-
-  onDatasourceLoaded: function pfs_onDatasourceLoaded (aDatasource, aPluginRequestItem) {
-    var container = Components.classes["@mozilla.org/rdf/container;1"]
-                              .createInstance(Components.interfaces.nsIRDFContainer);
-    var resultRes = this._rdfService.GetResource("urn:mozilla:plugin-results:" + aPluginRequestItem.mimetype);
-    var pluginList = aDatasource.GetTarget(resultRes, this._rdfService.GetResource(PFS_NS+"plugins"), true);
-
-    var pluginInfo = null;
-  
-    try {
-      container.Init(aDatasource, pluginList);
-
-      var children = container.GetElements();
-      var target;
-
-      // get the first item
-      var child = children.getNext();
-      if (child instanceof Components.interfaces.nsIRDFResource) {
-        var name = this._rdfService.GetResource("http://www.mozilla.org/2004/pfs-rdf#updates");
-        target = aDatasource.GetTarget(child, name, true);
-      }
-
-      try {
-        container.Init(aDatasource, target);
-        target = null;
-        children = container.GetElements();
-
-        var child = children.getNext();
-        if (child instanceof Components.interfaces.nsIRDFResource) {
-          target = child;
-        }
-
-        var rdfs = this._rdfService;
-
-        function getPFSValueFromRDF(aValue) {
-          var rv = null;
-
-          var myTarget = aDatasource.GetTarget(target, rdfs.GetResource(PFS_NS + aValue), true);
-          if (myTarget)
-            rv = myTarget.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
-
-          return rv;
-        }
-
-        pluginInfo = {
-          name: getPFSValueFromRDF("name"),
-          pid: getPFSValueFromRDF("guid"),
-          version: getPFSValueFromRDF("version"),
-          IconUrl: getPFSValueFromRDF("IconUrl"),
-          InstallerLocation: getPFSValueFromRDF("InstallerLocation"),
-          InstallerHash: getPFSValueFromRDF("InstallerHash"),
-          XPILocation: getPFSValueFromRDF("XPILocation"),
-          XPIHash: getPFSValueFromRDF("XPIHash"),
-          InstallerShowsUI: getPFSValueFromRDF("InstallerShowsUI"),
-          manualInstallationURL: getPFSValueFromRDF("manualInstallationURL"),
-          requestedMimetype: getPFSValueFromRDF("requestedMimetype"),
-          licenseURL: getPFSValueFromRDF("licenseURL"),
-          needsRestart: getPFSValueFromRDF("needsRestart")
-        };
-      }
-      catch (ex) {
-        Components.utils.reportError(ex);
-      }
-    }
-    catch (ex) {
-      Components.utils.reportError(ex);
-    }
-    
-    gPluginInstaller.pluginInfoReceived(aPluginRequestItem, pluginInfo);
-  },
-
-  onDatasourceError: function pfs_onDatasourceError (aPluginRequestItem, aError) {
-    this._os.notifyObservers(aPluginRequestItem, "error", aError);
-    Components.utils.reportError(aError);
-    gPluginInstaller.pluginInfoReceived(aPluginRequestItem, null);
-  }
-};
-
-function nsPluginXMLRDFDSObserver(aUpdater, aPluginRequestItem) {
-  this._updater = aUpdater;
-  this._item    = aPluginRequestItem;
-}
-
-nsPluginXMLRDFDSObserver.prototype = 
-{ 
-  _updater  : null,
-  _item     : null,
-
-  // nsIRDFXMLSinkObserver
-  onBeginLoad: function(aSink) {},
-  onInterrupt: function(aSink) {},
-  onResume: function(aSink) {},
-  onEndLoad: function(aSink) {
-    aSink.removeXMLSinkObserver(this);
-    
-    var ds = aSink.QueryInterface(Components.interfaces.nsIRDFDataSource);
-    this._updater.onDatasourceLoaded(ds, this._item);
-  },
-  
-  onError: function(aSink, aStatus, aErrorMsg) {  
-    aSink.removeXMLSinkObserver(this);   
-    this._updater.onDatasourceError(this._item, aStatus.toString());
-  }
-};
deleted file mode 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerService.js
+++ /dev/null
@@ -1,299 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/AddonManager.jsm");
-
-const DOWNLOAD_STARTED = 0;
-const DOWNLOAD_FINISHED = 1;
-const INSTALL_STARTED = 2;
-const INSTALL_FINISHED = 3;
-const INSTALLS_COMPLETE = 4;
-
-function getLocalizedError(key)
-{
-  return document.getElementById("xpinstallStrings").getString(key);
-}
-
-function binaryToHex(input)
-{
-  return [('0' + input.charCodeAt(i).toString(16)).slice(-2)
-          for (i in input)].join('');
-}
-
-function verifyHash(aFile, aHash)
-{
-  try {
-    var [, method, hash] = /^([A-Za-z0-9]+):(.*)$/.exec(aHash);
-
-    var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
-      createInstance(Components.interfaces.nsIFileInputStream);
-    fis.init(aFile, -1, -1, 0);
-
-    var hasher = Components.classes['@mozilla.org/security/hash;1'].
-      createInstance(Components.interfaces.nsICryptoHash);
-    hasher.initWithString(method);
-    hasher.updateFromStream(fis, -1);
-    dlhash = binaryToHex(hasher.finish(false));
-    return dlhash == hash;
-  }
-  catch (e) {
-    Components.utils.reportError(e);
-    return false;
-  }
-}
-
-function InstallerObserver(aPlugin)
-{
-  this._plugin = aPlugin;
-  this._init();
-}
-
-InstallerObserver.prototype = {
-  _init: function()
-  {
-    try {
-      var ios = Components.classes["@mozilla.org/network/io-service;1"].
-        getService(Components.interfaces.nsIIOService);
-      var uri = ios.newURI(this._plugin.InstallerLocation, null, null);
-      uri.QueryInterface(Components.interfaces.nsIURL);
-
-      // Use a local filename appropriate for the OS
-      var leafName = uri.fileName;
-      var os = Components.classes["@mozilla.org/xre/app-info;1"]
-                         .getService(Components.interfaces.nsIXULRuntime)
-                         .OS;
-      if (os == "WINNT" && leafName.indexOf(".") < 0)
-        leafName += ".exe";
-
-      var dirs = Components.classes["@mozilla.org/file/directory_service;1"].
-        getService(Components.interfaces.nsIProperties);
-
-      var resultFile = dirs.get("TmpD", Components.interfaces.nsIFile);
-      resultFile.append(leafName);
-      resultFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE,
-                              0770);
-
-      var channel = ios.newChannelFromURI(uri);
-      this._downloader =
-        Components.classes["@mozilla.org/network/downloader;1"].
-          createInstance(Components.interfaces.nsIDownloader);
-      this._downloader.init(this, resultFile);
-      channel.notificationCallbacks = this;
-
-      this._fireNotification(DOWNLOAD_STARTED, null);
-
-      channel.asyncOpen(this._downloader, null);
-    }
-    catch (e) {
-      Components.utils.reportError(e);
-      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-228"));
-      if (resultFile && resultFile.exists())
-        resultfile.remove(false);
-    }
-  },
-
-  /**
-   * Inform the gPluginInstaller about what's going on.
-   */
-  _fireNotification: function(aStatus, aErrorMsg)
-  {
-    gPluginInstaller.pluginInstallationProgress(this._plugin.pid,
-                                                aStatus, aErrorMsg);
-
-    if (aStatus == INSTALL_FINISHED) {
-      --PluginInstallService._installersPending;
-      PluginInstallService._fireFinishedNotification();
-    }
-  },
-
-  QueryInterface: function(iid)
-  {
-    if (iid.equals(Components.interfaces.nsISupports) ||
-        iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
-        iid.equals(Components.interfaces.nsIDownloadObserver) ||
-        iid.equals(Components.interfaces.nsIProgressEventSink))
-      return this;
-
-    throw Components.results.NS_ERROR_NO_INTERFACE;
-  },
-
-  getInterface: function(iid)
-  {
-    if (iid.equals(Components.interfaces.nsIProgressEventSink))
-      return this;
-
-    return null;
-  },
-
-  onDownloadComplete: function(downloader, request, ctxt, status, result)
-  {
-    if (!Components.isSuccessCode(status)) {
-      // xpinstall error 228 is "Download Error"
-      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-228"));
-      result.remove(false);
-      return;
-    }
-
-    this._fireNotification(DOWNLOAD_FINISHED);
-
-    if (this._plugin.InstallerHash &&
-        !verifyHash(result, this._plugin.InstallerHash)) {
-      // xpinstall error 261 is "Invalid file hash..."
-      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-261"));
-      result.remove(false);
-      return;
-    }
-
-    this._fireNotification(INSTALL_STARTED);
-
-    result.QueryInterface(Components.interfaces.nsILocalFile);
-    try {
-      // Make sure the file is executable
-      result.permissions = 0770;
-      var process = Components.classes["@mozilla.org/process/util;1"]
-                              .createInstance(Components.interfaces.nsIProcess);
-      process.init(result);
-      var self = this;
-      process.runAsync([], 0, {
-        observe: function(subject, topic, data) {
-          if (topic != "process-finished") {
-            Components.utils.reportError("Failed to launch installer");
-            self._fireNotification(INSTALL_FINISHED,
-                                   getLocalizedError("error-207"));
-          }
-          else if (process.exitValue != 0) {
-            Components.utils.reportError("Installer returned exit code " + process.exitValue);
-            self._fireNotification(INSTALL_FINISHED,
-                                   getLocalizedError("error-203"));
-          }
-          else {
-            self._fireNotification(INSTALL_FINISHED, null);
-          }
-          result.remove(false);
-        }
-      });
-    }
-    catch (e) {
-      Components.utils.reportError(e);
-      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-207"));
-      result.remove(false);
-    }
-  },
-
-  onProgress: function(aRequest, aContext, aProgress, aProgressMax)
-  {
-    gPluginInstaller.pluginInstallationProgressMeter(this._plugin.pid,
-                                                     aProgress,
-                                                     aProgressMax);
-  },
-
-  onStatus: function(aRequest, aContext, aStatus, aStatusArg)
-  {
-    /* pass */
-  }
-};
-
-var PluginInstallService = {
-
-  /**
-   * Start installation of installers and XPI plugins.
-   * @param aInstallerPlugins An array of objects which should have the
-   *                          properties "pid", "InstallerLocation",
-   *                          and "InstallerHash"
-   * @param aXPIPlugins       An array of objects which should have the
-   *                          properties "pid", "XPILocation",
-   *                          and "XPIHash"
-   */
-  startPluginInstallation: function (aInstallerPlugins,
-                                     aXPIPlugins)
-  {
-    this._xpiPlugins = aXPIPlugins;
-    this._xpisPending = aXPIPlugins.length;
-
-    aXPIPlugins.forEach(function(plugin) {
-      AddonManager.getInstallForURL(plugin.XPILocation, function(install) {
-        install.addListener(PluginInstallService);
-        install.install();
-      }, "application/x-xpinstall", plugin.XPIHash);
-    });
-
-    // InstallerObserver may finish immediately so we must initialise the
-    // installers after setting the number of installers and xpis pending
-    this._installersPending = aInstallerPlugins.length;
-    this._installerPlugins = [new InstallerObserver(plugin)
-                              for each (plugin in aInstallerPlugins)];
-  },
-
-  _fireFinishedNotification: function()
-  {
-    if (this._installersPending == 0 && this._xpisPending == 0)
-      gPluginInstaller.pluginInstallationProgress(null, INSTALLS_COMPLETE, null);
-  },
-
-  getPidForInstall: function(install) {
-    for (let i = 0; i < this._xpiPlugins.length; i++) {
-      if (install.sourceURI.spec == this._xpiPlugins[i].XPILocation)
-        return this._xpiPlugins[i].pid;
-    }
-    return -1;
-  },
-
-  // InstallListener interface
-  onDownloadStarted: function(install) {
-    var pid = this.getPidForInstall(install);
-    gPluginInstaller.pluginInstallationProgress(pid, DOWNLOAD_STARTED, null);
-  },
-
-  onDownloadProgress: function(install) {
-    var pid = this.getPidForInstall(install);
-    gPluginInstaller.pluginInstallationProgressMeter(pid, install.progress,
-                                                     install.maxProgress);
-  },
-
-  onDownloadEnded: function(install) {
-    var pid = this.getPidForInstall(install);
-    gPluginInstaller.pluginInstallationProgress(pid, DOWNLOAD_FINISHED, null);
-  },
-
-  onDownloadFailed: function(install) {
-    var pid = this.getPidForInstall(install);
-    switch (install.error) {
-    case AddonManager.ERROR_NETWORK_FAILURE:
-      var errorMsg = getLocalizedError("error-228");
-      break;
-    case AddonManager.ERROR_INCORRECT_HASH:
-      var errorMsg = getLocalizedError("error-261");
-      break;
-    case AddonManager.ERROR_CORRUPT_FILE:
-      var errorMsg = getLocalizedError("error-207");
-      break;
-    }
-    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_FINISHED, errorMsg);
-
-    this._xpisPending--;
-    this._fireFinishedNotification();
-  },
-
-  onInstallStarted: function(install) {
-    var pid = this.getPidForInstall(install);
-    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_STARTED, null);
-  },
-
-  onInstallEnded: function(install, addon) {
-    var pid = this.getPidForInstall(install);
-    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_FINISHED, null);
-
-    this._xpisPending--;
-    this._fireFinishedNotification();
-  },
-
-  onInstallFailed: function(install) {
-    var pid = this.getPidForInstall(install);
-    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_FINISHED,
-                                                getLocalizedError("error-203"));
-
-    this._xpisPending--;
-    this._fireFinishedNotification();
-  }
-}
deleted file mode 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerWizard.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/* 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/. */
-
-
-.wizard-header-description {
-  display: none;
-}
-
deleted file mode 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerWizard.js
+++ /dev/null
@@ -1,659 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function nsPluginInstallerWizard(){
-
-  // create the request array
-  this.mPluginRequests = new Map();
-
-  // create the plugin info array.
-  // a hash indexed by plugin id so we don't install 
-  // the same plugin more than once.
-  this.mPluginInfoArray = new Object();
-  this.mPluginInfoArrayLength = 0;
-
-  // holds plugins we couldn't find
-  this.mPluginNotFoundArray = new Object();
-  this.mPluginNotFoundArrayLength = 0;
-
-  // array holding pids of plugins that require a license
-  this.mPluginLicenseArray = new Array();
-
-  // how many plugins are to be installed
-  this.pluginsToInstallNum = 0;
-
-  this.mBrowser = null;
-  this.mSuccessfullPluginInstallation = 0;
-  this.mNeedsRestart = false;
-
-  // arguments[0] is an object that contains two items:
-  //     a mimetype->pluginInfo map of missing plugins,
-  //     a reference to the browser that needs them, 
-  //        so we can notify which browser can be reloaded.
-
-  if ("arguments" in window) {
-    for (let [mimetype, pluginInfo] of window.arguments[0].plugins){
-      this.mPluginRequests.set(mimetype, new nsPluginRequest(pluginInfo));
-    }
-
-    this.mBrowser = window.arguments[0].browser;
-  }
-
-  this.WSPluginCounter = 0;
-  this.licenseAcceptCounter = 0;
-
-  this.prefBranch = null;
-}
-
-nsPluginInstallerWizard.prototype.getPluginData = function (){
-  // for each mPluginRequests item, call the datasource
-  this.WSPluginCounter = 0;
-
-  // initiate the datasource call
-  var rdfUpdater = new nsRDFItemUpdater(this.getOS(), this.getChromeLocale());
-
-  for (let [mimetype, pluginRequest] of this.mPluginRequests) {
-    rdfUpdater.checkForPlugin(pluginRequest);
-  }
-}
-
-// aPluginInfo is null if the datasource call failed, and pid is -1 if
-// no matching plugin was found.
-nsPluginInstallerWizard.prototype.pluginInfoReceived = function (aPluginRequestItem, aPluginInfo){
-  this.WSPluginCounter++;
-
-  if (aPluginInfo && (aPluginInfo.pid != -1) ) {
-    // hash by id
-    this.mPluginInfoArray[aPluginInfo.pid] = new PluginInfo(aPluginInfo);
-    this.mPluginInfoArrayLength++;
-  } else {
-    this.mPluginNotFoundArray[aPluginRequestItem.mimetype] = aPluginRequestItem;
-    this.mPluginNotFoundArrayLength++;
-  }
-
-  var progressMeter = document.getElementById("ws_request_progress");
-
-  if (progressMeter.getAttribute("mode") == "undetermined")
-    progressMeter.setAttribute("mode", "determined");
-
-  progressMeter.setAttribute("value",
-      ((this.WSPluginCounter / this.mPluginRequests.size) * 100) + "%");
-
-  if (this.WSPluginCounter == this.mPluginRequests.size) {
-    // check if no plugins were found
-    if (this.mPluginInfoArrayLength == 0) {
-      this.advancePage("lastpage");
-    } else {
-      this.advancePage(null);
-    }
-  } else {
-    // process more.
-  }
-}
-
-nsPluginInstallerWizard.prototype.showPluginList = function (){
-  var myPluginList = document.getElementById("pluginList");
-  var hasPluginWithInstallerUI = false;
-
-  // clear children
-  for (var run = myPluginList.childNodes.length; run > 0; run--)
-    myPluginList.removeChild(myPluginList.childNodes.item(run));
-
-  this.pluginsToInstallNum = 0;
-
-  for (var pluginInfoItem in this.mPluginInfoArray){
-    // [plugin image] [Plugin_Name Plugin_Version]
-
-    var pluginInfo = this.mPluginInfoArray[pluginInfoItem];
-
-    // create the checkbox
-    var myCheckbox = document.createElement("checkbox");
-    myCheckbox.setAttribute("checked", "true");
-    myCheckbox.setAttribute("oncommand", "gPluginInstaller.toggleInstallPlugin('" + pluginInfo.pid + "', this)");
-    // XXXlocalize (nit)
-    myCheckbox.setAttribute("label", pluginInfo.name + " " + (pluginInfo.version ? pluginInfo.version : ""));
-    myCheckbox.setAttribute("src", pluginInfo.IconUrl);
-
-    myPluginList.appendChild(myCheckbox);
-
-    if (pluginInfo.InstallerShowsUI == "true")
-      hasPluginWithInstallerUI = true;
-
-    // keep a running count of plugins the user wants to install
-    this.pluginsToInstallNum++;
-  }
-
-  if (hasPluginWithInstallerUI)
-    document.getElementById("installerUI").hidden = false;
-
-  this.canAdvance(true);
-  this.canRewind(false);
-}
-
-nsPluginInstallerWizard.prototype.toggleInstallPlugin = function (aPid, aCheckbox) {
-  this.mPluginInfoArray[aPid].toBeInstalled = aCheckbox.checked;
-
-  // if no plugins are checked, don't allow to advance
-  this.pluginsToInstallNum = 0;
-  for (var pluginInfoItem in this.mPluginInfoArray){
-    if (this.mPluginInfoArray[pluginInfoItem].toBeInstalled)
-      this.pluginsToInstallNum++;
-  }
-
-  if (this.pluginsToInstallNum > 0)
-    this.canAdvance(true);
-  else
-    this.canAdvance(false);
-}
-
-nsPluginInstallerWizard.prototype.canAdvance = function (aBool){
-  document.getElementById("plugin-installer-wizard").canAdvance = aBool;
-}
-
-nsPluginInstallerWizard.prototype.canRewind = function (aBool){
-  document.getElementById("plugin-installer-wizard").canRewind = aBool;
-}
-
-nsPluginInstallerWizard.prototype.canCancel = function (aBool){
-  document.documentElement.getButton("cancel").disabled = !aBool;
-}
-
-nsPluginInstallerWizard.prototype.showLicenses = function (){
-  this.canAdvance(false);
-  this.canRewind(false);
-
-  // only add if a license is provided and the plugin was selected to
-  // be installed
-  for (var pluginInfoItem in this.mPluginInfoArray){
-    var myPluginInfoItem = this.mPluginInfoArray[pluginInfoItem];
-    if (myPluginInfoItem.toBeInstalled && myPluginInfoItem.licenseURL && (myPluginInfoItem.licenseURL != ""))
-      this.mPluginLicenseArray.push(myPluginInfoItem.pid);
-  }
-
-  if (this.mPluginLicenseArray.length == 0) {
-    // no plugins require licenses
-    this.advancePage(null);
-  } else {
-    this.licenseAcceptCounter = 0;
-
-    // add a nsIWebProgress listener to the license iframe.
-    var docShell = document.getElementById("licenseIFrame").docShell;
-    var iiReq = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
-    var webProgress = iiReq.getInterface(Components.interfaces.nsIWebProgress);
-    webProgress.addProgressListener(gPluginInstaller.progressListener,
-                                    Components.interfaces.nsIWebProgress.NOTIFY_ALL);
-
-    this.showLicense();
-  }
-}
-
-nsPluginInstallerWizard.prototype.enableNext = function (){
-  // if only one plugin exists, don't enable the next button until
-  // the license is accepted
-  if (gPluginInstaller.pluginsToInstallNum > 1)
-    gPluginInstaller.canAdvance(true);
-
-  document.getElementById("licenseRadioGroup1").disabled = false;
-  document.getElementById("licenseRadioGroup2").disabled = false;
-}
-
-const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
-nsPluginInstallerWizard.prototype.progressListener = {
-  onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
-  {
-    if ((aStateFlags & nsIWebProgressListener.STATE_STOP) &&
-       (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK)) {
-      // iframe loaded
-      gPluginInstaller.enableNext();
-    }
-  },
-
-  onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
-                              aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
-  {},
-  onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
-  {},
-
-  QueryInterface : function(aIID)
-  {
-     if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
-         aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
-         aIID.equals(Components.interfaces.nsISupports))
-       return this;
-     throw Components.results.NS_NOINTERFACE;
-   }
-}
-
-nsPluginInstallerWizard.prototype.showLicense = function (){
-  var pluginInfo = this.mPluginInfoArray[this.mPluginLicenseArray[this.licenseAcceptCounter]];
-
-  this.canAdvance(false);
-
-  var loadFlags = Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE;
-  document.getElementById("licenseIFrame").webNavigation.loadURI(pluginInfo.licenseURL, loadFlags, null, null, null);
-
-  document.getElementById("pluginLicenseLabel").firstChild.nodeValue = 
-    this.getFormattedString("pluginLicenseAgreement.label", [pluginInfo.name]);
-
-  document.getElementById("licenseRadioGroup1").disabled = true;
-  document.getElementById("licenseRadioGroup2").disabled = true;
-  document.getElementById("licenseRadioGroup").selectedIndex = 
-    pluginInfo.licenseAccepted ? 0 : 1;
-}
-
-nsPluginInstallerWizard.prototype.showNextLicense = function (){
-  var rv = true;
-
-  if (this.mPluginLicenseArray.length > 0) {
-    this.storeLicenseRadioGroup();
-
-    this.licenseAcceptCounter++;
-
-    if (this.licenseAcceptCounter < this.mPluginLicenseArray.length) {
-      this.showLicense();
-
-      rv = false;
-      this.canRewind(true);
-    }
-  }
-
-  return rv;
-}
-
-nsPluginInstallerWizard.prototype.showPreviousLicense = function (){
-  this.storeLicenseRadioGroup();
-  this.licenseAcceptCounter--;
-
-  if (this.licenseAcceptCounter > 0)
-    this.canRewind(true);
-  else
-    this.canRewind(false);
-
-  this.showLicense();
-  
-  // don't allow to return from the license screens
-  return false;
-}
-
-nsPluginInstallerWizard.prototype.storeLicenseRadioGroup = function (){
-  var pluginInfo = this.mPluginInfoArray[this.mPluginLicenseArray[this.licenseAcceptCounter]];
-  pluginInfo.licenseAccepted = !document.getElementById("licenseRadioGroup").selectedIndex;
-}
-
-nsPluginInstallerWizard.prototype.licenseRadioGroupChange = function(aAccepted) {
-  // only if one plugin is to be installed should selection change the next button
-  if (this.pluginsToInstallNum == 1)
-    this.canAdvance(aAccepted);
-}
-
-nsPluginInstallerWizard.prototype.advancePage = function (aPageId){
-  this.canAdvance(true);
-  document.getElementById("plugin-installer-wizard").advance(aPageId);
-}
-
-nsPluginInstallerWizard.prototype.startPluginInstallation = function (){
-  this.canAdvance(false);
-  this.canRewind(false);
-
-  var installerPlugins = [];
-  var xpiPlugins = [];
-
-  for (var pluginInfoItem in this.mPluginInfoArray){
-    var pluginItem = this.mPluginInfoArray[pluginInfoItem];
-
-    if (pluginItem.toBeInstalled && pluginItem.licenseAccepted) {
-      if (pluginItem.InstallerLocation)
-        installerPlugins.push(pluginItem);
-      else if (pluginItem.XPILocation)
-        xpiPlugins.push(pluginItem);
-    }
-  }
-
-  if (installerPlugins.length > 0 || xpiPlugins.length > 0)
-    PluginInstallService.startPluginInstallation(installerPlugins,
-                                                 xpiPlugins);
-  else
-    this.advancePage(null);
-}
-
-/*
-  0    starting download
-  1    download finished
-  2    starting installation
-  3    finished installation
-  4    all done
-*/
-nsPluginInstallerWizard.prototype.pluginInstallationProgress = function (aPid, aProgress, aError) {
-
-  var statMsg = null;
-  var pluginInfo = gPluginInstaller.mPluginInfoArray[aPid];
-
-  switch (aProgress) {
-
-    case 0:
-      statMsg = this.getFormattedString("pluginInstallation.download.start", [pluginInfo.name]);
-      break;
-
-    case 1:
-      statMsg = this.getFormattedString("pluginInstallation.download.finish", [pluginInfo.name]);
-      break;
-
-    case 2:
-      statMsg = this.getFormattedString("pluginInstallation.install.start", [pluginInfo.name]);
-      var progressElm = document.getElementById("plugin_install_progress");
-      progressElm.setAttribute("mode", "undetermined");
-      break;
-
-    case 3:
-      if (aError) {
-        statMsg = this.getFormattedString("pluginInstallation.install.error", [pluginInfo.name, aError]);
-        pluginInfo.error = aError;
-      } else {
-        statMsg = this.getFormattedString("pluginInstallation.install.finish", [pluginInfo.name]);
-        pluginInfo.error = null;
-      }
-      break;
-
-    case 4:
-      statMsg = this.getString("pluginInstallation.complete");
-      break;
-  }
-
-  if (statMsg)
-    document.getElementById("plugin_install_progress_message").value = statMsg;
-
-  if (aProgress == 4) {
-    this.advancePage(null);
-  }
-}
-
-nsPluginInstallerWizard.prototype.pluginInstallationProgressMeter = function (aPid, aValue, aMaxValue){
-  var progressElm = document.getElementById("plugin_install_progress");
-
-  if (progressElm.getAttribute("mode") == "undetermined")
-    progressElm.setAttribute("mode", "determined");
-  
-  progressElm.setAttribute("value", Math.ceil((aValue / aMaxValue) * 100) + "%")
-}
-
-nsPluginInstallerWizard.prototype.addPluginResultRow = function (aImgSrc, aName, aNameTooltip, aStatus, aStatusTooltip, aManualUrl){
-  var myRows = document.getElementById("pluginResultList");
-
-  var myRow = document.createElement("row");
-  myRow.setAttribute("align", "center");
-
-  // create the image
-  var myImage = document.createElement("image");
-  myImage.setAttribute("src", aImgSrc);
-  myImage.setAttribute("height", "16px");
-  myImage.setAttribute("width", "16px");
-  myRow.appendChild(myImage)
-
-  // create the labels
-  var myLabel = document.createElement("label");
-  myLabel.setAttribute("value", aName);
-  if (aNameTooltip)
-    myLabel.setAttribute("tooltiptext", aNameTooltip);
-  myRow.appendChild(myLabel);
-
-  if (aStatus) {
-    myLabel = document.createElement("label");
-    myLabel.setAttribute("value", aStatus);
-    myRow.appendChild(myLabel);
-  }
-
-  // manual install
-  if (aManualUrl) {
-    var myButton = document.createElement("button");
-
-    var manualInstallLabel = this.getString("pluginInstallationSummary.manualInstall.label");
-    var manualInstallTooltip = this.getString("pluginInstallationSummary.manualInstall.tooltip");
-
-    myButton.setAttribute("label", manualInstallLabel);
-    myButton.setAttribute("tooltiptext", manualInstallTooltip);
-
-    myRow.appendChild(myButton);
-
-    // XXX: XUL sucks, need to add the listener after it got added into the document
-    if (aManualUrl)
-      myButton.addEventListener("command", function() { gPluginInstaller.loadURL(aManualUrl) }, false);
-  }
-
-  myRows.appendChild(myRow);
-}
-
-nsPluginInstallerWizard.prototype.showPluginResults = function (){
-  var notInstalledList = "?action=missingplugins";
-  var myRows = document.getElementById("pluginResultList");
-
-  // clear children
-  for (var run = myRows.childNodes.length; run--; run > 0)
-    myRows.removeChild(myRows.childNodes.item(run));
-
-  for (var pluginInfoItem in this.mPluginInfoArray){
-    // [plugin image] [Plugin_Name Plugin_Version] [Success/Failed] [Manual Install (if Failed)]
-
-    var myPluginItem = this.mPluginInfoArray[pluginInfoItem];
-
-    if (myPluginItem.toBeInstalled) {
-      var statusMsg;
-      var statusTooltip;
-      if (myPluginItem.error){
-        statusMsg = this.getString("pluginInstallationSummary.failed");
-        statusTooltip = myPluginItem.error;
-        notInstalledList += "&mimetype=" + pluginInfoItem;
-      } else if (!myPluginItem.licenseAccepted) {
-        statusMsg = this.getString("pluginInstallationSummary.licenseNotAccepted");
-      } else if (!myPluginItem.XPILocation && !myPluginItem.InstallerLocation) {
-        statusMsg = this.getString("pluginInstallationSummary.notAvailable");
-        notInstalledList += "&mimetype=" + pluginInfoItem;
-      } else {
-        this.mSuccessfullPluginInstallation++;
-        statusMsg = this.getString("pluginInstallationSummary.success");
-
-        // only check needsRestart if the plugin was successfully installed.
-        if (myPluginItem.needsRestart)
-          this.mNeedsRestart = true;
-      }
-
-      // manual url - either returned from the webservice or the pluginspage attribute
-      var manualUrl;
-      if ((myPluginItem.error || (!myPluginItem.XPILocation && !myPluginItem.InstallerLocation)) &&
-          (myPluginItem.manualInstallationURL || this.mPluginRequests.get(myPluginItem.requestedMimetype).pluginsPage)){
-        manualUrl = myPluginItem.manualInstallationURL ? myPluginItem.manualInstallationURL : this.mPluginRequests.get(myPluginItem.requestedMimetype).pluginsPage;
-      }
-
-      this.addPluginResultRow(
-          myPluginItem.IconUrl, 
-          myPluginItem.name + " " + (myPluginItem.version ? myPluginItem.version : ""),
-          null,
-          statusMsg, 
-          statusTooltip,
-          manualUrl);
-    }
-  }
-
-  // handle plugins we couldn't find
-  for (pluginInfoItem in this.mPluginNotFoundArray){
-    var pluginRequest = this.mPluginNotFoundArray[pluginInfoItem];
-
-    // if there is a pluginspage, show UI
-    if (pluginRequest.pluginsPage) {
-      this.addPluginResultRow(
-          "",
-          this.getFormattedString("pluginInstallation.unknownPlugin", [pluginInfoItem]),
-          null,
-          null,
-          null,
-          pluginRequest.pluginsPage);
-    }
-
-    notInstalledList += "&mimetype=" + pluginInfoItem;
-  }
-
-  // no plugins were found, so change the description of the final page.
-  if (this.mPluginInfoArrayLength == 0) {
-    var noPluginsFound = this.getString("pluginInstallation.noPluginsFound");
-    document.getElementById("pluginSummaryDescription").setAttribute("value", noPluginsFound);
-  } else if (this.mSuccessfullPluginInstallation == 0) {
-    // plugins found, but none were installed.
-    var noPluginsInstalled = this.getString("pluginInstallation.noPluginsInstalled");
-    document.getElementById("pluginSummaryDescription").setAttribute("value", noPluginsInstalled);
-  }
-
-  document.getElementById("pluginSummaryRestartNeeded").hidden = !this.mNeedsRestart;
-
-  var app = Components.classes["@mozilla.org/xre/app-info;1"]
-                      .getService(Components.interfaces.nsIXULAppInfo);
-
-  // set the get more info link to contain the mimetypes we couldn't install.
-  notInstalledList +=
-    "&appID=" + app.ID +
-    "&appVersion=" + app.platformBuildID +
-    "&clientOS=" + this.getOS() +
-    "&chromeLocale=" + this.getChromeLocale() +
-    "&appRelease=" + app.version;
-
-  document.getElementById("moreInfoLink").addEventListener("click", function() { gPluginInstaller.loadURL("https://pfs.mozilla.org/plugins/" + notInstalledList) }, false);
-
-  if (this.mNeedsRestart) {
-    var cancel = document.getElementById("plugin-installer-wizard").getButton("cancel");
-    cancel.label = this.getString("pluginInstallation.close.label");
-    cancel.accessKey = this.getString("pluginInstallation.close.accesskey");
-    var finish = document.getElementById("plugin-installer-wizard").getButton("finish");
-    finish.label = this.getFormattedString("pluginInstallation.restart.label", [app.name]);
-    finish.accessKey = this.getString("pluginInstallation.restart.accesskey");
-    this.canCancel(true);
-  }
-  else {
-    this.canCancel(false);
-  }
-  this.canAdvance(true);
-  this.canRewind(false);
-}
-
-nsPluginInstallerWizard.prototype.loadURL = function (aUrl){
-  // Check if the page where the plugin came from can load aUrl before
-  // loading it, and do *not* allow loading URIs that would inherit our
-  // principal.
-  
-  var pluginPagePrincipal =
-    window.opener.content.document.nodePrincipal;
-
-  const nsIScriptSecurityManager =
-    Components.interfaces.nsIScriptSecurityManager;
-  var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
-                         .getService(nsIScriptSecurityManager);
-
-  secMan.checkLoadURIStrWithPrincipal(pluginPagePrincipal, aUrl,
-    nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
-
-  window.opener.open(aUrl);
-}
-
-nsPluginInstallerWizard.prototype.getString = function (aName){
-  return document.getElementById("pluginWizardString").getString(aName);
-}
-
-nsPluginInstallerWizard.prototype.getFormattedString = function (aName, aArray){
-  return document.getElementById("pluginWizardString").getFormattedString(aName, aArray);
-}
-
-nsPluginInstallerWizard.prototype.getOS = function (){
-  var httpService = Components.classes["@mozilla.org/network/protocol;1?name=http"]
-                              .getService(Components.interfaces.nsIHttpProtocolHandler);
-  return httpService.oscpu;
-}
-
-nsPluginInstallerWizard.prototype.getChromeLocale = function (){
-  var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
-                            .getService(Components.interfaces.nsIXULChromeRegistry);
-  return chromeReg.getSelectedLocale("global");
-}
-
-nsPluginInstallerWizard.prototype.getPrefBranch = function (){
-  if (!this.prefBranch)
-    this.prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
-                                .getService(Components.interfaces.nsIPrefBranch);
-  return this.prefBranch;
-}
-function nsPluginRequest(aPlugRequest){
-  this.mimetype = encodeURI(aPlugRequest.mimetype);
-  this.pluginsPage = aPlugRequest.pluginsPage;
-}
-
-function PluginInfo(aResult) {
-  this.name = aResult.name;
-  this.pid = aResult.pid;
-  this.version = aResult.version;
-  this.IconUrl = aResult.IconUrl;
-  this.InstallerLocation = aResult.InstallerLocation;
-  this.InstallerHash = aResult.InstallerHash;
-  this.XPILocation = aResult.XPILocation;
-  this.XPIHash = aResult.XPIHash;
-  this.InstallerShowsUI = aResult.InstallerShowsUI;
-  this.manualInstallationURL = aResult.manualInstallationURL;
-  this.requestedMimetype = aResult.requestedMimetype;
-  this.licenseURL = aResult.licenseURL;
-  this.needsRestart = (aResult.needsRestart == "true");
-
-  this.error = null;
-  this.toBeInstalled = true;
-
-  // no license provided, make it accepted
-  this.licenseAccepted = this.licenseURL ? false : true;
-}
-
-var gPluginInstaller;
-
-function wizardInit(){
-  gPluginInstaller = new nsPluginInstallerWizard();
-  gPluginInstaller.canAdvance(false);
-  gPluginInstaller.getPluginData();
-}
-
-function wizardFinish(){
-  if (gPluginInstaller.mNeedsRestart) {
-    // Notify all windows that an application quit has been requested.
-    var os = Components.classes["@mozilla.org/observer-service;1"]
-                       .getService(Components.interfaces.nsIObserverService);
-    var cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
-                               .createInstance(Components.interfaces.nsISupportsPRBool);
-    os.notifyObservers(cancelQuit, "quit-application-requested", "restart");
-
-    // Something aborted the quit process.
-    if (!cancelQuit.data) {
-      var nsIAppStartup = Components.interfaces.nsIAppStartup;
-      var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
-                                 .getService(nsIAppStartup);
-      appStartup.quit(nsIAppStartup.eAttemptQuit | nsIAppStartup.eRestart);
-      return true;
-    }
-  }
-
-  // don't refresh if no plugins were found or installed
-  if ((gPluginInstaller.mSuccessfullPluginInstallation > 0) &&
-      (gPluginInstaller.mPluginInfoArray.length != 0)) {
-
-    // reload plugins so JS detection works immediately
-    try {
-      var ph = Components.classes["@mozilla.org/plugin/host;1"]
-                         .getService(Components.interfaces.nsIPluginHost);
-      ph.reloadPlugins(false);
-    }
-    catch (e) {
-      // reloadPlugins throws an exception if there were no plugins to load
-    }
-
-    if (gPluginInstaller.mBrowser) {
-      // notify listeners that a plugin is installed,
-      // so that they can reset the UI and update the browser.
-      var event = document.createEvent("Events");
-      event.initEvent("NewPluginInstalled", true, true);
-      gPluginInstaller.mBrowser.dispatchEvent(event);
-    }
-  }
-
-  return true;
-}
deleted file mode 100644
--- a/toolkit/mozapps/plugins/content/pluginInstallerWizard.xul
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0"?>
-<!-- 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/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://mozapps/content/plugins/pluginInstallerWizard.css"?>
-<?xml-stylesheet href="chrome://mozapps/skin/plugins/pluginInstallerWizard.css"?>
-
-<!DOCTYPE wizard [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-%brandDTD;
-<!ENTITY % pluginsDTD SYSTEM "chrome://mozapps/locale/plugins/plugins.dtd">
-%pluginsDTD;
-]>
-
-<wizard id="plugin-installer-wizard" title="&pluginWizard.title;"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        persist="width height screenX screenY sizemode"
-        style="width: 50em; min-height: 40em;"
-        onload="wizardInit()"
-        onwizardfinish="return wizardFinish();">
-
-  <script type="application/javascript" src="chrome://mozapps/content/plugins/pluginInstallerWizard.js"/>
-  <script type="application/javascript" src="chrome://mozapps/content/plugins/pluginInstallerDatasource.js"/>
-  <script type="application/javascript" src="chrome://mozapps/content/plugins/pluginInstallerService.js"/>
-
-  <stringbundleset id="pluginSet">
-    <stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
-    <stringbundle id="xpinstallStrings" src="chrome://global/locale/xpinstall/xpinstall.properties"/>
-    <stringbundle id="pluginWizardString" src="chrome://mozapps/locale/plugins/plugins.properties"/>
-  </stringbundleset>
-
-  <wizardpage label="&pluginWizard.firstPage.title;">
-    <description value="&pluginWizard.checkingForPlugins.description.label;"/>
-    <separator />
-    <progressmeter id="ws_request_progress" mode="undetermined"/>
-  </wizardpage>
-
-  <wizardpage label="&pluginWizard.availablePluginsPage.title;"
-              onpageshow="gPluginInstaller.showPluginList()">
-
-    <description value="&pluginWizard.availablePluginsPage.description.label;"/>
-
-    <vbox id="pluginList" flex="1" align="left" style="overflow: auto;"/>
-
-    <vbox id="installerUI" hidden="true">
-      <separator />
-      <description>&pluginWizard.availablePluginsPage.installerUI;</description>
-    </vbox>
-
-    <separator />
-    <description value="&pluginWizard.availablePluginsPage.continueMsg.label;"/>
-  </wizardpage>
-
-  <wizardpage label="&pluginWizard.licensePage.title;" 
-              onpageshow="gPluginInstaller.showLicenses()"
-              onpageadvanced="return gPluginInstaller.showNextLicense();"
-              onpagerewound="return gPluginInstaller.showPreviousLicense();">
-    <description id="pluginLicenseLabel"> </description>
-
-    <vbox id="licenseContainer" flex="1">
-      <iframe id="licenseIFrame" flex="1" src="" />
-    </vbox>
-
-    <radiogroup id="licenseRadioGroup">
-      <radio id="licenseRadioGroup1" disabled="true"
-             oncommand="gPluginInstaller.licenseRadioGroupChange(true)"
-             label="&pluginWizard.licensePage.accept.label;"/>
-      <radio id="licenseRadioGroup2" disabled="true" selected="true"
-             oncommand="gPluginInstaller.licenseRadioGroupChange(false)"
-             label="&pluginWizard.licensePage.deny.label;"/>
-    </radiogroup>
-  </wizardpage>
-
-  <wizardpage label="&pluginWizard.installPluginsPage.title;" 
-              onpageshow="gPluginInstaller.startPluginInstallation()">
-    <description value="&pluginWizard.installPluginsPage.description.label;"/>
-
-    <separator />
-
-    <description id="plugin_install_progress_message" value=""/>
-    <progressmeter id="plugin_install_progress" mode="undetermined"/>
-  </wizardpage>
-
-  <wizardpage id="lastpage" pageid="lastpage" 
-              onpageshow="gPluginInstaller.showPluginResults()">
-
-    <description id="pluginSummaryDescription" 
-                 value="&pluginWizard.finalPage.description.label;"/>
-
-    <separator />
-
-    <grid class="indent">
-      <columns>
-        <column/>
-        <column style="margin-right:15px;"/>
-        <column style="margin-right:15px;"/>
-        <column />
-      </columns>
-
-      <rows id="pluginResultList">
-      </rows>
-    </grid>
-
-    <description id="pluginSummaryRestartNeeded" style="padding-top:10px;"
-                 value="&pluginWizard.finalPage.restart.label;"/>
-    <spacer flex="1" />
-    <description id="moreInfoLink"
-      style="color:rgb(0, 0, 255); cursor:pointer; text-decoration:underline;"
-      value="&pluginWizard.finalPage.moreInfo.label;"/>
-  </wizardpage>
-
-</wizard>
-
--- a/toolkit/mozapps/plugins/content/pluginProblem.xml
+++ b/toolkit/mozapps/plugins/content/pluginProblem.xml
@@ -36,21 +36,16 @@
                 <html:div class="msg msgDisabled">&disabledPlugin;</html:div>
                 <html:div class="msg msgBlocked">&blockedPlugin.label;</html:div>
                 <html:div class="msg msgCrashed">
                     <html:div class="msgCrashedText" anonid="crashedText"><!-- set at runtime --></html:div>
                     <!-- link href set at runtime -->
                     <html:div class="msgReload">&reloadPlugin.pre;<html:a class="reloadLink" anonid="reloadLink" href="">&reloadPlugin.middle;</html:a>&reloadPlugin.post;</html:div>
                 </html:div>
 
-                <html:div class="installStatus" anonid="installStatus">
-                    <html:div class="msg msgInstallPlugin">
-		        <html:a class="action-link" anonid="installPluginLink" href="">&installPlugin;</html:a>
-		    </html:div>
-                </html:div>
                 <html:div class="msg msgManagePlugins"><html:a class="action-link" anonid="managePluginsLink" href="">&managePlugins;</html:a></html:div>
                 <html:div class="submitStatus" anonid="submitStatus">
                     <html:div class="msg msgPleaseSubmit" anonid="pleaseSubmit">
                         <html:textarea class="submitComment"
                                        anonid="submitComment"
                                        placeholder="&report.comment;"/>
                         <html:div class="submitURLOptInBox">
                             <html:label><html:input class="submitURLOptIn" anonid="submitURLOptIn" type="checkbox"/> &report.pageURL;</html:label>
--- a/toolkit/mozapps/plugins/content/pluginProblemContent.css
+++ b/toolkit/mozapps/plugins/content/pluginProblemContent.css
@@ -120,20 +120,16 @@ html|applet:not([height]), html|applet[h
 :-moz-handler-clicktoplay .msgTapToPlay,
 :-moz-handler-disabled .msgDisabled,
 :-moz-handler-disabled .msgManagePlugins,
 :-moz-handler-blocked .msgBlocked,
 :-moz-handler-crashed .msgCrashed {
   display: block;
 }
 
-.installStatus[installable] .msgInstallPlugin {
-  display: block;
-}
-
 .submitStatus[status] {
   display: -moz-box;
   -moz-box-align: center;
   -moz-box-pack: center;
   height: 160px;
 }
 
 .submitStatus[status="noReport"]   .msgNoCrashReport,
--- a/toolkit/mozapps/plugins/jar.mn
+++ b/toolkit/mozapps/plugins/jar.mn
@@ -1,15 +1,10 @@
 # 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/.
 
 toolkit.jar:
 % content mozapps %content/mozapps/
-  content/mozapps/plugins/pluginInstallerWizard.xul             (content/pluginInstallerWizard.xul)
-  content/mozapps/plugins/pluginInstallerWizard.js              (content/pluginInstallerWizard.js)
-  content/mozapps/plugins/pluginInstallerWizard.css             (content/pluginInstallerWizard.css)
-  content/mozapps/plugins/pluginInstallerDatasource.js          (content/pluginInstallerDatasource.js)
-  content/mozapps/plugins/pluginInstallerService.js             (content/pluginInstallerService.js)
   content/mozapps/plugins/pluginProblem.xml                     (content/pluginProblem.xml)
   content/mozapps/plugins/pluginProblemContent.css              (content/pluginProblemContent.css)
   content/mozapps/plugins/pluginProblemBinding.css              (content/pluginProblemBinding.css)
   content/mozapps/plugins/pluginFinderBinding.css               (content/pluginFinderBinding.css)
--- a/toolkit/mozapps/plugins/moz.build
+++ b/toolkit/mozapps/plugins/moz.build
@@ -1,13 +1,11 @@
 # -*- 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/.
 
-TEST_DIRS += ['tests']
-
 EXTRA_COMPONENTS += [
     'pluginGlue.manifest',
 ]
 
-JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
+JAR_MANIFESTS += ['jar.mn']
deleted file mode 100644
--- a/toolkit/mozapps/plugins/service/PluginFinderService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-package org.mozilla.pfs;
-
-public class PluginFinderService {
-
-  public org.mozilla.pfs.PluginInfo getPluginInfo(java.lang.String aMimetype, java.lang.String aClientOS, java.lang.String aLocale) {
-    org.mozilla.pfs.PluginInfo response = new org.mozilla.pfs.PluginInfo();
-    
-    if (aMimetype.equals("application/x-shockwave-flash")) {
-      response.setPid(1);
-      response.setName("Flash Player");
-      response.setVersion("7");
-      response.setIconUrl("http://goat.austin.ibm.com:8080/flash.gif");
-      response.setXPILocation("http://www.nexgenmedia.net/flashlinux/flash-linux.xpi");
-      response.setInstallerShowsUI(false);
-      response.setManualInstallationURL("");
-      response.setLicenseURL("");
-    } else if (aMimetype.equals("application/x-mtx")) {
-      response.setPid(2);
-      response.setName("Viewpoint Media Player");
-      response.setVersion("5");
-      response.setIconUrl(null);
-      response.setXPILocation("http://www.nexgenmedia.net/flashlinux/invalid.xpi");
-      response.setInstallerShowsUI(false);
-      response.setManualInstallationURL("http://www.viewpoint.com/pub/products/vmp.html");   
-      response.setLicenseURL("http://www.viewpoint.com/pub/privacy.html");
-    } else {
-      response.setPid(-1);
-    }
-    
-    response.setRequestedMimetype(aMimetype);
-    return response;
-    
-  }
-}
-
deleted file mode 100644
--- a/toolkit/mozapps/plugins/service/PluginFinderService.php
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-/* -*- Mode: php; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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/. */
-
-/// config bits:
-$db_server = "";
-$db_user = "";
-$db_pass = "";
-$db_name = "";
-
-// error handling
-function bail ($errstr) {
-    die("Error: " . $errstr);
-}
-
-
-// major.minor.release.build[+]
-// make sure this is a valid version
-function expandversion ($vstr) {
-    $v = explode('.', $vstr);
-
-    if ($vstr == '' || count($v) == 0 || count($v) > 4) {
-        bail ('Bogus version.');
-    }
-
-    $vlen = count($v);
-    $ret = array();
-    $hasplus = 0;
-
-    for ($i = 0; $i < 4; $i++) {
-        if ($i > $vlen-1) {
-            // this version chunk was not specified; give 0
-            $ret[] = 0;
-        } else {
-            $s = $v[$i];
-            if ($i == 3) {
-                // need to check for +
-                $slen = strlen($s);
-                if ($s{$slen-1} == '+') {
-                    $s = substr($s, 0, $slen-1);
-                    $hasplus = 1;
-                }
-            }
-
-            $ret[] = intval($s);
-        }
-    }
-
-    $ret[] = $hasplus;
-
-    return $ret;
-}
-
-function vercmp ($a, $b) {
-    if ($a == $b)
-        return 0;
-
-    $va = expandversion($a);
-    $vb = expandversion($b);
-
-    for ($i = 0; $i < 5; $i++)
-        if ($va[$i] != $vb[$i])
-            return ($vb[$i] - $va[$i]);
-
-    return 0;
-}
-
-
-//
-// These are passed in the GET string
-//
-
-if (!array_key_exists('mimetype', $_GET))
-    bail ("Invalid request.");
-
-$mimetype = $_GET['mimetype'];
-
-if (!array_key_exists('appID', $_GET) 
-    || !array_key_exists('appVersion', $_GET)
-    || !array_key_exists('clientOS', $_GET))    
-    || !array_key_exists('chromeLocale', $_GET))
-   )
-    bail ("Invalid request.");
-
-$reqTargetAppGuid = $_GET['appID'];
-$reqTargetAppVersion = $_GET['appVersion'];
-$clientOS = $_GET['clientOS'];
-$chromeLocale = $_GET['chromeLocale'];
-
-// check args
-if (empty($reqTargetAppVersion) || empty($reqTargetAppGuid)) {
-    bail ("Invalid request.");
-}
-
-//
-// Now to spit out the RDF.  We hand-generate because the data is pretty simple.
-//
-
-if ($mimetype == "application/x-mtx") {
-  $name = "Viewpoint Media Player";
-  $guid = "{03F998B2-0E00-11D3-A498-00104B6EB52E}";
-  $version = "5.0";
-  $iconUrl = "";
-  $XPILocation = "http://www.nexgenmedia.net/flashlinux/invalid.xpi";
-  $InstallerShowsUI = false;
-  $manualInstallationURL = "http://www.viewpoint.com/pub/products/vmp.html";
-  $licenseURL = "http://www.viewpoint.com/pub/privacy.html";
-} else if ($mimetype == "application/x-shockwave-flash") {
-  $name = "Flash Player";
-  $guid = "{D27CDB6E-AE6D-11cf-96B8-444553540000}";
-  $version = "7.0.16";
-  $iconUrl = "http://goat.austin.ibm.com:8080/flash.gif";
-  $XPILocation = "http://www.nexgenmedia.net/flashlinux/flash-linux.xpi";
-  $InstallerShowsUI = "false";
-  $manualInstallationURL = "http://www.macromedia.com/go/getflashplayer";
-  $licenseURL = "http://www.macromedia.com/shockwave/download/license/desktop/";
-} else {
-  $name = "";
-  $guid = "-1";
-  $version = "";
-  $iconUrl = "";
-  $XPILocation = "";
-  $InstallerShowsUI = "";
-  $manualInstallationURL = "";
-  $licenseURL = "";
-}
-
-header("Content-type: application/xml");
-print "<?xml version=\"1.0\"?>\n";
-print "<RDF:RDF xmlns:RDF=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:pfs=\"http://www.mozilla.org/2004/pfs-rdf#\">\n\n";
-
-print "<RDF:Description about=\"urn:mozilla:plugin-results:{$mimetype}\">\n";
-
-// output list of matching plugins
-print " <pfs:plugins><RDF:Seq>\n";
-print "   <RDF:li resource=\"urn:mozilla:plugin:{$guid}\"/>\n";
-print " </RDF:Seq></pfs:plugins>\n";
-print "</RDF:Description>\n\n";
-
-print "<RDF:Description about=\"urn:mozilla:plugin:{$guid}\">\n";
-print " <pfs:updates><RDF:Seq>\n";
-print "   <RDF:li resource=\"urn:mozilla:plugin:{$guid}:{$version}\"/>\n";
-print " </RDF:Seq></pfs:updates>\n";
-print "</RDF:Description>\n\n";
-
-print "<RDF:Description about=\"urn:mozilla:plugin:{$guid}:{$version}\">\n";
-print " <pfs:name>{$name}</pfs:name>\n";
-print " <pfs:requestedMimetype>{$mimetype}</pfs:requestedMimetype>\n";
-print " <pfs:guid>{$guid}</pfs:guid>\n";
-print " <pfs:version>{$version}</pfs:version>\n";
-print " <pfs:IconUrl>{$iconUrl}</pfs:IconUrl>\n";
-print " <pfs:XPILocation>{$XPILocation}</pfs:XPILocation>\n";
-print " <pfs:InstallerShowsUI>{$InstallerShowsUI}</pfs:InstallerShowsUI>\n";
-print " <pfs:manualInstallationURL>{$manualInstallationURL}</pfs:manualInstallationURL>\n";
-print " <pfs:licenseURL>{$licenseURL}</pfs:licenseURL>\n";
-print "</RDF:Description>\n\n";
-
-print "</RDF:RDF>\n";
-
-?>
-
deleted file mode 100644
--- a/toolkit/mozapps/plugins/service/PluginInfo.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-package org.mozilla.pfs;
-
-public class PluginInfo {
-  private java.lang.String name;
-  private int pid;
-  private java.lang.String version;
-  private java.lang.String iconUrl;
-  private java.lang.String XPILocation;
-  private boolean installerShowsUI;
-  private java.lang.String manualInstallationURL;
-  private java.lang.String requestedMimetype;
-  private java.lang.String licenseURL;
-
-  public PluginInfo() {
-  }
-
-  public java.lang.String getName() {
-    return name;
-  }
-
-  public void setName(java.lang.String name) {
-    this.name = name;
-  }
-
-  public int getPid() {
-    return pid;
-  }
-
-  public void setPid(int pid) {
-    this.pid = pid;
-  }
-
-  public java.lang.String getVersion() {
-    return version;
-  }
-
-  public void setVersion(java.lang.String version) {
-    this.version = version;
-  }
-
-  public java.lang.String getIconUrl() {
-    return iconUrl;
-  }
-
-  public void setIconUrl(java.lang.String iconUrl) {
-    this.iconUrl = iconUrl;
-  }
-
-  public java.lang.String getXPILocation() {
-    return XPILocation;
-  }
-
-  public void setXPILocation(java.lang.String XPILocation) {
-    this.XPILocation = XPILocation;
-  }
-
-  public boolean isInstallerShowsUI() {
-    return installerShowsUI;
-  }
-
-  public void setInstallerShowsUI(boolean installerShowsUI) {
-    this.installerShowsUI = installerShowsUI;
-  }
-
-  public java.lang.String getManualInstallationURL() {
-    return manualInstallationURL;
-  }
-
-  public void setManualInstallationURL(java.lang.String manualInstallationURL) {
-    this.manualInstallationURL = manualInstallationURL;
-  }
-
-  public java.lang.String getRequestedMimetype() {
-    return requestedMimetype;
-  }
-
-  public void setRequestedMimetype(java.lang.String requestedMimetype) {
-    this.requestedMimetype = requestedMimetype;
-  }
-
-  public java.lang.String getLicenseURL() {
-    return licenseURL;
-  }
-
-  public void setLicenseURL(java.lang.String licenseURL) {
-    this.licenseURL = licenseURL;
-  }
-}
-
deleted file mode 100644
--- a/toolkit/mozapps/plugins/service/make.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-# 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/.
-
-
-export CATALINA_HOME=/var/tomcat-4.1.27
-export AXIS_HOME=/var/tomcat-4.1.27/axis-1_1
-export CLASSPATH=$AXIS_HOME/lib/axis.jar:$AXIS_HOME/lib/commons-discovery.jar:$AXIS_HOME/lib/commons-logging.jar:$AXIS_HOME/lib/jaxrpc.jar:$AXIS_HOME/lib/saaj.jar:$AXIS_HOME/lib/log4j-1.2.4.jar:$AXIS_HOME/lib/wsdl4j.jar:$CATALINA_HOME/webapps/axis/WEB-INF/classes
-
-name="PluginFinderService"
-pkg="org.mozilla.pfs"
-pkg_dir=$CATALINA_HOME/webapps/axis/WEB-INF/classes/org/mozilla/pfs
-
-echo "Copying Source..."
-
-rm -f $pkg_dir/*.*
-cp -f *.java $pkg_dir
-
-echo "Compiling Source..."
-javac -g $pkg_dir/*.java
-
-echo "Generating WSDL..."
-java org.apache.axis.wsdl.Java2WSDL -o $name.wsdl \
-      -l"http://localhost:8080/axis/services/$name" \
-      -n "urn:$name" -p"$pkg" "urn:$name" $pkg.$name
-      
-echo "Generating Stubs from WSDL..."
-rm -f org/mozilla/pfs/*.*
-java org.apache.axis.wsdl.WSDL2Java -o . -s -S true -Nurn:$name $pkg $name.wsdl
-
-# make our PluginFinderService.java looking the SoapBindingImpl syntax and replace
-cp $name.java $name.temp
-regexp="s/$name/${name}SoapBindingImpl/g"
-sed -e $regexp $name.temp > $name.temp2
-rm $name.temp
-
-regexp="s/public class ${name}SoapBindingImpl/public class ${name}SoapBindingImpl implements ${pkg}.${name}/g"
-sed -e "$regexp" $name.temp2 > $name.temp
-rm $name.temp2
-mv $name.temp org/mozilla/pfs/${name}SoapBindingImpl.java
-
-rm -f $pkg_dir/*.java
-cp org/mozilla/pfs/* $pkg_dir/
-javac $pkg_dir/*.java
-
-echo "Deploying Web Service..."
-java org.apache.axis.client.AdminClient -p 8080 $pkg_dir/deploy.wsdd  
-
-echo "All Done. Hoorah!"
deleted file mode 100644
index 1122537f7af6f3d430ba421830afb18b36756385..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/BadPlugin.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-int main(int argc, char** argv)
-{
-    return 1;
-}
deleted file mode 100644
index c4ade90d5bda85d83ec3ade8ee2b58f59d9d3eed..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/GoodPlugin.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-int main(int argc, char** argv)
-{
-    return 0;
-}
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/Makefile.in
+++ /dev/null
@@ -1,9 +0,0 @@
-# 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/.
-
-TESTROOT = $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
-
-PROGRAMS_DEST = $(TESTROOT)
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/browser.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[DEFAULT]
-support-files =
-  pfs_bug435788_1.rdf
-  pfs_bug435788_2.rdf
-  GoodExtension.xpi
-  BadExtension.xpi
-
-[browser_bug435788.js]
-disabled = disabled for leaks--bug-751100
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/browser_bug435788.js
+++ /dev/null
@@ -1,461 +0,0 @@
-const TEST_ROOT = "http://example.com/browser/toolkit/mozapps/plugins/tests/";
-
-let tmp = {};
-Components.utils.import("resource://gre/modules/AddonManager.jsm", tmp);
-let AddonManager = tmp.AddonManager;
-
-var gPFS;
-
-function test() {
-  waitForExplicitFinish();
-
-  prepare_test_1();
-}
-
-function finishTest() {
-  Services.prefs.clearUserPref("pfs.datasource.url");
-  finish();
-}
-
-// Gets the number of plugin items in the detected list
-function getListCount() {
-  var list = gPFS.document.getElementById("pluginList");
-  return list.childNodes.length;
-}
-
-// Gets wether the list contains a particular plugin name
-function hasListItem(name, version) {
-  var label = name + " " + (version ? version : "");
-  var list = gPFS.document.getElementById("pluginList");
-  for (var i = 0; i < list.childNodes.length; i++) {
-    if (list.childNodes[i].label == label)
-      return true;
-  }
-  return false;
-}
-
-// Gets the number of plugin results
-function getResultCount() {
-  var list = gPFS.document.getElementById("pluginResultList");
-  return list.childNodes.length;
-}
-
-// Gets the plugin result for a particular plugin name
-function getResultItem(name, version) {
-  var label = name + " " + (version ? version : "");
-  var list = gPFS.document.getElementById("pluginResultList");
-  for (var i = 0; i < list.childNodes.length; i++) {
-    if (list.childNodes[i].childNodes[1].value == label) {
-      var item = {
-        name: name,
-        version: version,
-        status: null
-      };
-      if (list.childNodes[i].childNodes[2].tagName == "label")
-        item.status = list.childNodes[i].childNodes[2].value;
-      return item;
-    }
-  }
-  return null;
-}
-
-// Logs the currently displaying wizard page
-function page_shown() {
-  function show_button_state(name) {
-    var button = gPFS.document.documentElement.getButton(name);
-    info("Button " + name + ". hidden: " + button.hidden +
-         ", disabled: " + button.disabled);
-  }
-
-  info("Page shown: " +
-       gPFS.document.documentElement.currentPage.getAttribute("label"));
-  show_button_state("next");
-  show_button_state("finish");
-}
-
-function pfs_loaded() {
-  info("PFS loaded");
-  var docEle = gPFS.document.documentElement;
-
-  var onwizardfinish = function () {
-    info("wizardfinish event");
-  };
-  var onwizardnext = function () {
-    info("wizardnext event");
-  };
-
-  docEle.addEventListener("pageshow", page_shown, false);
-  docEle.addEventListener("wizardfinish", onwizardfinish, false);
-  docEle.addEventListener("wizardnext", onwizardnext, false);
-
-  gPFS.addEventListener("unload", function() {
-    info("unload event");
-    gPFS.removeEventListener("unload", arguments.callee, false);
-    docEle.removeEventListener("pageshow", page_shown, false);
-    docEle.removeEventListener("wizardfinish", onwizardfinish, false);
-    docEle.removeEventListener("wizardnext", onwizardnext, false);
-  }, false);
-
-  page_shown();
-}
-
-function startTest(num, missingPluginsArray) {
-  info("Test " + num);
-
-  gPFS = window.openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
-                           "PFSWindow", "chrome,centerscreen,resizable=yes",
-                           {plugins: missingPluginsArray});
-
-  var testScope = this;
-
-  gPFS.addEventListener("load", function () {
-    gPFS.removeEventListener("load", arguments.callee, false);
-
-    pfs_loaded();
-
-    var seenAvailable = false;
-    var expectAvailable = typeof testScope["test_" + num + "_available"] == "function";
-
-    function availableListener() {
-      seenAvailable = true;
-
-      if (expectAvailable) {
-        executeSoon(function () {
-          testScope["test_" + num + "_available"]();
-          gPFS.document.documentElement.getButton("next").click();
-        });
-      } else {
-        ok(false, "Should not have found plugins to install");
-      }
-    }
-
-    function completeListener() {
-      if (expectAvailable)
-        ok(seenAvailable, "Should have seen the list of available plugins");
-
-      executeSoon(testScope["test_" + num + "_complete"]);
-    }
-
-    gPFS.document.documentElement.wizardPages[1].addEventListener("pageshow", availableListener);
-    gPFS.document.documentElement.wizardPages[4].addEventListener("pageshow", completeListener);
-
-    gPFS.addEventListener("unload", function () {
-      gPFS.removeEventListener("unload", arguments.callee, false);
-      gPFS.document.documentElement.wizardPages[1].removeEventListener("pageshow", availableListener, false);
-      gPFS.document.documentElement.wizardPages[4].removeEventListener("pageshow", completeListener, false);
-
-      num++;
-      if (typeof testScope["prepare_test_" + num] == "function")
-        testScope["prepare_test_" + num]();
-      else
-        finishTest();
-    });
-  });
-}
-
-function clickFinish() {
-  var finish = gPFS.document.documentElement.getButton("finish");
-  ok(!finish.hidden, "Finish button should not be hidden");
-  ok(!finish.disabled, "Finish button should not be disabled");
-  finish.click();
-}
-
-// Test a working installer
-function prepare_test_1() {
-  Services.prefs.setCharPref("pfs.datasource.url", TEST_ROOT + "pfs_bug435788_1.rdf");
-
-  var missingPluginsArray = {
-    "application/x-working-plugin": {
-      mimetype: "application/x-working-plugin",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(1, missingPluginsArray);
-}
-
-function test_1_available() {
-  is(getListCount(), 1, "Should have found 1 plugin to install");
-  ok(hasListItem("Test plugin 1", null), "Should have seen the right plugin name");
-}
-
-function test_1_complete() {
-  is(getResultCount(), 1, "Should have attempted to install 1 plugin");
-  var item = getResultItem("Test plugin 1", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Installed", "Should have been a successful install");
-
-  clickFinish();
-}
-
-// Test a broken installer (returns exit code 1)
-function prepare_test_2() {
-  var missingPluginsArray = {
-    "application/x-broken-installer": {
-      mimetype: "application/x-broken-installer",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(2, missingPluginsArray);
-}
-
-function test_2_available() {
-  is(getListCount(), 1, "Should have found 1 plugin to install");
-  ok(hasListItem("Test plugin 2", null), "Should have seen the right plugin name");
-}
-
-function test_2_complete() {
-  is(getResultCount(), 1, "Should have attempted to install 1 plugin");
-  var item = getResultItem("Test plugin 2", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Failed", "Should have been a failed install");
-
-  clickFinish();
-}
-
-// Test both working and broken together
-function prepare_test_3() {
-  var missingPluginsArray = {
-    "application/x-working-plugin": {
-      mimetype: "application/x-working-plugin",
-      pluginsPage: ""
-    },
-    "application/x-broken-installer": {
-      mimetype: "application/x-broken-installer",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(3, missingPluginsArray);
-}
-
-function test_3_available() {
-  is(getListCount(), 2, "Should have found 2 plugins to install");
-  ok(hasListItem("Test plugin 1", null), "Should have seen the right plugin name");
-  ok(hasListItem("Test plugin 2", null), "Should have seen the right plugin name");
-}
-
-function test_3_complete() {
-  is(getResultCount(), 2, "Should have attempted to install 2 plugins");
-  var item = getResultItem("Test plugin 1", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Installed", "Should have been a successful install");
-  item = getResultItem("Test plugin 2", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Failed", "Should have been a failed install");
-
-  clickFinish();
-}
-
-// Test an installer with a bad hash
-function prepare_test_4() {
-  var missingPluginsArray = {
-    "application/x-broken-plugin-hash": {
-      mimetype: "application/x-broken-plugin-hash",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(4, missingPluginsArray);
-}
-
-function test_4_available() {
-  is(getListCount(), 1, "Should have found 1 plugin to install");
-  ok(hasListItem("Test plugin 3", null), "Should have seen the right plugin name");
-}
-
-function test_4_complete() {
-  is(getResultCount(), 1, "Should have attempted to install 1 plugin");
-  var item = getResultItem("Test plugin 3", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Failed", "Should have not been a successful install");
-
-  clickFinish();
-}
-
-// Test a working xpi
-function prepare_test_5() {
-  var missingPluginsArray = {
-    "application/x-working-extension": {
-      mimetype: "application/x-working-extension",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(5, missingPluginsArray);
-}
-
-function test_5_available() {
-  is(getListCount(), 1, "Should have found 1 plugin to install");
-  ok(hasListItem("Test extension 1", null), "Should have seen the right plugin name");
-}
-
-function test_5_complete() {
-  is(getResultCount(), 1, "Should have attempted to install 1 plugin");
-  var item = getResultItem("Test extension 1", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Installed", "Should have been a successful install");
-
-  AddonManager.getAllInstalls(function(installs) {
-    is(installs.length, 1, "Should be just one install");
-    is(installs[0].state, AddonManager.STATE_INSTALLED, "Should be fully installed");
-    is(installs[0].addon.id, "bug435788_1@tests.mozilla.org", "Should have installed the extension");
-    installs[0].cancel();
-
-    clickFinish();
-  });
-}
-
-// Test a broke xpi (no install.rdf)
-function prepare_test_6() {
-  var missingPluginsArray = {
-    "application/x-broken-extension": {
-      mimetype: "application/x-broken-extension",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(6, missingPluginsArray);
-}
-
-function test_6_available() {
-  is(getListCount(), 1, "Should have found 1 plugin to install");
-  ok(hasListItem("Test extension 2", null), "Should have seen the right plugin name");
-}
-
-function test_6_complete() {
-  is(getResultCount(), 1, "Should have attempted to install 1 plugin");
-  var item = getResultItem("Test extension 2", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Failed", "Should have been a failed install");
-
-  clickFinish();
-}
-
-// Test both working and broken xpi
-function prepare_test_7() {
-  var missingPluginsArray = {
-    "application/x-working-extension": {
-      mimetype: "application/x-working-extension",
-      pluginsPage: ""
-    },
-    "application/x-broken-extension": {
-      mimetype: "application/x-broken-extension",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(7, missingPluginsArray);
-}
-
-function test_7_available() {
-  is(getListCount(), 2, "Should have found 2 plugins to install");
-  ok(hasListItem("Test extension 1", null), "Should have seen the right plugin name");
-  ok(hasListItem("Test extension 2", null), "Should have seen the right plugin name");
-}
-
-function test_7_complete() {
-  is(getResultCount(), 2, "Should have attempted to install 2 plugins");
-  var item = getResultItem("Test extension 1", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Installed", "Should have been a failed install");
-  item = getResultItem("Test extension 2", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Failed", "Should have been a failed install");
-
-  AddonManager.getAllInstalls(function(installs) {
-    is(installs.length, 1, "Should be one active installs");
-    installs[0].cancel();
-
-    clickFinish();
-  });
-}
-
-// Test an xpi with a bad hash
-function prepare_test_8() {
-  var missingPluginsArray = {
-    "application/x-broken-extension-hash": {
-      mimetype: "application/x-broken-extension-hash",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(8, missingPluginsArray);
-}
-
-function test_8_available() {
-  is(getListCount(), 1, "Should have found 1 plugin to install");
-  ok(hasListItem("Test extension 3", null), "Should have seen the right plugin name");
-}
-
-function test_8_complete() {
-  is(getResultCount(), 1, "Should have attempted to install 1 plugin");
-  var item = getResultItem("Test extension 3", null);
-  ok(item, "Should have seen the installed item");
-  is(item.status, "Failed", "Should have not been a successful install");
-
-  AddonManager.getAllInstalls(function(installs) {
-    is(installs.length, 0, "Should not be any installs");
-
-    clickFinish();
-  });
-}
-
-// Test when no plugin exists in the datasource
-function prepare_test_9() {
-  var missingPluginsArray = {
-    "application/x-unknown-plugin": {
-      mimetype: "application/x-unknown-plugin",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(9, missingPluginsArray);
-}
-
-function test_9_complete() {
-  is(getResultCount(), 0, "Should have found no plugins");
-
-  clickFinish();
-}
-
-// Test when the datasource is invalid xml
-function prepare_test_10() {
-  Services.prefs.setCharPref("pfs.datasource.url", TEST_ROOT + "pfs_bug435788_2.rdf");
-
-  var missingPluginsArray = {
-    "application/x-broken-xml": {
-      mimetype: "application/x-broken-xml",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(10, missingPluginsArray);
-}
-
-function test_10_complete() {
-  is(getResultCount(), 0, "Should have found no plugins");
-
-  clickFinish();
-}
-
-// Test when no datasource is returned
-function prepare_test_11() {
-  Services.prefs.setCharPref("pfs.datasource.url", TEST_ROOT + "pfs_bug435788_foo.rdf");
-
-  var missingPluginsArray = {
-    "application/x-missing-xml": {
-      mimetype: "application/x-missing-xml",
-      pluginsPage: ""
-    }
-  };
-
-  startTest(11, missingPluginsArray);
-}
-
-function test_11_complete() {
-  is(getResultCount(), 0, "Should have found no plugins");
-
-  clickFinish();
-}
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/moz.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- 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/.
-
-SimplePrograms([
-    'BadPlugin',
-    'GoodPlugin',
-])
-
-BROWSER_CHROME_MANIFESTS += ['browser.ini']
-USE_STATIC_LIBS = True
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/pfs_bug435788_1.rdf
+++ /dev/null
@@ -1,161 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:pfs="http://www.mozilla.org/2004/pfs-rdf#">
-
-<RDF:Description about="urn:mozilla:plugin-results:application/x-working-plugin">
- <pfs:plugins><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{8d3ab839-e03e-41a5-acd3-be1eabf94810}"/>
- </RDF:Seq></pfs:plugins>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{8d3ab839-e03e-41a5-acd3-be1eabf94810}">
- <pfs:updates><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{8d3ab839-e03e-41a5-acd3-be1eabf94810}:"/>
- </RDF:Seq></pfs:updates>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{8d3ab839-e03e-41a5-acd3-be1eabf94810}:">
- <pfs:name>Test plugin 1</pfs:name>
- <pfs:requestedMimetype>application/x-working-plugin</pfs:requestedMimetype>
- <pfs:guid>{8d3ab839-e03e-41a5-acd3-be1eabf94810}</pfs:guid>
- <pfs:version/>
- <pfs:IconUrl/>
- <pfs:InstallerLocation>http://example.com/browser/toolkit/mozapps/plugins/tests/GoodPlugin</pfs:InstallerLocation>
- <pfs:InstallerHash/>
- <pfs:InstallerShowsUI>false</pfs:InstallerShowsUI>
- <pfs:manualInstallationURL>http://www.mozilla.com</pfs:manualInstallationURL>
- <pfs:licenseURL/>
- <pfs:needsRestart>false</pfs:needsRestart>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin-results:application/x-broken-installer">
- <pfs:plugins><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{949a51e0-c633-4d9e-bf3a-6e0c2bc6e508}"/>
- </RDF:Seq></pfs:plugins>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{949a51e0-c633-4d9e-bf3a-6e0c2bc6e508}">
- <pfs:updates><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{949a51e0-c633-4d9e-bf3a-6e0c2bc6e508}:"/>
- </RDF:Seq></pfs:updates>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{949a51e0-c633-4d9e-bf3a-6e0c2bc6e508}:">
- <pfs:name>Test plugin 2</pfs:name>
- <pfs:requestedMimetype>application/x-broken-installer</pfs:requestedMimetype>
- <pfs:guid>{949a51e0-c633-4d9e-bf3a-6e0c2bc6e508}</pfs:guid>
- <pfs:version/>
- <pfs:IconUrl/>
- <pfs:InstallerLocation>http://example.com/browser/toolkit/mozapps/plugins/tests/BadPlugin</pfs:InstallerLocation>
- <pfs:InstallerHash/>
- <pfs:InstallerShowsUI>false</pfs:InstallerShowsUI>
- <pfs:manualInstallationURL>http://www.mozilla.com</pfs:manualInstallationURL>
- <pfs:licenseURL/>
- <pfs:needsRestart>false</pfs:needsRestart>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin-results:application/x-broken-plugin-hash">
- <pfs:plugins><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{cf1765cc-f962-4680-8a4d-2ba13971a24f}"/>
- </RDF:Seq></pfs:plugins>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{cf1765cc-f962-4680-8a4d-2ba13971a24f}">
- <pfs:updates><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{cf1765cc-f962-4680-8a4d-2ba13971a24f}:"/>
- </RDF:Seq></pfs:updates>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{cf1765cc-f962-4680-8a4d-2ba13971a24f}:">
- <pfs:name>Test plugin 3</pfs:name>
- <pfs:requestedMimetype>application/x-broken-plugin-hash</pfs:requestedMimetype>
- <pfs:guid>{8d3ab839-e03e-41a5-acd3-be1eabf94810}</pfs:guid>
- <pfs:version/>
- <pfs:IconUrl/>
- <pfs:InstallerLocation>http://example.com/browser/toolkit/mozapps/plugins/tests/GoodPlugin</pfs:InstallerLocation>
- <pfs:InstallerHash>sha1:foo</pfs:InstallerHash>
- <pfs:InstallerShowsUI>false</pfs:InstallerShowsUI>
- <pfs:manualInstallationURL>http://www.mozilla.com</pfs:manualInstallationURL>
- <pfs:licenseURL/>
- <pfs:needsRestart>false</pfs:needsRestart>
-</RDF:Description>
-
-
-<RDF:Description about="urn:mozilla:plugin-results:application/x-working-extension">
- <pfs:plugins><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{2fdd6830-66fe-43e7-8ef6-ce49998c8926}"/>
- </RDF:Seq></pfs:plugins>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{2fdd6830-66fe-43e7-8ef6-ce49998c8926}">
- <pfs:updates><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{2fdd6830-66fe-43e7-8ef6-ce49998c8926}:"/>
- </RDF:Seq></pfs:updates>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{2fdd6830-66fe-43e7-8ef6-ce49998c8926}:">
- <pfs:name>Test extension 1</pfs:name>
- <pfs:requestedMimetype>application/x-working-extension</pfs:requestedMimetype>
- <pfs:guid>{2fdd6830-66fe-43e7-8ef6-ce49998c8926}</pfs:guid>
- <pfs:version/>
- <pfs:IconUrl/>
- <pfs:XPILocation>http://example.com/browser/toolkit/mozapps/plugins/tests/GoodExtension.xpi</pfs:XPILocation>
- <pfs:XPIHash>sha1:ccda7915ba891cc6fd9d0874b8042be2ecaa2d65</pfs:XPIHash>
- <pfs:InstallerShowsUI>false</pfs:InstallerShowsUI>
- <pfs:manualInstallationURL>http://www.mozilla.com</pfs:manualInstallationURL>
- <pfs:licenseURL/>
- <pfs:needsRestart>false</pfs:needsRestart>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin-results:application/x-broken-extension">
- <pfs:plugins><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{91fdf294-3a51-48c6-b5e8-423b0eb4e84e}"/>
- </RDF:Seq></pfs:plugins>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{91fdf294-3a51-48c6-b5e8-423b0eb4e84e}">
- <pfs:updates><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{91fdf294-3a51-48c6-b5e8-423b0eb4e84e}:"/>
- </RDF:Seq></pfs:updates>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{91fdf294-3a51-48c6-b5e8-423b0eb4e84e}:">
- <pfs:name>Test extension 2</pfs:name>
- <pfs:requestedMimetype>application/x-broken-extension</pfs:requestedMimetype>
- <pfs:guid>{91fdf294-3a51-48c6-b5e8-423b0eb4e84e}</pfs:guid>
- <pfs:version/>
- <pfs:IconUrl/>
- <pfs:XPILocation>http://example.com/browser/toolkit/mozapps/plugins/tests/BadExtension.xpi</pfs:XPILocation>
- <pfs:XPIHash/>
- <pfs:InstallerShowsUI>false</pfs:InstallerShowsUI>
- <pfs:manualInstallationURL>http://www.mozilla.com</pfs:manualInstallationURL>
- <pfs:licenseURL/>
- <pfs:needsRestart>false</pfs:needsRestart>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin-results:application/x-broken-extension-hash">
- <pfs:plugins><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{889d0f32-4c77-4a57-8be1-44d109a210e4}"/>
- </RDF:Seq></pfs:plugins>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{889d0f32-4c77-4a57-8be1-44d109a210e4}">
- <pfs:updates><RDF:Seq>
-  <RDF:li resource="urn:mozilla:plugin:{889d0f32-4c77-4a57-8be1-44d109a210e4}:"/>
- </RDF:Seq></pfs:updates>
-</RDF:Description>
-
-<RDF:Description about="urn:mozilla:plugin:{889d0f32-4c77-4a57-8be1-44d109a210e4}:">
- <pfs:name>Test extension 3</pfs:name>
- <pfs:requestedMimetype>application/x-broken-extension-hash</pfs:requestedMimetype>
- <pfs:guid>{889d0f32-4c77-4a57-8be1-44d109a210e4}</pfs:guid>
- <pfs:version/>
- <pfs:IconUrl/>
- <pfs:XPILocation>http://example.com/browser/toolkit/mozapps/plugins/tests/GoodExtension.xpi</pfs:XPILocation>
- <pfs:XPIHash>sha1:3504e7bd87bad1246b7a016b29bdb50fe41dbc83</pfs:XPIHash>
- <pfs:InstallerShowsUI>false</pfs:InstallerShowsUI>
- <pfs:manualInstallationURL>http://www.mozilla.com</pfs:manualInstallationURL>
- <pfs:licenseURL/>
- <pfs:needsRestart>false</pfs:needsRestart>
-</RDF:Description>
-
-</RDF:RDF>
deleted file mode 100644
--- a/toolkit/mozapps/plugins/tests/pfs_bug435788_2.rdf
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:pfs="http://www.mozilla.org/2004/pfs-rdf#">
-
-</RDF>
--- a/toolkit/themes/windows/mozapps/jar.mn
+++ b/toolkit/themes/windows/mozapps/jar.mn
@@ -74,17 +74,16 @@ toolkit.jar:
         skin/classic/mozapps/plugins/contentPluginStripe.png       (../../shared/plugins/contentPluginStripe.png)
         skin/classic/mozapps/plugins/notifyPluginCrashed.png       (plugins/pluginGeneric-16.png)
         skin/classic/mozapps/plugins/notifyPluginGeneric.png       (plugins/pluginGeneric-16.png)
         skin/classic/mozapps/plugins/pluginGeneric.png             (plugins/pluginGeneric.png)
         skin/classic/mozapps/plugins/pluginBlocked.png             (plugins/pluginBlocked.png)
         skin/classic/mozapps/plugins/pluginBlocked-64.png          (plugins/pluginBlocked-64.png)
         skin/classic/mozapps/plugins/pluginGeneric-16.png          (plugins/pluginGeneric-16.png)
         skin/classic/mozapps/plugins/pluginHelp-16.png             (plugins/pluginHelp-16.png)
-        skin/classic/mozapps/plugins/pluginInstallerWizard.css     (plugins/pluginInstallerWizard.css)
         skin/classic/mozapps/profile/profileicon.png               (profile/profileicon.png)
         skin/classic/mozapps/profile/profileSelection.css          (profile/profileSelection.css)
         skin/classic/mozapps/update/downloadButtons.png            (update/downloadButtons.png)
         skin/classic/mozapps/update/updates.css                    (update/updates.css)
         skin/classic/mozapps/viewsource/viewsource.css             (viewsource/viewsource.css)
 *       skin/classic/mozapps/xpinstall/xpinstallConfirm.css        (extensions/xpinstallConfirm.css)
         skin/classic/mozapps/xpinstall/xpinstallItemGeneric.png    (extensions/extensionGeneric.png)
 
@@ -158,17 +157,16 @@ toolkit.jar:
         skin/classic/aero/mozapps/plugins/contentPluginStripe.png          (../../shared/plugins/contentPluginStripe.png)
         skin/classic/aero/mozapps/plugins/notifyPluginCrashed.png          (plugins/pluginGeneric-16-aero.png)
         skin/classic/aero/mozapps/plugins/notifyPluginGeneric.png          (plugins/pluginGeneric-16-aero.png)
         skin/classic/aero/mozapps/plugins/pluginGeneric.png                (plugins/pluginGeneric-aero.png)
         skin/classic/aero/mozapps/plugins/pluginBlocked.png                (plugins/pluginBlocked-aero.png)
         skin/classic/aero/mozapps/plugins/pluginBlocked-64.png             (plugins/pluginBlocked-64.png)
         skin/classic/aero/mozapps/plugins/pluginGeneric-16.png             (plugins/pluginGeneric-16-aero.png)
         skin/classic/aero/mozapps/plugins/pluginHelp-16.png                (plugins/pluginHelp-16.png)
-        skin/classic/aero/mozapps/plugins/pluginInstallerWizard.css        (plugins/pluginInstallerWizard.css)
         skin/classic/aero/mozapps/profile/profileicon.png                  (profile/profileicon-aero.png)
         skin/classic/aero/mozapps/profile/profileSelection.css             (profile/profileSelection.css)
         skin/classic/aero/mozapps/update/downloadButtons.png               (update/downloadButtons-aero.png)
         skin/classic/aero/mozapps/update/updates.css                       (update/updates.css)
         skin/classic/aero/mozapps/viewsource/viewsource.css                (viewsource/viewsource.css)
 *       skin/classic/aero/mozapps/xpinstall/xpinstallConfirm.css           (extensions/xpinstallConfirm.css)
         skin/classic/aero/mozapps/xpinstall/xpinstallItemGeneric.png       (extensions/extensionGeneric-aero.png)
 #endif