Merge m-c to inbound
authorWes Kocher <wkocher@mozilla.com>
Mon, 07 Jul 2014 16:34:44 -0700
changeset 213551 cf50c2bcdbd246174dccbcf1eaf0176376bd3d87
parent 213550 19176ab7d700ce6ea6bc9a7ad60ce15cfa837925 (current diff)
parent 213493 7f9db2379b3f932a3d2b2d83d922fd76d9152d8e (diff)
child 213552 f64db1df4ddc606e18970ff36b7acab8a4a6af3d
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound
browser/devtools/debugger/test/code_math_bogus_map.min.js
--- a/b2g/components/SimulatorScreen.js
+++ b/b2g/components/SimulatorScreen.js
@@ -21,17 +21,17 @@ function fireOrientationEvent(window) {
   let e = new window.Event('mozorientationchange');
   window.screen.dispatchEvent(e);
 }
 
 function hookScreen(window) {
   let nodePrincipal = window.document.nodePrincipal;
   let origin = nodePrincipal.origin;
   if (nodePrincipal.appStatus == nodePrincipal.APP_STATUS_NOT_INSTALLED) {
-    Cu.reportError('deny mozLockOrientation:' + origin + 'is not installed');
+    // Only inject screen mock for apps
     return;
   }
 
   let screen = window.wrappedJSObject.screen;
 
   screen.mozLockOrientation = function (orientation) {
     debug('mozLockOrientation:', orientation, 'from', origin);
 
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,22 +14,22 @@
   <!--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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="bf9aaf39dd5a6491925a022db167c460f8207d34"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,19 +12,19 @@
   <!--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="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
@@ -126,11 +126,11 @@
   <!-- Emulator specific things -->
   <project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="0e31f35a2a77301e91baa8a237aa9e9fa4076084"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="efd87a5797ca40fa2df256630c07e0dfb2f762dc"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="832f4acaf481a19031e479a40b03d9ce5370ddee"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d0aa65b140a45016975ed0ecf35f280dd336e1d3"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="dd72bacb432efc5135a1f747d00aab91f898bddb"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
 </manifest>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,21 +10,21 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,22 +14,22 @@
   <!--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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="bf9aaf39dd5a6491925a022db167c460f8207d34"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,19 +12,19 @@
   <!--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="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
@@ -138,13 +138,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="280d29203b2aa30d713c5a6cc63d626e5a7df822"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="5dc48bd46f9589653f8bf297be5d73676f2e2867"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="8a0d0b0d9889ef99c4c6317c810db4c09295f15a"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
   <project name="platform/system/core" path="system/core" revision="bbf7212289fc8311e43f9d11e10788e310d36a08"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d0aa65b140a45016975ed0ecf35f280dd336e1d3"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="dd72bacb432efc5135a1f747d00aab91f898bddb"/>
   <project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
 </manifest>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "278dd1b102a39cf2c48f11fe3038eaf8f0779d7d", 
+    "revision": "02f96bd32a7d77bc1684f3ca745f0e810871159b", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,21 +12,21 @@
   <!--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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,21 +10,21 @@
   <!--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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <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"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
   <project name="platform/development" path="development" revision="b1025ec93beeb480caaf3049d171283c3846461d"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,19 +12,19 @@
   <!--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="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
@@ -122,17 +122,17 @@
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
   <!-- Nexus 4 specific things -->
   <project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d0aa65b140a45016975ed0ecf35f280dd336e1d3"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="dd72bacb432efc5135a1f747d00aab91f898bddb"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="b0a528d839cfd9d170d092fe3743b5252b4243a6"/>
   <project name="platform/hardware/qcom/bt" path="hardware/qcom/bt" revision="380945eaa249a2dbdde0daa4c8adb8ca325edba6"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="6f3b0272cefaffeaed2a7d2bb8f633059f163ddc"/>
   <project name="platform/hardware/qcom/keymaster" path="hardware/qcom/keymaster" revision="16da8262c997a5a0d797885788a64a0771b26910"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="689b476ba3eb46c34b81343295fe144a0e81a18e"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,21 +12,21 @@
   <!--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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="99f56d9db3cd37c684b01de6fed786421f47e2b7"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1dc9e53393ae4680a174dffa44a958ec564ebbe8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="230f11aff069d90d20fc2dc63b48e9ae3d4bdcd1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="96cdde4b5b5d8d3785b36c3c68cd746aff3005cc"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1285,16 +1285,17 @@ pref("devtools.debugger.chrome-debugging
 pref("devtools.debugger.chrome-debugging-port", 6080);
 pref("devtools.debugger.remote-host", "localhost");
 pref("devtools.debugger.remote-timeout", 20000);
 pref("devtools.debugger.pause-on-exceptions", false);
 pref("devtools.debugger.ignore-caught-exceptions", true);
 pref("devtools.debugger.source-maps-enabled", true);
 pref("devtools.debugger.pretty-print-enabled", true);
 pref("devtools.debugger.auto-pretty-print", false);
+pref("devtools.debugger.auto-black-box", true);
 pref("devtools.debugger.tracer", false);
 
 // The default Debugger UI settings
 pref("devtools.debugger.ui.panes-sources-width", 200);
 pref("devtools.debugger.ui.panes-instruments-width", 300);
 pref("devtools.debugger.ui.panes-visible-on-startup", false);
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-only-enum-visible", false);
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -118,18 +118,25 @@ PlacesViewBase.prototype = {
   get controller() this._controller,
 
   get selType() "single",
   selectItems: function() { },
   selectAll: function() { },
 
   get selectedNode() {
     if (this._contextMenuShown) {
-      let popup = document.popupNode;
-      return popup._placesNode || popup.parentNode._placesNode || null;
+      let anchor = this._contextMenuShown.triggerNode;
+      if (!anchor)
+        return null;
+
+      if (anchor._placesNode)
+        return this._rootElt == anchor ? null : anchor._placesNode;
+
+      anchor = anchor.parentNode;
+      return this._rootElt == anchor ? null : (anchor._placesNode || null);
     }
     return null;
   },
 
   get hasSelection() this.selectedNode != null,
 
   get selectedNodes() {
     let selectedNode = this.selectedNode;
@@ -185,23 +192,23 @@ PlacesViewBase.prototype = {
     if (PlacesControllerDragHelper.disallowInsertion(container))
       return null;
 
     return new InsertionPoint(PlacesUtils.getConcreteItemId(container),
                               index, orientation, isTag);
   },
 
   buildContextMenu: function PVB_buildContextMenu(aPopup) {
-    this._contextMenuShown = true;
+    this._contextMenuShown = aPopup;
     window.updateCommands("places");
     return this.controller.buildContextMenu(aPopup);
   },
 
   destroyContextMenu: function PVB_destroyContextMenu(aPopup) {
-    this._contextMenuShown = false;
+    this._contextMenuShown = null;
   },
 
   _cleanPopup: function PVB_cleanPopup(aPopup, aDelay) {
     // Remove Places nodes from the popup.
     let child = aPopup._startMarker;
     while (child.nextSibling != aPopup._endMarker) {
       let sibling = child.nextSibling;
       if (sibling._placesNode && !aDelay) {
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -362,30 +362,16 @@ PlacesController.prototype = {
    * Determines whether or not nodes can be inserted relative to the selection.
    */
   _canInsert: function PC__canInsert(isPaste) {
     var ip = this._view.insertionPoint;
     return ip != null && (isPaste || ip.isTag != true);
   },
 
   /**
-   * Determines whether or not the root node for the view is selected
-   */
-  rootNodeIsSelected: function PC_rootNodeIsSelected() {
-    var nodes = this._view.selectedNodes;
-    var root = this._view.result.root;
-    for (var i = 0; i < nodes.length; ++i) {
-      if (nodes[i] == root)
-        return true;
-    }
-
-    return false;
-  },
-
-  /**
    * Looks at the data on the clipboard to see if it is paste-able.
    * Paste-able data is:
    *   - in a format that the view can receive
    * @return true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor,
    *                  - clipboard data is of type TEXT_UNICODE and
    *                    is a valid URI.
    */
   _isClipboardDataPasteable: function PC__isClipboardDataPasteable() {
@@ -428,39 +414,34 @@ PlacesController.prototype = {
       return false;
     }
   },
 
   /**
    * Gathers information about the selected nodes according to the following
    * rules:
    *    "link"              node is a URI
-   *    "bookmark"          node is a bookamrk
+   *    "bookmark"          node is a bookmark
    *    "livemarkChild"     node is a child of a livemark
    *    "tagChild"          node is a child of a tag
    *    "folder"            node is a folder
    *    "query"             node is a query
    *    "separator"         node is a separator line
    *    "host"              node is a host
    *
    * @return an array of objects corresponding the selected nodes. Each
    *         object has each of the properties above set if its corresponding
    *         node matches the rule. In addition, the annotations names for each
    *         node are set on its corresponding object as properties.
    * Notes:
    *   1) This can be slow, so don't call it anywhere performance critical!
-   *   2) A single-object array corresponding the root node is returned if
-   *      there's no selection.
    */
   _buildSelectionMetadata: function PC__buildSelectionMetadata() {
     var metadata = [];
-    var root = this._view.result.root;
     var nodes = this._view.selectedNodes;
-    if (nodes.length == 0)
-      nodes.push(root); // See the second note above
 
     for (var i = 0; i < nodes.length; i++) {
       var nodeData = {};
       var node = nodes[i];
       var nodeType = node.type;
       var uri = null;
 
       // We don't use the nodeIs* methods here to avoid going through the type
@@ -531,20 +512,33 @@ PlacesController.prototype = {
    *          the context menu item
    * @param   aMetaData
    *          meta data about the selection
    * @return true if the conditions (see buildContextMenu) are satisfied
    *         and the item can be displayed, false otherwise.
    */
   _shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) {
     var selectiontype = aMenuItem.getAttribute("selectiontype");
-    if (selectiontype == "multiple" && aMetaData.length == 1)
+    if (!selectiontype) {
+      selectiontype = "single|multiple";
+    }
+    var selectionTypes = selectiontype.split("|");
+    if (selectionTypes.indexOf("any") != -1) {
+      return true;
+    }
+    var count = aMetaData.length;
+    if (count > 1 && selectionTypes.indexOf("multiple") == -1)
       return false;
-    if (selectiontype == "single" && aMetaData.length != 1)
+    if (count == 1 && selectionTypes.indexOf("single") == -1)
       return false;
+    // NB: if there is no selection, we show the item if and only if
+    // the selectiontype includes 'none' - the metadata list will be
+    // empty so none of the other criteria will apply anyway.
+    if (count == 0)
+      return selectionTypes.indexOf("none") != -1;
 
     var forceHideAttr = aMenuItem.getAttribute("forcehideselection");
     if (forceHideAttr) {
       var forceHideRules = forceHideAttr.split("|");
       for (let i = 0; i < aMetaData.length; ++i) {
         for (let j = 0; j < forceHideRules.length; ++j) {
           if (forceHideRules[j] in aMetaData[i])
             return false;
@@ -581,19 +575,21 @@ PlacesController.prototype = {
 
   /**
    * Detects information (meta-data rules) about the current selection in the
    * view (see _buildSelectionMetadata) and sets the visibility state for each
    * of the menu-items in the given popup with the following rules applied:
    *  1) The "selectiontype" attribute may be set on a menu-item to "single"
    *     if the menu-item should be visible only if there is a single node
    *     selected, or to "multiple" if the menu-item should be visible only if
-   *     multiple nodes are selected. If the attribute is not set or if it is
-   *     set to an invalid value, the menu-item may be visible for both types of
-   *     selection.
+   *     multiple nodes are selected, or to "none" if the menuitems should be
+   *     visible for if there are no selected nodes, or to a |-separated
+   *     combination of these.
+   *     If the attribute is not set or set to an invalid value, the menu-item
+   *     may be visible irrespective of the selection.
    *  2) The "selection" attribute may be set on a menu-item to the various
    *     meta-data rules for which it may be visible. The rules should be
    *     separated with the | character.
    *  3) A menu-item may be visible only if at least one of the rules set in
    *     its selection attribute apply to each of the selected nodes in the
    *     view.
    *  4) The "forcehideselection" attribute may be set on a menu-item to rules
    *     for which it should be hidden. This attribute takes priority over the
@@ -614,28 +610,29 @@ PlacesController.prototype = {
    */
   buildContextMenu: function PC_buildContextMenu(aPopup) {
     var metadata = this._buildSelectionMetadata();
     var ip = this._view.insertionPoint;
     var noIp = !ip || ip.isTag;
 
     var separator = null;
     var visibleItemsBeforeSep = false;
-    var anyVisible = false;
+    var usableItemCount = 0;
     for (var i = 0; i < aPopup.childNodes.length; ++i) {
       var item = aPopup.childNodes[i];
       if (item.localName != "menuseparator") {
         // We allow pasting into tag containers, so special case that.
         var hideIfNoIP = item.getAttribute("hideifnoinsertionpoint") == "true" &&
                          noIp && !(ip && ip.isTag && item.id == "placesContext_paste");
-        item.hidden = hideIfNoIP || !this._shouldShowMenuItem(item, metadata);
+        var shouldHideItem = hideIfNoIP || !this._shouldShowMenuItem(item, metadata);
+        item.hidden = item.disabled = shouldHideItem;
 
         if (!item.hidden) {
           visibleItemsBeforeSep = true;
-          anyVisible = true;
+          usableItemCount++;
 
           // Show the separator above the menu-item if any
           if (separator) {
             separator.hidden = false;
             separator = null;
           }
         }
       }
@@ -649,31 +646,31 @@ PlacesController.prototype = {
           separator = item;
 
         // New separator, count again:
         visibleItemsBeforeSep = false;
       }
     }
 
     // Set Open Folder/Links In Tabs items enabled state if they're visible
-    if (anyVisible) {
+    if (usableItemCount > 0) {
       var openContainerInTabsItem = document.getElementById("placesContext_openContainer:tabs");
-      if (!openContainerInTabsItem.hidden && this._view.selectedNode &&
-          PlacesUtils.nodeIsContainer(this._view.selectedNode)) {
-        openContainerInTabsItem.disabled =
-          !PlacesUtils.hasChildURIs(this._view.selectedNode);
-      }
-      else {
-        // see selectiontype rule in the overlay
-        var openLinksInTabsItem = document.getElementById("placesContext_openLinks:tabs");
-        openLinksInTabsItem.disabled = openLinksInTabsItem.hidden;
+      if (!openContainerInTabsItem.hidden) {
+        var containerToUse = this._view.selectedNode || this._view.result.root;
+        if (PlacesUtils.nodeIsContainer(containerToUse)) {
+          if (!PlacesUtils.hasChildURIs(containerToUse, true)) {
+            openContainerInTabsItem.disabled = true;
+            // Ensure that we don't display the menu if nothing is enabled:
+            usableItemCount--;
+          }
+        }
       }
     }
 
-    return anyVisible;
+    return usableItemCount > 0;
   },
 
   /**
    * Select all links in the current view.
    */
   selectAll: function PC_selectAll() {
     this._view.selectAll();
   },
@@ -729,20 +726,25 @@ PlacesController.prototype = {
     }
   },
 
   /**
    * Opens the links in the selected folder, or the selected links in new tabs.
    */
   openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
     var node = this._view.selectedNode;
+    var nodes = this._view.selectedNodes;
+    // In the case of no selection, open the root node:
+    if (!node && !nodes.length) {
+      node = this._view.result.root;
+    }
     if (node && PlacesUtils.nodeIsContainer(node))
-      PlacesUIUtils.openContainerNodeInTabs(this._view.selectedNode, aEvent, this._view);
+      PlacesUIUtils.openContainerNodeInTabs(node, aEvent, this._view);
     else
-      PlacesUIUtils.openURINodesInTabs(this._view.selectedNodes, aEvent, this._view);
+      PlacesUIUtils.openURINodesInTabs(nodes, aEvent, this._view);
   },
 
   /**
    * Shows the Add Bookmark UI for the current insertion point.
    *
    * @param aType
    *        the type of the new item (bookmark/livemark/folder)
    */
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -108,17 +108,17 @@
               selectiontype="single"
               selection="link"/>
     <menuitem id="placesContext_openContainer:tabs"
               oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
                          view.controller.openSelectionInTabs(event);"
               onclick="checkForMiddleClick(this, event);"
               label="&cmd.open_all_in_tabs.label;"
               accesskey="&cmd.open_all_in_tabs.accesskey;"
-              selectiontype="single"
+              selectiontype="single|none"
               selection="folder|host|query"/>
     <menuitem id="placesContext_openLinks:tabs"
               oncommand="var view = PlacesUIUtils.getViewForNode(document.popupNode);
                          view.controller.openSelectionInTabs(event);"
               onclick="checkForMiddleClick(this, event);"
               label="&cmd.open_all_in_tabs.label;"
               accesskey="&cmd.open_all_in_tabs.accesskey;"
               selectiontype="multiple"
@@ -129,30 +129,30 @@
               accesskey="&cmd.open_window.accesskey;"
               selectiontype="single"
               selection="link"/>
     <menuseparator id="placesContext_openSeparator"/>
     <menuitem id="placesContext_new:bookmark"
               command="placesCmd_new:bookmark"
               label="&cmd.new_bookmark.label;"
               accesskey="&cmd.new_bookmark.accesskey;"
-              selection="any"
+              selectiontype="any"
               hideifnoinsertionpoint="true"/>
     <menuitem id="placesContext_new:folder"
               command="placesCmd_new:folder"
               label="&cmd.new_folder.label;"
               accesskey="&cmd.context_new_folder.accesskey;"
-              selection="any"
+              selectiontype="any"
               hideifnoinsertionpoint="true"/>
     <menuitem id="placesContext_new:separator"
               command="placesCmd_new:separator"
               label="&cmd.new_separator.label;"
               accesskey="&cmd.new_separator.accesskey;"
               closemenu="single"
-              selection="any"
+              selectiontype="any"
               hideifnoinsertionpoint="true"/>
     <menuseparator id="placesContext_newSeparator"/>
     <menuitem id="placesContext_createBookmark"
               command="placesCmd_createBookmark"
               label="&cmd.bookmarkLink.label;"
               accesskey="&cmd.bookmarkLink.accesskey;"
               selection="link"
               forcehideselection="bookmark|tagChild"/>
@@ -162,24 +162,23 @@
               accesskey="&cutCmd.accesskey;" 
               closemenu="single"
               selection="bookmark|folder|separator|query"
               forcehideselection="tagChild|livemarkChild"/>
     <menuitem id="placesContext_copy"
               command="placesCmd_copy"
               label="&copyCmd.label;"
               closemenu="single"
-              accesskey="&copyCmd.accesskey;" 
-              selection="any"/>
+              accesskey="&copyCmd.accesskey;"/>
     <menuitem id="placesContext_paste"
               command="placesCmd_paste"
               label="&pasteCmd.label;"
               closemenu="single"
               accesskey="&pasteCmd.accesskey;"
-              selection="any"
+              selectiontype="any"
               hideifnoinsertionpoint="true"/>
     <menuseparator id="placesContext_editSeparator"/>
     <menuitem id="placesContext_delete"
               command="placesCmd_delete"
               label="&deleteCmd.label;"
               accesskey="&deleteCmd.accesskey;"
               closemenu="single"
               selection="bookmark|tagChild|folder|query|dynamiccontainer|separator|host"/>
--- a/browser/components/places/content/sidebarUtils.js
+++ b/browser/components/places/content/sidebarUtils.js
@@ -38,17 +38,17 @@ var SidebarUtils = {
 #else
     var modifKey = aEvent.ctrlKey || aEvent.shiftKey;
 #endif
 
     var isContainer = tbo.view.isContainer(row.value);
     var openInTabs = isContainer &&
                      (aEvent.button == 1 ||
                       (aEvent.button == 0 && modifKey)) &&
-                     PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value));
+                     PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(row.value), true);
 
     if (aEvent.button == 0 && isContainer && !openInTabs) {
       tbo.view.toggleOpenState(row.value);
       return;
     }
     else if (!mouseInGutter && openInTabs &&
             aEvent.originalTarget.localName == "treechildren") {
       tbo.view.selection.select(row.value);
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -288,17 +288,18 @@ let DebuggerController = {
    * Sets up a debugging session.
    *
    * @return object
    *         A promise resolved once the client attaches to the active thread.
    */
   _startDebuggingTab: function() {
     let deferred = promise.defer();
     let threadOptions = {
-      useSourceMaps: Prefs.sourceMapsEnabled
+      useSourceMaps: Prefs.sourceMapsEnabled,
+      autoBlackBox: Prefs.autoBlackBox
     };
 
     this._target.activeTab.attachThread(threadOptions, (aResponse, aThreadClient) => {
       if (!aThreadClient) {
         deferred.reject(new Error("Couldn't attach to thread: " + aResponse.error));
         return;
       }
       this.activeThread = aThreadClient;
@@ -340,17 +341,18 @@ let DebuggerController = {
    * @param object aChromeDebugger
    *        The remote protocol grip of the chrome debugger.
    * @return object
    *         A promise resolved once the client attaches to the active thread.
    */
   _startChromeDebugging: function(aChromeDebugger) {
     let deferred = promise.defer();
     let threadOptions = {
-      useSourceMaps: Prefs.sourceMapsEnabled
+      useSourceMaps: Prefs.sourceMapsEnabled,
+      autoBlackBox: Prefs.autoBlackBox
     };
 
     this.client.attachThread(aChromeDebugger, (aResponse, aThreadClient) => {
       if (!aThreadClient) {
         deferred.reject(new Error("Couldn't attach to thread: " + aResponse.error));
         return;
       }
       this.activeThread = aThreadClient;
@@ -392,18 +394,21 @@ let DebuggerController = {
 
     return deferred.promise;
   },
 
   /**
    * Detach and reattach to the thread actor with useSourceMaps true, blow
    * away old sources and get them again.
    */
-  reconfigureThread: function(aUseSourceMaps) {
-    this.activeThread.reconfigure({ useSourceMaps: aUseSourceMaps }, aResponse => {
+  reconfigureThread: function({ useSourceMaps, autoBlackBox }) {
+    this.activeThread.reconfigure({
+      useSourceMaps: useSourceMaps,
+      autoBlackBox: autoBlackBox
+    }, aResponse => {
       if (aResponse.error) {
         let msg = "Couldn't reconfigure thread: " + aResponse.message;
         Cu.reportError(msg);
         dumpn(msg);
         return;
       }
 
       // Reset the view and fetch all the sources again.
@@ -2236,17 +2241,18 @@ let Prefs = new ViewHelpers.Prefs("devto
   variablesOnlyEnumVisible: ["Bool", "debugger.ui.variables-only-enum-visible"],
   variablesSearchboxVisible: ["Bool", "debugger.ui.variables-searchbox-visible"],
   pauseOnExceptions: ["Bool", "debugger.pause-on-exceptions"],
   ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"],
   sourceMapsEnabled: ["Bool", "debugger.source-maps-enabled"],
   prettyPrintEnabled: ["Bool", "debugger.pretty-print-enabled"],
   autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"],
   tracerEnabled: ["Bool", "debugger.tracer"],
-  editorTabSize: ["Int", "editor.tabsize"]
+  editorTabSize: ["Int", "editor.tabsize"],
+  autoBlackBox: ["Bool", "debugger.auto-black-box"]
 });
 
 /**
  * Convenient way of emitting events from the panel window.
  */
 EventEmitter.decorate(this);
 
 /**
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -192,16 +192,17 @@ function OptionsView() {
 
   this._toggleAutoPrettyPrint = this._toggleAutoPrettyPrint.bind(this);
   this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this);
   this._toggleIgnoreCaughtExceptions = this._toggleIgnoreCaughtExceptions.bind(this);
   this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
   this._toggleShowVariablesOnlyEnum = this._toggleShowVariablesOnlyEnum.bind(this);
   this._toggleShowVariablesFilterBox = this._toggleShowVariablesFilterBox.bind(this);
   this._toggleShowOriginalSource = this._toggleShowOriginalSource.bind(this);
+  this._toggleAutoBlackBox = this._toggleAutoBlackBox.bind(this);
 }
 
 OptionsView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function() {
     dumpn("Initializing the OptionsView");
@@ -209,26 +210,29 @@ OptionsView.prototype = {
     this._button = document.getElementById("debugger-options");
     this._autoPrettyPrint = document.getElementById("auto-pretty-print");
     this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
     this._ignoreCaughtExceptionsItem = document.getElementById("ignore-caught-exceptions");
     this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
     this._showVariablesOnlyEnumItem = document.getElementById("show-vars-only-enum");
     this._showVariablesFilterBoxItem = document.getElementById("show-vars-filter-box");
     this._showOriginalSourceItem = document.getElementById("show-original-source");
+    this._autoBlackBoxItem = document.getElementById("auto-black-box");
 
     this._autoPrettyPrint.setAttribute("checked", Prefs.autoPrettyPrint);
     this._pauseOnExceptionsItem.setAttribute("checked", Prefs.pauseOnExceptions);
     this._ignoreCaughtExceptionsItem.setAttribute("checked", Prefs.ignoreCaughtExceptions);
     this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
     this._showVariablesOnlyEnumItem.setAttribute("checked", Prefs.variablesOnlyEnumVisible);
     this._showVariablesFilterBoxItem.setAttribute("checked", Prefs.variablesSearchboxVisible);
     this._showOriginalSourceItem.setAttribute("checked", Prefs.sourceMapsEnabled);
+    this._autoBlackBoxItem.setAttribute("checked", Prefs.autoBlackBox);
   },
 
+
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function() {
     dumpn("Destroying the OptionsView");
     // Nothing to do here yet.
   },
 
@@ -317,27 +321,51 @@ OptionsView.prototype = {
   _toggleShowOriginalSource: function() {
     let pref = Prefs.sourceMapsEnabled =
       this._showOriginalSourceItem.getAttribute("checked") == "true";
 
     // Don't block the UI while reconfiguring the server.
     window.once(EVENTS.OPTIONS_POPUP_HIDDEN, () => {
       // The popup panel needs more time to hide after triggering onpopuphidden.
       window.setTimeout(() => {
-        DebuggerController.reconfigureThread(pref);
+        DebuggerController.reconfigureThread({
+          useSourceMaps: pref,
+          autoBlackBox: Prefs.autoBlackBox
+        });
+      }, POPUP_HIDDEN_DELAY);
+    });
+  },
+
+  /**
+   * Listener handling the 'automatically black box minified sources' menuitem
+   * command.
+   */
+  _toggleAutoBlackBox: function() {
+    let pref = Prefs.autoBlackBox =
+      this._autoBlackBoxItem.getAttribute("checked") == "true";
+
+    // Don't block the UI while reconfiguring the server.
+    window.once(EVENTS.OPTIONS_POPUP_HIDDEN, () => {
+      // The popup panel needs more time to hide after triggering onpopuphidden.
+      window.setTimeout(() => {
+        DebuggerController.reconfigureThread({
+          useSourceMaps: Prefs.sourceMapsEnabled,
+          autoBlackBox: pref
+        });
       }, POPUP_HIDDEN_DELAY);
     });
   },
 
   _button: null,
   _pauseOnExceptionsItem: null,
   _showPanesOnStartupItem: null,
   _showVariablesOnlyEnumItem: null,
   _showVariablesFilterBoxItem: null,
-  _showOriginalSourceItem: null
+  _showOriginalSourceItem: null,
+  _autoBlackBoxItem: null
 };
 
 /**
  * Functions handling the stackframes UI.
  */
 function StackFramesView() {
   dumpn("StackFramesView was instantiated");
 
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -83,16 +83,18 @@
     <command id="toggleShowPanesOnStartup"
              oncommand="DebuggerView.Options._toggleShowPanesOnStartup()"/>
     <command id="toggleShowOnlyEnum"
              oncommand="DebuggerView.Options._toggleShowVariablesOnlyEnum()"/>
     <command id="toggleShowVariablesFilterBox"
              oncommand="DebuggerView.Options._toggleShowVariablesFilterBox()"/>
     <command id="toggleShowOriginalSource"
              oncommand="DebuggerView.Options._toggleShowOriginalSource()"/>
+    <command id="toggleAutoBlackBox"
+             oncommand="DebuggerView.Options._toggleAutoBlackBox()"/>
     <command id="toggleTracing"
              oncommand="DebuggerView.Tracer._onToggleTracing()"/>
     <command id="startTracing"
              oncommand="DebuggerView.Tracer._onStartTracing()"/>
     <command id="clearTraces"
              oncommand="DebuggerView.Tracer._onClear()"/>
   </commandset>
 
@@ -204,16 +206,21 @@
                 label="&debuggerUI.showVarsFilter;"
                 accesskey="&debuggerUI.showVarsFilter.accesskey;"
                 command="toggleShowVariablesFilterBox"/>
       <menuitem id="show-original-source"
                 type="checkbox"
                 label="&debuggerUI.showOriginalSource;"
                 accesskey="&debuggerUI.showOriginalSource.accesskey;"
                 command="toggleShowOriginalSource"/>
+      <menuitem id="auto-black-box"
+                type="checkbox"
+                label="&debuggerUI.autoBlackBox;"
+                accesskey="&debuggerUI.autoBlackBox.accesskey;"
+                command="toggleAutoBlackBox"/>
     </menupopup>
   </popupset>
 
   <keyset id="debuggerKeys">
     <key id="nextSourceKey"
          keycode="VK_DOWN"
          modifiers="accel alt"
          command="nextSourceCommand"/>
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -17,17 +17,17 @@ support-files =
   code_breakpoints-break-on-last-line-of-script-on-reload.js
   code_function-search-01.js
   code_function-search-02.js
   code_function-search-03.js
   code_location-changes.js
   code_math.js
   code_math.map
   code_math.min.js
-  code_math_bogus_map.min.js
+  code_math_bogus_map.js
   code_script-switching-01.js
   code_script-switching-02.js
   code_test-editor-mode
   code_tracing-01.js
   code_ugly.js
   code_ugly-2.js
   code_ugly-3.js
   code_ugly-4.js
--- a/browser/devtools/debugger/test/browser_dbg_source-maps-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_source-maps-04.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Test that bogus source maps don't break debugging.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_minified_bogus_map.html";
-const JS_URL = EXAMPLE_URL + "code_math_bogus_map.min.js";
+const JS_URL = EXAMPLE_URL + "code_math_bogus_map.js";
 
 // This test causes an error to be logged in the console, which appears in TBPL
 // logs, so we are disabling that here.
 let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
 DevToolsUtils.reportingDisabled = true;
 
 let gPanel, gDebugger, gFrames, gSources, gPrefs, gOptions;
 
@@ -41,17 +41,17 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function checkInitialSource() {
-  isnot(gSources.selectedValue.indexOf(".min.js"), -1,
+  isnot(gSources.selectedValue.indexOf("code_math_bogus_map.js"), -1,
     "The debugger should show the minified js file.");
 }
 
 function enablePauseOnExceptions() {
   let deferred = promise.defer();
 
   gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
     is(gPrefs.pauseOnExceptions, true,
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/code_math_bogus_map.js
@@ -0,0 +1,4 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+function stopMe(){throw Error("boom");}try{stopMe();var a=1;a=a*2;}catch(e){};
+//# sourceMappingURL=bogus.map
deleted file mode 100644
--- a/browser/devtools/debugger/test/code_math_bogus_map.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-function stopMe(){throw Error("boom");}try{stopMe();var a=1;a=a*2;}catch(e){};
-//# sourceMappingURL=bogus.map
--- a/browser/devtools/debugger/test/doc_minified_bogus_map.html
+++ b/browser/devtools/debugger/test/doc_minified_bogus_map.html
@@ -4,11 +4,11 @@
 
 <html>
   <head>
     <meta charset="utf-8"/>
     <title>Debugger test page</title>
   </head>
 
   <body>
-    <script src="code_math_bogus_map.min.js"></script>
+    <script src="code_math_bogus_map.js"></script>
   </body>
 </html>
--- a/browser/devtools/shared/widgets/Graphs.jsm
+++ b/browser/devtools/shared/widgets/Graphs.jsm
@@ -27,26 +27,26 @@ const GRAPH_SELECTION_BOUNDARY_HOVER_THR
 const GRAPH_MAX_SELECTION_LEFT_PADDING = 1;
 const GRAPH_MAX_SELECTION_RIGHT_PADDING = 1;
 
 const GRAPH_REGION_LINE_WIDTH = 1; // px
 const GRAPH_REGION_LINE_COLOR = "rgba(237,38,85,0.8)";
 
 const GRAPH_STRIPE_PATTERN_WIDTH = 16; // px
 const GRAPH_STRIPE_PATTERN_HEIGHT = 16; // px
-const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 4; // px
-const GRAPH_STRIPE_PATTERN_LINE_SPACING = 8; // px
+const GRAPH_STRIPE_PATTERN_LINE_WIDTH = 2; // px
+const GRAPH_STRIPE_PATTERN_LINE_SPACING = 4; // px
 
 // Line graph constants.
 
 const LINE_GRAPH_DAMPEN_VALUES = 0.85;
 const LINE_GRAPH_MIN_SQUARED_DISTANCE_BETWEEN_POINTS = 400; // 20 px
 const LINE_GRAPH_TOOLTIP_SAFE_BOUNDS = 10; // px
 
-const LINE_GRAPH_STROKE_WIDTH = 2; // px
+const LINE_GRAPH_STROKE_WIDTH = 1; // px
 const LINE_GRAPH_STROKE_COLOR = "rgba(255,255,255,0.9)";
 const LINE_GRAPH_HELPER_LINES_DASH = [5]; // px
 const LINE_GRAPH_HELPER_LINES_WIDTH = 1; // px
 const LINE_GRAPH_MAXIMUM_LINE_COLOR = "rgba(255,255,255,0.4)";
 const LINE_GRAPH_AVERAGE_LINE_COLOR = "rgba(255,255,255,0.7)";
 const LINE_GRAPH_MINIMUM_LINE_COLOR = "rgba(255,255,255,0.9)";
 const LINE_GRAPH_BACKGROUND_GRADIENT_START = "rgba(255,255,255,0.25)";
 const LINE_GRAPH_BACKGROUND_GRADIENT_END = "rgba(255,255,255,0.0)";
@@ -57,17 +57,17 @@ const LINE_GRAPH_SELECTION_BACKGROUND_CO
 const LINE_GRAPH_SELECTION_STRIPES_COLOR = "rgba(255,255,255,0.1)";
 const LINE_GRAPH_REGION_BACKGROUND_COLOR = "transparent";
 const LINE_GRAPH_REGION_STRIPES_COLOR = "rgba(237,38,85,0.2)";
 
 // Bar graph constants.
 
 const BAR_GRAPH_DAMPEN_VALUES = 0.75;
 const BAR_GRAPH_BARS_MARGIN_TOP = 1; // px
-const BAR_GRAPH_BARS_MARGIN_END = 2; // px
+const BAR_GRAPH_BARS_MARGIN_END = 1; // px
 const BAR_GRAPH_MIN_BARS_WIDTH = 5; // px
 const BAR_GRAPH_MIN_BLOCKS_HEIGHT = 1; // px
 
 const BAR_GRAPH_BACKGROUND_GRADIENT_START = "rgba(0,136,204,0.0)";
 const BAR_GRAPH_BACKGROUND_GRADIENT_END = "rgba(255,255,255,0.25)";
 
 const BAR_GRAPH_CLIPHEAD_LINE_COLOR = "#666";
 const BAR_GRAPH_SELECTION_LINE_COLOR = "#555";
@@ -1106,17 +1106,17 @@ LineGraphWidget.prototype = Heritage.ext
 
     // Draw the graph.
 
     let gradient = ctx.createLinearGradient(0, height / 2, 0, height);
     gradient.addColorStop(0, LINE_GRAPH_BACKGROUND_GRADIENT_START);
     gradient.addColorStop(1, LINE_GRAPH_BACKGROUND_GRADIENT_END);
     ctx.fillStyle = gradient;
     ctx.strokeStyle = LINE_GRAPH_STROKE_COLOR;
-    ctx.lineWidth = LINE_GRAPH_STROKE_WIDTH;
+    ctx.lineWidth = LINE_GRAPH_STROKE_WIDTH * this._pixelRatio;
     ctx.beginPath();
 
     let prevX = 0;
     let prevY = 0;
 
     for (let { delta, value } of this._data) {
       let currX = (delta - firstTick) * dataScaleX;
       let currY = height - value * dataScaleY;
@@ -1374,16 +1374,18 @@ BarGraphWidget.prototype = Heritage.exte
 
     // Draw the graph.
 
     // Iterate over the blocks, then the bars, to draw all rectangles of
     // the same color in a single pass. See the @constructor for more
     // information about the data source, and how a "bar" contains "blocks".
 
     let prevHeight = [];
+    let scaledMarginEnd = BAR_GRAPH_BARS_MARGIN_END * this._pixelRatio;
+    let unscaledMarginTop = BAR_GRAPH_BARS_MARGIN_TOP;
 
     for (let type = 0; type < totalTypes; type++) {
       ctx.fillStyle = this.format[type].color || "#000";
       ctx.beginPath();
 
       let prevLeft = 0;
       let skippedCount = 0;
       let skippedHeight = 0;
@@ -1405,23 +1407,23 @@ BarGraphWidget.prototype = Heritage.exte
         if (averageHeight >= minBlocksHeight) {
           let bottom = height - ~~prevHeight[tick];
           ctx.moveTo(prevLeft, bottom);
           ctx.lineTo(prevLeft, bottom - averageHeight);
           ctx.lineTo(blockLeft, bottom - averageHeight);
           ctx.lineTo(blockLeft, bottom);
 
           if (prevHeight[tick] === undefined) {
-            prevHeight[tick] = averageHeight + BAR_GRAPH_BARS_MARGIN_TOP;
+            prevHeight[tick] = averageHeight + unscaledMarginTop;
           } else {
-            prevHeight[tick] += averageHeight + BAR_GRAPH_BARS_MARGIN_TOP;
+            prevHeight[tick] += averageHeight + unscaledMarginTop;
           }
         }
 
-        prevLeft += blockWidth + BAR_GRAPH_BARS_MARGIN_END;
+        prevLeft += blockWidth + scaledMarginEnd;
         skippedHeight = 0;
         skippedCount = 0;
       }
 
       ctx.fill();
     }
 
     // Update the legend.
@@ -1446,32 +1448,33 @@ BarGraphWidget.prototype = Heritage.exte
    * @return number
    *         The tallest bar height in this graph.
    */
   _calcMaxHeight: function({ data, dataScaleX, dataOffsetX, minBarsWidth }) {
     let maxHeight = 0;
     let prevLeft = 0;
     let skippedCount = 0;
     let skippedHeight = 0;
+    let scaledMarginEnd = BAR_GRAPH_BARS_MARGIN_END * this._pixelRatio;
 
     for (let { delta, values } of data) {
       let barLeft = (delta - dataOffsetX) * dataScaleX;
       let barHeight = values.reduce((a, b) => a + b, 0);
 
       let barWidth = barLeft - prevLeft;
       if (barWidth < minBarsWidth) {
         skippedCount++;
         skippedHeight += barHeight;
         continue;
       }
 
       let averageHeight = (barHeight + skippedHeight) / (skippedCount + 1);
       maxHeight = Math.max(averageHeight, maxHeight);
 
-      prevLeft += barWidth;
+      prevLeft += barWidth + scaledMarginEnd;
       skippedHeight = 0;
       skippedCount = 0;
     }
 
     return maxHeight;
   },
 
   /**
@@ -1553,22 +1556,26 @@ AbstractCanvasGraph.getStripePattern = f
   let canvas = ownerDocument.createElementNS(HTML_NS, "canvas");
   let ctx = canvas.getContext("2d");
   let width = canvas.width = GRAPH_STRIPE_PATTERN_WIDTH;
   let height = canvas.height = GRAPH_STRIPE_PATTERN_HEIGHT;
 
   ctx.fillStyle = backgroundColor;
   ctx.fillRect(0, 0, width, height);
 
+  let pixelRatio = ownerDocument.defaultView.devicePixelRatio;
+  let scaledLineWidth = GRAPH_STRIPE_PATTERN_LINE_WIDTH * pixelRatio;
+  let scaledLineSpacing = GRAPH_STRIPE_PATTERN_LINE_SPACING * pixelRatio;
+
   ctx.strokeStyle = stripesColor;
-  ctx.lineWidth = GRAPH_STRIPE_PATTERN_LINE_WIDTH;
+  ctx.lineWidth = scaledLineWidth;
   ctx.lineCap = "square";
   ctx.beginPath();
 
-  for (let i = -height; i <= height; i += GRAPH_STRIPE_PATTERN_LINE_SPACING) {
+  for (let i = -height; i <= height; i += scaledLineSpacing) {
     ctx.moveTo(width, i);
     ctx.lineTo(0, i + height);
   }
 
   ctx.stroke();
 
   let pattern = ctx.createPattern(canvas, "repeat");
   gCachedStripePattern.set(id, pattern);
--- a/browser/devtools/webconsole/test/browser.ini
+++ b/browser/devtools/webconsole/test/browser.ini
@@ -132,17 +132,16 @@ support-files =
 [browser_console_filters.js]
 [browser_console_iframe_messages.js]
 [browser_console_keyboard_accessibility.js]
 [browser_console_log_inspectable_object.js]
 [browser_console_native_getters.js]
 [browser_console_navigation_marker.js]
 [browser_console_nsiconsolemessage.js]
 [browser_console_optimized_out_vars.js]
-skip-if = true # Intermittent failures - bug 1016310
 [browser_console_private_browsing.js]
 [browser_console_variables_view.js]
 [browser_console_variables_view_dom_nodes.js]
 [browser_console_variables_view_dont_sort_non_sortable_classes_properties.js]
 [browser_console_variables_view_while_debugging.js]
 [browser_console_variables_view_while_debugging_and_inspecting.js]
 [browser_eval_in_debugger_stackframe.js]
 [browser_jsterm_inspect.js]
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -90,16 +90,22 @@
 <!ENTITY debuggerUI.showOnlyEnum.accesskey "P">
 
 <!-- LOCALIZATION NOTE (debuggerUI.showOriginalSource): This is the label for
   -  the checkbox that toggles the display of original or sourcemap-derived
   -  sources. -->
 <!ENTITY debuggerUI.showOriginalSource           "Show Original Sources">
 <!ENTITY debuggerUI.showOriginalSource.accesskey "O">
 
+<!-- LOCALIZATION NOTE (debuggerUI.autoBlackBox): This is the label for
+  -  the checkbox that toggles whether sources that we suspect are minified are
+  -  automatically black boxed or not. -->
+<!ENTITY debuggerUI.autoBlackBox           "Automatically Black Box Minified Sources">
+<!ENTITY debuggerUI.autoBlackBox.accesskey "B">
+
 <!-- LOCALIZATION NOTE (debuggerUI.searchPanelOperators): This is the text that
   -  appears in the filter panel popup as a header for the operators part. -->
 <!ENTITY debuggerUI.searchPanelOperators    "Operators:">
 
 <!-- LOCALIZATION NOTE (debuggerUI.searchFile): This is the text that appears
   -  in the source editor's context menu for the scripts search operation. -->
 <!ENTITY debuggerUI.searchFile           "Filter Scripts">
 <!ENTITY debuggerUI.searchFile.key       "P">
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -61,25 +61,32 @@ MediaOmxReader::~MediaOmxReader()
 {
 }
 
 nsresult MediaOmxReader::Init(MediaDecoderReader* aCloneDonor)
 {
   return NS_OK;
 }
 
-void MediaOmxReader::Shutdown()
+void MediaOmxReader::ReleaseDecoder()
 {
-  ReleaseMediaResources();
   if (mOmxDecoder.get()) {
     mOmxDecoder->ReleaseDecoder();
   }
   mOmxDecoder.clear();
 }
 
+void MediaOmxReader::Shutdown()
+{
+  ReleaseMediaResources();
+  nsCOMPtr<nsIRunnable> event =
+    NS_NewRunnableMethod(this, &MediaOmxReader::ReleaseDecoder);
+  NS_DispatchToMainThread(event);
+}
+
 bool MediaOmxReader::IsWaitingMediaResources()
 {
   if (!mOmxDecoder.get()) {
     return false;
   }
   return mOmxDecoder->IsWaitingMediaResources();
 }
 
--- a/content/media/omx/MediaOmxReader.h
+++ b/content/media/omx/MediaOmxReader.h
@@ -99,13 +99,15 @@ public:
   }
 
 #ifdef MOZ_AUDIO_OFFLOAD
   // Check whether it is possible to offload current audio track. This access
   // canOffloadStream() from libStageFright Utils.cpp, which is not there in
   // ANDROID_VERSION < 19
   void CheckAudioOffload();
 #endif
+
+  void ReleaseDecoder();
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -243,16 +243,30 @@ CameraControlImpl::OnPreviewStateChange(
   mPreviewState = aNewState;
 
   for (uint32_t i = 0; i < mListeners.Length(); ++i) {
     CameraControlListener* l = mListeners[i];
     l->OnPreviewStateChange(mPreviewState);
   }
 }
 
+void
+CameraControlImpl::OnRateLimitPreview(bool aLimit)
+{
+  // This function runs on neither the Main Thread nor the Camera Thread.
+  RwLockAutoEnterRead lock(mListenerLock);
+
+  DOM_CAMERA_LOGI("OnRateLimitPreview: %d\n", aLimit);
+
+  for (uint32_t i = 0; i < mListeners.Length(); ++i) {
+    CameraControlListener* l = mListeners[i];
+    l->OnRateLimitPreview(aLimit);
+  }
+}
+
 bool
 CameraControlImpl::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
 {
   // This function runs on neither the Main Thread nor the Camera Thread.
   //  On Gonk, it is called from the camera driver's preview thread.
   RwLockAutoEnterRead lock(mListenerLock);
 
   DOM_CAMERA_LOGI("OnNewPreviewFrame: we have %d preview frame listener(s)\n",
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -62,16 +62,17 @@ public:
   void OnAutoFocusMoving(bool aIsMoving);
 
 protected:
   // Event handlers.
   void OnAutoFocusComplete(bool aAutoFocusSucceeded);
   void OnFacesDetected(const nsTArray<Face>& aFaces);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType);
 
+  void OnRateLimitPreview(bool aLimit);
   bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
   void OnRecorderStateChange(CameraControlListener::RecorderState aState,
                              int32_t aStatus = -1, int32_t aTrackNumber = -1);
   void OnPreviewStateChange(CameraControlListener::PreviewState aState);
   void OnHardwareStateChange(CameraControlListener::HardwareState aState);
   void OnConfigurationChange();
 
   // When we create a new CameraThread, we keep a static reference to it so
--- a/dom/camera/CameraControlListener.h
+++ b/dom/camera/CameraControlListener.h
@@ -59,16 +59,17 @@ public:
     kMediaRecorderFailed,
     kMediaServerFailed
 #endif
   };
   enum { kNoTrackNumber = -1 };
   virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) { }
 
   virtual void OnShutter() { }
+  virtual void OnRateLimitPreview(bool aLimit) { }
   virtual bool OnNewPreviewFrame(layers::Image* aFrame, uint32_t aWidth, uint32_t aHeight)
   {
     return false;
   }
 
   class CameraListenerConfiguration : public ICameraControl::Configuration
   {
   public:
--- a/dom/camera/CameraPreviewMediaStream.cpp
+++ b/dom/camera/CameraPreviewMediaStream.cpp
@@ -1,24 +1,35 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CameraPreviewMediaStream.h"
+#include "CameraCommon.h"
+
+/**
+ * Maximum number of outstanding invalidates before we start to drop frames;
+ * if we hit this threshold, it is an indicator that the main thread is
+ * either very busy or the device is busy elsewhere (e.g. encoding or
+ * persisting video data).
+ */
+#define MAX_INVALIDATE_PENDING 4
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
   : MediaStream(aWrapper)
   , mMutex("mozilla::camera::CameraPreviewMediaStream")
-  , mFrameCallback(nullptr)
+  , mInvalidatePending(0)
+  , mDiscardedFrames(0)
+  , mRateLimit(false)
 {
   SetGraphImpl(MediaStreamGraph::GetInstance());
   mIsConsumed = false;
 }
 
 void
 CameraPreviewMediaStream::AddAudioOutput(void* aKey)
 {
@@ -98,40 +109,71 @@ CameraPreviewMediaStream::RemoveListener
 void
 CameraPreviewMediaStream::Destroy()
 {
   MutexAutoLock lock(mMutex);
   DestroyImpl();
 }
 
 void
-CameraPreviewMediaStream::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage)
+CameraPreviewMediaStream::Invalidate()
 {
   MutexAutoLock lock(mMutex);
-
-  TimeStamp now = TimeStamp::Now();
-  for (uint32_t i = 0; i < mVideoOutputs.Length(); ++i) {
+  --mInvalidatePending;
+  for (nsTArray<nsRefPtr<VideoFrameContainer> >::size_type i = 0; i < mVideoOutputs.Length(); ++i) {
     VideoFrameContainer* output = mVideoOutputs[i];
-    output->SetCurrentFrame(aIntrinsicSize, aImage, now);
-    nsCOMPtr<nsIRunnable> event =
-      NS_NewRunnableMethod(output, &VideoFrameContainer::Invalidate);
-    NS_DispatchToMainThread(event);
+    output->Invalidate();
+  }
+}
+
+void
+CameraPreviewMediaStream::RateLimit(bool aLimit)
+{
+  mRateLimit = aLimit;
+}
+
+void
+CameraPreviewMediaStream::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage)
+{
+  {
+    MutexAutoLock lock(mMutex);
+
+    if (mInvalidatePending > 0) {
+      if (mRateLimit || mInvalidatePending > MAX_INVALIDATE_PENDING) {
+        ++mDiscardedFrames;
+        DOM_CAMERA_LOGW("Discard preview frame %d, %d invalidation(s) pending",
+          mDiscardedFrames, mInvalidatePending);
+        return;
+      }
+
+      DOM_CAMERA_LOGI("Update preview frame, %d invalidation(s) pending",
+        mInvalidatePending);
+    }
+    mDiscardedFrames = 0;
+
+    TimeStamp now = TimeStamp::Now();
+    for (nsTArray<nsRefPtr<VideoFrameContainer> >::size_type i = 0; i < mVideoOutputs.Length(); ++i) {
+      VideoFrameContainer* output = mVideoOutputs[i];
+      output->SetCurrentFrame(aIntrinsicSize, aImage, now);
+    }
+
+    ++mInvalidatePending;
   }
 
-  if (mFrameCallback) {
-    mFrameCallback->OnNewFrame(aIntrinsicSize, aImage);
-  }
+  nsCOMPtr<nsIRunnable> event =
+    NS_NewRunnableMethod(this, &CameraPreviewMediaStream::Invalidate);
+  NS_DispatchToMainThread(event);
 }
 
 void
 CameraPreviewMediaStream::ClearCurrentFrame()
 {
   MutexAutoLock lock(mMutex);
 
-  for (uint32_t i = 0; i < mVideoOutputs.Length(); ++i) {
+  for (nsTArray<nsRefPtr<VideoFrameContainer> >::size_type i = 0; i < mVideoOutputs.Length(); ++i) {
     VideoFrameContainer* output = mVideoOutputs[i];
     output->ClearCurrentFrame();
     nsCOMPtr<nsIRunnable> event =
       NS_NewRunnableMethod(output, &VideoFrameContainer::Invalidate);
     NS_DispatchToMainThread(event);
   }
 }
 
--- a/dom/camera/CameraPreviewMediaStream.h
+++ b/dom/camera/CameraPreviewMediaStream.h
@@ -6,23 +6,18 @@
 #define DOM_CAMERA_CAMERAPREVIEWMEDIASTREAM_H
 
 #include "VideoFrameContainer.h"
 #include "MediaStreamGraph.h"
 #include "mozilla/Mutex.h"
 
 namespace mozilla {
 
-class CameraPreviewFrameCallback {
-public:
-  virtual void OnNewFrame(const gfxIntSize& aIntrinsicSize, layers::Image* aImage) = 0;
-};
-
 /**
- * This is a stream for camere preview.
+ * This is a stream for camera preview.
  *
  * XXX It is a temporary fix of SourceMediaStream.
  * A camera preview requests no delay and no buffering stream.
  * But the SourceMediaStream do not support it.
  */
 class CameraPreviewMediaStream : public MediaStream
 {
   typedef mozilla::layers::Image Image;
@@ -35,27 +30,28 @@ public:
   virtual void RemoveAudioOutput(void* aKey) MOZ_OVERRIDE;
   virtual void AddVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void RemoveVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
   virtual void ChangeExplicitBlockerCount(int32_t aDelta) MOZ_OVERRIDE;
   virtual void AddListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
   virtual void Destroy();
 
+  void Invalidate();
+
   // Call these on any thread.
   void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage);
   void ClearCurrentFrame();
-
-  void SetFrameCallback(CameraPreviewFrameCallback* aCallback) {
-    mFrameCallback = aCallback;
-  }
+  void RateLimit(bool aLimit);
 
 protected:
   // mMutex protects all the class' fields.
   // This class is not registered to MediaStreamGraph.
   // It needs to protect all the fields.
   Mutex mMutex;
-  CameraPreviewFrameCallback* mFrameCallback;
+  int32_t mInvalidatePending;
+  uint32_t mDiscardedFrames;
+  bool mRateLimit;
 };
 
 }
 
 #endif // DOM_CAMERA_CAMERAPREVIEWMEDIASTREAM_H
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -209,17 +209,17 @@ protected:
   nsRefPtr<dom::CameraFaceDetectionCallback>    mOnFacesDetectedCb;
 
   // Camera event listener; we only need this weak reference so that
   //  we can remove the listener from the camera when we're done
   //  with it.
   DOMCameraControlListener* mListener;
 
   // our viewfinder stream
-  CameraPreviewMediaStream* mInput;
+  nsRefPtr<CameraPreviewMediaStream> mInput;
 
   // set once when this object is created
   nsCOMPtr<nsPIDOMWindow>   mWindow;
 
   dom::CameraStartRecordingOptions mOptions;
   nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
 
 private:
--- a/dom/camera/DOMCameraControlListener.cpp
+++ b/dom/camera/DOMCameraControlListener.cpp
@@ -282,16 +282,22 @@ DOMCameraControlListener::OnShutter()
     {
       aDOMCameraControl->OnShutter();
     }
   };
 
   NS_DispatchToMainThread(new Callback(mDOMCameraControl));
 }
 
+void
+DOMCameraControlListener::OnRateLimitPreview(bool aLimit)
+{
+  mStream->RateLimit(aLimit);
+}
+
 bool
 DOMCameraControlListener::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight)
 {
   DOM_CAMERA_LOGI("OnNewPreviewFrame: got %d x %d frame\n", aWidth, aHeight);
 
   mStream->SetCurrentFrame(gfxIntSize(aWidth, aHeight), aImage);
   return true;
 }
--- a/dom/camera/DOMCameraControlListener.h
+++ b/dom/camera/DOMCameraControlListener.h
@@ -23,16 +23,17 @@ public:
   virtual void OnFacesDetected(const nsTArray<ICameraControl::Face>& aFaces) MOZ_OVERRIDE;
   virtual void OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType) MOZ_OVERRIDE;
 
   virtual void OnHardwareStateChange(HardwareState aState) MOZ_OVERRIDE;
   virtual void OnPreviewStateChange(PreviewState aState) MOZ_OVERRIDE;
   virtual void OnRecorderStateChange(RecorderState aState, int32_t aStatus, int32_t aTrackNum) MOZ_OVERRIDE;
   virtual void OnConfigurationChange(const CameraListenerConfiguration& aConfiguration) MOZ_OVERRIDE;
   virtual void OnShutter() MOZ_OVERRIDE;
+  virtual void OnRateLimitPreview(bool aLimit) MOZ_OVERRIDE;
   virtual bool OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) MOZ_OVERRIDE;
   virtual void OnUserError(UserContext aContext, nsresult aError) MOZ_OVERRIDE;
 
 protected:
   virtual ~DOMCameraControlListener();
 
   nsMainThreadPtrHandle<nsDOMCameraControl> mDOMCameraControl;
   CameraPreviewMediaStream* mStream;
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -1678,16 +1678,22 @@ nsGonkCameraControl::GetGonkRecorderProf
 already_AddRefed<RecorderProfileManager>
 nsGonkCameraControl::GetRecorderProfileManagerImpl()
 {
   nsRefPtr<RecorderProfileManager> profileMgr = GetGonkRecorderProfileManager();
   return profileMgr.forget();
 }
 
 void
+nsGonkCameraControl::OnRateLimitPreview(bool aLimit)
+{
+  CameraControlImpl::OnRateLimitPreview(aLimit);
+}
+
+void
 nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer)
 {
   nsRefPtr<Image> frame = mImageContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
 
   GrallocImage* videoImage = static_cast<GrallocImage*>(frame.get());
 
   GrallocImage::GrallocData data;
   data.mGraphicBuffer = aBuffer;
@@ -1740,16 +1746,22 @@ OnAutoFocusMoving(nsGonkCameraControl* g
 
 void
 OnFacesDetected(nsGonkCameraControl* gc, camera_frame_metadata_t* aMetaData)
 {
   gc->OnFacesDetected(aMetaData);
 }
 
 void
+OnRateLimitPreview(nsGonkCameraControl* gc, bool aLimit)
+{
+  gc->OnRateLimitPreview(aLimit);
+}
+
+void
 OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer)
 {
   gc->OnNewPreviewFrame(aBuffer);
 }
 
 void
 OnShutter(nsGonkCameraControl* gc)
 {
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -47,20 +47,21 @@ class nsGonkCameraControl : public Camer
 {
 public:
   nsGonkCameraControl(uint32_t aCameraId);
 
   void OnAutoFocusComplete(bool aSuccess);
   void OnFacesDetected(camera_frame_metadata_t* aMetaData);
   void OnTakePictureComplete(uint8_t* aData, uint32_t aLength);
   void OnTakePictureError();
+  void OnRateLimitPreview(bool aLimit);
   void OnNewPreviewFrame(layers::TextureClient* aBuffer);
   void OnRecorderEvent(int msg, int ext1, int ext2);
   void OnSystemError(CameraControlListener::SystemContext aWhere, nsresult aError);
- 
+
   // See ICameraControl.h for getter/setter return values.
   virtual nsresult Set(uint32_t aKey, const nsAString& aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, nsAString& aValue) MOZ_OVERRIDE;
   virtual nsresult Set(uint32_t aKey, double aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, double& aValue) MOZ_OVERRIDE;
   virtual nsresult Set(uint32_t aKey, int32_t aValue) MOZ_OVERRIDE;
   virtual nsresult Get(uint32_t aKey, int32_t& aValue) MOZ_OVERRIDE;
   virtual nsresult Set(uint32_t aKey, int64_t aValue) MOZ_OVERRIDE;
@@ -79,16 +80,17 @@ public:
   virtual nsresult Get(uint32_t aKey, nsTArray<double>& aValues) MOZ_OVERRIDE;
 
   nsresult PushParameters();
   nsresult PullParameters();
 
 protected:
   ~nsGonkCameraControl();
 
+  using CameraControlImpl::OnRateLimitPreview;
   using CameraControlImpl::OnNewPreviewFrame;
   using CameraControlImpl::OnAutoFocusComplete;
   using CameraControlImpl::OnFacesDetected;
   using CameraControlImpl::OnTakePictureComplete;
   using CameraControlImpl::OnConfigurationChange;
   using CameraControlImpl::OnUserError;
 
   virtual void BeginBatchParameterSet() MOZ_OVERRIDE;
@@ -173,16 +175,17 @@ protected:
   ReentrantMonitor          mReentrantMonitor;
 
 private:
   nsGonkCameraControl(const nsGonkCameraControl&) MOZ_DELETE;
   nsGonkCameraControl& operator=(const nsGonkCameraControl&) MOZ_DELETE;
 };
 
 // camera driver callbacks
+void OnRateLimitPreview(nsGonkCameraControl* gc, bool aLimit);
 void OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
 void OnTakePictureError(nsGonkCameraControl* gc);
 void OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);
 void OnAutoFocusMoving(nsGonkCameraControl* gc, bool aIsMoving);
 void OnFacesDetected(nsGonkCameraControl* gc, camera_frame_metadata_t* aMetaData);
 void OnNewPreviewFrame(nsGonkCameraControl* gc, layers::TextureClient* aBuffer);
 void OnShutter(nsGonkCameraControl* gc);
 void OnClosed(nsGonkCameraControl* gc);
--- a/dom/camera/GonkCameraHwMgr.cpp
+++ b/dom/camera/GonkCameraHwMgr.cpp
@@ -40,16 +40,22 @@ GonkCameraHardware::GonkCameraHardware(m
   , mCamera(aCamera)
   , mTarget(aTarget)
   , mSensorOrientation(0)
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget);
 }
 
 void
+GonkCameraHardware::OnRateLimitPreview(bool aLimit)
+{
+  ::OnRateLimitPreview(mTarget, aLimit);
+}
+
+void
 GonkCameraHardware::OnNewFrame()
 {
   if (mClosing) {
     return;
   }
   RefPtr<TextureClient> buffer = mNativeWindow->getCurrentBuffer();
   if (!buffer) {
     DOM_CAMERA_LOGW("received null frame");
--- a/dom/camera/GonkCameraHwMgr.h
+++ b/dom/camera/GonkCameraHwMgr.h
@@ -50,16 +50,18 @@ protected:
   //  - NS_OK on success;
   //  - NS_ERROR_NOT_INITIALIZED if the interface could not be initialized.
   virtual nsresult Init();
 
 public:
   static sp<GonkCameraHardware> Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId);
   virtual void Close();
 
+  virtual void OnRateLimitPreview(bool aLimit);
+
   // derived from GonkNativeWindowNewFrameCallback
   virtual void OnNewFrame() MOZ_OVERRIDE;
 
   // derived from CameraListener
   virtual void notify(int32_t aMsgType, int32_t ext1, int32_t ext2);
   virtual void postData(int32_t aMsgType, const sp<IMemory>& aDataPtr, camera_frame_metadata_t* metadata);
   virtual void postDataTimestamp(nsecs_t aTimestamp, int32_t aMsgType, const sp<IMemory>& aDataPtr);
 
--- a/dom/camera/GonkCameraSource.cpp
+++ b/dom/camera/GonkCameraSource.cpp
@@ -165,16 +165,17 @@ GonkCameraSource::GonkCameraSource(
     : mCameraFlags(0),
       mNumInputBuffers(0),
       mVideoFrameRate(-1),
       mNumFramesReceived(0),
       mLastFrameTimestampUs(0),
       mStarted(false),
       mNumFramesEncoded(0),
       mTimeBetweenFrameCaptureUs(0),
+      mRateLimit(false),
       mFirstFrameTimeUs(0),
       mNumFramesDropped(0),
       mNumGlitches(0),
       mGlitchDurationThresholdUs(200000),
       mCollectStats(false),
       mCameraHw(aCameraHw) {
     mVideoSize.width  = -1;
     mVideoSize.height = -1;
@@ -584,16 +585,20 @@ status_t GonkCameraSource::reset() {
         if (NO_ERROR !=
             mFrameCompleteCondition.waitRelative(mLock,
                     mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
             CS_LOGW("Timed out waiting for outstanding frames being encoded: %d",
                 mFramesBeingEncoded.size());
         }
     }
     stopCameraRecording();
+    if (mRateLimit) {
+      mRateLimit = false;
+      mCameraHw->OnRateLimitPreview(false);
+    }
     releaseCamera();
 
     if (mCollectStats) {
         CS_LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
                 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
                 mLastFrameTimestampUs - mFirstFrameTimeUs);
     }
 
@@ -687,61 +692,75 @@ status_t GonkCameraSource::read(
         (*buffer)->add_ref();
         (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
     }
     return OK;
 }
 
 void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs,
         int32_t msgType, const sp<IMemory> &data) {
+    bool rateLimit;
+    bool prevRateLimit;
     CS_LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
-    Mutex::Autolock autoLock(mLock);
-    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
-        CS_LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
-        releaseOneRecordingFrame(data);
-        return;
-    }
+    {
+        Mutex::Autolock autoLock(mLock);
+        if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
+            CS_LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
+            releaseOneRecordingFrame(data);
+            return;
+        }
+
+        if (mNumFramesReceived > 0) {
+            CHECK(timestampUs > mLastFrameTimestampUs);
+            if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
+                ++mNumGlitches;
+            }
+        }
+
+        // May need to skip frame or modify timestamp. Currently implemented
+        // by the subclass CameraSourceTimeLapse.
+        if (skipCurrentFrame(timestampUs)) {
+            releaseOneRecordingFrame(data);
+            return;
+        }
 
-    if (mNumFramesReceived > 0) {
-        CHECK(timestampUs > mLastFrameTimestampUs);
-        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
-            ++mNumGlitches;
+        mLastFrameTimestampUs = timestampUs;
+        if (mNumFramesReceived == 0) {
+            mFirstFrameTimeUs = timestampUs;
+            // Initial delay
+            if (mStartTimeUs > 0) {
+                if (timestampUs < mStartTimeUs) {
+                    // Frame was captured before recording was started
+                    // Drop it without updating the statistical data.
+                    releaseOneRecordingFrame(data);
+                    return;
+                }
+                mStartTimeUs = timestampUs - mStartTimeUs;
+            }
         }
-    }
+        ++mNumFramesReceived;
+
+        // If a backlog is building up in the receive queue, we are likely
+        // resource constrained and we need to throttle
+        prevRateLimit = mRateLimit;
+        rateLimit = mFramesReceived.empty();
+        mRateLimit = rateLimit;
 
-    // May need to skip frame or modify timestamp. Currently implemented
-    // by the subclass CameraSourceTimeLapse.
-    if (skipCurrentFrame(timestampUs)) {
-        releaseOneRecordingFrame(data);
-        return;
+        CHECK(data != NULL && data->size() > 0);
+        mFramesReceived.push_back(data);
+        int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
+        mFrameTimes.push_back(timeUs);
+        CS_LOGV("initial delay: %lld, current time stamp: %lld",
+            mStartTimeUs, timeUs);
+        mFrameAvailableCondition.signal();
     }
 
-    mLastFrameTimestampUs = timestampUs;
-    if (mNumFramesReceived == 0) {
-        mFirstFrameTimeUs = timestampUs;
-        // Initial delay
-        if (mStartTimeUs > 0) {
-            if (timestampUs < mStartTimeUs) {
-                // Frame was captured before recording was started
-                // Drop it without updating the statistical data.
-                releaseOneRecordingFrame(data);
-                return;
-            }
-            mStartTimeUs = timestampUs - mStartTimeUs;
-        }
+    if(prevRateLimit != rateLimit) {
+        mCameraHw->OnRateLimitPreview(rateLimit);
     }
-    ++mNumFramesReceived;
-
-    CHECK(data != NULL && data->size() > 0);
-    mFramesReceived.push_back(data);
-    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
-    mFrameTimes.push_back(timeUs);
-    CS_LOGV("initial delay: %lld, current time stamp: %lld",
-        mStartTimeUs, timeUs);
-    mFrameAvailableCondition.signal();
 }
 
 bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {
     CS_LOGV("isMetaDataStoredInVideoBuffers");
     return mIsMetaDataStoredInVideoBuffers;
 }
 
 }  // namespace android
--- a/dom/camera/GonkCameraSource.h
+++ b/dom/camera/GonkCameraSource.h
@@ -122,16 +122,17 @@ protected:
 private:
 
     Mutex mLock;
     Condition mFrameAvailableCondition;
     Condition mFrameCompleteCondition;
     List<sp<IMemory> > mFramesReceived;
     List<sp<IMemory> > mFramesBeingEncoded;
     List<int64_t> mFrameTimes;
+    bool mRateLimit;
 
     int64_t mFirstFrameTimeUs;
     int32_t mNumFramesDropped;
     int32_t mNumGlitches;
     int64_t mGlitchDurationThresholdUs;
     bool mCollectStats;
     bool mIsMetaDataStoredInVideoBuffers;
     sp<GonkCameraHardware> mCameraHw;
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -344,17 +344,18 @@ private:
 
   friend class WatchFileEvent;
   friend class DeviceStorageRequest;
 
   static mozilla::StaticAutoPtr<nsTArray<nsString>> sVolumeNameCache;
 
 #ifdef MOZ_WIDGET_GONK
   nsString mLastStatus;
-  void DispatchMountChangeEvent(nsAString& aVolumeStatus);
+  void DispatchStatusChangeEvent(nsAString& aStatus);
+  void DispatchStorageStatusChangeEvent(nsAString& aVolumeStatus);
 #endif
 
   // nsIDOMDeviceStorage.type
   enum {
       DEVICE_STORAGE_TYPE_DEFAULT = 0,
       DEVICE_STORAGE_TYPE_SHARED,
       DEVICE_STORAGE_TYPE_EXTERNAL
   };
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -4189,32 +4189,50 @@ nsDOMDeviceStorage::EnumerateInternal(co
     prompt->Prompt(r);
   }
 
   return cursor.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
-nsDOMDeviceStorage::DispatchMountChangeEvent(nsAString& aVolumeStatus)
+nsDOMDeviceStorage::DispatchStatusChangeEvent(nsAString& aStatus)
 {
-  if (aVolumeStatus == mLastStatus) {
+  if (aStatus == mLastStatus) {
     // We've already sent this status, don't bother sending it again.
     return;
   }
-  mLastStatus = aVolumeStatus;
-
+  mLastStatus = aStatus;
+
+  DeviceStorageChangeEventInit init;
+  init.mBubbles = true;
+  init.mCancelable = false;
+  init.mPath = mStorageName;
+  init.mReason = aStatus;
+
+  nsRefPtr<DeviceStorageChangeEvent> event =
+    DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("change"),
+                                          init);
+  event->SetTrusted(true);
+
+  bool ignore;
+  DispatchEvent(event, &ignore);
+}
+
+void
+nsDOMDeviceStorage::DispatchStorageStatusChangeEvent(nsAString& aVolumeStatus)
+{
   DeviceStorageChangeEventInit init;
   init.mBubbles = true;
   init.mCancelable = false;
   init.mPath = mStorageName;
   init.mReason = aVolumeStatus;
 
   nsRefPtr<DeviceStorageChangeEvent> event =
-    DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("change"),
+    DeviceStorageChangeEvent::Constructor(this, NS_LITERAL_STRING("storage-state-change"),
                                           init);
   event->SetTrusted(true);
 
   bool ignore;
   DispatchEvent(event, &ignore);
 }
 #endif
 
@@ -4263,19 +4281,25 @@ nsDOMDeviceStorage::Observe(nsISupports 
     usedSpaceCache->Invalidate(volName);
 
     if (!volName.Equals(mStorageName)) {
       // Not our volume - we can ignore.
       return NS_OK;
     }
 
     DeviceStorageFile dsf(mStorageType, mStorageName);
-    nsString status;
+    nsString status, storageStatus;
+
+    // Get Status (one of "available, unavailable, shared")
     dsf.GetStatus(status);
-    DispatchMountChangeEvent(status);
+    DispatchStatusChangeEvent(status);
+
+    // Get real volume status (defined in dom/system/gonk/nsIVolume.idl)
+    dsf.GetStorageStatus(storageStatus);
+    DispatchStorageStatusChangeEvent(storageStatus);
     return NS_OK;
   }
 #endif
   return NS_OK;
 }
 
 nsresult
 nsDOMDeviceStorage::Notify(const char* aReason, DeviceStorageFile* aFile)
--- a/dom/inputmethod/MozKeyboard.js
+++ b/dom/inputmethod/MozKeyboard.js
@@ -99,16 +99,17 @@ MozInputMethodManager.prototype = {
  * ==============================================
  * InputMethod
  * ==============================================
  */
 function MozInputMethod() { }
 
 MozInputMethod.prototype = {
   _inputcontext: null,
+  _wrappedInputContext: null,
   _layouts: {},
   _window: null,
   _isSystem: false,
   _isKeyboard: true,
 
   classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"),
 
   QueryInterface: XPCOMUtils.generateQI([
@@ -206,41 +207,46 @@ MozInputMethod.prototype = {
   get mgmt() {
     return this._mgmt;
   },
 
   get inputcontext() {
     if (!WindowMap.isActive(this._window)) {
       return null;
     }
-    return this._inputcontext;
+    return this._wrappedInputContext;
   },
 
   set oninputcontextchange(handler) {
     this.__DOM_IMPL__.setEventHandler("oninputcontextchange", handler);
   },
 
   get oninputcontextchange() {
     return this.__DOM_IMPL__.getEventHandler("oninputcontextchange");
   },
 
   setInputContext: function mozKeyboardContextChange(data) {
     if (this._inputcontext) {
       this._inputcontext.destroy();
       this._inputcontext = null;
+      this._wrappedInputContext = null;
       this._mgmt._supportsSwitching = false;
     }
 
     if (data) {
       this._mgmt._supportsSwitching = this._layouts[data.type] ?
         this._layouts[data.type] > 1 :
         false;
 
       this._inputcontext = new MozInputContext(data);
       this._inputcontext.init(this._window);
+      // inputcontext will be exposed as a WebIDL object. Create its
+      // content-side object explicitly to avoid Bug 1001325.
+      this._wrappedInputContext =
+        this._window.MozInputContext._create(this._window, this._inputcontext);
     }
 
     let event = new this._window.Event("inputcontextchange",
                                        Cu.cloneInto({}, this._window));
     this.__DOM_IMPL__.dispatchEvent(event);
   },
 
   setActive: function mozInputMethodSetActive(isActive) {
--- a/dom/nfc/tests/marionette/test_nfc_peer.js
+++ b/dom/nfc/tests/marionette/test_nfc_peer.js
@@ -7,27 +7,35 @@ MARIONETTE_HEAD_JS = 'head.js';
 let MANIFEST_URL = "app://system.gaiamobile.org/manifest.webapp";
 let INCORRECT_MANIFEST_URL = "app://xyz.gaiamobile.org/manifest.webapp";
 
 function peerReadyCb(evt) {
   log("peerReadyCb called");
   let peer = nfc.getNFCPeer(evt.detail);
   ok(peer instanceof MozNFCPeer, "Should get a NFCPeer object.");
 
-  // reset callback and NFC Hardware.
+  // reset callback.
   nfc.onpeerready = null;
+  emulator.deactivate();
+}
+
+function peerLostCb() {
+  log("peerLostCb called");
+  ok(true);
+  nfc.onpeerlost = null;
   toggleNFC(false).then(runNextTest);
 }
 
 function handleTechnologyDiscoveredRE0(msg) {
   log("Received \'nfc-manager-tech-discovered\'");
   is(msg.type, "techDiscovered", "check for correct message type");
   is(msg.techList[0], "P2P", "check for correct tech type");
 
   nfc.onpeerready = peerReadyCb;
+  nfc.onpeerlost = peerLostCb;
 
   let request = nfc.checkP2PRegistration(MANIFEST_URL);
   request.onsuccess = function (evt) {
     is(request.result, true, "check for P2P registration result");
     nfc.notifyUserAcceptedP2P(MANIFEST_URL);
   }
 
   request.onerror = function () {
--- a/dom/system/gonk/Nfc.js
+++ b/dom/system/gonk/Nfc.js
@@ -281,17 +281,17 @@ XPCOMUtils.defineLazyGetter(this, "gMess
           delete targets[appId];
         }
       });
     },
 
     isRegisteredP2PTarget: function isRegisteredP2PTarget(appId, event) {
       let targetInfo = this.peerTargetsMap[appId];
       // Check if it is a registered target for the 'event'
-      return ((targetInfo != null) && (targetInfo.event & event !== 0));
+      return ((targetInfo != null) && ((targetInfo.event & event) !== 0));
     },
 
     notifyPeerEvent: function notifyPeerEvent(appId, event) {
       let targetInfo = this.peerTargetsMap[appId];
       // Check if the application id is a registeredP2PTarget
       if (this.isRegisteredP2PTarget(appId, event)) {
         targetInfo.target.sendAsyncMessage("NFC:PeerEvent", {
           event: event,
@@ -522,17 +522,17 @@ Nfc.prototype = {
 
         // Update the upper layers with a session token (alias)
         message.sessionToken = this.sessionTokenMap[this._currentSessionId];
         // Do not expose the actual session to the content
         delete message.sessionId;
 
         gSystemMessenger.broadcastMessage("nfc-manager-tech-lost", message);
         // Notify 'PeerLost' to appropriate registered target, if any
-        gMessageManager.notifyPeerEvent(this.currentPeerAppId, NFC.NFC_PEER_EVENT_LOST);
+        gMessageManager.notifyPeerEvent(gMessageManager.currentPeerAppId, NFC.NFC_PEER_EVENT_LOST);
         delete this.sessionTokenMap[this._currentSessionId];
         this._currentSessionId = null;
         this.currentPeerAppId = null;
         break;
      case "ConfigResponse":
         let target = this.targetsByRequestId[message.requestId];
         if (!target) {
           debug("No target for requestId: " + message.requestId);
--- a/dom/webidl/MozWifiManager.webidl
+++ b/dom/webidl/MozWifiManager.webidl
@@ -310,23 +310,23 @@ interface MozWifiManager : EventTarget {
    *                   disconnected).
    */
   attribute EventHandler onstatuschange;
 
   /**
    * An event listener that is called with information about the signal
    * strength and link speed every 5 seconds.
    */
-  attribute EventHandler onconnectionInfoUpdate;
+  attribute EventHandler onconnectioninfoupdate;
 
   /**
    * These two events fire when the wifi system is brought online or taken
    * offline.
    */
   attribute EventHandler onenabled;
   attribute EventHandler ondisabled;
 
   /**
    * An event listener that is called with information about the number
    * of wifi stations connected to wifi hotspot every 5 seconds.
    */
-  attribute EventHandler onstationInfoUpdate;
+  attribute EventHandler onstationinfoupdate;
 };
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -72,20 +72,20 @@ function MozWifiCapabilities(obj) {
 MozWifiCapabilities.prototype = {
   classID: Components.ID("08c88ece-8092-481b-863b-5515a52e411a"),
   contractID: "@mozilla.org/mozwificapabilities;1",
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
 }
 
 function DOMWifiManager() {
   this.defineEventHandlerGetterSetter("onstatuschange");
-  this.defineEventHandlerGetterSetter("onconnectionInfoUpdate");
+  this.defineEventHandlerGetterSetter("onconnectioninfoupdate");
   this.defineEventHandlerGetterSetter("onenabled");
   this.defineEventHandlerGetterSetter("ondisabled");
-  this.defineEventHandlerGetterSetter("onstationInfoUpdate");
+  this.defineEventHandlerGetterSetter("onstationinfoupdate");
 }
 
 DOMWifiManager.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
   classDescription: "DOMWifiManager",
   classID: DOMWIFIMANAGER_CID,
   contractID: DOMWIFIMANAGER_CONTRACTID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
@@ -112,19 +112,19 @@ DOMWifiManager.prototype = {
                       "WifiManager:setStaticIpMode:Return:OK", "WifiManager:setStaticIpMode:Return:NO",
                       "WifiManager:importCert:Return:OK", "WifiManager:importCert:Return:NO",
                       "WifiManager:getImportedCerts:Return:OK", "WifiManager:getImportedCerts:Return:NO",
                       "WifiManager:deleteCert:Return:OK", "WifiManager:deleteCert:Return:NO",
                       "WifiManager:wifiDown", "WifiManager:wifiUp",
                       "WifiManager:onconnecting", "WifiManager:onassociate",
                       "WifiManager:onconnect", "WifiManager:ondisconnect",
                       "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
-                      "WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
+                      "WifiManager:onwpsoverlap", "WifiManager:connectioninfoupdate",
                       "WifiManager:onauthenticating", "WifiManager:onconnectingfailed",
-                      "WifiManager:stationInfoUpdate"];
+                      "WifiManager:stationinfoupdate"];
     this.initDOMRequestHelper(aWindow, messages);
     this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
 
     var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
     if (state) {
       this._currentNetwork = this._convertWifiNetwork(state.network);
       this._lastConnectionInfo = this._convertConnectionInfo(state.connectionInfo);
       this._enabled = state.enabled;
@@ -374,32 +374,32 @@ DOMWifiManager.prototype = {
 
       case "WifiManager:onwpsoverlap":
         this._currentNetwork = null;
         this._connectionStatus = "wps-overlapped";
         this._lastConnectionInfo = null;
         this._fireStatusChangeEvent();
         break;
 
-      case "WifiManager:connectionInfoUpdate":
+      case "WifiManager:connectioninfoupdate":
         this._lastConnectionInfo = this._convertConnectionInfo(msg);
         this._fireConnectionInfoUpdate(msg);
         break;
       case "WifiManager:onconnectingfailed":
         this._currentNetwork = null;
         this._connectionStatus = "connectingfailed";
         this._lastConnectionInfo = null;
         this._fireStatusChangeEvent();
         break;
       case "WifiManager:onauthenticating":
         this._currentNetwork = msg.network;
         this._connectionStatus = "authenticating";
         this._fireStatusChangeEvent();
         break;
-      case "WifiManager:stationInfoUpdate":
+      case "WifiManager:stationinfoupdate":
         this._stationNumber = msg.station;
         this._fireStationInfoUpdate(msg);
         break;
     }
   },
 
   _fireStatusChangeEvent: function StatusChangeEvent() {
     var event = new this._window.MozWifiStatusChangeEvent("statuschange",
@@ -421,17 +421,17 @@ DOMWifiManager.prototype = {
   },
 
   _fireEnabledOrDisabled: function enabledDisabled(enabled) {
     var evt = new this._window.Event(enabled ? "enabled" : "disabled");
     this.__DOM_IMPL__.dispatchEvent(evt);
   },
 
   _fireStationInfoUpdate: function onStationInfoUpdate(info) {
-    var evt = new this._window.MozWifiStationInfoEvent("stationInfoUpdate",
+    var evt = new this._window.MozWifiStationInfoEvent("stationinfoupdate",
                                                        { station: this._stationNumber}
                                                       );
     this.__DOM_IMPL__.dispatchEvent(evt);
   },
 
   getNetworks: function getNetworks() {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:getNetworks", null, request);
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1107,17 +1107,17 @@ var WifiManager = (function() {
             wifiCommand.closeHostapdConnection(function(result) {
             });
           }
           return;
         }
 
         function getWifiHotspotStatus() {
           wifiCommand.hostapdGetStations(function(result) {
-            notify("stationInfoUpdate", {station: result});
+            notify("stationinfoupdate", {station: result});
           });
         }
 
         function doStartWifiTethering() {
           cancelWaitForDriverReadyTimer();
           WifiNetworkInterface.name = manager.ifname;
           gNetworkManager.setWifiTethering(enabled, WifiNetworkInterface,
                                            configuration, function(result) {
@@ -2319,18 +2319,18 @@ function WifiWorker() {
         }
       }
 
       self.wantScanResults.forEach(function(callback) { callback(self.networksArray) });
       self.wantScanResults = [];
     });
   };
 
-  WifiManager.onstationInfoUpdate = function() {
-    self._fireEvent("stationInfoUpdate", { station: this.station });
+  WifiManager.onstationinfoupdate = function() {
+    self._fireEvent("stationinfoupdate", { station: this.station });
   };
 
   // Read the 'wifi.enabled' setting in order to start with a known
   // value at boot time. The handle() will be called after reading.
   //
   // nsISettingsServiceCallback implementation.
   var initWifiEnabledCb = {
     handle: function handle(aName, aResult) {
@@ -2506,18 +2506,18 @@ WifiWorker.prototype = {
 
         if (last && last.linkSpeed === info.linkSpeed &&
             last.ipAddress === info.ipAddress &&
             tensPlace(last.relSignalStrength) === tensPlace(info.relSignalStrength)) {
           return;
         }
 
         self._lastConnectionInfo = info;
-        debug("Firing connectionInfoUpdate: " + uneval(info));
-        self._fireEvent("connectionInfoUpdate", info);
+        debug("Firing connectioninfoupdate: " + uneval(info));
+        self._fireEvent("connectioninfoupdate", info);
       });
     }
 
     // Prime our _lastConnectionInfo immediately and fire the event at the
     // same time.
     getConnectionInformation();
 
     // Now, set up the timer for regular updates.
--- a/mobile/android/base/db/BrowserDB.java
+++ b/mobile/android/base/db/BrowserDB.java
@@ -1,23 +1,25 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.db;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.List;
 
 import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
 import org.mozilla.gecko.db.SuggestedSites;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
 import org.mozilla.gecko.mozglue.RobocopTarget;
+import org.mozilla.gecko.util.StringUtils;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.Color;
@@ -30,24 +32,29 @@ public class BrowserDB {
         public static String TITLE = "title";
         public static String FAVICON = "favicon";
         public static String THUMBNAIL = "thumbnail";
         public static String DATE_LAST_VISITED = "date-last-visited";
         public static String VISITS = "visits";
         public static String KEYWORD = "keyword";
     }
 
+    public static enum FilterFlags {
+        EXCLUDE_PINNED_SITES
+    }
+
     private static BrowserDBIface sDb = null;
     private static SuggestedSites sSuggestedSites;
 
     public interface BrowserDBIface {
         public void invalidateCachedState();
 
         @RobocopTarget
-        public Cursor filter(ContentResolver cr, CharSequence constraint, int limit);
+        public Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
+                             EnumSet<FilterFlags> flags);
 
         // This should only return frecent sites. BrowserDB.getTopSites will do the
         // work to combine that list with the pinned sites list.
         public Cursor getTopSites(ContentResolver cr, int limit);
 
         public void updateVisitedHistory(ContentResolver cr, String uri);
 
         public void updateHistoryTitle(ContentResolver cr, String uri, String title);
@@ -171,23 +178,37 @@ public class BrowserDB {
     }
 
     public static void invalidateCachedState() {
         sDb.invalidateCachedState();
     }
 
     @RobocopTarget
     public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
-        return sDb.filter(cr, constraint, limit);
+        return filter(cr, constraint, limit, EnumSet.noneOf(FilterFlags.class));
+    }
+
+    @RobocopTarget
+    public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
+                                EnumSet<FilterFlags> flags) {
+        return sDb.filter(cr, constraint, limit, flags);
     }
 
     private static void appendUrlsFromCursor(List<String> urls, Cursor c) {
         c.moveToPosition(-1);
         while (c.moveToNext()) {
-            urls.add(c.getString(c.getColumnIndex(URLColumns.URL)));
+            String url = c.getString(c.getColumnIndex(URLColumns.URL));
+
+            // Do a simpler check before decoding to avoid parsing
+            // all URLs unnecessarily.
+            if (StringUtils.isUserEnteredUrl(url)) {
+                url = StringUtils.decodeUserEnteredUrl(url);
+            }
+
+            urls.add(url);
         };
     }
 
     public static Cursor getTopSites(ContentResolver cr, int minLimit, int maxLimit) {
         // Note this is not a single query anymore, but actually returns a mixture
         // of two queries, one for topSites and one for pinned sites.
         Cursor pinnedSites = sDb.getPinnedSites(cr, minLimit);
 
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -6,16 +6,17 @@
 package org.mozilla.gecko.db;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -27,16 +28,17 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
 import org.mozilla.gecko.db.BrowserContract.FaviconColumns;
 import org.mozilla.gecko.db.BrowserContract.Favicons;
 import org.mozilla.gecko.db.BrowserContract.History;
 import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
 import org.mozilla.gecko.db.BrowserContract.URLColumns;
+import org.mozilla.gecko.db.BrowserDB.FilterFlags;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
 import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.util.GeckoJarReader;
 
 import android.content.ContentProviderOperation;
@@ -502,27 +504,40 @@ public class LocalBrowserDB implements B
                     cursor.close();
             }
         }
         debug("Got count " + count + " for " + database);
         return count;
     }
 
     @Override
-    public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
+    public Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
+                         EnumSet<FilterFlags> flags) {
+        String selection = "";
+        String[] selectionArgs = null;
+
+        if (flags.contains(FilterFlags.EXCLUDE_PINNED_SITES)) {
+            selection = Combined.URL + " NOT IN (SELECT " +
+                                                 Bookmarks.URL + " FROM bookmarks WHERE " +
+                                                 DBUtils.qualifyColumn("bookmarks", Bookmarks.PARENT) + " = ? AND " +
+                                                 DBUtils.qualifyColumn("bookmarks", Bookmarks.IS_DELETED) + " == 0)";
+            selectionArgs = new String[] { String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) };
+        }
+
         return filterAllSites(cr,
                               new String[] { Combined._ID,
                                              Combined.URL,
                                              Combined.TITLE,
                                              Combined.DISPLAY,
                                              Combined.BOOKMARK_ID,
                                              Combined.HISTORY_ID },
                               constraint,
                               limit,
-                              null);
+                              null,
+                              selection, selectionArgs);
     }
 
     @Override
     public Cursor getTopSites(ContentResolver cr, int limit) {
         // Filter out unvisited bookmarks and the ones that don't have real
         // parents (e.g. pinned sites or reading list items).
         String selection = DBUtils.concatenateWhere(Combined.HISTORY_ID + " <> -1",
                                              Combined.URL + " NOT IN (SELECT " +
--- a/mobile/android/base/home/HomeFragment.java
+++ b/mobile/android/base/home/HomeFragment.java
@@ -191,17 +191,17 @@ abstract class HomeFragment extends Frag
             }
 
             Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.CONTEXT_MENU);
 
             final String url = (info.isInReadingList() ? ReaderModeUtils.getAboutReaderForUrl(info.url) : info.url);
 
             // Some pinned site items have "user-entered" urls. URLs entered in the PinSiteDialog are wrapped in
             // a special URI until we can get a valid URL. If the url is a user-entered url, decode the URL before loading it.
-            final Tab newTab = Tabs.getInstance().loadUrl(decodeUserEnteredUrl(url), flags);
+            final Tab newTab = Tabs.getInstance().loadUrl(StringUtils.decodeUserEnteredUrl(url), flags);
             final int newTabId = newTab.getId(); // We don't want to hold a reference to the Tab.
 
             final String message = isPrivate ?
                     getResources().getString(R.string.new_private_tab_opened) :
                     getResources().getString(R.string.new_tab_opened);
             final String buttonMessage = getResources().getString(R.string.switch_button_message);
             final GeckoApp geckoApp = (GeckoApp) context;
             geckoApp.getButtonToast().show(false,
@@ -270,32 +270,16 @@ abstract class HomeFragment extends Frag
         mCanLoadHint = canLoadHint;
         loadIfVisible();
     }
 
     boolean getCanLoadHint() {
         return mCanLoadHint;
     }
 
-    /**
-     * Given a url with a user-entered scheme, extract the
-     * scheme-specific component. For e.g, given "user-entered://www.google.com",
-     * this method returns "//www.google.com". If the passed url
-     * does not have a user-entered scheme, the same url will be returned.
-     *
-     * @param  url to be decoded
-     * @return url component entered by user
-     */
-    public static String decodeUserEnteredUrl(String url) {
-        Uri uri = Uri.parse(url);
-        if ("user-entered".equals(uri.getScheme())) {
-            return uri.getSchemeSpecificPart();
-        }
-        return url;
-    }
 
     protected abstract void load();
 
     protected boolean canLoad() {
         return (mCanLoadHint && isVisible() && getUserVisibleHint());
     }
 
     protected void loadIfVisible() {
--- a/mobile/android/base/home/PinSiteDialog.java
+++ b/mobile/android/base/home/PinSiteDialog.java
@@ -1,17 +1,21 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
+import java.util.EnumSet;
+
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.db.BrowserDB.FilterFlags;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
+import org.mozilla.gecko.util.StringUtils;
 
 import android.content.Context;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.support.v4.app.DialogFragment;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
@@ -106,17 +110,17 @@ class PinSiteDialog extends DialogFragme
                 if (keyCode != KeyEvent.KEYCODE_ENTER || mOnSiteSelectedListener == null) {
                     return false;
                 }
 
                 // If the user manually entered a search term or URL, wrap the value in
                 // a special URI until we can get a valid URL for this bookmark.
                 final String text = mSearch.getText().toString().trim();
                 if (!TextUtils.isEmpty(text)) {
-                    final String url = TopSitesPanel.encodeUserEnteredUrl(text);
+                    final String url = StringUtils.encodeUserEnteredUrl(text);
                     mOnSiteSelectedListener.onSiteSelected(url, text);
                     dismiss();
                 }
 
                 return true;
             }
         });
 
@@ -186,17 +190,19 @@ class PinSiteDialog extends DialogFragme
     }
 
     public void setSearchTerm(String searchTerm) {
         mSearchTerm = searchTerm;
     }
 
     private void filter(String searchTerm) {
         // Restart loaders with the new search term
-        SearchLoader.restart(getLoaderManager(), LOADER_ID_SEARCH, mLoaderCallbacks, searchTerm);
+        SearchLoader.restart(getLoaderManager(), LOADER_ID_SEARCH,
+                             mLoaderCallbacks, searchTerm,
+                             EnumSet.of(FilterFlags.EXCLUDE_PINNED_SITES));
     }
 
     public void setOnSiteSelectedListener(OnSiteSelectedListener listener) {
         mOnSiteSelectedListener = listener;
     }
 
     private static class SearchAdapter extends CursorAdapter {
         private LayoutInflater mInflater;
--- a/mobile/android/base/home/SearchLoader.java
+++ b/mobile/android/base/home/SearchLoader.java
@@ -1,17 +1,20 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
+import java.util.EnumSet;
+
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.db.BrowserDB.FilterFlags;
 
 import android.content.Context;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
@@ -19,66 +22,87 @@ import android.util.Log;
 
 /**
  * Encapsulates the implementation of the search cursor loader.
  */
 class SearchLoader {
     public static final String LOGTAG = "GeckoSearchLoader";
 
     private static final String KEY_SEARCH_TERM = "search_term";
+    private static final String KEY_FILTER_FLAGS = "flags";
 
     private SearchLoader() {
     }
 
+    @SuppressWarnings("unchecked")
     public static Loader<Cursor> createInstance(Context context, Bundle args) {
         if (args != null) {
             final String searchTerm = args.getString(KEY_SEARCH_TERM);
-            return new SearchCursorLoader(context, searchTerm);
+            final EnumSet<FilterFlags> flags =
+                    (EnumSet<FilterFlags>) args.getSerializable(KEY_FILTER_FLAGS);
+            return new SearchCursorLoader(context, searchTerm, flags);
         } else {
-            return new SearchCursorLoader(context, "");
+            return new SearchCursorLoader(context, "", EnumSet.noneOf(FilterFlags.class));
         }
     }
 
-    private static Bundle createArgs(String searchTerm) {
+    private static Bundle createArgs(String searchTerm, EnumSet<FilterFlags> flags) {
         Bundle args = new Bundle();
         args.putString(SearchLoader.KEY_SEARCH_TERM, searchTerm);
+        args.putSerializable(SearchLoader.KEY_FILTER_FLAGS, flags);
 
         return args;
     }
 
     public static void init(LoaderManager manager, int loaderId,
-                               LoaderCallbacks<Cursor> callbacks, String searchTerm) {
-        final Bundle args = createArgs(searchTerm);
+                            LoaderCallbacks<Cursor> callbacks, String searchTerm) {
+        init(manager, loaderId, callbacks, searchTerm, EnumSet.noneOf(FilterFlags.class));
+    }
+
+    public static void init(LoaderManager manager, int loaderId,
+                            LoaderCallbacks<Cursor> callbacks, String searchTerm,
+                            EnumSet<FilterFlags> flags) {
+        final Bundle args = createArgs(searchTerm, flags);
         manager.initLoader(loaderId, args, callbacks);
     }
 
     public static void restart(LoaderManager manager, int loaderId,
                                LoaderCallbacks<Cursor> callbacks, String searchTerm) {
-        final Bundle args = createArgs(searchTerm);
+        restart(manager, loaderId, callbacks, searchTerm, EnumSet.noneOf(FilterFlags.class));
+    }
+
+    public static void restart(LoaderManager manager, int loaderId,
+                               LoaderCallbacks<Cursor> callbacks, String searchTerm,
+                               EnumSet<FilterFlags> flags) {
+        final Bundle args = createArgs(searchTerm, flags);
         manager.restartLoader(loaderId, args, callbacks);
     }
 
     public static class SearchCursorLoader extends SimpleCursorLoader {
         private static final String TELEMETRY_HISTOGRAM_LOAD_CURSOR = "FENNEC_SEARCH_LOADER_TIME_MS";
 
         // Max number of search results
         private static final int SEARCH_LIMIT = 100;
 
         // The target search term associated with the loader
         private final String mSearchTerm;
 
-        public SearchCursorLoader(Context context, String searchTerm) {
+        // The filter flags associated with the loader
+        private final EnumSet<FilterFlags> mFlags;
+
+        public SearchCursorLoader(Context context, String searchTerm, EnumSet<FilterFlags> flags) {
             super(context);
             mSearchTerm = searchTerm;
+            mFlags = flags;
         }
 
         @Override
         public Cursor loadCursor() {
             final long start = SystemClock.uptimeMillis();
-            final Cursor cursor = BrowserDB.filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT);
+            final Cursor cursor = BrowserDB.filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT, mFlags);
             final long end = SystemClock.uptimeMillis();
             final long took = end - start;
             Telemetry.HistogramAdd(TELEMETRY_HISTOGRAM_LOAD_CURSOR, (int) Math.min(took, Integer.MAX_VALUE));
             return cursor;
         }
 
         public String getSearchTerm() {
             return mSearchTerm;
--- a/mobile/android/base/home/TopSitesGridItemView.java
+++ b/mobile/android/base/home/TopSitesGridItemView.java
@@ -131,19 +131,18 @@ public class TopSitesGridItemView extend
 
         mUrl = url;
         updateTitleView();
     }
 
     public void blankOut() {
         mUrl = "";
         mTitle = "";
-        mType = TopSites.TYPE_BLANK;
+        updateType(TopSites.TYPE_BLANK);
         updateTitleView();
-        mTitleView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
         setLoadId(Favicons.NOT_LOADING);
         Picasso.with(getContext()).cancelRequest(mThumbnailView);
         displayThumbnail(R.drawable.top_site_add);
 
     }
 
     public void markAsDirty() {
         mIsDirty = true;
@@ -177,22 +176,17 @@ public class TopSitesGridItemView extend
         }
 
         if (changed) {
             updateTitleView();
             setLoadId(Favicons.NOT_LOADING);
             Picasso.with(getContext()).cancelRequest(mThumbnailView);
         }
 
-        if (mType != type) {
-            mType = type;
-
-            int pinResourceId = (type == TopSites.TYPE_PINNED ? R.drawable.pin : 0); 
-            mTitleView.setCompoundDrawablesWithIntrinsicBounds(pinResourceId, 0, 0, 0);
-
+        if (updateType(type)) {
             changed = true;
         }
 
         // The dirty state forces the state update to return true
         // so that the adapter loads favicons once the thumbnails
         // are loaded in TopSitesPanel/TopSitesGridAdapter.
         changed = (changed || mIsDirty);
         mIsDirty = false;
@@ -287,28 +281,43 @@ public class TopSitesGridItemView extend
 
         if (mFaviconURL != null) {
             final int bgColor = Favicons.getFaviconColor(mFaviconURL);
             mThumbnailView.setBackgroundColorWithOpacityFilter(bgColor);
         }
     }
 
     /**
+     * Update the item type associated with this view. Returns true if
+     * the type has changed, false otherwise.
+     */
+    private boolean updateType(int type) {
+        if (mType == type) {
+            return false;
+        }
+
+        mType = type;
+        refreshDrawableState();
+
+        int pinResourceId = (type == TopSites.TYPE_PINNED ? R.drawable.pin : 0);
+        mTitleView.setCompoundDrawablesWithIntrinsicBounds(pinResourceId, 0, 0, 0);
+
+        return true;
+    }
+
+    /**
      * Update the title shown by this view. If both title and url
      * are empty, mark the state as STATE_EMPTY and show a default text.
      */
     private void updateTitleView() {
         String title = getTitle();
         if (!TextUtils.isEmpty(title)) {
             mTitleView.setText(title);
         } else {
             mTitleView.setText(R.string.home_top_sites_add);
         }
-
-        // Refresh for state change.
-        refreshDrawableState();
     }
 
     public void setLoadId(int aLoadId) {
         Favicons.cancelFaviconLoad(mLoadId);
         mLoadId = aLoadId;
     }
 }
--- a/mobile/android/base/home/TopSitesGridView.java
+++ b/mobile/android/base/home/TopSitesGridView.java
@@ -9,16 +9,17 @@ import java.util.EnumSet;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.ThumbnailHelper;
 import org.mozilla.gecko.db.BrowserContract.TopSites;
 import org.mozilla.gecko.db.TopSitesCursorWrapper;
 import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
+import org.mozilla.gecko.util.StringUtils;
 
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.database.Cursor;
 import android.graphics.Rect;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -101,17 +102,17 @@ public class TopSitesGridView extends Gr
         super.onAttachedToWindow();
 
         setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 TopSitesGridItemView item = (TopSitesGridItemView) view;
 
                 // Decode "user-entered" URLs before loading them.
-                String url = HomeFragment.decodeUserEnteredUrl(item.getUrl());
+                String url = StringUtils.decodeUserEnteredUrl(item.getUrl());
                 int type = item.getType();
 
                 // If the url is empty, the user can pin a site.
                 // If not, navigate to the page given by the url.
                 if (type != TopSites.TYPE_BLANK) {
                     if (mUrlOpenListener != null) {
                         final TelemetryContract.Method method;
                         if (type == TopSites.TYPE_SUGGESTED) {
--- a/mobile/android/base/home/TopSitesPanel.java
+++ b/mobile/android/base/home/TopSitesPanel.java
@@ -351,17 +351,18 @@ public class TopSitesPanel extends HomeF
 
             Telemetry.sendUIEvent(TelemetryContract.Event.UNPIN);
 
             return true;
         }
 
         if (itemId == R.id.top_sites_edit) {
             // Decode "user-entered" URLs before showing them.
-            mEditPinnedSiteListener.onEditPinnedSite(info.position, decodeUserEnteredUrl(info.url));
+            mEditPinnedSiteListener.onEditPinnedSite(info.position,
+                                                     StringUtils.decodeUserEnteredUrl(info.url));
 
             Telemetry.sendUIEvent(TelemetryContract.Event.EDIT);
             return true;
         }
 
         return false;
     }
 
@@ -373,20 +374,16 @@ public class TopSitesPanel extends HomeF
         // visited, we want to load it as quickly as possible. Heavy load on
         // the Gecko thread can slow down the time it takes for thumbnails to
         // appear, especially during startup (bug 897162). By minimizing the
         // Gecko thread priority, we ensure that the UI appears quickly. The
         // priority is reset to normal once thumbnails are loaded.
         ThreadUtils.reduceGeckoPriority(PRIORITY_RESET_TIMEOUT);
     }
 
-    static String encodeUserEnteredUrl(String url) {
-        return Uri.fromParts("user-entered", url, null).toString();
-    }
-
     /**
      * Listener for editing pinned sites.
      */
     private class EditPinnedSiteListener implements OnEditPinnedSiteListener,
                                                     OnSiteSelectedListener {
         // Tag for the PinSiteDialog fragment.
         private static final String TAG_PIN_SITE = "pin_site";
 
@@ -553,21 +550,24 @@ public class TopSitesPanel extends HomeF
             // Thumbnails are delivered late, so we can't short-circuit any
             // sooner than this. But we can avoid a duplicate favicon
             // fetch...
             if (!updated) {
                 debug("bindView called twice for same values; short-circuiting.");
                 return;
             }
 
+            // Make sure we query suggested images without the user-entered wrapper.
+            final String decodedUrl = StringUtils.decodeUserEnteredUrl(url);
+
             // Suggested images have precedence over thumbnails, no need to wait
             // for them to be loaded. See: CursorLoaderCallbacks.onLoadFinished()
-            final String imageUrl = BrowserDB.getSuggestedImageUrlForUrl(url);
+            final String imageUrl = BrowserDB.getSuggestedImageUrlForUrl(decodedUrl);
             if (!TextUtils.isEmpty(imageUrl)) {
-                final int bgColor = BrowserDB.getSuggestedBackgroundColorForUrl(url);
+                final int bgColor = BrowserDB.getSuggestedBackgroundColorForUrl(decodedUrl);
                 view.displayThumbnail(imageUrl, bgColor);
                 return;
             }
 
             // If thumbnails are still being loaded, don't try to load favicons
             // just yet. If we sent in a thumbnail, we're done now.
             if (mThumbnails == null || thumbnail != null) {
                 return;
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -350,17 +350,17 @@
   <string name="bookmarkdefaults_url_aboutfirefox">about:firefox</string>
   <string name="bookmarkdefaults_favicon_aboutfirefox">chrome/chrome/content/branding/favicon64.png</string>
 
   <!-- Icon is automatically generated from R.drawable.bookmarkdefaults_favicon_addons -->
   <string name="bookmarkdefaults_title_addons">@bookmarks_addons@</string>
   <string name="bookmarkdefaults_url_addons">https://addons.mozilla.org/@AB_CD@/android/</string>
 
   <string name="bookmarkdefaults_title_support">@bookmarks_support@</string>
-  <string name="bookmarkdefaults_url_support">http://support.mozilla.org/@AB_CD@/products/mobile</string>
+  <string name="bookmarkdefaults_url_support">https://support.mozilla.org/@AB_CD@/products/mobile</string>
   <string name="bookmarkdefaults_favicon_abouthome">chrome/chrome/content/branding/favicon64.png</string>
 
   <!-- Icon is automatically generated from R.drawable.bookmarkdefaults_favicon_marketplace -->
   <string name="bookmarkdefaults_title_marketplace">@bookmarks_marketplace@</string>
   <string name="bookmarkdefaults_url_marketplace">https://marketplace.firefox.com/</string>
 
   <!-- Site identity popup -->
   <string name="identity_connected_to">&identity_connected_to;</string>
--- a/mobile/android/base/tests/StringHelper.java
+++ b/mobile/android/base/tests/StringHelper.java
@@ -5,17 +5,17 @@ public class StringHelper {
     // Note: DEFAULT_BOOKMARKS_TITLES.length == DEFAULT_BOOKMARKS_URLS.length
     public static final String[] DEFAULT_BOOKMARKS_TITLES = new String[] {
         "Firefox: About your browser",
         "Firefox: Support",
         "Firefox: Customize with add-ons"
     };
     public static final String[] DEFAULT_BOOKMARKS_URLS = new String[] {
         "about:firefox",
-        "http://support.mozilla.org/en-US/products/mobile",
+        "https://support.mozilla.org/en-US/products/mobile",
         "https://addons.mozilla.org/en-US/android/"
     };
     public static final int DEFAULT_BOOKMARKS_COUNT = DEFAULT_BOOKMARKS_TITLES.length;
 
     // About pages
     public static final String ABOUT_BLANK_URL = "about:blank";
     public static final String ABOUT_FIREFOX_URL = "about:firefox";
     public static final String ABOUT_DOWNLOADS_URL = "about:downloads";
--- a/mobile/android/base/tests/testBrowserProviderPerf.java
+++ b/mobile/android/base/tests/testBrowserProviderPerf.java
@@ -1,19 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tests;
 
 import java.io.File;
+import java.util.EnumSet;
 import java.util.Random;
 import java.util.UUID;
 
 import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.db.BrowserDB.FilterFlags;
 import org.mozilla.gecko.db.BrowserProvider;
 import org.mozilla.gecko.db.LocalBrowserDB;
 import org.mozilla.gecko.util.FileUtils;
 
 import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -265,17 +267,18 @@ public class testBrowserProviderPerf ext
      */
     public void testBrowserProviderQueryPerf() throws Exception {
         // We add at least this many results.
         final int limit = 100;
 
         // Make sure we're querying the right profile.
         final LocalBrowserDB db = new LocalBrowserDB(mProfile);
 
-        final Cursor before = db.filter(mResolver, KNOWN_PREFIX, limit);
+        final Cursor before = db.filter(mResolver, KNOWN_PREFIX, limit,
+                                        EnumSet.noneOf(FilterFlags.class));
         try {
             mAsserter.is(before.getCount(), 0, "Starts empty");
         } finally {
             before.close();
         }
 
         // Add data.
         loadMobileFolderId();
@@ -290,17 +293,18 @@ public class testBrowserProviderPerf ext
         // * Adjusting the provider interface to allow a "don't notify" param.
         // * Adjusting the interface schema to include the profile in the path,
         //   and only observe the correct path.
         // * Launching a different activity.
         Thread.sleep(5000);
 
         // Time the query.
         final long start = SystemClock.uptimeMillis();
-        final Cursor c = db.filter(mResolver, KNOWN_PREFIX, limit);
+        final Cursor c = db.filter(mResolver, KNOWN_PREFIX, limit,
+                                   EnumSet.noneOf(FilterFlags.class));
 
         try {
             final int count = c.getCount();
             final long end = SystemClock.uptimeMillis();
 
             mAsserter.is(count, limit, "Retrieved results");
             mAsserter.dumpLog("Results: " + count);
             mAsserter.dumpLog("__start_report" + Long.toString(end - start) + "__end_report");
--- a/mobile/android/base/util/StringUtils.java
+++ b/mobile/android/base/util/StringUtils.java
@@ -6,16 +6,17 @@
 package org.mozilla.gecko.util;
 
 import android.net.Uri;
 import android.text.TextUtils;
 
 public class StringUtils {
 
     private static final String FILTER_URL_PREFIX = "filter://";
+    private static final String USER_ENTERED_URL_PREFIX = "user-entered:";
 
     /*
      * This method tries to guess if the given string could be a search query or URL,
      * and returns a previous result if there is ambiguity
      *
      * Search examples:
      *  foo
      *  foo bar.com
@@ -155,9 +156,34 @@ public class StringUtils {
         return url.substring(FILTER_URL_PREFIX.length());
     }
 
     public static boolean isShareableUrl(final String url) {
         final String scheme = Uri.parse(url).getScheme();
         return !("about".equals(scheme) || "chrome".equals(scheme) ||
                 "file".equals(scheme) || "resource".equals(scheme));
     }
+
+    public static boolean isUserEnteredUrl(String url) {
+        return (url != null && url.startsWith(USER_ENTERED_URL_PREFIX));
+    }
+
+    /**
+     * Given a url with a user-entered scheme, extract the
+     * scheme-specific component. For e.g, given "user-entered://www.google.com",
+     * this method returns "//www.google.com". If the passed url
+     * does not have a user-entered scheme, the same url will be returned.
+     *
+     * @param  url to be decoded
+     * @return url component entered by user
+     */
+    public static String decodeUserEnteredUrl(String url) {
+        Uri uri = Uri.parse(url);
+        if ("user-entered".equals(uri.getScheme())) {
+            return uri.getSchemeSpecificPart();
+        }
+        return url;
+    }
+
+    public static String encodeUserEnteredUrl(String url) {
+        return Uri.fromParts("user-entered", url, null).toString();
+    }
 }
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -1022,37 +1022,40 @@ this.PlacesUtils = {
 
   /**
    * Returns true if a container has uri nodes in its first level.
    * Has better performance than (getURLsForContainerNode(node).length > 0).
    * @param aNode
    *        The container node to search through.
    * @returns true if the node contains uri nodes, false otherwise.
    */
-  hasChildURIs: function PU_hasChildURIs(aNode) {
+  hasChildURIs: function PU_hasChildURIs(aNode, aMultiple=false) {
     if (!this.nodeIsContainer(aNode))
       return false;
 
     let root = this.getContainerNodeWithOptions(aNode, false, true);
     let result = root.parentResult;
     let didSuppressNotifications = false;
     let wasOpen = root.containerOpen;
     if (!wasOpen) {
       didSuppressNotifications = result.suppressNotifications;
       if (!didSuppressNotifications)
         result.suppressNotifications = true;
 
       root.containerOpen = true;
     }
 
+    let foundFirst = !aMultiple;
     let found = false;
     for (let i = 0; i < root.childCount && !found; i++) {
       let child = root.getChild(i);
-      if (this.nodeIsURI(child))
-        found = true;
+      if (this.nodeIsURI(child)) {
+        found = foundFirst;
+        foundFirst = true;
+      }
     }
 
     if (!wasOpen) {
       root.containerOpen = false;
       if (!didSuppressNotifications)
         result.suppressNotifications = false;
     }
     return found;
--- a/toolkit/components/places/tests/unit/test_utils_getURLsForContainerNode.js
+++ b/toolkit/components/places/tests/unit/test_utils_getURLsForContainerNode.js
@@ -160,16 +160,17 @@ function() {
  *         number of expected uri nodes
  */
 function check_uri_nodes(aQuery, aOptions, aExpectedURINodes) {
   var result = hs.executeQuery(aQuery, aOptions);
   var root = result.root;
   root.containerOpen = true;
   var node = root.getChild(0);
   do_check_eq(PU.hasChildURIs(node), aExpectedURINodes > 0);
+  do_check_eq(PU.hasChildURIs(node, true), aExpectedURINodes > 1);
   do_check_eq(PU.getURLsForContainerNode(node).length, aExpectedURINodes);
   root.containerOpen = false;
 }
 
 function run_test() {
   tests.forEach(function(aTest) {
                   remove_all_bookmarks();
                   aTest();
--- a/toolkit/devtools/gcli/commands/screenshot.js
+++ b/toolkit/devtools/gcli/commands/screenshot.js
@@ -119,16 +119,18 @@ exports.items = [
             let lh = new LayoutHelpers(window);
             let rect = lh.getRect(node, window);
             top = rect.top;
             left = rect.left;
             width = rect.width;
             height = rect.height;
           }
         } else {
+          // Bug 961832: GCLI screenshot shows fixed position element in wrong position if
+          // we don't scroll to top
           window.scrollTo(0,0);
           width = window.innerWidth + window.scrollMaxX;
           height = window.innerHeight + window.scrollMaxY;
         }
         canvas.width = width;
         canvas.height = height;
 
         let ctx = canvas.getContext("2d");
--- a/toolkit/devtools/server/actors/framerate.js
+++ b/toolkit/devtools/server/actors/framerate.js
@@ -44,42 +44,50 @@ let FramerateActor = exports.FramerateAc
   startRecording: method(function() {
     if (this._recording) {
       return;
     }
     this._recording = true;
     this._ticks = [];
 
     this._startTime = this._chromeWin.performance.now();
-    this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
+    this._rafID = this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
   }, {
   }),
 
   /**
    * Stops monitoring framerate, returning the recorded values.
    */
   stopRecording: method(function(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
     if (!this._recording) {
       return [];
     }
-    this._recording = false;
-
-    // We don't need to store the ticks array for future use, release it.
     let ticks = this.getPendingTicks(beginAt, endAt);
-    this._ticks = null;
+    this.cancelRecording();
     return ticks;
   }, {
     request: {
       beginAt: Arg(0, "nullable:number"),
       endAt: Arg(1, "nullable:number")
     },
     response: { ticks: RetVal("array:number") }
   }),
 
   /**
+   * Stops monitoring framerate, without returning the recorded values.
+   */
+  cancelRecording: method(function() {
+    this._chromeWin.cancelAnimationFrame(this._rafID);
+    this._recording = false;
+    this._ticks = null;
+    this._rafID = -1;
+  }, {
+  }),
+
+  /**
    * Gets the refresh driver ticks recorded so far.
    */
   getPendingTicks: method(function(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
     if (!this._ticks) {
       return [];
     }
     return this._ticks.filter(e => e >= beginAt && e <= endAt);
   }, {
@@ -92,84 +100,83 @@ let FramerateActor = exports.FramerateAc
 
   /**
    * Function invoked along with the refresh driver.
    */
   _onRefreshDriverTick: function() {
     if (!this._recording) {
       return;
     }
-    this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
+    this._rafID = this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
 
     // Store the amount of time passed since the recording started.
     let currentTime = this._chromeWin.performance.now();
     let elapsedTime = currentTime - this._startTime;
     this._ticks.push(elapsedTime);
   }
 });
 
 /**
  * The corresponding Front object for the FramerateActor.
  */
 let FramerateFront = exports.FramerateFront = protocol.FrontClass(FramerateActor, {
   initialize: function(client, { framerateActor }) {
     protocol.Front.prototype.initialize.call(this, client, { actor: framerateActor });
     this.manage(this);
-  },
-
-  /**
-   * Plots the frames per second on a timeline.
-   *
-   * @param array ticks
-   *        The raw data received from the framerate actor, which represents
-   *        the elapsed time on each refresh driver tick.
-   * @param number interval
-   *        The maximum amount of time to wait between calculations.
-   * @param number clamp
-   *        The maximum allowed framerate value.
-   * @return array
-   *         A collection of { delta, value } objects representing the
-   *         framerate value at every delta time.
-   */
-  plotFPS: function(ticks, interval = 100, clamp = 60) {
-    let timeline = [];
-    let totalTicks = ticks.length;
-
-    // If the refresh driver didn't get a chance to tick before the
-    // recording was stopped, assume framerate was 0.
-    if (totalTicks == 0) {
-      timeline.push({ delta: 0, value: 0 });
-      timeline.push({ delta: interval, value: 0 });
-      return timeline;
-    }
-
-    let frameCount = 0;
-    let prevTime = ticks[0];
-
-    for (let i = 1; i < totalTicks; i++) {
-      let currTime = ticks[i];
-      frameCount++;
-
-      let elapsedTime = currTime - prevTime;
-      if (elapsedTime < interval) {
-        continue;
-      }
-
-      let framerate = Math.min(1000 / (elapsedTime / frameCount), clamp);
-      timeline.push({ delta: prevTime, value: framerate });
-      timeline.push({ delta: currTime, value: framerate });
-
-      frameCount = 0;
-      prevTime = currTime;
-    }
-
-    return timeline;
   }
 });
 
+/**
+ * Plots the frames per second on a timeline.
+ *
+ * @param array ticks
+ *        The raw data received from the framerate actor, which represents
+ *        the elapsed time on each refresh driver tick.
+ * @param number interval
+ *        The maximum amount of time to wait between calculations.
+ * @param number clamp
+ *        The maximum allowed framerate value.
+ * @return array
+ *         A collection of { delta, value } objects representing the
+ *         framerate value at every delta time.
+ */
+FramerateFront.plotFPS = function(ticks, interval = 100, clamp = 60) {
+  let timeline = [];
+  let totalTicks = ticks.length;
+
+  // If the refresh driver didn't get a chance to tick before the
+  // recording was stopped, assume framerate was 0.
+  if (totalTicks == 0) {
+    timeline.push({ delta: 0, value: 0 });
+    timeline.push({ delta: interval, value: 0 });
+    return timeline;
+  }
+
+  let frameCount = 0;
+  let prevTime = ticks[0];
+
+  for (let i = 1; i < totalTicks; i++) {
+    let currTime = ticks[i];
+    frameCount++;
+
+    let elapsedTime = currTime - prevTime;
+    if (elapsedTime < interval) {
+      continue;
+    }
+
+    let framerate = Math.min(1000 / (elapsedTime / frameCount), clamp);
+    timeline.push({ delta: prevTime, value: framerate });
+    timeline.push({ delta: currTime, value: framerate });
+
+    frameCount = 0;
+    prevTime = currTime;
+  }
+
+  return timeline;
+};
 
 /**
  * Gets the top level browser window from a content window.
  *
  * @param nsIDOMWindow innerWin
  *        The content window to query.
  * @return nsIDOMWindow
  *         The top level browser window.
--- a/toolkit/devtools/server/actors/layout.js
+++ b/toolkit/devtools/server/actors/layout.js
@@ -271,16 +271,22 @@ LayoutChangesObserver.prototype = Herita
   },
 
   /**
    * Start the event loop, which regularly checks if there are any observer
    * events to be sent as batched events
    * Calls itself in a loop.
    */
   _startEventLoop: function() {
+    // Avoid emitting events if the tabActor has been detached (may happen
+    // during shutdown)
+    if (!this.tabActor.attached) {
+      return;
+    }
+
     // Send any reflows we have
     if (this.reflows && this.reflows.length) {
       this.emit("reflows", this.reflows);
       this.reflows = [];
     }
     this.eventLoopTimer = this._setTimeout(this._startEventLoop,
       this.EVENT_BATCHING_DELAY);
   },
--- a/toolkit/devtools/server/actors/script.js
+++ b/toolkit/devtools/server/actors/script.js
@@ -493,17 +493,18 @@ function ThreadActor(aHooks, aGlobal)
   this._hiddenBreakpoints = new Map();
 
   this.findGlobals = this.globalManager.findGlobals.bind(this);
   this.onNewGlobal = this.globalManager.onNewGlobal.bind(this);
   this.onNewSource = this.onNewSource.bind(this);
   this._allEventsListener = this._allEventsListener.bind(this);
 
   this._options = {
-    useSourceMaps: false
+    useSourceMaps: false,
+    autoBlackBox: false
   };
 
   this._gripDepth = 0;
   this._threadLifetimePool = null;
   this._tabClosed = false;
 }
 
 /**
@@ -531,17 +532,17 @@ ThreadActor.prototype = {
       this.conn.addActorPool(this._threadLifetimePool);
       this._threadLifetimePool.objectActors = new WeakMap();
     }
     return this._threadLifetimePool;
   },
 
   get sources() {
     if (!this._sources) {
-      this._sources = new ThreadSources(this, this._options.useSourceMaps,
+      this._sources = new ThreadSources(this, this._options,
                                         this._allowSource, this.onNewSource);
     }
     return this._sources;
   },
 
   get youngestFrame() {
     if (this.state != "paused") {
       return null;
@@ -4962,20 +4963,21 @@ update(AddonThreadActor.prototype, {
 });
 
 exports.AddonThreadActor = AddonThreadActor;
 
 /**
  * Manages the sources for a thread. Handles source maps, locations in the
  * sources, etc for ThreadActors.
  */
-function ThreadSources(aThreadActor, aUseSourceMaps, aAllowPredicate,
+function ThreadSources(aThreadActor, aOptions, aAllowPredicate,
                        aOnNewSource) {
   this._thread = aThreadActor;
-  this._useSourceMaps = aUseSourceMaps;
+  this._useSourceMaps = aOptions.useSourceMaps;
+  this._autoBlackBox = aOptions.autoBlackBox;
   this._allow = aAllowPredicate;
   this._onNewSource = aOnNewSource;
 
   // generated source url --> promise of SourceMapConsumer
   this._sourceMapsByGeneratedSource = Object.create(null);
   // original source url --> promise of SourceMapConsumer
   this._sourceMapsByOriginalSource = Object.create(null);
   // source url --> SourceActor
@@ -4986,16 +4988,23 @@ function ThreadSources(aThreadActor, aUs
 
 /**
  * Must be a class property because it needs to persist across reloads, same as
  * the breakpoint store.
  */
 ThreadSources._blackBoxedSources = new Set(["self-hosted"]);
 ThreadSources._prettyPrintedSources = new Map();
 
+/**
+ * Matches strings of the form "foo.min.js" or "foo-min.js", etc. If the regular
+ * expression matches, we can be fairly sure that the source is minified, and
+ * treat it as such.
+ */
+const MINIFIED_SOURCE_REGEXP = /\bmin\.js$/;
+
 ThreadSources.prototype = {
   /**
    * Return the source actor representing |url|, creating one if none
    * exists already. Returns null if |url| is not allowed by the 'allow'
    * predicate.
    *
    * Right now this takes a URL, but in the future it should
    * take a Debugger.Source. See bug 637572.
@@ -5017,16 +5026,20 @@ ThreadSources.prototype = {
     if (!this._allow(url)) {
       return null;
     }
 
     if (url in this._sourceActors) {
       return this._sourceActors[url];
     }
 
+    if (this._autoBlackBox && this._isMinifiedURL(url)) {
+      this.blackBox(url);
+    }
+
     let actor = new SourceActor({
       url: url,
       thread: this._thread,
       sourceMap: sourceMap,
       generatedSource: generatedSource,
       text: text,
       contentType: contentType
     });
@@ -5036,16 +5049,36 @@ ThreadSources.prototype = {
       this._onNewSource(actor);
     } catch (e) {
       reportError(e);
     }
     return actor;
   },
 
   /**
+   * Returns true if the URL likely points to a minified resource, false
+   * otherwise.
+   *
+   * @param String aURL
+   *        The URL to test.
+   * @returns Boolean
+   */
+  _isMinifiedURL: function (aURL) {
+    try {
+      let url = Services.io.newURI(aURL, null, null)
+                           .QueryInterface(Ci.nsIURL);
+      return MINIFIED_SOURCE_REGEXP.test(url.fileName);
+    } catch (e) {
+      // Not a valid URL so don't try to parse out the filename, just test the
+      // whole thing with the minified source regexp.
+      return MINIFIED_SOURCE_REGEXP.test(aURL);
+    }
+  },
+
+  /**
    * Only to be used when we aren't source mapping.
    */
   _sourceForScript: function (aScript) {
     const spec = {
       url: aScript.url
     };
 
     // XXX bug 915433: We can't rely on Debugger.Source.prototype.text if the
@@ -5177,17 +5210,17 @@ ThreadSources.prototype = {
 
   /**
    * Returns a promise of the location in the original source if the source is
    * source mapped, otherwise a promise of the same location.
    */
   getOriginalLocation: function ({ url, line, column }) {
     if (url in this._sourceMapsByGeneratedSource) {
       column = column || 0;
-      
+
       return this._sourceMapsByGeneratedSource[url]
         .then((aSourceMap) => {
           let { source: aSourceURL, line: aLine, column: aColumn } = aSourceMap.originalPositionFor({
             line: line,
             column: column
           });
           return {
             url: aSourceURL,
--- a/toolkit/devtools/server/actors/tracer.js
+++ b/toolkit/devtools/server/actors/tracer.js
@@ -313,17 +313,17 @@ TraceActor.prototype = {
   },
 
   // JS Debugger API hooks.
 
   /**
    * Called by the engine when a frame is entered. Sends an unsolicited packet
    * to the client carrying requested trace information.
    *
-   * @param aFrame Debugger.frame
+   * @param aFrame Debugger.Frame
    *        The stack frame that was entered.
    */
   onEnterFrame: function(aFrame) {
     if (aFrame.script && aFrame.script.url == "self-hosted") {
       return;
     }
 
     let packet = {
--- a/toolkit/devtools/server/tests/mochitest/chrome.ini
+++ b/toolkit/devtools/server/tests/mochitest/chrome.ini
@@ -18,16 +18,17 @@ support-files =
 [test_Debugger.Script.prototype.global.html]
 [test_connection-manager.html]
 [test_css-logic.html]
 [test_device.html]
 [test_framerate_01.html]
 [test_framerate_02.html]
 [test_framerate_03.html]
 [test_framerate_04.html]
+[test_framerate_05.html]
 [test_highlighter-boxmodel_01.html]
 [test_highlighter-boxmodel_02.html]
 [test_highlighter-csstransform_01.html]
 [test_highlighter-csstransform_02.html]
 [test_highlighter-csstransform_03.html]
 [test_inspector-changeattrs.html]
 [test_inspector-changevalue.html]
 [test_inspector-hide.html]
--- a/toolkit/devtools/server/tests/mochitest/test_framerate_01.html
+++ b/toolkit/devtools/server/tests/mochitest/test_framerate_01.html
@@ -53,17 +53,17 @@ window.onload = function() {
         });
       }, 1000);
     });
   });
 
   function onRecordingStopped(front, rawData) {
     ok(rawData, "There should be a recording available.");
 
-    var timeline = front.plotFPS(rawData);
+    var timeline = FramerateFront.plotFPS(rawData);
     ok(timeline.length >= 2,
       "There should be at least one measurement available, with two entries.");
 
     var prevTimeStart = timeline[0].delta;
 
     for (var i = 0; i < timeline.length; i += 2) {
       var currTimeStart = timeline[i].delta;
       var currTimeEnd = timeline[i + 1].delta;
--- a/toolkit/devtools/server/tests/mochitest/test_framerate_02.html
+++ b/toolkit/devtools/server/tests/mochitest/test_framerate_02.html
@@ -42,17 +42,17 @@ window.onload = function() {
     client.listTabs(function onListTabs(aResponse) {
       var form = aResponse.tabs[aResponse.selected];
       var front = FramerateFront(client, form);
 
       front.stopRecording().then(rawData => {
         ok(rawData, "There should be a recording available.");
         is(rawData.length, 0, "...but it should be empty.");
 
-        var timeline = front.plotFPS(rawData);
+        var timeline = FramerateFront.plotFPS(rawData);
         is(timeline.length, 2,
           "There should be one measurement plotted, with two entries.");
 
         info("The framerate should be assumed to be 0 if the recording is empty.");
 
         is(timeline[0].delta, 0,
           "The first time delta should be 0.");
         is(timeline[0].value, 0,
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/mochitest/test_framerate_05.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Bug 1034648 - Tests whether a framerate recording can be cancelled.
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Framerate actor test</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script>
+
+window.onload = function() {
+  var Cu = Components.utils;
+  var Cc = Components.classes;
+  var Ci = Components.interfaces;
+
+  Cu.import("resource://gre/modules/Services.jsm");
+
+  // Always log packets when running tests.
+  Services.prefs.setBoolPref("devtools.debugger.log", true);
+  SimpleTest.registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("devtools.debugger.log");
+  });
+
+  Cu.import("resource://gre/modules/devtools/Loader.jsm");
+  Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
+  Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
+
+  SimpleTest.waitForExplicitFinish();
+
+  var {FramerateFront} = devtools.require("devtools/server/actors/framerate");
+
+  DebuggerServer.init(function () { return true; });
+  DebuggerServer.addBrowserActors();
+
+  var client = new DebuggerClient(DebuggerServer.connectPipe());
+  client.connect(function onConnect() {
+    client.listTabs(function onListTabs(aResponse) {
+      var form = aResponse.tabs[aResponse.selected];
+      var front = FramerateFront(client, form);
+
+      front.startRecording().then(() => {
+        window.setTimeout(() => {
+          front.cancelRecording().then(() => {
+            window.setTimeout(() => {
+              front.getPendingTicks().then(rawTicks => {
+                ok(rawTicks,
+                  "The returned pending ticks should be empty (1).");
+                is(rawTicks.length, 0,
+                  "The returned pending ticks should be empty (2).");
+
+                front.stopRecording().then(rawData => {
+                  ok(rawData,
+                    "The returned raw data should be an empty array (1).");
+                  is(rawData.length, 0,
+                    "The returned raw data should be an empty array (2).");
+
+                  client.close(() => {
+                    DebuggerServer.destroy();
+                    SimpleTest.finish()
+                  });
+                });
+              });
+            }, 1000);
+          });
+        }, 1000);
+      });
+    });
+  });
+}
+</script>
+</pre>
+</body>
+</html>
--- a/toolkit/devtools/server/tests/unit/head_dbg.js
+++ b/toolkit/devtools/server/tests/unit/head_dbg.js
@@ -173,17 +173,20 @@ function attachTestTab(aClient, aTitle, 
 // that tab's thread. Pass |aCallback| the thread attach response packet, a
 // TabClient referring to the tab, and a ThreadClient referring to the
 // thread.
 function attachTestThread(aClient, aTitle, aCallback) {
   attachTestTab(aClient, aTitle, function (aResponse, aTabClient) {
     function onAttach(aResponse, aThreadClient) {
       aCallback(aResponse, aTabClient, aThreadClient);
     }
-    aTabClient.attachThread({ useSourceMaps: true }, onAttach);
+    aTabClient.attachThread({
+      useSourceMaps: true,
+      autoBlackBox: true
+    }, onAttach);
   });
 }
 
 // Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's
 // thread, and then resume it. Pass |aCallback| the thread's response to
 // the 'resume' packet, a TabClient for the tab, and a ThreadClient for the
 // thread.
 function attachTestTabAndResume(aClient, aTitle, aCallback) {
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/unit/test_blackboxing-07.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that sources whose URL ends with ".min.js" automatically get black
+ * boxed.
+ */
+
+var gDebuggee;
+var gClient;
+var gThreadClient;
+
+function run_test()
+{
+  initTestDebuggerServer();
+  gDebuggee = addTestGlobal("test-black-box");
+  gClient = new DebuggerClient(DebuggerServer.connectPipe());
+  gClient.connect(function() {
+    attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
+      gThreadClient = aThreadClient;
+      testBlackBox();
+    });
+  });
+  do_test_pending();
+}
+
+const BLACK_BOXED_URL = "http://example.com/black-boxed.min.js";
+const SOURCE_URL = "http://example.com/source.js";
+
+const testBlackBox = Task.async(function* () {
+  yield executeOnNextTickAndWaitForPause(evalCode, gClient);
+
+  const { sources } = yield getSources(gThreadClient);
+  equal(sources.length, 2);
+
+  const blackBoxedSource = sources.filter(s => s.url === BLACK_BOXED_URL)[0];
+  equal(blackBoxedSource.isBlackBoxed, true);
+
+  const regularSource = sources.filter(s => s.url === SOURCE_URL)[0];
+  equal(regularSource.isBlackBoxed, false);
+
+  finishClient(gClient);
+});
+
+function evalCode() {
+  Components.utils.evalInSandbox(
+    "" + function blackBoxed() {},
+    gDebuggee,
+    "1.8",
+    BLACK_BOXED_URL,
+    1
+  );
+
+  Components.utils.evalInSandbox(
+    "" + function source() {}
+      + "\ndebugger;",
+    gDebuggee,
+    "1.8",
+    SOURCE_URL,
+    1
+  );
+}
--- a/toolkit/devtools/server/tests/unit/test_layout-reflows-observer.js
+++ b/toolkit/devtools/server/tests/unit/test_layout-reflows-observer.js
@@ -16,16 +16,17 @@ let {
 LayoutChangesObserver.prototype._setTimeout = cb => cb;
 LayoutChangesObserver.prototype._clearTimeout = function() {};
 
 // Mock the tabActor since we only really want to test the LayoutChangesObserver
 // and don't want to depend on a window object, nor want to test protocol.js
 function MockTabActor() {
   this.window = new MockWindow();
   this.windows = [this.window];
+  this.attached = true;
 }
 
 function MockWindow() {}
 MockWindow.prototype = {
   QueryInterface: function() {
     let self = this;
     return {
       getInterface: function() {
--- a/toolkit/devtools/server/tests/unit/xpcshell.ini
+++ b/toolkit/devtools/server/tests/unit/xpcshell.ini
@@ -27,16 +27,17 @@ support-files =
 [test_attach.js]
 [test_reattach-thread.js]
 [test_blackboxing-01.js]
 [test_blackboxing-02.js]
 [test_blackboxing-03.js]
 [test_blackboxing-04.js]
 [test_blackboxing-05.js]
 [test_blackboxing-06.js]
+[test_blackboxing-07.js]
 [test_frameactor-01.js]
 [test_frameactor-02.js]
 [test_frameactor-03.js]
 [test_frameactor-04.js]
 [test_frameactor-05.js]
 [test_framearguments-01.js]
 [test_pauselifetime-01.js]
 [test_pauselifetime-02.js]