Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 28 Feb 2014 10:15:57 -0500
changeset 171579 67f280d40200c30f735cd05e7e742b41412f4836
parent 171526 c4aa6080a06437e8d4d1e6a3db24d692351d3900 (current diff)
parent 171578 53dbf19f2f8d5de981e24cd488e5a1cbb8d2b677 (diff)
child 171580 095f820877eb9c449d64966deeaf908f764d17f1
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge m-c to inbound.
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -121,16 +121,31 @@ var shell = {
     // Bail if there isn't a valid crashID.
     if (!this.CrashSubmit || !crashID && !this.CrashSubmit.pendingIDs().length) {
       return;
     }
 
     // purge the queue.
     this.CrashSubmit.pruneSavedDumps();
 
+    // check for environment affecting crash reporting
+    let env = Cc["@mozilla.org/process/environment;1"]
+                .getService(Ci.nsIEnvironment);
+    let shutdown = env.get("MOZ_CRASHREPORTER_SHUTDOWN");
+    if (shutdown) {
+      let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
+                         .getService(Ci.nsIAppStartup);
+      appStartup.quit(Ci.nsIAppStartup.eForceQuit);
+    }
+
+    let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT");
+    if (noReport) {
+      return;
+    }
+
     try {
       // Check if we should automatically submit this crash.
       if (Services.prefs.getBoolPref('app.reportCrashes')) {
         this.submitCrash(crashID);
       } else {
         this.deleteCrash(crashID);
       }
     } catch (e) {
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="456499c44d1ef39b602ea02e9ed460b6aab85b44"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "remote": "", 
         "branch": "", 
         "revision": ""
     }, 
-    "revision": "8911c19f1f8d6fabd76c3892b62e6b87da9ff76e", 
+    "revision": "46003c7d6ba57fee31542ad22656334a34d4d8ef", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
@@ -91,17 +91,17 @@
   <project name="platform/prebuilt" path="prebuilt" revision="248d92592df169569c387a91db56b1fedd6e5d29"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="395aff045276107a285daf0392d0884a98b9f538"/>
   <project name="platform/system/core" path="system/core" revision="70229cf62037cfb70ec2257f7c78b5550628fb53"/>
   <project name="platform/system/extras" path="system/extras" revision="a5dd0ea60ce973c2c762b41835a43316fb4ff9e3"/>
   <project name="platform/system/media" path="system/media" revision="fbb3d9b4c5bf59071424e820e872e3f64f0a244a"/>
   <project name="platform/system/netd" path="system/netd" revision="2e226e6e636ca0a8cc4c51093e46f4baba1ffcce"/>
   <project name="platform/system/vold" path="system/vold" revision="8ac5eef8ea3a456b96d52ce2091bf6d814782d8c"/>
   <!-- hamachi specific things -->
-  <project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="43829d56fab6ad16883f1ac9f55ffb9aa5863543"/>
+  <project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="6d90df25658d59dfcfd34f83e74e75c3af3901af"/>
   <project name="quic/lf/b2g/external/jsmin" path="external/jsmin" revision="cec896f0affaa0226c02605ad28d42df1bc0e393"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="d13aaf080177b7c48f243d51827db5c7a7873cd0"/>
   <project name="platform/vendor/qcom/msm7627a" path="device/qcom/msm7627a" revision="f06bcacc6f13cec895dc5d4c2385c076396194ec"/>
   <project name="android-device-hamachi" path="device/qcom/hamachi" remote="b2g" revision="9071ac8f0830979fe4a96ce47c7443d8adf0929d"/>
   <project name="kernel/msm" path="kernel" revision="a6578b9cacf9079f2dcf5bfe77c31b1be18809e3"/>
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="19933e5d182a4799c6217b19a18562193a419298"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="5a58382180c70d0c446badc9c9837918ab69ec60"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="20d83ab382a1f813702421e76c2f9f994585990e"/>
--- 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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <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/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="9422aca1931ba6c68784f9e80bb1b6a7fcfd92e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3e9005ca10de70f6a55cf52c87a8b96937acd481"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="990ddd9f96fd4bac333d1178e56985d09bb26173"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -213,17 +213,19 @@
           <hbox id="UITourTooltipButtons" flex="1" align="center"/>
         </vbox>
         <vbox align="start">
           <toolbarbutton id="UITourTooltipClose" class="close-icon"
                          tooltiptext="&uiTour.infoPanel.close;"/>
         </vbox>
       </hbox>
     </panel>
+    <!-- type="default" forces frames to be created so that the panel's size can be determined --> 
     <panel id="UITourHighlightContainer"
+           type="default"
            hidden="true"
            noautofocus="true"
            noautohide="true"
            flip="none"
            consumeoutsideclicks="false"
            mousethrough="always">
       <box id="UITourHighlight"></box>
     </panel>
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -2,16 +2,17 @@
    - 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/. -->
 
 <panel id="PanelUI-popup"
        role="group"
        type="arrow"
        hidden="true"
        flip="slide"
+       position="bottomcenter topright"
        noautofocus="true">
   <panelmultiview id="PanelUI-multiView" mainViewId="PanelUI-mainView">
     <panelview id="PanelUI-mainView" context="customizationPanelContextMenu">
       <vbox id="PanelUI-contents-scroller">
         <vbox id="PanelUI-contents" class="panelUI-grid"/>
       </vbox>
 
       <footer id="PanelUI-footer">
@@ -218,14 +219,15 @@
   </svg:svg>
 </panel>
 
 <panel id="widget-overflow"
        role="group"
        type="arrow"
        noautofocus="true"
        context="toolbar-context-menu"
+       position="bottomcenter topright"
        hidden="true">
   <vbox id="widget-overflow-scroller">
     <vbox id="widget-overflow-list" class="widget-overflow-list"
           overflowfortoolbar="nav-bar"/>
   </vbox>
 </panel>
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -138,17 +138,17 @@ const PanelUI = {
           aEvent.type == "command") {
         anchor = this.menuButton;
       } else {
         anchor = aEvent.target;
       }
       let iconAnchor =
         document.getAnonymousElementByAttribute(anchor, "class",
                                                 "toolbarbutton-icon");
-      this.panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
+      this.panel.openPopup(iconAnchor || anchor);
 
       this.panel.addEventListener("popupshown", function onPopupShown() {
         this.removeEventListener("popupshown", onPopupShown);
         deferred.resolve();
       });
     });
 
     return deferred.promise;
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -3486,40 +3486,37 @@ OverflowableToolbar.prototype = {
   show: function() {
     let deferred = Promise.defer();
     if (this._panel.state == "open") {
       deferred.resolve();
       return deferred.promise;
     }
     let doc = this._panel.ownerDocument;
     this._panel.hidden = false;
+    let contextMenu = doc.getElementById(this._panel.getAttribute("context"));
+    gELS.addSystemEventListener(contextMenu, 'command', this, true);
     let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
-    this._panel.openPopup(anchor || this._chevron, "bottomcenter topright");
+    this._panel.openPopup(anchor || this._chevron);
     this._chevron.open = true;
 
     this._panel.addEventListener("popupshown", function onPopupShown() {
       this.removeEventListener("popupshown", onPopupShown);
       deferred.resolve();
     });
 
     return deferred.promise;
   },
 
   _onClickChevron: function(aEvent) {
     if (this._chevron.open) {
       this._panel.hidePopup();
+      this._chevron.open = false;
     } else {
-      let doc = aEvent.target.ownerDocument;
-      this._panel.hidden = false;
-      let contextMenu = doc.getElementById(this._panel.getAttribute("context"));
-      gELS.addSystemEventListener(contextMenu, 'command', this, true);
-      let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
-      this._panel.openPopup(anchor || this._chevron, "bottomcenter topright");
+      this.show();
     }
-    this._chevron.open = !this._chevron.open;
   },
 
   _onPanelHiding: function(aEvent) {
     this._chevron.open = false;
     let doc = aEvent.target.ownerDocument;
     let contextMenu = doc.getElementById(this._panel.getAttribute("context"));
     gELS.removeSystemEventListener(contextMenu, 'command', this, true);
   },
--- a/browser/components/customizableui/src/CustomizeMode.jsm
+++ b/browser/components/customizableui/src/CustomizeMode.jsm
@@ -1683,28 +1683,46 @@ CustomizeMode.prototype = {
       return aEvent.target;
     }
     // Offset the drag event's position with the offset to the center of
     // the thing we're dragging
     let dragX = aEvent.clientX - this._dragOffset.x;
     let dragY = aEvent.clientY - this._dragOffset.y;
 
     // Ensure this is within the container
-    let bounds = expectedParent.getBoundingClientRect();
+    let boundsContainer = expectedParent;
+    // NB: because the panel UI itself is inside a scrolling container, we need
+    // to use the parent bounds (otherwise, if the panel UI is scrolled down,
+    // the numbers we get are in window coordinates which leads to various kinds
+    // of weirdness)
+    if (boundsContainer == this.panelUIContents) {
+      boundsContainer = boundsContainer.parentNode;
+    }
+    let bounds = boundsContainer.getBoundingClientRect();
     dragX = Math.min(bounds.right, Math.max(dragX, bounds.left));
     dragY = Math.min(bounds.bottom, Math.max(dragY, bounds.top));
 
     let targetNode;
     if (aInToolbar) {
       targetNode = aAreaElement.ownerDocument.elementFromPoint(dragX, dragY);
       while (targetNode && targetNode.parentNode != expectedParent) {
         targetNode = targetNode.parentNode;
       }
     } else {
       let positionManager = DragPositionManager.getManagerForArea(aAreaElement);
+      // Make it relative to the container:
+      dragX -= bounds.left;
+      // NB: but if we're in the panel UI, we need to use the actual panel
+      // contents instead of the scrolling container to determine our origin
+      // offset against:
+      if (expectedParent == this.panelUIContents) {
+        dragY -= this.panelUIContents.getBoundingClientRect().top;
+      } else {
+        dragY -= bounds.top;
+      }
       // Find the closest node:
       targetNode = positionManager.find(aAreaElement, dragX, dragY, aDraggedItemId);
     }
     return targetNode || aEvent.target;
   },
 
   _onMouseDown: function(aEvent) {
     LOG("_onMouseDown");
--- a/browser/components/customizableui/src/DragPositionManager.jsm
+++ b/browser/components/customizableui/src/DragPositionManager.jsm
@@ -16,16 +16,17 @@ this.EXPORTED_SYMBOLS = ["DragPositionMa
 function AreaPositionManager(aContainer) {
   // Caching the direction and bounds of the container for quick access later:
   let window = aContainer.ownerDocument.defaultView;
   this._dir = window.getComputedStyle(aContainer).direction;
   let containerRect = aContainer.getBoundingClientRect();
   this._containerInfo = {
     left: containerRect.left,
     right: containerRect.right,
+    top: containerRect.top,
     width: containerRect.width
   };
   this._inPanel = aContainer.id == CustomizableUI.AREA_PANEL;
   this._horizontalDistance = null;
   this.update(aContainer);
 }
 
 AreaPositionManager.prototype = {
@@ -71,20 +72,24 @@ AreaPositionManager.prototype = {
    * which are in the same row over nodes that are in a different row.
    * In order to implement this, we use a weighted cartesian distance
    * where dy is more heavily weighted by a factor corresponding to the
    * ratio between the container's width and the height of its elements.
    */
   find: function(aContainer, aX, aY, aDraggedItemId) {
     let closest = null;
     let minCartesian = Number.MAX_VALUE;
+    let containerX = this._containerInfo.left;
+    let containerY = this._containerInfo.top;
     for (let node of aContainer.children) {
       let coordinates = this._lazyStoreGet(node);
-      let hDiff = coordinates.x - aX;
-      let vDiff = coordinates.y - aY;
+      let offsetX = coordinates.x - containerX;
+      let offsetY = coordinates.y - containerY;
+      let hDiff = offsetX - aX;
+      let vDiff = offsetY - aY;
       // For wide widgets, we're always going to be further from the center
       // horizontally. Compensate:
       if (this.isWide(node)) {
         hDiff /= CustomizableUI.PANEL_COLUMN_COUNT;
       }
       // Then compensate for the height/width ratio so that we prefer items
       // which are in the same row:
       hDiff /= this._heightToWidthFactor;
--- a/browser/components/preferences/sync.xul
+++ b/browser/components/preferences/sync.xul
@@ -181,28 +181,27 @@
         <!-- These panels are for the Firefox Accounts identity provider -->
         <vbox id="fxaDeterminingStatus" align="center">
           <spacer flex="1"/>
           <p>&determiningAcctStatus.label;</p>
           <spacer flex="1"/>
         </vbox>
 
         <vbox id="noFxaAccount">
-          <description>&welcome.description;</description>
+          <label value="&welcome.description;"/>
           <label class="text-link"
                  onclick="gSyncPane.signUp(); return false;"
                  value="&welcome.createAccount.label;"/>
           <label class="text-link"
                  onclick="gSyncPane.signIn(); return false;"
                  value="&welcome.signIn.label;"/>
-          <spacer flex="1"/>
+          <separator/>
           <label class="text-link"
                  onclick="gSyncPane.openOldSyncSupportPage(); return false;"
                  value="&welcome.useOldSync.label;"/>
-          <spacer flex="10"/>
         </vbox>
 
         <vbox id="hasFxaAccount">
           <groupbox id="fxaGroup">
             <caption label="&syncBrand.fxAccount.label;"/>
 
             <deck id="fxaLoginStatus">
 
@@ -300,20 +299,21 @@
           <hbox align="center">
             <label value="&syncDeviceName.label;"
                    accesskey="&syncDeviceName.accesskey;"
                    control="syncComputerName"/>
             <textbox id="fxaSyncComputerName"
                      flex="1"
                      onchange="gSyncUtils.changeName(this)"/>
           </hbox>
+          <spacer flex="1"/>
           <hbox id="tosPP" pack="center">
-            <label class="text-link"
+            <label class="text-link small"
                    onclick="event.stopPropagation();gSyncUtils.openToS();"
                    value="&prefs.tosLink.label;"/>
-            <label class="text-link"
+            <label class="text-link small"
                    onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"
                    value="&fxaPrivacyNotice.link.label;"/>
           </hbox>
         </vbox>
       </deck>
   </prefpane>
 </overlay>
--- a/browser/themes/linux/preferences/preferences.css
+++ b/browser/themes/linux/preferences/preferences.css
@@ -41,16 +41,24 @@ radio[pane=paneAdvanced] {
 }
 
 %ifdef MOZ_SERVICES_SYNC
 radio[pane=paneSync] {
   list-style-image: url("chrome://browser/skin/preferences/Options-sync.png") !important;
 }
 %endif
 
+label.small {
+  font-size: smaller;
+}
+
+#tabPrefsBox {
+  margin: 5px;
+}
+
 /* Applications Pane */
 #BrowserPreferences[animated="true"] #handlersView {
   height: 25em;
 }
 
 #BrowserPreferences[animated="false"] #handlersView {
   -moz-box-flex: 1;
 }
@@ -143,9 +151,18 @@ radio[pane=paneSync] {
   list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
 }
 
 #syncAddDeviceLabel {
   margin-top: 1em;
   margin-bottom: 1em;
 }
 
+#noFxaAccount {
+  margin: 5px;
+  line-height: 1.2em;
+}
+
+#noFxaAccount > label:first-child {
+  margin-bottom: 0.6em;
+}
+
 %endif
--- a/browser/themes/osx/preferences/preferences.css
+++ b/browser/themes/osx/preferences/preferences.css
@@ -65,16 +65,19 @@ radio[pane=paneAdvanced] {
 %ifdef MOZ_SERVICES_SYNC
 /* ----- SYNC BUTTON ----- */
 
 radio[pane=paneSync] {
   list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
 }
 %endif
 
+label.small {
+  font-size: smaller;
+}
 
 /* ----- APPLICATIONS PREFPANE ----- */
 #BrowserPreferences[animated="true"] #handlersView {
   height: 25em;
 }
 
 #BrowserPreferences[animated="false"] #handlersView {
   -moz-box-flex: 1;
@@ -213,9 +216,18 @@ html|a.inline-link:-moz-focusring {
   margin-top: 1em;
   margin-bottom: 1em;
 }
 
 #fxaUnlinkButton {
   margin: 0;
 }
 
+#noFxaAccount {
+  margin: 12px 4px;
+  line-height: 1.2em;
+}
+
+#noFxaAccount > label:first-child {
+  margin-bottom: 0.6em;
+}
+
 %endif
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2495,16 +2495,26 @@ chatbox {
   border-top-left-radius: 2.5px;
   border-top-right-radius: 2.5px;
 }
 
 /* Customization mode */
 
 %include ../shared/customizableui/customizeMode.inc.css
 
+/**
+ * This next rule is a hack to disable subpixel anti-aliasing on all
+ * labels during the customize mode transition. Subpixel anti-aliasing
+ * on Windows with Direct2D layers acceleration is particularly slow to
+ * paint, so this hack is how we sidestep that performance bottleneck.
+ */
+#main-window:-moz-any([customize-entering],[customize-exiting]) label {
+  transform: perspective(0.01px);
+}
+
 #main-window[customize-entered] {
   background-image: url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png");
   background-attachment: fixed;
 }
 
 #customization-container {
   border-left: 1px solid @toolbarShadowColor@;
   border-right: 1px solid @toolbarShadowColor@;
--- a/browser/themes/windows/preferences/preferences.css
+++ b/browser/themes/windows/preferences/preferences.css
@@ -40,16 +40,24 @@ radio[pane=paneAdvanced] {
 }
 
 %ifdef MOZ_SERVICES_SYNC
 radio[pane=paneSync] {
   list-style-image: url("chrome://browser/skin/preferences/Options-sync.png") !important;
 }
 %endif
 
+label.small {
+  font-size: smaller;
+}
+
+#tabPrefsBox {
+  margin: 6px;
+}
+
 /* Applications Pane */
 #BrowserPreferences[animated="true"] #handlersView {
   height: 25em;
 }
 
 #BrowserPreferences[animated="false"] #handlersView {
   -moz-box-flex: 1;
 }
@@ -133,9 +141,18 @@ radio[pane=paneSync] {
   list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
 }
 
 #syncAddDeviceLabel {
   margin-top: 1em;
   margin-bottom: 1em;
 }
 
+#noFxaAccount {
+  margin: 6px;
+  line-height: 1.2em;
+}
+
+#noFxaAccount > label:first-child {
+  margin-bottom: 0.6em;
+}
+
 %endif
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -10,17 +10,17 @@
 #include <cutils/properties.h>
 #include <stagefright/foundation/ADebug.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaExtractor.h>
 #include <stagefright/MetaData.h>
 #include <stagefright/OMXClient.h>
 #include <stagefright/OMXCodec.h>
 #include <OMX.h>
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 #include <ui/Fence.h>
 #endif
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Types.h"
 #include "mozilla/Monitor.h"
 #include "nsMimeTypes.h"
 #include "MPAPI.h"
@@ -1055,17 +1055,17 @@ void OmxDecoder::ReleaseAllPendingVideoB
     }
     mPendingVideoBuffers.clear();
   }
   // Free all pending video buffers without holding mPendingVideoBuffersLock.
   int size = releasingVideoBuffers.size();
   for (int i = 0; i < size; i++) {
     MediaBuffer *buffer;
     buffer = releasingVideoBuffers[i].mMediaBuffer;
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
     android::sp<Fence> fence;
     int fenceFd = -1;
     fence = releasingVideoBuffers[i].mReleaseFenceHandle.mFence;
     if (fence.get() && fence->isValid()) {
       fenceFd = fence->dup();
     }
     MOZ_ASSERT(buffer->refcount() == 1);
     // This code expect MediaBuffer's ref count is 1.
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -27,24 +27,23 @@
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
 
-#if defined(MOZ_CONTENT_SANDBOX)
-#if defined(XP_WIN)
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
-#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+#endif
+#if defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
 #endif
-#endif
 
 #include "mozilla/unused.h"
 
 #include "nsIConsoleListener.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
@@ -654,29 +653,28 @@ ContentChild::AllocPBackgroundChild(Tran
 }
 
 bool
 ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
 {
   ChildPrivileges privs = (aPrivs == PRIVILEGES_DEFAULT) ?
                           GeckoChildProcessHost::DefaultChildPrivileges() :
                           aPrivs;
+#if defined(XP_LINUX)
+  // SetCurrentProcessSandbox includes SetCurrentProcessPrivileges.
+  // But we may want to move the sandbox initialization somewhere else
+  // at some point; see bug 880808.
+  SetCurrentProcessSandbox(privs);
+#else
   // If this fails, we die.
   SetCurrentProcessPrivileges(privs);
+#endif
 
-#if defined(MOZ_CONTENT_SANDBOX)
-#if defined(XP_WIN)
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
   mozilla::SandboxTarget::Instance()->StartSandbox();
-#else if defined(XP_UNIX) && !defined(XP_MACOSX)
-  // SetCurrentProcessSandbox should be moved close to process initialization
-  // time if/when possible. SetCurrentProcessPrivileges should probably be
-  // moved as well. Right now this is set ONLY if we receive the
-  // RecvSetProcessPrivileges message. See bug 880808.
-  SetCurrentProcessSandbox();
-#endif
 #endif
   return true;
 }
 
 bool
 ContentChild::RecvSpeakerManagerNotify()
 {
 #ifdef MOZ_WIDGET_GONK
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -299,17 +299,17 @@ CompositableParentManager::ReceiveCompos
     default: {
       MOZ_ASSERT(false, "bad type");
     }
   }
 
   return true;
 }
 
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 void
 CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
                                                         EditReplyVector& replyv,
                                                         PCompositableParent* aParent)
 {
   if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
     return;
   }
--- a/gfx/layers/ipc/FenceUtils.h
+++ b/gfx/layers/ipc/FenceUtils.h
@@ -8,36 +8,36 @@
 #ifndef IPC_FencerUtils_h
 #define IPC_FencerUtils_h
 
 #include "ipc/IPCMessageUtils.h"
 
 /**
  * FenceHandle is used for delivering Fence object via ipc.
  */
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 # include "mozilla/layers/FenceUtilsGonk.h"
 #else
 namespace mozilla {
 namespace layers {
 struct FenceHandle {
   bool operator==(const FenceHandle&) const { return false; }
   bool IsValid() const { return false; }
 };
 } // namespace layers
 } // namespace mozilla
-#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 
 namespace IPC {
 
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 #else
 template <>
 struct ParamTraits<mozilla::layers::FenceHandle> {
   typedef mozilla::layers::FenceHandle paramType;
   static void Write(Message*, const paramType&) {}
   static bool Read(const Message*, void**, paramType*) { return false; }
 };
-#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 
 } // namespace IPC
 
 #endif // IPC_FencerUtils_h
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -198,17 +198,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
         'opengl/EGLImageHelpers.cpp',
         'opengl/GrallocTextureClient.cpp',
         'opengl/GrallocTextureHost.cpp',
     ]
     SOURCES += [
         'ipc/ShadowLayerUtilsGralloc.cpp',
     ]
 
-    if CONFIG['ANDROID_VERSION'] >= '18':
+    if CONFIG['ANDROID_VERSION'] >= '17':
         EXPORTS.mozilla.layers += [
             'ipc/FenceUtilsGonk.h',
         ]
         SOURCES += [
             'ipc/FenceUtilsGonk.cpp',
         ]
 
 UNIFIED_SOURCES += [
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -213,20 +213,25 @@ GrallocTextureClientOGL::Lock(OpenMode a
   if (!IsValid() || !IsAllocated()) {
     return false;
   }
 
   if (mMappedBuffer) {
     return true;
   }
 
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
   if (mReleaseFenceHandle.IsValid()) {
     android::sp<Fence> fence = mReleaseFenceHandle.mFence;
+#if ANDROID_VERSION == 17
+    fence->waitForever(1000, "GrallocTextureClientOGL::Lock");
+    // 1000 is what Android uses. It is warning timeout ms.
+#else
     fence->waitForever("GrallocTextureClientOGL::Lock");
+#endif
     mReleaseFenceHandle = FenceHandle();
   }
 #endif
 
   uint32_t usage = 0;
   if (aMode & OPEN_READ) {
     usage |= GRALLOC_USAGE_SW_READ_OFTEN;
   }
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -66,17 +66,17 @@ protected:
   CompositorOGL* mCompositor;
   android::sp<android::GraphicBuffer> mGraphicBuffer;
   EGLImage mEGLImage;
   gfx::SurfaceFormat mFormat;
   bool mNeedsReset;
 };
 
 class GrallocTextureHostOGL : public TextureHost
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
                             , public TextureHostOGL
 #endif
 {
   friend class GrallocBufferActor;
 public:
   GrallocTextureHostOGL(TextureFlags aFlags,
                         const NewSurfaceDescriptorGralloc& aDescriptor);
 
@@ -102,17 +102,17 @@ public:
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
   virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
   {
     return mTextureSource;
   }
 
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
   virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE
   {
     return this;
   }
 #endif
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
 
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -196,17 +196,17 @@ CompositableDataGonkOGL::DeleteTextureIf
   if (mTexture) {
     if (gl()->MakeCurrent()) {
       gl()->fDeleteTextures(1, &mTexture);
     }
     mTexture = 0;
   }
 }
 
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 bool
 TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
 {
   if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
     return false;
   }
 
   if (!mReleaseFence.get()) {
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -26,17 +26,17 @@
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for TextureImage::Release, etc
 #include "OGLShaderProgram.h"           // for ShaderProgramType, etc
 #ifdef MOZ_WIDGET_GONK
 #include <ui/GraphicBuffer.h>
-#if ANDROID_VERSION >= 18
+#if ANDROID_VERSION >= 17
 #include <ui/Fence.h>
 #endif
 #endif
 
 class gfxImageSurface;
 class gfxReusableSurfaceWrapper;
 class nsIntRegion;
 struct nsIntPoint;
@@ -120,17 +120,17 @@ public:
 };
 
 /**
  * TextureHostOGL provides the necessary API for platform specific composition.
  */
 class TextureHostOGL
 {
 public:
-#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
+#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 
   /**
    * Store a fence that will signal when the current buffer is no longer being read.
    * Similar to android's GLConsumer::setReleaseFence()
    */
   virtual bool SetReleaseFence(const android::sp<android::Fence>& aReleaseFence);
 
   /**
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2447,18 +2447,16 @@ ContainerState::ProcessDisplayItems(cons
       // Note that items without their own layers can't be skipped this
       // way, since their ThebesLayer may decide it wants to draw them
       // into its buffer even if they're currently covered.
       if (itemVisibleRect.IsEmpty() &&
           !item->ShouldBuildLayerEvenIfInvisible(mBuilder)) {
         continue;
       }
 
-      bool setVisibleRegion = (itemType != nsDisplayItem::TYPE_TRANSFORM) &&
-        (itemType != nsDisplayItem::TYPE_SCROLL_LAYER);
       if (itemType == nsDisplayItem::TYPE_TRANSFORM) {
         mParameters.mAncestorClipRect = itemClip.HasClip() ? &clipRect : nullptr;
       } else {
         mParameters.mAncestorClipRect = nullptr;
       }
 
       // Just use its layer.
       nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
@@ -2521,17 +2519,17 @@ ContainerState::ProcessDisplayItems(cons
           // Add the entire bounds rect to the mDrawAboveRegion.
           // The visible region may be excluding opaque content above the
           // item, and we need to ensure that that content is not placed
           // in a ThebesLayer below the item!
           data->AddDrawAboveRegion(itemDrawRect);
         }
       }
       itemVisibleRect.MoveBy(mParameters.mOffset);
-      if (setVisibleRegion) {
+      if (item->SetVisibleRegionOnLayer()) {
         SetVisibleRegionForLayer(ownLayer, ownLayer->GetVisibleRegion(), itemVisibleRect);
       }
 
       // rounded rectangle clipping using mask layers
       // (must be done after visible rect is set on layer)
       if (itemClip.IsRectClippedByRoundedCorner(itemContent)) {
         SetupMaskLayer(ownLayer, itemClip);
       }
--- a/layout/base/nsDisplayItemTypesList.h
+++ b/layout/base/nsDisplayItemTypesList.h
@@ -44,16 +44,17 @@ DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_VIDEO)
 DECLARE_DISPLAY_ITEM_TYPE(PRINT_PLUGIN)
 DECLARE_DISPLAY_ITEM_TYPE(REMOTE)
 DECLARE_DISPLAY_ITEM_TYPE(REMOTE_SHADOW)
 DECLARE_DISPLAY_ITEM_TYPE(RESOLUTION)
 DECLARE_DISPLAY_ITEM_TYPE(SCROLL_LAYER)
 DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER)
 DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY)
 DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR)
+DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_EFFECTS)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_GLYPHS)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)
 DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
 DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
 DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
 DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND)
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1239,22 +1239,27 @@ void nsDisplayList::PaintForFrame(nsDisp
       if (isRoot) {
         id = nsLayoutUtils::FindOrCreateIDFor(content);
       }
     }
   }
 
   nsRect viewport(aBuilder->ToReferenceFrame(aForFrame), aForFrame->GetSize());
 
-  RecordFrameMetrics(aForFrame, rootScrollFrame,
-                     aBuilder->FindReferenceFrameFor(aForFrame),
-                     root, mVisibleRect, viewport,
-                     (usingDisplayport ? &displayport : nullptr),
-                     (usingCriticalDisplayport ? &criticalDisplayport : nullptr),
-                     id, isRoot, containerParameters);
+  // If we are ignoring the root scroll frame we make the RecordFrameMetrics
+  // call for it. Otherwise nsGfxScrollFrame will create scroll layer(s) that
+  // will do that.
+  if (aBuilder->GetIgnoreScrollFrame() == rootScrollFrame) {
+    RecordFrameMetrics(aForFrame, rootScrollFrame,
+                       aBuilder->FindReferenceFrameFor(aForFrame),
+                       root, mVisibleRect, viewport,
+                       (usingDisplayport ? &displayport : nullptr),
+                       (usingCriticalDisplayport ? &criticalDisplayport : nullptr),
+                       id, isRoot, containerParameters);
+  }
   if (usingDisplayport &&
       !(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
     // See bug 693938, attachment 567017
     NS_WARNING("Transparent content with displayports can be expensive.");
   }
 
   layerManager->SetRoot(root);
   layerBuilder->WillEndTransaction();
@@ -3418,20 +3423,156 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayL
   }
 
   if (mFlags & GENERATE_SUBDOC_INVALIDATIONS) {
     mFrame->PresContext()->SetNotifySubDocInvalidationData(layer);
   }
   return layer.forget();
 }
 
+nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
+                                           nsIFrame* aFrame, nsDisplayList* aList,
+                                           uint32_t aFlags)
+    : nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags) {
+  MOZ_COUNT_CTOR(nsDisplaySubDocument);
+}
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+nsDisplaySubDocument::~nsDisplaySubDocument() {
+  MOZ_COUNT_DTOR(nsDisplaySubDocument);
+}
+#endif
+
+already_AddRefed<Layer>
+nsDisplaySubDocument::BuildLayer(nsDisplayListBuilder* aBuilder,
+                                 LayerManager* aManager,
+                                 const ContainerLayerParameters& aContainerParameters) {
+  nsRefPtr<Layer> layer = nsDisplayOwnLayer::BuildLayer(
+    aBuilder, aManager, aContainerParameters);
+
+  if (!(mFlags & GENERATE_SCROLLABLE_LAYER)) {
+    return layer.forget();
+  }
+
+  NS_ASSERTION(layer->AsContainerLayer(), "nsDisplayOwnLayer should have made a ContainerLayer");
+  if (ContainerLayer* container = layer->AsContainerLayer()) {
+    nsPresContext* presContext = mFrame->PresContext();
+    nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
+    bool isRootContentDocument = presContext->IsRootContentDocument();
+
+    bool usingDisplayport = false;
+    bool usingCriticalDisplayport = false;
+    nsRect displayport, criticalDisplayport;
+    ViewID scrollId = FrameMetrics::NULL_SCROLL_ID;
+    if (rootScrollFrame) {
+      nsIContent* content = rootScrollFrame->GetContent();
+      if (content) {
+        usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
+        usingCriticalDisplayport =
+          nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
+
+        if (isRootContentDocument) {
+          scrollId = nsLayoutUtils::FindOrCreateIDFor(content);
+        } else {
+          nsLayoutUtils::FindIDFor(content, &scrollId);
+        }
+      }
+    }
+
+    nsRect viewport = mFrame->GetRect() -
+                      mFrame->GetPosition() +
+                      mFrame->GetOffsetToCrossDoc(ReferenceFrame());
+
+    RecordFrameMetrics(mFrame, rootScrollFrame, ReferenceFrame(),
+                       container, mVisibleRect, viewport,
+                       (usingDisplayport ? &displayport : nullptr),
+                       (usingCriticalDisplayport ? &criticalDisplayport : nullptr),
+                       scrollId, isRootContentDocument, aContainerParameters);
+  }
+
+  return layer.forget();
+}
+
+nsRect
+nsDisplaySubDocument::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
+{
+  bool usingDisplayPort =
+    nsLayoutUtils::ViewportHasDisplayPort(mFrame->PresContext());
+
+  if ((mFlags & GENERATE_SCROLLABLE_LAYER) && usingDisplayPort) {
+    *aSnap = false;
+    return mFrame->GetRect() + aBuilder->ToReferenceFrame(mFrame);
+  }
+
+  return nsDisplayOwnLayer::GetBounds(aBuilder, aSnap);
+}
+
+bool
+nsDisplaySubDocument::ComputeVisibility(nsDisplayListBuilder* aBuilder,
+                                        nsRegion* aVisibleRegion,
+                                        const nsRect& aAllowVisibleRegionExpansion)
+{
+  nsRect displayport;
+  bool usingDisplayPort =
+    nsLayoutUtils::ViewportHasDisplayPort(mFrame->PresContext(), &displayport);
+
+  if (!(mFlags & GENERATE_SCROLLABLE_LAYER) || !usingDisplayPort) {
+    return nsDisplayWrapList::ComputeVisibility(aBuilder, aVisibleRegion,
+                                                aAllowVisibleRegionExpansion);
+  }
+
+  nsRegion childVisibleRegion;
+  // The visible region for the children may be much bigger than the hole we
+  // are viewing the children from, so that the compositor process has enough
+  // content to asynchronously pan while content is being refreshed.
+  childVisibleRegion = displayport + mFrame->GetOffsetToCrossDoc(ReferenceFrame());
+
+  nsRect boundedRect =
+    childVisibleRegion.GetBounds().Intersect(mList.GetBounds(aBuilder));
+  nsRect allowExpansion = boundedRect.Intersect(aAllowVisibleRegionExpansion);
+  bool visible = mList.ComputeVisibilityForSublist(
+    aBuilder, &childVisibleRegion, boundedRect, allowExpansion);
+  // We don't allow this computation to influence aVisibleRegion, on the
+  // assumption that the layer can be asynchronously scrolled so we'll
+  // definitely need all the content under it.
+
+  return visible;
+}
+
+bool
+nsDisplaySubDocument::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
+{
+  bool usingDisplayPort =
+    nsLayoutUtils::ViewportHasDisplayPort(mFrame->PresContext());
+
+  if ((mFlags & GENERATE_SCROLLABLE_LAYER) && usingDisplayPort) {
+    return true;
+  }
+
+  return nsDisplayOwnLayer::ShouldBuildLayerEvenIfInvisible(aBuilder);
+}
+
+nsRegion
+nsDisplaySubDocument::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap)
+{
+  bool usingDisplayPort =
+    nsLayoutUtils::ViewportHasDisplayPort(mFrame->PresContext());
+
+  if ((mFlags & GENERATE_SCROLLABLE_LAYER) && usingDisplayPort) {
+    *aSnap = false;
+    return nsRegion();
+  }
+
+  return nsDisplayOwnLayer::GetOpaqueRegion(aBuilder, aSnap);
+}
+
 nsDisplayResolution::nsDisplayResolution(nsDisplayListBuilder* aBuilder,
                                          nsIFrame* aFrame, nsDisplayList* aList,
                                          uint32_t aFlags)
-    : nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags) {
+    : nsDisplaySubDocument(aBuilder, aFrame, aList, aFlags) {
   MOZ_COUNT_CTOR(nsDisplayResolution);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayResolution::~nsDisplayResolution() {
   MOZ_COUNT_DTOR(nsDisplayResolution);
 }
 #endif
@@ -3440,17 +3581,17 @@ already_AddRefed<Layer>
 nsDisplayResolution::BuildLayer(nsDisplayListBuilder* aBuilder,
                                 LayerManager* aManager,
                                 const ContainerLayerParameters& aContainerParameters) {
   nsIPresShell* presShell = mFrame->PresContext()->PresShell();
   ContainerLayerParameters containerParameters(
     presShell->GetXResolution(), presShell->GetYResolution(), nsIntPoint(),
     aContainerParameters);
 
-  nsRefPtr<Layer> layer = nsDisplayOwnLayer::BuildLayer(
+  nsRefPtr<Layer> layer = nsDisplaySubDocument::BuildLayer(
     aBuilder, aManager, containerParameters);
   layer->SetPostScale(1.0f / presShell->GetXResolution(),
                       1.0f / presShell->GetYResolution());
   return layer.forget();
 }
 
 nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
                                                  nsIFrame* aFrame,
@@ -3865,17 +4006,17 @@ nsDisplayScrollInfoLayer::ShouldFlattenA
   // visibility computation.
   return GetScrollLayerCount() == 1;
 }
 
 nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
                              nsIFrame* aFrame, nsDisplayList* aList,
                              int32_t aAPD, int32_t aParentAPD,
                              uint32_t aFlags)
-    : nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags)
+    : nsDisplaySubDocument(aBuilder, aFrame, aList, aFlags)
     , mAPD(aAPD), mParentAPD(aParentAPD) {
   MOZ_COUNT_CTOR(nsDisplayZoom);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayZoom::~nsDisplayZoom() {
   MOZ_COUNT_DTOR(nsDisplayZoom);
 }
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1228,16 +1228,21 @@ public:
   {
     if (!aClip.HasClip()) {
       mClip = nullptr;
       return;
     }
     mClip = aBuilder->AllocateDisplayItemClip(aClip);
   }
 
+  // If we return false here it means that if this item creates a layer then
+  // ProcessDisplayItems will not set the visible region on the layer. The item
+  // should set the visible region, usually in BuildContainerLayer.
+  virtual bool SetVisibleRegionOnLayer() { return true; }
+
 protected:
   friend class nsDisplayList;
 
   nsDisplayItem() { mAbove = nullptr; }
 
   nsIFrame* mFrame;
   const DisplayItemClip* mClip;
   // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
@@ -2651,23 +2656,27 @@ class nsDisplayOwnLayer : public nsDispl
 public:
 
   /**
    * nsDisplayOwnLayer constructor flags
    */
   enum {
     GENERATE_SUBDOC_INVALIDATIONS = 0x01,
     VERTICAL_SCROLLBAR = 0x02,
-    HORIZONTAL_SCROLLBAR = 0x04
+    HORIZONTAL_SCROLLBAR = 0x04,
+    GENERATE_SCROLLABLE_LAYER = 0x08
   };
 
   /**
    * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
    * Add UserData to the created ContainerLayer, so that invalidations
    * for this layer are send to our nsPresContext.
+   * GENERATE_SCROLLABLE_LAYER : only valid on nsDisplaySubDocument (and
+   * subclasses), indicates this layer is to be a scrollable layer, so call
+   * RecordFrameMetrics, etc.
    * @param aScrollTarget when VERTICAL_SCROLLBAR or HORIZONTAL_SCROLLBAR
    * is set in the flags, this parameter should be the ViewID of the
    * scrollable content this scrollbar is for.
    */
   nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                     nsDisplayList* aList, uint32_t aFlags = 0,
                     ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID);
 #ifdef NS_BUILD_REFCNT_LOGGING
@@ -2685,30 +2694,62 @@ public:
   }
   virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE
   {
     // Don't allow merging, each sublist must have its own layer
     return false;
   }
   uint32_t GetFlags() { return mFlags; }
   NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
-private:
+protected:
   uint32_t mFlags;
   ViewID mScrollTarget;
 };
 
 /**
+ * A display item for subdocuments. This is more or less the same as nsDisplayOwnLayer,
+ * except that it always populates the FrameMetrics instance on the ContainerLayer it
+ * builds.
+ */
+class nsDisplaySubDocument : public nsDisplayOwnLayer {
+public:
+  nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
+                       nsDisplayList* aList, uint32_t aFlags);
+#ifdef NS_BUILD_REFCNT_LOGGING
+  virtual ~nsDisplaySubDocument();
+#endif
+
+  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
+                                             LayerManager* aManager,
+                                             const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
+
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
+
+  virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
+                                 nsRegion* aVisibleRegion,
+                                 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
+
+  virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return !(mFlags & GENERATE_SCROLLABLE_LAYER); }
+
+  virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
+
+  virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
+
+  NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
+};
+
+/**
  * A display item for subdocuments to capture the resolution from the presShell
  * and ensure that it gets applied to all the right elements. This item creates
  * a container layer.
  */
-class nsDisplayResolution : public nsDisplayOwnLayer {
+class nsDisplayResolution : public nsDisplaySubDocument {
 public:
   nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                     nsDisplayList* aList, uint32_t aFlags);
+                      nsDisplayList* aList, uint32_t aFlags);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayResolution();
 #endif
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
   NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION)
@@ -2816,16 +2857,18 @@ public:
   // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
   // number does not include nsDisplayScrollInfoLayers. If this number is not 1
   // after merging, all the nsDisplayScrollLayers should flatten away.
   intptr_t GetScrollLayerCount();
 
   virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
   virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
 
+  virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; }
+
 #ifdef MOZ_DUMP_PAINTING
   virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
 #endif
 
 protected:
   nsIFrame* mScrollFrame;
   nsIFrame* mScrolledFrame;
 };
@@ -2862,17 +2905,17 @@ public:
 
   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
 };
 
 /**
  * nsDisplayZoom is used for subdocuments that have a different full zoom than
  * their parent documents. This item creates a container layer.
  */
-class nsDisplayZoom : public nsDisplayOwnLayer {
+class nsDisplayZoom : public nsDisplaySubDocument {
 public:
   /**
    * @param aFrame is the root frame of the subdocument.
    * @param aList contains the display items for the subdocument.
    * @param aAPD is the app units per dev pixel ratio of the subdocument.
    * @param aParentAPD is the app units per dev pixel ratio of the parent
    * document.
    * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
@@ -3174,16 +3217,18 @@ public:
    * Return true when we should try to prerender the entire contents of the
    * transformed frame even when it's not completely visible (yet).
    */
   static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
                                                 nsIFrame* aFrame,
                                                 bool aLogAnimations = false);
   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
 
+  virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; }
+
 private:
   static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
                                                          const nsPoint& aOrigin,
                                                          float aAppUnitsPerPixel,
                                                          const nsRect* aBoundsOverride,
                                                          nsIFrame** aOutAncestor);
 
   nsDisplayWrapList mStoredList;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2221,18 +2221,16 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   nsRect displayport;
   if (rootScrollFrame && !aFrame->GetParent()) {
     nsIContent* content = rootScrollFrame->GetContent();
     if (content) {
       usingDisplayPort = nsLayoutUtils::GetDisplayPort(content, &displayport);
     }
   }
 
-  bool ignoreViewportScrolling =
-    aFrame->GetParent() ? false : presShell->IgnoringViewportScrolling();
   nsRegion visibleRegion;
   if (aFlags & PAINT_WIDGET_LAYERS) {
     // This layer tree will be reused, so we'll need to calculate it
     // for the whole "visible" area of the window
     // 
     // |ignoreViewportScrolling| and |usingDisplayPort| are persistent
     // document-rendering state.  We rely on PresShell to flush
     // retained layers as needed when that persistent state changes.
@@ -2270,16 +2268,18 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   if ((aFlags & PAINT_WIDGET_LAYERS) &&
       !willFlushRetainedLayers &&
       !(aFlags & PAINT_DOCUMENT_RELATIVE) &&
       rootPresContext->NeedToComputePluginGeometryUpdates()) {
     builder.SetWillComputePluginGeometry(true);
   }
   nsRect canvasArea(nsPoint(0, 0), aFrame->GetSize());
 
+  bool ignoreViewportScrolling =
+    aFrame->GetParent() ? false : presShell->IgnoringViewportScrolling();
   if (ignoreViewportScrolling && rootScrollFrame) {
     nsIScrollableFrame* rootScrollableFrame =
       presShell->GetRootScrollFrameAsScrollable();
     if (aFlags & PAINT_DOCUMENT_RELATIVE) {
       // Make visibleRegion and aRenderingContext relative to the
       // scrolled frame instead of the root frame.
       nsPoint pos = rootScrollableFrame->GetScrollPosition();
       visibleRegion.MoveBy(-pos);
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -368,30 +368,38 @@ nsSubDocumentFrame::BuildDisplayList(nsD
 
   nsPresContext* presContext = presShell->GetPresContext();
 
   int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
   int32_t subdocAPD = presContext->AppUnitsPerDevPixel();
 
   nsRect dirty;
   bool haveDisplayPort = false;
+  bool ignoreViewportScrolling = false;
+  nsIFrame* savedIgnoreScrollFrame = nullptr;
   if (subdocRootFrame) {
-    nsIDocument* doc = subdocRootFrame->PresContext()->Document();
-    nsIContent* root = doc ? doc->GetRootElement() : nullptr;
     nsRect displayPort;
-    if (root && nsLayoutUtils::GetDisplayPort(root, &displayPort)) {
+    if (nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort)) {
       haveDisplayPort = true;
       dirty = displayPort;
     } else {
       // get the dirty rect relative to the root frame of the subdoc
       dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
       // and convert into the appunits of the subdoc
       dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
     }
 
+    nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
+    ignoreViewportScrolling =
+      rootScrollFrame && presShell->IgnoringViewportScrolling();
+    if (ignoreViewportScrolling) {
+      savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
+      aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
+    }
+
     aBuilder->EnterPresShell(subdocRootFrame, dirty);
   }
 
   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
   if (ShouldClipSubdocument()) {
     clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this);
   }
 
@@ -447,43 +455,60 @@ nsSubDocumentFrame::BuildDisplayList(nsD
         presShell->AddCanvasBackgroundColorItem(
           *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
           bounds, NS_RGBA(0,0,0,0), flags);
       }
     }
   }
 
   // Generate a resolution and/or zoom item if needed. If one or both of those is
-  // created, we don't need to create a separate nsDisplayOwnLayer.
+  // created, we don't need to create a separate nsDisplaySubDocument.
 
+  uint32_t flags = nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS;
+  // If ignoreViewportScrolling is true then the top most layer we create here
+  // is going to become the scrollable layer for the root scroll frame, so we
+  // want to add nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER to whatever layer
+  // becomes the topmost. We do this below.
+  if (constructZoomItem) {
+    uint32_t zoomFlags = flags;
+    if (ignoreViewportScrolling && !constructResolutionItem) {
+      zoomFlags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
+    }
+    nsDisplayZoom* zoomItem =
+      new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
+                                   subdocAPD, parentAPD, zoomFlags);
+    childItems.AppendToTop(zoomItem);
+    needsOwnLayer = false;
+  }
+  // Wrap the zoom item in the resolution item if we have both because we want the
+  // resolution scale applied on top of the app units per dev pixel conversion.
+  if (ignoreViewportScrolling) {
+    flags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
+  }
   if (constructResolutionItem) {
     nsDisplayResolution* resolutionItem =
       new (aBuilder) nsDisplayResolution(aBuilder, subdocRootFrame, &childItems,
-                                         nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
+                                         flags);
     childItems.AppendToTop(resolutionItem);
     needsOwnLayer = false;
   }
-  if (constructZoomItem) {
-    nsDisplayZoom* zoomItem =
-      new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
-                                   subdocAPD, parentAPD,
-                                   nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
-    childItems.AppendToTop(zoomItem);
-    needsOwnLayer = false;
-  }
   if (needsOwnLayer) {
     // We always want top level content documents to be in their own layer.
-    nsDisplayOwnLayer* layerItem = new (aBuilder) nsDisplayOwnLayer(
+    nsDisplaySubDocument* layerItem = new (aBuilder) nsDisplaySubDocument(
       aBuilder, subdocRootFrame ? subdocRootFrame : this,
-      &childItems, nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
+      &childItems, flags);
     childItems.AppendToTop(layerItem);
   }
 
   if (subdocRootFrame) {
     aBuilder->LeavePresShell(subdocRootFrame, dirty);
+
+    if (ignoreViewportScrolling) {
+      aBuilder->SetIgnoreScrollFrame(savedIgnoreScrollFrame);
+    }
   }
 
   if (aBuilder->IsForImageVisibility()) {
     // We don't add the childItems to the return list as we're dealing with them here.
     presShell->RebuildImageVisibility(childItems);
     childItems.DeleteAll();
   } else {
     aLists.Content()->AppendToTop(&childItems);
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -395,18 +395,20 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayou
   SchedulePaint();
 
   bool shouldPosition = true;
   bool isOpen = IsOpen();
   if (!isOpen) {
     // if the popup is not open, only do layout while showing or if the menu
     // is sized to the popup
     shouldPosition = (mPopupState == ePopupShowing);
-    if (!shouldPosition && !aSizedToPopup)
+    if (!shouldPosition && !aSizedToPopup) {
+      RemoveStateBits(NS_FRAME_FIRST_REFLOW);
       return;
+    }
   }
 
   // if the popup has just been opened, make sure the scrolled window is at 0,0
   if (mIsOpenChanged) {
     nsIScrollableFrame *scrollframe = do_QueryFrame(GetChildBox());
     if (scrollframe) {
       nsWeakFrame weakFrame(this);
       scrollframe->ScrollTo(nsPoint(0,0), nsIScrollableFrame::INSTANT);
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -438,24 +438,28 @@ abstract public class BrowserApp extends
 
         String args = intent.getStringExtra("args");
         if (args != null && args.contains(GUEST_BROWSING_ARG)) {
             mProfile = GeckoProfile.createGuestProfile(this);
         } else {
             GeckoProfile.maybeCleanupGuestProfile(this);
         }
 
+        // This has to be prepared prior to calling GeckoApp.onCreate, because
+        // widget code and BrowserToolbar need it, and they're created by the
+        // layout, which GeckoApp takes care of.
+        ((GeckoApplication) getApplication()).prepareLightweightTheme();
         super.onCreate(savedInstanceState);
 
         mViewFlipper = (ViewFlipper) findViewById(R.id.browser_actionbar);
         mActionBar = (ActionModeCompatView) findViewById(R.id.actionbar);
 
         mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browser_toolbar);
         if (Intent.ACTION_VIEW.equals(intent.getAction())) {
-            // Show the target URL immediately in the toolbar
+            // Show the target URL immediately in the toolbar.
             mBrowserToolbar.setTitle(intent.getDataString());
         }
 
         ((GeckoApp.MainLayout) mMainLayout).setTouchEventInterceptor(new HideTabsTouchListener());
         ((GeckoApp.MainLayout) mMainLayout).setMotionEventInterceptor(new MotionEventInterceptor() {
             @Override
             public boolean onInterceptMotionEvent(View view, MotionEvent event) {
                 // If we get a gamepad panning MotionEvent while the focus is not on the layerview,
--- a/mobile/android/base/FilePicker.java
+++ b/mobile/android/base/FilePicker.java
@@ -36,17 +36,17 @@ public class FilePicker implements Gecko
     private final Context mContext;
 
     public interface ResultHandler {
         public void gotFile(String filename);
     }
 
     public static void init(Context context) {
         if (sFilePicker == null) {
-            sFilePicker = new FilePicker(context);
+            sFilePicker = new FilePicker(context.getApplicationContext());
         }
     }
 
     protected FilePicker(Context context) {
         mContext = context;
         GeckoAppShell.getEventDispatcher().registerEventListener("FilePicker:Show", this);
     }
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1208,17 +1208,23 @@ public abstract class GeckoApp
 
                 if (profileName != null || profilePath != null) {
                     mProfile = GeckoProfile.get(this, profileName, profilePath);
                 }
             }
         }
 
         BrowserDB.initialize(getProfile().getName());
-        ((GeckoApplication) getApplication()).initialize();
+
+        // Workaround for <http://code.google.com/p/android/issues/detail?id=20915>.
+        try {
+            Class.forName("android.os.AsyncTask");
+        } catch (ClassNotFoundException e) {}
+
+        MemoryMonitor.getInstance().init(getApplicationContext());
 
         sAppContext = this;
         GeckoAppShell.setContextGetter(this);
         GeckoAppShell.setGeckoInterface(this);
         ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
 
         Tabs.getInstance().attachToContext(this);
         try {
@@ -1273,17 +1279,16 @@ public abstract class GeckoApp
                 prefs.edit().remove(PREFS_ALLOW_STATE_BUNDLE).commit();
                 savedInstanceState = stateBundle;
             }
         } else if (savedInstanceState != null) {
             // Bug 896992 - This intent has already been handled; reset the intent.
             setIntent(new Intent(Intent.ACTION_MAIN));
         }
 
-
         super.onCreate(savedInstanceState);
 
         GeckoScreenOrientation.getInstance().update(getResources().getConfiguration().orientation);
 
         setContentView(getLayout());
 
         // Set up Gecko layout.
         mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
--- a/mobile/android/base/GeckoApplication.java
+++ b/mobile/android/base/GeckoApplication.java
@@ -8,23 +8,23 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.home.HomeConfigInvalidator;
 import org.mozilla.gecko.mozglue.GeckoLoader;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.app.Application;
+import android.content.Context;
 import android.content.res.Configuration;
 import android.util.Log;
 
 public class GeckoApplication extends Application {
     private static final String LOG_TAG = "GeckoApplication";
 
-    private boolean mInited;
     private boolean mInBackground;
     private boolean mPausedGecko;
 
     private LightweightTheme mLightweightTheme;
 
     /**
      * We need to do locale work here, because we need to intercept
      * each hit to onConfigurationChanged.
@@ -48,36 +48,16 @@ public class GeckoApplication extends Ap
         } catch (IllegalStateException ex) {
             // GeckoApp hasn't started, so we have no ContextGetter in LocaleManager.
             Log.w(LOG_TAG, "Couldn't correct locale.", ex);
         }
 
         super.onConfigurationChanged(config);
     }
 
-    protected void initialize() {
-        if (mInited)
-            return;
-
-        // workaround for http://code.google.com/p/android/issues/detail?id=20915
-        try {
-            Class.forName("android.os.AsyncTask");
-        } catch (ClassNotFoundException e) {}
-
-        mLightweightTheme = new LightweightTheme(this);
-
-        GeckoConnectivityReceiver.getInstance().init(getApplicationContext());
-        GeckoBatteryManager.getInstance().init(getApplicationContext());
-        GeckoBatteryManager.getInstance().start();
-        GeckoNetworkManager.getInstance().init(getApplicationContext());
-        MemoryMonitor.getInstance().init(getApplicationContext());
-
-        mInited = true;
-    }
-
     public void onActivityPause(GeckoActivityStatus activity) {
         mInBackground = true;
 
         if ((activity.isFinishing() == false) &&
             (activity.isGeckoActivityOpened() == false)) {
             // Notify Gecko that we are pausing; the cache service will be
             // shutdown, closing the disk cache cleanly. If the android
             // low memory killer subsequently kills us, the disk cache will
@@ -98,18 +78,21 @@ public class GeckoApplication extends Ap
         GeckoNetworkManager.getInstance().stop();
     }
 
     public void onActivityResume(GeckoActivityStatus activity) {
         if (mPausedGecko) {
             GeckoAppShell.sendEventToGecko(GeckoEvent.createAppForegroundingEvent());
             mPausedGecko = false;
         }
-        GeckoConnectivityReceiver.getInstance().start();
-        GeckoNetworkManager.getInstance().start();
+
+        final Context applicationContext = getApplicationContext();
+        GeckoBatteryManager.getInstance().start(applicationContext);
+        GeckoConnectivityReceiver.getInstance().start(applicationContext);
+        GeckoNetworkManager.getInstance().start(applicationContext);
 
         mInBackground = false;
     }
 
     @Override
     public void onCreate() {
         HardwareUtils.init(getApplicationContext());
         Clipboard.init(getApplicationContext());
@@ -121,9 +104,13 @@ public class GeckoApplication extends Ap
 
     public boolean isApplicationInBackground() {
         return mInBackground;
     }
 
     public LightweightTheme getLightweightTheme() {
         return mLightweightTheme;
     }
+
+    public void prepareLightweightTheme() {
+        mLightweightTheme = new LightweightTheme(this);
+    }
 }
--- a/mobile/android/base/GeckoBatteryManager.java
+++ b/mobile/android/base/GeckoBatteryManager.java
@@ -27,49 +27,53 @@ public class GeckoBatteryManager extends
     private static long    sLastLevelChange            = 0;
     private static boolean sNotificationsEnabled       = false;
     private static double  sLevel                      = kDefaultLevel;
     private static boolean sCharging                   = kDefaultCharging;
     private static double  sRemainingTime              = kDefaultRemainingTime;
 
     private static GeckoBatteryManager sInstance = new GeckoBatteryManager();
 
-    private IntentFilter mFilter;
+    private final IntentFilter mFilter;
     private Context mApplicationContext;
     private boolean mIsEnabled;
 
     public static GeckoBatteryManager getInstance() {
         return sInstance;
     }
 
     private GeckoBatteryManager() {
         mFilter = new IntentFilter();
         mFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
     }
 
-    public void init(Context context) {
-        mApplicationContext = context.getApplicationContext();
-    }
+    public synchronized void start(final Context context) {
+        if (mIsEnabled) {
+            Log.w(LOGTAG, "Already started!");
+            return;
+        }
 
-    public synchronized void start() {
-        if (!mIsEnabled) {
-            // registerReceiver will return null if registering fails
-            if (mApplicationContext.registerReceiver(this, mFilter) == null) {
-                Log.e(LOGTAG, "Registering receiver failed");
-            } else {
-                mIsEnabled = true;
-            }
+        mApplicationContext = context.getApplicationContext();
+        // registerReceiver will return null if registering fails.
+        if (mApplicationContext.registerReceiver(this, mFilter) == null) {
+            Log.e(LOGTAG, "Registering receiver failed");
+        } else {
+            mIsEnabled = true;
         }
     }
 
     public synchronized void stop() {
-        if (mIsEnabled) {
-            mApplicationContext.unregisterReceiver(this);
-            mIsEnabled = false;
+        if (!mIsEnabled) {
+            Log.w(LOGTAG, "Already stopped!");
+            return;
         }
+
+        mApplicationContext.unregisterReceiver(this);
+        mApplicationContext = null;
+        mIsEnabled = false;
     }
 
     @Override
     public void onReceive(Context context, Intent intent) {
         if (!intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
             Log.e(LOGTAG, "Got an unexpected intent!");
             return;
         }
--- a/mobile/android/base/GeckoConnectivityReceiver.java
+++ b/mobile/android/base/GeckoConnectivityReceiver.java
@@ -21,57 +21,62 @@ public class GeckoConnectivityReceiver e
     private static final String LINK_DATA_UP = "up";
     private static final String LINK_DATA_DOWN = "down";
     private static final String LINK_DATA_UNKNOWN = "unknown";
 
     private static final String LOGTAG = "GeckoConnectivityReceiver";
 
     private static GeckoConnectivityReceiver sInstance = new GeckoConnectivityReceiver();
 
-    private IntentFilter mFilter;
+    private final IntentFilter mFilter;
     private Context mApplicationContext;
     private boolean mIsEnabled;
 
     public static GeckoConnectivityReceiver getInstance() {
         return sInstance;
     }
 
     private GeckoConnectivityReceiver() {
         mFilter = new IntentFilter();
         mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
     }
 
-    public void init(Context context) {
-        mApplicationContext = context.getApplicationContext();
-    }
+    public synchronized void start(Context context) {
+        if (mIsEnabled) {
+            Log.w(LOGTAG, "Already started!");
+            return;
+        }
 
-    public synchronized void start() {
-        if (!mIsEnabled) {
-            // registerReceiver will return null if registering fails
-            if (mApplicationContext.registerReceiver(this, mFilter) == null) {
-                Log.e(LOGTAG, "Registering receiver failed");
-            } else {
-                mIsEnabled = true;
-            }
+        mApplicationContext = context.getApplicationContext();
+
+        // registerReceiver will return null if registering fails.
+        if (mApplicationContext.registerReceiver(this, mFilter) == null) {
+            Log.e(LOGTAG, "Registering receiver failed");
+        } else {
+            mIsEnabled = true;
         }
     }
 
     public synchronized void stop() {
-        if (mIsEnabled) {
-            mApplicationContext.unregisterReceiver(this);
-            mIsEnabled = false;
+        if (!mIsEnabled) {
+            Log.w(LOGTAG, "Already stopped!");
+            return;
         }
+
+        mApplicationContext.unregisterReceiver(this);
+        mApplicationContext = null;
+        mIsEnabled = false;
     }
 
     @Override
     public void onReceive(Context context, Intent intent) {
         ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo info = cm.getActiveNetworkInfo();
 
-        String status;
+        final String status;
         if (info == null) {
             status = LINK_DATA_UNKNOWN;
         } else if (!info.isConnected()) {
             status = LINK_DATA_DOWN;
         } else {
             status = LINK_DATA_UP;
         }
 
--- a/mobile/android/base/GeckoNetworkManager.java
+++ b/mobile/android/base/GeckoNetworkManager.java
@@ -98,57 +98,60 @@ public class GeckoNetworkManager extends
     }
 
     private enum InfoType {
         MCC,
         MNC
     }
 
     private Context mApplicationContext;
-    private NetworkType  mNetworkType = NetworkType.NETWORK_NONE;
-    private IntentFilter mNetworkFilter = new IntentFilter();
+    private NetworkType mNetworkType = NetworkType.NETWORK_NONE;
+    private final IntentFilter mNetworkFilter = new IntentFilter();
+
     // Whether the manager should be listening to Network Information changes.
     private boolean mShouldBeListening = false;
+
     // Whether the manager should notify Gecko that a change in Network
     // Information happened.
-    private boolean mShouldNotify      = false;
+    private boolean mShouldNotify = false;
 
     public static GeckoNetworkManager getInstance() {
         return sInstance;
     }
 
     @Override
     public void onReceive(Context aContext, Intent aIntent) {
         updateNetworkType();
     }
 
-    public void init(Context context) {
-        mApplicationContext = context.getApplicationContext();
-        mNetworkFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-        mNetworkType = getNetworkType();
-    }
+    public void start(final Context context) {
+        // Note that this initialization clause only runs once.
+        if (mApplicationContext == null) {
+            mApplicationContext = context.getApplicationContext();
+            mNetworkFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+            mNetworkType = getNetworkType();
+        }
 
-    public void start() {
         mShouldBeListening = true;
         updateNetworkType();
 
         if (mShouldNotify) {
             startListening();
         }
     }
 
     private void startListening() {
         mApplicationContext.registerReceiver(sInstance, mNetworkFilter);
     }
 
     public void stop() {
         mShouldBeListening = false;
 
         if (mShouldNotify) {
-        stopListening();
+            stopListening();
         }
     }
 
     private void stopListening() {
         mApplicationContext.unregisterReceiver(sInstance);
     }
 
     private int wifiDhcpGatewayAddress() {
--- a/mobile/android/base/GeckoView.java
+++ b/mobile/android/base/GeckoView.java
@@ -70,17 +70,18 @@ public class GeckoView extends LayerView
             // Set the GeckoInterface if the context is an activity and the GeckoInterface
             // has not already been set
             if (context instanceof Activity && getGeckoInterface() == null) {
                 setGeckoInterface(new BaseGeckoInterface(context));
             }
 
             Clipboard.init(context);
             HardwareUtils.init(context);
-            GeckoNetworkManager.getInstance().init(context);
+
+            // If you want to use GeckoNetworkManager, start it.
 
             GeckoLoader.loadMozGlue();
             BrowserDB.setEnableContentProviders(false);
          }
 
         if (url != null) {
             GeckoThread.setUri(url);
             GeckoThread.setAction(Intent.ACTION_VIEW);
--- a/mobile/android/base/MemoryMonitor.java
+++ b/mobile/android/base/MemoryMonitor.java
@@ -51,30 +51,36 @@ class MemoryMonitor extends BroadcastRec
 
     static MemoryMonitor getInstance() {
         return sInstance;
     }
 
     private final PressureDecrementer mPressureDecrementer;
     private int mMemoryPressure;
     private boolean mStoragePressure;
+    private boolean mInited;
 
     private MemoryMonitor() {
         mPressureDecrementer = new PressureDecrementer();
         mMemoryPressure = MEMORY_PRESSURE_NONE;
         mStoragePressure = false;
     }
 
-    public void init(Context context) {
+    public void init(final Context context) {
+        if (mInited) {
+            return;
+        }
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
         filter.addAction(ACTION_MEMORY_DUMP);
         filter.addAction(ACTION_FORCE_PRESSURE);
         context.getApplicationContext().registerReceiver(this, filter);
+        mInited = true;
     }
 
     public void onLowMemory() {
         Log.d(LOGTAG, "onLowMemory() notification received");
         if (increaseMemoryPressure(MEMORY_PRESSURE_HIGH)) {
             // We need to wait on Gecko here, because if we haven't reduced
             // memory usage enough when we return from this, Android will kill us.
             GeckoAppShell.sendEventToGeckoSync(GeckoEvent.createNoOpEvent());
index f3fe0bdaf5a83b22709ba611985b47d399c9cdde..42566ff2e3322f62ecb36bb3b6b8a4f094abc11e
GIT binary patch
literal 451
zc$@*l0X+VRP)<h;3K|Lk000e1NJLTq001cf001Be1^@s6k8e>v0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzWl2OqR9M69n9EATKoo|*X?n4^bLV^X
zA>8;9g7k&lWbd1}Ev^Mo#7#voUO>f5=6BJPc1TlgW3?&GfuEC^keqK0XU@PlNjT@k
z#2gheNjN}N1Iu&PkjsRuy48?1WDWVJkV$_vggfyp$apaF{oZ(-oc7Abae*3vve@2~
zn%B3GI^LZb>HcK6C`c6eOf8^kY8cQ5@M?MkK10wlkVPP&GJsa#Gqp_}^O0rm8AyOT
z;L%{yDM%enm#Q>kk|yJ)v(yDZ?SkN2rmiV`?&jv3mbnDD1}=di@Bq9QL24dId@%MP
zs~~v?9weKyck&wh(YJzB_79tvkmm~Nz(8*;o0WqEX%9FDZh)66LS7&p{*=kz)?_EB
z$)Z{;s?%tpnq1QE&hPA5yE|J{WbJ0Y-Mz#<*~lsDmCf8j%J)g)0ovX#1Nna^&U&5Q
t>k7F-t06ZJvcAFC9LR#JziJUm?hD*qSqwLXHrfCH002ovPDHLkV1f={&Ab2r
index 34725059357b87a72a188a8eec29e3457a922944..370898c4a4b6460acca43de7c87a5b11bf83d18c
GIT binary patch
literal 426
zc$@*M0agBqP)<h;3K|Lk000e1NJLTq000~S000&U1^@s6)0X`50000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzOi4sRR7l6&mO)O#Fc3xG#3`lQT#`F*
z1}=~l7vT&n*dnoDQ-nkXi&9l>=CkOyvZ6o>sIAnIzJBB=|9d=RJ0=M;6Pqv&7?LnR
zhc+rbPhxn?IFaG(>Nsvq`#(b~P!-6l=7BC)`xp+1rh+p@Kpm)}5m&$>umsjki)X_j
z(Gpo~RB*;cU>uwxt2r<O-hdBa(X^~f!z_L=Aaog+1j^@0Z@i9-X23J>1WbYVre$dW
ztDE``nW@9%REWym5*?L9k}KgPIkj9{#w|%oblR+nsN@(@Cox631s=lmwQ2dxhC+rM
z<eLh}4IHExi+6Hu88;+BC#3wHKnfjQ1NXoq@Y1x*f0JP?C&`uh?-~A3!*Nl=q1p}A
zHSMh7jxOzY=yzS3Czycst}flR533&XUaWhQ+It@!_oO-d+v3b`{N7L0VcjJA0!H`s
U{aZymmjD0&07*qoM6N<$g1vFKga7~l
index a37de873f1d150b2b0dbeeb093eddef527e25399..93546b15fb9bc0cd40c8ccd80ddf1270f24ca226
GIT binary patch
literal 572
zc$@(|0>k}@P)<h;3K|Lk000e1NJLTq001@s001fo1^@s6_)(}m0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz-bqA3RA}Dqn!Qp2F%ZYI$DI~d+VLK?
zK7fVK!4p{e7B=+0fiK{UjfJI^mD;G|2!0_tj9E8#8_31naexSiyEA__At9GvlG!W+
zfQSkJP~{C&jV)y|zV09)HUSf`B?4PT6EFc2FaZ-V0h`_0=h;&>_EHbM<6M0fOUG($
z&k2kt9vpd^$!pByCqj`CgyD?+1oXhX74Dwi*6s{$wF6*y)Xa7ILojd@vB2>*r`4n{
z$KxWv!0}Ouw`!CqVweHxgVbj~;P){IhKJ?x#eC}N0wJ)9YRu#tfl0>&^@Pi=w`B`v
zfSyT@X5C3|q)*efxzhyN2%HG4n?XhVkl1;ct2i(@e}bX1)taMquioIJ_d+tq=!SGf
zdLX@;oht&vaXXfFMU^iPJ@-R3s%xiBt5KWwJT;(p`yn4L^v1(sfAVKk*k?Gid;L`b
zGlgAxy(Ha}dIGlOU?)^KsB#pi4IXaPiwmM!GA82Lz>yRLkHiTcCL-REt}6wPiuYJ3
z+=moRa6iQ*ixLOI{X4^TSmoh<ju$li(gkfZj{)Ch)h_4-r&MLT4qi%yd?amJr7NXW
zE1LxS)@jv_>z{+w*aS?#1WdrD2a{hk1x&!^2v+b1mU>gsSNm`1d+`kRa$@2D0000<
KMNUMnLSTX$K>q0f
--- a/mobile/android/base/resources/layout-large-v11/browser_toolbar.xml
+++ b/mobile/android/base/resources/layout-large-v11/browser_toolbar.xml
@@ -102,15 +102,16 @@
                android:layout_width="fill_parent"
                android:layout_height="2dp"
                android:layout_alignParentBottom="true"
                android:background="@color/url_bar_shadow"
                android:contentDescription="@null"/>
 
     <org.mozilla.gecko.toolbar.ToolbarProgressView android:id="@+id/progress"
                                                    android:layout_width="fill_parent"
-                                                   android:layout_height="2dp"
+                                                   android:layout_height="14dp"
+                                                   android:layout_marginBottom="-7dp"
                                                    android:layout_alignBottom="@id/shadow"
                                                    android:src="@drawable/progress"
                                                    android:background="@null"
                                                    android:visibility="gone" />
 
 </merge>
--- a/mobile/android/base/resources/layout/browser_toolbar.xml
+++ b/mobile/android/base/resources/layout/browser_toolbar.xml
@@ -102,15 +102,16 @@
                android:layout_width="fill_parent"
                android:layout_height="2dp"
                android:layout_alignParentBottom="true"
                android:background="@color/url_bar_shadow"
                android:contentDescription="@null"/>
 
     <org.mozilla.gecko.toolbar.ToolbarProgressView android:id="@+id/progress"
                                                    android:layout_width="fill_parent"
-                                                   android:layout_height="2dp"
+                                                   android:layout_height="14dp"
+                                                   android:layout_marginBottom="-7dp"
                                                    android:layout_alignBottom="@id/shadow"
                                                    android:src="@drawable/progress"
                                                    android:background="@null"
                                                    android:visibility="gone" />
 
 </merge>
--- a/mobile/android/base/resources/layout/gecko_app.xml
+++ b/mobile/android/base/resources/layout/gecko_app.xml
@@ -12,17 +12,18 @@
               android:layout="@layout/tabs_panel_view"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"/>
 
    <view class="org.mozilla.gecko.GeckoApp$MainLayout"
          android:id="@+id/main_layout"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
-         android:background="@android:color/transparent">
+         android:background="@android:color/transparent"
+         android:clipChildren="false">
 
         <RelativeLayout android:id="@+id/gecko_layout"
                         android:layout_width="fill_parent"
                         android:layout_height="fill_parent"
                         android:layout_above="@+id/find_in_page">
 
             <include layout="@layout/shared_ui_components"/>
 
@@ -85,25 +86,31 @@
              view. To make sure the EditText is not the first focusable view in
              the root view, BrowserToolbar should be specified as low in the
              view hierarchy as possible. -->
 
         <org.mozilla.gecko.widget.GeckoViewFlipper android:id="@id/browser_actionbar"
                 android:layout_width="fill_parent"
                 android:layout_height="@dimen/browser_toolbar_height"
                 android:clickable="true"
+                android:clipChildren="false"
                 android:focusable="true">
 
+            <!-- clipChildren="false" allows the child ToolbarProgressView to be drawn
+                 outside of BrowserToolbar's boundaries. Likewise, we need this property
+                 on BrowserToolbar's parent ViewFlipper, then on its parent MainLayout
+                 to allow the progress to overlap the content LayerView. -->
             <org.mozilla.gecko.toolbar.BrowserToolbar
                 android:id="@+id/browser_toolbar"
                 style="@style/BrowserToolbar"
                 android:layout_width="fill_parent"
                 android:layout_height="@dimen/browser_toolbar_height"
                 android:clickable="true"
                 android:focusable="true"
+                android:clipChildren="false"
                 android:background="@drawable/url_bar_bg"/>
 
             <org.mozilla.gecko.ActionModeCompatView android:id="@+id/actionbar"
                                                     android:layout_height="fill_parent"
                                                     android:layout_width="fill_parent"
                                                     style="@style/GeckoActionBar"/>
 
         </org.mozilla.gecko.widget.GeckoViewFlipper>
--- a/mobile/android/base/util/Clipboard.java
+++ b/mobile/android/base/util/Clipboard.java
@@ -16,22 +16,22 @@ import java.util.concurrent.SynchronousQ
 public final class Clipboard {
     private static Context mContext;
     private final static String LOGTAG = "GeckoClipboard";
     private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
 
     private Clipboard() {
     }
 
-    public static void init(Context c) {
+    public static void init(final Context c) {
         if (mContext != null) {
             Log.w(LOGTAG, "Clipboard.init() called twice!");
             return;
         }
-        mContext = c;
+        mContext = c.getApplicationContext();
     }
 
     @WrapElementForJNI(stubName = "GetClipboardTextWrapper")
     public static String getText() {
         // If we're on the UI thread or the background thread, we have a looper on the thread
         // and can just call this directly. For any other threads, post the call to the
         // background thread.
 
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -1,40 +1,47 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/Sandbox.h"
+
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/ptrace.h>
 #include <sys/prctl.h>
 #include <sys/syscall.h>
 #include <signal.h>
 #include <string.h>
+#include <linux/futex.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <pthread.h>
 
+#include "mozilla/Atomics.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/unused.h"
+#include "mozilla/dom/Exceptions.h"
+#include "nsString.h"
+#include "nsThreadUtils.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 #if defined(ANDROID)
 #include "android_ucontext.h"
 #include <android/log.h>
 #endif
 #include "seccomp_filter.h"
 
-#include "mozilla/dom/Exceptions.h"
-#include "nsString.h"
-#include "nsThreadUtils.h"
-
 #include "linux_seccomp.h"
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 #include "prenv.h"
 
 namespace mozilla {
@@ -42,16 +49,18 @@ namespace mozilla {
 #define LOG_ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "Sandbox", ## args)
 #elif defined(PR_LOGGING)
 static PRLogModuleInfo* gSeccompSandboxLog;
 #define LOG_ERROR(args...) PR_LOG(gSeccompSandboxLog, PR_LOG_ERROR, (args))
 #else
 #define LOG_ERROR(args...)
 #endif
 
+// Note: this ifdef includes most of the file.
+#ifdef MOZ_CONTENT_SANDBOX
 struct sock_filter seccomp_filter[] = {
   VALIDATE_ARCHITECTURE,
   EXAMINE_SYSCALL,
   SECCOMP_WHITELIST,
 #ifdef MOZ_CONTENT_SANDBOX_REPORTER
   TRAP_PROCESS,
 #else
   KILL_PROCESS,
@@ -216,55 +225,221 @@ InstallSyscallFilter(void)
     return 1;
   }
 
   if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &seccomp_prog, 0, 0)) {
     return 1;
   }
   return 0;
 }
+#endif
+
+#if defined(ANDROID) || defined(MOZ_CONTENT_SANDBOX)
+// Use signals for permissions that need to be set per-thread.
+static base::ChildPrivileges sSetPrivilegesTo;
+// The communication channel from the signal handler back to the main thread.
+static mozilla::Atomic<int> sSetSandboxDone;
+// about:memory has the first 3 RT signals.  (We should allocate
+// signals centrally instead of hard-coding them like this.)
+static const int sSetSandboxSignum = SIGRTMIN + 3;
+#endif
+
+static bool
+SetThreadSandbox(base::ChildPrivileges aPrivs, bool aIsMainThread)
+{
+  bool didAnything = false;
+  bool shouldSetPrivs = aIsMainThread;
+#if defined(ANDROID)
+  shouldSetPrivs = true;
+#endif
+
+  if (shouldSetPrivs && (aIsMainThread || geteuid() == 0)) {
+    SetCurrentProcessPrivileges(aPrivs);
+    if (aPrivs != base::PRIVILEGES_INHERIT) {
+      didAnything = true;
+    }
+  }
+#if defined(MOZ_CONTENT_SANDBOX)
+  if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
+      prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
+    if (InstallSyscallFilter() == 0) {
+      didAnything = true;
+    }
+    /*
+     * Bug 880797: when all B2G devices are required to support
+     * seccomp-bpf, this should exit/crash if InstallSyscallFilter
+     * returns nonzero (ifdef MOZ_WIDGET_GONK).
+     */
+  }
+#endif
+  return didAnything;
+}
+
+#if defined(ANDROID) || defined(MOZ_CONTENT_SANDBOX)
+static void
+SetThreadSandboxHandler(int signum)
+{
+  // The non-zero number sent back to the main thread indicates
+  // whether action was taken.
+  if (SetThreadSandbox(sSetPrivilegesTo, /* main: */ false)) {
+    sSetSandboxDone = 2;
+  } else {
+    sSetSandboxDone = 1;
+  }
+  // Wake up the main thread.  See the FUTEX_WAIT call, below, for an
+  // explanation.
+  syscall(__NR_futex, reinterpret_cast<int*>(&sSetSandboxDone),
+          FUTEX_WAKE, 1);
+}
+
+static void
+BroadcastSetThreadSandbox(base::ChildPrivileges aPrivs)
+{
+  pid_t pid, tid;
+  DIR *taskdp;
+  struct dirent *de;
+
+  static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
+                "mozilla::Atomic<int> isn't represented by an int");
+  MOZ_ASSERT(NS_IsMainThread());
+  pid = getpid();
+  taskdp = opendir("/proc/self/task");
+  if (taskdp == nullptr) {
+    LOG_ERROR("opendir /proc/self/task: %s\n", strerror(errno));
+    MOZ_CRASH();
+  }
+  if (signal(sSetSandboxSignum, SetThreadSandboxHandler) != SIG_DFL) {
+    LOG_ERROR("signal %d in use!\n", sSetSandboxSignum);
+    MOZ_CRASH();
+  }
+
+  // In case this races with a not-yet-deprivileged thread cloning
+  // itself, repeat iterating over all threads until we find none
+  // that are still privileged.
+  sSetPrivilegesTo = aPrivs;
+  bool sandboxProgress;
+  do {
+    sandboxProgress = false;
+    // For each thread...
+    while ((de = readdir(taskdp))) {
+      char *endptr;
+      tid = strtol(de->d_name, &endptr, 10);
+      if (*endptr != '\0' || tid <= 0) {
+        // Not a task ID.
+        continue;
+      }
+      if (tid == pid) {
+        // Drop the main thread's privileges last, below, so
+        // we can continue to signal other threads.
+        continue;
+      }
+      // Reset the futex cell and signal.
+      sSetSandboxDone = 0;
+      if (syscall(__NR_tgkill, pid, tid, sSetSandboxSignum) != 0) {
+        if (errno == ESRCH) {
+          LOG_ERROR("Thread %d unexpectedly exited.", tid);
+          // Rescan threads, in case it forked before exiting.
+          sandboxProgress = true;
+          continue;
+        }
+        LOG_ERROR("tgkill(%d,%d): %s\n", pid, tid, strerror(errno));
+        MOZ_CRASH();
+      }
+      // It's unlikely, but if the thread somehow manages to exit
+      // after receiving the signal but before entering the signal
+      // handler, we need to avoid blocking forever.
+      //
+      // Using futex directly lets the signal handler send the wakeup
+      // from an async signal handler (pthread mutex/condvar calls
+      // aren't allowed), and to use a relative timeout that isn't
+      // affected by changes to the system clock (not possible with
+      // POSIX semaphores).
+      //
+      // If a thread doesn't respond within a reasonable amount of
+      // time, but still exists, we crash -- the alternative is either
+      // blocking forever or silently losing security, and it
+      // shouldn't actually happen.
+      static const int crashDelay = 10; // seconds
+      struct timespec timeLimit;
+      clock_gettime(CLOCK_MONOTONIC, &timeLimit);
+      timeLimit.tv_sec += crashDelay;
+      while (true) {
+        static const struct timespec futexTimeout = { 0, 10*1000*1000 }; // 10ms
+        // Atomically: if sSetSandboxDone == 0, then sleep.
+        if (syscall(__NR_futex, reinterpret_cast<int*>(&sSetSandboxDone),
+                  FUTEX_WAIT, 0, &futexTimeout) != 0) {
+          if (errno != EWOULDBLOCK && errno != ETIMEDOUT && errno != EINTR) {
+            LOG_ERROR("FUTEX_WAIT: %s\n", strerror(errno));
+            MOZ_CRASH();
+          }
+        }
+        // Did the handler finish?
+        if (sSetSandboxDone > 0) {
+          if (sSetSandboxDone == 2) {
+            sandboxProgress = true;
+          }
+          break;
+        }
+        // Has the thread ceased to exist?
+        if (syscall(__NR_tgkill, pid, tid, 0) != 0) {
+          if (errno == ESRCH) {
+            LOG_ERROR("Thread %d unexpectedly exited.", tid);
+          }
+          // Rescan threads, in case it forked before exiting.
+          // Also, if it somehow failed in a way that wasn't ESRCH,
+          // and still exists, that will be handled on the next pass.
+          sandboxProgress = true;
+          break;
+        }
+        struct timespec now;
+        clock_gettime(CLOCK_MONOTONIC, &now);
+        if (now.tv_sec > timeLimit.tv_nsec ||
+            (now.tv_sec == timeLimit.tv_nsec &&
+             now.tv_nsec > timeLimit.tv_nsec)) {
+          LOG_ERROR("Thread %d unresponsive for %d seconds.  Killing process.",
+                    tid, crashDelay);
+          MOZ_CRASH();
+        }
+      }
+    }
+    rewinddir(taskdp);
+  } while (sandboxProgress);
+  unused << signal(sSetSandboxSignum, SIG_DFL);
+  unused << closedir(taskdp);
+  // And now, deprivilege the main thread:
+  SetThreadSandbox(aPrivs, /* main: */ true);
+}
+#else
+static void
+BroadcastSetThreadSandbox(base::ChildPrivileges aPrivs)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  SetThreadSandbox(aPrivs, /* main: */ true);
+}
+#endif
 
 /**
- * Starts the seccomp sandbox for this process.
- * Generally called just after SetCurrentProcessPrivileges.
+ * Starts the seccomp sandbox for this process and sets user/group-based privileges.
  * Should be called only once, and before any potentially harmful content is loaded.
  *
  * Should normally make the process exit on failure.
 */
 void
-SetCurrentProcessSandbox(void)
+SetCurrentProcessSandbox(base::ChildPrivileges aPrivs)
 {
-  if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX"))
-    return;
-
 #if !defined(ANDROID) && defined(PR_LOGGING)
   if (!gSeccompSandboxLog) {
     gSeccompSandboxLog = PR_NewLogModule("SeccompSandbox");
   }
   PR_ASSERT(gSeccompSandboxLog);
 #endif
 
-#ifdef MOZ_CONTENT_SANDBOX_REPORTER
+#if defined(MOZ_CONTENT_SANDBOX) && defined(MOZ_CONTENT_SANDBOX_REPORTER)
   if (InstallSyscallReporter()) {
     LOG_ERROR("install_syscall_reporter() failed\n");
-    /* This is disabled so that we do not exit if seccomp-bpf is not available
-     * This will be re-enabled when all B2G devices are required to support seccomp-bpf
-     * See bug 880797 for reversal
-     */
-
-    /* _exit(127); */
   }
-
 #endif
 
-  if (InstallSyscallFilter()) {
-    LOG_ERROR("install_syscall_filter() failed\n");
-    /* This is disabled so that we do not exit if seccomp-bpf is not available
-     * This will be re-enabled when all B2G devices are required to support seccomp-bpf
-     * See bug 880797 for reversal
-     */
+  BroadcastSetThreadSandbox(aPrivs);
+}
 
-    /* _exit(127); */
-  }
-
-}
 } // namespace mozilla
 
--- a/security/sandbox/linux/Sandbox.h
+++ b/security/sandbox/linux/Sandbox.h
@@ -2,16 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_Sandbox_h
 #define mozilla_Sandbox_h
 
+#include "base/process_util.h"
+
 namespace mozilla {
 
-void SetCurrentProcessSandbox(void);
+void SetCurrentProcessSandbox(base::ChildPrivileges aPrivs);
 
 } // namespace mozilla
 
 #endif // mozilla_Sandbox_h
 
--- a/security/sandbox/linux/seccomp_filter.h
+++ b/security/sandbox/linux/seccomp_filter.h
@@ -8,23 +8,27 @@
 
 /* This is the actual seccomp whitelist.
  * This is used for B2G content-processes.
  */
 
 /* Architecture-specific frequently used syscalls */
 #if defined(__arm__)
 #define SECCOMP_WHITELIST_ARCH_HIGH \
+  ALLOW_SYSCALL(recvmsg), \
+  ALLOW_SYSCALL(sendmsg), \
   ALLOW_SYSCALL(mmap2),
 #elif defined(__i386__)
 #define SECCOMP_WHITELIST_ARCH_HIGH \
   ALLOW_SYSCALL(ipc), \
   ALLOW_SYSCALL(mmap2),
 #elif defined(__x86_64__)
-#define SECCOMP_WHITELIST_ARCH_HIGH
+#define SECCOMP_WHITELIST_ARCH_HIGH \
+  ALLOW_SYSCALL(recvmsg), \
+  ALLOW_SYSCALL(sendmsg),
 #else
 #define SECCOMP_WHITELIST_ARCH_HIGH
 #endif
 
 /* Architecture-specific infrequently used syscalls */
 #if defined(__arm__)
 #define SECCOMP_WHITELIST_ARCH_LOW \
   ALLOW_SYSCALL(_newselect), \
@@ -77,29 +81,27 @@
 
 /* Architecture-specific syscalls that should eventually be removed */
 #if defined(__arm__)
 #define SECCOMP_WHITELIST_ARCH_TOREMOVE \
   ALLOW_SYSCALL(fstat64), \
   ALLOW_SYSCALL(stat64), \
   ALLOW_SYSCALL(lstat64), \
   ALLOW_SYSCALL(socketpair), \
-  ALLOW_SYSCALL(sendmsg), \
   ALLOW_SYSCALL(sigprocmask), \
   DENY_SYSCALL(socket, EACCES),
 #elif defined(__i386__)
 #define SECCOMP_WHITELIST_ARCH_TOREMOVE \
   ALLOW_SYSCALL(fstat64), \
   ALLOW_SYSCALL(stat64), \
   ALLOW_SYSCALL(lstat64), \
   ALLOW_SYSCALL(sigprocmask),
 #else
 #define SECCOMP_WHITELIST_ARCH_TOREMOVE \
   ALLOW_SYSCALL(socketpair), \
-  ALLOW_SYSCALL(sendmsg), \
   DENY_SYSCALL(socket, EACCES),
 #endif
 
 /* Architecture-specific syscalls for desktop linux */
 #if defined(__arm__)
 #define SECCOMP_WHITELIST_ARCH_DESKTOP_LINUX
 #elif defined(__i386__)
 #define SECCOMP_WHITELIST_ARCH_DESKTOP_LINUX
@@ -114,22 +116,24 @@
 
 #define SECCOMP_WHITELIST_B2G_HIGH \
   ALLOW_SYSCALL(clock_gettime), \
   ALLOW_SYSCALL(epoll_wait), \
   ALLOW_SYSCALL(gettimeofday),
 
 #define SECCOMP_WHITELIST_B2G_MED \
   ALLOW_SYSCALL(getpid), \
-  ALLOW_SYSCALL(rt_sigreturn),
+  ALLOW_SYSCALL(rt_sigreturn), \
+  ALLOW_SYSCALL(poll),
 
 #define SECCOMP_WHITELIST_B2G_LOW \
   ALLOW_SYSCALL(sendto), \
   ALLOW_SYSCALL(recvfrom), \
   ALLOW_SYSCALL(getdents64), \
+  ALLOW_SYSCALL(epoll_ctl), \
   ALLOW_SYSCALL(sched_yield), \
   ALLOW_SYSCALL(sched_getscheduler), \
   ALLOW_SYSCALL(sched_setscheduler),
 
 #else
 #define SECCOMP_WHITELIST_B2G_HIGH
 #define SECCOMP_WHITELIST_B2G_MED
 #define SECCOMP_WHITELIST_B2G_LOW
@@ -158,17 +162,16 @@
   ALLOW_SYSCALL(getdents), \
   ALLOW_SYSCALL(lstat), \
   ALLOW_SYSCALL(mmap), \
   ALLOW_SYSCALL(openat), \
   ALLOW_SYSCALL(fcntl), \
   ALLOW_SYSCALL(fstat), \
   ALLOW_SYSCALL(readlink), \
   ALLOW_SYSCALL(getsockname), \
-  ALLOW_SYSCALL(recvmsg), \
   /* duplicate rt_sigaction in SECCOMP_WHITELIST_PROFILING */ \
   ALLOW_SYSCALL(rt_sigaction), \
   ALLOW_SYSCALL(getuid), \
   ALLOW_SYSCALL(geteuid), \
   ALLOW_SYSCALL(mkdir), \
   ALLOW_SYSCALL(getcwd), \
   ALLOW_SYSCALL(readahead), \
   ALLOW_SYSCALL(pread64), \
--- a/services/common/hawkclient.js
+++ b/services/common/hawkclient.js
@@ -66,17 +66,17 @@ this.HawkClient.prototype = {
    */
   _constructError: function(restResponse, errorString) {
     let errorObj = {
       error: errorString,
       message: restResponse.statusText,
       code: restResponse.status,
       errno: restResponse.status
     };
-    let retryAfter = restResponse.headers["retry-after"];
+    let retryAfter = restResponse.headers && restResponse.headers["retry-after"];
     retryAfter = retryAfter ? parseInt(retryAfter) : retryAfter;
     if (retryAfter) {
       errorObj.retryAfter = retryAfter;
     }
     return errorObj;
   },
 
   /*
--- a/testing/marionette/client/marionette/__init__.py
+++ b/testing/marionette/client/marionette/__init__.py
@@ -6,8 +6,9 @@ from gestures import *
 from by import By
 from marionette import Marionette, HTMLElement, Actions, MultiActions
 from marionette_test import MarionetteTestCase, MarionetteJSTestCase, CommonTestCase, expectedFailure, skip, SkipTest
 from emulator import Emulator
 from errors import *
 from runner import *
 from wait import Wait
 from date_time_value import DateTimeValue
+import decorators
new file mode 100644
--- /dev/null
+++ b/testing/marionette/client/marionette/decorators.py
@@ -0,0 +1,65 @@
+# 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/.
+
+from errors import MarionetteException
+from functools import wraps
+import sys
+import traceback
+
+def _find_marionette_in_args(*args, **kwargs):
+    try:
+        m = [a for a in args + tuple(kwargs.values()) if hasattr(a, 'session')][0]
+    except IndexError:
+        print("Can only apply decorator to function using a marionette object")
+        raise
+    return m
+
+def do_crash_check(func, always=False):
+    """Decorator which checks for crashes after the function has run.
+
+    :param always: If False, only checks for crashes if an exception
+                   was raised. If True, always checks for crashes.
+    """
+    @wraps(func)
+    def _(*args, **kwargs):
+        def check():
+            m = _find_marionette_in_args(*args, **kwargs)
+            try:
+                m.check_for_crash()
+            except:
+                # don't want to lose the original exception
+                traceback.print_exc()
+
+        try:
+            return func(*args, **kwargs)
+        except MarionetteException:
+            exc, val, tb = sys.exc_info()
+            if not always:
+                check()
+            raise exc, val, tb
+        finally:
+            if always:
+                check()
+    return _
+
+def uses_marionette(func):
+    """Decorator which creates a marionette session and deletes it
+    afterwards if one doesn't already exist.
+    """
+    @wraps(func)
+    def _(*args, **kwargs):
+        m = _find_marionette_in_args(*args, **kwargs)
+        delete_session = False
+        if not m.session:
+            delete_session = True
+            m.start_session()
+
+        m.set_context(m.CONTEXT_CHROME)
+        ret = func(*args, **kwargs)
+
+        if delete_session:
+            m.delete_session()
+
+        return ret
+    return _
--- a/testing/marionette/client/marionette/emulator.py
+++ b/testing/marionette/client/marionette/emulator.py
@@ -1,31 +1,39 @@
 # 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/.
 
 from b2ginstance import B2GInstance
 import datetime
-from errors import *
 from mozdevice import devicemanagerADB, DMError
 from mozprocess import ProcessHandlerMixin
 import os
 import re
 import platform
 import shutil
 import socket
 import subprocess
 from telnetlib import Telnet
 import tempfile
 import time
 import traceback
 
 from emulator_battery import EmulatorBattery
 from emulator_geo import EmulatorGeo
 from emulator_screen import EmulatorScreen
+from decorators import uses_marionette
+
+from errors import (
+    InstallGeckoError,
+    InvalidResponseException,
+    MarionetteException,
+    ScriptTimeoutException,
+    TimeoutException
+)
 
 
 class LogOutputProc(ProcessHandlerMixin):
     """
     Process handler for processes which save all output to a logfile.
     If no logfile is specified, output will still be consumed to prevent
     the output pipe's from overflowing.
     """
@@ -46,16 +54,19 @@ class LogOutputProc(ProcessHandlerMixin)
 
 class Emulator(object):
 
     deviceRe = re.compile(r"^emulator-(\d+)(\s*)(.*)$")
     _default_res = '320x480'
     prefs = {'app.update.enabled': False,
              'app.update.staging.enabled': False,
              'app.update.service.enabled': False}
+    env = {'MOZ_CRASHREPORTER': '1',
+           'MOZ_CRASHREPORTER_NO_REPORT': '1',
+           'MOZ_CRASHREPORTER_SHUTDOWN': '1'}
 
     def __init__(self, homedir=None, noWindow=False, logcat_dir=None,
                  arch="x86", emulatorBinary=None, res=None, sdcard=None,
                  symbols_path=None, userdata=None):
         self.port = None
         self.dm = None
         self._emulator_launched = False
         self.proc = None
@@ -251,19 +262,18 @@ class Emulator(object):
         result = self._run_adb(['start-server'])
         # We keep track of whether we've started adb or not, so we know
         # if we need to kill it.
         if 'daemon started successfully' in result:
             self._adb_started = True
         else:
             self._adb_started = False
 
+    @uses_marionette
     def wait_for_system_message(self, marionette):
-        marionette.start_session()
-        marionette.set_context(marionette.CONTEXT_CHROME)
         marionette.set_script_timeout(45000)
         # Telephony API's won't be available immediately upon emulator
         # boot; we have to wait for the syste-message-listener-ready
         # message before we'll be able to use them successfully.  See
         # bug 792647.
         print 'waiting for system-message-listener-ready...'
         try:
             marionette.execute_async_script("""
@@ -277,19 +287,17 @@ waitFor(
             # We silently ignore the timeout if it occurs, since
             # isSystemMessageListenerReady() isn't available on
             # older emulators.  45s *should* be enough of a delay
             # to allow telephony API's to work.
             pass
         except InvalidResponseException:
             self.check_for_minidumps()
             raise
-        print 'done'
-        marionette.set_context(marionette.CONTEXT_CONTENT)
-        marionette.delete_session()
+        print '...done'
 
     def connect(self):
         self.adb = B2GInstance.check_adb(self.homedir, emulator=True)
         self.start_adb()
 
         online, offline = self._get_adb_devices()
         now = datetime.datetime.now()
         while online == set([]):
@@ -350,67 +358,69 @@ waitFor(
         self.screen.initialize()
 
         if self.logcat_dir:
             self.save_logcat()
 
         # setup DNS fix for networking
         self._run_adb(['shell', 'setprop', 'net.dns1', '10.0.2.3'])
 
+    @uses_marionette
     def wait_for_homescreen(self, marionette):
         print 'waiting for homescreen...'
 
-        created_session = False
-        if not marionette.session:
-            marionette.start_session()
-            created_session = True
-
         marionette.set_context(marionette.CONTEXT_CONTENT)
         marionette.execute_async_script("""
 log('waiting for mozbrowserloadend');
 window.addEventListener('mozbrowserloadend', function loaded(aEvent) {
   log('received mozbrowserloadend for ' + aEvent.target.src);
   if (aEvent.target.src.indexOf('ftu') != -1 || aEvent.target.src.indexOf('homescreen') != -1) {
     window.removeEventListener('mozbrowserloadend', loaded);
     marionetteScriptFinished();
   }
 });""", script_timeout=120000)
         print '...done'
-        if created_session:
-            marionette.delete_session()
 
     def setup(self, marionette, gecko_path=None, busybox=None):
+        self.set_environment(marionette)
         if busybox:
             self.install_busybox(busybox)
 
         if gecko_path:
             self.install_gecko(gecko_path, marionette)
 
         self.wait_for_system_message(marionette)
         self.set_prefs(marionette)
 
+    @uses_marionette
+    def set_environment(self, marionette):
+        for k, v in self.env.iteritems():
+            marionette.execute_script("""
+            let env = Cc["@mozilla.org/process/environment;1"].
+                      getService(Ci.nsIEnvironment);
+            env.set("%s", "%s");
+            """ % (k, v))
+
+    @uses_marionette
     def set_prefs(self, marionette):
-        marionette.start_session()
-        marionette.set_context(marionette.CONTEXT_CHROME)
         for pref in self.prefs:
             marionette.execute_script("""
             Components.utils.import("resource://gre/modules/Services.jsm");
             let argtype = typeof(arguments[1]);
             switch(argtype) {
                 case 'boolean':
                     Services.prefs.setBoolPref(arguments[0], arguments[1]);
                     break;
                 case 'number':
                     Services.prefs.setIntPref(arguments[0], arguments[1]);
                     break;
                 default:
                     Services.prefs.setCharPref(arguments[0], arguments[1]);
             }
             """, [pref, self.prefs[pref]])
-        marionette.delete_session()
 
     def restart_b2g(self):
         print 'restarting B2G'
         self.dm.shellCheckOutput(['stop', 'b2g'])
         time.sleep(10)
         self.dm.shellCheckOutput(['start', 'b2g'])
 
         if not self.wait_for_port():
--- a/testing/marionette/client/marionette/marionette.py
+++ b/testing/marionette/client/marionette/marionette.py
@@ -7,16 +7,17 @@ import datetime
 import os
 import socket
 import sys
 import time
 import traceback
 
 from application_cache import ApplicationCache
 from client import MarionetteClient
+from decorators import do_crash_check
 from emulator import Emulator
 from emulator_screen import EmulatorScreen
 from errors import *
 from keys import Keys
 
 import geckoinstance
 
 class HTMLElement(object):
@@ -415,16 +416,17 @@ class MultiActions(object):
         return self
 
     def perform(self):
         '''
         Perform all the actions added to this object.
         '''
         return self.marionette._send_message('multiAction', 'ok', value=self.multi_actions, max_length=self.max_length)
 
+
 class Marionette(object):
     """
     Represents a Marionette connection to a browser or device.
     """
 
     CONTEXT_CHROME = 'chrome' # non-browser content: windows, dialogs, etc.
     CONTEXT_CONTENT = 'content' # browser content: iframes, divs, etc.
     TIMEOUT_SEARCH = 'implicit'
@@ -579,29 +581,30 @@ class Marionette(object):
                 if '"from"' in data:
                     time.sleep(5)
                     return True
             except socket.error:
                 pass
             time.sleep(1)
         return False
 
+    @do_crash_check
     def _send_message(self, command, response_key="ok", **kwargs):
         if not self.session and command != "newSession":
             raise MarionetteException("Please start a session")
 
         message = {"name": command}
         if self.session:
             message["sessionId"] = self.session
         if kwargs:
             message["parameters"] = kwargs
 
         try:
             response = self.client.send(message)
-        except socket.timeout as e:
+        except socket.timeout:
             self.session = None
             self.window = None
             self.client.close()
             raise TimeoutException(
                 "Connection timed out", status=ErrorCodes.TIMEOUT)
 
         # Process any emulator commands that are sent from a script
         # while it's executing.
@@ -709,24 +712,18 @@ class Marionette(object):
 
         :params desired_capabilities: An optional dict of desired
             capabilities.  This is currently ignored.
 
         :returns: A dict of the capabilities offered.
 
         """
 
-        try:
-            # We are ignoring desired_capabilities, at least for now.
-            self.session = self._send_message('newSession', 'value')
-        except:
-            exc, val, tb = sys.exc_info()
-            self.check_for_crash()
-            raise exc, val, tb
-
+        # We are ignoring desired_capabilities, at least for now.
+        self.session = self._send_message('newSession', 'value')
         self.b2g = 'b2g' in self.session
         return self.session
 
     @property
     def test_name(self):
         return self._test_name
 
     @test_name.setter
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -1,17 +1,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['LIBXUL_SDK']:
     error('toolkit.mozbuild is not compatible with --enable-libxul-sdk=')
 
-if CONFIG['MOZ_CONTENT_SANDBOX']:
+if CONFIG['MOZ_CONTENT_SANDBOX'] or CONFIG['OS_ARCH'] == 'Linux':
     add_tier_dir('sandbox', 'security/sandbox')
 
 # Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator
 # builds fail.
 add_tier_dir('platform', 'security/certverifier')
 
 # Depends on certverifier
 add_tier_dir('platform', 'security/apps')
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -64,17 +64,17 @@ namespace mozilla {
 static StaticRefPtr<HwcComposer2D> sInstance;
 
 HwcComposer2D::HwcComposer2D()
     : mMaxLayerCount(0)
     , mList(nullptr)
     , mHwc(nullptr)
     , mColorFill(false)
     , mRBSwapSupport(false)
-#if ANDROID_VERSION >= 18
+#if ANDROID_VERSION >= 17
     , mPrevRetireFence(Fence::NO_FENCE)
     , mPrevDisplayFence(Fence::NO_FENCE)
 #endif
     , mPrepared(false)
 {
 }
 
 HwcComposer2D::~HwcComposer2D() {
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -18,17 +18,17 @@
 #define mozilla_HwcComposer2D
 
 #include "Composer2D.h"
 #include "Layers.h"
 #include <vector>
 #include <list>
 
 #include <hardware/hwcomposer.h>
-#if ANDROID_VERSION >= 18
+#if ANDROID_VERSION >= 17
 #include <ui/Fence.h>
 #endif
 
 namespace mozilla {
 
 namespace layers {
 class ContainerLayer;
 class Layer;
@@ -81,17 +81,17 @@ private:
     hwc_surface_t           mSur;
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
     bool                    mRBSwapSupport;
     //Holds all the dynamically allocated RectVectors needed
     //to render the current frame
     std::list<RectVector>   mVisibleRegions;
-#if ANDROID_VERSION >= 18
+#if ANDROID_VERSION >= 17
     android::sp<android::Fence> mPrevRetireFence;
     android::sp<android::Fence> mPrevDisplayFence;
 #endif
     nsTArray<layers::LayerComposite*> mHwcLayerMap;
     bool                    mPrepared;
 };
 
 } // namespace mozilla