Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 21 Apr 2015 12:38:27 +0200
changeset 240167 b8d59286a581795934ca38a566b07d00d6a5e180
parent 240166 a81b76a677aff7273c0556eac273cf7e6b28a4cc (current diff)
parent 240128 3de89bd361c3c68adc7b959823e34d5ca29abf2d (diff)
child 240168 41cda3ce8c9809c54211a6dafb04810320446198
child 240198 94df0a4a500642a12d92b0db37565a56af5e57f7
child 240212 2df6451d16bb25e6697425c944ae671bdc42ec96
child 240292 3576be34a78eaf95625b90ffebafee2af93a84b5
push id28623
push usercbook@mozilla.com
push dateTue, 21 Apr 2015 13:17:41 +0000
treeherdermozilla-central@b8d59286a581 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone40.0a1
first release with
nightly mac
b8d59286a581 / 40.0a1 / 20150421062453 / files
nightly linux32
nightly linux64
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly mac
Merge mozilla-central to mozilla-inbound
--- a/addon-sdk/source/test/tabs/test-firefox-tabs.js
+++ b/addon-sdk/source/test/tabs/test-firefox-tabs.js
@@ -366,39 +366,40 @@ exports.testTabMove = function(assert, d
         assert.equal(tab.index, 0, "tab index after move matches");
         close(window).then(done).then(null, assert.fail);
       }
     });
   }).then(null, assert.fail);
 };
 
 exports.testIgnoreClosing = function(assert, done) {
-  let originalWindow = browserWindows.activeWindow;
+  let originalWindow = viewFor(browserWindows.activeWindow);
   openBrowserWindow(function(window, browser) {
-    let url = "data:text/html;charset=utf-8,foobar";
+    onFocus(window).then(() => {
+      let url = "data:text/html;charset=utf-8,foobar";
 
-    assert.equal(tabs.length, 2, "should be two windows open each with one tab");
+      assert.equal(tabs.length, 2, "should be two windows open each with one tab");
 
-    tabs.on('ready', function onReady(tab) {
-      tabs.removeListener('ready', onReady);
+      tabs.on('ready', function onReady(tab) {
+        tabs.removeListener('ready', onReady);
 
-      let win = tab.window;
-      assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
-      assert.equal(tabs.length, 3, "should be three tabs in total");
+        let win = tab.window;
+        assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
+        assert.equal(tabs.length, 3, "should be three tabs in total");
 
-      tab.close(function() {
-        assert.equal(win.tabs.length, 1, "should be one tab in the new window");
-        assert.equal(tabs.length, 2, "should be two tabs in total");
+        tab.close(function() {
+          assert.equal(win.tabs.length, 1, "should be one tab in the new window");
+          assert.equal(tabs.length, 2, "should be two tabs in total");
 
-        originalWindow.once("activate", done);
-        close(window);
+          close(window).then(onFocus(originalWindow)).then(done).then(null, assert.fail);
+        });
       });
+
+      tabs.open(url);
     });
-
-    tabs.open(url);
   });
 };
 
 // TEST: open tab with default options
 exports.testOpen = function(assert, done) {
   let url = "data:text/html;charset=utf-8,default";
   tabs.open({
     url: url,
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "a8e4f95dce9db727dda5d408b038f97fb4296557", 
+        "git_revision": "0645bbed4d6cbd8064652eebafe011edc3e417fd", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "b3bc7b2c50201c1110e3f7157d6ed542e52d9355", 
+    "revision": "b8a031b1d0d2dfe6dc33194ec18b25c6f0cd625a", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="6b0721ca0e92788df30daf8f7a5fb2863544f9c8">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a8e4f95dce9db727dda5d408b038f97fb4296557"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0645bbed4d6cbd8064652eebafe011edc3e417fd"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f2f2f0cbee2f2517070dd194051d509c07cdacff"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="c7d4045742862a7cf3f0074902ebc7d1b339b0ee"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -247,17 +247,17 @@ pref("browser.eme.ui.enabled", false);
 
 // UI tour experience.
 pref("browser.uitour.enabled", true);
 pref("browser.uitour.loglevel", "Error");
 pref("browser.uitour.requireSecure", true);
 pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
 pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/");
 // This is used as a regexp match against the page's URL.
-pref("browser.uitour.readerViewTrigger", "^https:\/\/www\.mozilla\.org\/[^\/]+\/firefox\/reading\/start");
+pref("browser.uitour.readerViewTrigger", "^https:\\/\\/www\\.mozilla\\.org\\/[^\\/]+\\/firefox\\/reading\\/start");
 
 pref("browser.customizemode.tip0.shown", false);
 pref("browser.customizemode.tip0.learnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/customize");
 
 pref("keyword.enabled", true);
 pref("browser.fixup.domainwhitelist.localhost", true);
 
 pref("general.useragent.locale", "@AB_CD@");
@@ -1875,22 +1875,19 @@ pref("dom.ipc.processHangMonitor", true)
 #ifdef DEBUG
 // Don't report hangs in DEBUG builds. They're too slow and often a
 // debugger is attached.
 pref("dom.ipc.reportProcessHangs", false);
 #else
 pref("dom.ipc.reportProcessHangs", true);
 #endif
 
-// Enable ReadingList browser UI by default.
-pref("browser.readinglist.enabled", true);
+pref("browser.readinglist.enabled", false);
 pref("browser.readinglist.sidebarEverOpened", false);
-
-// Enable the readinglist engine by default.
-pref("readinglist.scheduler.enabled", true);
+pref("readinglist.scheduler.enabled", false);
 pref("readinglist.server", "https://readinglist.services.mozilla.com/v1");
 
 // Don't limit how many nodes we care about on desktop:
 pref("reader.parse-node-limit", 0);
 
 // Enable Service workers for desktop on non-release builds
 #ifdef NIGHTLY_BUILD
 pref("dom.serviceWorkers.enabled", true);
--- a/browser/components/places/tests/unit/test_leftpane_corruption_handling.js
+++ b/browser/components/places/tests/unit/test_leftpane_corruption_handling.js
@@ -3,40 +3,38 @@
 /* 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/. */
 
 /**
  * Tests that we build a working leftpane in various corruption situations.
  */
 
-function run_test() {
+// Used to store the original leftPaneFolderId getter.
+let gLeftPaneFolderIdGetter;
+let gAllBookmarksFolderIdGetter;
+// Used to store the original left Pane status as a JSON string.
+let gReferenceHierarchy;
+let gLeftPaneFolderId;
+
+add_task(function* () {
   // We want empty roots.
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 
   // Sanity check.
   Assert.ok(!!PlacesUIUtils);
 
   // Check getters.
   gLeftPaneFolderIdGetter = Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId");
   Assert.equal(typeof(gLeftPaneFolderIdGetter.get), "function");
   gAllBookmarksFolderIdGetter = Object.getOwnPropertyDescriptor(PlacesUIUtils, "allBookmarksFolderId");
   Assert.equal(typeof(gAllBookmarksFolderIdGetter.get), "function");
 
-  run_next_test();
-}
-
-do_register_cleanup(remove_all_bookmarks);
-
-// Used to store the original leftPaneFolderId getter.
-let gLeftPaneFolderIdGetter;
-let gAllBookmarksFolderIdGetter;
-// Used to store the original left Pane status as a JSON string.
-let gReferenceHierarchy;
-let gLeftPaneFolderId;
+  do_register_cleanup(() => PlacesUtils.bookmarks.eraseEverything());
+});
 
 add_task(function* () {
   // Add a third party bogus annotated item.  Should not be removed.
   let folder = yield PlacesUtils.bookmarks.insert({
     parentGuid: PlacesUtils.bookmarks.unfiledGuid,
     title: "test",
     index: PlacesUtils.bookmarks.DEFAULT_INDEX,
     type: PlacesUtils.bookmarks.TYPE_FOLDER
--- a/browser/components/readinglist/test/xpcshell/test_scheduler.js
+++ b/browser/components/readinglist/test/xpcshell/test_scheduler.js
@@ -10,16 +10,17 @@ Services.prefs.setCharPref("readinglist.
 let {createTestableScheduler} = Cu.import("resource:///modules/readinglist/Scheduler.jsm", {});
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 
 // Log rotation needs a profile dir.
 do_get_profile();
 
 let prefs = new Preferences("readinglist.scheduler.");
+prefs.set("enabled", true);
 
 function promiseObserver(topic) {
   return new Promise(resolve => {
     let obs = (subject, topic, data) => {
       Services.obs.removeObserver(obs, topic);
       resolve(data);
     }
     Services.obs.addObserver(obs, topic, false);
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -1824,16 +1824,17 @@ MarkupContainer.prototype = {
       return;
     }
 
     // target is the MarkupContainer itself.
     this._isMouseDown = true;
     this.hovered = false;
     this.markup.navigate(this);
     event.stopPropagation();
+    event.preventDefault();
 
     // Start dragging the container after a delay.
     this.markup._dragStartEl = target;
     setTimeout(() => {
       // Make sure the mouse is still down and on target.
       if (!this._isMouseDown || this.markup._dragStartEl !== target ||
           this.node.isPseudoElement || this.node.isAnonymous ||
           !this.win.getSelection().isCollapsed) {
@@ -2140,17 +2141,17 @@ MarkupElementContainer.prototype = Herit
         data.data.string().then(str => {
           let res = {data: str, size: data.size};
           // Resolving the data promise and, to always keep tooltipData.data
           // as a promise, create a new one that resolves immediately
           def.resolve(res);
           this.tooltipData.data = promise.resolve(res);
         });
       }, () => {
-        this.tooltipData.data = promise.reject();
+        this.tooltipData.data = promise.resolve({});
       });
     }
   },
 
   /**
    * Executed by MarkupView._isImagePreviewTarget which is itself called when the
    * mouse hovers over a target in the markup-view.
    * Checks if the target is indeed something we want to have an image tooltip
@@ -2160,19 +2161,21 @@ MarkupElementContainer.prototype = Herit
    * to decide if/when to show the tooltip
    */
   isImagePreviewTarget: function(target, tooltip) {
     if (!this.tooltipData || this.tooltipData.target !== target) {
       return promise.reject();
     }
 
     return this.tooltipData.data.then(({data, size}) => {
-      tooltip.setImageContent(data, size);
-    }, () => {
-      tooltip.setBrokenImageContent();
+      if (data && size) {
+        tooltip.setImageContent(data, size);
+      } else {
+        tooltip.setBrokenImageContent();
+      }
     });
   },
 
   copyImageDataUri: function() {
     // We need to send again a request to gettooltipData even if one was sent for
     // the tooltip, because we want the full-size image
     this.node.getImageData().then(data => {
       data.data.string().then(str => {
--- a/browser/devtools/markupview/test/browser.ini
+++ b/browser/devtools/markupview/test/browser.ini
@@ -63,22 +63,24 @@ skip-if = e10s # Bug 1040751 - CodeMirro
 [browser_markupview_events_jquery_1.6.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_1.7.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_1.11.1.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_2.1.1.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
+[browser_markupview_load_01.js]
 [browser_markupview_html_edit_01.js]
 [browser_markupview_html_edit_02.js]
 [browser_markupview_html_edit_03.js]
 [browser_markupview_image_tooltip.js]
 [browser_markupview_keybindings_01.js]
 [browser_markupview_keybindings_02.js]
+[browser_markupview_keybindings_03.js]
 [browser_markupview_mutation_01.js]
 [browser_markupview_mutation_02.js]
 [browser_markupview_navigation.js]
 [browser_markupview_node_not_displayed_01.js]
 [browser_markupview_node_not_displayed_02.js]
 [browser_markupview_pagesize_01.js]
 [browser_markupview_pagesize_02.js]
 [browser_markupview_remove_xul_attributes.js]
--- a/browser/devtools/markupview/test/browser_markupview_dragdrop_isDragging.js
+++ b/browser/devtools/markupview/test/browser_markupview_dragdrop_isDragging.js
@@ -16,17 +16,18 @@ add_task(function*() {
   let el = yield getContainerForSelector("#test", inspector);
   let rect = el.tagLine.getBoundingClientRect();
 
   info("Simulating mouseDown on #test");
   el._onMouseDown({
     target: el.tagLine,
     pageX: rect.x,
     pageY: rect.y,
-    stopPropagation: function() {}
+    stopPropagation: function() {},
+    preventDefault: function() {}
   });
 
   is(el.isDragging, false, "isDragging should not be set to true immedietly");
 
   info("Waiting " + (GRAB_DELAY + 1) + "ms");
   yield wait(GRAB_DELAY + 1);
   ok(el.isDragging, "isDragging true after GRAB_DELAY has passed");
 
--- a/browser/devtools/markupview/test/browser_markupview_dragdrop_reorder.js
+++ b/browser/devtools/markupview/test/browser_markupview_dragdrop_reorder.js
@@ -59,17 +59,18 @@ function* dragContainer(selector, target
     y: container.tagLine.offsetTop
   };
 
   info("Simulating mouseDown on " + selector);
   container._onMouseDown({
     target: container.tagLine,
     pageX: rect.x,
     pageY: rect.y,
-    stopPropagation: function() {}
+    stopPropagation: function() {},
+    preventDefault: function() {}
   });
 
   let targetX = rect.x + targetOffset.x,
       targetY = rect.y + targetOffset.y;
 
   setTimeout(() => {
     info("Simulating mouseMove on " + selector +
          " with pageX: " + targetX + " pageY: " + targetY);
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.0.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.0.js
@@ -153,26 +153,16 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":894",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "handle: function(event) {\n" +
                  "  if (typeof jQuery == \"undefined\") return;\n" +
@@ -194,16 +184,26 @@ const TEST_DATA = [
                  "    }\n" +
                  "  }\n" +
                  "\n" +
                  "  return returnValue;\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":894",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "handle: function(event) {\n" +
                  "  if (typeof jQuery == \"undefined\") return;\n" +
                  "\n" +
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.1.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.1.js
@@ -167,26 +167,16 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":1224",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "handle: function(event) {\n" +
                  "  if (typeof jQuery == \"undefined\") return false;\n" +
@@ -218,16 +208,26 @@ const TEST_DATA = [
                  "  // Clean up added properties in IE to prevent memory leak\n" +
                  "  if (jQuery.browser.msie) event.target = event.preventDefault = event.stopPropagation = event.handler = event.data = null;\n" +
                  "\n" +
                  "  return returnValue;\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":1224",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "handle: function(event) {\n" +
                  "  if (typeof jQuery == \"undefined\") return false;\n" +
                  "\n" +
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.11.1.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.11.1.js
@@ -99,94 +99,94 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":3",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "k = r.handle = function(a) {\n" +
                  "  return typeof m === K || a && m.event.triggered === a.type ? void 0 : m.event.dispatch.apply(k.elem, arguments)\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":3",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "k = r.handle = function(a) {\n" +
                  "  return typeof m === K || a && m.event.triggered === a.type ? void 0 : m.event.dispatch.apply(k.elem, arguments)\n" +
                  "}"
       }
     ]
   },
 
   {
     selector: "#livediv",
     expected: [
       {
+        type: "dragend",
+        filename: TEST_URL + ":31",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler4 = function liveDivDragEnd() {\n" +
+                 "  alert(4);\n" +
+                 "}"
+      },
+      {
         type: "dragleave",
         filename: TEST_URL + ":30",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "var handler3 = function liveDivDragLeave() {\n" +
                  "  alert(3);\n" +
                  "}"
       },
       {
-        type: "dragend",
-        filename: TEST_URL + ":31",
+        type: "dragover",
+        filename: TEST_URL + ":33",
         attributes: [
           "jQuery",
           "Live"
         ],
-        handler: "var handler4 = function liveDivDragEnd() {\n" +
-                 "  alert(4);\n" +
+        handler: "var handler6 = function liveDivDragOver() {\n" +
+                 "  alert(6);\n" +
                  "}"
       },
       {
         type: "drop",
         filename: TEST_URL + ":32",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "var handler5 = function liveDivDrop() {\n" +
                  "  alert(5);\n" +
                  "}"
-      },
-      {
-        type: "dragover",
-        filename: TEST_URL + ":33",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler6 = function liveDivDragOver() {\n" +
-                 "  alert(6);\n" +
-                 "}"
       }
     ]
   },
 ];
 
 add_task(runEventPopupTests);
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.2.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.2.js
@@ -138,41 +138,41 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":24",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function() {\n" +
                  "  var val;\n" +
                  "  if (typeof jQuery == \"undefined\" || jQuery.event.triggered) return val;\n" +
                  "  val = jQuery.event.handle.apply(element, arguments);\n" +
                  "  return val;\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":24",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function() {\n" +
                  "  var val;\n" +
                  "  if (typeof jQuery == \"undefined\" || jQuery.event.triggered) return val;\n" +
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.3.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.3.js
@@ -12,27 +12,16 @@ const TEST_URL = TEST_URL_ROOT + "doc_ma
 
 loadHelperScript("helper_events_test_runner.js");
 
 const TEST_DATA = [
   {
     selector: "html",
     expected: [
       {
-        type: "unload",
-        filename: TEST_URL_ROOT + TEST_LIB + ":19",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "function(H) {\n" +
-                 "  n(this).unbind(H, D);\n" +
-                 "  return (E || G).apply(this, arguments)\n" +
-                 "}"
-      },
-      {
         type: "load",
         filename: TEST_URL_ROOT + TEST_LIB + ":19",
         attributes: [
           "jQuery"
         ],
         handler: "ready: function() {\n" +
                  "  if (!n.isReady) {\n" +
                  "    n.isReady = true;\n" +
@@ -103,28 +92,39 @@ const TEST_DATA = [
                  "\n" +
                  "  var div = $(\"div\")[0];\n" +
                  "  $(div).click(handler7);\n" +
                  "  $(div).click(handler8);\n" +
                  "  $(div).keydown(handler9);\n" +
                  "}"
       },
       {
-        type: "unload",
+        type: "load",
         filename: TEST_URL_ROOT + TEST_LIB + ":19",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function() {\n" +
                  "  return typeof n !== \"undefined\" && !n.event.triggered ? n.event.handle.apply(arguments.callee.elem, arguments) : g\n" +
                  "}"
       },
       {
-        type: "load",
+        type: "unload",
+        filename: TEST_URL_ROOT + TEST_LIB + ":19",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "function(H) {\n" +
+                 "  n(this).unbind(H, D);\n" +
+                 "  return (E || G).apply(this, arguments)\n" +
+                 "}"
+      },
+      {
+        type: "unload",
         filename: TEST_URL_ROOT + TEST_LIB + ":19",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function() {\n" +
                  "  return typeof n !== \"undefined\" && !n.event.triggered ? n.event.handle.apply(arguments.callee.elem, arguments) : g\n" +
                  "}"
@@ -150,38 +150,38 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":19",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function() {\n" +
                  "  return typeof n !== \"undefined\" && !n.event.triggered ? n.event.handle.apply(arguments.callee.elem, arguments) : g\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":19",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function() {\n" +
                  "  return typeof n !== \"undefined\" && !n.event.triggered ? n.event.handle.apply(arguments.callee.elem, arguments) : g\n" +
                  "}"
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.4.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.4.js
@@ -117,38 +117,38 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":48",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "j = function() {\n" +
                  "  return typeof c !== \"undefined\" && !c.event.triggered ? c.event.handle.apply(j.elem, arguments) : w\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":48",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "j = function() {\n" +
                  "  return typeof c !== \"undefined\" && !c.event.triggered ? c.event.handle.apply(j.elem, arguments) : w\n" +
                  "}"
@@ -165,27 +165,16 @@ const TEST_DATA = [
           "jQuery",
           "Live"
         ],
         handler: "var handler1 = function liveDivDblClick() {\n" +
                  "  alert(1);\n" +
                  "}"
       },
       {
-        type: "dragstart",
-        filename: TEST_URL + ":29",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler2 = function liveDivDragStart() {\n" +
-                 "  alert(2);\n" +
-                 "}"
-      },
-      {
         type: "dblclick",
         filename: TEST_URL_ROOT + TEST_LIB + ":17",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "function qa(a) {\n" +
                  "  var b = true,\n" +
@@ -225,16 +214,27 @@ const TEST_DATA = [
                  "      break\n" +
                  "    }\n" +
                  "  }\n" +
                  "  return b\n" +
                  "}"
       },
       {
         type: "dragstart",
+        filename: TEST_URL + ":29",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler2 = function liveDivDragStart() {\n" +
+                 "  alert(2);\n" +
+                 "}"
+      },
+      {
+        type: "dragstart",
         filename: TEST_URL_ROOT + TEST_LIB + ":17",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "function qa(a) {\n" +
                  "  var b = true,\n" +
                  "    d = [],\n" +
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.6.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.6.js
@@ -114,38 +114,38 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":16",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "i.handle = k = function(a) {\n" +
                  "  return typeof f != \"undefined\" && (!a || f.event.triggered !== a.type) ? f.event.handle.apply(k.elem, arguments) : b\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":16",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "i.handle = k = function(a) {\n" +
                  "  return typeof f != \"undefined\" && (!a || f.event.triggered !== a.type) ? f.event.handle.apply(k.elem, arguments) : b\n" +
                  "}"
@@ -162,49 +162,16 @@ const TEST_DATA = [
           "jQuery",
           "Live"
         ],
         handler: "var handler1 = function liveDivDblClick() {\n" +
                  "  alert(1);\n" +
                  "}"
       },
       {
-        type: "dragstart",
-        filename: TEST_URL + ":29",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler2 = function liveDivDragStart() {\n" +
-                 "  alert(2);\n" +
-                 "}"
-      },
-      {
-        type: "dragleave",
-        filename: TEST_URL + ":30",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler3 = function liveDivDragLeave() {\n" +
-                 "  alert(3);\n" +
-                 "}"
-      },
-      {
-        type: "dragend",
-        filename: TEST_URL + ":31",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler4 = function liveDivDragEnd() {\n" +
-                 "  alert(4);\n" +
-                 "}"
-      },
-      {
         type: "dblclick",
         filename: TEST_URL_ROOT + TEST_LIB + ":16",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "function M(a) {\n" +
                  "  var b, c, d, e, g, h, i, j, k, l, m, n, o, p = [],\n" +
@@ -239,17 +206,28 @@ const TEST_DATA = [
                  "        if (a.isImmediatePropagationStopped()) break\n" +
                  "      }\n" +
                  "    }\n" +
                  "    return b\n" +
                  "  }\n" +
                  "}"
       },
       {
-        type: "dragstart",
+        type: "dragend",
+        filename: TEST_URL + ":31",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler4 = function liveDivDragEnd() {\n" +
+                 "  alert(4);\n" +
+                 "}"
+      },
+      {
+        type: "dragend",
         filename: TEST_URL_ROOT + TEST_LIB + ":16",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "function M(a) {\n" +
                  "  var b, c, d, e, g, h, i, j, k, l, m, n, o, p = [],\n" +
                  "    q = [],\n" +
@@ -284,16 +262,27 @@ const TEST_DATA = [
                  "      }\n" +
                  "    }\n" +
                  "    return b\n" +
                  "  }\n" +
                  "}"
       },
       {
         type: "dragleave",
+        filename: TEST_URL + ":30",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler3 = function liveDivDragLeave() {\n" +
+                 "  alert(3);\n" +
+                 "}"
+      },
+      {
+        type: "dragleave",
         filename: TEST_URL_ROOT + TEST_LIB + ":16",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "function M(a) {\n" +
                  "  var b, c, d, e, g, h, i, j, k, l, m, n, o, p = [],\n" +
                  "    q = [],\n" +
@@ -327,17 +316,28 @@ const TEST_DATA = [
                  "        if (a.isImmediatePropagationStopped()) break\n" +
                  "      }\n" +
                  "    }\n" +
                  "    return b\n" +
                  "  }\n" +
                  "}"
       },
       {
-        type: "dragend",
+        type: "dragstart",
+        filename: TEST_URL + ":29",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler2 = function liveDivDragStart() {\n" +
+                 "  alert(2);\n" +
+                 "}"
+      },
+      {
+        type: "dragstart",
         filename: TEST_URL_ROOT + TEST_LIB + ":16",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "function M(a) {\n" +
                  "  var b, c, d, e, g, h, i, j, k, l, m, n, o, p = [],\n" +
                  "    q = [],\n" +
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_1.7.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_1.7.js
@@ -114,38 +114,38 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":3",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "h.handle = i = function(a) {\n" +
                  "  return typeof f != \"undefined\" && (!a || f.event.triggered !== a.type) ? f.event.dispatch.apply(i.elem, arguments) : b\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":3",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "h.handle = i = function(a) {\n" +
                  "  return typeof f != \"undefined\" && (!a || f.event.triggered !== a.type) ? f.event.dispatch.apply(i.elem, arguments) : b\n" +
                  "}"
@@ -162,67 +162,67 @@ const TEST_DATA = [
           "jQuery",
           "Live"
         ],
         handler: "var handler1 = function liveDivDblClick() {\n" +
                  "  alert(1);\n" +
                  "}"
       },
       {
-        type: "dragstart",
-        filename: TEST_URL + ":29",
+        type: "dragend",
+        filename: TEST_URL + ":31",
         attributes: [
           "jQuery",
           "Live"
         ],
-        handler: "var handler2 = function liveDivDragStart() {\n" +
-                 "  alert(2);\n" +
+        handler: "var handler4 = function liveDivDragEnd() {\n" +
+                 "  alert(4);\n" +
                  "}"
       },
       {
         type: "dragleave",
         filename: TEST_URL + ":30",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "var handler3 = function liveDivDragLeave() {\n" +
                  "  alert(3);\n" +
                  "}"
       },
       {
-        type: "dragend",
-        filename: TEST_URL + ":31",
+        type: "dragover",
+        filename: TEST_URL + ":33",
         attributes: [
           "jQuery",
           "Live"
         ],
-        handler: "var handler4 = function liveDivDragEnd() {\n" +
-                 "  alert(4);\n" +
+        handler: "var handler6 = function liveDivDragOver() {\n" +
+                 "  alert(6);\n" +
+                 "}"
+      },
+      {
+        type: "dragstart",
+        filename: TEST_URL + ":29",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler2 = function liveDivDragStart() {\n" +
+                 "  alert(2);\n" +
                  "}"
       },
       {
         type: "drop",
         filename: TEST_URL + ":32",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "var handler5 = function liveDivDrop() {\n" +
                  "  alert(5);\n" +
                  "}"
-      },
-      {
-        type: "dragover",
-        filename: TEST_URL + ":33",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler6 = function liveDivDragOver() {\n" +
-                 "  alert(6);\n" +
-                 "}"
       }
     ]
   },
 ];
 
 add_task(runEventPopupTests);
--- a/browser/devtools/markupview/test/browser_markupview_events_jquery_2.1.1.js
+++ b/browser/devtools/markupview/test/browser_markupview_events_jquery_2.1.1.js
@@ -98,93 +98,93 @@ const TEST_DATA = [
         attributes: [
           "jQuery"
         ],
         handler: "var handler8 = function divClick2() {\n" +
                  "  alert(8);\n" +
                  "}"
       },
       {
-        type: "keydown",
-        filename: TEST_URL + ":36",
-        attributes: [
-          "jQuery"
-        ],
-        handler: "var handler9 = function divKeyDown() {\n" +
-                 "  alert(9);\n" +
-                 "}"
-      },
-      {
         type: "click",
         filename: TEST_URL_ROOT + TEST_LIB + ":3",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "g = r.handle = function(b) {\n" +
                  "  return typeof n !== U && n.event.triggered !== b.type ? n.event.dispatch.apply(a, arguments) : void 0\n" +
                  "}"
       },
       {
         type: "keydown",
+        filename: TEST_URL + ":36",
+        attributes: [
+          "jQuery"
+        ],
+        handler: "var handler9 = function divKeyDown() {\n" +
+                 "  alert(9);\n" +
+                 "}"
+      },
+      {
+        type: "keydown",
         filename: TEST_URL_ROOT + TEST_LIB + ":3",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "g = r.handle = function(b) {\n" +
                  "  return typeof n !== U && n.event.triggered !== b.type ? n.event.dispatch.apply(a, arguments) : void 0\n" +
                  "}"
       }
     ]
   },
   {
     selector: "#livediv",
     expected: [
       {
+        type: "dragend",
+        filename: TEST_URL + ":31",
+        attributes: [
+          "jQuery",
+          "Live"
+        ],
+        handler: "var handler4 = function liveDivDragEnd() {\n" +
+                 "  alert(4);\n" +
+                 "}"
+      },
+      {
         type: "dragleave",
         filename: TEST_URL + ":30",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "var handler3 = function liveDivDragLeave() {\n" +
                  "  alert(3);\n" +
                  "}"
       },
       {
-        type: "dragend",
-        filename: TEST_URL + ":31",
+        type: "dragover",
+        filename: TEST_URL + ":33",
         attributes: [
           "jQuery",
           "Live"
         ],
-        handler: "var handler4 = function liveDivDragEnd() {\n" +
-                 "  alert(4);\n" +
+        handler: "var handler6 = function liveDivDragOver() {\n" +
+                 "  alert(6);\n" +
                  "}"
       },
       {
         type: "drop",
         filename: TEST_URL + ":32",
         attributes: [
           "jQuery",
           "Live"
         ],
         handler: "var handler5 = function liveDivDrop() {\n" +
                  "  alert(5);\n" +
                  "}"
-      },
-      {
-        type: "dragover",
-        filename: TEST_URL + ":33",
-        attributes: [
-          "jQuery",
-          "Live"
-        ],
-        handler: "var handler6 = function liveDivDragOver() {\n" +
-                 "  alert(6);\n" +
-                 "}"
       }
     ]
   },
 ];
 
 add_task(runEventPopupTests);
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_keybindings_03.js
@@ -0,0 +1,34 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that selecting a node with the mouse (by clicking on the line) focuses
+// the first focusable element in the corresponding MarkupContainer so that the
+// keyboard can be used immediately.
+
+const TEST_URL = "data:text/html;charset=utf8,<div></div>Text node";
+
+add_task(function*() {
+  let {inspector, toolbox} = yield addTab(TEST_URL).then(openInspector);
+  let {walker} = inspector;
+
+  info("Select the test node to have the 2 test containers visible");
+  yield selectNode("div", inspector);
+
+  let divFront = yield walker.querySelector(walker.rootNode, "div");
+  let textFront = yield walker.nextSibling(divFront);
+
+  info("Click on the MarkupContainer element for the text node");
+  yield clickContainer(textFront, inspector);
+  is(inspector.markup.doc.activeElement,
+     getContainerForNodeFront(textFront, inspector).editor.value,
+     "The currently focused element is the node's text content");
+
+  info("Click on the MarkupContainer element for the <div> node");
+  yield clickContainer(divFront, inspector);
+  is(inspector.markup.doc.activeElement,
+     getContainerForNodeFront(divFront, inspector).editor.tag,
+     "The currently focused element is the div's tagname");
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_load_01.js
@@ -0,0 +1,70 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that selecting an element with the 'Inspect Element' context
+// menu during a page reload doesn't cause the markup view to become empty.
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=1036324
+
+const server = createTestHTTPServer();
+
+// Register a slow image handler so we can simulate a long time between
+// a reload and the load event firing.
+server.registerContentType("gif", "image/gif");
+server.registerPathHandler("/slow.gif", function (metadata, response) {
+  info ("Image has been requested");
+  response.processAsync();
+  setTimeout(() => {
+    info ("Image is responding");
+    response.finish();
+  }, 500);
+});
+
+// Test page load events.
+const TEST_URL = "data:text/html," +
+  "<!DOCTYPE html>" +
+  "<head><meta charset='utf-8' /></head>" +
+  "<body>" +
+  "<p>Slow script</p>" +
+  "<img src='http://localhost:" + server.identity.primaryPort + "/slow.gif' /></script>" +
+  "</body>" +
+  "</html>";
+
+add_task(function*() {
+  let tab = yield addTab(TEST_URL);
+  let {inspector} = yield openInspector();
+  let domContentLoaded = waitForLinkedBrowserEvent(tab, "DOMContentLoaded");
+  let pageLoaded = waitForLinkedBrowserEvent(tab, "load");
+
+  ok (inspector.markup, "There is a markup view");
+
+  // Select an element while the tab is in the middle of a slow reload.
+  reloadTab();
+  yield domContentLoaded;
+  yield chooseWithInspectElementContextMenu("img");
+  yield pageLoaded;
+
+  yield inspector.once("markuploaded");
+  ok (inspector.markup, "There is a markup view");
+  is (inspector.markup._elt.children.length, 1, "The markup view is rendering");
+});
+
+function* chooseWithInspectElementContextMenu(selector) {
+  yield executeInContent("Test:SynthesizeMouse", {
+    center: true,
+    selector: selector,
+    options: {type: "contextmenu", button: 2}
+  });
+  executeInContent("Test:SynthesizeKey", {key: "Q", options: {}});
+}
+
+function waitForLinkedBrowserEvent(tab, event) {
+  let def = promise.defer();
+  tab.linkedBrowser.addEventListener(event, function cb() {
+    tab.linkedBrowser.removeEventListener(event, cb, true);
+    def.resolve();
+  }, true);
+  return def.promise;
+}
--- a/browser/devtools/markupview/test/head.js
+++ b/browser/devtools/markupview/test/head.js
@@ -168,16 +168,23 @@ function executeInContent(name, data={},
   if (expectResponse) {
     return waitForContentMessage(name);
   } else {
     return promise.resolve();
   }
 }
 
 /**
+ * Reload the current tab location.
+ */
+function reloadTab() {
+  return executeInContent("devtools:test:reload", {}, {}, false);
+}
+
+/**
  * Simple DOM node accesor function that takes either a node or a string css
  * selector as argument and returns the corresponding node
  * @param {String|DOMNode} nodeOrSelector
  * @return {DOMNode|CPOW} Note that in e10s mode a CPOW object is returned which
  * doesn't implement *all* of the DOMNode's properties
  */
 function getNode(nodeOrSelector) {
   info("Getting the node for '" + nodeOrSelector + "'");
@@ -642,8 +649,39 @@ function* waitForMultipleChildrenUpdates
   // As long as child updates are queued up while we wait for an update already
   // wait again
   if (inspector.markup._queuedChildUpdates &&
       inspector.markup._queuedChildUpdates.size) {
     yield waitForChildrenUpdated(inspector);
     return yield waitForMultipleChildrenUpdates(inspector);
   }
 }
+
+/**
+ * Create an HTTP server that can be used to simulate custom requests within
+ * a test.  It is automatically cleaned up when the test ends, so no need to
+ * call `destroy`.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Httpd.js/HTTP_server_for_unit_tests
+ * for more information about how to register handlers.
+ *
+ * The server can be accessed like:
+ *
+ *   const server = createTestHTTPServer();
+ *   let url = "http://localhost: " + server.identity.primaryPort + "/path";
+ *
+ * @returns {HttpServer}
+ */
+function createTestHTTPServer() {
+  const {HttpServer} = Cu.import("resource://testing-common/httpd.js", {});
+  let server = new HttpServer();
+
+  registerCleanupFunction(function* cleanup() {
+    let destroyed = promise.defer();
+    server.stop(() => {
+      destroyed.resolve();
+    });
+    yield destroyed.promise;
+  });
+
+  server.start(-1);
+  return server;
+}
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -1225,16 +1225,17 @@ RequestsMenuView.prototype = Heritage.ex
           case "responseCookies":
             requestItem.attachment.responseCookies = value;
             break;
           case "httpVersion":
             requestItem.attachment.httpVersion = value;
             break;
           case "remoteAddress":
             requestItem.attachment.remoteAddress = value;
+            this.updateMenuView(requestItem, key, value);
             break;
           case "remotePort":
             requestItem.attachment.remotePort = value;
             break;
           case "status":
             requestItem.attachment.status = value;
             this.updateMenuView(requestItem, key, value);
             break;
@@ -1377,16 +1378,21 @@ RequestsMenuView.prototype = Heritage.ex
         file.setAttribute("value", nameWithQuery);
         file.setAttribute("tooltiptext", nameWithQuery);
 
         let domain = $(".requests-menu-domain", target);
         domain.setAttribute("value", hostPort);
         domain.setAttribute("tooltiptext", hostPort);
         break;
       }
+      case "remoteAddress":
+        let domain = $(".requests-menu-domain", target);
+        let tooltip = domain.getAttribute("value") + " (" + aValue + ")";
+        domain.setAttribute("tooltiptext", tooltip);
+        break;
       case "securityState": {
         let tooltip = L10N.getStr("netmonitor.security.state." + aValue);
         let icon = $(".requests-security-state-icon", target);
         icon.classList.add("security-state-" + aValue);
         icon.setAttribute("tooltiptext", tooltip);
 
         this.attachSecurityIconClickListener(aItem);
         break;
--- a/browser/devtools/netmonitor/test/head.js
+++ b/browser/devtools/netmonitor/test/head.js
@@ -270,100 +270,103 @@ function verifyRequestItemTarget(aReques
 
   let { fuzzyUrl, status, statusText, type, fullMimeType, transferred, size, time } = aData;
   let { attachment, target } = aRequestItem
 
   let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
   let name = uri.fileName || "/";
   let query = uri.query;
   let hostPort = uri.hostPort;
+  let remoteAddress = attachment.remoteAddress;
 
   if (fuzzyUrl) {
-    ok(attachment.method.startsWith(aMethod), "The attached method is incorrect.");
-    ok(attachment.url.startsWith(aUrl), "The attached url is incorrect.");
+    ok(attachment.method.startsWith(aMethod), "The attached method is correct.");
+    ok(attachment.url.startsWith(aUrl), "The attached url is correct.");
   } else {
-    is(attachment.method, aMethod, "The attached method is incorrect.");
-    is(attachment.url, aUrl, "The attached url is incorrect.");
+    is(attachment.method, aMethod, "The attached method is correct.");
+    is(attachment.url, aUrl, "The attached url is correct.");
   }
 
   is(target.querySelector(".requests-menu-method").getAttribute("value"),
-    aMethod, "The displayed method is incorrect.");
+    aMethod, "The displayed method is correct.");
 
   if (fuzzyUrl) {
     ok(target.querySelector(".requests-menu-file").getAttribute("value").startsWith(
-      name + (query ? "?" + query : "")), "The displayed file is incorrect.");
+      name + (query ? "?" + query : "")), "The displayed file is correct.");
     ok(target.querySelector(".requests-menu-file").getAttribute("tooltiptext").startsWith(
-      name + (query ? "?" + query : "")), "The tooltip file is incorrect.");
+      name + (query ? "?" + query : "")), "The tooltip file is correct.");
   } else {
     is(target.querySelector(".requests-menu-file").getAttribute("value"),
-      name + (query ? "?" + query : ""), "The displayed file is incorrect.");
+      name + (query ? "?" + query : ""), "The displayed file is correct.");
     is(target.querySelector(".requests-menu-file").getAttribute("tooltiptext"),
-      name + (query ? "?" + query : ""), "The tooltip file is incorrect.");
+      name + (query ? "?" + query : ""), "The tooltip file is correct.");
   }
 
   is(target.querySelector(".requests-menu-domain").getAttribute("value"),
-    hostPort, "The displayed domain is incorrect.");
+    hostPort, "The displayed domain is correct.");
+
+  let domainTooltip = hostPort + (remoteAddress ? " (" + remoteAddress + ")" : "");
   is(target.querySelector(".requests-menu-domain").getAttribute("tooltiptext"),
-    hostPort, "The tooltip domain is incorrect.");
+    domainTooltip, "The tooltip domain is correct.");
 
   if (status !== undefined) {
     let value = target.querySelector(".requests-menu-status").getAttribute("code");
     let codeValue = target.querySelector(".requests-menu-status-code").getAttribute("value");
     let tooltip = target.querySelector(".requests-menu-status-and-method").getAttribute("tooltiptext");
     info("Displayed status: " + value);
     info("Displayed code: " + codeValue);
     info("Tooltip status: " + tooltip);
-    is(value, status, "The displayed status is incorrect.");
-    is(codeValue, status, "The displayed status code is incorrect.");
-    is(tooltip, status + " " + statusText, "The tooltip status is incorrect.");
+    is(value, status, "The displayed status is correct.");
+    is(codeValue, status, "The displayed status code is correct.");
+    is(tooltip, status + " " + statusText, "The tooltip status is correct.");
   }
   if (type !== undefined) {
     let value = target.querySelector(".requests-menu-type").getAttribute("value");
     let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext");
     info("Displayed type: " + value);
     info("Tooltip type: " + tooltip);
-    is(value, type, "The displayed type is incorrect.");
-    is(tooltip, fullMimeType, "The tooltip type is incorrect.");
+    is(value, type, "The displayed type is correct.");
+    is(tooltip, fullMimeType, "The tooltip type is correct.");
   }
   if (transferred !== undefined) {
     let value = target.querySelector(".requests-menu-transferred").getAttribute("value");
     let tooltip = target.querySelector(".requests-menu-transferred").getAttribute("tooltiptext");
     info("Displayed transferred size: " + value);
     info("Tooltip transferred size: " + tooltip);
-    is(value, transferred, "The displayed transferred size is incorrect.");
-    is(tooltip, transferred, "The tooltip transferred size is incorrect.");
+    is(value, transferred, "The displayed transferred size is correct.");
+    is(tooltip, transferred, "The tooltip transferred size is correct.");
   }
   if (size !== undefined) {
     let value = target.querySelector(".requests-menu-size").getAttribute("value");
     let tooltip = target.querySelector(".requests-menu-size").getAttribute("tooltiptext");
     info("Displayed size: " + value);
     info("Tooltip size: " + tooltip);
-    is(value, size, "The displayed size is incorrect.");
-    is(tooltip, size, "The tooltip size is incorrect.");
+    is(value, size, "The displayed size is correct.");
+    is(tooltip, size, "The tooltip size is correct.");
   }
   if (time !== undefined) {
     let value = target.querySelector(".requests-menu-timings-total").getAttribute("value");
     let tooltip = target.querySelector(".requests-menu-timings-total").getAttribute("tooltiptext");
     info("Displayed time: " + value);
     info("Tooltip time: " + tooltip);
-    ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect.");
-    ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is incorrect.");
+    ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is correct.");
+    ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is correct.");
   }
 
   if (visibleIndex != -1) {
     if (visibleIndex % 2 == 0) {
       ok(aRequestItem.target.hasAttribute("even"),
-        "Unexpected 'even' attribute for " + aRequestItem.value);
+        aRequestItem.value + " should have 'even' attribute.");
       ok(!aRequestItem.target.hasAttribute("odd"),
-        "Unexpected 'odd' attribute for " + aRequestItem.value);
+        aRequestItem.value + " shouldn't have 'odd' attribute.");
     } else {
       ok(!aRequestItem.target.hasAttribute("even"),
-        "Unexpected 'even' attribute for " + aRequestItem.value);
+        aRequestItem.value + " shouldn't have 'even' attribute.");
       ok(aRequestItem.target.hasAttribute("odd"),
-        "Unexpected 'odd' attribute for " + aRequestItem.value);
+        aRequestItem.value + " should have 'odd' attribute.");
     }
   }
 }
 
 /**
  * Helper function for waiting for an event to fire before resolving a promise.
  * Example: waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.TAB_UPDATED);
  *
--- a/browser/devtools/shared/frame-script-utils.js
+++ b/browser/devtools/shared/frame-script-utils.js
@@ -1,18 +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/. */
 
 "use strict";
-const Cu = Components.utils;
-
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 devtools.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
 devtools.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm", "Task");
+const loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
+            .getService(Ci.mozIJSSubScriptLoader);
+let EventUtils = {};
+loader.loadSubScript("chrome://marionette/content/EventUtils.js", EventUtils);
 
 addMessageListener("devtools:test:history", function ({ data }) {
   content.history[data.direction]();
 });
 
 addMessageListener("devtools:test:navigate", function ({ data }) {
   content.location = data.location;
 });
@@ -185,16 +188,65 @@ addMessageListener("devtools:test:setAtt
   }
 
   node.setAttribute(attributeName, attributeValue);
 
   sendAsyncMessage("devtools:test:setAttribute");
 });
 
 /**
+ * Synthesize a mouse event on an element. This handler doesn't send a message
+ * back. Consumers should listen to specific events on the inspector/highlighter
+ * to know when the event got synthesized.
+ * @param {Object} msg The msg.data part expects the following properties:
+ * - {Number} x
+ * - {Number} y
+ * - {Boolean} center If set to true, x/y will be ignored and
+ *             synthesizeMouseAtCenter will be used instead
+ * - {Object} options Other event options
+ * - {String} selector An optional selector that will be used to find the node to
+ *            synthesize the event on, if msg.objects doesn't contain the CPOW.
+ * The msg.objects part should be the element.
+ * @param {Object} data Event detail properties:
+ */
+addMessageListener("Test:SynthesizeMouse", function(msg) {
+  let {x, y, center, options, selector} = msg.data;
+  let {node} = msg.objects;
+
+  if (!node && selector) {
+    node = superQuerySelector(selector);
+  }
+
+  if (center) {
+    EventUtils.synthesizeMouseAtCenter(node, options, node.ownerDocument.defaultView);
+  } else {
+    EventUtils.synthesizeMouse(node, x, y, options, node.ownerDocument.defaultView);
+  }
+
+  // Most consumers won't need to listen to this message, unless they want to
+  // wait for the mouse event to be synthesized and don't have another event
+  // to listen to instead.
+  sendAsyncMessage("Test:SynthesizeMouse");
+});
+
+/**
+ * Synthesize a key event for an element. This handler doesn't send a message
+ * back. Consumers should listen to specific events on the inspector/highlighter
+ * to know when the event got synthesized.
+ * @param  {Object} msg The msg.data part expects the following properties:
+ * - {String} key
+ * - {Object} options
+ */
+addMessageListener("Test:SynthesizeKey", function(msg) {
+  let {key, options} = msg.data;
+
+  EventUtils.synthesizeKey(key, options, content);
+});
+
+/**
  * Like document.querySelector but can go into iframes too.
  * ".container iframe || .sub-container div" will first try to find the node
  * matched by ".container iframe" in the root document, then try to get the
  * content document inside it, and then try to match ".sub-container div" inside
  * this document.
  * Any selector coming before the || separator *MUST* match a frame node.
  * @param {String} superSelector.
  * @return {DOMNode} The node, or null if not found.
--- a/browser/devtools/webconsole/test/browser.ini
+++ b/browser/devtools/webconsole/test/browser.ini
@@ -302,17 +302,16 @@ skip-if = buildapp == 'mulet' || e10s # 
 [browser_webconsole_bug_915141_toggle_response_logging_with_keyboard.js]
 [browser_webconsole_filter_buttons_contextmenu.js]
 [browser_webconsole_bug_1006027_message_timestamps_incorrect.js]
 skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug intermittent)
 [browser_webconsole_bug_1010953_cspro.js]
 [browser_webconsole_certificate_messages.js]
 skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_webconsole_show_subresource_security_errors.js]
-skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_webconsole_cached_autocomplete.js]
 [browser_webconsole_change_font_size.js]
 [browser_webconsole_chrome.js]
 [browser_webconsole_clickable_urls.js]
 skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
 [browser_webconsole_closure_inspection.js]
 skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_webconsole_completion.js]
--- a/dom/camera/GonkCameraParameters.cpp
+++ b/dom/camera/GonkCameraParameters.cpp
@@ -101,17 +101,17 @@ GonkCameraParameters::Unflatten(const St
 
   const char* data = aFlatParameters.string();
   while (data && *data) {
     const char* pos = strchr(data, '=');
     if (!pos) {
       break;
     }
 
-    nsAutoCString key(data, pos - data);
+    nsDependentCSubstring key(data, pos - data);
     data = pos + 1;
 
     nsCString* value;
     pos = strchr(data, ';');
     if (pos) {
       value = new nsCString(data, pos - data);
       data = pos + 1;
     } else {
--- a/dom/camera/GonkCameraParameters.h
+++ b/dom/camera/GonkCameraParameters.h
@@ -92,109 +92,112 @@ protected:
   nsTArray<nsString> mMeteringModes;
   nsClassHashtable<nsStringHashKey, nsCString> mIsoModeMap;
   nsClassHashtable<nsCStringHashKey, nsCString> mParams;
 
   static PLDHashOperator EnumerateFlatten(const nsACString& aKey, nsCString* aValue, void* aUserArg);
 
   nsresult SetImpl(const char* aKey, const char* aValue)
   {
-    nsCString key(aKey);
+    if (!aValue || strchr(aValue, ';') || strchr(aValue, '=')) {
+      return NS_ERROR_ILLEGAL_VALUE;
+    }
+    nsDependentCString key(aKey);
     mParams.Put(key, new nsCString(aValue));
     return NS_OK;
   }
 
   nsresult SetImpl(const char* aKey, int aValue)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value = new nsCString();
     value->AppendInt(aValue);
     mParams.Put(key, value);
     return NS_OK;
   }
 
   nsresult SetImpl(const char* aKey, double aValue)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value = new nsCString();
     value->AppendFloat(aValue);
     mParams.Put(key, value);
     return NS_OK;
   }
 
   nsresult SetImpl(const char* aKey, float aValue)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value = new nsCString();
     value->AppendFloat(aValue);
     mParams.Put(key, value);
     return NS_OK;
   }
 
   nsresult SetImpl(const char* aKey, bool aValue)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     mParams.Put(key, new nsCString(aValue ? "true" : "false"));
     return NS_OK;
   }
 
   nsresult GetImpl(const char* aKey, const char*& aRet)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value;
     if (!mParams.Get(key, &value)) {
       aRet = nullptr;
       return NS_ERROR_FAILURE;
     }
     aRet = value->Data();
     return NS_OK;
   }
 
   nsresult GetImpl(const char* aKey, float& aRet)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value;
     nsresult rv = NS_ERROR_FAILURE;
     if (mParams.Get(key, &value)) {
       aRet = value->ToFloat(&rv);
     } else {
       aRet = 0.0;
     }
     return rv;
   }
 
   nsresult GetImpl(const char* aKey, double& aRet)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value;
     nsresult rv = NS_ERROR_FAILURE;
     if (mParams.Get(key, &value)) {
       aRet = value->ToFloat(&rv);
     } else {
       aRet = 0.0;
     }
     return rv;
   }
 
   nsresult GetImpl(const char* aKey, int& aRet)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value;
     nsresult rv = NS_ERROR_FAILURE;
     if (mParams.Get(key, &value)) {
       aRet = value->ToInteger(&rv);
     } else {
       aRet = 0.0;
     }
     return rv;
   }
 
   nsresult GetImpl(const char* aKey, bool& aRet)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     nsCString* value;
     if (!mParams.Get(key, &value)) {
       aRet = false;
       return NS_ERROR_FAILURE;
     }
     aRet = value->EqualsLiteral("true");
     return NS_OK;
   }
@@ -223,17 +226,17 @@ protected:
     const char* key = GetTextKey(aKey);
     NS_ENSURE_TRUE(key, NS_ERROR_NOT_IMPLEMENTED);
     return GetImpl(key, aValue);
   }
 
   nsresult
   ClearImpl(const char* aKey)
   {
-    nsCString key(aKey);
+    nsDependentCString key(aKey);
     mParams.Remove(key);
     return NS_OK;
   }
 
   // The *Translated() functions allow us to handle special cases;
   // for example, where the thumbnail size setting is exposed as an
   // ICameraControl::Size object, but is handled by the AOSP layer
   // as two separate parameters.
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -985,17 +985,17 @@ nsBidiPresUtils::TraverseFrames(nsBlockF
         frame = realFrame;
       }
     }
 
     char16_t ch = 0;
     if (frame->IsFrameOfType(nsIFrame::eBidiInlineContainer)) {
       if (!(frame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
         nsContainerFrame* c = static_cast<nsContainerFrame*>(frame);
-        MOZ_ASSERT(c = do_QueryFrame(frame),
+        MOZ_ASSERT(c == do_QueryFrame(frame),
                    "eBidiInlineContainer must be a nsContainerFrame subclass");
         c->DrainSelfOverflowList();
       }
 
       const nsStyleVisibility* vis = frame->StyleVisibility();
       const nsStyleTextReset* text = frame->StyleTextReset();
       if (text->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_OVERRIDE) {
         if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -200,17 +200,17 @@ nsHTMLCSSStyleSheet::CacheStyleAttr(cons
 }
 
 void
 nsHTMLCSSStyleSheet::EvictStyleAttr(const nsAString& aSerialized,
                                     MiscContainer* aValue)
 {
 #ifdef DEBUG
   {
-    NS_ASSERTION(aValue = mCachedStyleAttrs.Get(aSerialized),
+    NS_ASSERTION(aValue == mCachedStyleAttrs.Get(aSerialized),
                  "Cached value does not match?!");
   }
 #endif
   mCachedStyleAttrs.Remove(aSerialized);
 }
 
 MiscContainer*
 nsHTMLCSSStyleSheet::LookupStyleAttr(const nsAString& aSerialized)
--- a/mobile/android/base/fxa/activities/FxAccountStatusFragment.java
+++ b/mobile/android/base/fxa/activities/FxAccountStatusFragment.java
@@ -8,35 +8,32 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.R;
-import org.mozilla.gecko.background.ReadingListConstants;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountUtils;
 import org.mozilla.gecko.background.preferences.PreferenceFragment;
-import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.fxa.login.Married;
 import org.mozilla.gecko.fxa.login.State;
 import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
 import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
 import org.mozilla.gecko.sync.SyncConfiguration;
 import org.mozilla.gecko.util.HardwareUtils;
 
 import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.Handler;
 import android.preference.CheckBoxPreference;
 import android.preference.EditTextPreference;
@@ -173,19 +170,16 @@ public class FxAccountStatusFragment
     needsFinishMigratingPreference = ensureFindPreference("needs_finish_migrating");
 
     syncCategory = (PreferenceCategory) ensureFindPreference("sync_category");
 
     bookmarksPreference = (CheckBoxPreference) ensureFindPreference("bookmarks");
     historyPreference = (CheckBoxPreference) ensureFindPreference("history");
     tabsPreference = (CheckBoxPreference) ensureFindPreference("tabs");
     passwordsPreference = (CheckBoxPreference) ensureFindPreference("passwords");
-    // The Reading List toggle appears with the other Firefox Sync toggles but
-    // controls a separate Android authority.
-    readingListPreference = (CheckBoxPreference) ensureFindPreference("reading_list");
 
     if (!FxAccountUtils.LOG_PERSONAL_INFORMATION) {
       removeDebugButtons();
     } else {
       connectDebugButtons();
       ALWAYS_SHOW_AUTH_SERVER = true;
       ALWAYS_SHOW_SYNC_SERVER = true;
     }
@@ -195,17 +189,16 @@ public class FxAccountStatusFragment
     needsPasswordPreference.setOnPreferenceClickListener(this);
     needsVerificationPreference.setOnPreferenceClickListener(this);
     needsFinishMigratingPreference.setOnPreferenceClickListener(this);
 
     bookmarksPreference.setOnPreferenceClickListener(this);
     historyPreference.setOnPreferenceClickListener(this);
     tabsPreference.setOnPreferenceClickListener(this);
     passwordsPreference.setOnPreferenceClickListener(this);
-    readingListPreference.setOnPreferenceClickListener(this);
 
     deviceNamePreference = (EditTextPreference) ensureFindPreference("device_name");
     deviceNamePreference.setOnPreferenceChangeListener(this);
 
     syncServerPreference = ensureFindPreference("sync_server");
     morePreference = ensureFindPreference("more");
     morePreference.setOnPreferenceClickListener(this);
 
@@ -283,24 +276,16 @@ public class FxAccountStatusFragment
     if (preference == bookmarksPreference ||
         preference == historyPreference ||
         preference == passwordsPreference ||
         preference == tabsPreference) {
       saveEngineSelections();
       return true;
     }
 
-    if (preference == readingListPreference) {
-      final boolean syncAutomatically = readingListPreference.isChecked();
-      ContentResolver.setIsSyncable(fxAccount.getAndroidAccount(), BrowserContract.READING_LIST_AUTHORITY, 1);
-      ContentResolver.setSyncAutomatically(fxAccount.getAndroidAccount(), BrowserContract.READING_LIST_AUTHORITY, syncAutomatically);
-      FxAccountUtils.pii(LOG_TAG, (syncAutomatically ? "En" : "Dis") + "abling Reading List sync automatically.");
-      return true;
-    }
-
     if (preference == morePreference) {
       getActivity().openOptionsMenu();
       return true;
     }
 
     if (preference == syncNowPreference) {
       if (fxAccount != null) {
         FirefoxAccounts.requestSync(fxAccount.getAndroidAccount(), FirefoxAccounts.FORCE, null, null);
@@ -325,21 +310,16 @@ public class FxAccountStatusFragment
   protected void setCheckboxesEnabled(boolean enabled) {
     bookmarksPreference.setEnabled(enabled);
     historyPreference.setEnabled(enabled);
     tabsPreference.setEnabled(enabled);
     passwordsPreference.setEnabled(enabled);
     // Since we can't sync, we can't update our remote client record.
     deviceNamePreference.setEnabled(enabled);
     syncNowPreference.setEnabled(enabled);
-
-    // The checkboxes are a set of global settings: they reflect the account
-    // state and not the underlying Sync state. In the future, each checkbox
-    // will reflect its own piece of the account state.
-    readingListPreference.setEnabled(enabled);
   }
 
   /**
    * Show at most one error preference, hiding all others.
    *
    * @param errorPreferenceToShow
    *          single error preference to show; if null, hide all error preferences
    */
@@ -551,17 +531,16 @@ public class FxAccountStatusFragment
       final boolean masterSyncAutomatically = ContentResolver.getMasterSyncAutomatically();
       if (!masterSyncAutomatically) {
         showNeedsMasterSyncAutomaticallyEnabled();
         return;
       }
     } finally {
       // No matter our state, we should update the checkboxes.
       updateSelectedEngines();
-      updateReadingList();
     }
 
     final String clientName = clientsDataDelegate.getClientName();
     deviceNamePreference.setSummary(clientName);
     deviceNamePreference.setText(clientName);
 
     updateSyncNowPreference();
   }
@@ -664,29 +643,16 @@ public class FxAccountStatusFragment
       setCheckboxesEnabled(false);
     } catch (Exception e) {
       Logger.warn(LOG_TAG, "Got exception getting engines to select; ignoring.", e);
       return;
     }
   }
 
   /**
-   * Query the current reading list automatic sync state, and update the UI
-   * accordingly.
-   */
-  protected void updateReadingList() {
-    if (AppConstants.MOZ_ANDROID_READING_LIST_SERVICE) {
-      final boolean syncAutomatically = ContentResolver.getSyncAutomatically(fxAccount.getAndroidAccount(), BrowserContract.READING_LIST_AUTHORITY);
-      readingListPreference.setChecked(syncAutomatically);
-    } else {
-      syncCategory.removePreference(readingListPreference);
-    }
-  }
-
-  /**
    * Persist engine selections to local shared preferences, and request a sync
    * to persist selections to remote storage.
    */
   protected void saveEngineSelections() {
     final Map<String, Boolean> engineSelections = new HashMap<String, Boolean>();
     engineSelections.put("bookmarks", bookmarksPreference.isChecked());
     engineSelections.put("history", historyPreference.isChecked());
     engineSelections.put("passwords", passwordsPreference.isChecked());
@@ -785,26 +751,16 @@ public class FxAccountStatusFragment
         Logger.info(LOG_TAG, "Refreshing.");
         refresh();
       } else if ("debug_dump".equals(key)) {
         fxAccount.dump();
       } else if ("debug_force_sync".equals(key)) {
         Logger.info(LOG_TAG, "Force syncing.");
         fxAccount.requestSync(FirefoxAccounts.FORCE);
         // No sense refreshing, since the sync will complete in the future.
-      } else if ("debug_forget_reading_list_oauth_token".equals(key)) {
-        final Account account = fxAccount.getAndroidAccount();
-        final AccountManager accountManager = AccountManager.get(getActivity());
-        final String authToken = accountManager.peekAuthToken(account, ReadingListConstants.AUTH_TOKEN_TYPE);
-        if (authToken != null) {
-          Logger.info(LOG_TAG, "Forgetting reading list oauth token: " + authToken);
-          accountManager.invalidateAuthToken(account.type, authToken);
-        } else {
-          Logger.warn(LOG_TAG, "No reading list oauth token to forget!");
-        }
       } else if ("debug_forget_certificate".equals(key)) {
         State state = fxAccount.getState();
         try {
           Married married = (Married) state;
           Logger.info(LOG_TAG, "Moving to Cohabiting state: Forgetting certificate.");
           fxAccount.setState(married.makeCohabitingState());
           refresh();
         } catch (ClassCastException e) {
--- a/mobile/android/base/fxa/authenticator/AndroidFxAccount.java
+++ b/mobile/android/base/fxa/authenticator/AndroidFxAccount.java
@@ -58,23 +58,16 @@ public class AndroidFxAccount {
   public static final int CURRENT_ACCOUNT_VERSION = 3;
   public static final String ACCOUNT_KEY_ACCOUNT_VERSION = "version";
   public static final String ACCOUNT_KEY_PROFILE = "profile";
   public static final String ACCOUNT_KEY_IDP_SERVER = "idpServerURI";
 
   public static final String ACCOUNT_KEY_TOKEN_SERVER = "tokenServerURI";       // Sync-specific.
   public static final String ACCOUNT_KEY_DESCRIPTOR = "descriptor";
 
-  // The set of authorities to sync automatically changes over time. The first
-  // new authority is the Reading List. This tracks if we've enabled syncing,
-  // and opted in (or out) of syncing automatically, for the new Reading List
-  // authority. This happens either on when the account is created or when
-  // upgrading.
-  public static final String ACCOUNT_KEY_READING_LIST_AUTHORITY_INITIALIZED = "readingListAuthorityInitialized";
-
   public static final int CURRENT_BUNDLE_VERSION = 2;
   public static final String BUNDLE_KEY_BUNDLE_VERSION = "version";
   public static final String BUNDLE_KEY_STATE_LABEL = "stateLabel";
   public static final String BUNDLE_KEY_STATE = "state";
 
   // Services may request OAuth tokens from the Firefox Account dynamically.
   // Each such token is prefixed with "oauth::" and a service-dependent scope.
   // Such tokens should be destroyed when the account is removed from the device.
@@ -88,20 +81,16 @@ public class AndroidFxAccount {
     KNOWN_OAUTH_TOKEN_TYPES = Collections.unmodifiableList(list);
   }
 
   public static final Map<String, Boolean> DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP;
   static {
     final HashMap<String, Boolean> m = new HashMap<String, Boolean>();
     // By default, Firefox Sync is enabled.
     m.put(BrowserContract.AUTHORITY, true);
-    if (AppConstants.MOZ_ANDROID_READING_LIST_SERVICE) {
-      // Sync the Reading List.
-      m.put(BrowserContract.READING_LIST_AUTHORITY, true);
-    }
     DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP = Collections.unmodifiableMap(m);
   }
 
   private static final String PREF_KEY_LAST_SYNCED_TIMESTAMP = "lastSyncedTimestamp";
 
   protected final Context context;
   protected final AccountManager accountManager;
   protected final Account account;
@@ -425,20 +414,16 @@ public class AndroidFxAccount {
 
     // Android has internal restrictions that require all values in this
     // bundle to be strings. *sigh*
     Bundle userdata = new Bundle();
     userdata.putString(ACCOUNT_KEY_ACCOUNT_VERSION, "" + CURRENT_ACCOUNT_VERSION);
     userdata.putString(ACCOUNT_KEY_IDP_SERVER, idpServerURI);
     userdata.putString(ACCOUNT_KEY_TOKEN_SERVER, tokenServerURI);
     userdata.putString(ACCOUNT_KEY_PROFILE, profile);
-    if (DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP.containsKey(BrowserContract.READING_LIST_AUTHORITY)) {
-      // Have we initialized the Reading List authority?
-      userdata.putString(ACCOUNT_KEY_READING_LIST_AUTHORITY_INITIALIZED, "1");
-    }
 
     if (bundle == null) {
       bundle = new ExtendedJSONObject();
       // TODO: How to upgrade?
       bundle.put(BUNDLE_KEY_BUNDLE_VERSION, CURRENT_BUNDLE_VERSION);
     }
     bundle.put(BUNDLE_KEY_STATE_LABEL, state.getStateLabel().name());
     bundle.put(BUNDLE_KEY_STATE, state.toJSONObject().toJSONString());
--- a/mobile/android/base/fxa/receivers/FxAccountUpgradeReceiver.java
+++ b/mobile/android/base/fxa/receivers/FxAccountUpgradeReceiver.java
@@ -6,28 +6,25 @@ package org.mozilla.gecko.fxa.receivers;
 
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountUtils;
-import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.fxa.login.State;
 import org.mozilla.gecko.fxa.login.State.StateLabel;
 import org.mozilla.gecko.sync.Utils;
 
 import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 
 /**
  * A receiver that takes action when our Android package is upgraded (replaced).
  */
 public class FxAccountUpgradeReceiver extends BroadcastReceiver {
   private static final String LOG_TAG = FxAccountUpgradeReceiver.class.getSimpleName();
@@ -43,17 +40,16 @@ public class FxAccountUpgradeReceiver ex
    * @return list of Runnable instances.
    */
   protected List<Runnable> onUpgradeRunnables(Context context) {
     List<Runnable> runnables = new LinkedList<Runnable>();
     runnables.add(new MaybeUnpickleRunnable(context));
     // Recovering accounts that are in the Doghouse should happen *after* we
     // unpickle any accounts saved to disk.
     runnables.add(new AdvanceFromDoghouseRunnable(context));
-    runnables.add(new MaybeInitializeReadingListAuthority(context));
     return runnables;
   }
 
   @Override
   public void onReceive(final Context context, Intent intent) {
     Logger.setThreadLogTag(FxAccountConstants.GLOBAL_LOG_TAG);
     Logger.info(LOG_TAG, "Upgrade broadcast received.");
 
@@ -129,73 +125,9 @@ public class FxAccountUpgradeReceiver ex
           fxAccount.setState(state.makeSeparatedState());
         } catch (Exception e) {
           Logger.warn(LOG_TAG, "Got exception trying to advance account named like " + Utils.obfuscateEmail(account.name) +
               " from Doghouse to Separated state; ignoring.", e);
         }
       }
     }
   }
-
-  /**
-   * A Runnable that initializes the Reading List authority (specifically, set
-   * the sync automatically flag) for existing Firefox Accounts that have not
-   * yet seen the authority. That is, if a new authority (Reading List) is added
-   * to the set of defaults, existing Firefox Accounts won't be syncing it
-   * automatically. This tries to set the sync automatically flag for such
-   * existing accounts.
-   *
-   * Public for testing only.
-   */
-  public static class MaybeInitializeReadingListAuthority implements Runnable {
-    protected final Context context;
-
-    public MaybeInitializeReadingListAuthority(Context context) {
-      this.context = context;
-    }
-
-    @Override
-    public void run() {
-      final String authority = BrowserContract.READING_LIST_AUTHORITY;
-      Boolean enabledByDefault = AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP.get(authority);
-      if (enabledByDefault == null || !enabledByDefault.booleanValue()) {
-        Logger.info(LOG_TAG, "Reading List authority is not enabled by default; not trying to initialize Reading List authority for any accounts.");
-      }
-
-      final AccountManager accountManager = AccountManager.get(context);
-      final Account[] accounts = FirefoxAccounts.getFirefoxAccounts(context);
-      Logger.info(LOG_TAG, "Trying to initialize Reading List authority for " + accounts.length + " existing Firefox Accounts (if necessary).");
-
-      for (Account account : accounts) {
-        try {
-          final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
-          // For great debugging.
-          if (FxAccountUtils.LOG_PERSONAL_INFORMATION) {
-            fxAccount.dump();
-          }
-
-          final boolean readingListAuthorityInitialized =
-              "1".equals(accountManager.getUserData(account, AndroidFxAccount.ACCOUNT_KEY_READING_LIST_AUTHORITY_INITIALIZED));
-          if (readingListAuthorityInitialized) {
-            Logger.debug(LOG_TAG, "Reading List authority has already been initialized.");
-            continue;
-          }
-
-          // The Reading List authority has not been seen. This happens when an
-          // authority is added after the Firefox Account has been added (and
-          // the package last upgraded). If Firefox Sync is not syncing
-          // automatically, Reading List should not start syncing
-          // automatically: the user has elected not to upload data to Mozilla
-          // servers; we shouldn't opt them in.
-          final boolean syncAutomatically = ContentResolver.getSyncAutomatically(account, BrowserContract.AUTHORITY);
-            Logger.debug(LOG_TAG, "Setting Reading List authority " +
-                (syncAutomatically ? " to " : " to not ") + "sync automatically.");
-            ContentResolver.setSyncAutomatically(account, BrowserContract.READING_LIST_AUTHORITY, syncAutomatically);
-          // Update the account record.
-          accountManager.setUserData(account, AndroidFxAccount.ACCOUNT_KEY_READING_LIST_AUTHORITY_INITIALIZED, "1");
-        } catch (Exception e) {
-          Logger.warn(LOG_TAG, "Got exception trying to set authoritities to sync automatically for account named like " +
-              Utils.obfuscateEmail(account.name) + "; ignoring.", e);
-        }
-      }
-    }
-  }
 }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -187,20 +187,20 @@
 <!ENTITY pref_cookies_not_accept_foreign "Enabled, excluding 3rd party">
 <!ENTITY pref_cookies_disabled "Disabled">
 
 <!ENTITY pref_tracking_protection_title "Tracking protection">
 <!ENTITY pref_tracking_protection_summary "&brandShortName; will prevent sites from tracking you">
 <!ENTITY pref_donottrack_title "Do not track">
 <!ENTITY pref_donottrack_summary "&brandShortName; will tell sites that you do not want to be tracked">
 
-<!ENTITY tab_queue_toast_message "Open later">
+<!ENTITY tab_queue_toast_message2 "Tab queued in &brandShortName;">
 <!ENTITY tab_queue_toast_action "Open now">
 <!ENTITY tab_queue_prompt_title "Opening multiple links?">
-<!ENTITY tab_queue_prompt_text "Open them without switching to Firefox each time.">
+<!ENTITY tab_queue_prompt_text2 "Open them without switching to &brandShortName; each time.">
 <!ENTITY tab_queue_prompt_tip_text "you can change this later in Settings">
 <!ENTITY tab_queue_prompt_positive_action_button "Enable">
 <!ENTITY tab_queue_prompt_negative_action_button "Not now">
 <!-- Localization note (tab_queue_notification_text_plural) : The
      formatD is replaced with the number of tabs queued.  The
      number of tabs queued is always more than one.  We can't use
      Android plural forms, sadly. See Bug #753859. -->
 <!ENTITY tab_queue_notification_text_plural "&formatD; tabs queued">
@@ -392,18 +392,18 @@ size. -->
 <!ENTITY pref_titlebar_mode_title "Show page title">
 <!ENTITY pref_titlebar_mode_url "Show page address">
 
 <!-- Localization note (pref_scroll_title_bar2): Label for setting that controls
      whether or not the dynamic toolbar is enabled. -->
 <!ENTITY pref_scroll_title_bar2 "Full-screen browsing">
 <!ENTITY pref_scroll_title_bar_summary "Hide the &brandShortName; title bar when scrolling down a page">
 
-<!ENTITY pref_tab_queue_title "Open later">
-<!ENTITY pref_tab_queue_summary "Prevent tabs from opening immediately, but open all queued tabs the next time &brandShortName; loads.">
+<!ENTITY pref_tab_queue_title2 "Open multiple links">
+<!ENTITY pref_tab_queue_summary2 "Queue links for later instead of switching to &brandShortName; each time">
 
 <!-- Localization note (page_removed): This string appears in a toast message when
      any page is removed frome about:home. This includes pages that are in history,
      bookmarks, or reading list. -->
 <!ENTITY page_removed "Page removed">
 
 <!ENTITY bookmark_edit_title "Edit Bookmark">
 <!ENTITY bookmark_edit_name "Name">
--- a/mobile/android/base/resources/layout/tabs_panel_default.xml
+++ b/mobile/android/base/resources/layout/tabs_panel_default.xml
@@ -10,17 +10,17 @@
          and as an offset in PrivateTabsPanel: if you change it here,
          change it there! -->
     <RelativeLayout android:id="@+id/tabs_panel_header"
                     android:layout_width="match_parent"
                     android:layout_height="@dimen/browser_toolbar_height">
 
         <view class="org.mozilla.gecko.tabs.TabsPanel$TabsPanelToolbar"
               android:layout_width="match_parent"
-              android:layout_height="match_parent"
+              android:layout_height="@dimen/browser_toolbar_height"
               android:background="@color/background_tabs">
 
             <ViewStub android:id="@+id/nav_back_stub"
                       android:layout="@layout/new_tablet_tabs_panel_back_button"
                       android:layout_width="wrap_content"
                       android:layout_height="match_parent"/>
 
             <org.mozilla.gecko.widget.IconTabWidget android:id="@+id/tab_widget"
--- a/mobile/android/base/resources/layout/tabs_panel_view.xml
+++ b/mobile/android/base/resources/layout/tabs_panel_view.xml
@@ -5,9 +5,10 @@
 
 <!-- The tabs panel is initial hidden on startup. It will be made
      visible when the user activates it. See TabsPanel.show() -->
 <org.mozilla.gecko.tabs.TabsPanel xmlns:android="http://schemas.android.com/apk/res/android"
                                   android:id="@+id/tabs_panel"
                                   android:layout_width="match_parent"
                                   android:layout_height="match_parent"
                                   android:background="@color/background_tabs"
+                                  android:orientation="vertical"
                                   android:visibility="invisible"/>
--- a/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
+++ b/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
@@ -74,20 +74,16 @@
         <CheckBoxPreference
             android:key="tabs"
             android:persistent="false"
             android:title="@string/fxaccount_status_tabs" />
         <CheckBoxPreference
             android:key="passwords"
             android:persistent="false"
             android:title="@string/fxaccount_status_passwords" />
-        <CheckBoxPreference
-            android:key="reading_list"
-            android:persistent="false"
-            android:title="@string/fxaccount_status_reading_list" />
 
         <EditTextPreference
             android:singleLine="true"
             android:key="device_name"
             android:persistent="false"
             android:title="@string/fxaccount_status_device_name" />
 
         <Preference
@@ -122,17 +118,16 @@
         </Preference>
     </PreferenceCategory>
     <PreferenceCategory
         android:key="debug_category" >
         <Preference android:key="debug_refresh" />
         <Preference android:key="debug_dump" />
         <Preference android:key="debug_force_sync" />
         <Preference android:key="debug_invalidate_certificate" />
-        <Preference android:key="debug_forget_reading_list_oauth_token" />
         <Preference android:key="debug_forget_certificate" />
         <Preference android:key="debug_require_password" />
         <Preference android:key="debug_require_upgrade" />
         <Preference android:key="debug_migrated_from_sync11" />
         <Preference android:key="debug_make_account_stage" />
         <Preference android:key="debug_make_account_default" />
 	</PreferenceCategory>
 
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -234,24 +234,24 @@
   <string name="pref_private_data_downloadFiles2">&pref_private_data_downloadFiles2;</string>
   <string name="pref_import_android">&pref_import_android;</string>
   <string name="pref_import_android_summary">&pref_import_android_summary;</string>
   <string name="pref_update_autodownload">&pref_update_autodownload2;</string>
   <string name="pref_update_autodownload_wifi">&pref_update_autodownload_wifi;</string>
   <string name="pref_update_autodownload_disabled">&pref_update_autodownload_never;</string>
   <string name="pref_update_autodownload_enabled">&pref_update_autodownload_always;</string>
 
-  <string name="pref_tab_queue_title">&pref_tab_queue_title;</string>
-  <string name="pref_tab_queue_summary">&pref_tab_queue_summary;</string>
+  <string name="pref_tab_queue_title">&pref_tab_queue_title2;</string>
+  <string name="pref_tab_queue_summary">&pref_tab_queue_summary2;</string>
   <string name="tab_queue_prompt_title">&tab_queue_prompt_title;</string>
-  <string name="tab_queue_prompt_text">&tab_queue_prompt_text;</string>
+  <string name="tab_queue_prompt_text">&tab_queue_prompt_text2;</string>
   <string name="tab_queue_prompt_tip_text">&tab_queue_prompt_tip_text;</string>
   <string name="tab_queue_prompt_positive_action_button">&tab_queue_prompt_positive_action_button;</string>
   <string name="tab_queue_prompt_negative_action_button">&tab_queue_prompt_negative_action_button;</string>
-  <string name="tab_queue_toast_message">&tab_queue_toast_message;</string>
+  <string name="tab_queue_toast_message">&tab_queue_toast_message2;</string>
   <string name="tab_queue_toast_action">&tab_queue_toast_action;</string>
   <string name="tab_queue_notification_text_singular">&tab_queue_notification_text_singular;</string>
   <string name="tab_queue_notification_text_plural">&tab_queue_notification_text_plural;</string>
   <string name="tab_queue_notification_title_singular">&tab_queue_notification_title_singular;</string>
   <string name="tab_queue_notification_title_plural">&tab_queue_notification_title_plural;</string>
 
   <string name="pref_about_firefox">&pref_about_firefox;</string>
   <string name="pref_vendor_faqs">&pref_vendor_faqs;</string>
--- a/mobile/android/base/tabqueue/TabQueueService.java
+++ b/mobile/android/base/tabqueue/TabQueueService.java
@@ -133,16 +133,17 @@ public class TabQueueService extends Ser
 
 
                 Intent forwardIntent = new Intent(intent);
                 forwardIntent.setClass(getApplicationContext(), BrowserApp.class);
                 forwardIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 startActivity(forwardIntent);
 
                 removeView();
+                stopSelfResult(startId);
             }
         });
 
         tabQueueHandler.postDelayed(stopServiceRunnable, TOAST_TIMEOUT);
 
         return START_REDELIVER_INTENT;
     }
 
--- a/mobile/android/base/tabs/TabsPanel.java
+++ b/mobile/android/base/tabs/TabsPanel.java
@@ -97,20 +97,16 @@ public class TabsPanel extends LinearLay
     private final GeckoPopupMenu mPopupMenu;
 
     public TabsPanel(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
         mActivity = (GeckoApp) context;
         mTheme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme();
 
-        setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
-                                                      LinearLayout.LayoutParams.MATCH_PARENT));
-        setOrientation(LinearLayout.VERTICAL);
-
         mCurrentPanel = Panel.NORMAL_TABS;
 
         mPopupMenu = new GeckoPopupMenu(context);
         mPopupMenu.inflate(R.menu.tabs_menu);
         mPopupMenu.setOnMenuItemClickListener(this);
 
         inflateLayout(context);
         initialize();
@@ -327,21 +323,16 @@ public class TabsPanel extends LinearLay
     // Tabs Panel Toolbar contains the Buttons
     static class TabsPanelToolbar extends LinearLayout
                                   implements LightweightTheme.OnChangeListener {
         private final LightweightTheme mTheme;
 
         public TabsPanelToolbar(Context context, AttributeSet attrs) {
             super(context, attrs);
             mTheme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme();
-
-            setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
-                                                          (int) context.getResources().getDimension(R.dimen.browser_toolbar_height)));
-
-            setOrientation(LinearLayout.HORIZONTAL);
         }
 
         @Override
         public void onAttachedToWindow() {
             super.onAttachedToWindow();
             mTheme.addListener(this);
         }
 
--- a/mobile/android/base/tests/testSettingsMenuItems.java
+++ b/mobile/android/base/tests/testSettingsMenuItems.java
@@ -202,17 +202,18 @@ public class testSettingsMenuItems exten
         // Automatic updates
         if (AppConstants.MOZ_UPDATER) {
             String[] autoUpdateUi = { "Download updates automatically", "Only over Wi-Fi", "Always", "Only over Wi-Fi", "Never" };
             settingsMap.get(PATH_CUSTOMIZE).add(autoUpdateUi);
         }
 
         // Tab Queue
         if (AppConstants.NIGHTLY_BUILD && AppConstants.MOZ_ANDROID_TAB_QUEUE) {
-            String[] tabQueue = { mStringHelper.TAB_QUEUE_LABEL, "Prevent tabs from opening immediately, but open all queued tabs the next time " + mStringHelper.BRAND_NAME + " loads." };
+            final String expected = "Queue links for later instead of switching to " + mStringHelper.BRAND_NAME + " each time";
+            String[] tabQueue = { mStringHelper.TAB_QUEUE_LABEL, expected };
             settingsMap.get(PATH_CUSTOMIZE).add(tabQueue);
         }
 
         // Crash reporter
         if (AppConstants.MOZ_CRASHREPORTER) {
             String[] crashReporterUi = { "Crash Reporter", mStringHelper.BRAND_NAME + " submits crash reports to help Mozilla make your browser more stable and secure" };
             settingsMap.get(PATH_MOZILLA).add(crashReporterUi);
         }
--- a/mobile/android/base/toolbar/BrowserToolbarTabletBase.java
+++ b/mobile/android/base/toolbar/BrowserToolbarTabletBase.java
@@ -122,16 +122,21 @@ abstract class BrowserToolbarTabletBase 
         backButton.setPrivateMode(isPrivate);
         forwardButton.setPrivateMode(isPrivate);
         for (int i = 0; i < actionItemBar.getChildCount(); ++i) {
             final MenuItemActionBar child = (MenuItemActionBar) actionItemBar.getChildAt(i);
             child.setPrivateMode(isPrivate);
         }
     }
 
+    @Override
+    public View getDoorHangerAnchor() {
+        return backButton;
+    }
+
     protected boolean canDoBack(final Tab tab) {
         return (tab.canDoBack() && !isEditing());
     }
 
     protected boolean canDoForward(final Tab tab) {
         return (tab.canDoForward() && !isEditing());
     }
 
--- a/mobile/android/base/widget/AnchoredPopup.java
+++ b/mobile/android/base/widget/AnchoredPopup.java
@@ -95,18 +95,20 @@ public abstract class AnchoredPopup exte
             offsetY = mContext.getResources().getDimensionPixelOffset(R.dimen.doorhanger_GB_offsetY);
             if (mAnchor == null) {
               mAnchor = decorView;
             }
             showAsDropDown(mAnchor, 0, -offsetY);
             return;
         }
 
-        // If the anchor is null or out of the window bounds, just show the popup at the top of the
-        // root view.
-        if (mAnchor == null || anchorLocation[1] < 0) {
-            showAtLocation(decorView, Gravity.NO_GRAVITY, 0, offsetY);
-            return;
+        if (HardwareUtils.isTablet()) {
+            showAsDropDown(mAnchor, 0, 0);
+        } else {
+            // If the anchor is null or out of the window bounds, just show the popup at the top of the
+            // root view.
+            final boolean validAnchor = (mAnchor != null) && (anchorLocation[1] > 0);
+            final View anchor = validAnchor ? mAnchor : decorView;
+
+            showAtLocation(anchor, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, offsetY);
         }
-
-        showAtLocation(mAnchor, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, offsetY);
     }
 }
--- a/mobile/android/confvars.sh
+++ b/mobile/android/confvars.sh
@@ -50,19 +50,16 @@ MOZ_APP_STATIC_INI=1
 MOZ_ENABLE_SZIP=1
 
 # Enable navigator.mozPay
 MOZ_PAY=1
 
 # Enable UI for healthreporter
 MOZ_SERVICES_HEALTHREPORT=1
 
-# Enable reading list service integration.
-MOZ_ANDROID_READING_LIST_SERVICE=1
-
 # Enable runtime locale switching.
 MOZ_LOCALE_SWITCHER=1
 
 # Enable second screen and casting support for external devices.
 MOZ_DEVICES=1
 
 # Enable second screen using native Android libraries, provided we're
 # not resource constrained.
--- a/mobile/android/services/manifests/FxAccountAndroidManifest_services.xml.in
+++ b/mobile/android/services/manifests/FxAccountAndroidManifest_services.xml.in
@@ -21,24 +21,9 @@
             android:name="org.mozilla.gecko.fxa.sync.FxAccountSyncService" >
             <intent-filter >
                 <action android:name="android.content.SyncAdapter" />
             </intent-filter>
 
             <meta-data
                 android:name="android.content.SyncAdapter"
                 android:resource="@xml/fxaccount_syncadapter" />
-        </service>
-
-        <!-- Reading List. -->
-#ifdef MOZ_ANDROID_READING_LIST_SERVICE
-        <service
-            android:exported="false"
-            android:name="org.mozilla.gecko.reading.ReadingListSyncService" >
-            <intent-filter >
-                <action android:name="android.content.SyncAdapter" />
-            </intent-filter>
-
-            <meta-data
-                android:name="android.content.SyncAdapter"
-                android:resource="@xml/readinglist_syncadapter" />
-        </service>
-#endif
+        </service>
\ No newline at end of file
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -177,17 +177,17 @@ public:
   NS_IMETHOD GetLocalPort(int32_t* port) override;
   NS_IMETHOD GetRemoteAddress(nsACString& addr) override;
   NS_IMETHOD GetRemotePort(int32_t* port) override;
   NS_IMETHOD GetAllowSpdy(bool *aAllowSpdy) override;
   NS_IMETHOD SetAllowSpdy(bool aAllowSpdy) override;
   NS_IMETHOD GetAllowAltSvc(bool *aAllowAltSvc) override;
   NS_IMETHOD SetAllowAltSvc(bool aAllowAltSvc) override;
   NS_IMETHOD GetApiRedirectToURI(nsIURI * *aApiRedirectToURI) override;
-  nsresult AddSecurityMessage(const nsAString &aMessageTag, const nsAString &aMessageCategory);
+  virtual nsresult AddSecurityMessage(const nsAString &aMessageTag, const nsAString &aMessageCategory);
   NS_IMETHOD TakeAllSecurityMessages(nsCOMArray<nsISecurityConsoleMessage> &aMessages) override;
   NS_IMETHOD GetResponseTimeoutEnabled(bool *aEnable) override;
   NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable) override;
   NS_IMETHOD GetNetworkInterfaceId(nsACString& aNetworkInterfaceId) override;
   NS_IMETHOD SetNetworkInterfaceId(const nsACString& aNetworkInterfaceId) override;
   NS_IMETHOD AddRedirect(nsIPrincipal *aRedirect) override;
   NS_IMETHOD ForcePending(bool aForcePending) override;
   NS_IMETHOD GetLastModifiedTime(PRTime* lastModifiedTime) override;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -986,16 +986,24 @@ HttpChannelChild::RecvDeleteSelf()
 }
 
 void
 HttpChannelChild::DeleteSelf()
 {
   Send__delete__(this);
 }
 
+bool
+HttpChannelChild::RecvReportSecurityMessage(const nsString& messageTag,
+                                            const nsString& messageCategory)
+{
+  AddSecurityMessage(messageTag, messageCategory);
+  return true;
+}
+
 class Redirect1Event : public ChannelEvent
 {
  public:
   Redirect1Event(HttpChannelChild* child,
                  const uint32_t& newChannelId,
                  const URIParams& newURI,
                  const uint32_t& redirectFlags,
                  const nsHttpResponseHead& responseHead)
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -135,16 +135,19 @@ protected:
                           const nsHttpResponseHead& responseHead) override;
   bool RecvRedirect3Complete() override;
   bool RecvAssociateApplicationCache(const nsCString& groupID,
                                      const nsCString& clientID) override;
   bool RecvFlushedForDiversion() override;
   bool RecvDivertMessages() override;
   bool RecvDeleteSelf() override;
 
+  bool RecvReportSecurityMessage(const nsString& messageTag,
+                                 const nsString& messageCategory) override;
+
   bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr);
   virtual void DoNotifyListenerCleanup() override;
 
 private:
   nsresult ContinueAsyncOpen();
 
   void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext);
   void DoOnStatus(nsIRequest* aRequest, nsresult status);
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -325,16 +325,17 @@ HttpChannelParent::DoAsyncOpen(  const U
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo,
                              nullptr, nullptr, loadFlags, ios);
 
   if (NS_FAILED(rv))
     return SendFailedAsyncOpen(rv);
 
   mChannel = static_cast<nsHttpChannel *>(channel.get());
+  mChannel->SetWarningReporter(this);
   mChannel->SetTimingEnabled(true);
   if (mPBOverride != kPBOverride_Unset) {
     mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
   }
 
   if (doResumeAt)
     mChannel->ResumeAt(startPos, entityID);
 
@@ -1260,9 +1261,24 @@ HttpChannelParent::GetAuthPrompt(uint32_
                                  void** aResult)
 {
   nsCOMPtr<nsIAuthPrompt2> prompt =
     new NeckoParent::NestedFrameAuthPrompt(Manager(), mNestedFrameId);
   prompt.forget(aResult);
   return NS_OK;
 }
 
+//-----------------------------------------------------------------------------
+// HttpChannelSecurityWarningReporter
+//-----------------------------------------------------------------------------
+
+nsresult
+HttpChannelParent::ReportSecurityMessage(const nsAString& aMessageTag,
+                                         const nsAString& aMessageCategory)
+{
+  if (NS_WARN_IF(!SendReportSecurityMessage(nsString(aMessageTag),
+                                            nsString(aMessageCategory)))) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  return NS_OK;
+}
+
 }} // mozilla::net
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -39,16 +39,17 @@ class HttpChannelParentListener;
 class HttpChannelParent final : public PHttpChannelParent
                               , public nsIParentRedirectingChannel
                               , public nsIProgressEventSink
                               , public nsIInterfaceRequestor
                               , public ADivertableParentChannel
                               , public nsIAuthPromptProvider
                               , public nsINetworkInterceptController
                               , public DisconnectableParent
+                              , public HttpChannelSecurityWarningReporter
 {
   virtual ~HttpChannelParent();
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIPARENTCHANNEL
@@ -149,16 +150,19 @@ protected:
   void FailDiversion(nsresult aErrorCode, bool aSkipResume = true);
 
   friend class HttpChannelParentListener;
   nsRefPtr<mozilla::dom::TabParent> mTabParent;
 
   void OfflineDisconnect() override;
   uint32_t GetAppId() override;
 
+  nsresult ReportSecurityMessage(const nsAString& aMessageTag,
+                                 const nsAString& aMessageCategory) override;
+
 private:
   nsRefPtr<nsHttpChannel>       mChannel;
   nsCOMPtr<nsICacheEntry>       mCacheEntry;
   nsCOMPtr<nsIAssociatedContentSecurity>  mAssociatedContentSecurity;
   bool mIPCClosed;                // PHttpChannel actor has been Closed()
 
   nsCOMPtr<nsIChannel> mRedirectChannel;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -134,16 +134,20 @@ child:
 
   // Parent has been suspended for diversion; no more events to be enqueued.
   FlushedForDiversion();
 
   // Child should resume processing the ChannelEventQueue, i.e. diverting any
   // OnDataAvailable and OnStopRequest messages in the queue back to the parent.
   DivertMessages();
 
+  // Report a security message to the console associated with this
+  // channel.
+  ReportSecurityMessage(nsString messageTag, nsString messageCategory);
+
   // Tell child to delete channel (all IPDL deletes must be done from child to
   // avoid races: see bug 591708).
   DeleteSelf();
 };
 
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -240,16 +240,17 @@ nsHttpChannel::nsHttpChannel()
     , mCacheEntryIsWriteOnly(false)
     , mCacheEntriesToWaitFor(0)
     , mHasQueryString(0)
     , mConcurentCacheAccess(0)
     , mIsPartialRequest(0)
     , mHasAutoRedirectVetoNotifier(0)
     , mPushedStream(nullptr)
     , mLocalBlocklist(false)
+    , mWarningReporter(nullptr)
     , mDidReval(false)
 {
     LOG(("Creating nsHttpChannel [this=%p]\n", this));
     mChannelCreationTime = PR_Now();
     mChannelCreationTimestamp = TimeStamp::Now();
 }
 
 nsHttpChannel::~nsHttpChannel()
@@ -277,16 +278,29 @@ nsHttpChannel::Init(nsIURI *uri,
                                         proxyResolveFlags, proxyURI);
     if (NS_FAILED(rv))
         return rv;
 
     LOG(("nsHttpChannel::Init [this=%p]\n", this));
 
     return rv;
 }
+
+nsresult
+nsHttpChannel::AddSecurityMessage(const nsAString& aMessageTag,
+                                  const nsAString& aMessageCategory)
+{
+    if (mWarningReporter) {
+        return mWarningReporter->ReportSecurityMessage(aMessageTag,
+                                                       aMessageCategory);
+    }
+    return HttpBaseChannel::AddSecurityMessage(aMessageTag,
+                                               aMessageCategory);
+}
+
 //-----------------------------------------------------------------------------
 // nsHttpChannel <private>
 //-----------------------------------------------------------------------------
 
 nsresult
 nsHttpChannel::Connect()
 {
     nsresult rv;
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -28,16 +28,24 @@ class nsDNSPrefetch;
 class nsICancelable;
 class nsIHttpChannelAuthProvider;
 class nsInputStreamPump;
 class nsISSLStatus;
 
 namespace mozilla { namespace net {
 
 class Http2PushedStream;
+
+class HttpChannelSecurityWarningReporter
+{
+public:
+  virtual nsresult ReportSecurityMessage(const nsAString& aMessageTag,
+                                         const nsAString& aMessageCategory) = 0;
+};
+
 //-----------------------------------------------------------------------------
 // nsHttpChannel
 //-----------------------------------------------------------------------------
 
 // Use to support QI nsIChannel to nsHttpChannel
 #define NS_HTTPCHANNEL_IID                         \
 {                                                  \
   0x301bf95b,                                      \
@@ -136,16 +144,22 @@ public:
     NS_IMETHOD GetDomainLookupStart(mozilla::TimeStamp *aDomainLookupStart) override;
     NS_IMETHOD GetDomainLookupEnd(mozilla::TimeStamp *aDomainLookupEnd) override;
     NS_IMETHOD GetConnectStart(mozilla::TimeStamp *aConnectStart) override;
     NS_IMETHOD GetConnectEnd(mozilla::TimeStamp *aConnectEnd) override;
     NS_IMETHOD GetRequestStart(mozilla::TimeStamp *aRequestStart) override;
     NS_IMETHOD GetResponseStart(mozilla::TimeStamp *aResponseStart) override;
     NS_IMETHOD GetResponseEnd(mozilla::TimeStamp *aResponseEnd) override;
 
+    nsresult AddSecurityMessage(const nsAString& aMessageTag,
+                                const nsAString& aMessageCategory) override;
+
+    void SetWarningReporter(HttpChannelSecurityWarningReporter* aReporter)
+      { mWarningReporter = aReporter; }
+
 public: /* internal necko use only */
 
     void InternalSetUploadStream(nsIInputStream *uploadStream)
       { mUploadStream = uploadStream; }
     void SetUploadStreamHasHeaders(bool hasHeaders)
       { mUploadStreamHasHeaders = hasHeaders; }
 
     nsresult SetReferrerWithPolicyInternal(nsIURI *referrer,
@@ -472,16 +486,19 @@ private:
     bool                              mLocalBlocklist;
 
     nsresult WaitForRedirectCallback();
     void PushRedirectAsyncFunc(nsContinueRedirectionFunc func);
     void PopRedirectAsyncFunc(nsContinueRedirectionFunc func);
 
     nsCString mUsername;
 
+    // If non-null, warnings should be reported to this object.
+    HttpChannelSecurityWarningReporter* mWarningReporter;
+
 protected:
     virtual void DoNotifyListenerCleanup() override;
 
 private: // cache telemetry
     bool mDidReval;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpChannel, NS_HTTPCHANNEL_IID)
--- a/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js
+++ b/toolkit/components/places/tests/bookmarks/test_417228-exclude-from-backup.js
@@ -122,17 +122,17 @@ add_task(function() {
   // restore json file
   yield BookmarkJSONUtils.importFromFile(jsonFile, true);
 
   // validate without removing all bookmarks
   // restore do not remove backup exclude entries
   test.validate(false);
 
   // cleanup
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   // manually remove the excluded root
   PlacesUtils.bookmarks.removeItem(test._excludeRootId);
   // restore json file
   yield BookmarkJSONUtils.importFromFile(jsonFile, true);
 
   // validate after a complete bookmarks cleanup
   test.validate(true);
 
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -326,30 +326,16 @@ function visits_in_database(aURI)
     return stmt.getInt64(0);
   }
   finally {
     stmt.finalize();
   }
 }
 
 /**
- * Removes all bookmarks and checks for correct cleanup
- */
-function remove_all_bookmarks() {
-  let PU = PlacesUtils;
-  // Clear all bookmarks
-  PU.bookmarks.removeFolderChildren(PU.bookmarks.bookmarksMenuFolder);
-  PU.bookmarks.removeFolderChildren(PU.bookmarks.toolbarFolder);
-  PU.bookmarks.removeFolderChildren(PU.bookmarks.unfiledBookmarksFolder);
-  // Check for correct cleanup
-  check_no_bookmarks();
-}
-
-
-/**
  * Checks that we don't have any bookmark
  */
 function check_no_bookmarks() {
   let query = PlacesUtils.history.getNewQuery();
   let folders = [
     PlacesUtils.bookmarks.toolbarFolder,
     PlacesUtils.bookmarks.bookmarksMenuFolder,
     PlacesUtils.bookmarks.unfiledBookmarksFolder,
--- a/toolkit/components/places/tests/inline/head_autocomplete.js
+++ b/toolkit/components/places/tests/inline/head_autocomplete.js
@@ -135,18 +135,20 @@ function ensure_results(aSearchString, a
         // Now force completion and check correct casing of the result.
         // This ensures the controller is able to do its magic case-preserving
         // stuff and correct replacement of the user's casing with result's one.
         controller.handleEnter(false);
         do_check_eq(input.textValue, completedValue);
       }
 
       // Cleanup.
-      remove_all_bookmarks();
-      PlacesTestUtils.clearHistory().then(resolve);
+      Promise.all([
+        PlacesUtils.bookmarks.eraseEverything(),
+        PlacesTestUtils.clearHistory()
+      ]).then(resolve);
     };
   });
 
   do_print("Searching for: '" + aSearchString + "'");
   controller.startSearch(aSearchString);
 
   return promise;
 }
--- a/toolkit/components/places/tests/queries/test_async.js
+++ b/toolkit/components/places/tests/queries/test_async.js
@@ -348,20 +348,20 @@ let DataHelper = {
 function run_test()
 {
   run_next_test();
 }
 
 add_task(function* test_async()
 {
   for (let [, test] in Iterator(tests)) {
-    remove_all_bookmarks();
+    yield PlacesUtils.bookmarks.eraseEverything();
 
     test.__proto__ = new Test();
     yield test.setup();
 
     print("------ Running test: " + test.desc);
     yield test.run();
   }
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   print("All tests done, exiting");
 });
--- a/toolkit/components/places/tests/queries/test_redirects.js
+++ b/toolkit/components/places/tests/queries/test_redirects.js
@@ -182,17 +182,17 @@ function run_test()
 
 /**
  * Populate the visits array and add visits to the database.
  * We will generate visit-chains like:
  *   visit -> redirect_temp -> redirect_perm
  */
 add_task(function test_add_visits_to_database()
 {
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 
   // We don't really bother on this, but we need a time to add visits.
   let timeInMicroseconds = Date.now() * 1000;
   let visitCount = 1;
 
   // Array of all possible transition types we could be redirected from.
   let t = [
     Ci.nsINavHistoryService.TRANSITION_LINK,
@@ -293,12 +293,12 @@ add_task(function test_redirects()
   // menu and most visited smart bookmark.
   let sorting_options = [Ci.nsINavHistoryQueryOptions.SORT_BY_NONE,
                          Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING,
                          Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING];
   // Will execute check_results_callback() for each generated combination.
   cartProd([includeHidden_options, maxResults_options, sorting_options],
            check_results_callback);
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 
   yield PlacesTestUtils.clearHistory();
 });
--- a/toolkit/components/places/tests/queries/test_sorting.js
+++ b/toolkit/components/places/tests/queries/test_sorting.js
@@ -1273,12 +1273,12 @@ add_task(function test_sorting()
 {
   for (let [, test] in Iterator(tests)) {
     yield test.setup();
     yield PlacesTestUtils.promiseAsyncUpdates();
     test.check();
     // sorting reversed, usually SORT_BY have ASC and DESC
     test.check_reverse();
     // Execute cleanup tasks
-    remove_all_bookmarks();
+    yield PlacesUtils.bookmarks.eraseEverything();
     yield PlacesTestUtils.clearHistory();
   }
 });
--- a/toolkit/components/places/tests/queries/test_tags.js
+++ b/toolkit/components/places/tests/queries/test_tags.js
@@ -549,17 +549,17 @@ function addBookmark(aURI) {
     url: aURI
   });
 }
 
 /**
  * Asynchronous task that removes all pages from history and bookmarks.
  */
 function* task_cleanDatabase(aCallback) {
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield PlacesTestUtils.clearHistory();
 }
 
 /**
  * Sets up a query with the specified tags, converts it to a URI, and makes sure
  * the URI is what we expect it to be.
  *
  * @param aTags
--- a/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
+++ b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js
@@ -27,17 +27,17 @@ function run_test() {
 function* cleanup() {
   Services.prefs.clearUserPref("browser.urlbar.autocomplete.enabled");
   Services.prefs.clearUserPref("browser.urlbar.autoFill");
   Services.prefs.clearUserPref("browser.urlbar.autoFill.typed");
   Services.prefs.clearUserPref("browser.urlbar.autoFill.searchEngines");
   for (let type of ["history", "bookmark", "history.onlyTyped", "openpage"]) {
     Services.prefs.clearUserPref("browser.urlbar.suggest." + type);
   }
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield PlacesTestUtils.clearHistory();
 }
 do_register_cleanup(cleanup);
 
 /**
  * @param aSearches
  *        Array of AutoCompleteSearch names.
  */
--- a/toolkit/components/places/tests/unit/test_412132.js
+++ b/toolkit/components/places/tests/unit/test_412132.js
@@ -28,17 +28,17 @@ add_task(function changeuri_unvisited_bo
 
   PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/2"));
 
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   do_print("Unvisited URI no longer bookmarked => frecency should = 0");
   do_check_eq(frecencyForUrl(TEST_URI), 0);
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield PlacesTestUtils.clearHistory();
 });
 
 add_task(function changeuri_visited_bookmark()
 {
   do_print("After changing URI of bookmark, frecency of bookmark's " +
            "original URI should not be zero if original URI is visited.");
   const TEST_URI = NetUtil.newURI("http://example.com/1");
@@ -58,17 +58,17 @@ add_task(function changeuri_visited_book
 
   PlacesUtils.bookmarks.changeBookmarkURI(id, uri("http://example.com/2"));
 
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   do_print("*Visited* URI no longer bookmarked => frecency should != 0");
   do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield PlacesTestUtils.clearHistory();
 });
 
 add_task(function changeuri_bookmark_still_bookmarked()
 {
   do_print("After changing URI of bookmark, frecency of bookmark's " +
            "original URI should not be zero if original URI is still " +
            "bookmarked.");
@@ -89,17 +89,17 @@ add_task(function changeuri_bookmark_sti
 
   PlacesUtils.bookmarks.changeBookmarkURI(id1, uri("http://example.com/2"));
 
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   do_print("URI still bookmarked => frecency should != 0");
   do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield PlacesTestUtils.clearHistory();
 });
 
 add_task(function changeuri_nonexistent_bookmark()
 {
   do_print("Changing the URI of a nonexistent bookmark should fail.");
   function tryChange(itemId)
   {
@@ -121,17 +121,17 @@ add_task(function changeuri_nonexistent_
   // Now add a bookmark, delete it, and check.
   let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                                 uri("http://example.com/"),
                                                 PlacesUtils.bookmarks.DEFAULT_INDEX,
                                                 "bookmark title");
   PlacesUtils.bookmarks.removeItem(id);
   tryChange(id);
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield PlacesTestUtils.clearHistory();
 });
 
 ///////////////////////////////////////////////////////////////////////////////
 
 function run_test()
 {
   run_next_test();
--- a/toolkit/components/places/tests/unit/test_adaptive_bug527311.js
+++ b/toolkit/components/places/tests/unit/test_adaptive_bug527311.js
@@ -84,19 +84,20 @@ function check_results() {
   let input = new AutoCompleteInput(["history"]);
   controller.input = input;
 
   input.onSearchComplete = function() {
     do_check_eq(controller.searchStatus,
                 Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH);
     do_check_eq(controller.matchCount, 0);
 
-    remove_all_bookmarks();
-    cleanup();
-    do_test_finished();
+    PlacesUtils.bookmarks.eraseEverything().then(() => {
+      cleanup();
+      do_test_finished();
+    });
  };
 
   controller.startSearch(SEARCH_STRING);
 }
 
 
 function addAdaptiveFeedback(aUrl, aSearch, aCallback) {
   let observer = {
--- a/toolkit/components/places/tests/unit/test_asyncExecuteLegacyQueries.js
+++ b/toolkit/components/places/tests/unit/test_asyncExecuteLegacyQueries.js
@@ -83,14 +83,13 @@ function run_test()
 }
 
 function run_next_test() {
   if (tests.length == 0) {
     do_test_finished();
     return;
   }
 
-  let test = tests.shift();
-  PlacesTestUtils.clearHistory().then(function() {
-    remove_all_bookmarks();
-    do_execute_soon(test);
-  });
+  Promise.all([
+    PlacesTestUtils.clearHistory(),
+    PlacesUtils.bookmarks.eraseEverything()
+  ]).then(tests.shift());
 }
--- a/toolkit/components/places/tests/unit/test_bookmarks_html.js
+++ b/toolkit/components/places/tests/unit/test_bookmarks_html.js
@@ -99,31 +99,31 @@ add_task(function* setup() {
   // 2. run the test-suite
   // Note: we do not empty the db before this import to catch bugs like 380999
   yield BookmarkHTMLUtils.importFromFile(gBookmarksFileOld, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield testImportedBookmarks();
 
   yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
   yield PlacesTestUtils.promiseAsyncUpdates();
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function* test_import_new()
 {
   // Test importing a Places bookmarks.html file.
   // 1. import bookmarks.exported.html
   // 2. run the test-suite
   yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   yield testImportedBookmarks();
   yield PlacesTestUtils.promiseAsyncUpdates();
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function* test_emptytitle_export()
 {
   // Test exporting and importing with an empty-titled bookmark.
   // 1. import bookmarks
   // 2. create an empty-titled bookmark.
   // 3. export to bookmarks.exported.html
@@ -141,29 +141,29 @@ add_task(function* test_emptytitle_expor
   let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                                 NetUtil.newURI(NOTITLE_URL),
                                                 PlacesUtils.bookmarks.DEFAULT_INDEX,
                                                 "");
   test_bookmarks.unfiled.push({ title: "", url: NOTITLE_URL });
 
   yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
   yield PlacesTestUtils.promiseAsyncUpdates();
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 
   yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield testImportedBookmarks();
 
   // Cleanup.
   test_bookmarks.unfiled.pop();
   PlacesUtils.bookmarks.removeItem(id);
 
   yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
   yield PlacesTestUtils.promiseAsyncUpdates();
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function* test_import_chromefavicon()
 {
   // Test exporting and importing with a bookmark pointing to a chrome favicon.
   // 1. import bookmarks
   // 2. create a bookmark pointing to a chrome favicon.
   // 3. export to bookmarks.exported.html
@@ -209,29 +209,29 @@ add_task(function* test_import_chromefav
   // Change the favicon to check it's really imported again later.
   deferred = Promise.defer();
   PlacesUtils.favicons.setAndFetchFaviconForPage(
                                   PAGE_URI, CHROME_FAVICON_URI_2, true,
                                   PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
                                   deferred.resolve);
   yield deferred.promise;
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 
   yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield testImportedBookmarks();
 
   // Cleanup.
   test_bookmarks.unfiled.pop();
   PlacesUtils.bookmarks.removeItem(id);
 
   yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
   yield PlacesTestUtils.promiseAsyncUpdates();
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function* test_import_ontop()
 {
   // Test importing the exported bookmarks.html file *on top of* the existing
   // bookmarks.
   // 1. empty bookmarks db
   // 2. import the exported bookmarks file
@@ -243,17 +243,17 @@ add_task(function* test_import_ontop()
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
   yield PlacesTestUtils.promiseAsyncUpdates();
 
   yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield testImportedBookmarks();
   yield PlacesTestUtils.promiseAsyncUpdates();
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 function* testImportedBookmarks()
 {
   for (let group in test_bookmarks) {
     do_print("[testImportedBookmarks()] Checking group '" + group + "'");
 
     let root;
--- a/toolkit/components/places/tests/unit/test_bookmarks_html_corrupt.js
+++ b/toolkit/components/places/tests/unit/test_bookmarks_html_corrupt.js
@@ -36,17 +36,17 @@ add_task(function* test_corrupt_database
                    { guid: corruptBookmark.guid });
 
   let bookmarksFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.html");
   if ((yield OS.File.exists(bookmarksFile)))
     yield OS.File.remove(bookmarksFile);
   yield BookmarkHTMLUtils.exportToFile(bookmarksFile);
 
   // Import again and check for correctness.
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield BookmarkHTMLUtils.importFromFile(bookmarksFile, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield database_check();
 });
 
 /*
  * Check for imported bookmarks correctness
  *
--- a/toolkit/components/places/tests/unit/test_bookmarks_json.js
+++ b/toolkit/components/places/tests/unit/test_bookmarks_json.js
@@ -85,35 +85,35 @@ add_task(function test_import_bookmarks(
 add_task(function test_export_bookmarks() {
   bookmarksExportedFile = OS.Path.join(OS.Constants.Path.profileDir,
                                        "bookmarks.exported.json");
   yield BookmarkJSONUtils.exportToFile(bookmarksExportedFile);
   yield PlacesTestUtils.promiseAsyncUpdates();
 });
 
 add_task(function test_import_exported_bookmarks() {
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield testImportedBookmarks();
 });
 
 add_task(function test_import_ontop() {
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield BookmarkJSONUtils.exportToFile(bookmarksExportedFile);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield BookmarkJSONUtils.importFromFile(bookmarksExportedFile, true);
   yield PlacesTestUtils.promiseAsyncUpdates();
   yield testImportedBookmarks();
 });
 
 add_task(function test_clean() {
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 function testImportedBookmarks() {
   for (let group in test_bookmarks) {
     do_print("[testImportedBookmarks()] Checking group '" + group + "'");
 
     let root;
     switch (group) {
--- a/toolkit/components/places/tests/unit/test_bookmarks_restore_notification.js
+++ b/toolkit/components/places/tests/unit/test_bookmarks_restore_notification.js
@@ -48,17 +48,17 @@ var tests = [
     data:       NSIOBSERVER_DATA_JSON,
     folderId:   null,
     run:        function () {
       Task.spawn(function () {
         this.file = yield promiseFile("bookmarks-test_restoreNotification.json");
         addBookmarks();
 
         yield BookmarkJSONUtils.exportToFile(this.file);
-        remove_all_bookmarks();
+        yield PlacesUtils.bookmarks.eraseEverything();
         try {
           yield BookmarkJSONUtils.importFromFile(this.file, true);
         }
         catch (e) {
           do_throw("  Restore should not have failed");
         }
       }.bind(this));
     }
@@ -109,17 +109,17 @@ var tests = [
     finalTopic: NSIOBSERVER_TOPIC_SUCCESS,
     data:       NSIOBSERVER_DATA_HTML,
     folderId:   null,
     run:        function () {
       Task.spawn(function() {
         this.file = yield promiseFile("bookmarks-test_restoreNotification.html");
         addBookmarks();
         yield BookmarkHTMLUtils.exportToFile(this.file);
-        remove_all_bookmarks();
+        yield PlacesUtils.bookmarks.eraseEverything();
         try {
           BookmarkHTMLUtils.importFromFile(this.file, false)
                            .then(null, do_report_unexpected_exception);
         }
         catch (e) {
           do_throw("  Restore should not have failed");
         }
       }.bind(this));
@@ -169,17 +169,17 @@ var tests = [
     finalTopic: NSIOBSERVER_TOPIC_SUCCESS,
     data:       NSIOBSERVER_DATA_HTML_INIT,
     folderId:   null,
     run:        function () {
       Task.spawn(function () {
         this.file = yield promiseFile("bookmarks-test_restoreNotification.init.html");
         addBookmarks();
         yield BookmarkHTMLUtils.exportToFile(this.file);
-        remove_all_bookmarks();
+        yield PlacesUtils.bookmarks.eraseEverything();
         try {
           BookmarkHTMLUtils.importFromFile(this.file, true)
                            .then(null, do_report_unexpected_exception);
         }
         catch (e) {
           do_throw("  Restore should not have failed");
         }
       }.bind(this));
@@ -264,18 +264,17 @@ var successAndFailedObserver = {
     // folder, this will be an integer, otherwise null.
     if (aSubject) {
       do_check_eq(aSubject.QueryInterface(Ci.nsISupportsPRInt64).data,
                   test.folderId);
     }
     else
       do_check_eq(test.folderId, null);
 
-    remove_all_bookmarks();
-    do_execute_soon(doNextTest);
+    PlacesUtils.bookmarks.eraseEverything().then(doNextTest);
   }
 };
 
 // Index of the currently running test.  See doNextTest().
 var currTestIndex = -1;
 
 var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
             getService(Ci.nsINavBookmarksService);
--- a/toolkit/components/places/tests/unit/test_frecency.js
+++ b/toolkit/components/places/tests/unit/test_frecency.js
@@ -281,17 +281,17 @@ add_task(function test_frecency()
   // always search in history + bookmarks, no matter what the default is
   var prefs = Cc["@mozilla.org/preferences-service;1"].
               getService(Ci.nsIPrefBranch);
 
   prefs.setBoolPref("browser.urlbar.suggest.history", true);
   prefs.setBoolPref("browser.urlbar.suggest.bookmark", true);
   prefs.setBoolPref("browser.urlbar.suggest.openpage", false);
   for (let [, test] in Iterator(tests)) {
-    remove_all_bookmarks();
+    yield PlacesUtils.bookmarks.eraseEverything();
     yield PlacesTestUtils.clearHistory();
 
     deferEnsureResults = Promise.defer();
     yield test();
     yield deferEnsureResults.promise;
   }
   for (let type of ["history", "bookmark", "openpage"]) {
     prefs.clearUserPref("browser.urlbar.suggest." + type);
--- a/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js
+++ b/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js
@@ -51,17 +51,17 @@ add_task(function test_addBookmarksAndCh
   do_check_eq(root.getChild(3).pageGuid, "");
   do_check_eq(root.getChild(4).pageGuid, "");
 
   do_check_neq(pageGuidZero, root.getChild(1).pageGuid);
   do_check_neq(root.getChild(1).pageGuid, root.getChild(2).pageGuid);
 
   root.containerOpen = false;
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function test_updateBookmarksAndCheckGuids() {
   let folder = bmsvc.createFolder(bmsvc.placesRoot, "test folder", bmsvc.DEFAULT_INDEX);
   let b1 = bmsvc.insertBookmark(folder, uri("http://test1.com/"),
                                 bmsvc.DEFAULT_INDEX, "1 title");
   let f1 = bmsvc.createFolder(folder, "test folder 2", bmsvc.DEFAULT_INDEX);
 
@@ -80,17 +80,17 @@ add_task(function test_updateBookmarksAn
   let pageGuidOne = root.getChild(1).pageGuid;
   bmsvc.setItemTitle(f1, "test foolder 234");
   do_check_eq(root.getChild(1).title, "test foolder 234");
   do_check_eq(root.getChild(1).bookmarkGuid, bookmarkGuidOne);
   do_check_eq(root.getChild(1).pageGuid, pageGuidOne);
 
   root.containerOpen = false;
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function test_addVisitAndCheckGuid() {
   // add a visit and test page guid and non-existing bookmark guids.
   let now = Date.now() * 1000;
   let sourceURI = uri("http://test4.com/");
   yield PlacesTestUtils.addVisits({ uri: sourceURI });
   do_check_eq(bmsvc.getBookmarkedURIFor(sourceURI), null);
@@ -128,17 +128,17 @@ add_task(function test_addItemsWithInval
   catch(ex) { }
 
   try {
     bmsvc.insertSeparator(folder, bmsvc.DEFAULT_INDEX, INVALID_GUID);
     do_throw("Adding a separator with an invalid guid should fail");
   }
   catch(ex) { }
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function test_addItemsWithGUIDs() {
   const FOLDER_GUID     = "FOLDER--GUID";
   const BOOKMARK_GUID   = "BM------GUID";
   const SEPARATOR_GUID  = "SEP-----GUID";
 
   let folder = bmsvc.createFolder(bmsvc.placesRoot, "test folder",
@@ -149,32 +149,32 @@ add_task(function test_addItemsWithGUIDs
 
   let root = PlacesUtils.getFolderContents(folder).root;
   do_check_eq(root.childCount, 2);
   do_check_eq(root.bookmarkGuid, FOLDER_GUID);
   do_check_eq(root.getChild(0).bookmarkGuid, BOOKMARK_GUID);
   do_check_eq(root.getChild(1).bookmarkGuid, SEPARATOR_GUID);
 
   root.containerOpen = false;
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function test_emptyGUIDIgnored() {
   let folder = bmsvc.createFolder(bmsvc.placesRoot, "test folder",
                                   bmsvc.DEFAULT_INDEX, "");
   do_check_valid_places_guid(PlacesUtils.getFolderContents(folder)
                                         .root.bookmarkGuid);
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
 
 add_task(function test_usingSameGUIDFails() {
   const GUID = "XYZXYZXYZXYZ";
   bmsvc.createFolder(bmsvc.placesRoot, "test folder",
                      bmsvc.DEFAULT_INDEX, GUID);
   try {
     bmsvc.createFolder(bmsvc.placesRoot, "test folder 2",
                        bmsvc.DEFAULT_INDEX, GUID);
     do_throw("Using the same guid twice should fail");
   }
   catch(ex) { }
 
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
 });
--- a/toolkit/components/places/tests/unit/test_removeVisitsByTimeframe.js
+++ b/toolkit/components/places/tests/unit/test_removeVisitsByTimeframe.js
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const NOW = Date.now() * 1000;
 const TEST_URI = uri("http://example.com/");
 const PLACE_URI = uri("place:queryType=0&sort=8&maxResults=10");
 
 function* cleanup() {
   yield PlacesTestUtils.clearHistory();
-  remove_all_bookmarks();
+  yield PlacesUtils.bookmarks.eraseEverything();
   // This is needed to remove place: entries.
   DBConn().executeSimpleSQL("DELETE FROM moz_places");
 }
 
 add_task(function remove_visits_outside_unbookmarked_uri() {
   do_print("*** TEST: Remove some visits outside valid timeframe from an unbookmarked URI");
  
   do_print("Add 10 visits for the URI from way in the past.");
--- a/toolkit/components/places/tests/unit/test_update_frecency_after_delete.js
+++ b/toolkit/components/places/tests/unit/test_update_frecency_after_delete.js
@@ -7,153 +7,145 @@
 /**
  * Bug 455315
  * https://bugzilla.mozilla.org/show_bug.cgi?id=412132
  *
  * Ensures that the frecency of a bookmark's URI is what it should be after the
  * bookmark is deleted.
  */
 
-add_test(function removed_bookmark()
-{
+add_task(function* removed_bookmark() {
   do_print("After removing bookmark, frecency of bookmark's URI should be " +
            "zero if URI is unvisited and no longer bookmarked.");
   const TEST_URI = NetUtil.newURI("http://example.com/1");
-  let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
-                                                TEST_URI,
-                                                PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                "bookmark title");
-  PlacesTestUtils.promiseAsyncUpdates().then(() => {
-    do_print("Bookmarked => frecency of URI should be != 0");
-    do_check_neq(frecencyForUrl(TEST_URI), 0);
+  let bm = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    title: "bookmark title",
+    url: TEST_URI
+  });
 
-    PlacesUtils.bookmarks.removeItem(id);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("Bookmarked => frecency of URI should be != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
+
+  yield PlacesUtils.bookmarks.remove(bm);
 
-    PlacesTestUtils.promiseAsyncUpdates().then(() => {
-      do_print("Unvisited URI no longer bookmarked => frecency should = 0");
-      do_check_eq(frecencyForUrl(TEST_URI), 0);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("Unvisited URI no longer bookmarked => frecency should = 0");
+  do_check_eq(frecencyForUrl(TEST_URI), 0);
 
-      remove_all_bookmarks();
-      PlacesTestUtils.clearHistory().then(run_next_test);
-    });
-  });
+  yield PlacesUtils.bookmarks.eraseEverything();
+  yield PlacesTestUtils.clearHistory();
 });
 
-add_test(function removed_but_visited_bookmark()
-{
+add_task(function* removed_but_visited_bookmark() {
   do_print("After removing bookmark, frecency of bookmark's URI should " +
            "not be zero if URI is visited.");
   const TEST_URI = NetUtil.newURI("http://example.com/1");
-  let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
-                                                TEST_URI,
-                                                PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                "bookmark title");
-  PlacesTestUtils.promiseAsyncUpdates().then(() => {
-    do_print("Bookmarked => frecency of URI should be != 0");
-    do_check_neq(frecencyForUrl(TEST_URI), 0);
+  let bm = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    title: "bookmark title",
+    url: TEST_URI
+  });
+
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("Bookmarked => frecency of URI should be != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-    PlacesTestUtils.addVisits(TEST_URI).then(function () {
-      PlacesUtils.bookmarks.removeItem(id);
+  yield PlacesTestUtils.addVisits(TEST_URI);
+  yield PlacesUtils.bookmarks.remove(bm);
 
-      PlacesTestUtils.promiseAsyncUpdates().then(() => {
-        do_print("*Visited* URI no longer bookmarked => frecency should != 0");
-        do_check_neq(frecencyForUrl(TEST_URI), 0);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("*Visited* URI no longer bookmarked => frecency should != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-        remove_all_bookmarks();
-        PlacesTestUtils.clearHistory().then(run_next_test);
-      });
-    });
-  });
+  yield PlacesUtils.bookmarks.eraseEverything();
+  yield PlacesTestUtils.clearHistory();
 });
 
-add_test(function remove_bookmark_still_bookmarked()
-{
+add_task(function* remove_bookmark_still_bookmarked() {
   do_print("After removing bookmark, frecency of bookmark's URI should " +
            "not be zero if URI is still bookmarked.");
   const TEST_URI = NetUtil.newURI("http://example.com/1");
-  let id1 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
-                                                 TEST_URI,
-                                                 PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                 "bookmark 1 title");
-  let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
-                                                 TEST_URI,
-                                                 PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                 "bookmark 2 title");
-  PlacesTestUtils.promiseAsyncUpdates().then(() => {
-    do_print("Bookmarked => frecency of URI should be != 0");
-    do_check_neq(frecencyForUrl(TEST_URI), 0);
+  let bm1 = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    title: "bookmark 1 title",
+    url: TEST_URI
+  });
+  let bm2 = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    title: "bookmark 2 title",
+    url: TEST_URI
+  });
 
-    PlacesUtils.bookmarks.removeItem(id1);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("Bookmarked => frecency of URI should be != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
+
+  yield PlacesUtils.bookmarks.remove(bm1);
 
-    PlacesTestUtils.promiseAsyncUpdates().then(() => {
-      do_print("URI still bookmarked => frecency should != 0");
-      do_check_neq(frecencyForUrl(TEST_URI), 0);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("URI still bookmarked => frecency should != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-      remove_all_bookmarks();
-      PlacesTestUtils.clearHistory().then(run_next_test);
-    });
-  });
+  yield PlacesUtils.bookmarks.eraseEverything();
+  yield PlacesTestUtils.clearHistory();
 });
 
-add_test(function cleared_parent_of_visited_bookmark()
-{
+add_task(function* cleared_parent_of_visited_bookmark() {
   do_print("After removing all children from bookmark's parent, frecency " +
            "of bookmark's URI should not be zero if URI is visited.");
   const TEST_URI = NetUtil.newURI("http://example.com/1");
-  let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
-                                                TEST_URI,
-                                                PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                "bookmark title");
-  PlacesTestUtils.promiseAsyncUpdates().then(() => {
-    do_print("Bookmarked => frecency of URI should be != 0");
-    do_check_neq(frecencyForUrl(TEST_URI), 0);
+  let bm = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    title: "bookmark title",
+    url: TEST_URI
+  });
+
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("Bookmarked => frecency of URI should be != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-    PlacesTestUtils.addVisits(TEST_URI).then(function () {
-      PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+  yield PlacesTestUtils.addVisits(TEST_URI);
+  PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
 
-      PlacesTestUtils.promiseAsyncUpdates().then(() => {
-        do_print("*Visited* URI no longer bookmarked => frecency should != 0");
-        do_check_neq(frecencyForUrl(TEST_URI), 0);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("*Visited* URI no longer bookmarked => frecency should != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-        remove_all_bookmarks();
-        PlacesTestUtils.clearHistory().then(run_next_test);
-      });
-    });
-  });
+  yield PlacesUtils.bookmarks.eraseEverything();
+  yield PlacesTestUtils.clearHistory();
 });
 
-add_test(function cleared_parent_of_bookmark_still_bookmarked()
-{
+add_task(function* cleared_parent_of_bookmark_still_bookmarked() {
   do_print("After removing all children from bookmark's parent, frecency " +
            "of bookmark's URI should not be zero if URI is still " +
            "bookmarked.");
   const TEST_URI = NetUtil.newURI("http://example.com/1");
-  let id1 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
-                                                 TEST_URI,
-                                                 PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                 "bookmark 1 title");
-
-  let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
-                                                TEST_URI,
-                                                PlacesUtils.bookmarks.DEFAULT_INDEX,
-                                                "bookmark 2 title");
-  PlacesTestUtils.promiseAsyncUpdates().then(() => {
-    do_print("Bookmarked => frecency of URI should be != 0");
-    do_check_neq(frecencyForUrl(TEST_URI), 0);
-
-    PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+  let bm1 = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.toolbarGuid,
+    title: "bookmark 1 title",
+    url: TEST_URI
+  });
 
-    PlacesTestUtils.promiseAsyncUpdates().then(() => {
-      // URI still bookmarked => frecency should != 0.
-      do_check_neq(frecencyForUrl(TEST_URI), 0);
-
-      remove_all_bookmarks();
-      PlacesTestUtils.clearHistory().then(run_next_test);
-    });
+  let folder = yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    type: PlacesUtils.bookmarks.TYPE_FOLDER,
+    title: "bookmark 2 folder"
+  });
+  let bm2 = yield PlacesUtils.bookmarks.insert({
+    title: "bookmark 2 title",
+    parentGuid: folder.guid,
+    url: TEST_URI
   });
-});
 
-///////////////////////////////////////////////////////////////////////////////
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  do_print("Bookmarked => frecency of URI should be != 0");
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
 
-function run_test()
-{
-  run_next_test();
-}
+  yield PlacesUtils.bookmarks.remove(folder);
+  yield PlacesTestUtils.promiseAsyncUpdates();
+  // URI still bookmarked => frecency should != 0.
+  do_check_neq(frecencyForUrl(TEST_URI), 0);
+
+  yield PlacesUtils.bookmarks.eraseEverything();
+  yield PlacesTestUtils.clearHistory();
+});
--- a/toolkit/components/places/tests/unit/test_utils_getURLsForContainerNode.js
+++ b/toolkit/components/places/tests/unit/test_utils_getURLsForContainerNode.js
@@ -164,16 +164,17 @@ function check_uri_nodes(aQuery, aOption
   var root = result.root;
   root.containerOpen = true;
   var node = root.getChild(0);
   do_check_eq(PU.hasChildURIs(node), aExpectedURINodes > 0);
   do_check_eq(PU.getURLsForContainerNode(node).length, aExpectedURINodes);
   root.containerOpen = false;
 }
 
-function run_test() {
-  tests.forEach(function(aTest) {
-                  remove_all_bookmarks();
-                  aTest();
-                });
+add_task(function* () {
+  for (let test of tests) {
+    yield PlacesUtils.bookmarks.eraseEverything();
+    test();
+  }
+
   // Cleanup.
-  remove_all_bookmarks();
-}
+  yield PlacesUtils.bookmarks.eraseEverything();
+});
--- a/toolkit/devtools/Loader.jsm
+++ b/toolkit/devtools/Loader.jsm
@@ -311,20 +311,35 @@ DevToolsLoader.prototype = {
    *    The property name.
    * @param String module
    *    The module path.
    * @param Boolean destructure
    *    Pass true if the property name is a member of the module's exports.
    */
   lazyRequireGetter: function (obj, property, module, destructure) {
     Object.defineProperty(obj, property, {
-      get: () => destructure
-        ? this.require(module)[property]
-        : this.require(module || property),
-      configurable: true
+      get: () => {
+        // Redefine this accessor property as a data property.
+        // Delete it first, to rule out "too much recursion" in case obj is
+        // a proxy whose defineProperty handler might unwittingly trigger this
+        // getter again.
+        delete obj[property];
+        let value = destructure
+          ? this.require(module)[property]
+          : this.require(module || property);
+        Object.defineProperty(obj, property, {
+          value,
+          writable: true,
+          configurable: true,
+          enumerable: true
+        });
+        return value;
+      },
+      configurable: true,
+      enumerable: true
     });
   },
 
   /**
    * Add a URI to the loader.
    * @param string id
    *    The module id that can be used within the loader to refer to this module.
    * @param string uri
--- a/toolkit/devtools/server/actors/inspector.js
+++ b/toolkit/devtools/server/actors/inspector.js
@@ -408,16 +408,20 @@ var NodeActor = exports.NodeActor = prot
           this.processHandlerForEvent(node, events, dbg, eventInfo);
         }
       } catch(e) {
         // An object attached to the node looked like a listener but wasn't...
         // do nothing.
       }
     }
 
+    events.sort((a, b) => {
+      return a.type.localeCompare(b.type);
+    });
+
     return events;
   },
 
   /**
    * Process a handler
    *
    * @param  {Node} node
    *         The node for which we want information.
@@ -1401,36 +1405,45 @@ var WalkerActor = protocol.ActorClass({
    * Return all parents of the given node, ordered from immediate parent
    * to root.
    * @param NodeActor node
    *    The node whose parents are requested.
    * @param object options
    *    Named options, including:
    *    `sameDocument`: If true, parents will be restricted to the same
    *      document as the node.
+   *    `sameTypeRootTreeItem`: If true, this will not traverse across
+   *     different types of docshells.
    */
   parents: method(function(node, options={}) {
     if (isNodeDead(node)) {
       return [];
     }
 
     let walker = this.getDocumentWalker(node.rawNode);
     let parents = [];
     let cur;
     while((cur = walker.parentNode())) {
-      if (options.sameDocument && cur.ownerDocument != node.rawNode.ownerDocument) {
+      if (options.sameDocument && nodeDocument(cur) != nodeDocument(node.rawNode)) {
         break;
       }
+
+      if (options.sameTypeRootTreeItem &&
+          nodeDocshell(cur).sameTypeRootTreeItem != nodeDocshell(node.rawNode).sameTypeRootTreeItem) {
+        break;
+      }
+
       parents.push(this._ref(cur));
     }
     return parents;
   }, {
     request: {
       node: Arg(0, "domnode"),
-      sameDocument: Option(1)
+      sameDocument: Option(1),
+      sameTypeRootTreeItem: Option(1)
     },
     response: {
       nodes: RetVal("array:domnode")
     },
   }),
 
   parentNode: function(node) {
     let walker = this.getDocumentWalker(node.rawNode);
@@ -3217,17 +3230,17 @@ var WalkerFront = exports.WalkerFront = 
       throw Error("Could not find client side for actor " + this.actorID);
     }
     let nodeActor = walkerActor._ref(rawNode);
 
     // Pass the node through a read/write pair to create the client side actor.
     let nodeType = types.getType("domnode");
     let returnNode = nodeType.read(nodeType.write(nodeActor, walkerActor), this);
     let top = returnNode;
-    let extras = walkerActor.parents(nodeActor);
+    let extras = walkerActor.parents(nodeActor, {sameTypeRootTreeItem: true});
     for (let extraActor of extras) {
       top = nodeType.read(nodeType.write(extraActor, walkerActor), this);
     }
 
     if (top !== this.rootNode) {
       // Imported an already-orphaned node.
       this._orphaned.add(top);
       walkerActor._orphaned.add(this.conn._transport._serverConnection.getActor(top.actorID));
@@ -3510,16 +3523,26 @@ exports._documentWalker = DocumentWalker
 
 function nodeDocument(node) {
   if (Cu.isDeadWrapper(node)) {
     return null;
   }
   return node.ownerDocument || (node.nodeType == Ci.nsIDOMNode.DOCUMENT_NODE ? node : null);
 }
 
+function nodeDocshell(node) {
+  let doc = node ? nodeDocument(node) : null;
+  let win = doc ? doc.defaultView : null;
+  if (win) {
+    return win.
+           QueryInterface(Ci.nsIInterfaceRequestor).
+           getInterface(Ci.nsIDocShell);
+  }
+}
+
 function isNodeDead(node) {
   return !node || !node.rawNode || Cu.isDeadWrapper(node.rawNode);
 }
 
 /**
  * Wrapper for inDeepTreeWalker.  Adds filtering to the traversal methods.
  * See inDeepTreeWalker for more information about the methods.
  *
--- a/toolkit/devtools/server/actors/styles.js
+++ b/toolkit/devtools/server/actors/styles.js
@@ -1015,17 +1015,18 @@ var StyleRuleActor = protocol.ActorClass
       case Ci.nsIDOMCSSRule.STYLE_RULE:
         form.selectors = CssLogic.getSelectors(this.rawRule);
         form.cssText = this.rawStyle.cssText || "";
         break;
       case ELEMENT_STYLE:
         // Elements don't have a parent stylesheet, and therefore
         // don't have an associated URI.  Provide a URI for
         // those.
-        form.href = this.rawNode.ownerDocument.location.href;
+        let doc = this.rawNode.ownerDocument;
+        form.href = doc.location ? doc.location.href : "";
         form.cssText = this.rawStyle.cssText || "";
         break;
       case Ci.nsIDOMCSSRule.CHARSET_RULE:
         form.encoding = this.rawRule.encoding;
         break;
       case Ci.nsIDOMCSSRule.IMPORT_RULE:
         form.href = this.rawRule.href;
         break;
@@ -1226,17 +1227,17 @@ var StyleRuleFront = protocol.FrontClass
     return this.conn.getActor(this._form.element);
   },
 
   get href() {
     if (this._form.href) {
       return this._form.href;
     }
     let sheet = this.parentStyleSheet;
-    return sheet.href;
+    return sheet ? sheet.href : "";
   },
 
   get nodeHref() {
     let sheet = this.parentStyleSheet;
     return sheet ? sheet.nodeHref : "";
   },
 
   get location()
--- a/toolkit/devtools/server/actors/utils/TabSources.js
+++ b/toolkit/devtools/server/actors/utils/TabSources.js
@@ -1,15 +1,21 @@
-const Services = require("Services");
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
 const { Ci, Cu } = require("chrome");
+const Services = require("Services");
 const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
+const { dbg_assert, fetch } = DevToolsUtils;
 const EventEmitter = require("devtools/toolkit/event-emitter");
-const { dbg_assert, fetch } = require("devtools/toolkit/DevToolsUtils");
 const { OriginalLocation, GeneratedLocation, getOffsetColumn } = require("devtools/server/actors/common");
-const { resolve } = require("promise");
+const { resolve } = Promise;
 
 loader.lazyRequireGetter(this, "SourceActor", "devtools/server/actors/script", true);
 loader.lazyRequireGetter(this, "isEvalSource", "devtools/server/actors/script", true);
 loader.lazyRequireGetter(this, "SourceMapConsumer", "source-map", true);
 loader.lazyRequireGetter(this, "SourceMapGenerator", "source-map", true);
 
 /**
  * Manages the sources for a thread. Handles source maps, locations in the
--- a/toolkit/devtools/server/actors/webbrowser.js
+++ b/toolkit/devtools/server/actors/webbrowser.js
@@ -3,24 +3,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 let { Ci, Cu } = require("chrome");
 let Services = require("Services");
+let promise = require("promise");
 let { ActorPool, createExtraActors, appendExtraActors } = require("devtools/server/actors/common");
 let { DebuggerServer } = require("devtools/server/main");
 let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
 let { dbg_assert } = DevToolsUtils;
 let { TabSources, isHiddenSource } = require("./utils/TabSources");
 let makeDebugger = require("./utils/make-debugger");
 
-let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 loader.lazyRequireGetter(this, "RootActor", "devtools/server/actors/root", true);
 loader.lazyRequireGetter(this, "AddonThreadActor", "devtools/server/actors/script", true);
 loader.lazyRequireGetter(this, "ThreadActor", "devtools/server/actors/script", true);
 loader.lazyRequireGetter(this, "mapURIToAddonID", "devtools/server/actors/utils/map-uri-to-addon-id");
 loader.lazyImporter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");