Merge m-c to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 08 Oct 2014 15:57:31 +0200
changeset 209349 5830312dbcb46915c6c3369a7e73b618655197f8
parent 209348 2a12b3e698c9a1abbb26d0ee8adf39843482a290 (current diff)
parent 209331 4bad24a306b29ee04a3dc9edece5ffc43cd57310 (diff)
child 209350 1d454aaf1dec70298aa89ba79c890acab32f85a5
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone35.0a1
Merge m-c to mozilla-inbound
browser/themes/shared/devtools/projecteditor/file-icons-sheet@2x.png
mobile/android/base/resources/layout-xlarge-v11/remote_tabs_child.xml
mobile/android/base/resources/layout-xlarge-v11/remote_tabs_group.xml
mobile/android/base/resources/layout/remote_tabs_child.xml
mobile/android/base/resources/layout/remote_tabs_container_panel.xml
mobile/android/base/resources/layout/remote_tabs_group.xml
mobile/android/base/resources/layout/remote_tabs_setup_panel.xml
mobile/android/base/resources/layout/remote_tabs_verification_panel.xml
mobile/android/base/tabs/RemoteTabsContainerPanel.java
mobile/android/base/tabs/RemoteTabsList.java
mobile/android/base/tabs/RemoteTabsSetupPanel.java
mobile/android/base/tabs/RemoteTabsVerificationPanel.java
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,25 +10,25 @@
   <!--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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <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"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--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="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <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"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "8cad8de0f7b98963537f267151275caed62d5d30", 
+    "revision": "3adc8626bd88ae4a8782d2f478656e8d52d805c2", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,22 +12,22 @@
   <!--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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- 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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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,20 +12,20 @@
   <!--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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <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"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,22 +12,22 @@
   <!--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="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="0bc74ce502672cf0265b24cf3a25d117c3de5e71"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="2665e714beea5dc433862ca6bb8d2b47ffe2f2d1"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <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="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
   <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="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1611,16 +1611,21 @@ pref("loop.ringtone", "chrome://browser/
 pref("loop.retry_delay.start", 60000);
 pref("loop.retry_delay.limit", 300000);
 pref("loop.feedback.baseUrl", "https://input.mozilla.org/api/v1/feedback");
 pref("loop.feedback.product", "Loop");
 pref("loop.debug.loglevel", "Error");
 pref("loop.debug.dispatcher", false);
 pref("loop.debug.websocket", false);
 pref("loop.debug.sdk", false);
+#ifdef DEBUG
+pref("loop.CSP", "default-src 'self' about: file: chrome: http://localhost:*; img-src 'self' data: http://www.gravatar.com/ about: file: chrome:; font-src 'none'; connect-src wss://*.tokbox.com https://*.opentok.com https://*.tokbox.com wss://*.mozilla.com https://*.mozilla.org wss://*.mozaws.net http://localhost:* ws://localhost:*");
+#else
+pref("loop.CSP", "default-src 'self' about: file: chrome:; img-src 'self' data: http://www.gravatar.com/ about: file: chrome:; font-src 'none'; connect-src wss://*.tokbox.com https://*.opentok.com https://*.tokbox.com wss://*.mozilla.com https://*.mozilla.org wss://*.mozaws.net");
+#endif
 pref("loop.oauth.google.redirect_uri", "urn:ietf:wg:oauth:2.0:oob:auto");
 pref("loop.oauth.google.scope", "https://www.google.com/m8/feeds");
 
 // serverURL to be assigned by services team
 pref("services.push.serverURL", "wss://push.services.mozilla.com/");
 
 pref("social.sidebar.unload_timeout_ms", 10000);
 
--- a/browser/base/content/newtab/intro.js
+++ b/browser/base/content/newtab/intro.js
@@ -2,18 +2,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #endif
 
 const PREF_INTRO_SHOWN = "browser.newtabpage.introShown";
 
 let gIntro = {
-  _introShown: Services.prefs.getBoolPref(PREF_INTRO_SHOWN),
-
   _nodeIDSuffixes: [
     "panel",
     "what",
   ],
 
   _nodes: {},
 
   init: function() {
@@ -21,17 +19,17 @@ let gIntro = {
       this._nodes[idSuffix] = document.getElementById("newtab-intro-" + idSuffix);
     }
 
     this._nodes.panel.addEventListener("popupshowing", e => this._setUpPanel());
     this._nodes.what.addEventListener("click", e => this.showPanel());
   },
 
   showIfNecessary: function() {
-    if (!this._introShown) {
+    if (!Services.prefs.getBoolPref(PREF_INTRO_SHOWN)) {
       Services.prefs.setBoolPref(PREF_INTRO_SHOWN, true);
       this.showPanel();
     }
   },
 
   showPanel: function() {
     // Point the panel at the 'what' link
     this._nodes.panel.openPopup(this._nodes.what);
--- a/browser/base/content/test/general/browser_devices_get_user_media_about_urls.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media_about_urls.js
@@ -7,16 +7,17 @@ const kObservedTopics = [
   "getUserMedia:revoke",
   "getUserMedia:response:deny",
   "getUserMedia:request",
   "recording-device-events",
   "recording-window-ended"
 ];
 
 const PREF_PERMISSION_FAKE = "media.navigator.permission.fake";
+const PREF_LOOP_CSP = "loop.CSP";
 
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
                                    "@mozilla.org/mediaManagerService;1",
                                    "nsIMediaManagerService");
 
 var gTab;
@@ -157,30 +158,34 @@ fakeLoopAboutModule.prototype = {
            Ci.nsIAboutModule.ALLOW_SCRIPT |
            Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
   }
 };
 
 let factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
 let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
 
+let originalLoopCsp = Services.prefs.getCharPref(PREF_LOOP_CSP);
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
   kObservedTopics.forEach(topic => {
     Services.obs.removeObserver(observer, topic);
   });
   Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
+  Services.prefs.setCharPref(PREF_LOOP_CSP, originalLoopCsp);
 });
 
 
 let gTests = [
 
 {
   desc: "getUserMedia about:loopconversation shouldn't prompt",
   run: function checkAudioVideoLoop() {
+    Services.prefs.setCharPref(PREF_LOOP_CSP, "default-src 'unsafe-inline'");
+
     let classID = Cc["@mozilla.org/uuid-generator;1"]
                     .getService(Ci.nsIUUIDGenerator).generateUUID();
     registrar.registerFactory(classID, "",
                               "@mozilla.org/network/protocol/about;1?what=loopconversation",
                               factory);
 
     yield loadPage("about:loopconversation");
 
@@ -193,16 +198,17 @@ let gTests = [
     yield promisePopupNotification("webRTC-sharingDevices");
 
     is(getMediaCaptureState(), "CameraAndMicrophone",
        "expected camera and microphone to be shared");
 
     yield closeStream();
 
     registrar.unregisterFactory(classID, factory);
+    Services.prefs.setCharPref(PREF_LOOP_CSP, originalLoopCsp);
   }
 },
 
 {
   desc: "getUserMedia about:evil should prompt",
   run: function checkAudioVideoNonLoop() {
     let classID = Cc["@mozilla.org/uuid-generator;1"]
                     .getService(Ci.nsIUUIDGenerator).generateUUID();
--- a/browser/components/loop/run-all-loop-tests.sh
+++ b/browser/components/loop/run-all-loop-tests.sh
@@ -4,8 +4,13 @@
 set -e
 
 # Main tests
 ./mach xpcshell-test browser/components/loop/
 ./mach marionette-test browser/components/loop/manifest.ini
 
 # The browser_parsable_css.js can fail if we add some css that isn't parsable.
 ./mach mochitest browser/components/loop/test/mochitest browser/base/content/test/general/browser_parsable_css.js
+
+# The check to make sure that the media devices can be used in Loop without
+# prompting is in browser_devices_get_user_media_about_urls.js. It's possible
+# to mess this up with CSP handling, and probably other changes, too.
+./mach mochitest browser/base/content/test/general/browser_devices_get_user_media_about_urls.js
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -502,17 +502,16 @@ BrowserGlue.prototype = {
 
     this._syncSearchEngines();
 
     WebappManager.init();
     PageThumbs.init();
     NewTabUtils.init();
     DirectoryLinksProvider.init();
     NewTabUtils.links.addProvider(DirectoryLinksProvider);
-    BrowserNewTabPreloader.init();
 #ifdef NIGHTLY_BUILD
     if (Services.prefs.getBoolPref("dom.identity.enabled")) {
       SignInToWebsiteUX.init();
     }
 #endif
 #ifdef NIGHTLY_BUILD
     ShumwayUtils.init();
 #endif
@@ -2238,17 +2237,17 @@ let DefaultBrowserCheck = {
         accessKey: optionsKey,
         popup: this.OPTIONPOPUP
       }
     ];
 
 
     let iconPixels = win.devicePixelRatio > 1 ? "32" : "16";
     let iconURL = "chrome://branding/content/icon" + iconPixels + ".png";
-    const priority = notificationBox.PRIORITY_INFO_HIGH;
+    const priority = notificationBox.PRIORITY_WARNING_HIGH;
     let callback = this._onNotificationEvent.bind(this);
     this._notification = notificationBox.appendNotification(promptMessage, "default-browser",
                                                             iconURL, priority, buttons,
                                                             callback);
     this._notification.persistence = -1;
   },
 
   _onNotificationEvent: function(eventType) {
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -392,17 +392,16 @@
           const kXULNS =
                "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
           var engines = this.engines;
           for (var i = engines.length - 1; i >= 0; --i) {
             var menuitem = document.createElementNS(kXULNS, "menuitem");
             var name = engines[i].name;
             menuitem.setAttribute("label", name);
-            menuitem.setAttribute("id", name);
             menuitem.setAttribute("class", "menuitem-iconic searchbar-engine-menuitem menuitem-with-favicon");
             // Since this menu is rebuilt by the observer method whenever a new
             // engine is selected, the "selected" attribute does not need to be
             // explicitly cleared anywhere.
             if (engines[i] == this.currentEngine)
               menuitem.setAttribute("selected", "true");
             var tooltip = this._stringBundle.getFormattedString("searchtip", [name]);
             menuitem.setAttribute("tooltiptext", tooltip);
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -182,17 +182,17 @@ skip-if = true # Needs to be rewritten a
 [browser_687710_2.js]
 [browser_694378.js]
 [browser_701377.js]
 [browser_705597.js]
 [browser_707862.js]
 [browser_739531.js]
 [browser_739805.js]
 [browser_819510_perwindowpb.js]
-skip-if = os == "linux" # Intermittent failures, bug 894063
+skip-if = os == "linux" || e10s # Linux: Intermittent failures, bug 894063; e10s: Bug 1079073
 
 # Disabled for frequent intermittent failures
 [browser_464620_a.js]
 skip-if = true
 [browser_464620_b.js]
 skip-if = true
 
 # Disabled on OS X:
--- a/browser/devtools/framework/sidebar.js
+++ b/browser/devtools/framework/sidebar.js
@@ -44,16 +44,18 @@ function ToolSidebar(tabbox, panel, uid,
 
   this._tabbox.tabpanels.addEventListener("select", this, true);
 
   this._tabs = new Map();
 
   if (!showTabstripe) {
     this._tabbox.setAttribute("hidetabs", "true");
   }
+
+  this._toolPanel.emit("sidebar-created", this);
 }
 
 exports.ToolSidebar = ToolSidebar;
 
 ToolSidebar.prototype = {
   /**
    * Register a tab. A tab is a document.
    * The document must have a title, which will be used as the name of the tab.
@@ -205,24 +207,28 @@ ToolSidebar.prototype = {
   /**
    * Show the sidebar.
    */
   show: function ToolSidebar_show() {
     if (this._width) {
       this._tabbox.width = this._width;
     }
     this._tabbox.removeAttribute("hidden");
+
+    this.emit("show");
   },
 
   /**
    * Show the sidebar.
    */
   hide: function ToolSidebar_hide() {
     Services.prefs.setIntPref("devtools.toolsidebar-width." + this._uid, this._tabbox.width);
     this._tabbox.setAttribute("hidden", "true");
+
+    this.emit("hide");
   },
 
   /**
    * Return the window containing the tab content.
    */
   getWindowForTab: function ToolSidebar_getWindowForTab(id) {
     if (!this._tabs.has(id)) {
       return null;
@@ -252,16 +258,18 @@ ToolSidebar.prototype = {
     while (this._tabbox.tabs.hasChildNodes()) {
       this._tabbox.tabs.removeChild(this._tabbox.tabs.firstChild);
     }
 
     if (this._currentTool) {
       this._telemetry.toolClosed(this._currentTool);
     }
 
+    this._toolPanel.emit("sidebar-destroyed", this);
+
     this._tabs = null;
     this._tabbox = null;
     this._panelDoc = null;
     this._toolPanel = null;
 
     return promise.resolve(null);
   },
 }
--- a/browser/devtools/framework/test/browser.ini
+++ b/browser/devtools/framework/test/browser.ini
@@ -25,16 +25,17 @@ skip-if = e10s # Bug 1030318
 [browser_toolbox_options_disable_js.js]
 skip-if = e10s # Bug 1070837 - devtools/framework/toolbox.js |doc| getter not e10s friendly
 # [browser_toolbox_raise.js] # Bug 962258
 # skip-if = os == "win"
 [browser_toolbox_ready.js]
 [browser_toolbox_select_event.js]
 skip-if = e10s # Bug 1069044 - destroyInspector may hang during shutdown
 [browser_toolbox_sidebar.js]
+[browser_toolbox_sidebar_events.js]
 [browser_toolbox_tabsswitch_shortcuts.js]
 [browser_toolbox_tool_ready.js]
 [browser_toolbox_tool_remote_reopen.js]
 [browser_toolbox_window_reload_target.js]
 [browser_toolbox_window_shortcuts.js]
 [browser_toolbox_window_title_changes.js]
 [browser_toolbox_zoom.js]
 [browser_toolbox_custom_host.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_sidebar_events.js
@@ -0,0 +1,90 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  const Cu = Components.utils;
+  const { ToolSidebar } = devtools.require("devtools/framework/sidebar");
+
+  const toolURL = "data:text/xml;charset=utf8,<?xml version='1.0'?>" +
+                  "<?xml-stylesheet href='chrome://browser/skin/devtools/common.css' type='text/css'?>" +
+                  "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'>" +
+                  "<hbox flex='1'><description flex='1'>foo</description><splitter class='devtools-side-splitter'/>" +
+                  "<tabbox flex='1' id='sidebar' class='devtools-sidebar-tabs'><tabs/><tabpanels flex='1'/></tabbox>" +
+                  "</hbox>" +
+                  "</window>";
+
+  const tab1URL = "data:text/html;charset=utf8,<title>1</title><p>1</p>";
+
+  let collectedEvents = [];
+
+  let toolDefinition = {
+    id: "testTool1072208",
+    visibilityswitch: "devtools.testTool1072208.enabled",
+    url: toolURL,
+    label: "Test tool",
+    isTargetSupported: function() true,
+    build: function(iframeWindow, toolbox) {
+      let deferred = promise.defer();
+      executeSoon(() => {
+        deferred.resolve({
+          target: toolbox.target,
+          toolbox: toolbox,
+          isReady: true,
+          destroy: function(){},
+          panelDoc: iframeWindow.document,
+        });
+      });
+      return deferred.promise;
+    },
+  };
+
+  gDevTools.registerTool(toolDefinition);
+
+  addTab("about:blank").then(function(aTab) {
+    let target = TargetFactory.forTab(aTab);
+    gDevTools.showToolbox(target, toolDefinition.id).then(function(toolbox) {
+      let panel = toolbox.getPanel(toolDefinition.id);
+      ok(true, "Tool open");
+
+      panel.once("sidebar-created", function(event, id) {
+        collectedEvents.push(event);
+      });
+
+      panel.once("sidebar-destroyed", function(event, id) {
+        collectedEvents.push(event);
+      });
+
+      let tabbox = panel.panelDoc.getElementById("sidebar");
+      panel.sidebar = new ToolSidebar(tabbox, panel, "testbug1072208", true);
+
+      panel.sidebar.once("show", function(event, id) {
+        collectedEvents.push(event);
+      });
+
+      panel.sidebar.once("hide", function(event, id) {
+        collectedEvents.push(event);
+      });
+
+      panel.sidebar.once("tab1-selected", () => finishUp(panel));
+      panel.sidebar.addTab("tab1", tab1URL, true);
+      panel.sidebar.show();
+    }).then(null, console.error);
+  });
+
+  function finishUp(panel) {
+    panel.sidebar.hide();
+    panel.sidebar.destroy();
+
+    let events = collectedEvents.join(":");
+    is(events, "sidebar-created:show:hide:sidebar-destroyed",
+      "Found the right amount of collected events.");
+
+    gDevTools.unregisterTool(toolDefinition.id);
+    gBrowser.removeCurrentTab();
+
+    executeSoon(function() {
+      finish();
+    });
+  }
+}
+
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -892,16 +892,25 @@ Toolbox.prototype = {
       // be fired with the panel as an argument. However, in order to keep
       // backward compatibility with existing extensions do a check
       // for a promise return value.
       let built = definition.build(iframe.contentWindow, this);
       if (!(built instanceof Promise)) {
         let panel = built;
         iframe.panel = panel;
 
+        // The panel instance is expected to fire (and listen to) various
+        // framework events, so make sure it's properly decorated with
+        // appropriate API (on, off, once, emit).
+        // In this case we decorate panel instances directly returned by
+        // the tool definition 'build' method.
+        if (typeof panel.emit == "undefined") {
+          EventEmitter.decorate(panel);
+        }
+
         gDevTools.emit(id + "-build", this, panel);
         this.emit(id + "-build", panel);
 
         // The panel can implement an 'open' method for asynchronous
         // initialization sequence.
         if (typeof panel.open == "function") {
           built = panel.open();
         } else {
@@ -910,16 +919,24 @@ Toolbox.prototype = {
           built = deferred.promise;
         }
       }
 
       // Wait till the panel is fully ready and fire 'ready' events.
       promise.resolve(built).then((panel) => {
         this._toolPanels.set(id, panel);
 
+        // Make sure to decorate panel object with event API also in case
+        // where the tool definition 'build' method returns only a promise
+        // and the actual panel instance is available as soon as the
+        // promise is resolved.
+        if (typeof panel.emit == "undefined") {
+          EventEmitter.decorate(panel);
+        }
+
         gDevTools.emit(id + "-ready", this, panel);
         this.emit(id + "-ready", panel);
 
         deferred.resolve(panel);
       }, console.error);
     };
 
     iframe.setAttribute("src", definition.url);
--- a/browser/devtools/projecteditor/lib/tree.js
+++ b/browser/devtools/projecteditor/lib/tree.js
@@ -49,19 +49,16 @@ var ResourceContainer = Class({
     this.highlighter.classList.add("highlighter");
     this.line.appendChild(this.highlighter);
 
     this.expander = doc.createElementNS(HTML_NS, "span");
     this.expander.className = "arrow expander";
     this.expander.setAttribute("open", "");
     this.line.appendChild(this.expander);
 
-    this.icon = doc.createElementNS(HTML_NS, "span");
-    this.line.appendChild(this.icon);
-
     this.label = doc.createElementNS(HTML_NS, "span");
     this.label.className = "file-label";
     this.line.appendChild(this.label);
 
     this.line.addEventListener("contextmenu", (ev) => {
       this.select();
       this.openContextMenu(ev);
     }, false);
@@ -88,21 +85,20 @@ var ResourceContainer = Class({
       this.expanded = false;
     }
     this.update();
   },
 
   destroy: function() {
     this.elt.remove();
     this.expander.remove();
-    this.icon.remove();
     this.highlighter.remove();
     this.children.remove();
     this.label.remove();
-    this.elt = this.expander = this.icon = this.highlighter = this.children = this.label = null;
+    this.elt = this.expander = this.highlighter = this.children = this.label = null;
   },
 
   /**
    * Open the context menu when right clicking on the view.
    * XXX: We could pass this to plugins to allow themselves
    * to be register/remove items from the context menu if needed.
    *
    * @param Event e
@@ -120,39 +116,16 @@ var ResourceContainer = Class({
     let visible = this.tree.options.resourceVisible ?
       this.tree.options.resourceVisible(this.resource) :
       true;
 
     this.elt.hidden = !visible;
 
     this.tree.options.resourceFormatter(this.resource, this.label);
 
-    this.icon.className = "file-icon";
-
-    let contentCategory = this.resource.contentCategory;
-    let baseName = this.resource.basename || "";
-
-    if (!this.resource.parent) {
-      this.icon.classList.add("icon-none");
-    } else if (this.resource.isDir) {
-      this.icon.classList.add("icon-folder");
-    } else if (baseName.endsWith(".manifest") || baseName.endsWith(".webapp")) {
-      this.icon.classList.add("icon-manifest");
-    } else if (contentCategory === "js") {
-      this.icon.classList.add("icon-js");
-    } else if (contentCategory === "css") {
-      this.icon.classList.add("icon-css");
-    } else if (contentCategory === "html") {
-      this.icon.classList.add("icon-html");
-    } else if (contentCategory === "image") {
-      this.icon.classList.add("icon-img");
-    } else {
-      this.icon.classList.add("icon-file");
-    }
-
     this.expander.style.visibility = this.resource.hasChildren ? "visible" : "hidden";
 
   },
 
   /**
    * Select this view in the ProjectTreeView.
    */
   select: function() {
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -40,16 +40,17 @@ const FALLBACK_CHARSET_LIST = "intl.fall
 
 const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
 
 const require   = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
 
 const Telemetry = require("devtools/shared/telemetry");
 const Editor    = require("devtools/sourceeditor/editor");
 const TargetFactory = require("devtools/framework/target").TargetFactory;
+const EventEmitter = require("devtools/toolkit/event-emitter");
 
 const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
 Cu.import("resource://gre/modules/jsdebugger.jsm");
 Cu.import("resource:///modules/devtools/gDevTools.jsm");
@@ -2164,16 +2165,20 @@ ScratchpadTarget.prototype = Heritage.ex
 
 
 /**
  * Encapsulates management of the sidebar containing the VariablesView for
  * object inspection.
  */
 function ScratchpadSidebar(aScratchpad)
 {
+  // Make sure to decorate this object. ToolSidebar requires the parent
+  // panel to support event (emit) API.
+  EventEmitter.decorate(this);
+
   let ToolSidebar = require("devtools/framework/sidebar").ToolSidebar;
   let tabbox = document.querySelector("#scratchpad-sidebar");
   this._sidebar = new ToolSidebar(tabbox, this, "scratchpad");
   this._scratchpad = aScratchpad;
 }
 
 ScratchpadSidebar.prototype = {
   /*
--- a/browser/modules/BrowserNewTabPreloader.jsm
+++ b/browser/modules/BrowserNewTabPreloader.jsm
@@ -13,58 +13,60 @@ const Ci = Components.interfaces;
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='win'/>";
 const NEWTAB_URL = "about:newtab";
-const PREF_BRANCH = "browser.newtab.";
+
+const PREF_NEWTAB_URL = "browser.newtab.url";
+const PREF_NEWTAB_PRELOAD = "browser.newtab.preload";
 
 // The interval between swapping in a preload docShell and kicking off the
 // next preload in the background.
 const PRELOADER_INTERVAL_MS = 600;
 // The number of miliseconds we'll wait after we received a notification that
 // causes us to update our list of browsers and tabbrowser sizes. This acts as
 // kind of a damper when too many events are occuring in quick succession.
 const PRELOADER_UPDATE_DELAY_MS = 3000;
 
 const TOPIC_TIMER_CALLBACK = "timer-callback";
 const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished";
 const TOPIC_XUL_WINDOW_CLOSED = "xul-window-destroyed";
 
 const BROWSER_CONTENT_SCRIPT = "chrome://browser/content/content.js";
 
+function isPreloadingEnabled() {
+  return Services.prefs.getBoolPref(PREF_NEWTAB_PRELOAD) &&
+         !Services.prefs.prefHasUserValue(PREF_NEWTAB_URL);
+}
+
 function createTimer(obj, delay) {
   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   timer.init(obj, delay, Ci.nsITimer.TYPE_ONE_SHOT);
   return timer;
 }
 
 function clearTimer(timer) {
   if (timer) {
     timer.cancel();
   }
   return null;
 }
 
 this.BrowserNewTabPreloader = {
-  init: function Preloader_init() {
-    Preferences.init();
-  },
-
   uninit: function Preloader_uninit() {
     HostFrame.destroy();
-    Preferences.uninit();
     HiddenBrowsers.uninit();
   },
 
   newTab: function Preloader_newTab(aTab) {
-    if (!Preferences.enabled) {
+    if (!isPreloadingEnabled()) {
       return false;
     }
 
     let win = aTab.ownerDocument.defaultView;
     if (win.gBrowser) {
       let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
                      .getInterface(Ci.nsIDOMWindowUtils);
 
@@ -76,51 +78,16 @@ this.BrowserNewTabPreloader = {
     }
 
     return false;
   }
 };
 
 Object.freeze(BrowserNewTabPreloader);
 
-let Preferences = {
-  _enabled: null,
-  _branch: null,
-
-  get enabled() {
-    if (this._enabled === null) {
-      this._enabled = this._branch.getBoolPref("preload") &&
-                      !this._branch.prefHasUserValue("url");
-    }
-
-    return this._enabled;
-  },
-
-  init: function Preferences_init() {
-    this._branch = Services.prefs.getBranch(PREF_BRANCH);
-    this._branch.addObserver("", this, false);
-  },
-
-  uninit: function Preferences_uninit() {
-    if (this._branch) {
-      this._branch.removeObserver("", this);
-      this._branch = null;
-    }
-  },
-
-  observe: function Preferences_observe() {
-    let prevEnabled = this._enabled;
-    this._enabled = null;
-
-    if (prevEnabled && !this.enabled) {
-      HiddenBrowsers.uninit();
-    }
-  },
-};
-
 let HiddenBrowsers = {
   _browsers: null,
   _updateTimer: null,
 
   _topics: [
     TOPIC_DELAYED_STARTUP,
     TOPIC_XUL_WINDOW_CLOSED
   ],
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -337,17 +337,16 @@ browser.jar:
   skin/classic/browser/devtools/cubic-bezier-swatch@2x.png  (../shared/devtools/images/cubic-bezier-swatch@2x.png)
   skin/classic/browser/devtools/undock@2x.png               (../shared/devtools/images/undock@2x.png)
   skin/classic/browser/devtools/font-inspector.css          (../shared/devtools/font-inspector.css)
   skin/classic/browser/devtools/computedview.css            (../shared/devtools/computedview.css)
   skin/classic/browser/devtools/arrow-e.png                 (../shared/devtools/images/arrow-e.png)
   skin/classic/browser/devtools/arrow-e@2x.png              (../shared/devtools/images/arrow-e@2x.png)
   skin/classic/browser/devtools/responsiveui-home.png       (../shared/devtools/responsiveui-home.png)
   skin/classic/browser/devtools/projecteditor/projecteditor.css         (../shared/devtools/projecteditor/projecteditor.css)
-  skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png       (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
   skin/classic/browser/devtools/app-manager/connection-footer.css     (../shared/devtools/app-manager/connection-footer.css)
   skin/classic/browser/devtools/app-manager/index.css                 (../shared/devtools/app-manager/index.css)
   skin/classic/browser/devtools/app-manager/device.css                (../shared/devtools/app-manager/device.css)
   skin/classic/browser/devtools/app-manager/projects.css              (../shared/devtools/app-manager/projects.css)
   skin/classic/browser/devtools/app-manager/help.css                  (../shared/devtools/app-manager/help.css)
   skin/classic/browser/devtools/app-manager/warning.svg               (../shared/devtools/app-manager/images/warning.svg)
   skin/classic/browser/devtools/app-manager/error.svg                 (../shared/devtools/app-manager/images/error.svg)
   skin/classic/browser/devtools/app-manager/plus.svg                  (../shared/devtools/app-manager/images/plus.svg)
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -467,17 +467,16 @@ browser.jar:
   skin/classic/browser/devtools/cubic-bezier-swatch@2x.png  (../shared/devtools/images/cubic-bezier-swatch@2x.png)
   skin/classic/browser/devtools/undock@2x.png               (../shared/devtools/images/undock@2x.png)
   skin/classic/browser/devtools/font-inspector.css          (../shared/devtools/font-inspector.css)
   skin/classic/browser/devtools/computedview.css            (../shared/devtools/computedview.css)
   skin/classic/browser/devtools/arrow-e.png                 (../shared/devtools/images/arrow-e.png)
   skin/classic/browser/devtools/arrow-e@2x.png              (../shared/devtools/images/arrow-e@2x.png)
   skin/classic/browser/devtools/responsiveui-home.png       (../shared/devtools/responsiveui-home.png)
   skin/classic/browser/devtools/projecteditor/projecteditor.css         (../shared/devtools/projecteditor/projecteditor.css)
-  skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png       (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
   skin/classic/browser/devtools/app-manager/connection-footer.css     (../shared/devtools/app-manager/connection-footer.css)
   skin/classic/browser/devtools/app-manager/index.css                 (../shared/devtools/app-manager/index.css)
   skin/classic/browser/devtools/app-manager/device.css                (../shared/devtools/app-manager/device.css)
   skin/classic/browser/devtools/app-manager/projects.css              (../shared/devtools/app-manager/projects.css)
   skin/classic/browser/devtools/app-manager/help.css                  (../shared/devtools/app-manager/help.css)
   skin/classic/browser/devtools/app-manager/warning.svg               (../shared/devtools/app-manager/images/warning.svg)
   skin/classic/browser/devtools/app-manager/error.svg                 (../shared/devtools/app-manager/images/error.svg)
   skin/classic/browser/devtools/app-manager/plus.svg                  (../shared/devtools/app-manager/images/plus.svg)
deleted file mode 100644
index 39672e1fbefd907a0b3cf46be241487a3f1ce95d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/shared/devtools/projecteditor/projecteditor.css
+++ b/browser/themes/shared/devtools/projecteditor/projecteditor.css
@@ -73,59 +73,16 @@
 }
 
 .entry .file-label {
   display: flex;
   flex: 1;
   align-items: center;
 }
 
-.entry .file-icon {
-  display: inline-block;
-  background: url(file-icons-sheet@2x.png);
-  background-size: 140px 15px;
-  background-repeat: no-repeat;
-  width: 20px;
-  height: 15px;
-  background-position: -40px 0;
-  flex-shrink: 0;
-}
-
-.entry .file-icon.icon-none {
-  display: none;
-}
-
-.entry .icon-css {
-  background-position: 0 0;
-}
-
-.entry .icon-js {
-  background-position: -20px 0;
-}
-
-.entry .icon-html {
-  background-position: -40px 0;
-}
-
-.entry .icon-file {
-  background-position: -60px 0;
-}
-
-.entry .icon-folder {
-  background-position: -80px 0;
-}
-
-.entry .icon-img {
-  background-position: -100px 0;
-}
-
-.entry .icon-manifest {
-  background-position: -120px 0;
-}
-
 .entry {
   border: none;
   box-shadow: none;
   white-space: nowrap;
   cursor: pointer;
 }
 
 .entry:hover:not(.entry-group-title):not(.selected) {
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -373,17 +373,16 @@ browser.jar:
         skin/classic/browser/devtools/cubic-bezier-swatch@2x.png    (../shared/devtools/images/cubic-bezier-swatch@2x.png)
         skin/classic/browser/devtools/undock@2x.png                 (../shared/devtools/images/undock@2x.png)
         skin/classic/browser/devtools/font-inspector.css            (../shared/devtools/font-inspector.css)
         skin/classic/browser/devtools/computedview.css              (../shared/devtools/computedview.css)
         skin/classic/browser/devtools/arrow-e.png                   (../shared/devtools/images/arrow-e.png)
         skin/classic/browser/devtools/arrow-e@2x.png                (../shared/devtools/images/arrow-e@2x.png)
         skin/classic/browser/devtools/responsiveui-home.png         (../shared/devtools/responsiveui-home.png)
         skin/classic/browser/devtools/projecteditor/projecteditor.css           (../shared/devtools/projecteditor/projecteditor.css)
-        skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png       (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
         skin/classic/browser/devtools/app-manager/connection-footer.css     (../shared/devtools/app-manager/connection-footer.css)
         skin/classic/browser/devtools/app-manager/index.css                 (../shared/devtools/app-manager/index.css)
         skin/classic/browser/devtools/app-manager/device.css                (../shared/devtools/app-manager/device.css)
         skin/classic/browser/devtools/app-manager/projects.css              (../shared/devtools/app-manager/projects.css)
         skin/classic/browser/devtools/app-manager/help.css                  (../shared/devtools/app-manager/help.css)
         skin/classic/browser/devtools/app-manager/warning.svg               (../shared/devtools/app-manager/images/warning.svg)
         skin/classic/browser/devtools/app-manager/error.svg                 (../shared/devtools/app-manager/images/error.svg)
         skin/classic/browser/devtools/app-manager/plus.svg                  (../shared/devtools/app-manager/images/plus.svg)
@@ -801,17 +800,16 @@ browser.jar:
         skin/classic/aero/browser/devtools/cubic-bezier-swatch@2x.png  (../shared/devtools/images/cubic-bezier-swatch@2x.png)
         skin/classic/aero/browser/devtools/undock@2x.png             (../shared/devtools/images/undock@2x.png)
         skin/classic/aero/browser/devtools/font-inspector.css        (../shared/devtools/font-inspector.css)
         skin/classic/aero/browser/devtools/computedview.css          (../shared/devtools/computedview.css)
         skin/classic/aero/browser/devtools/arrow-e.png               (../shared/devtools/images/arrow-e.png)
         skin/classic/aero/browser/devtools/arrow-e@2x.png               (../shared/devtools/images/arrow-e@2x.png)
         skin/classic/browser/devtools/responsiveui-home.png          (../shared/devtools/responsiveui-home.png)
         skin/classic/aero/browser/devtools/projecteditor/projecteditor.css       (../shared/devtools/projecteditor/projecteditor.css)
-        skin/classic/aero/browser/devtools/projecteditor/file-icons-sheet@2x.png       (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
         skin/classic/aero/browser/devtools/app-manager/connection-footer.css     (../shared/devtools/app-manager/connection-footer.css)
         skin/classic/aero/browser/devtools/app-manager/index.css                 (../shared/devtools/app-manager/index.css)
         skin/classic/aero/browser/devtools/app-manager/device.css                (../shared/devtools/app-manager/device.css)
         skin/classic/aero/browser/devtools/app-manager/projects.css              (../shared/devtools/app-manager/projects.css)
         skin/classic/aero/browser/devtools/app-manager/help.css                  (../shared/devtools/app-manager/help.css)
         skin/classic/aero/browser/devtools/app-manager/warning.svg               (../shared/devtools/app-manager/images/warning.svg)
         skin/classic/aero/browser/devtools/app-manager/error.svg                 (../shared/devtools/app-manager/images/error.svg)
         skin/classic/aero/browser/devtools/app-manager/plus.svg                  (../shared/devtools/app-manager/images/plus.svg)
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2747,16 +2747,43 @@ AppendCSPFromHeader(nsIContentSecurityPo
                 ("CSP refined with policy: \"%s\"",
                 NS_ConvertUTF16toUTF8(policy).get()));
       }
 #endif
   }
   return NS_OK;
 }
 
+bool
+nsDocument::IsLoopDocument(nsIChannel *aChannel)
+{
+  nsCOMPtr<nsIURI> chanURI;
+  nsresult rv = aChannel->GetOriginalURI(getter_AddRefs(chanURI));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  bool isAbout = false;
+  bool isLoop = false;
+  rv = chanURI->SchemeIs("about", &isAbout);
+  NS_ENSURE_SUCCESS(rv, false);
+  if (isAbout) {
+    nsCOMPtr<nsIURI> loopURI;
+    rv = NS_NewURI(getter_AddRefs(loopURI), "about:loopconversation");
+    NS_ENSURE_SUCCESS(rv, false);
+    rv = chanURI->EqualsExceptRef(loopURI, &isLoop);
+    NS_ENSURE_SUCCESS(rv, false);
+    if (!isLoop) {
+      rv = NS_NewURI(getter_AddRefs(loopURI), "about:looppanel");
+      NS_ENSURE_SUCCESS(rv, false);
+      rv = chanURI->EqualsExceptRef(loopURI, &isLoop);
+      NS_ENSURE_SUCCESS(rv, false);
+    }
+  }
+  return isLoop;
+}
+
 nsresult
 nsDocument::InitCSP(nsIChannel* aChannel)
 {
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   if (!CSPService::sCSPEnabled) {
 #ifdef PR_LOGGING
     PR_LOG(gCspPRLog, PR_LOG_DEBUG,
            ("CSP is disabled, skipping CSP init for document %p", this));
@@ -2800,19 +2827,23 @@ nsDocument::InitCSP(nsIChannel* aChannel
         appsService->GetDefaultCSPByLocalId(appId, appDefaultCSP);
         if (!appDefaultCSP.IsEmpty()) {
           applyAppDefaultCSP = true;
         }
       }
     }
   }
 
+ // Check if this is part of the Loop/Hello service
+ bool applyLoopCSP = IsLoopDocument(aChannel);
+
   // If there's no CSP to apply, go ahead and return early
   if (!applyAppDefaultCSP &&
       !applyAppManifestCSP &&
+      !applyLoopCSP &&
       cspHeaderValue.IsEmpty() &&
       cspROHeaderValue.IsEmpty()) {
 #ifdef PR_LOGGING
     nsCOMPtr<nsIURI> chanURI;
     aChannel->GetURI(getter_AddRefs(chanURI));
     nsAutoCString aspec;
     chanURI->GetAsciiSpec(aspec);
     PR_LOG(gCspPRLog, PR_LOG_DEBUG,
@@ -2875,16 +2906,27 @@ nsDocument::InitCSP(nsIChannel* aChannel
     csp->AppendPolicy(appDefaultCSP, false);
   }
 
   // ----- if the doc is an app and specifies a CSP in its manifest, apply it.
   if (applyAppManifestCSP) {
     csp->AppendPolicy(appManifestCSP, false);
   }
 
+  // ----- if the doc is part of Loop, apply the loop CSP
+  if (applyLoopCSP) {
+    nsAdoptingString loopCSP;
+    loopCSP = Preferences::GetString("loop.CSP");
+    NS_ASSERTION(loopCSP, "Missing loop.CSP preference");
+    // If the pref has been removed, we continue without setting a CSP
+    if (loopCSP) {
+      csp->AppendPolicy(loopCSP, false);
+    }
+  }
+
   // ----- if there's a full-strength CSP header, apply it.
   if (!cspHeaderValue.IsEmpty()) {
     rv = AppendCSPFromHeader(csp, cspHeaderValue, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // ----- if there's a report-only CSP header, apply it.
   if (!cspROHeaderValue.IsEmpty()) {
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1657,16 +1657,17 @@ private:
   mozilla::dom::VisibilityState GetVisibilityState() const;
   void NotifyStyleSheetAdded(nsIStyleSheet* aSheet, bool aDocumentSheet);
   void NotifyStyleSheetRemoved(nsIStyleSheet* aSheet, bool aDocumentSheet);
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   nsresult CheckFrameOptions();
+  bool IsLoopDocument(nsIChannel* aChannel);
   nsresult InitCSP(nsIChannel* aChannel);
 
   void FlushCSPWebConsoleErrorQueue()
   {
     mCSPWebConsoleErrorQueue.Flush(this);
   }
 
   /**
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3086,28 +3086,21 @@ CanvasRenderingContext2D::GetHitRegionRe
  */
 struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcessor
 {
   typedef CanvasRenderingContext2D::ContextState ContextState;
 
   virtual void SetText(const char16_t* text, int32_t length, nsBidiDirection direction)
   {
     mFontgrp->UpdateUserFonts(); // ensure user font generation is current
-    // adjust flags for current direction run
-    uint32_t flags = mTextRunFlags;
-    if (direction & 1) {
-      flags |= gfxTextRunFactory::TEXT_IS_RTL;
-    } else {
-      flags &= ~gfxTextRunFactory::TEXT_IS_RTL;
-    }
     mTextRun = mFontgrp->MakeTextRun(text,
                                      length,
                                      mThebes,
                                      mAppUnitsPerDevPixel,
-                                     flags);
+                                     direction==NSBIDI_RTL ? gfxTextRunFactory::TEXT_IS_RTL : 0);
   }
 
   virtual nscoord GetWidth()
   {
     gfxTextRun::Metrics textRunMetrics = mTextRun->MeasureText(0,
                                                                mTextRun->GetLength(),
                                                                mDoMeasureBoundingBox ?
                                                                  gfxFont::TIGHT_INK_EXTENTS :
@@ -3123,38 +3116,34 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
     }
 
     return NSToCoordRound(textRunMetrics.mAdvanceWidth);
   }
 
   virtual void DrawText(nscoord xOffset, nscoord width)
   {
     gfxPoint point = mPt;
-    bool rtl = mTextRun->IsRightToLeft();
-    bool verticalRun = mTextRun->IsVertical();
-
-    gfxFloat& inlineCoord = verticalRun ? point.y : point.x;
-    inlineCoord += xOffset;
+    point.x += xOffset;
 
     // offset is given in terms of left side of string
-    if (rtl) {
+    if (mTextRun->IsRightToLeft()) {
       // Bug 581092 - don't use rounded pixel width to advance to
       // right-hand end of run, because this will cause different
       // glyph positioning for LTR vs RTL drawing of the same
       // glyph string on OS X and DWrite where textrun widths may
       // involve fractional pixels.
       gfxTextRun::Metrics textRunMetrics =
         mTextRun->MeasureText(0,
                               mTextRun->GetLength(),
                               mDoMeasureBoundingBox ?
                                   gfxFont::TIGHT_INK_EXTENTS :
                                   gfxFont::LOOSE_INK_EXTENTS,
                               mThebes,
                               nullptr);
-      inlineCoord += textRunMetrics.mAdvanceWidth;
+      point.x += textRunMetrics.mAdvanceWidth;
       // old code was:
       //   point.x += width * mAppUnitsPerDevPixel;
       // TODO: restore this if/when we move to fractional coords
       // throughout the text layout process
     }
 
     uint32_t numRuns;
     const gfxTextRun::GlyphRun *runs = mTextRun->GetGlyphRuns(&numRuns);
@@ -3163,25 +3152,16 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
     Point baselineOrigin =
       Point(point.x * devUnitsPerAppUnit, point.y * devUnitsPerAppUnit);
 
     float advanceSum = 0;
 
     mCtx->EnsureTarget();
     for (uint32_t c = 0; c < numRuns; c++) {
       gfxFont *font = runs[c].mFont;
-
-      bool verticalFont =
-        runs[c].mOrientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
-
-      const float& baselineOriginInline =
-        verticalFont ? baselineOrigin.y : baselineOrigin.x;
-      const float& baselineOriginBlock =
-        verticalFont ? baselineOrigin.x : baselineOrigin.y;
-
       uint32_t endRun = 0;
       if (c + 1 < numRuns) {
         endRun = runs[c + 1].mCharacterOffset;
       } else {
         endRun = mTextRun->GetLength();
       }
 
       const gfxTextRun::CompressedGlyph *glyphs = mTextRun->GetCharacterGlyphs();
@@ -3189,100 +3169,70 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
       RefPtr<ScaledFont> scaledFont =
         gfxPlatform::GetPlatform()->GetScaledFontForFont(mCtx->mTarget, font);
 
       if (!scaledFont) {
         // This can occur when something switched DirectWrite off.
         return;
       }
 
-      AutoRestoreTransform sidewaysRestore;
-      if (runs[c].mOrientation ==
-          gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT) {
-        sidewaysRestore.Init(mCtx->mTarget);
-        // TODO: The baseline adjustment here is kinda ad-hoc; eventually
-        // perhaps we should check for horizontal and vertical baseline data
-        // in the font, and adjust accordingly.
-        // (The same will be true for HTML text layout.)
-        const gfxFont::Metrics& metrics = mTextRun->GetFontGroup()->
-          GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal);
-        mCtx->mTarget->SetTransform(mCtx->mTarget->GetTransform().Copy().
-          PreTranslate(baselineOrigin).      // translate origin for rotation
-          PreRotate(gfx::Float(M_PI / 2.0)). // turn 90deg clockwise
-          PreTranslate(-baselineOrigin).     // undo the translation
-          PreTranslate(Point(0, metrics.emAscent - metrics.emDescent) / 2));
-                              // and offset the (alphabetic) baseline of the
-                              // horizontally-shaped text from the (centered)
-                              // default baseline used for vertical
-      }
-
       RefPtr<GlyphRenderingOptions> renderingOptions = font->GetGlyphRenderingOptions();
 
       GlyphBuffer buffer;
 
       std::vector<Glyph> glyphBuf;
 
-      // TODO:
-      // This more-or-less duplicates the code found in gfxTextRun::Draw
-      // and the gfxFont methods that uses (Draw, DrawGlyphs, DrawOneGlyph);
-      // it would be nice to refactor and share that code.
       for (uint32_t i = runs[c].mCharacterOffset; i < endRun; i++) {
         Glyph newGlyph;
-
-        float& inlinePos =
-          verticalFont ? newGlyph.mPosition.y : newGlyph.mPosition.x;
-        float& blockPos =
-          verticalFont ? newGlyph.mPosition.x : newGlyph.mPosition.y;
-
         if (glyphs[i].IsSimpleGlyph()) {
           newGlyph.mIndex = glyphs[i].GetSimpleGlyph();
-          if (rtl) {
-            inlinePos = baselineOriginInline - advanceSum -
+          if (mTextRun->IsRightToLeft()) {
+            newGlyph.mPosition.x = baselineOrigin.x - advanceSum -
               glyphs[i].GetSimpleAdvance() * devUnitsPerAppUnit;
           } else {
-            inlinePos = baselineOriginInline + advanceSum;
+            newGlyph.mPosition.x = baselineOrigin.x + advanceSum;
           }
-          blockPos = baselineOriginBlock;
+          newGlyph.mPosition.y = baselineOrigin.y;
           advanceSum += glyphs[i].GetSimpleAdvance() * devUnitsPerAppUnit;
           glyphBuf.push_back(newGlyph);
           continue;
         }
 
         if (!glyphs[i].GetGlyphCount()) {
           continue;
         }
 
-        const gfxTextRun::DetailedGlyph *d = mTextRun->GetDetailedGlyphs(i);
+        gfxTextRun::DetailedGlyph *detailedGlyphs =
+          mTextRun->GetDetailedGlyphs(i);
 
         if (glyphs[i].IsMissing()) {
           newGlyph.mIndex = 0;
-          if (rtl) {
-            inlinePos = baselineOriginInline - advanceSum -
-              d->mAdvance * devUnitsPerAppUnit;
+          if (mTextRun->IsRightToLeft()) {
+            newGlyph.mPosition.x = baselineOrigin.x - advanceSum -
+              detailedGlyphs[0].mAdvance * devUnitsPerAppUnit;
           } else {
-            inlinePos = baselineOriginInline + advanceSum;
+            newGlyph.mPosition.x = baselineOrigin.x + advanceSum;
           }
-          blockPos = baselineOriginBlock;
-          advanceSum += d->mAdvance * devUnitsPerAppUnit;
+          newGlyph.mPosition.y = baselineOrigin.y;
+          advanceSum += detailedGlyphs[0].mAdvance * devUnitsPerAppUnit;
           glyphBuf.push_back(newGlyph);
           continue;
         }
 
-        for (uint32_t c = 0; c < glyphs[i].GetGlyphCount(); c++, d++) {
-          newGlyph.mIndex = d->mGlyphID;
-          if (rtl) {
-            inlinePos = baselineOriginInline - advanceSum -
-              d->mAdvance * devUnitsPerAppUnit;
+        for (uint32_t c = 0; c < glyphs[i].GetGlyphCount(); c++) {
+          newGlyph.mIndex = detailedGlyphs[c].mGlyphID;
+          if (mTextRun->IsRightToLeft()) {
+            newGlyph.mPosition.x = baselineOrigin.x + detailedGlyphs[c].mXOffset * devUnitsPerAppUnit -
+              advanceSum - detailedGlyphs[c].mAdvance * devUnitsPerAppUnit;
           } else {
-            inlinePos = baselineOriginInline + advanceSum;
+            newGlyph.mPosition.x = baselineOrigin.x + detailedGlyphs[c].mXOffset * devUnitsPerAppUnit + advanceSum;
           }
-          inlinePos += d->mXOffset * devUnitsPerAppUnit;
-          blockPos = baselineOriginBlock + d->mYOffset * devUnitsPerAppUnit;
+          newGlyph.mPosition.y = baselineOrigin.y + detailedGlyphs[c].mYOffset * devUnitsPerAppUnit;
           glyphBuf.push_back(newGlyph);
-          advanceSum += d->mAdvance * devUnitsPerAppUnit;
+          advanceSum += detailedGlyphs[c].mAdvance * devUnitsPerAppUnit;
         }
       }
 
       if (!glyphBuf.size()) {
         // This may happen for glyph runs for a 0 size font.
         continue;
       }
 
@@ -3347,19 +3297,16 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
   CanvasRenderingContext2D::TextDrawOperation mOp;
 
   // context state
   ContextState *mState;
 
   // union of bounding boxes of all runs, needed for shadows
   gfxRect mBoundingBox;
 
-  // flags to use when creating textrun, based on CSS style
-  uint32_t mTextRunFlags;
-
   // true iff the bounding box should be measured
   bool mDoMeasureBoundingBox;
 };
 
 nsresult
 CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
                                             float aX,
                                             float aY,
@@ -3389,20 +3336,19 @@ CanvasRenderingContext2D::DrawOrMeasureT
 
   // replace all the whitespace characters with U+0020 SPACE
   nsAutoString textToDraw(aRawText);
   TextReplaceWhitespaceCharacters(textToDraw);
 
   // for now, default to ltr if not in doc
   bool isRTL = false;
 
-  nsRefPtr<nsStyleContext> canvasStyle;
   if (mCanvasElement && mCanvasElement->IsInDoc()) {
     // try to find the closest context
-    canvasStyle =
+    nsRefPtr<nsStyleContext> canvasStyle =
       nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement,
                                                     nullptr,
                                                     presShell);
     if (!canvasStyle) {
       return NS_ERROR_FAILURE;
     }
 
     isRTL = canvasStyle->StyleVisibility()->mDirection ==
@@ -3427,24 +3373,16 @@ CanvasRenderingContext2D::DrawOrMeasureT
 
   const ContextState &state = CurrentState();
 
   // This is only needed to know if we can know the drawing bounding box easily.
   bool doCalculateBounds = NeedToCalculateBounds();
 
   CanvasBidiProcessor processor;
 
-  // If we don't have a style context, we can't set up vertical-text flags
-  // (for now, at least; perhaps we need new Canvas API to control this).
-  processor.mTextRunFlags = canvasStyle ?
-    nsLayoutUtils::GetTextRunFlagsForStyle(canvasStyle,
-                                           canvasStyle->StyleFont(),
-                                           canvasStyle->StyleText(),
-                                           0) : 0;
-
   GetAppUnitsValues(&processor.mAppUnitsPerDevPixel, nullptr);
   processor.mPt = gfxPoint(aX, aY);
   processor.mThebes =
     new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
 
   // If we don't have a target then we don't have a transform. A target won't
   // be needed in the case where we're measuring the text size. This allows
   // to avoid creating a target if it's only being used to measure text sizes.
@@ -3501,19 +3439,17 @@ CanvasRenderingContext2D::DrawOrMeasureT
     anchorX = 1;
   }
 
   processor.mPt.x -= anchorX * totalWidth;
 
   // offset pt.y based on text baseline
   processor.mFontgrp->UpdateUserFonts(); // ensure user font generation is current
   const gfxFont::Metrics& fontMetrics =
-    processor.mFontgrp->GetFirstValidFont()->GetMetrics(
-      processor.mTextRun->IsVertical() ? gfxFont::eVertical :
-                                         gfxFont::eHorizontal);
+    processor.mFontgrp->GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal); // XXX vertical?
 
   gfxFloat anchorY;
 
   switch (state.textBaseline)
   {
   case TextBaseline::HANGING:
       // fall through; best we can do with the information available
   case TextBaseline::TOP:
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -6743,17 +6743,24 @@ RilObject.prototype[UNSOLICITED_RESPONSE
     });
 };
 RilObject.prototype[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
   let [typeCode, message] = this.context.Buf.readStringList();
   if (DEBUG) {
     this.context.debug("On USSD. Type Code: " + typeCode + " Message: " + message);
   }
 
-  this._ussdSession = (typeCode != "0" && typeCode != "2");
+  let oldSession = this._ussdSession;
+
+  // Per ril.h the USSD session is assumed to persist if the type code is "1".
+  this._ussdSession = typeCode == "1";
+
+  if (!oldSession && !this._ussdSession && !message) {
+    return;
+  }
 
   this.sendChromeMessage({rilMessageType: "ussdreceived",
                           message: message,
                           sessionEnded: !this._ussdSession});
 };
 RilObject.prototype[UNSOLICITED_ON_USSD_REQUEST] = null;
 RilObject.prototype[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
   let dateString = this.context.Buf.readString();
--- a/gfx/2d/Helpers.h
+++ b/gfx/2d/Helpers.h
@@ -9,20 +9,16 @@
 #include "2D.h"
 
 namespace mozilla {
 namespace gfx {
 
 class AutoRestoreTransform
 {
  public:
-  AutoRestoreTransform()
-  {
-  }
-
   explicit AutoRestoreTransform(DrawTarget *aTarget)
    : mDrawTarget(aTarget),
      mOldTransform(aTarget->GetTransform())
   {
   }
 
   void Init(DrawTarget *aTarget)
   {
--- a/mobile/android/base/AboutPages.java
+++ b/mobile/android/base/AboutPages.java
@@ -1,15 +1,18 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * 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.gecko;
 
+import org.mozilla.gecko.home.HomeConfig;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
+import org.mozilla.gecko.mozglue.RobocopTarget;
 import org.mozilla.gecko.util.StringUtils;
 
 public class AboutPages {
     // All of our special pages.
     public static final String ADDONS          = "about:addons";
     public static final String APPS            = "about:apps";
     public static final String CONFIG          = "about:config";
     public static final String DOWNLOADS       = "about:downloads";
@@ -84,10 +87,21 @@ public class AboutPages {
         // TODO: it'd be quicker to not compare the "about:" part every time.
         for (int i = 0; i < DEFAULT_ICON_PAGES.length; ++i) {
             if (DEFAULT_ICON_PAGES[i].equals(url)) {
                 return true;
             }
         }
         return false;
     }
+
+    /**
+     * Get a URL that navigates to the specified built-in Home Panel.
+     *
+     * @param panelType to navigate to.
+     * @return URL.
+     * @throws IllegalArgumentException if the built-in panel type is not a built-in panel.
+     */
+    @RobocopTarget
+    public static String getURLForBuiltinPanelType(PanelType panelType) throws IllegalArgumentException {
+        return HOME + "?panel=" + HomeConfig.getIdForBuiltinPanelType(panelType);
+    }
 }
-
--- a/mobile/android/base/AppConstants.java.in
+++ b/mobile/android/base/AppConstants.java.in
@@ -17,18 +17,16 @@ import android.os.Build;
  * other things.
  *
  * See also SysInfo.java, which includes some of the values available from
  * nsSystemInfo inside Gecko.
  */
 @RobocopTarget
 public class AppConstants {
     public static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
-    // Maintain a separate search package name so that we can speciailize it in the standalone search project
-    public static final String SEARCH_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
     public static final String MANGLED_ANDROID_PACKAGE_NAME = "@MANGLED_ANDROID_PACKAGE_NAME@";
 
     /**
      * Encapsulates access to compile-time version definitions, allowing
      * for dead code removal for particular APKs.
      */
     public static final class Versions {
         public static final int MIN_SDK_VERSION = @MOZ_ANDROID_MIN_SDK_VERSION@;
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1905,16 +1905,17 @@ public abstract class GeckoApp
                 SharedPreferences.Editor editor = prefs.edit();
                 editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, false);
                 currentSession.recordBegin(editor);
                 editor.apply();
 
                 final HealthRecorder rec = mHealthRecorder;
                 if (rec != null) {
                     rec.setCurrentSession(currentSession);
+                    rec.processDelayed();
                 } else {
                     Log.w(LOGTAG, "Can't record session: rec is null.");
                 }
             }
          });
     }
 
     @Override
--- a/mobile/android/base/health/BrowserHealthRecorder.java
+++ b/mobile/android/base/health/BrowserHealthRecorder.java
@@ -12,16 +12,17 @@ import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Scanner;
 import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
@@ -636,22 +637,23 @@ public class BrowserHealthRecorder imple
         }
     }
 
     /*
      * Searches.
      */
 
     public static final String MEASUREMENT_NAME_SEARCH_COUNTS = "org.mozilla.searches.counts";
-    public static final int MEASUREMENT_VERSION_SEARCH_COUNTS = 5;
+    public static final int MEASUREMENT_VERSION_SEARCH_COUNTS = 6;
 
     public static final Set<String> SEARCH_LOCATIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(new String[] {
-        "barkeyword",
-        "barsuggest",
-        "bartext",
+        "barkeyword",    // A search keyword (e.g., "imdb star wars").
+        "barsuggest",    // A suggestion picked after typing in the search bar.
+        "bartext",       // Raw text in the search bar.
+        "activity",      // The search activity.
     })));
 
     void initializeSearchProvider() {
         this.storage.ensureMeasurementInitialized(
             MEASUREMENT_NAME_SEARCH_COUNTS,
             MEASUREMENT_VERSION_SEARCH_COUNTS,
             new MeasurementFields() {
                 @Override
@@ -893,9 +895,47 @@ public class BrowserHealthRecorder imple
             // Continue so we don't hit it next time.
             // Future: record this exception in FHR's own error submitter.
         }
 
         // Track the end of this session in shared prefs, so it doesn't get
         // double-counted on next run.
         session.recordCompletion(editor);
     }
+
+    private static class Search {
+        public final String location;
+        public final String engineID;
+
+        public Search(final String location, final String engineID) {
+            if (!SEARCH_LOCATIONS.contains(location)) {
+                throw new IllegalArgumentException("Unknown search location: " + location);
+            }
+
+            this.location = location;
+            this.engineID = engineID;
+        }
+    }
+
+    private static ConcurrentLinkedQueue<Search> delayedSearches = new ConcurrentLinkedQueue<>();
+
+    public static void recordSearchDelayed(String location, String engineID) {
+        final Search search = new Search(location, engineID);
+        delayedSearches.add(search);
+    }
+
+    @Override
+    public void processDelayed() {
+        if (delayedSearches.isEmpty()) {
+            return;
+        }
+
+        if (this.state != State.INITIALIZED) {
+            Log.d(LOG_TAG, "Not initialized: not processing delayed items. (" + this.state + ")");
+            return;
+        }
+
+        Search poll;
+        while ((poll = delayedSearches.poll()) != null) {
+            recordSearch(poll.engineID, poll.location);
+        }
+    }
 }
--- a/mobile/android/base/health/HealthRecorder.java
+++ b/mobile/android/base/health/HealthRecorder.java
@@ -29,9 +29,11 @@ public interface HealthRecorder {
 
     public void onAppLocaleChanged(String to);
     public void onAddonChanged(String id, JSONObject json);
     public void onAddonUninstalling(String id);
     public void onEnvironmentChanged();
     public void onEnvironmentChanged(final boolean startNewSession, final String sessionEndReason);
 
     public void close();
+
+    public void processDelayed();
 }
--- a/mobile/android/base/health/StubbedHealthRecorder.java
+++ b/mobile/android/base/health/StubbedHealthRecorder.java
@@ -27,9 +27,12 @@ public class StubbedHealthRecorder imple
 
     public void onAppLocaleChanged(String to) { }
     public void onAddonChanged(String id, JSONObject json) { }
     public void onAddonUninstalling(String id) { }
     public void onEnvironmentChanged() { }
     public void onEnvironmentChanged(final boolean startNewSession, final String sessionEndReason) { }
 
     public void close() { }
+
+    @Override
+    public void processDelayed() { }
 }
--- a/mobile/android/base/home/HomeConfig.java
+++ b/mobile/android/base/home/HomeConfig.java
@@ -1,45 +1,46 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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.gecko.home;
 
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEvent;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.home.RemoteTabsPanel;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoEvent;
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.mozglue.RobocopTarget;
+import org.mozilla.gecko.util.ThreadUtils;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
 public final class HomeConfig {
     /**
      * Used to determine what type of HomeFragment subclass to use when creating
      * a given panel. With the exception of DYNAMIC, all of these types correspond
      * to a default set of built-in panels. The DYNAMIC panel type is used by
      * third-party services to create panels with varying types of content.
      */
+    @RobocopTarget
     public static enum PanelType implements Parcelable {
         TOP_SITES("top_sites", TopSitesPanel.class),
         BOOKMARKS("bookmarks", BookmarksPanel.class),
         HISTORY("history", HistoryPanel.class),
         REMOTE_TABS("remote_tabs", RemoteTabsPanel.class),
         READING_LIST("reading_list", ReadingListPanel.class),
         RECENT_TABS("recent_tabs", RecentTabsPanel.class),
         DYNAMIC("dynamic", DynamicPanel.class);
@@ -827,17 +828,16 @@ public final class HomeConfig {
         static final String JSON_KEY_TEXT = "text";
         static final String JSON_KEY_IMAGE_URL = "imageUrl";
 
         public EmptyViewConfig(JSONObject json) throws JSONException, IllegalArgumentException {
             mText = json.optString(JSON_KEY_TEXT, null);
             mImageUrl = json.optString(JSON_KEY_IMAGE_URL, null);
         }
 
-        @SuppressWarnings("unchecked")
         public EmptyViewConfig(Parcel in) {
             mText = in.readString();
             mImageUrl = in.readString();
         }
 
         public EmptyViewConfig(EmptyViewConfig emptyViewConfig) {
             mText = emptyViewConfig.mText;
             mImageUrl = emptyViewConfig.mImageUrl;
@@ -899,17 +899,16 @@ public final class HomeConfig {
         static final String JSON_KEY_IMAGE_URL = "imageUrl";
 
         public AuthConfig(JSONObject json) throws JSONException, IllegalArgumentException {
             mMessageText = json.optString(JSON_KEY_MESSAGE_TEXT);
             mButtonText = json.optString(JSON_KEY_BUTTON_TEXT);
             mImageUrl = json.optString(JSON_KEY_IMAGE_URL, null);
         }
 
-        @SuppressWarnings("unchecked")
         public AuthConfig(Parcel in) {
             mMessageText = in.readString();
             mButtonText = in.readString();
             mImageUrl = in.readString();
 
             validate();
         }
 
@@ -1490,17 +1489,22 @@ public final class HomeConfig {
 
     public interface HomeConfigBackend {
         public State load();
         public void save(State configState);
         public String getLocale();
         public void setOnReloadListener(OnReloadListener listener);
     }
 
-    // UUIDs used to create PanelConfigs for default built-in panels
+    // UUIDs used to create PanelConfigs for default built-in panels. These are
+    // public because they can be used in "about:home?panel=UUID" query strings
+    // to open specific panels without querying the active Home Panel
+    // configuration. Because they don't consider the active configuration, it
+    // is only sensible to do this for built-in panels (and not for dynamic
+    // panels).
     private static final String TOP_SITES_PANEL_ID = "4becc86b-41eb-429a-a042-88fe8b5a094e";
     private static final String BOOKMARKS_PANEL_ID = "7f6d419a-cd6c-4e34-b26f-f68b1b551907";
     private static final String READING_LIST_PANEL_ID = "20f4549a-64ad-4c32-93e4-1dcef792733b";
     private static final String HISTORY_PANEL_ID = "f134bf20-11f7-4867-ab8b-e8e705d7fbe8";
     private static final String RECENT_TABS_PANEL_ID = "5c2601a5-eedc-4477-b297-ce4cef52adf8";
     private static final String REMOTE_TABS_PANEL_ID = "72429afd-8d8b-43d8-9189-14b779c563d0";
 
     private final HomeConfigBackend mBackend;
@@ -1527,54 +1531,69 @@ public final class HomeConfig {
     public void setOnReloadListener(OnReloadListener listener) {
         mBackend.setOnReloadListener(listener);
     }
 
     public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType) {
         return createBuiltinPanelConfig(context, panelType, EnumSet.noneOf(PanelConfig.Flags.class));
     }
 
-    public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType, EnumSet<PanelConfig.Flags> flags) {
-        int titleId = 0;
-        String id = null;
-
+    public static int getTitleResourceIdForBuiltinPanelType(PanelType panelType) {
         switch(panelType) {
-            case TOP_SITES:
-                titleId = R.string.home_top_sites_title;
-                id = TOP_SITES_PANEL_ID;
-                break;
+        case TOP_SITES:
+            return R.string.home_top_sites_title;
+
+        case BOOKMARKS:
+            return R.string.bookmarks_title;
+
+        case HISTORY:
+            return R.string.home_history_title;
 
-            case BOOKMARKS:
-                titleId = R.string.bookmarks_title;
-                id = BOOKMARKS_PANEL_ID;
-                break;
+        case REMOTE_TABS:
+            return R.string.home_remote_tabs_title;
+
+        case READING_LIST:
+            return R.string.reading_list_title;
+
+        case RECENT_TABS:
+            return R.string.recent_tabs_title;
+
+        default:
+            throw new IllegalArgumentException("Only for built-in panel types: " + panelType);
+        }
+    }
 
-            case HISTORY:
-                titleId = R.string.home_history_title;
-                id = HISTORY_PANEL_ID;
-                break;
+    public static String getIdForBuiltinPanelType(PanelType panelType) {
+        switch(panelType) {
+        case TOP_SITES:
+            return TOP_SITES_PANEL_ID;
 
-            case REMOTE_TABS:
-                titleId = R.string.home_remote_tabs_title;
-                id = REMOTE_TABS_PANEL_ID;
-                break;
+        case BOOKMARKS:
+            return BOOKMARKS_PANEL_ID;
+
+        case HISTORY:
+            return HISTORY_PANEL_ID;
+
+        case REMOTE_TABS:
+            return REMOTE_TABS_PANEL_ID;
 
-            case READING_LIST:
-                titleId = R.string.reading_list_title;
-                id = READING_LIST_PANEL_ID;
-                break;
+        case READING_LIST:
+            return READING_LIST_PANEL_ID;
+
+        case RECENT_TABS:
+            return RECENT_TABS_PANEL_ID;
 
-            case RECENT_TABS:
-                titleId = R.string.recent_tabs_title;
-                id = RECENT_TABS_PANEL_ID;
-                break;
+        default:
+            throw new IllegalArgumentException("Only for built-in panel types: " + panelType);
+        }
+    }
 
-            case DYNAMIC:
-                throw new IllegalArgumentException("createBuiltinPanelConfig() is only for built-in panels");
-        }
+    public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType, EnumSet<PanelConfig.Flags> flags) {
+        final int titleId = getTitleResourceIdForBuiltinPanelType(panelType);
+        final String id = getIdForBuiltinPanelType(panelType);
 
         return new PanelConfig(panelType, context.getString(titleId), id, flags);
     }
 
     public static HomeConfig getDefault(Context context) {
         return new HomeConfig(new HomeConfigPrefsBackend(context));
     }
 }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -433,16 +433,20 @@ size. -->
 <!-- Localization note (home_remote_tabs_unhide_selected_devices) : This is
      the text of a button; we expect more than one device. -->
 <!ENTITY home_remote_tabs_unhide_selected_devices "Unhide selected devices">
 
 <!ENTITY private_browsing_title "Private Browsing">
 <!ENTITY private_tabs_panel_empty_desc "Your private tabs will show up here. While we don\'t keep any of your browsing history or cookies, bookmarks and files that you download will still be saved on your device.">
 <!ENTITY private_tabs_panel_learn_more "Want to learn more?">
 
+<!ENTITY remote_tabs_panel_moved_title "Where did my tabs go?">
+<!ENTITY remote_tabs_panel_moved_desc "We\'ve moved your tabs from other devices into a panel on your home page that can be easily accessed every time you open a new tab.">
+<!ENTITY remote_tabs_panel_moved_link "Take me to my new panel.">
+
 <!ENTITY pin_site_dialog_hint "Enter a search keyword">
 
 <!ENTITY filepicker_title "Choose File">
 <!ENTITY filepicker_audio_title "Choose or record a sound">
 <!ENTITY filepicker_image_title "Choose or take a picture">
 <!ENTITY filepicker_video_title "Choose or record a video">
 
 <!-- Site identity popup -->
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -384,21 +384,17 @@ gbjar.sources += [
     'sqlite/SQLiteBridge.java',
     'sqlite/SQLiteBridgeException.java',
     'StartPane.java',
     'SuggestClient.java',
     'SurfaceBits.java',
     'Tab.java',
     'Tabs.java',
     'tabs/PrivateTabsPanel.java',
-    'tabs/RemoteTabsContainerPanel.java',
-    'tabs/RemoteTabsList.java',
     'tabs/RemoteTabsPanel.java',
-    'tabs/RemoteTabsSetupPanel.java',
-    'tabs/RemoteTabsVerificationPanel.java',
     'tabs/TabCurve.java',
     'tabs/TabsGridLayout.java',
     'tabs/TabsLayoutAdapter.java',
     'tabs/TabsLayoutItemView.java',
     'tabs/TabsListLayout.java',
     'tabs/TabsPanel.java',
     'TabsAccessor.java',
     'Telemetry.java',
deleted file mode 100644
--- a/mobile/android/base/resources/layout-xlarge-v11/remote_tabs_child.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:background="@drawable/action_bar_button_inverse"
-              android:gravity="center_vertical"
-              android:layout_width="match_parent"
-              android:layout_height="@dimen/remote_tab_child_row_height"
-              android:orientation="vertical"
-              android:paddingLeft="2dp"
-              android:paddingRight="2dp">
-
-    <TextView android:id="@+id/title"
-              style="@style/TabRowTextAppearance"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:textSize="14sp"/>
-
-    <TextView android:id="@+id/url"
-              style="@style/TabRowTextAppearance.Url"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:textSize="12sp"/>
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout-xlarge-v11/remote_tabs_group.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:background="@android:color/transparent"
-              android:layout_width="match_parent"
-              android:layout_height="@dimen/remote_tab_child_row_height"
-              android:gravity="center_vertical"
-              android:orientation="vertical"
-              android:paddingLeft="2dp"
-              android:paddingRight="2dp">
-
-    <org.mozilla.gecko.widget.AllCapsTextView android:id="@+id/client"
-                                              style="@style/TabRowTextAppearance"
-                                              android:layout_width="match_parent"
-                                              android:layout_height="wrap_content"
-                                              android:maxLines="2"
-                                              android:singleLine="false"
-                                              android:textSize="14sp"
-                                              android:textStyle="bold" />
-
-    <TextView android:id="@+id/last_synced"
-              style="@style/TabRowTextAppearance.Url"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:textSize="12sp"/>
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_child.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:background="@android:color/transparent"
-              android:gravity="center_vertical"
-              android:layout_width="match_parent"
-              android:layout_height="@dimen/remote_tab_child_row_height"
-              android:orientation="vertical"
-              android:paddingLeft="4dp"
-              android:paddingRight="4dp">
-
-    <TextView android:id="@+id/title"
-              style="@style/TabRowTextAppearance"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:textSize="18sp" />
-
-    <TextView android:id="@+id/url"
-              style="@style/TabRowTextAppearance.Url"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:maxLength="1024"
-              android:textSize="14sp" />
-
-</LinearLayout>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_container_panel.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<org.mozilla.gecko.tabs.RemoteTabsContainerPanel
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="gone">
-
-    <org.mozilla.gecko.tabs.RemoteTabsList
-            style="@style/RemoteTabsList"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:paddingLeft="@dimen/tabs_panel_list_padding"
-            android:paddingRight="@dimen/tabs_panel_list_padding"
-            android:scrollbarStyle="outsideOverlay"/>
-
-</org.mozilla.gecko.tabs.RemoteTabsContainerPanel>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_group.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:background="@android:color/transparent"
-              android:layout_width="match_parent"
-              android:layout_height="@dimen/remote_tab_child_row_height"
-              android:gravity="center_vertical"
-              android:orientation="vertical"
-              android:paddingLeft="4dp"
-              android:paddingRight="4dp" >
-
-    <org.mozilla.gecko.widget.AllCapsTextView android:id="@+id/client"
-                                              style="@style/TabRowTextAppearance"
-                                              android:layout_width="match_parent"
-                                              android:layout_height="@dimen/remote_tab_group_row_height"
-                                              android:textSize="18sp"
-                                              android:textStyle="bold" />
-
-    <TextView android:id="@+id/last_synced"
-              style="@style/TabRowTextAppearance.Url"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:maxLength="1024"
-              android:textSize="14sp" />
-
-</LinearLayout>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/remote_tabs_panel.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+   This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:gecko="http://schemas.android.com/apk/res-auto" >
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+
+        <LinearLayout
+            android:id="@+id/container"
+            style="@style/TabsPanelFrame.PrivateTabs"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <LinearLayout
+                style="@style/TabsPanelSection.PrivateTabs.Header"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <TextView
+                    style="@style/TabsPanelItem.TextAppearance.Header.PrivateTabs"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/remote_tabs_panel_moved_title" />
+
+                <TextView
+                    style="@style/TabsPanelItem.TextAppearance"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/remote_tabs_panel_moved_desc" />
+            </LinearLayout>
+
+            <LinearLayout
+                style="@style/TabsPanelSection.PrivateTabs"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" >
+
+                <TextView
+                    android:id="@+id/go_to_panel"
+                    style="@style/TabsPanelItem.TextAppearance.Linkified.LearnMore"
+                    android:layout_width="match_parent"
+                    android:text="@string/remote_tabs_panel_moved_link" />
+            </LinearLayout>
+        </LinearLayout>
+    </ScrollView>
+
+</merge>
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_setup_panel.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <LinearLayout android:id="@+id/remote_tabs_setup_containing_layout"
-                  style="@style/TabsPanelFrame.RemoteTabs"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent">
-
-        <LinearLayout style="@style/TabsPanelSection"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content">
-
-           <TextView style="@style/TabsPanelItem.TextAppearance.Header"
-                     android:layout_width="match_parent"
-                     android:layout_height="wrap_content"
-                     android:text="@string/fxaccount_getting_started_welcome_to_sync"/>
-
-           <TextView style="@style/TabsPanelItem.TextAppearance"
-                     android:layout_width="match_parent"
-                     android:layout_height="wrap_content"
-                     android:text="@string/fxaccount_getting_started_description"/>
-
-        </LinearLayout>
-
-        <LinearLayout style="@style/TabsPanelSection"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content">
-
-            <!-- Setting gravity/layout_gravity in portrait is redundant to these elements'
-                 styles, however, it overrides the default left-align behavior in landscape. -->
-            <Button android:id="@+id/remote_tabs_setup_get_started"
-                    android:layout_gravity="center"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    style="@style/TabsPanelItem.Button"
-                    android:text="@string/fxaccount_getting_started_get_started"
-                    android:layout_marginBottom="15dp"/>
-
-            <TextView android:id="@+id/remote_tabs_setup_old_sync_link"
-                      android:gravity="center"
-                      android:layout_gravity="center"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content"
-                      style="@style/TabsPanelItem.TextAppearance.Linkified"
-                      android:text="@string/fxaccount_getting_started_old_firefox"/>
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-</merge>
deleted file mode 100644
--- a/mobile/android/base/resources/layout/remote_tabs_verification_panel.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <LinearLayout android:id="@+id/remote_tabs_verification_containing_layout"
-                  style="@style/TabsPanelFrame.RemoteTabs"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent">
-
-        <LinearLayout style="@style/TabsPanelSection"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content">
-
-            <TextView style="@style/TabsPanelItem.TextAppearance.Header.FXAccounts"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content"
-                      android:text="@string/fxaccount_full_label"
-                      android:layout_marginBottom="0dp"/>
-
-            <TextView style="@style/TabsPanelItem.TextAppearance.Header"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content"
-                      android:text="@string/fxaccount_confirm_account_header"
-                      android:layout_marginTop="0dp"/>
-
-            <TextView android:id="@+id/remote_tabs_confirm_verification"
-                      style="@style/TabsPanelItem.TextAppearance"
-                      android:layout_width="match_parent"
-                      android:layout_height="wrap_content"
-                      android:text="@string/fxaccount_confirm_account_verification_link"/>
-
-        </LinearLayout>
-
-        <LinearLayout style="@style/TabsPanelSection"
-                      android:layout_width="match_parent"
-                      android:layout_height="match_parent">
-
-            <TextView android:id="@+id/remote_tabs_confirm_resend"
-                      style="@style/TabsPanelItem.TextAppearance.Linkified.Resend"
-                      android:layout_width="match_parent"
-                      android:text="@string/fxaccount_confirm_account_resend_email"/>
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-</merge>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -373,16 +373,20 @@
   <string name="home_remote_tabs_unhide_selected_devices">&home_remote_tabs_unhide_selected_devices;</string>
   <string name="private_browsing_title">&private_browsing_title;</string>
   <string name="private_tabs_panel_empty_desc">&private_tabs_panel_empty_desc;</string>
   <string name="private_tabs_panel_learn_more">&private_tabs_panel_learn_more;</string>
   <!-- https://support.mozilla.org/%LOCALE%/kb/mobile-private-browsing-browse-web-without-saving-syncing-info -->
   <string name="private_tabs_panel_learn_more_link">https://support.mozilla.org/&formatS1;/kb/mobile-private-browsing-browse-web-without-saving-syncing-info</string>
   <string name="pin_site_dialog_hint">&pin_site_dialog_hint;</string>
 
+  <string name="remote_tabs_panel_moved_title">&remote_tabs_panel_moved_title;</string>
+  <string name="remote_tabs_panel_moved_desc">&remote_tabs_panel_moved_desc;</string>
+  <string name="remote_tabs_panel_moved_link">&remote_tabs_panel_moved_link;</string>
+
   <string name="filepicker_title">&filepicker_title;</string>
   <string name="filepicker_audio_title">&filepicker_audio_title;</string>
   <string name="filepicker_image_title">&filepicker_image_title;</string>
   <string name="filepicker_video_title">&filepicker_video_title;</string>
 
   <!-- Default bookmarks. We used to use bookmark titles shared with XUL from mobile's
        profile/bookmarks.inc (see bug 964946). Don't expose the URLs to L10N. -->
   <string name="bookmarkdefaults_title_aboutfirefox">@bookmarks_aboutBrowser@</string>
deleted file mode 100644
--- a/mobile/android/base/tabs/RemoteTabsContainerPanel.java
+++ /dev/null
@@ -1,188 +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/. */
-
-package org.mozilla.gecko.tabs;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.TabsAccessor;
-import org.mozilla.gecko.fxa.FirefoxAccounts;
-import org.mozilla.gecko.tabs.TabsPanel.Panel;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.widget.GeckoSwipeRefreshLayout;
-
-import android.accounts.Account;
-import android.content.Context;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Provides a container to wrap the list of synced tabs and provide
- * swipe-to-refresh support. The only child view should be an instance of
- * {@link RemoteTabsList}.
- */
-public class RemoteTabsContainerPanel extends GeckoSwipeRefreshLayout
-                                 implements TabsPanel.PanelView {
-    private static final String[] STAGES_TO_SYNC_ON_REFRESH = new String[] { "clients", "tabs" };
-
-    /**
-     * Refresh indicators (the swipe-to-refresh "laser show" and the spinning
-     * icon) will never be shown for less than the following duration, in
-     * milliseconds.
-     */
-    private static final long MINIMUM_REFRESH_INDICATOR_DURATION_IN_MS = 12 * 100; // 12 frames, 100 ms each.
-
-    private final Context context;
-    private final RemoteTabsSyncObserver syncListener;
-    private TabsPanel panel;
-    private RemoteTabsList list;
-
-    // Whether or not a sync status listener is attached.
-    private boolean isListening;
-
-    public RemoteTabsContainerPanel(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        this.context = context;
-        this.syncListener = new RemoteTabsSyncObserver();
-
-        setOnRefreshListener(new RemoteTabsRefreshListener());
-    }
-
-    @Override
-    public void addView(View child, int index, ViewGroup.LayoutParams params) {
-        super.addView(child, index, params);
-
-        list = (RemoteTabsList) child;
-
-        // Must be called after the child view has been added.
-        setColorScheme(R.color.swipe_refresh_orange1, R.color.swipe_refresh_orange2,
-                       R.color.swipe_refresh_orange3, R.color.swipe_refresh_orange4);
-    }
-
-
-    @Override
-    public boolean canChildScrollUp() {
-        // We are not supporting swipe-to-refresh for old sync. This disables
-        // the swipe gesture if no FxA are detected.
-        if (FirefoxAccounts.firefoxAccountsExist(getContext())) {
-            return super.canChildScrollUp();
-        } else {
-            return true;
-        }
-    }
-
-    @Override
-    public void setTabsPanel(TabsPanel panel) {
-        this.panel = panel;
-        list.setTabsPanel(panel);
-    }
-
-    @Override
-    public void show() {
-        // Start fetching remote tabs.
-        TabsAccessor.getTabs(context, list);
-        // The user can trigger a tabs sync, so we want to be very certain the
-        // locally-persisted tabs are fresh (tab writes are batched and delayed).
-        Tabs.getInstance().persistAllTabs();
-
-        if (!isListening) {
-            isListening = true;
-            FirefoxAccounts.addSyncStatusListener(syncListener);
-        }
-        setVisibility(View.VISIBLE);
-    }
-
-    @Override
-    public void hide() {
-        setVisibility(View.GONE);
-        if (isListening) {
-            isListening = false;
-            FirefoxAccounts.removeSyncStatusListener(syncListener);
-        }
-    }
-
-    @Override
-    public boolean shouldExpand() {
-        return true;
-    }
-
-    private class RemoteTabsRefreshListener implements OnRefreshListener {
-        @Override
-        public void onRefresh() {
-            if (FirefoxAccounts.firefoxAccountsExist(getContext())) {
-                final Account account = FirefoxAccounts.getFirefoxAccount(getContext());
-                FirefoxAccounts.requestSync(account, FirefoxAccounts.FORCE, STAGES_TO_SYNC_ON_REFRESH, null);
-            }
-        }
-    }
-
-    private class RemoteTabsSyncObserver implements FirefoxAccounts.SyncStatusListener {
-        // Written on the main thread, and read off the main thread, but no need
-        // to synchronize.
-        protected volatile long lastSyncStarted;
-
-        @Override
-        public Context getContext() {
-            return RemoteTabsContainerPanel.this.getContext();
-        }
-
-        @Override
-        public Account getAccount() {
-            return FirefoxAccounts.getFirefoxAccount(getContext());
-        }
-
-        public void onSyncStarted() {
-            ThreadUtils.postToUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    lastSyncStarted = System.currentTimeMillis();
-
-                    // Replace the static sync icon with an animated icon, and
-                    // start the animation. This works around an Android 4.4.2
-                    // bug, which makes animating the animated icon unreliable.
-                    // See Bug 1015974.
-                    panel.setIconDrawable(Panel.REMOTE_TABS, R.drawable.tabs_synced_animated);
-                    final Drawable iconDrawable = panel.getIconDrawable(Panel.REMOTE_TABS);
-                    if (iconDrawable instanceof AnimationDrawable) {
-                        ((AnimationDrawable) iconDrawable).start();
-                    }
-                }
-            });
-        }
-
-        public void onSyncFinished() {
-            final Handler uiHandler = ThreadUtils.getUiHandler();
-
-            // We want to update the list immediately ...
-            uiHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    TabsAccessor.getTabs(context, list);
-                }
-            });
-
-            // ... but we want the refresh indicators to persist for long enough
-            // to be visible.
-            final long last = lastSyncStarted;
-            final long now = System.currentTimeMillis();
-            final long delay = Math.max(0, MINIMUM_REFRESH_INDICATOR_DURATION_IN_MS - (now - last));
-
-            uiHandler.postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    setRefreshing(false);
-
-                    // Replace the animated sync icon with the static sync icon.
-                    // This works around an Android 4.4.2 bug, which makes
-                    // animating the animated icon unreliable. See Bug 1015974.
-                    panel.setIconDrawable(Panel.REMOTE_TABS, R.drawable.tabs_synced);
-                }
-            }, delay);
-        }
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/tabs/RemoteTabsList.java
+++ /dev/null
@@ -1,120 +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/. */
-
-package org.mozilla.gecko.tabs;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
-import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.TabsAccessor;
-import org.mozilla.gecko.TabsAccessor.RemoteClient;
-import org.mozilla.gecko.TabsAccessor.RemoteTab;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ExpandableListView;
-
-/**
- * The actual list of synced tabs. This serves as the only child view of {@link RemoteTabsContainerPanel}
- * so it can be refreshed using a swipe-to-refresh gesture.
- */
-public class RemoteTabsList extends ExpandableListView
-                            implements ExpandableListView.OnGroupClickListener,
-                                       ExpandableListView.OnChildClickListener,
-                                       TabsAccessor.OnQueryTabsCompleteListener {
-    private TabsPanel tabsPanel;
-
-    // A list of the clients that are currently expanded.
-    private List<String> expandedClientList;
-
-    // The client that previously had an item selected is used to restore the scroll position.
-    private String clientScrollPosition;
-
-    public RemoteTabsList(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        setOnGroupClickListener(this);
-        setOnChildClickListener(this);
-        setAdapter(new RemoteTabsExpandableListAdapter(R.layout.remote_tabs_group, R.layout.remote_tabs_child, null));
-    }
-
-    public void setTabsPanel(TabsPanel panel) {
-        tabsPanel = panel;
-    }
-
-    private void autoHidePanel() {
-        tabsPanel.autoHidePanel();
-    }
-
-    @Override
-    public boolean onGroupClick(ExpandableListView parent, View view, int groupPosition, long id) {
-        final RemoteClient client = (RemoteClient) parent.getExpandableListAdapter().getGroup(groupPosition);
-        final String clientGuid = client.guid;
-
-        if (isGroupExpanded(groupPosition)) {
-            collapseGroup(groupPosition);
-            expandedClientList.remove(clientGuid);
-        } else {
-            expandGroup(groupPosition);
-            expandedClientList.add(clientGuid);
-        }
-
-        clientScrollPosition = clientGuid;
-        return true;
-    }
-
-    @Override
-    public boolean onChildClick(ExpandableListView parent, View view, int groupPosition, int childPosition, long id) {
-        final RemoteTab tab = (RemoteTab) parent.getExpandableListAdapter().getChild(groupPosition, childPosition);
-        if (tab == null) {
-            autoHidePanel();
-            return true;
-        }
-
-        Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "remote");
-
-        Tabs.getInstance().loadUrl(tab.url, Tabs.LOADURL_NEW_TAB);
-        autoHidePanel();
-
-        final RemoteClient client = (RemoteClient) parent.getExpandableListAdapter().getGroup(groupPosition);
-        clientScrollPosition = client.guid;
-
-        return true;
-    }
-
-    @Override
-    public void onQueryTabsComplete(List<RemoteClient> clients) {
-        ((RemoteTabsExpandableListAdapter) getExpandableListAdapter()).replaceClients(clients);
-
-        // Either set the initial UI state, or restore it.
-        List<String> newExpandedClientList = new ArrayList<String>();
-        for (int i = 0; i < clients.size(); i++) {
-            final String clientGuid = clients.get(i).guid;
-
-            if (expandedClientList == null) {
-                // On initial entry we expand all clients by default.
-                newExpandedClientList.add(clientGuid);
-                expandGroup(i);
-            } else {
-                // On subsequent entries, we expand clients based on their previous UI state.
-                if (expandedClientList.contains(clientGuid)) {
-                    newExpandedClientList.add(clientGuid);
-                    expandGroup(i);
-                }
-
-                // Additionally we reset the UI scroll position.
-                if (clientGuid.equals(clientScrollPosition)) {
-                    setSelectedGroup(i);
-                }
-            }
-        }
-        expandedClientList = newExpandedClientList;
-    }
-}
--- a/mobile/android/base/tabs/RemoteTabsPanel.java
+++ b/mobile/android/base/tabs/RemoteTabsPanel.java
@@ -1,123 +1,73 @@
 /* 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.gecko.tabs;
 
+import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.R;
-import org.mozilla.gecko.fxa.FirefoxAccounts;
-import org.mozilla.gecko.fxa.login.State;
-import org.mozilla.gecko.sync.setup.SyncAccounts;
+import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.tabs.TabsPanel.PanelView;
 
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 
 /**
- * This panel, which is a {@link TabsPanel.PanelView}, chooses which underlying
- * PanelView to show based on the current account state, and forwards the appropriate
- * calls to the currently visible panel.
+ * A tabs tray panel that displays a static view that informs users that the
+ * Synced Tabs/Remote Tabs list is now accessed as a home panel. The view
+ * provides a single link that opens the new home panel.
  */
 class RemoteTabsPanel extends FrameLayout implements PanelView {
-    private enum RemotePanelType {
-        SETUP,
-        VERIFICATION,
-        CONTAINER
-    }
-
-    private PanelView currentPanel;
-    private RemotePanelType currentPanelType;
-
     private TabsPanel tabsPanel;
 
     public RemoteTabsPanel(Context context, AttributeSet attrs) {
         super(context, attrs);
-        updateCurrentPanel();
+
+        LayoutInflater.from(context).inflate(R.layout.remote_tabs_panel, this);
+
+        final View link = findViewById(R.id.go_to_panel);
+        link.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // It is possible that this will fail: if the user has removed
+                // the Remote Tabs panel, it won't exist. (The new tab will open
+                // to the default panel, which is confusing but not
+                // catastrophic.) Querying the current configuration to
+                // determine if the panel is present is not worth the effort; we
+                // expect very few configurations to not include the Remote Tabs
+                // panel.
+                Tabs.getInstance().loadUrl(AboutPages.getURLForBuiltinPanelType(PanelType.REMOTE_TABS),
+                        Tabs.LOADURL_NEW_TAB);
+                if (tabsPanel != null) {
+                    tabsPanel.autoHidePanel();
+                }
+            }
+        });
     }
 
     @Override
     public void setTabsPanel(TabsPanel panel) {
         tabsPanel = panel;
-        currentPanel.setTabsPanel(panel);
     }
 
     @Override
     public void show() {
-        updateCurrentPanel();
-        currentPanel.show();
         setVisibility(View.VISIBLE);
     }
 
     @Override
     public void hide() {
         setVisibility(View.GONE);
-        currentPanel.hide();
     }
 
     @Override
     public boolean shouldExpand() {
-        return currentPanel.shouldExpand();
-    }
-
-    private void updateCurrentPanel() {
-        final RemotePanelType newPanelType = getPanelTypeFromAccountState();
-        if (newPanelType != currentPanelType) {
-            // The current panel should be null the first time this is called.
-            if (currentPanel != null) {
-                currentPanel.hide();
-            }
-            removeAllViews();
-
-            currentPanelType = newPanelType;
-            currentPanel = inflatePanel(currentPanelType);
-            currentPanel.setTabsPanel(tabsPanel);
-            addView((View) currentPanel);
-        }
-    }
-
-    private RemotePanelType getPanelTypeFromAccountState() {
-        final Context context = getContext();
-        final State accountState = FirefoxAccounts.getFirefoxAccountState(context);
-        if (accountState == null) {
-            // If old Sync exists, we want to show their synced tabs,
-            // rather than the new Sync setup screen.
-            if (SyncAccounts.syncAccountsExist(context)) {
-                return RemotePanelType.CONTAINER;
-            } else {
-                return RemotePanelType.SETUP;
-            }
-        }
-
-        if (accountState.getNeededAction() == State.Action.NeedsVerification) {
-            return RemotePanelType.VERIFICATION;
-        }
-
-        return RemotePanelType.CONTAINER;
-    }
-
-    private PanelView inflatePanel(final RemotePanelType panelType) {
-        final PanelView view;
-        switch (panelType) {
-            case SETUP:
-                view = new RemoteTabsSetupPanel(getContext());
-                break;
-
-            case VERIFICATION:
-                view = new RemoteTabsVerificationPanel(getContext());
-                break;
-
-            case CONTAINER:
-                final LayoutInflater inflater = LayoutInflater.from(getContext());
-                view = (PanelView) inflater.inflate(R.layout.remote_tabs_container_panel, null);
-                break;
-
-            default:
-                throw new IllegalArgumentException("Unknown panelType, " + panelType);
-        }
-
-        return view;
+        final LinearLayout container = (LinearLayout) findViewById(R.id.container);
+        return container.getOrientation() == LinearLayout.VERTICAL;
     }
 }
deleted file mode 100644
--- a/mobile/android/base/tabs/RemoteTabsSetupPanel.java
+++ /dev/null
@@ -1,86 +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/. */
-
-package org.mozilla.gecko.tabs;
-
-import java.util.Locale;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.fxa.FirefoxAccounts;
-import org.mozilla.gecko.fxa.activities.FxAccountCreateAccountActivity;
-import org.mozilla.gecko.tabs.TabsPanel.PanelView;
-
-import android.content.Context;
-import android.content.Intent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-
-/**
- * A tabs panel which allows a user to get started setting up a Firefox
- * Accounts account. Currently used as one sub-panel in a sequence
- * contained by the {@link RemoteTabsPanel}.
- */
-class RemoteTabsSetupPanel extends ScrollView implements PanelView {
-    private final LinearLayout containingLayout;
-
-    private TabsPanel tabsPanel;
-
-    public RemoteTabsSetupPanel(Context context) {
-        super(context);
-
-        LayoutInflater.from(context).inflate(R.layout.remote_tabs_setup_panel, this);
-        containingLayout = (LinearLayout) findViewById(R.id.remote_tabs_setup_containing_layout);
-
-        final View setupGetStartedButton =
-                containingLayout.findViewById(R.id.remote_tabs_setup_get_started);
-        setupGetStartedButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(final View v) {
-                final Context context = getContext();
-                // This Activity will redirect to the correct Activity if the
-                // account is no longer in the setup state.
-                final Intent intent = new Intent(context, FxAccountCreateAccountActivity.class);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                context.startActivity(intent);
-            }
-        });
-
-        final View setupOlderVersionLink =
-                containingLayout.findViewById(R.id.remote_tabs_setup_old_sync_link);
-        setupOlderVersionLink.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(final View v) {
-                final String url = FirefoxAccounts.getOldSyncUpgradeURL(
-                        getResources(), Locale.getDefault());
-                Tabs.getInstance().loadUrlInTab(url);
-                if (tabsPanel != null) {
-                    tabsPanel.autoHidePanel();
-                }
-            }
-        });
-    }
-
-    @Override
-    public void setTabsPanel(TabsPanel panel) {
-        tabsPanel = panel;
-    }
-
-    @Override
-    public void show() {
-        setVisibility(View.VISIBLE);
-    }
-
-    @Override
-    public void hide() {
-        setVisibility(View.GONE);
-    }
-
-    @Override
-    public boolean shouldExpand() {
-        return containingLayout.getOrientation() == LinearLayout.VERTICAL;
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/tabs/RemoteTabsVerificationPanel.java
+++ /dev/null
@@ -1,114 +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/. */
-
-package org.mozilla.gecko.tabs;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.fxa.FirefoxAccounts;
-import org.mozilla.gecko.fxa.login.State;
-import org.mozilla.gecko.tabs.TabsPanel.PanelView;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-/**
- * A tabs panel which allows a user to get resend the verification email
- * to confirm a Firefox Account. Currently used as one sub-panel in a sequence
- * contained by the {@link RemoteTabsPanel}.
- */
-class RemoteTabsVerificationPanel extends ScrollView implements PanelView {
-    private static final String LOG_TAG = RemoteTabsVerificationPanel.class.getSimpleName();
-
-    private final LinearLayout containingLayout;
-
-    private TabsPanel tabsPanel;
-
-    public RemoteTabsVerificationPanel(Context context) {
-        super(context);
-
-        LayoutInflater.from(context).inflate(R.layout.remote_tabs_verification_panel, this);
-        containingLayout = (LinearLayout) findViewById(R.id.remote_tabs_verification_containing_layout);
-
-        final View resendLink = containingLayout.findViewById(R.id.remote_tabs_confirm_resend);
-        resendLink.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                final State accountState = FirefoxAccounts.getFirefoxAccountState(getContext());
-                final State.Action neededAction = accountState.getNeededAction();
-                if (accountState.getNeededAction() != State.Action.NeedsVerification) {
-                    autoHideTabsPanelOnUnexpectedState("Account expected to need verification " +
-                            "on resend, but action was " + neededAction + " instead.");
-                    return;
-                }
-
-                if (!FirefoxAccounts.resendVerificationEmail(getContext())) {
-                    autoHideTabsPanelOnUnexpectedState("Account DNE when resending verification email.");
-                    return;
-                }
-            }
-        });
-    }
-
-    private void refresh() {
-        final TextView verificationView =
-                (TextView) containingLayout.findViewById(R.id.remote_tabs_confirm_verification);
-        final String email = FirefoxAccounts.getFirefoxAccountEmail(getContext());
-        if (email == null) {
-            autoHideTabsPanelOnUnexpectedState("Account email DNE on View refresh.");
-            return;
-        }
-
-        final String text = getResources().getString(
-                R.string.fxaccount_confirm_account_verification_link, email);
-        verificationView.setText(text);
-    }
-
-    /**
-     * Hides the tabs panel and logs the given String.
-     *
-     * As the name suggests, this method should be only be used for unexpected states!
-     * We hide the tabs panel on unexpected states as the best of several evils - hiding
-     * the tabs panel communicates to the user, "Hey, that's a strange bug!" and, if they're
-     * curious enough, will reopen the RemoteTabsPanel, refreshing its contents. Since we're
-     * in a strange state, we may already be screwed, but it's better than some alternatives like:
-     *   * Crashing
-     *   * Hiding the resources which allow invalid state (e.g. resend link, email text)
-     *   * Attempting to refresh the RemoteTabsPanel, possibly starting an infinite loop.
-     *
-     * @param log The message to log.
-     */
-    private void autoHideTabsPanelOnUnexpectedState(final String log) {
-        Log.w(LOG_TAG, "Unexpected state: " + log + " Closing the tabs panel.");
-
-        if (tabsPanel != null) {
-            tabsPanel.autoHidePanel();
-        }
-    }
-
-    @Override
-    public void setTabsPanel(TabsPanel panel) {
-        tabsPanel = panel;
-    }
-
-    @Override
-    public void show() {
-        refresh();
-        setVisibility(View.VISIBLE);
-    }
-
-    @Override
-    public void hide() {
-        setVisibility(View.GONE);
-    }
-
-    @Override
-    public boolean shouldExpand() {
-        return containingLayout.getOrientation() == LinearLayout.VERTICAL;
-    }
-}
--- a/mobile/android/base/tests/components/AboutHomeComponent.java
+++ b/mobile/android/base/tests/components/AboutHomeComponent.java
@@ -2,64 +2,58 @@
  * 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.gecko.tests.components;
 
 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals;
 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue;
 
+import java.util.Arrays;
+
+import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.tests.UITestContext;
-import org.mozilla.gecko.tests.helpers.DeviceHelper;
 import org.mozilla.gecko.tests.helpers.WaitHelper;
+import org.mozilla.gecko.util.HardwareUtils;
 
 import android.support.v4.view.ViewPager;
 import android.view.View;
 import android.widget.TextView;
 
 import com.jayway.android.robotium.solo.Condition;
 import com.jayway.android.robotium.solo.Solo;
-import org.mozilla.gecko.util.HardwareUtils;
-
-import java.util.Arrays;
-import java.util.Enumeration;
 
 /**
  * A class representing any interactions that take place on the Awesomescreen.
  */
 public class AboutHomeComponent extends BaseComponent {
     private static final String LOGTAG = AboutHomeComponent.class.getSimpleName();
 
-    // The different types of panels that can be present on about:home
-    public enum PanelType {
-        HISTORY,
-        TOP_SITES,
-        BOOKMARKS,
-        READING_LIST,
-        RECENT_TABS
-    }
-
     // TODO: Having a specific ordering of panels is prone to fail and thus temporary.
     // Hopefully the work in bug 940565 will alleviate the need for these enums.
     // Explicit ordering of HomePager panels on a phone.
     private static final PanelType[] PANEL_ORDERING_PHONE = {
+            PanelType.REMOTE_TABS,
             PanelType.RECENT_TABS,
             PanelType.HISTORY,
             PanelType.TOP_SITES,
             PanelType.BOOKMARKS,
-            PanelType.READING_LIST
+            PanelType.READING_LIST,
     };
 
     private static final PanelType[] PANEL_ORDERING_TABLET = {
             PanelType.TOP_SITES,
             PanelType.BOOKMARKS,
             PanelType.READING_LIST,
             PanelType.HISTORY,
-            PanelType.RECENT_TABS
+            PanelType.RECENT_TABS,
+            PanelType.REMOTE_TABS,
     };
 
     // The percentage of the panel to swipe between 0 and 1. This value was set through
     // testing: 0.55f was tested on try and fails on armv6 devices.
     private static final float SWIPE_PERCENTAGE = 0.70f;
 
     public AboutHomeComponent(final UITestContext testContext) {
         super(testContext);
@@ -193,9 +187,24 @@ public class AboutHomeComponent extends 
     }
 
     /**
      * Get an array of PanelType objects ordered as we want the panels to be ordered on this device.
      */
     public static PanelType[] getPanelOrderingForDevice() {
         return HardwareUtils.isTablet() ? PANEL_ORDERING_TABLET : PANEL_ORDERING_PHONE;
     }
+
+    /**
+     * Navigate directly to a built-in panel by its panel type.
+     * <p>
+     * If the panel type is not part of the active Home Panel configuration, the
+     * default about:home panel is displayed. If the panel type is not a
+     * built-in panel, an IllegalArgumentException is thrown.
+     *
+     * @param panelType to navigate to.
+     * @return self, for chaining.
+     */
+    public AboutHomeComponent navigateToBuiltinPanelType(PanelType panelType) throws IllegalArgumentException {
+        Tabs.getInstance().loadUrl(AboutPages.getURLForBuiltinPanelType(panelType));
+        return this;
+    }
 }
--- a/mobile/android/base/tests/testAboutHomePageNavigation.java
+++ b/mobile/android/base/tests/testAboutHomePageNavigation.java
@@ -1,11 +1,12 @@
 package org.mozilla.gecko.tests;
 
-import org.mozilla.gecko.tests.components.AboutHomeComponent.PanelType;
+import org.mozilla.gecko.home.HomeConfig;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.tests.helpers.DeviceHelper;
 import org.mozilla.gecko.tests.helpers.GeckoHelper;
 
 /**
  * Tests functionality related to navigating between the various about:home panels.
  *
  * TODO: Update this test to account for recent tabs panel (bug 1028727).
  */
--- a/mobile/android/base/tests/testAboutHomeVisibility.java
+++ b/mobile/android/base/tests/testAboutHomeVisibility.java
@@ -1,11 +1,12 @@
 package org.mozilla.gecko.tests;
 
-import org.mozilla.gecko.tests.components.AboutHomeComponent.PanelType;
+import org.mozilla.gecko.home.HomeConfig;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.tests.helpers.GeckoHelper;
 import org.mozilla.gecko.tests.helpers.NavigationHelper;
 
 /**
  * Tests the visibility of about:home after various interactions with the browser.
  */
 public class testAboutHomeVisibility extends UITest {
     public void testAboutHomeVisibility() {
@@ -36,11 +37,19 @@ public class testAboutHomeVisibility ext
         mAboutHome.assertNotVisible();
 
         // Loading about:home should show about:home again.
         NavigationHelper.enterAndLoadUrl(StringHelper.ABOUT_HOME_URL);
         mToolbar.assertTitle(StringHelper.ABOUT_HOME_TITLE);
         mAboutHome.assertVisible()
                   .assertCurrentPanel(PanelType.TOP_SITES);
 
+        // We can navigate to about:home panels by panel UUID.
+        mAboutHome.navigateToBuiltinPanelType(PanelType.BOOKMARKS)
+                  .assertVisible()
+                  .assertCurrentPanel(PanelType.BOOKMARKS);
+        mAboutHome.navigateToBuiltinPanelType(PanelType.HISTORY)
+                  .assertVisible()
+                  .assertCurrentPanel(PanelType.HISTORY);
+
         // TODO: Type in a url and assert the go button is visible.
     }
 }
--- a/mobile/android/chrome/content/aboutAddons.js
+++ b/mobile/android/chrome/content/aboutAddons.js
@@ -438,39 +438,34 @@ var Addons = {
     let addon = detailItem.addon;
     if (!addon)
       return;
 
     this.uninstall(addon);
   },
 
   uninstall: function uninstall(aAddon) {
-    let list = document.getElementById("addons-list");
-
     if (!aAddon) {
-        return;
+      return;
     }
 
     let listItem = this._getElementForAddon(aAddon.id);
+    aAddon.uninstall();
 
-    aAddon.uninstall();
     if (aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL) {
       this.showRestart();
 
       // A disabled addon doesn't need a restart so it has no pending ops and
       // can't be cancelled
       let opType = this._getOpTypeForOperations(aAddon.pendingOperations);
       if (!aAddon.isActive && opType == "")
         opType = "needs-uninstall";
 
       detailItem.setAttribute("opType", opType);
       listItem.setAttribute("opType", opType);
-    } else {
-      list.removeChild(listItem);
-      history.back();
     }
   },
 
   cancelUninstall: function ev_cancelUninstall() {
     let detailItem = document.querySelector("#addons-details > .addon-item");
     let addon = detailItem.addon;
     if (!addon)
       return;
@@ -534,16 +529,22 @@ var Addons = {
       list.insertBefore(element, list.firstElementChild);
     }
   },
 
   onUninstalled: function(aAddon) {
     let list = document.getElementById("addons-list");
     let element = this._getElementForAddon(aAddon.id);
     list.removeChild(element);
+
+    // Go back if we're in the detail view of the add-on that was uninstalled.
+    let detailItem = document.querySelector("#addons-details > .addon-item");
+    if (detailItem.addon == aAddon) {
+      history.back();
+    }
   },
 
   onInstallFailed: function(aInstall) {
   },
 
   onDownloadProgress: function xpidm_onDownloadProgress(aInstall) {
   },
 
--- a/mobile/android/chrome/content/aboutAddons.xhtml
+++ b/mobile/android/chrome/content/aboutAddons.xhtml
@@ -36,18 +36,17 @@
   <div id="addons-list" class="list">
   </div>
 
   <div id="addons-details" class="list">
     <div class="addon-item list-item">
       <img class="icon"/>
       <div class="inner">
         <div class="details">
-          <div class="title"></div>
-          <div class="version"></div>
+          <div class="title"></div><div class="version"></div>
         </div>
         <div class="description-full"></div>
         <div class="options-header">&aboutAddons.options;</div>
         <div class="options-box"></div>
       </div>
       <div class="status status-uninstalled show-on-uninstall"></div>
       <div class="buttons">
         <button id="enable-btn" class="show-on-disable hide-on-enable hide-on-uninstall" >&addonAction.enable;</button>
--- a/mobile/android/search/java/org/mozilla/search/SearchActivity.java
+++ b/mobile/android/search/java/org/mozilla/search/SearchActivity.java
@@ -1,47 +1,51 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.search;
 
+import org.mozilla.gecko.LocaleAware;
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
+import org.mozilla.gecko.db.BrowserContract.SearchHistory;
+import org.mozilla.gecko.health.BrowserHealthRecorder;
+import org.mozilla.search.autocomplete.SearchBar;
+import org.mozilla.search.autocomplete.SuggestionsFragment;
+import org.mozilla.search.providers.SearchEngine;
+import org.mozilla.search.providers.SearchEngineManager;
+import org.mozilla.search.providers.SearchEngineManager.SearchEngineCallback;
+
 import android.content.AsyncQueryHandler;
 import android.content.ContentValues;
 import android.content.Intent;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.View;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.Interpolator;
 
 import com.nineoldandroids.animation.Animator;
 import com.nineoldandroids.animation.AnimatorSet;
 import com.nineoldandroids.animation.ObjectAnimator;
 
-import org.mozilla.gecko.LocaleAware;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract.SearchHistory;
-import org.mozilla.search.autocomplete.SearchBar;
-import org.mozilla.search.autocomplete.SuggestionsFragment;
-import org.mozilla.search.providers.SearchEngine;
-import org.mozilla.search.providers.SearchEngineManager;
-import org.mozilla.search.providers.SearchEngineManager.SearchEngineCallback;
-
 /**
  * The main entrance for the Android search intent.
  * <p/>
  * State management is delegated to child fragments. Fragments communicate
  * with each other by passing messages through this activity.
  */
 public class SearchActivity extends LocaleAware.LocaleAwareFragmentActivity
         implements AcceptsSearchQuery, SearchEngineCallback {
 
+    private static final String LOGTAG = "GeckoSearchActivity";
+
     private static final String KEY_SEARCH_STATE = "search_state";
     private static final String KEY_EDIT_STATE = "edit_state";
     private static final String KEY_QUERY = "query";
 
     static enum SearchState {
         PRESEARCH,
         POSTSEARCH
     }
@@ -229,16 +233,24 @@ public class SearchActivity extends Loca
     public void onSearch(String query) {
         onSearch(query, null);
     }
 
     @Override
     public void onSearch(String query, SuggestionAnimation suggestionAnimation) {
         storeQuery(query);
 
+        try {
+            BrowserHealthRecorder.recordSearchDelayed("activity", engine.getIdentifier());
+        } catch (Exception e) {
+            // This should never happen: it'll only throw if the
+            // search location is wrong. But let's not tempt fate.
+            Log.w(LOGTAG, "Unable to record search.");
+        }
+
         startSearch(query);
 
         if (suggestionAnimation != null) {
             searchBar.setText(query);
             // Animate the suggestion card if start bounds are specified.
             animateSuggestion(suggestionAnimation);
         } else {
             // Otherwise immediately switch to the results view.
--- a/mobile/android/search/java/org/mozilla/search/SearchWidget.java
+++ b/mobile/android/search/java/org/mozilla/search/SearchWidget.java
@@ -13,20 +13,18 @@ import org.mozilla.gecko.TelemetryContra
 import android.annotation.SuppressLint;
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProvider;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.widget.RemoteViews;
-import android.util.Log;
 
 /* Provides a really simple widget with two buttons, one to launch Fennec
  * and one to launch the search activity. All intents are actually sent back
  * here and then forwarded on to start the real activity. */
 public class SearchWidget extends AppWidgetProvider {
     final private static String LOGTAG = "GeckoSearchWidget";
 
     final public static String ACTION_LAUNCH_BROWSER = "org.mozilla.widget.LAUNCH_BROWSER";
@@ -58,52 +56,49 @@ public class SearchWidget extends AppWid
         addView(manager, context, id, options);
         if (AppConstants.Versions.feature16Plus) {
             super.onAppWidgetOptionsChanged(context, manager, id, options);
         }
     }
 
     @Override
     public void onReceive(final Context context, final Intent intent) {
-        // This will hold the intent to redispatch
+        // This will hold the intent to redispatch.
         final Intent redirect;
-        if (intent.getAction().equals(ACTION_LAUNCH_BROWSER)) {
-            redirect = buildRedirectIntent(Intent.ACTION_MAIN,
-                    AppConstants.ANDROID_PACKAGE_NAME,
-                    AppConstants.BROWSER_INTENT_CLASS_NAME,
-                    intent);
-            Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
-                    TelemetryContract.Method.WIDGET, "browser");
-        } else if (intent.getAction().equals(ACTION_LAUNCH_NEW_TAB)) {
+        switch (intent.getAction()) {
+            case ACTION_LAUNCH_BROWSER:
+                redirect = buildRedirectIntent(Intent.ACTION_MAIN,
+                                               AppConstants.ANDROID_PACKAGE_NAME,
+                                               AppConstants.BROWSER_INTENT_CLASS_NAME,
+                                               intent);
+                Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
+                                      TelemetryContract.Method.WIDGET, "browser");
+                break;
+            case ACTION_LAUNCH_NEW_TAB:
                 redirect = buildRedirectIntent(Intent.ACTION_VIEW,
-                        AppConstants.ANDROID_PACKAGE_NAME,
-                        AppConstants.BROWSER_INTENT_CLASS_NAME,
-                        intent);
-            Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
-                    TelemetryContract.Method.WIDGET, "new-tab");
-        } else if (intent.getAction().equals(ACTION_LAUNCH_SEARCH)) {
-            redirect = buildRedirectIntent(Intent.ACTION_VIEW,
-                    AppConstants.SEARCH_PACKAGE_NAME,
-                    AppConstants.SEARCH_INTENT_CLASS_NAME,
-                    intent);
-            Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
-                    TelemetryContract.Method.WIDGET, "search");
-        } else {
-            redirect = null;
+                                               AppConstants.ANDROID_PACKAGE_NAME,
+                                               AppConstants.BROWSER_INTENT_CLASS_NAME,
+                                               intent);
+                Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
+                                      TelemetryContract.Method.WIDGET, "new-tab");
+                break;
+            case ACTION_LAUNCH_SEARCH:
+                redirect = buildRedirectIntent(Intent.ACTION_VIEW,
+                                               AppConstants.ANDROID_PACKAGE_NAME,
+                                               AppConstants.SEARCH_INTENT_CLASS_NAME,
+                                               intent);
+                Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH,
+                                      TelemetryContract.Method.WIDGET, "search");
+                break;
+            default:
+                redirect = null;
         }
 
         if (redirect != null) {
-            try {
-                context.startActivity(redirect);
-            } catch(Exception ex) {
-                // When this is built stand alone, its hardcoded to try and launch nightly.
-                // If that fails, just fire a generic VIEW intent.
-                Intent redirect2 = buildRedirectIntent(Intent.ACTION_VIEW, null, null, intent);
-                context.startActivity(redirect2);
-            }
+            context.startActivity(redirect);
         }
 
         super.onReceive(context, intent);
     }
 
     // Utility to create the view for this widget and attach any event listeners to it
     private void addView(final AppWidgetManager manager, final Context context, final int id, final Bundle options) {
         final int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
@@ -139,9 +134,9 @@ public class SearchWidget extends AppWid
         if (pkg != null && className != null) {
             activity.setClassName(pkg, className);
         }
         activity.setData(source.getData());
         activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         return activity;
     }
 
-}
\ No newline at end of file
+}
--- a/mobile/android/themes/core/aboutAddons.css
+++ b/mobile/android/themes/core/aboutAddons.css
@@ -21,19 +21,17 @@
 .description {
   width: 100%;
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
 }
 
 .status {
-  background-color: @color_about_item_inner@;
-  border-top: 2px solid;
-  -moz-border-top-colors: #bac2ac #ffffff;
+  border-top: 1px solid @color_about_item_border@;
   font-weight: bold;
   padding: 0.5em;
   width: 100%;
 }
 
 .options-header {
   font-weight: bold;
   text-transform: uppercase;
@@ -44,16 +42,20 @@
 .addon-item:not([optionsURL]) .options-header,
 .addon-item[optionsURL=""] .options-header,
 .addon-item[isDisabled="true"] .options-box,
 .addon-item:not([optionsURL]) .options-box,
 .addon-item[optionsURL=""] .options-box {
   display: none;
 }
 
+#addons-details > .list-item:active {
+  background-color: #fff;
+}
+
 /* Settings */
 
 setting {
   padding-bottom: 1em;
   -moz-box-align: center;
   box-sizing: border-box;
   width: 100%;
 }
@@ -132,17 +134,17 @@ textbox {
   background: #fff;
   border: 1px solid #ccc;
   border-radius: 4px;
   color: #333;
 }
 
 /* Button */
 
-button {
+setting button {
   margin: 2px 0;
   background: #fff;
   border: 1px solid #ccc;
   padding: 0.5em;
 }
 
 /* Menulist */
 
--- a/mobile/android/themes/core/aboutBase.css
+++ b/mobile/android/themes/core/aboutBase.css
@@ -5,24 +5,26 @@
 %filter substitution
 %include defines.inc
 
 html {
   font-family: "Clear Sans",sans-serif;
   font-size: 14px;
   background-color: @color_about_background@;
   -moz-text-size-adjust: none;
+  --icon-size: 1.8em;
+  --icon-margin: 1.35em;
 }
 
 body {
   margin: 0;
 }
 
 .header {
-  color: black;
+  color: #363B40;
   font-size: 1.1em;
   font-weight: bold;
   border-bottom: 2px solid;
   -moz-border-bottom-colors: #ff9100 #f27900;
   display: flex;
   flex-direction: row;
   align-items: center;
 }
@@ -43,58 +45,46 @@ body {
 
 .list {
   padding: 0px;
   margin: 0px;
   width: 100%;
 }
 
 .list-item {
-  color: black;
+  color: #363B40;
   background-color: @color_about_item@;
-  border-bottom: 2px solid;
-  -moz-border-bottom-colors: #ffffff #bac2ac;
+  border-bottom: 1px solid @color_about_item_border@;
   position: relative;
   list-style-type: none;
   list-style-image: none;
   margin: 0px;
   padding: 0px;
+  min-height: calc(var(--icon-size) + var(--icon-margin) * 2);
+}
+
+.list-item:active {
+  background-color: #eeeeee;
 }
 
 .list-item[isDisabled="true"] {
   color: #999999;
 }
 
-.list-item:active,
-.list-item:active > .inner {
-  background-image: none;
-}
-
 .inner {
-  background-color: @color_about_item_inner@;
+  -moz-margin-start: calc(var(--icon-size) + var(--icon-margin) * 2 - 1em);
   padding: 1em;
-
-  /* make room for the favicon */
-  -moz-margin-start: 4.5em;
-}
-
-/* Icons */
-body[dir="ltr"] .icon {
-  left: 1.35em;
-}
-
-body[dir="ltr"] .icon {
-  right: 1.35em;
 }
 
 .icon {
   border: none;
-  top: 1.35em;
-  width: 1.8em;
-  height: 1.8em;
+  width: var(--icon-size);
+  height: var(--icon-size);
+  top: var(--icon-margin);
+  -moz-margin-start: var(--icon-margin);
   position: absolute;
   pointer-events: none;
 }
 
 .list-item[isDisabled="true"] .favicon {
   opacity: 0.3;
 }
 
@@ -102,28 +92,29 @@ body[dir="ltr"] .icon {
 .buttons {
   display: flex;
   flex-direction: row;
   width: 100%;
 }
 
 .buttons > button {
   -moz-appearance: none;
-  color: black;
-  font-size: 1em !important;
+  font-size: 1em;
   border: 1px solid transparent;
-  border-top-color: #bac2ac;
-  -moz-border-start-color: #bac2ac;
-  background-image: none;
-  background-color: @color_about_item_inner@;
-  border-radius: 0px !important;
+  border-top-color: @color_about_item_border@;
+  -moz-border-start-color: @color_about_item_border@;
+  background-color: @color_about_item@;
   flex: 1;
   padding: 0.75em 0.5em;
 }
 
+.buttons > button:active {
+  background-color: #eeeeee;
+}
+
 .buttons > button[disabled="true"] {
   color: #b5b5b5;
 }
 
 .buttons > button[hidden="true"] {
   display: none;
 }
 
--- a/mobile/android/themes/core/aboutDownloads.css
+++ b/mobile/android/themes/core/aboutDownloads.css
@@ -5,50 +5,29 @@
 %filter substitution
 %include defines.inc
 
 .list-item > a {
   color: inherit;
   text-decoration: none;
 }
 
-.list-item {
-  height: 4.8em;
-  font-size: 1em !important;
-}
-
 #private-downloads-list .list-item {
-  background-image: none;
-  background-color: #080a0b;
+  background-color: #393e43;
   color: #ddd;
 }
 
-div.details {
-  background-color: #eef2f5;
-}
-
-#private-downloads-list div.details {
-  background-image: none;
-  background-color: #393e43;
-}
-
-li:active div.details,
-#private-downloads-list li:active div.details {
-  background-image: none;
-  background-color: transparent;
-}
-
 .details {
-  margin-left: 4.8em;
-  padding: .5em;
-  min-height: 3.7em;
+  -moz-margin-start: calc(var(--icon-size) + var(--icon-margin) * 2 - 1em);
+  padding: 1em;
 }
 
 .date {
   color: gray;
+  -moz-margin-start: 0.5em;
 }
 
 .domain,
 .size {
   display: inline;
 }
 
 .displayState {
--- a/mobile/android/themes/core/defines.inc
+++ b/mobile/android/themes/core/defines.inc
@@ -3,19 +3,19 @@
 %define form_border #bfbfbf
 %define form_border_radius-radius 2px
 %define form_text #363b40
 %define form_text_disabled #bebebe
 %define form_background white
 %define form_background_disabled #f5f5f5
 %define form_background white
 
-%define color_about_background #ced7de
-%define color_about_item #e6e9eb
-%define color_about_item_inner #eef2f5
+%define color_about_background #F5F5F5
+%define color_about_item #FFFFFF
+%define color_about_item_border #D7D9DB
 
 %define color_background_active #525252
 %define color_background_default #000
 %define color_text_default #fff
 %define color_divider_border #333333
 %define color_button_border #5a5a5a
 %define color_dialog_border #5a5a5a
 %define color_background_dlgbuttons #9a9a9a
--- a/services/healthreport/docs/dataformat.rst
+++ b/services/healthreport/docs/dataformat.rst
@@ -288,16 +288,21 @@ Keys are:
 
 Abnormal terminations will be missing a duration and will feature these keys:
 
 "oom"
     was the session killed by an OOM exception?
 "stopped"
     was the session stopped gently?
 
+Version 3.2
+-----------
+
+As of Firefox 35, the search counts measurement is now bumped to v6, including the *activity* location for the search activity.
+
 Version 3.1
 -----------
 
 As of Firefox 27, *appinfo* is now bumped to v3, including *osLocale*,
 *appLocale* (currently always the same as *osLocale*), *distribution* (a string
 containing the distribution ID and version, separated by a colon), and
 *acceptLangIsUserSet*, an integer-boolean that describes whether the user set
 an *intl.accept_languages* preference.
@@ -1380,16 +1385,21 @@ Example
     }
 
 org.mozilla.searches.counts
 ---------------------------
 
 This measurement contains information about searches performed in the
 application.
 
+Version 6 (mobile)
+^^^^^^^^^^^^^^^^^^
+
+This adds two new search locations: *widget* and *activity*, corresponding to the search widget and search activity respectively.
+
 Version 2
 ^^^^^^^^^
 
 This behaves like version 1 except we added all search engines that
 Mozilla has a partner agreement with. Like version 1, we concatenate
 a search engine ID with a search origin.
 
 Another difference with version 2 is we should no longer misattribute
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -249,16 +249,17 @@ user_pref("dom.mozApps.debug", true);
 user_pref("browser.newtabpage.directory.source", 'data:application/json,{"testing":1}');
 user_pref("browser.newtabpage.directory.ping", "");
 
 // Enable Loop
 user_pref("loop.enabled", true);
 user_pref("loop.throttled", false);
 user_pref("loop.oauth.google.URL", "http://%(server)s/browser/browser/components/loop/test/mochitest/google_service.sjs?action=");
 user_pref("loop.oauth.google.getContactsURL", "http://%(server)s/browser/browser/components/loop/test/mochitest/google_service.sjs?action=contacts");
+user_pref("loop.CSP","default-src 'self' about: file: chrome: data: wss://* http://* https://*");
 
 // Ensure UITour won't hit the network
 user_pref("browser.uitour.pinnedTabUrl", "http://%(server)s/uitour-dummy/pinnedTab");
 user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
 
 user_pref("media.eme.enabled", true);
 
 // Don't prompt about e10s
--- a/toolkit/devtools/apps/app-actor-front.js
+++ b/toolkit/devtools/apps/app-actor-front.js
@@ -660,62 +660,65 @@ AppActorFront.prototype = {
     let request = {
       to: this.actor,
       type: "unwatchApps"
     };
     return this.client.request(request);
   },
 
   _clientListener: function (type, message) {
-
     let { manifestURL } = message;
 
     // Reset the app object to get a fresh copy when we (re)install the app.
     if (type == "appInstall" && this._apps && this._apps.has(manifestURL)) {
       this._apps.delete(manifestURL);
     }
 
     this._getApp(manifestURL).then((app) => {
       switch(type) {
         case "appOpen":
           app.running = true;
+          this._notifyListeners("appOpen", app);
           break;
         case "appClose":
           app.running = false;
+          this._notifyListeners("appClose", app);
           break;
         case "appInstall":
           // The call to _getApp is going to create App object
 
           // This app may have been running while being installed, so check the list
           // of running apps again to get the right answer.
           let request = {
             to: this.actor,
             type: "listRunningApps"
           };
           this.client.request(request)
               .then(res => {
                 if (res.apps.indexOf(manifestURL) !== -1) {
                   app.running = true;
+                  this._notifyListeners("appInstall", app);
                   this._notifyListeners("appOpen", app);
+                } else {
+                  this._notifyListeners("appInstall", app);
                 }
               });
           break;
         case "appUninstall":
           // Fake a appClose event if we didn't got one before uninstall
           if (app.running) {
             app.running = false;
             this._notifyListeners("appClose", app);
           }
           this._apps.delete(manifestURL);
+          this._notifyListeners("appUninstall", app);
           break;
         default:
           return;
       }
-      this._notifyListeners(type, app);
-
     });
   },
 
   _notifyListeners: function (type, app) {
     this._listeners.forEach(f => {
       f(type, app);
     });
   },