Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 22 Apr 2014 13:07:17 -0700
changeset 198146 ed7386e724988fb2281e96288d48833c54a6dfa1
parent 198145 1042d0e085d3e90f4534eb2ae31051efc24afe81 (current diff)
parent 198108 1ab07aa4d004229b7537e7366c8d5ce1eea0d8be (diff)
child 198147 c8f78e4ede49f777f302ad9faac26a8e3415ace6
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound.
browser/devtools/inspector/test/browser_inspector_changes.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -44,17 +44,17 @@ pref("offline-apps.allow_by_default", tr
 pref("network.protocol-handler.warn-external.tel", false);
 pref("network.protocol-handler.warn-external.mailto", false);
 pref("network.protocol-handler.warn-external.vnd.youtube", false);
 
 /* protocol expose prefs */
 // By default, all protocol handlers are exposed. This means that the browser
 // will response to openURL commands for all URL types. It will also try to open
 // link clicks inside the browser before failing over to the system handlers.
-pref("network.protocol-handler.expose.rtsp", false);
+pref("network.protocol-handler.expose.rtsp", true);
 
 /* http prefs */
 pref("network.http.pipelining", true);
 pref("network.http.pipelining.ssl", true);
 pref("network.http.proxy.pipelining", true);
 pref("network.http.pipelining.maxrequests" , 6);
 pref("network.http.keep-alive.timeout", 600);
 pref("network.http.max-connections", 20);
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,21 +14,21 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="55bcc2d7e44dc805c24b57d1e783fc26e8a2ee86"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="52720b94a4f709d5f96c23b2d63c398e7002ecb9"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0292e64ef8451df104dcf9ac3b2c6749b81684dd"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="85f9690323b235f4dcf2901ea2240d3c60fc22a0"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- 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="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <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"/>
@@ -123,14 +123,14 @@
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="09485b73629856b21b2ed6073e327ab0e69a1189"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8afce6d5d48b71b6e7cb917179fb6147fb747521"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9a00b3db898a83ef0766baa93e935e525572899e"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="72e3a520e3c700839f07ba0113fd527b923c3330"/>
   <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="baaf899afb158b9530690002f3656e958e3eb047"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
 </manifest>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--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="52c909ccead537f8f9dbf634f3e6639078a8b0bd">
+  <project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
@@ -114,20 +114,20 @@
   <project name="platform/prebuilts/qemu-kernel" path="prebuilts/qemu-kernel" revision="0efba6f55dca4756b05f81b6cac3d5f28297da79"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
   <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
   <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
   <project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
   <project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
-  <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="ee814270f52127febfcf29bacf9f1b327d7c4c29"/>
-  <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="a706bf388e30ec1f5273cf72cd0156e429f23fac"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="0909f27aaa6bf55314edddb48bb1cd6296a2d55c"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3ef6c54fd5bba6fbd4c11f3870ab3aa32693f0da"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="e5dba2723b3e417b107cf9546fb8e10b98e977ae"/>
+  <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="ee814270f52127febfcf29bacf9f1b327d7c4c29"/>
+  <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
 </manifest>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,21 +14,21 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="55bcc2d7e44dc805c24b57d1e783fc26e8a2ee86"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="52720b94a4f709d5f96c23b2d63c398e7002ecb9"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0292e64ef8451df104dcf9ac3b2c6749b81684dd"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="85f9690323b235f4dcf2901ea2240d3c60fc22a0"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -13,17 +13,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "3f54f719dc145f1544db67881a48819559ecb71b", 
+    "revision": "b209dbf62facaae103d9a577ef885d429a431d6c", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="f0463704888881b8ed1619e8d4b0d851b0e0311b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0a4d2dea25a7162ee43db3a0db817798b70e7521"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -658,32 +658,144 @@ pref("plugins.hide_infobar_for_outdated_
 
 pref("plugins.update.url", "https://www.mozilla.org/%LOCALE%/plugincheck/");
 pref("plugins.update.notifyUser", false);
 
 pref("plugins.click_to_play", true);
 
 pref("plugins.hideMissingPluginsNotification", false);
 
-#ifdef RELEASE_BUILD
-// For now, plugins other than Java and Flash are enabled in beta/release
-// and click-to-activate in earlier channels.
-pref("plugin.default.state", 2);
-#else
 pref("plugin.default.state", 1);
-#endif
 
 // Plugins bundled in XPIs are enabled by default.
 pref("plugin.defaultXpi.state", 2);
 
 // Flash is enabled by default, and Java is click-to-activate by default on
 // all channels.
 pref("plugin.state.flash", 2);
 pref("plugin.state.java", 1);
 
+// Whitelist Requests
+
+// Unity player, bug 979849
+#ifdef XP_WIN
+pref("plugin.state.npunity3d", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.unity web player", 2);
+#endif
+
+// Cisco Jabber SDK, bug 980133
+#ifdef XP_WIN
+pref("plugin.state.npciscowebcommunicator", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.ciscowebcommunicator", 2);
+#endif
+
+// McAfee Security Scanner detection plugin, bug 980772
+#ifdef XP_WIN
+pref("plugin.state.npmcafeemss", 2);
+#endif
+
+// Cisco VGConnect for directv.com, bug 981403
+#ifdef XP_WIN
+pref("plugin.state.npplayerplugin", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.playerplugin", 2);
+#endif
+
+// Cisco Jabber Client, bug 981905
+#ifdef XP_WIN
+pref("plugin.state.npchip", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.cisco jabber guest plug-in", 2);
+#endif
+
+// Estonian ID-card plugin, bug 982045
+#ifdef XP_WIN
+pref("plugin.state.npesteid-firefox-plugin", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.esteidfirefoxplugin", 2);
+#endif
+#ifdef UNIX_BUT_NOT_MAC
+pref("plugin.state.npesteid-firefox-plugin", 2);
+#endif
+
+// coupons.com, bug 984441
+#ifdef XP_WIN
+pref("plugin.state.npmozcouponprinter", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.couponprinter-firefox_v", 2);
+#endif
+
+// Nexus Personal BankID, bug 987056
+pref("plugin.state.npbispbrowser", 2);
+
+// Gradecam, bug 988119
+#ifdef XP_WIN
+pref("plugin.state.npgcplugin", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.gcplugin", 2);
+#endif
+
+// Smart Card Plugin, bug 988781
+#ifdef XP_WIN
+pref("plugin.state.npwebcard", 2);
+#endif
+
+// Cisco WebEx, bug 989096
+#ifdef XP_WIN
+pref("plugin.state.npatgpc", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.webex", 2);
+#endif
+#ifdef UNIX_BUT_NOT_MAC
+pref("plugin.state.npatgpc", 2);
+#endif
+
+// Skype, bug 990067
+#ifdef XP_WIN
+pref("plugin.state.npskypewebplugin", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.skypewebplugin", 2);
+#endif
+
+// Facebook video calling, bug 990068
+#ifdef XP_WIN
+pref("plugin.state.npfacebookvideocalling", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.facebookvideocalling", 2);
+#endif
+
+// MS Office Lync plugin, bug 990069
+#ifdef XP_WIN
+pref("plugin.state.npmeetingjoinpluginoc", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.lwaplugin", 2);
+#endif
+
+// VidyoWeb, bug 990286
+#ifdef XP_WIN
+pref("plugin.state.npvidyoweb", 2);
+#endif
+#ifdef XP_MACOSX
+pref("plugin.state.npvidyoweb", 2);
+pref("plugin.state.vidyoweb", 2);
+#endif
+
 // display door hanger if flash not installed
 pref("plugins.notifyMissingFlash", true);
 
 #ifdef XP_WIN
 pref("browser.preferences.instantApply", false);
 #else
 pref("browser.preferences.instantApply", true);
 #endif
@@ -1281,17 +1393,17 @@ pref("devtools.hud.loglimit.console", 20
 pref("devtools.eyedropper.zoom", 6);
 
 // The developer tools editor configuration:
 // - tabsize: how many spaces to use when a Tab character is displayed.
 // - expandtab: expand Tab characters to spaces.
 // - keymap: which keymap to use (can be 'default', 'emacs' or 'vim')
 // - autoclosebrackets: whether to permit automatic bracket/quote closing.
 // - detectindentation: whether to detect the indentation from the file
-pref("devtools.editor.tabsize", 4);
+pref("devtools.editor.tabsize", 2);
 pref("devtools.editor.expandtab", true);
 pref("devtools.editor.keymap", "default");
 pref("devtools.editor.autoclosebrackets", true);
 pref("devtools.editor.detectindentation", true);
 
 // Enable the Font Inspector
 pref("devtools.fontinspector.enabled", true);
 
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -117,46 +117,35 @@ tabbrowser {
 }
 
 .tabbrowser-tab:not([pinned]):not([fadein]) {
   max-width: 0.1px;
   min-width: 0.1px;
   visibility: hidden;
 }
 
-.tab-background,
 .tab-close-button,
-.tab-label {
+.tab-background {
   /* Explicitly set the visibility to override the value (collapsed)
    * we inherit from #TabsToolbar[collapsed] upon opening a browser window. */
   visibility: visible;
 }
 
+.tab-close-button[fadein],
 .tab-background[fadein] {
   /* This transition is only wanted for opening tabs. */
   transition: visibility 0ms 25ms;
 }
 
+.tab-close-button:not([fadein]),
 .tab-background:not([fadein]) {
   visibility: hidden;
 }
 
-.tab-close-button[fadein],
-.tab-label[fadein] {
-  /* This transition is only wanted for opening tabs. */
-  transition: opacity 70ms 230ms,
-              visibility 0ms 230ms;
-}
-
-.tab-close-button:not([fadein]),
-.tab-label:not([fadein]) {
-  visibility: collapse;
-  opacity: .6;
-}
-
+.tab-label:not([fadein]),
 .tab-throbber:not([fadein]),
 .tab-icon-image:not([fadein]) {
   display: none;
 }
 
 .tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
   position: fixed !important;
   display: block; /* position:fixed already does this (bug 579776), but let's be explicit */
--- a/browser/components/customizableui/test/browser_968447_bookmarks_toolbar_items_in_panel.js
+++ b/browser/components/customizableui/test/browser_968447_bookmarks_toolbar_items_in_panel.js
@@ -22,11 +22,11 @@ add_task(function() {
   let newWin = yield openAndLoadWindow();
   yield newWin.PanelUI.show();
   let newWinBookmarksToolbarPlaceholder = newWin.document.getElementById(buttonId);
   ok(newWinBookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
      "Button in new window should have toolbarbutton-1 class");
   is(newWinBookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
      "Button in new window should have 'wrap' attribute");
   yield newWin.PanelUI.hide();
-  newWin.close();
+  yield promiseWindowClosed(newWin);
   CustomizableUI.reset();
 });
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -128,17 +128,16 @@ PlacesController.prototype = {
     if (PlacesUIUtils.useAsyncTransactions) {
       switch (aCommand) {
       case "cmd_cut":
       case "placesCmd_cut":
       case "cmd_copy":
       case "cmd_paste":
       case "cmd_delete":
       case "placesCmd_delete":
-      case "placesCmd_moveBookmarks":
       case "cmd_paste":
       case "placesCmd_paste":
       case "placesCmd_new:folder":
       case "placesCmd_new:bookmark":
       case "placesCmd_createBookmark":
         return false;
       }
     }
--- a/browser/components/places/content/moveBookmarks.js
+++ b/browser/components/places/content/moveBookmarks.js
@@ -18,37 +18,48 @@ var gMoveBookmarksDialog = {
     this._nodes = window.arguments[0];
 
     this.foldersTree.place =
       "place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder=" +
       PlacesUIUtils.allBookmarksFolderId;
   },
 
   onOK: function MBD_onOK(aEvent) {
-    var selectedNode = this.foldersTree.selectedNode;
-    NS_ASSERT(selectedNode,
-              "selectedNode must be set in a single-selection tree with initial selection set");
-    var selectedFolderID = PlacesUtils.getConcreteItemId(selectedNode);
+    let selectedNode = this.foldersTree.selectedNode;
+    let selectedFolderId = PlacesUtils.getConcreteItemId(selectedNode);
+
+    if (!PlacesUIUtils.useAsyncTransactions) {
+      let transactions = [];
+      for (var i=0; i < this._nodes.length; i++) {
+        // Nothing to do if the node is already under the selected folder
+        if (this._nodes[i].parent.itemId == selectedFolderId)
+          continue;
 
-    var transactions = [];
-    for (var i=0; i < this._nodes.length; i++) {
-      // Nothing to do if the node is already under the selected folder
-      if (this._nodes[i].parent.itemId == selectedFolderID)
-        continue;
-
-      let txn = new PlacesMoveItemTransaction(this._nodes[i].itemId,
-                                              selectedFolderID,
-                                              PlacesUtils.bookmarks.DEFAULT_INDEX);
-      transactions.push(txn);
+        let txn = new PlacesMoveItemTransaction(this._nodes[i].itemId,
+                                                selectedFolderId,
+                                                PlacesUtils.bookmarks.DEFAULT_INDEX);
+        transactions.push(txn);
+      }
+      if (transactions.length != 0) {
+        let txn = new PlacesAggregatedTransaction("Move Items", transactions);
+        PlacesUtils.transactionManager.doTransaction(txn);
+      }
+      return;
     }
 
-    if (transactions.length != 0) {
-      let txn = new PlacesAggregatedTransaction("Move Items", transactions);
-      PlacesUtils.transactionManager.doTransaction(txn);
-    }
+    PlacesTransactions.transact(function* () {
+      let newParentGUID = yield PlacesUtils.promiseItemGUID(selectedFolderId);
+      for (let node of this._nodes) {
+        // Nothing to do if the node is already under the selected folder.
+        if (node.parent.itemId == selectedFolderId)
+          continue;
+        yield PlacesTransactions.MoveItem({ GUID: node.bookmarkGuid
+                                          , newParentGUID: newParentGUID });
+      }
+    }.bind(this)).then(null, Components.utils.reportError);
   },
 
   newFolder: function MBD_newFolder() {
     // The command is disabled when the tree is not focused
     this.foldersTree.focus();
     goDoCommand("placesCmd_new:folder");
   }
 };
--- a/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-01.js
@@ -47,17 +47,17 @@ function test(){
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       })
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n    "),
+  ok(!gEditor.getText().contains("\n  "),
     "The source shouldn't be pretty printed yet.");
 }
 
 function testSecondSourceLabel(){
   ok(gSources.containsValue(EXAMPLE_URL + gSecondSourceLabel),
     "Second source url is correct.");
 }
 
@@ -88,17 +88,17 @@ function enableAutoPrettyPrint(){
 function testAutoPrettyPrintOff(){
   is(gPrefs.autoPrettyPrint, false,
     "The auto-pretty-print pref should be off.");
   isnot(gOptions._autoPrettyPrint.getAttribute("checked"), "true",
        "The Auto pretty print menu item should not be checked.");
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n    "),
+  ok(gEditor.getText().contains("\n  "),
     "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gDebuggee = null;
   gPanel = null;
   gDebugger = null;
--- a/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_auto-pretty-print-02.js
@@ -58,17 +58,17 @@ function test(){
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       })
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n    "),
+  ok(!gEditor.getText().contains("\n  "),
     "The source shouldn't be pretty printed yet.");
 }
 
 function testFirstSourceLabel(){
   ok(gSources.containsValue(EXAMPLE_URL + gFirstSourceLabel),
     "First source url is correct.");
 }
 
@@ -91,17 +91,17 @@ function testPrettyPrintButtonOn(){
 
 function disableAutoPrettyPrint(){
   gOptions._autoPrettyPrint.setAttribute("checked", "false");
   gOptions._toggleAutoPrettyPrint();
   gOptions._onPopupHidden();
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n    "),
+  ok(gEditor.getText().contains("\n  "),
     "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gDebuggee = null;
   gPanel = null;
   gDebugger = null;
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-01.js
@@ -33,45 +33,45 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n    "),
+  ok(!gEditor.getText().contains("\n  "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 function testProgressBarShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 2, "The progress bar should be shown");
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n    "),
+  ok(gEditor.getText().contains("\n  "),
      "The source should be pretty printed.")
 }
 
 function testEditorShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 0, "The editor should be shown");
 }
 
 function testSourceIsStillPretty() {
   const deferred = promise.defer();
 
   const { source } = gSources.selectedItem.attachment;
   gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
-    ok(text.contains("\n    "),
+    ok(text.contains("\n  "),
        "Subsequent calls to getText return the pretty printed source.");
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-02.js
@@ -38,17 +38,17 @@ function selectContextMenuItem() {
   once(gContextMenu, "popupshown").then(() => {
     const menuItem = gDebugger.document.getElementById("se-dbg-cMenu-prettyPrint");
     menuItem.click();
   });
   gContextMenu.openPopup(gEditor.container, "overlap", 0, 0, true, false);
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n    "),
+  ok(gEditor.getText().contains("\n  "),
      "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gDebuggee = null;
   gPanel = null;
   gDebugger = null;
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-11.js
@@ -32,26 +32,26 @@ function test() {
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n    "),
+  ok(!gEditor.getText().contains("\n  "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n    "),
+  ok(gEditor.getText().contains("\n  "),
      "The source should be pretty printed.")
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gDebuggee = null;
   gPanel = null;
   gDebugger = null;
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-13.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-13.js
@@ -36,45 +36,45 @@ function test() {
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
-  ok(!gEditor.getText().contains("\n    "),
+  ok(!gEditor.getText().contains("\n  "),
      "The source shouldn't be pretty printed yet.");
 }
 
 function clickPrettyPrintButton() {
   gDebugger.document.getElementById("pretty-print").click();
 }
 
 function testProgressBarShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 2, "The progress bar should be shown");
 }
 
 function testSourceIsPretty() {
-  ok(gEditor.getText().contains("\n    "),
+  ok(gEditor.getText().contains("\n  "),
      "The source should be pretty printed.")
 }
 
 function testEditorShown() {
   const deck = gDebugger.document.getElementById("editor-deck");
   is(deck.selectedIndex, 0, "The editor should be shown");
 }
 
 function testSourceIsStillPretty() {
   const deferred = promise.defer();
 
   const { source } = gSources.selectedItem.attachment;
   gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
-    ok(text.contains("\n    "),
+    ok(text.contains("\n  "),
        "Subsequent calls to getText return the pretty printed source.");
     deferred.resolve();
   });
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/inspector/test/browser.ini
+++ b/browser/devtools/inspector/test/browser.ini
@@ -23,17 +23,16 @@ support-files =
 [browser_inspector_bug_674871.js]
 [browser_inspector_bug_699308_iframe_navigation.js]
 [browser_inspector_bug_817558_delete_node.js]
 [browser_inspector_bug_831693_combinator_suggestions.js]
 [browser_inspector_bug_831693_input_suggestion.js]
 # [browser_inspector_bug_831693_searchbox_panel_navigation.js]
 # Disabled for too many intermittent failures (bug 851349)
 [browser_inspector_bug_840156_destroy_after_navigation.js]
-[browser_inspector_changes.js]
 [browser_inspector_cmd_inspect.js]
 [browser_inspector_dead_node_exception.js]
 [browser_inspector_destroyselection.js]
 [browser_inspector_highlighter.js]
 [browser_inspector_iframeTest.js]
 [browser_inspector_infobar.js]
 [browser_inspector_initialization.js]
 [browser_inspector_invalidate.js]
deleted file mode 100644
--- a/browser/devtools/inspector/test/browser_inspector_changes.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-let doc;
-let testDiv;
-
-function test() {
-  let inspector;
-
-  function createDocument()
-  {
-    doc.body.innerHTML = '<div id="testdiv">Test div!</div>';
-    doc.title = "Inspector Change Test";
-    openInspector(runInspectorTests);
-  }
-
-  function getInspectorRuleProp(aName)
-  {
-    let ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
-    let inlineStyles = ruleview._elementStyle.rules[0];
-
-    for (let key in inlineStyles.textProps) {
-      let prop = inlineStyles.textProps[key];
-      if (prop.name == aName) {
-        return prop;
-      }
-    }
-    return null;
-  }
-
-  function runInspectorTests(aInspector)
-  {
-    inspector = aInspector;
-
-    waitForView("computedview", () => {
-      info("Computed View ready");
-      inspector.sidebar.select("computedview");
-
-      testDiv = doc.getElementById("testdiv");
-
-      testDiv.style.fontSize = "10px";
-
-      // Start up the style inspector panel...
-      inspector.once("computed-view-refreshed", () => {
-        executeSoon(computedStylePanelTests);
-      });
-      inspector.selection.setNode(testDiv);
-    });
-  }
-
-  function computedStylePanelTests()
-  {
-    let computedview = inspector.sidebar.getWindowForTab("computedview").computedview;
-    ok(computedview, "Style Panel has a cssHtmlTree");
-
-    let fontSize = getComputedPropertyValue("font-size");
-    is(fontSize, "10px", "Style inspector should be showing the correct font size.");
-
-    testDiv.style.cssText = "font-size: 15px; color: red;";
-
-    // Wait until layout-change fires from mutation to skip earlier refresh event
-    inspector.once("layout-change", () => {
-      inspector.once("computed-view-refreshed", () => {
-        executeSoon(computedStylePanelAfterChange);
-      });
-    });
-  }
-
-  function computedStylePanelAfterChange()
-  {
-    let fontSize = getComputedPropertyValue("font-size");
-    is(fontSize, "15px", "Style inspector should be showing the new font size.");
-
-    let color = getComputedPropertyValue("color");
-    is(color, "#F00", "Style inspector should be showing the new color.");
-
-    computedStylePanelNotActive();
-  }
-
-  function computedStylePanelNotActive()
-  {
-    // Tests changes made while the style panel is not active.
-    inspector.sidebar.select("ruleview");
-
-    testDiv.style.cssText = "font-size: 20px; color: blue; text-align: center";
-
-    inspector.once("computed-view-refreshed", () => {
-      executeSoon(computedStylePanelAfterSwitch);
-    });
-  }
-
-  function computedStylePanelAfterSwitch()
-  {
-    let fontSize = getComputedPropertyValue("font-size");
-    is(fontSize, "20px", "Style inspector should be showing the new font size.");
-
-    let color = getComputedPropertyValue("color");
-    is(color, "#00F", "Style inspector should be showing the new color.");
-
-    let textAlign = getComputedPropertyValue("text-align");
-    is(textAlign, "center", "Style inspector should be showing the new text align.");
-
-    rulePanelTests();
-  }
-
-  function rulePanelTests()
-  {
-    inspector.sidebar.select("ruleview");
-    let ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview;
-    ok(ruleview, "Style Panel has a ruleview");
-
-    let propView = getInspectorRuleProp("text-align");
-    is(propView.value, "center", "Style inspector should be showing the new text align.");
-
-    testDiv.style.cssText = "font-size: 3em; color: lightgoldenrodyellow; text-align: right; text-transform: uppercase";
-
-    inspector.once("rule-view-refreshed", () => {
-      executeSoon(rulePanelAfterChange);
-    });
-  }
-
-  function rulePanelAfterChange()
-  {
-    let propView = getInspectorRuleProp("text-align");
-    is(propView.value, "right", "Style inspector should be showing the new text align.");
-
-    let propView = getInspectorRuleProp("color");
-    is(propView.value, "lightgoldenrodyellow", "Style inspector should be showing the new color.")
-
-    let propView = getInspectorRuleProp("font-size");
-    is(propView.value, "3em", "Style inspector should be showing the new font size.");
-
-    let propView = getInspectorRuleProp("text-transform");
-    is(propView.value, "uppercase", "Style inspector should be showing the new text transform.");
-
-    finishTest();
-  }
-
-  function finishTest()
-  {
-    gBrowser.removeCurrentTab();
-    finish();
-  }
-
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js";
-}
--- a/browser/devtools/sourceeditor/autocomplete.js
+++ b/browser/devtools/sourceeditor/autocomplete.js
@@ -164,17 +164,35 @@ function onEditorKeypress({ ed, Editor }
 
   // Do not try to autocomplete with multiple selections.
   if (ed.hasMultipleSelections()) {
     private.doNotAutocomplete = true;
     private.popup.hidePopup();
     return;
   }
 
+  if ((event.ctrlKey || event.metaKey) && event.keyCode == event.DOM_VK_SPACE) {
+    // When Ctrl/Cmd + Space is pressed, two simultaneous keypresses are emitted
+    // first one for just the Ctrl/Cmd and second one for combo. The first one
+    // leave the private.doNotAutocomplete as true, so we have to make it false
+    private.doNotAutocomplete = false;
+    return;
+  }
+
+  if (event.ctrlKey || event.metaKey || event.altKey) {
+    private.doNotAutocomplete = true;
+    private.popup.hidePopup();
+    return;
+  }
+
   switch (event.keyCode) {
+    case event.DOM_VK_RETURN:
+      private.doNotAutocomplete = true;
+      break;
+
     case event.DOM_VK_ESCAPE:
       if (private.popup.isOpen)
         event.preventDefault();
     case event.DOM_VK_LEFT:
     case event.DOM_VK_RIGHT:
     case event.DOM_VK_HOME:
     case event.DOM_VK_END:
       private.doNotAutocomplete = true;
--- a/browser/devtools/sourceeditor/test/browser_detectindent.js
+++ b/browser/devtools/sourceeditor/test/browser_detectindent.js
@@ -57,34 +57,34 @@ const TABS_CODE = [
 "}"
 ].join("\n");
 
 
 function test() {
   waitForExplicitFinish();
 
   setup((ed, win) => {
-    is(ed.getOption("indentUnit"), 4,
-       "4 spaces before code added");
+    is(ed.getOption("indentUnit"), 2,
+       "2 spaces before code added");
     is(ed.getOption("indentWithTabs"), false,
        "spaces is default");
 
+    ed.setText(FOUR_SPACES_CODE);
+    is(ed.getOption("indentUnit"), 4,
+       "4 spaces detected in 4 space code");
+    is(ed.getOption("indentWithTabs"), false,
+       "spaces detected in 4 space code");
+
     ed.setText(TWO_SPACES_CODE);
     is(ed.getOption("indentUnit"), 2,
        "2 spaces detected in 2 space code");
     is(ed.getOption("indentWithTabs"), false,
        "spaces detected in 2 space code");
 
-    ed.setText(FOUR_SPACES_CODE);
-    is(ed.getOption("indentUnit"), 4,
-       "4 spaces detected in 4 space code");
-    is(ed.getOption("indentWithTabs"), false,
-       "spaces detected in 4 space code");
-
     ed.setText(TABS_CODE);
-    is(ed.getOption("indentUnit"), 4,
-       "4 space indentation unit");
+    is(ed.getOption("indentUnit"), 2,
+       "2 space indentation unit");
     is(ed.getOption("indentWithTabs"), true,
        "tabs detected in majority tabs code");
 
     teardown(ed, win);
   });
 }
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -26,16 +26,18 @@ support-files =
 [browser_computedview_keybindings_01.js]
 [browser_computedview_keybindings_02.js]
 [browser_computedview_matched-selectors-toggle.js]
 [browser_computedview_matched-selectors_01.js]
 [browser_computedview_matched-selectors_02.js]
 [browser_computedview_media-queries.js]
 [browser_computedview_no-results-placeholder.js]
 [browser_computedview_original-source-link.js]
+[browser_computedview_refresh-on-style-change_01.js]
+[browser_computedview_refresh-on-style-change_02.js]
 [browser_computedview_search-filter.js]
 [browser_computedview_select-and-copy-styles.js]
 [browser_computedview_style-editor-link.js]
 [browser_ruleview_add-property-and-reselect.js]
 [browser_ruleview_add-property-cancel_01.js]
 [browser_ruleview_add-property-cancel_02.js]
 [browser_ruleview_add-property-cancel_03.js]
 [browser_ruleview_add-property_01.js]
@@ -72,16 +74,17 @@ skip-if = os == "win" && debug # bug 963
 [browser_ruleview_multiple-properties-unfinished_02.js]
 [browser_ruleview_multiple_properties_01.js]
 [browser_ruleview_multiple_properties_02.js]
 [browser_ruleview_original-source-link.js]
 [browser_ruleview_override.js]
 [browser_ruleview_pseudo-element.js]
 [browser_ruleview_refresh-on-attribute-change_01.js]
 [browser_ruleview_refresh-on-attribute-change_02.js]
+[browser_ruleview_refresh-on-style-change.js]
 [browser_ruleview_select-and-copy-styles.js]
 [browser_ruleview_style-editor-link.js]
 [browser_ruleview_urls-clickable.js]
 [browser_ruleview_user-property-reset.js]
 [browser_styleinspector_csslogic-content-stylesheets.js]
 [browser_styleinspector_csslogic-inherited-properties.js]
 [browser_styleinspector_csslogic-specificity.js]
 [browser_styleinspector_inplace-editor.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_computedview_refresh-on-style-change_01.js
@@ -0,0 +1,35 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the computed view refreshes when the current node has its style
+// changed
+
+const TESTCASE_URI = 'data:text/html;charset=utf-8,' +
+                     '<div id="testdiv" style="font-size:10px;">Test div!</div>';
+
+let test = asyncTest(function*() {
+  yield addTab(TESTCASE_URI);
+
+  info("Getting the test node");
+  let div = getNode("#testdiv");
+
+  info("Opening the computed view and selecting the test node");
+  let {toolbox, inspector, view} = yield openComputedView();
+  yield selectNode(div, inspector);
+
+  let fontSize = getComputedViewPropertyValue(view, "font-size");
+  is(fontSize, "10px", "The computed view shows the right font-size");
+
+  info("Changing the node's style and waiting for the update");
+  let onUpdated = inspector.once("computed-view-refreshed");
+  div.style.cssText = "font-size: 15px; color: red;";
+  yield onUpdated;
+
+  fontSize = getComputedViewPropertyValue(view, "font-size");
+  is(fontSize, "15px", "The computed view shows the updated font-size");
+  let color = getComputedViewPropertyValue(view, "color");
+  is(color, "#F00", "The computed view also shows the color now");
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_computedview_refresh-on-style-change_02.js
@@ -0,0 +1,40 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the computed view refreshes when the current node has its style
+// changed, even if the view is not the active one
+
+const TESTCASE_URI = 'data:text/html;charset=utf-8,' +
+                     '<div id="testdiv" style="font-size:10px;">Test div!</div>';
+
+let test = asyncTest(function*() {
+  yield addTab(TESTCASE_URI);
+
+  info("Getting the test node");
+  let div = getNode("#testdiv");
+
+  info("Opening the computed view and selecting the test node");
+  let {toolbox, inspector, view} = yield openComputedView();
+  yield selectNode(div, inspector);
+
+  let fontSize = getComputedViewPropertyValue(view, "font-size");
+  is(fontSize, "10px", "The computed view shows the right font-size");
+
+  info("Now switching to the rule view");
+  yield openRuleView();
+
+  info("Changing the node's style and waiting for the update");
+  let onUpdated = inspector.once("computed-view-refreshed");
+  div.style.cssText = "font-size: 20px; color: blue; text-align: center";
+  yield onUpdated;
+
+  fontSize = getComputedViewPropertyValue(view, "font-size");
+  is(fontSize, "20px", "The computed view shows the updated font-size");
+  let color = getComputedViewPropertyValue(view, "color");
+  is(color, "#00F", "The computed view also shows the color now");
+  let textAlign = getComputedViewPropertyValue(view, "text-align");
+  is(textAlign, "center", "The computed view also shows the text-align now");
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_refresh-on-style-change.js
@@ -0,0 +1,41 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the rule view refreshes when the current node has its style
+// changed
+
+const TESTCASE_URI = 'data:text/html;charset=utf-8,' +
+                     '<div id="testdiv" style="font-size:10px;">Test div!</div>';
+
+let test = asyncTest(function*() {
+  yield addTab(TESTCASE_URI);
+
+  Services.prefs.setCharPref("devtools.defaultColorUnit", "name");
+
+  info("Getting the test node");
+  let div = getNode("#testdiv");
+
+  info("Opening the rule view and selecting the test node");
+  let {toolbox, inspector, view} = yield openRuleView();
+  yield selectNode(div, inspector);
+
+  let fontSize = getRuleViewPropertyValue(view, "element", "font-size");
+  is(fontSize, "10px", "The rule view shows the right font-size");
+
+  info("Changing the node's style and waiting for the update");
+  let onUpdated = inspector.once("rule-view-refreshed");
+  div.style.cssText = "font-size: 3em; color: lightgoldenrodyellow; text-align: right; text-transform: uppercase";
+  yield onUpdated;
+
+  let textAlign = getRuleViewPropertyValue(view, "element", "text-align");
+  is(textAlign, "right", "The rule view shows the new text align.");
+  let color = getRuleViewPropertyValue(view, "element", "color");
+  is(color, "lightgoldenrodyellow", "The rule view shows the new color.")
+  let fontSize = getRuleViewPropertyValue(view, "element", "font-size");
+  is(fontSize, "3em", "The rule view shows the new font size.");
+  let textTransform = getRuleViewPropertyValue(view, "element", "text-transform");
+  is(textTransform, "uppercase", "The rule view shows the new text transform.");
+});
--- a/browser/devtools/styleinspector/test/head.js
+++ b/browser/devtools/styleinspector/test/head.js
@@ -29,19 +29,24 @@ registerCleanupFunction(() => {
   } catch (ex) {
     dump(ex);
   }
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 });
 
+// Uncomment to log events
 // Services.prefs.setBoolPref("devtools.dump.emit", true);
+
+// Clean-up all prefs that might have been changed during a test run
+// (safer here because if the test fails, then the pref is never reverted)
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("devtools.dump.emit");
+  Services.prefs.clearUserPref("devtools.defaultColorUnit");
 });
 
 /**
  * The functions found below are here to ease test development and maintenance.
  * Most of these functions are stateless and will require some form of context
  * (the instance of the current toolbox, or inspector panel for instance).
  *
  * Most of these functions are async too and return promises.
@@ -472,17 +477,17 @@ function hasSideBarTab(inspector, id) {
  * @param {CssRuleView} view The instance of the rule-view panel
  * @param {String} selectorText The selector in the rule-view for which the rule
  * object is wanted
  * @return {DOMNode}
  */
 function getRuleViewRule(view, selectorText) {
   let rule;
   for (let r of view.doc.querySelectorAll(".ruleview-rule")) {
-    let selector = r.querySelector(".ruleview-selector-matched");
+    let selector = r.querySelector(".ruleview-selector, .ruleview-selector-matched");
     if (selector && selector.textContent === selectorText) {
       rule = r;
       break;
     }
   }
 
   return rule;
 }
@@ -511,16 +516,30 @@ function getRuleViewProperty(view, selec
         break;
       }
     }
   }
   return prop;
 }
 
 /**
+ * Get the text value of the property corresponding to a given selector and name
+ * in the rule-view
+ * @param {CssRuleView} view The instance of the rule-view panel
+ * @param {String} selectorText The selector in the rule-view to look for the
+ * property in
+ * @param {String} propertyName The name of the property
+ * @return {String} The property value
+ */
+function getRuleViewPropertyValue(view, selectorText, propertyName) {
+  return getRuleViewProperty(view, selectorText, propertyName)
+    .valueSpan.textContent;
+}
+
+/**
  * Simulate a color change in a given color picker tooltip, and optionally wait
  * for a given element in the page to have its style changed as a result
  * @param {SwatchColorPickerTooltip} colorPicker
  * @param {Array} newRgba The new color to be set [r, g, b, a]
  * @param {Object} expectedChange Optional object that needs the following props:
  *                 - {DOMNode} element The element in the page that will have its
  *                   style changed.
  *                 - {String} name The style name that will be changed
@@ -651,16 +670,28 @@ function getComputedViewProperty(view, n
       prop = {nameSpan: nameSpan, valueSpan: valueSpan};
       break;
     }
   }
   return prop;
 }
 
 /**
+ * Get the text value of the property corresponding to a given name in the
+ * computed-view
+ * @param {CssHtmlTree} view The instance of the computed view panel
+ * @param {String} name The name of the property to retrieve
+ * @return {String} The property value
+ */
+function getComputedViewPropertyValue(view, selectorText, propertyName) {
+  return getComputedViewProperty(view, selectorText, propertyName)
+    .valueSpan.textContent;
+}
+
+/**
  * Expand a given property, given its index in the current property list of
  * the computed view
  * @param {CssHtmlTree} view The instance of the computed view panel
  * @param {InspectorPanel} inspector The instance of the inspector panel
  * @param {Number} index The index of the property to be expanded
  * @return a promise that resolves when the property has been expanded, or
  * rejects if the property was not found
  */
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -46,25 +46,28 @@
   background-color: -moz-Dialog;
 }
 
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(#nav-bar) {
   padding-top: 1px;
   padding-bottom: 1px;
 }
 
+#TabsToolbar:not([collapsed="true"]) + #nav-bar {
+  margin-top: -@tabToolbarNavbarOverlap@; /* Move up into the TabsToolbar */
+  /* Position the toolbar above the bottom of background tabs */
+  position: relative;
+  z-index: 1;
+}
+
 #nav-bar {
   background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
   box-shadow: 0 1px 0 @toolbarHighlight@ inset;
-  margin-top: -@tabToolbarNavbarOverlap@; /* Move up into the TabsToolbar */
   padding-top: 2px;
   padding-bottom: 2px;
-  /* Position the toolbar above the bottom of background tabs */
-  position: relative;
-  z-index: 1;
 }
 
 #nav-bar-overflow-button {
   -moz-image-region: rect(-5px, 12px, 11px, -4px);
 }
 
 /* This only has an effect when this element is placed on the bookmarks toolbar.
  * It's 30px to make sure buttons with 18px icons fit along with the default 16px
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -104,35 +104,38 @@ toolbarseparator {
   min-height: 22px;
 }
 
 #navigator-toolbox > toolbar:not(#TabsToolbar):not(#nav-bar):not(:-moz-lwtheme) {
   -moz-appearance: none;
   background: url(chrome://browser/skin/Toolbar-background-noise.png) hsl(0,0%,83%);
 }
 
+#TabsToolbar:not([collapsed="true"]) + #nav-bar {
+  margin-top: -@tabToolbarNavbarOverlap@; /* Move up into the TabsToolbar */
+  /* Position the toolbar above the bottom of background tabs */
+  position: relative;
+  z-index: 1;
+}
+
 #nav-bar {
   -moz-appearance: none;
   background: url(chrome://browser/skin/Toolbar-background-noise.png),
               linear-gradient(hsl(0,0%,93%), hsl(0,0%,83%));
   background-clip: border-box;
   background-origin: border-box !important;
 
   /* Move the noise texture out of the top 1px strip because that overlaps
      with the tabbar and we don't want to repaint it when animating tabs.
      The noise image is at least 100px high, so repeating it only horizontally
      is enough. */
   background-repeat: repeat-x, no-repeat;
   background-position: 0 1px, 0 0;
 
   box-shadow: inset 0 1px 0 hsla(0,0%,100%,.4);
-  margin-top: -@tabToolbarNavbarOverlap@;
-  /* Position the toolbar above the bottom of background tabs */
-  position: relative;
-  z-index: 1;
 }
 
 @media (min-resolution: 2dppx) {
   #nav-bar {
     background-size: 100px 100px, auto;
   }
 }
 
--- a/browser/themes/osx/customizableui/panelUIOverlay.css
+++ b/browser/themes/osx/customizableui/panelUIOverlay.css
@@ -94,16 +94,20 @@
 .subviewbutton {
   -moz-padding-start: 18px;
 }
 
 .subviewbutton[checked="true"] {
   background-position: top 5px left 4px;
 }
 
+.subviewbutton[checked="true"]:-moz-locale-dir(rtl) {
+  background-position: top 5px right 4px;
+}
+
 .subviewbutton:not(:-moz-any([image],[targetURI],.cui-withicon, .bookmark-item)) > .menu-iconic-left {
   display: none;
 }
 
 menu.subviewbutton,
 menuitem.subviewbutton:not(.panel-subview-footer) {
   padding-top: 2px;
   padding-bottom: 2px;
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -1063,16 +1063,20 @@ toolbaritem[overflowedItem=true],
   background-size: 1px 18px;
   box-shadow: 0 0 0 1px hsla(0,0%,100%,.2);
 }
 
 .subviewbutton[checked="true"] {
   background: url("chrome://global/skin/menu/shared-menu-check.png") center left 7px / 11px 11px no-repeat transparent;
 }
 
+.subviewbutton[checked="true"]:-moz-locale-dir(rtl) {
+  background-position: center right 7px;
+}
+
 .subviewbutton > .menu-iconic-left {
   -moz-appearance: none;
   -moz-margin-end: 3px;
 }
 
 menuitem[checked="true"].subviewbutton > .menu-iconic-left {
   visibility: hidden;
 }
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -278,25 +278,28 @@
     background-image: linear-gradient(to bottom,
         rgb(207, 214, 188) 0, rgb(207, 214, 188) 1px,
         rgb(224, 226, 200) 1px, rgb(224, 226, 200) 2px,
         rgb(214, 216, 190) 2px, rgb(214, 216, 190) 3px,
         transparent 3px);
   }
 }
 
-#nav-bar {
-  background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
-  box-shadow: 0 1px 0 @toolbarHighlight@ inset;
+#TabsToolbar:not([collapsed="true"]) + #nav-bar {
   margin-top: -@tabToolbarNavbarOverlap@; /* Move up into the TabsToolbar */
   /* Position the toolbar above the bottom of background tabs */
   position: relative;
   z-index: 1;
 }
 
+#nav-bar {
+  background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
+  box-shadow: 0 1px 0 @toolbarHighlight@ inset;
+}
+
 #personal-bookmarks {
   min-height: 24px;
 }
 
 #print-preview-toolbar:not(:-moz-lwtheme) {
   -moz-appearance: toolbox;
 }
 
--- a/content/media/DecoderTraits.cpp
+++ b/content/media/DecoderTraits.cpp
@@ -426,16 +426,21 @@ DecoderTraits::CanHandleMediaType(const 
     result = CANPLAY_MAYBE;
   }
 #endif
 #ifdef MOZ_MEDIA_PLUGINS
   if (MediaDecoder::IsMediaPluginsEnabled() &&
       GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), &codecList))
     result = CANPLAY_MAYBE;
 #endif
+#ifdef NECKO_PROTOCOL_rtsp
+  if (IsRtspSupportedType(nsDependentCString(aMIMEType))) {
+    result = CANPLAY_MAYBE;
+  }
+#endif
   if (result == CANPLAY_NO || !aHaveRequestedCodecs || !codecList) {
     return result;
   }
 
   // See http://www.rfc-editor.org/rfc/rfc4281.txt for the description
   // of the 'codecs' parameter
   nsCharSeparatedTokenizer tokenizer(aRequestedCodecs, ',');
   bool expectMoreTokens = false;
@@ -660,12 +665,15 @@ bool DecoderTraits::IsSupportedInVideoDo
      Preferences::GetBool("media.windows-media-foundation.play-stand-alone", true)) ||
 #endif
 #ifdef MOZ_DIRECTSHOW
     IsDirectShowSupportedType(aType) ||
 #endif
 #ifdef MOZ_APPLEMEDIA
     IsAppleMediaSupportedType(aType) ||
 #endif
+#ifdef NECKO_PROTOCOL_rtsp
+    IsRtspSupportedType(aType) ||
+#endif
     false;
 }
 
 }
--- a/content/media/MediaCache.cpp
+++ b/content/media/MediaCache.cpp
@@ -1547,16 +1547,21 @@ MediaCache::OpenStream(MediaCacheStream*
 void
 MediaCache::ReleaseStream(MediaCacheStream* aStream)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   CACHE_LOG(PR_LOG_DEBUG, ("Stream %p closed", aStream));
   mStreams.RemoveElement(aStream);
+
+  // Update MediaCache again for |mStreams| is changed.
+  // We need to re-run Update() to ensure streams reading from the same resource
+  // as the removed stream get a chance to continue reading.
+  gMediaCache->QueueUpdate();
 }
 
 void
 MediaCache::ReleaseStreamBlocks(MediaCacheStream* aStream)
 {
   mReentrantMonitor.AssertCurrentThreadIn();
 
   // XXX scanning the entire stream doesn't seem great, if not much of it
--- a/content/media/RtspMediaResource.cpp
+++ b/content/media/RtspMediaResource.cpp
@@ -10,16 +10,20 @@
 
 #include "MediaDecoder.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Preferences.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIStreamingProtocolService.h"
 #include "nsServiceManagerUtils.h"
+#ifdef NECKO_PROTOCOL_rtsp
+#include "mozilla/net/RtspChannelChild.h"
+#endif
+using namespace mozilla::net;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gRtspMediaResourceLog;
 #define RTSP_LOG(msg, ...) PR_LOG(gRtspMediaResourceLog, PR_LOG_DEBUG, \
                                   (msg, ##__VA_ARGS__))
 // Debug logging macro with object pointer and class name.
 #define RTSPMLOG(msg, ...) \
         RTSP_LOG("%p [RtspMediaResource]: " msg, this, ##__VA_ARGS__)
@@ -32,19 +36,19 @@ namespace mozilla {
 
 /* class RtspTrackBuffer: a ring buffer implementation for audio/video track
  * un-decoded data.
  * The ring buffer is divided into BUFFER_SLOT_NUM slots,
  * and each slot's size is fixed(mSlotSize).
  * Even though the ring buffer is divided into fixed size slots, it still can
  * store the data which size is larger than one slot size.
  * */
-#define BUFFER_SLOT_NUM 512
+#define BUFFER_SLOT_NUM 8192
 #define BUFFER_SLOT_DEFAULT_SIZE 256
-#define BUFFER_SLOT_MAX_SIZE 8192
+#define BUFFER_SLOT_MAX_SIZE 512
 #define BUFFER_SLOT_INVALID -1
 #define BUFFER_SLOT_EMPTY 0
 
 struct BufferSlotData {
   int32_t mLength;
   uint64_t mTime;
 };
 
@@ -349,31 +353,31 @@ void RtspTrackBuffer::Reset() {
 }
 
 RtspMediaResource::RtspMediaResource(MediaDecoder* aDecoder,
     nsIChannel* aChannel, nsIURI* aURI, const nsACString& aContentType)
   : BaseMediaResource(aDecoder, aChannel, aURI, aContentType)
   , mIsConnected(false)
   , mRealTime(false)
 {
-  nsCOMPtr<nsIStreamingProtocolControllerService> mediaControllerService =
-    do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID);
-  MOZ_ASSERT(mediaControllerService);
-  if (mediaControllerService) {
-    mediaControllerService->Create(mChannel,
-                                   getter_AddRefs(mMediaStreamController));
-    MOZ_ASSERT(mMediaStreamController);
-    mListener = new Listener(this);
-    mMediaStreamController->AsyncOpen(mListener);
-  }
+#ifndef NECKO_PROTOCOL_rtsp
+  MOZ_CRASH("Should not be called except for B2G platform");
+#else
+  MOZ_ASSERT(aChannel);
+  mMediaStreamController =
+    static_cast<RtspChannelChild*>(aChannel)->GetController();
+  MOZ_ASSERT(mMediaStreamController);
+  mListener = new Listener(this);
+  mMediaStreamController->AsyncOpen(mListener);
 #ifdef PR_LOGGING
   if (!gRtspMediaResourceLog) {
     gRtspMediaResourceLog = PR_NewLogModule("RtspMediaResource");
   }
 #endif
+#endif
 }
 
 RtspMediaResource::~RtspMediaResource()
 {
   RTSPMLOG("~RtspMediaResource");
   if (mListener) {
     // Kill its reference to us since we're going away
     mListener->Revoke();
@@ -629,29 +633,35 @@ RtspMediaResource::OnDisconnected(uint8_
   }
 
   return NS_OK;
 }
 
 void RtspMediaResource::Suspend(bool aCloseImmediately)
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
+  if (NS_WARN_IF(!mDecoder)) {
+    return;
+  }
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   NS_ENSURE_TRUE_VOID(owner);
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE_VOID(element);
 
   mMediaStreamController->Suspend();
   element->DownloadSuspended();
 }
 
 void RtspMediaResource::Resume()
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
+  if (NS_WARN_IF(!mDecoder)) {
+    return;
+  }
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   NS_ENSURE_TRUE_VOID(owner);
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE_VOID(element);
 
   if (mChannel) {
     element->DownloadResumed();
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -170,16 +170,17 @@ MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/layout/generic',
     '/layout/xul',
+    '/netwerk/base/src',
 ]
 
 if CONFIG['MOZ_DIRECTSHOW']:
     LOCAL_INCLUDES += [
         '/media/webrtc/trunk/webrtc/modules/video_capture/windows',
     ]
 
 DEFINES['MOZILLA_INTERNAL_API'] = True
--- a/content/media/omx/AudioOffloadPlayer.cpp
+++ b/content/media/omx/AudioOffloadPlayer.cpp
@@ -42,16 +42,20 @@ namespace mozilla {
 #ifdef PR_LOGGING
 PRLogModuleInfo* gAudioOffloadPlayerLog;
 #define AUDIO_OFFLOAD_LOG(type, msg) \
   PR_LOG(gAudioOffloadPlayerLog, type, msg)
 #else
 #define AUDIO_OFFLOAD_LOG(type, msg)
 #endif
 
+// maximum time in paused state when offloading audio decompression.
+// When elapsed, the AudioSink is destroyed to allow the audio DSP to power down.
+static const uint64_t OFFLOAD_PAUSE_MAX_MSECS = 60000ll;
+
 AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxDecoder* aObserver) :
   mObserver(aObserver),
   mInputBuffer(nullptr),
   mSampleRate(0),
   mSeeking(false),
   mSeekDuringPause(false),
   mReachedEOS(false),
   mSeekTimeUs(0),
@@ -73,19 +77,17 @@ AudioOffloadPlayer::AudioOffloadPlayer(M
   mSessionId = AudioSystem::newAudioSessionId();
   AudioSystem::acquireAudioSessionId(mSessionId);
   mAudioSink = new AudioOutput(mSessionId,
       IPCThreadState::self()->getCallingUid());
 }
 
 AudioOffloadPlayer::~AudioOffloadPlayer()
 {
-  if (mStarted) {
-    Reset();
-  }
+  Reset();
   AudioSystem::releaseAudioSessionId(mSessionId);
 }
 
 void AudioOffloadPlayer::SetSource(const sp<MediaSource> &aSource)
 {
   MOZ_ASSERT(NS_IsMainThread());
   CHECK(!mSource.get());
 
@@ -104,22 +106,16 @@ status_t AudioOffloadPlayer::Start(bool 
   if (!aSourceAlreadyStarted) {
     err = mSource->start();
 
     if (err != OK) {
       return err;
     }
   }
 
-  MediaSource::ReadOptions options;
-  if (mSeeking) {
-    options.setSeekTo(mSeekTimeUs);
-    mSeeking = false;
-  }
-
   sp<MetaData> format = mSource->getFormat();
   const char* mime;
   int avgBitRate = -1;
   int32_t channelMask;
   int32_t numChannels;
   int64_t durationUs = -1;
   audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
   uint32_t flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
@@ -172,31 +168,34 @@ status_t AudioOffloadPlayer::Start(bool 
     SendMetaDataToHal(mAudioSink, format);
   }
   mStarted = true;
   mPlaying = false;
 
   return err;
 }
 
-void AudioOffloadPlayer::ChangeState(MediaDecoder::PlayState aState)
+status_t AudioOffloadPlayer::ChangeState(MediaDecoder::PlayState aState)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mPlayState = aState;
 
   switch (mPlayState) {
-    case MediaDecoder::PLAY_STATE_PLAYING:
-      Play();
+    case MediaDecoder::PLAY_STATE_PLAYING: {
+      status_t err = Play();
+      if (err != OK) {
+        return err;
+      }
       StartTimeUpdate();
-      break;
+    } break;
 
     case MediaDecoder::PLAY_STATE_SEEKING: {
       int64_t seekTimeUs
           = mObserver->GetSeekTime();
-      SeekTo(seekTimeUs);
+      SeekTo(seekTimeUs, true);
       mObserver->ResetSeekTime();
     } break;
 
     case MediaDecoder::PLAY_STATE_PAUSED:
     case MediaDecoder::PLAY_STATE_SHUTDOWN:
       // Just pause here during play state shutdown as well to stop playing
       // offload track immediately. Resources will be freed by MediaOmxDecoder
       Pause();
@@ -204,51 +203,91 @@ void AudioOffloadPlayer::ChangeState(Med
 
     case MediaDecoder::PLAY_STATE_ENDED:
       Pause(true);
       break;
 
     default:
       break;
   }
+  return OK;
+}
+
+static void ResetCallback(nsITimer* aTimer, void* aClosure)
+{
+  AudioOffloadPlayer* player = static_cast<AudioOffloadPlayer*>(aClosure);
+  if (player) {
+    player->Reset();
+  }
 }
 
 void AudioOffloadPlayer::Pause(bool aPlayPendingSamples)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  CHECK(mStarted);
-  CHECK(mAudioSink.get());
 
-  if (aPlayPendingSamples) {
-    mAudioSink->Stop();
-  } else {
-    mAudioSink->Pause();
+  if (mStarted) {
+    CHECK(mAudioSink.get());
+    if (aPlayPendingSamples) {
+      mAudioSink->Stop();
+    } else {
+      mAudioSink->Pause();
+    }
+    mPlaying = false;
   }
-  mPlaying = false;
+
+  if (mResetTimer) {
+    return;
+  }
+  mResetTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mResetTimer->InitWithFuncCallback(ResetCallback,
+                                    this,
+                                    OFFLOAD_PAUSE_MAX_MSECS,
+                                    nsITimer::TYPE_ONE_SHOT);
 }
 
 status_t AudioOffloadPlayer::Play()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  CHECK(mStarted);
-  CHECK(mAudioSink.get());
+
+  if (mResetTimer) {
+    mResetTimer->Cancel();
+    mResetTimer = nullptr;
+  }
 
   status_t err = OK;
-  err = mAudioSink->Start();
 
-  if (err == OK) {
-    mPlaying = true;
+  if (!mStarted) {
+    // Last pause timed out and offloaded audio sink was reset. Start it again
+    err = Start(false);
+    if (err != OK) {
+      return err;
+    }
+    // Seek to last play position only when there was no seek during last pause
+    if (!mSeeking) {
+      SeekTo(mPositionTimeMediaUs);
+    }
+  }
+
+  if (!mPlaying) {
+    CHECK(mAudioSink.get());
+    err = mAudioSink->Start();
+    if (err == OK) {
+      mPlaying = true;
+    }
   }
 
   return err;
 }
 
 void AudioOffloadPlayer::Reset()
 {
-  CHECK(mStarted);
+  if (!mStarted) {
+    return;
+  }
+
   CHECK(mAudioSink.get());
 
   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("reset: mPlaying=%d mReachedEOS=%d",
       mPlaying, mReachedEOS));
 
   mAudioSink->Stop();
   // If we're closing and have reached EOS, we don't want to flush
   // the track because if it is offloaded there could be a small
@@ -268,62 +307,68 @@ void AudioOffloadPlayer::Reset()
   // source is able to stop().
 
   if (mInputBuffer) {
     AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Releasing input buffer"));
 
     mInputBuffer->release();
     mInputBuffer = nullptr;
   }
+  mSource->stop();
 
   IPCThreadState::self()->flushCommands();
   StopTimeUpdate();
 
-  mSeeking = false;
-  mSeekTimeUs = 0;
   mReachedEOS = false;
   mStarted = false;
   mPlaying = false;
   mStartPosUs = 0;
 }
 
-status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs)
+status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents)
 {
   MOZ_ASSERT(NS_IsMainThread());
   CHECK(mAudioSink.get());
 
   android::Mutex::Autolock autoLock(mLock);
 
   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("SeekTo ( %lld )", aTimeUs));
 
   mSeeking = true;
   mReachedEOS = false;
   mPositionTimeMediaUs = -1;
   mSeekTimeUs = aTimeUs;
   mStartPosUs = aTimeUs;
+  mDispatchSeekEvents = aDispatchSeekEvents;
 
-  nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
-      &MediaDecoder::SeekingStarted);
-  NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
+  if (mDispatchSeekEvents) {
+    nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
+        &MediaDecoder::SeekingStarted);
+    NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
+  }
 
   if (mPlaying) {
     mAudioSink->Pause();
-  }
+    mAudioSink->Flush();
+    mAudioSink->Start();
 
-  mAudioSink->Flush();
-
-  if (mPlaying) {
-    mAudioSink->Start();
   } else {
     mSeekDuringPause = true;
-    AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Fake seek complete during pause"));
+
+    if (mStarted) {
+      mAudioSink->Flush();
+    }
 
-    nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
-        &MediaDecoder::SeekingStopped);
-    NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
+    if (mDispatchSeekEvents) {
+      mDispatchSeekEvents = false;
+      AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Fake seek complete during pause"));
+      nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
+          &MediaDecoder::SeekingStopped);
+      NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
+    }
   }
 
   return OK;
 }
 
 double AudioOffloadPlayer::GetMediaTimeSecs()
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -334,16 +379,19 @@ double AudioOffloadPlayer::GetMediaTimeS
 int64_t AudioOffloadPlayer::GetMediaTimeUs()
 {
   android::Mutex::Autolock autoLock(mLock);
 
   int64_t playPosition = 0;
   if (mSeeking) {
     return mSeekTimeUs;
   }
+  if (!mStarted) {
+    return mPositionTimeMediaUs;
+  }
 
   playPosition = GetOutputPlayPositionUs_l();
   if (!mReachedEOS) {
     mPositionTimeMediaUs = playPosition;
   }
 
   return mPositionTimeMediaUs;
 }
@@ -422,18 +470,16 @@ size_t AudioOffloadPlayer::AudioSinkCall
 size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize)
 {
   CHECK(mAudioSink.get());
 
   if (mReachedEOS) {
     return 0;
   }
 
-  bool postSeekComplete = false;
-
   size_t sizeDone = 0;
   size_t sizeRemaining = aSize;
   while (sizeRemaining > 0) {
     MediaSource::ReadOptions options;
     bool refreshSeekTime = false;
 
     {
       android::Mutex::Autolock autoLock(mLock);
@@ -441,19 +487,17 @@ size_t AudioOffloadPlayer::FillBuffer(vo
       if (mSeeking) {
         options.setSeekTo(mSeekTimeUs);
         refreshSeekTime = true;
 
         if (mInputBuffer) {
           mInputBuffer->release();
           mInputBuffer = nullptr;
         }
-
         mSeeking = false;
-        postSeekComplete = true;
       }
     }
 
     if (!mInputBuffer) {
 
       status_t err;
       err = mSource->read(&mInputBuffer, &options);
 
@@ -486,41 +530,41 @@ size_t AudioOffloadPlayer::FillBuffer(vo
         break;
       }
 
       if(mInputBuffer->range_length() != 0) {
         CHECK(mInputBuffer->meta_data()->findInt64(
             kKeyTime, &mPositionTimeMediaUs));
       }
 
-      // need to adjust the mStartPosUs for offload decoding since parser
-      // might not be able to get the exact seek time requested.
       if (refreshSeekTime) {
-        if (postSeekComplete) {
 
-          if (!mSeekDuringPause) {
-            AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("FillBuffer posting SEEK_COMPLETE"));
-            nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
-                &MediaDecoder::SeekingStopped);
-            NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
-          } else {
-            // Callback is already called for seek during pause. Just reset the
-            // flag
-            AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Not posting seek complete as its"
-                " already faked"));
-            mSeekDuringPause = false;
-          }
+        if (mDispatchSeekEvents && !mSeekDuringPause) {
+          mDispatchSeekEvents = false;
+          AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("FillBuffer posting SEEK_COMPLETE"));
+          nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
+              &MediaDecoder::SeekingStopped);
+          NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
 
-          NotifyPositionChanged();
-          postSeekComplete = false;
+        } else if (mSeekDuringPause) {
+          // Callback is already called for seek during pause. Just reset the
+          // flag
+          AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Not posting seek complete as its"
+              " already faked"));
+          mSeekDuringPause = false;
         }
 
+        NotifyPositionChanged();
+
+        // need to adjust the mStartPosUs for offload decoding since parser
+        // might not be able to get the exact seek time requested.
         mStartPosUs = mPositionTimeMediaUs;
         AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Adjust seek time to: %.2f",
             mStartPosUs / 1E6));
+
         // clear seek time with mLock locked and once we have valid
         // mPositionTimeMediaUs
         // before clearing mSeekTimeUs check if a new seek request has been
         // received while we were reading from the source with mLock released.
         if (!mSeeking) {
           mSeekTimeUs = 0;
         }
       }
--- a/content/media/omx/AudioOffloadPlayer.h
+++ b/content/media/omx/AudioOffloadPlayer.h
@@ -81,27 +81,30 @@ public:
   // create an offloaded audio track
   status_t Start(bool aSourceAlreadyStarted = false);
 
   double GetMediaTimeSecs();
 
   // To update progress bar when the element is visible
   void SetElementVisibility(bool aIsVisible);
 
-  void ChangeState(MediaDecoder::PlayState aState);
+  status_t ChangeState(MediaDecoder::PlayState aState);
 
   void SetVolume(double aVolume);
 
   // Update ready state based on current play state. Not checking data
   // availability since offloading is currently done only when whole compressed
   // data is available
   MediaDecoderOwner::NextFrameStatus GetNextFrameStatus();
 
   void TimeUpdate();
 
+  // Close the audio sink, stop time updates, frees the input buffers
+  void Reset();
+
 private:
   // Set when audio source is started and audioSink is initialized
   // Used only in main thread
   bool mStarted;
 
   // Set when audio sink is started. i.e. playback started
   // Used only in main thread
   bool mPlaying;
@@ -117,16 +120,22 @@ private:
   // mLock
   bool mReachedEOS;
 
   // Set when there is a seek request during pause.
   // Used in main thread and offload callback thread, protected by Mutex
   // mLock
   bool mSeekDuringPause;
 
+  // Seek can be triggered internally or by MediaDecoder. This bool is to
+  // to track seek triggered by MediaDecoder so that we can send back
+  // SeekingStarted and SeekingStopped events.
+  // Used in main thread and offload callback thread, protected by Mutex mLock
+  bool mDispatchSeekEvents;
+
   // Set when the HTML Audio Element is visible to the user.
   // Used only in main thread
   bool mIsElementVisible;
 
   // Session id given by Android::AudioSystem and used while creating audio sink
   // Used only in main thread
   int mSessionId;
 
@@ -159,31 +168,38 @@ private:
   // offload callback thread
   Mutex mLock;
 
   // Compressed audio source.
   // Used in main thread first and later in offload callback thread
   android::sp<MediaSource> mSource;
 
   // Audio sink wrapper to access offloaded audio tracks
-  // Used in main thread and offload callback thread, access is protected by
+  // Used in main thread and offload callback thread
   // Race conditions are protected in underlying Android::AudioTrack class
   android::sp<AudioSink> mAudioSink;
 
   // Buffer used to get date from audio source. Used in offload callback thread
   MediaBuffer* mInputBuffer;
 
   // MediaOmxDecoder object used mainly to notify the audio sink status
   MediaOmxDecoder* mObserver;
 
   TimeStamp mLastFireUpdateTime;
+
   // Timer to trigger position changed events
   nsCOMPtr<nsITimer> mTimeUpdateTimer;
 
+  // Timer to reset AudioSink when audio is paused for OFFLOAD_PAUSE_MAX_USECS.
+  // It is triggered in Pause() and canceled when there is a Play() within
+  // OFFLOAD_PAUSE_MAX_USECS. Used only from main thread so no lock is needed.
+  nsCOMPtr<nsITimer> mResetTimer;
+
   int64_t GetMediaTimeUs();
+
   // Provide the playback position in microseconds from total number of
   // frames played by audio track
   int64_t GetOutputPlayPositionUs_l() const;
 
   // Fill the buffer given by audio sink with data from compressed audio
   // source. Also handles the seek by seeking audio source and stop the sink in
   // case of error
   size_t FillBuffer(void *aData, size_t aSize);
@@ -193,26 +209,24 @@ private:
                                   void *aData,
                                   size_t aSize,
                                   void *aMe,
                                   AudioSink::cb_event_t aEvent);
 
   bool IsSeeking();
 
   // Set mSeekTime to the given position and restart the sink. Actual seek
-  // happens in FillBuffer(). To MediaDecoder, send SeekingStarted event always
-  // and SeekingStopped event when the play state is paused.
+  // happens in FillBuffer(). If aDispatchSeekEvents is true, send
+  // SeekingStarted event always and SeekingStopped event when the play state is
+  // paused to MediaDecoder.
   // When decoding and playing happens separately, if there is a seek during
   // pause, we can decode and keep data ready.
   // In case of offload player, no way to seek during pause. So just fake that
   // seek is done.
-  status_t SeekTo(int64_t aTimeUs);
-
-  // Close the audio sink, stop time updates, frees the input buffers
-  void Reset();
+  status_t SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents = false);
 
   // Start/Resume the audio sink so that callback will start being called to get
   // compressed data
   status_t Play();
 
   // Stop the audio sink if we need to play till we drain the current buffer.
   // or Pause the sink in case we should stop playing immediately
   void Pause(bool aPlayPendingSamples = false);
--- a/content/media/omx/AudioOffloadPlayerBase.h
+++ b/content/media/omx/AudioOffloadPlayerBase.h
@@ -44,17 +44,20 @@ public:
 
   // Start the source if it's not already started and open the AudioSink to
   // create an offloaded audio track
   virtual status_t Start(bool aSourceAlreadyStarted = false)
   {
     return android::NO_INIT;
   }
 
-  virtual void ChangeState(MediaDecoder::PlayState aState) {}
+  virtual status_t ChangeState(MediaDecoder::PlayState aState)
+  {
+    return android::NO_INIT;
+  }
 
   virtual void SetVolume(double aVolume) {}
 
   virtual double GetMediaTimeSecs() { return 0; }
 
   // To update progress bar when the element is visible
   virtual void SetElementVisibility(bool aIsVisible) {}
 
--- a/content/media/omx/MediaOmxDecoder.cpp
+++ b/content/media/omx/MediaOmxDecoder.cpp
@@ -60,17 +60,16 @@ void MediaOmxDecoder::MetadataLoaded(int
                                      bool aHasAudio,
                                      bool aHasVideo,
                                      MetadataTags* aTags)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MediaDecoder::MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags);
 
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
-
   if (!mCanOffloadAudio || mFallbackToStateMachine || mOutputStreams.Length() ||
       mInitialPlaybackRate != 1.0) {
     DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed",
         __PRETTY_FUNCTION__));
     return;
   }
 
 #ifdef MOZ_AUDIO_OFFLOAD
@@ -90,28 +89,27 @@ void MediaOmxDecoder::MetadataLoaded(int
       "Switching to normal mode", __PRETTY_FUNCTION__, err));
 }
 
 void MediaOmxDecoder::PauseStateMachine()
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
   DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
-
   if (!mDecoderStateMachine) {
     return;
   }
   StopProgress();
   mDecoderStateMachine->SetDormant(true);
 }
 
 void MediaOmxDecoder::ResumeStateMachine()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  GetReentrantMonitor().AssertCurrentThreadIn();
+  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   DECODER_LOG(PR_LOG_DEBUG, ("%s current time %f", __PRETTY_FUNCTION__,
       mCurrentTime));
 
   if (!mDecoderStateMachine) {
     return;
   }
 
   mFallbackToStateMachine = true;
@@ -125,69 +123,67 @@ void MediaOmxDecoder::ResumeStateMachine
 
 void MediaOmxDecoder::AudioOffloadTearDown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   PlaybackPositionChanged();
   DECODER_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
   {
     // Audio offload player sent tear down event. Fallback to state machine
-    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     ResumeStateMachine();
   }
 }
 
 void MediaOmxDecoder::AddOutputStream(ProcessedMediaStream* aStream,
                                       bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   PlaybackPositionChanged();
 
   if (mAudioOffloadPlayer) {
     // Offload player cannot handle MediaStream. Fallback
-    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     ResumeStateMachine();
   }
 
   MediaDecoder::AddOutputStream(aStream, aFinishWhenEnded);
 }
 
 void MediaOmxDecoder::SetPlaybackRate(double aPlaybackRate)
 {
   MOZ_ASSERT(NS_IsMainThread());
   PlaybackPositionChanged();
 
   if (mAudioOffloadPlayer &&
       ((aPlaybackRate != 0.0) || (aPlaybackRate != 1.0))) {
     // Offload player cannot handle playback rate other than 1/0. Fallback
-    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     ResumeStateMachine();
   }
 
   MediaDecoder::SetPlaybackRate(aPlaybackRate);
 }
 
 void MediaOmxDecoder::ChangeState(PlayState aState)
 {
   MOZ_ASSERT(NS_IsMainThread());
-
   // Keep MediaDecoder state in sync with MediaElement irrespective of offload
   // playback so it will continue to work in normal mode when offloading fails
   // in between
   MediaDecoder::ChangeState(aState);
 
   if (mAudioOffloadPlayer) {
-    mAudioOffloadPlayer->ChangeState(aState);
+    status_t err = mAudioOffloadPlayer->ChangeState(aState);
+    if (err != OK) {
+      ResumeStateMachine();
+    }
   }
 }
 
 void MediaOmxDecoder::ApplyStateToStateMachine(PlayState aState)
 {
   MOZ_ASSERT(NS_IsMainThread());
-
   // During offload playback, state machine should be in dormant state.
   // ApplyStateToStateMachine() can change state machine state to
   // something else or reset the seek time. So don't call this when audio is
   // offloaded
   if (!mAudioOffloadPlayer) {
     MediaDecoder::ApplyStateToStateMachine(aState);
   }
 }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -533,35 +533,52 @@ nsDOMWindowUtils::SetCriticalDisplayPort
 NS_IMETHODIMP
 nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
-  return presShell ? presShell->SetResolution(aXResolution, aYResolution)
-                   : NS_ERROR_FAILURE;
+  if (!presShell) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
+  if (sf) {
+    sf->SetResolution(gfxSize(aXResolution, aYResolution));
+    presShell->SetResolution(aXResolution, aYResolution);
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetResolution(float* aXResolution, float* aYResolution)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
-
-  if (presShell) {
+  if (!presShell) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
+  if (sf) {
+    const gfxSize& res = sf->GetResolution();
+    *aXResolution = res.width;
+    *aYResolution = res.height;
+  } else {
     *aXResolution = presShell->GetXResolution();
     *aYResolution = presShell->GetYResolution();
-    return NS_OK;
-  }
-  return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -994,35 +994,26 @@ BluetoothHfpManager::SendResponse(bthf_a
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
     sBluetoothHfpInterface->at_response(aResponseCode, 0));
 }
 
 void
 BluetoothHfpManager::UpdatePhoneCIND(uint32_t aCallIndex, bool aSend)
 {
-  // Update callsetup state
-  uint16_t callState = mCurrentCallArray[aCallIndex].mState;
-  if (callState == nsITelephonyProvider::CALL_STATE_CONNECTED ||
-      callState == nsITelephonyProvider::CALL_STATE_HELD) {
-    mCallSetupState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
-  } else {
-    mCallSetupState = callState;
-  }
-
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   int numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
   int numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
   bthf_call_state_t bthfCallState = ConvertToBthfCallState(mCallSetupState);
   nsAutoCString number = NS_ConvertUTF16toUTF8(mCurrentCallArray[aCallIndex].mNumber);
   bthf_call_addrtype_t type = mCurrentCallArray[aCallIndex].mType;
 
-  BT_LOGR("[%d] state %d => BTHF: active[%d] held[%d] state[%d]",
-          aCallIndex, callState, numActive, numHeld, bthfCallState);
+  BT_LOGR("[%d] state %d => BTHF: active[%d] held[%d] state[%d]", aCallIndex,
+          mCurrentCallArray[aCallIndex].mState, numActive, numHeld, bthfCallState);
 
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
     sBluetoothHfpInterface->phone_state_change(
       numActive, numHeld, bthfCallState, number.get(), type));
 }
 
 void
 BluetoothHfpManager::UpdateDeviceCIND()
@@ -1119,16 +1110,32 @@ BluetoothHfpManager::HandleCallStateChan
   mCurrentCallArray[aCallIndex].mDirection = (aIsOutgoing) ?
                                               BTHF_CALL_DIRECTION_OUTGOING :
                                               BTHF_CALL_DIRECTION_INCOMING;
   // Same logic as implementation in ril_worker.js
   if (aNumber.Length() && aNumber[0] == '+') {
     mCurrentCallArray[aCallIndex].mType = BTHF_CALL_ADDRTYPE_INTERNATIONAL;
   }
 
+  bool isSetupCall = (aCallState == nsITelephonyProvider::CALL_STATE_INCOMING ||
+                      aCallState == nsITelephonyProvider::CALL_STATE_ALERTING ||
+                      aCallState == nsITelephonyProvider::CALL_STATE_DIALING);
+  bool hasSetupCall = (FindFirstCall(nsITelephonyProvider::CALL_STATE_INCOMING) ||
+                       FindFirstCall(nsITelephonyProvider::CALL_STATE_ALERTING) ||
+                       FindFirstCall(nsITelephonyProvider::CALL_STATE_DIALING));
+
+  // Update callsetup state when
+  // 1) this call is in call setup
+  // 2) all calls in the call array including this call are not in call setup
+  if (isSetupCall) {
+    mCallSetupState = aCallState;
+  } else if (!hasSetupCall) {
+    mCallSetupState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  }
+
   UpdatePhoneCIND(aCallIndex, aSend);
 
   switch (aCallState) {
     case nsITelephonyProvider::CALL_STATE_DIALING:
       // We've send Dialer a dialing request and this is the response.
       if (!mDialingRequestProcessed) {
         SendResponse(BTHF_AT_RESPONSE_OK);
         mDialingRequestProcessed = true;
--- a/dom/bluetooth/bluez/BluetoothDBusService.cpp
+++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp
@@ -1157,16 +1157,84 @@ AppendDeviceName(BluetoothSignal& aSigna
     BLUEZ_DBUS_BASE_IFC, NS_ConvertUTF16toUTF8(devicePath).get(),
     DBUS_DEVICE_IFACE, "GetProperties", DBUS_TYPE_INVALID);
 
   NS_ENSURE_TRUE_VOID(success);
 
   unused << handler.forget(); // picked up by callback handler
 }
 
+class SetPairingConfirmationTask : public Task
+{
+public:
+  SetPairingConfirmationTask(const nsAString& aDeviceAddress,
+                             bool aConfirm,
+                             BluetoothReplyRunnable* aRunnable)
+    : mDeviceAddress(aDeviceAddress)
+    , mConfirm(aConfirm)
+    , mRunnable(aRunnable)
+  {
+    MOZ_ASSERT(!mDeviceAddress.IsEmpty());
+  }
+
+  void Run() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
+    MOZ_ASSERT(sDBusConnection);
+
+    nsAutoString errorStr;
+    BluetoothValue v = true;
+    DBusMessage *msg;
+
+    if (!sPairingReqTable->Get(mDeviceAddress, &msg) && mRunnable) {
+      BT_WARNING("%s: Couldn't get original request message.", __FUNCTION__);
+      errorStr.AssignLiteral("Couldn't get original request message.");
+      DispatchBluetoothReply(mRunnable, v, errorStr);
+
+      return;
+    }
+
+    DBusMessage *reply;
+
+    if (mConfirm) {
+      reply = dbus_message_new_method_return(msg);
+    } else {
+      reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected",
+                                     "User rejected confirmation");
+    }
+
+    if (!reply) {
+      BT_WARNING("%s: Memory can't be allocated for the message.", __FUNCTION__);
+      dbus_message_unref(msg);
+      errorStr.AssignLiteral("Memory can't be allocated for the message.");
+      if (mRunnable) {
+        DispatchBluetoothReply(mRunnable, v, errorStr);
+      }
+      return;
+    }
+
+    bool result = sDBusConnection->Send(reply);
+    if (!result) {
+      errorStr.AssignLiteral("Can't send message!");
+    }
+
+    dbus_message_unref(msg);
+    dbus_message_unref(reply);
+    sPairingReqTable->Remove(mDeviceAddress);
+    if (mRunnable) {
+      DispatchBluetoothReply(mRunnable, v, errorStr);
+    }
+  }
+
+private:
+  nsString mDeviceAddress;
+  bool mConfirm;
+  nsRefPtr<BluetoothReplyRunnable> mRunnable;
+};
+
 static DBusHandlerResult
 AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data)
 {
   if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
     BT_WARNING("%s: agent handler not interested (not a method call).\n",
                __FUNCTION__);
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
@@ -1326,17 +1394,35 @@ AgentEventFilter(DBusConnection *conn, D
     if (!reply) {
       errorStr.AssignLiteral("Memory can't be allocated for the message.");
       goto handle_error;
     }
 
     dbus_connection_send(conn, reply, nullptr);
     dbus_message_unref(reply);
 
-    // Do not send an notification to upper layer, too annoying.
+    // Do not send a notification to upper layer, too annoying.
+    return DBUS_HANDLER_RESULT_HANDLED;
+  } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "RequestPairingConsent")) {
+    // Directly SetPairingconfirmation for RequestPairingConsent here
+    if (!dbus_message_get_args(msg, nullptr,
+                               DBUS_TYPE_OBJECT_PATH, &objectPath,
+                               DBUS_TYPE_INVALID)) {
+      errorStr.AssignLiteral("Invalid arguments: RequestPairingConsent()");
+      goto handle_error;
+    }
+
+    nsString address = GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
+    sPairingReqTable->Put(address, msg);
+    Task* task = new SetPairingConfirmationTask(address, true, nullptr);
+    DispatchToDBusThread(task);
+    // Increase dbus message reference counts, it will be decreased in
+    // SetPairingConfirmationTask
+    dbus_message_ref(msg);
+    // Do not send a notification to upper layer
     return DBUS_HANDLER_RESULT_HANDLED;
   } else {
 #ifdef DEBUG
     BT_WARNING("agent handler %s: Unhandled event. Ignore.", __FUNCTION__);
 #endif
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
@@ -3177,78 +3263,16 @@ BluetoothDBusService::SetPasskeyInternal
   Task* task = new SetPasskeyTask(aDeviceAddress,
                                   aPasskey,
                                   aRunnable);
   DispatchToDBusThread(task);
 
   return true;
 }
 
-class SetPairingConfirmationTask : public Task
-{
-public:
-  SetPairingConfirmationTask(const nsAString& aDeviceAddress,
-                             bool aConfirm,
-                             BluetoothReplyRunnable* aRunnable)
-    : mDeviceAddress(aDeviceAddress)
-    , mConfirm(aConfirm)
-    , mRunnable(aRunnable)
-  {
-    MOZ_ASSERT(!mDeviceAddress.IsEmpty());
-    MOZ_ASSERT(mRunnable);
-  }
-
-  void Run() MOZ_OVERRIDE
-  {
-    MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
-    MOZ_ASSERT(sDBusConnection);
-
-    nsAutoString errorStr;
-    BluetoothValue v = true;
-    DBusMessage *msg;
-    if (!sPairingReqTable->Get(mDeviceAddress, &msg)) {
-      BT_WARNING("%s: Couldn't get original request message.", __FUNCTION__);
-      errorStr.AssignLiteral("Couldn't get original request message.");
-      DispatchBluetoothReply(mRunnable, v, errorStr);
-      return;
-    }
-
-    DBusMessage *reply;
-
-    if (mConfirm) {
-      reply = dbus_message_new_method_return(msg);
-    } else {
-      reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected",
-                                     "User rejected confirmation");
-    }
-
-    if (!reply) {
-      BT_WARNING("%s: Memory can't be allocated for the message.", __FUNCTION__);
-      dbus_message_unref(msg);
-      errorStr.AssignLiteral("Memory can't be allocated for the message.");
-      DispatchBluetoothReply(mRunnable, v, errorStr);
-      return;
-    }
-
-    bool result = sDBusConnection->Send(reply);
-    if (!result) {
-      errorStr.AssignLiteral("Can't send message!");
-    }
-    dbus_message_unref(msg);
-    dbus_message_unref(reply);
-
-    sPairingReqTable->Remove(mDeviceAddress);
-    DispatchBluetoothReply(mRunnable, v, errorStr);
-  }
-
-private:
-  nsString mDeviceAddress;
-  bool mConfirm;
-  nsRefPtr<BluetoothReplyRunnable> mRunnable;
-};
 
 bool
 BluetoothDBusService::SetPairingConfirmationInternal(
                                               const nsAString& aDeviceAddress,
                                               bool aConfirm,
                                               BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/camera/GonkRecorder.cpp
+++ b/dom/camera/GonkRecorder.cpp
@@ -46,16 +46,17 @@
 #include <utils/Errors.h>
 #include <sys/types.h>
 #include <ctype.h>
 #include <unistd.h>
 
 #include <cutils/properties.h>
 #include <system/audio.h>
 
+#define RES_720P (720 * 1280)
 namespace android {
 
 GonkRecorder::GonkRecorder()
     : mWriter(NULL),
       mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
       mStarted(false) {
@@ -365,16 +366,21 @@ status_t GonkRecorder::setParamMaxFileSi
         RE_LOGE("Max file size is too small: %lld bytes", bytes);
         return BAD_VALUE;
     }
 
     if (bytes <= 100 * 1024) {
         RE_LOGW("Target file size (%lld bytes) is too small to be respected", bytes);
     }
 
+    if (bytes >= 0xffffffffLL) {
+        RE_LOGW("Target file size (%lld bytes) too large to be respected, clipping to 4GB", bytes);
+        bytes = 0xffffffffLL;
+    }
+
     mMaxFileSizeBytes = bytes;
     return OK;
 }
 
 status_t GonkRecorder::setParamInterleaveDuration(int32_t durationUs) {
     RE_LOGV("setParamInterleaveDuration: %d", durationUs);
     if (durationUs <= 500000) {           //  500 ms
         // If interleave duration is too small, it is very inefficient to do
@@ -651,16 +657,23 @@ status_t GonkRecorder::setListener(const
 
 status_t GonkRecorder::setClientName(const String16& clientName) {
     mClientName = clientName;
 
     return OK;
 }
 
 status_t GonkRecorder::prepare() {
+    if (mVideoSource != VIDEO_SOURCE_LIST_END && mVideoEncoder != VIDEO_ENCODER_LIST_END &&
+        mVideoHeight && mVideoWidth &&  // Video recording
+        (mVideoHeight * mVideoWidth >= RES_720P)) {
+        // TODO: Above check needs to be updated when mMaxFileDurationUs is set from camera app
+        RE_LOGV("Video is high resolution so setting 64-bit file offsets");
+        setParam64BitFileOffset(true);
+    }
     return OK;
 }
 
 status_t GonkRecorder::start() {
     CHECK_GE(mOutputFd, 0);
 
     // Get UID here for permission checking
     mClientUid = IPCThreadState::self()->getCallingUid();
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -25,24 +25,16 @@
 #include "CallsList.h"
 #include "TelephonyCall.h"
 #include "TelephonyCallGroup.h"
 
 using namespace mozilla::dom;
 using mozilla::ErrorResult;
 using mozilla::dom::telephony::kOutgoingPlaceholderCallIndex;
 
-namespace {
-
-typedef nsAutoTArray<Telephony*, 2> TelephonyList;
-
-TelephonyList* gTelephonyList;
-
-} // anonymous namespace
-
 class Telephony::Listener : public nsITelephonyListener
 {
   Telephony* mTelephony;
 
 public:
   NS_DECL_ISUPPORTS
   NS_FORWARD_SAFE_NSITELEPHONYLISTENER(mTelephony)
 
@@ -116,36 +108,21 @@ public:
     mTelephony->NotifyCallsChanged(nullptr);
     return NS_OK;
   }
 };
 
 Telephony::Telephony(nsPIDOMWindow* aOwner)
   : DOMEventTargetHelper(aOwner), mActiveCall(nullptr), mEnumerated(false)
 {
-  if (!gTelephonyList) {
-    gTelephonyList = new TelephonyList();
-  }
-
-  gTelephonyList->AppendElement(this);
 }
 
 Telephony::~Telephony()
 {
   Shutdown();
-
-  NS_ASSERTION(gTelephonyList, "This should never be null!");
-  NS_ASSERTION(gTelephonyList->Contains(this), "Should be in the list!");
-
-  if (gTelephonyList->Length() == 1) {
-    delete gTelephonyList;
-    gTelephonyList = nullptr;
-  } else {
-    gTelephonyList->RemoveElement(this);
-  }
 }
 
 void
 Telephony::Shutdown()
 {
   if (mListener) {
     mListener->Disconnect();
 
--- a/dom/telephony/gonk/TelephonyProvider.js
+++ b/dom/telephony/gonk/TelephonyProvider.js
@@ -782,33 +782,27 @@ TelephonyProvider.prototype = {
                                                     aCall.number,
                                                     aCall.isActive,
                                                     aCall.isOutgoing,
                                                     aCall.isEmergency,
                                                     aCall.isConference,
                                                     aCall.isSwitchable,
                                                     aCall.isMergeable]);
     } else {
-      this.notifyCallError(aClientId, aCall.callIndex, aCall.failCause);
+      this._notifyAllListeners("notifyError",
+                               [aClientId, aCall.callIndex, aCall.failCause]);
     }
     delete this._currentCalls[aClientId][aCall.callIndex];
 
     if (manualConfStateChange) {
       this.notifyConferenceCallStateChanged(RIL.CALL_STATE_UNKNOWN);
     }
   },
 
   /**
-   * Handle call error.
-   */
-  notifyCallError: function(aClientId, aCallIndex, aErrorMsg) {
-    this._notifyAllListeners("notifyError", [aClientId, aCallIndex, aErrorMsg]);
-  },
-
-  /**
    * Handle an incoming call.
    *
    * Not much is known about this call at this point, but it's enough
    * to start bringing up the Phone app already.
    */
   notifyCallRing: function() {
     // We need to acquire a CPU wake lock to avoid the system falling into
     // the sleep mode when the RIL handles the incoming call.
--- a/dom/telephony/nsIGonkTelephonyProvider.idl
+++ b/dom/telephony/nsIGonkTelephonyProvider.idl
@@ -5,24 +5,21 @@
 
 #include "nsITelephonyProvider.idl"
 
 %{C++
 #define GONK_TELEPHONY_PROVIDER_CONTRACTID \
         "@mozilla.org/telephony/gonktelephonyprovider;1"
 %}
 
-[scriptable, uuid(5fdd720f-fbe8-46f5-b671-3bf3360013dd)]
+[scriptable, uuid(9d884482-90fc-4050-a4b1-1a370afe7a35)]
 interface nsIGonkTelephonyProvider : nsITelephonyProvider
 {
   void notifyCallDisconnected(in unsigned long clientId, in jsval call);
 
-  void notifyCallError(in unsigned long clientId, in long callIndex,
-                       in AString error);
-
   void notifyCallRing();
 
   void notifyCallStateChanged(in unsigned long clientId, in jsval call,
                               [optional] in boolean skipStateConversion);
 
   void notifyCdmaCallWaiting(in unsigned long clientId, in AString number);
 
   void notifySupplementaryService(in unsigned long clientId, in long callIndex,
--- a/layout/base/nsPresState.h
+++ b/layout/base/nsPresState.h
@@ -7,71 +7,84 @@
  * a piece of state that is stored in session history when the document
  * is not
  */
 
 #ifndef nsPresState_h_
 #define nsPresState_h_
 
 #include "nsPoint.h"
+#include "gfxPoint.h"
 #include "nsAutoPtr.h"
 
 class nsPresState
 {
 public:
   nsPresState()
     : mContentData(nullptr)
     , mScrollState(0, 0)
+    , mResolution(1.0, 1.0)
     , mDisabledSet(false)
     , mDisabled(false)
   {}
 
   void SetScrollState(const nsPoint& aState)
   {
     mScrollState = aState;
   }
 
-  nsPoint GetScrollState()
+  nsPoint GetScrollState() const
   {
     return mScrollState;
   }
 
+  void SetResolution(const gfxSize& aSize)
+  {
+    mResolution = aSize;
+  }
+
+  gfxSize GetResolution() const
+  {
+    return mResolution;
+  }
+
   void ClearNonScrollState()
   {
     mContentData = nullptr;
     mDisabledSet = false;
   }
 
-  bool GetDisabled()
+  bool GetDisabled() const
   {
     return mDisabled;
   }
 
   void SetDisabled(bool aDisabled)
   {
     mDisabled = aDisabled;
     mDisabledSet = true;
   }
 
-  bool IsDisabledSet()
+  bool IsDisabledSet() const
   {
     return mDisabledSet;
   }
 
-  nsISupports* GetStateProperty()
+  nsISupports* GetStateProperty() const
   {
     return mContentData;
   }
 
   void SetStateProperty(nsISupports *aProperty)
   {
     mContentData = aProperty;
   }
 
 // MEMBER VARIABLES
 protected:
   nsCOMPtr<nsISupports> mContentData;
   nsPoint mScrollState;
+  gfxSize mResolution;
   bool mDisabledSet;
   bool mDisabled;
 };
 
 #endif /* nsPresState_h_ */
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1595,16 +1595,17 @@ ScrollFrameHelper::ScrollFrameHelper(nsC
   , mOuter(aOuter)
   , mAsyncScroll(nullptr)
   , mOriginOfLastScroll(nsGkAtoms::other)
   , mScrollGeneration(++sScrollGenerationCounter)
   , mDestination(0, 0)
   , mScrollPosAtLastPaint(0, 0)
   , mRestorePos(-1, -1)
   , mLastPos(-1, -1)
+  , mResolution(1.0, 1.0)
   , mScrollPosForLayerPixelAlignment(-1, -1)
   , mLastUpdateImagesPos(-1, -1)
   , mNeverHasVerticalScrollbar(false)
   , mNeverHasHorizontalScrollbar(false)
   , mHasVerticalScrollbar(false)
   , mHasHorizontalScrollbar(false)
   , mFrameIsUpdatingScrollbar(false)
   , mDidHistoryRestore(false)
@@ -2781,16 +2782,28 @@ ScrollFrameHelper::GetScrollPositionClam
 {
   nsIPresShell* presShell = mOuter->PresContext()->PresShell();
   if (mIsRoot && presShell->IsScrollPositionClampingScrollPortSizeSet()) {
     return presShell->GetScrollPositionClampingScrollPortSize();
   }
   return mScrollPort.Size();
 }
 
+gfxSize
+ScrollFrameHelper::GetResolution() const
+{
+  return mResolution;
+}
+
+void
+ScrollFrameHelper::SetResolution(const gfxSize& aResolution)
+{
+  mResolution = aResolution;
+}
+
 static void
 AdjustForWholeDelta(int32_t aDelta, nscoord* aCoord)
 {
   if (aDelta < 0) {
     *aCoord = nscoord_MIN;
   } else if (aDelta > 0) {
     *aCoord = nscoord_MAX;
   }
@@ -4481,17 +4494,17 @@ ScrollFrameHelper::GetCoordAttribute(nsI
 
   // Only this exact default value is allowed.
   *aRangeStart = aDefaultValue;
   *aRangeLength = 0;
   return aDefaultValue;
 }
 
 nsPresState*
-ScrollFrameHelper::SaveState()
+ScrollFrameHelper::SaveState() const
 {
   nsIScrollbarMediator* mediator = do_QueryFrame(GetScrolledFrame());
   if (mediator) {
     // child handles its own scroll state, so don't bother saving state here
     return nullptr;
   }
 
   // Don't store a scroll state if we never have been scrolled or restored
@@ -4506,25 +4519,31 @@ ScrollFrameHelper::SaveState()
   // that ScrollToRestoredPosition uses). This ensures if a reframe occurs
   // while we're in the process of loading content to scroll to a restored
   // position, we'll keep trying after the reframe.
   nsPoint pt = GetLogicalScrollPosition();
   if (mRestorePos.y != -1 && pt == mLastPos) {
     pt = mRestorePos;
   }
   state->SetScrollState(pt);
+  state->SetResolution(mResolution);
   return state;
 }
 
 void
 ScrollFrameHelper::RestoreState(nsPresState* aState)
 {
   mRestorePos = aState->GetScrollState();
   mDidHistoryRestore = true;
   mLastPos = mScrolledFrame ? GetLogicalScrollPosition() : nsPoint(0,0);
+  mResolution = aState->GetResolution();
+
+  if (mIsRoot) {
+    mOuter->PresContext()->PresShell()->SetResolution(mResolution.width, mResolution.height);
+  }
 }
 
 void
 ScrollFrameHelper::PostScrolledAreaEvent()
 {
   if (mScrolledAreaEvent.IsPending()) {
     return;
   }
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -158,16 +158,19 @@ public:
       mScrollPort.XMost() - mScrolledFrame->GetRect().XMost();
     pt.y = mScrollPort.y - mScrolledFrame->GetPosition().y;
     return pt;
   }
   nsRect GetScrollRange() const;
   // Get the scroll range assuming the scrollport has size (aWidth, aHeight).
   nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
   nsSize GetScrollPositionClampingScrollPortSize() const;
+  gfxSize GetResolution() const;
+  void SetResolution(const gfxSize& aResolution);
+
 protected:
   nsRect GetScrollRangeForClamping() const;
 
 public:
   static void AsyncScrollCallback(void* anInstance, mozilla::TimeStamp aTime);
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    * aRange is the range of allowable scroll positions around the desired
@@ -202,17 +205,17 @@ public:
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    */
   void ScrollToRestoredPosition();
 
   nsSize GetLineScrollAmount() const;
   nsSize GetPageScrollAmount() const;
 
-  nsPresState* SaveState();
+  nsPresState* SaveState() const;
   void RestoreState(nsPresState* aState);
 
   nsIFrame* GetScrolledFrame() const { return mScrolledFrame; }
   nsIFrame* GetScrollbarBox(bool aVertical) const {
     return aVertical ? mVScrollbarBox : mHScrollbarBox;
   }
 
   void AddScrollPositionListener(nsIScrollPositionListener* aListener) {
@@ -343,16 +346,19 @@ public:
   // after every reflow --- because after each time content is loaded/added to the
   // scrollable element, there will be a reflow.
   nsPoint mRestorePos;
   // The last logical position we scrolled to while trying to restore mRestorePos, or
   // 0,0 when this is a new frame. Set to -1,-1 once we've scrolled for any reason
   // other than trying to restore mRestorePos.
   nsPoint mLastPos;
 
+  // The current resolution derived from the zoom level and device pixel ratio.
+  gfxSize mResolution;
+
   nsExpirationState mActivityExpirationState;
 
   nsCOMPtr<nsITimer> mScrollActivityTimer;
   nsPoint mScrollPosForLayerPixelAlignment;
 
   // The scroll position where we last updated image visibility.
   nsPoint mLastUpdateImagesPos;
 
@@ -572,16 +578,22 @@ public:
     return mHelper.GetLogicalScrollPosition();
   }
   virtual nsRect GetScrollRange() const MOZ_OVERRIDE {
     return mHelper.GetScrollRange();
   }
   virtual nsSize GetScrollPositionClampingScrollPortSize() const MOZ_OVERRIDE {
     return mHelper.GetScrollPositionClampingScrollPortSize();
   }
+  virtual gfxSize GetResolution() const MOZ_OVERRIDE {
+    return mHelper.GetResolution();
+  }
+  virtual void SetResolution(const gfxSize& aResolution) MOZ_OVERRIDE {
+    return mHelper.SetResolution(aResolution);
+  }
   virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE {
     return mHelper.GetLineScrollAmount();
   }
   virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE {
     return mHelper.GetPageScrollAmount();
   }
   /**
    * @note This method might destroy the frame, pres shell and other objects.
@@ -882,16 +894,22 @@ public:
     return mHelper.GetLogicalScrollPosition();
   }
   virtual nsRect GetScrollRange() const MOZ_OVERRIDE {
     return mHelper.GetScrollRange();
   }
   virtual nsSize GetScrollPositionClampingScrollPortSize() const MOZ_OVERRIDE {
     return mHelper.GetScrollPositionClampingScrollPortSize();
   }
+  virtual gfxSize GetResolution() const MOZ_OVERRIDE {
+    return mHelper.GetResolution();
+  }
+  virtual void SetResolution(const gfxSize& aResolution) MOZ_OVERRIDE {
+    return mHelper.SetResolution(aResolution);
+  }
   virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE {
     return mHelper.GetLineScrollAmount();
   }
   virtual nsSize GetPageScrollAmount() const MOZ_OVERRIDE {
     return mHelper.GetPageScrollAmount();
   }
   /**
    * @note This method might destroy the frame, pres shell and other objects.
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -129,17 +129,24 @@ public:
    * device pixels.
    */
   virtual nsRect GetScrollRange() const = 0;
   /**
    * Get the size of the scroll port to use when clamping the scroll
    * position.
    */
   virtual nsSize GetScrollPositionClampingScrollPortSize() const = 0;
-
+  /**
+   * Get the element resolution.
+   */
+  virtual gfxSize GetResolution() const = 0;
+  /**
+   * Set the element resolution.
+   */
+  virtual void SetResolution(const gfxSize& aResolution) = 0;
   /**
    * Return how much we would try to scroll by in each direction if
    * asked to scroll by one "line" vertically and horizontally.
    */
   virtual nsSize GetLineScrollAmount() const = 0;
   /**
    * Return how much we would try to scroll by in each direction if
    * asked to scroll by one "page" vertically and horizontally.
--- a/mobile/android/base/db/HomeProvider.java
+++ b/mobile/android/base/db/HomeProvider.java
@@ -78,17 +78,17 @@ public class HomeProvider extends SQLite
     }
 
     /**
      * Returns a cursor populated with static fake data.
      */
     private Cursor queryFakeItems(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         JSONArray items = null;
         try {
-            final String jsonString = RawResource.get(getContext(), R.raw.fake_home_items);
+            final String jsonString = RawResource.getAsString(getContext(), R.raw.fake_home_items);
             items = new JSONArray(jsonString);
         } catch (IOException e) {
             Log.e(LOGTAG, "Error getting fake home items", e);
             return null;
         } catch (JSONException e) {
             Log.e(LOGTAG, "Error parsing fake_home_items.json", e);
             return null;
         }
--- a/mobile/android/base/tests/components/ToolbarComponent.java
+++ b/mobile/android/base/tests/components/ToolbarComponent.java
@@ -81,16 +81,23 @@ public class ToolbarComponent extends Ba
         return (ImageButton) getToolbarView().findViewById(R.id.back);
     }
 
     private ImageButton getForwardButton() {
         DeviceHelper.assertIsTablet();
         return (ImageButton) getToolbarView().findViewById(R.id.forward);
     }
 
+    /**
+     * Returns the View for the edit cancel button in the browser toolbar.
+     */
+    private ImageButton getEditCancelButton() {
+        return (ImageButton) getToolbarView().findViewById(R.id.edit_cancel);
+    }
+
     private CharSequence getTitle() {
         return getTitleHelper(true);
     }
 
     /**
      * Returns the title of the page. Note that this makes no assertions to Toolbar state and
      * may return a value that may never be visible to the user. Callers likely want to use
      * {@link assertTitle} instead.
@@ -140,25 +147,30 @@ public class ToolbarComponent extends Ba
         waitForNotEditing();
 
         return this;
     }
 
     public ToolbarComponent dismissEditingMode() {
         assertIsEditing();
 
-        if (getUrlEditText().isInputMethodTarget()) {
-            // Drop the soft keyboard.
-            // TODO: Solo.hideSoftKeyboard() does not clear focus, causing unexpected
-            // behavior, but we may want to use it over goBack().
+        // Cancel Button not implemeneted in tablet.
+        if (DeviceHelper.isTablet()) {
+            if (getUrlEditText().isInputMethodTarget()) {
+                // Drop the soft keyboard.
+                // TODO: Solo.hideSoftKeyboard() does not clear focus, causing unexpected
+                // behavior, but we may want to use it over goBack().
+                mSolo.goBack();
+            }
+
             mSolo.goBack();
+        } else {
+            mSolo.clickOnView(getEditCancelButton());
         }
 
-        mSolo.goBack();
-
         waitForNotEditing();
 
         return this;
     }
 
     public ToolbarComponent enterUrl(final String url) {
         fAssertNotNull("url is not null", url);
 
--- a/mobile/android/base/util/RawResource.java
+++ b/mobile/android/base/util/RawResource.java
@@ -7,18 +7,27 @@ package org.mozilla.gecko.util;
 import android.content.Context;
 import android.content.res.Resources;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.StringWriter;
 
+/**
+ * {@code RawResource} provides API to load raw resources in different
+ * forms. For now, we only load them as strings. We're using raw resources
+ * as localizable 'assets' as opposed to a string that can be directly
+ * translatable e.g. JSON file vs string.
+ *
+ * This is just a utility class to avoid code duplication for the different
+ * cases where need to read such assets.
+ */
 public final class RawResource {
-    public static String get(Context context, int id) throws IOException {
+    public static String getAsString(Context context, int id) throws IOException {
         InputStreamReader reader = null;
 
         try {
             final Resources res = context.getResources();
             final InputStream is = res.openRawResource(id);
             if (is == null) {
                 return null;
             }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2877,16 +2877,17 @@ let gReflowPending = null;
 let gViewportMargins = { top: 0, right: 0, bottom: 0, left: 0};
 
 function Tab(aURL, aParams) {
   this.browser = null;
   this.id = 0;
   this.lastTouchedAt = Date.now();
   this._zoom = 1.0;
   this._drawZoom = 1.0;
+  this._restoreZoom = false;
   this._fixedMarginLeft = 0;
   this._fixedMarginTop = 0;
   this._fixedMarginRight = 0;
   this._fixedMarginBottom = 0;
   this._readerEnabled = false;
   this._readerActive = false;
   this.userScrollPos = { x: 0, y: 0 };
   this.viewportExcludesHorizontalMargins = true;
@@ -3481,16 +3482,17 @@ Tab.prototype = {
       docViewer.pausePainting();
 
       BrowserApp.selectedTab.performReflowOnZoom(aViewport);
       BrowserApp.selectedTab.probablyNeedRefloz = false;
     }
 
     let win = this.browser.contentWindow;
     win.scrollTo(x, y);
+    this.saveSessionZoom(aViewport.zoom);
 
     this.userScrollPos.x = win.scrollX;
     this.userScrollPos.y = win.scrollY;
     this.setResolution(aViewport.zoom, false);
 
     if (aViewport.displayPort)
       this.setDisplayPort(aViewport.displayPort);
 
@@ -3530,36 +3532,37 @@ Tab.prototype = {
     let html = aDocument.documentElement || { scrollWidth: aDefaultWidth, scrollHeight: aDefaultHeight };
     return [Math.max(body.scrollWidth, html.scrollWidth),
       Math.max(body.scrollHeight, html.scrollHeight)];
   },
 
   getViewport: function() {
     let screenW = gScreenWidth - gViewportMargins.left - gViewportMargins.right;
     let screenH = gScreenHeight - gViewportMargins.top - gViewportMargins.bottom;
+    let zoom = this.restoredSessionZoom() || this._zoom;
 
     let viewport = {
       width: screenW,
       height: screenH,
-      cssWidth: screenW / this._zoom,
-      cssHeight: screenH / this._zoom,
+      cssWidth: screenW / zoom,
+      cssHeight: screenH / zoom,
       pageLeft: 0,
       pageTop: 0,
       pageRight: screenW,
       pageBottom: screenH,
       // We make up matching css page dimensions
       cssPageLeft: 0,
       cssPageTop: 0,
-      cssPageRight: screenW / this._zoom,
-      cssPageBottom: screenH / this._zoom,
+      cssPageRight: screenW / zoom,
+      cssPageBottom: screenH / zoom,
       fixedMarginLeft: this._fixedMarginLeft,
       fixedMarginTop: this._fixedMarginTop,
       fixedMarginRight: this._fixedMarginRight,
       fixedMarginBottom: this._fixedMarginBottom,
-      zoom: this._zoom,
+      zoom: zoom,
     };
 
     // Set the viewport offset to current scroll offset
     viewport.cssX = this.browser.contentWindow.scrollX || 0;
     viewport.cssY = this.browser.contentWindow.scrollY || 0;
 
     // Transform coordinates based on zoom
     viewport.x = Math.round(viewport.cssX * viewport.zoom);
@@ -4181,28 +4184,47 @@ Tab.prototype = {
   },
 
   _sendHistoryEvent: function(aMessage, aParams) {
     let message = {
       type: "SessionHistory:" + aMessage,
       tabID: this.id,
     };
 
+    // Restore zoom only when moving in session history, not for new page loads.
+    this._restoreZoom = aMessage != "New";
+
     if (aParams) {
       if ("url" in aParams)
         message.url = aParams.url;
       if ("index" in aParams)
         message.index = aParams.index;
       if ("numEntries" in aParams)
         message.numEntries = aParams.numEntries;
     }
 
     sendMessageToJava(message);
   },
 
+  saveSessionZoom: function(aZoom) {
+    let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    cwu.setResolution(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio);
+  },
+
+  restoredSessionZoom: function() {
+    if (!this._restoreZoom) {
+      return null;
+    }
+
+    let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    let res = {x: {}, y: {}};
+    cwu.getResolution(res.x, res.y);
+    return res.x.value * window.devicePixelRatio;
+  },
+
   OnHistoryNewEntry: function(aUri) {
     this._sendHistoryEvent("New", { url: aUri.spec });
   },
 
   OnHistoryGoBack: function(aUri) {
     this._sendHistoryEvent("Back");
     return true;
   },
@@ -4317,18 +4339,21 @@ Tab.prototype = {
     //    viewport)
     // 3. screen size remains constant, but CSS viewport changes (meta viewport
     //    tag is added or removed)
     // 4. neither screen size nor CSS viewport changes
     //
     // In all of these cases, we maintain how much actual content is visible
     // within the screen width. Note that "actual content" may be different
     // with respect to CSS pixels because of the CSS viewport size changing.
-    let zoomScale = (screenW * oldBrowserWidth) / (aOldScreenWidth * viewportW);
-    let zoom = (aInitialLoad && metadata.defaultZoom) ? metadata.defaultZoom : this.clampZoom(this._zoom * zoomScale);
+    let zoom = this.restoredSessionZoom() || metadata.defaultZoom;
+    if (!zoom || !aInitialLoad) {
+      let zoomScale = (screenW * oldBrowserWidth) / (aOldScreenWidth * viewportW);
+      zoom = this.clampZoom(this._zoom * zoomScale);
+    }
     this.setResolution(zoom, false);
     this.setScrollClampingSize(zoom);
 
     // if this page has not been painted yet, then this must be getting run
     // because a meta-viewport element was added (via the DOMMetaAdded handler).
     // in this case, we should not do anything that forces a reflow (see bug 759678)
     // such as requesting the page size or sending a viewport update. this code
     // will get run again in the before-first-paint handler and that point we
@@ -4454,17 +4479,18 @@ Tab.prototype = {
           this.contentDocumentIsDisplayed = true;
 
           // reset CSS viewport and zoom to default on new page, and then calculate
           // them properly using the actual metadata from the page. note that the
           // updateMetadata call takes into account the existing CSS viewport size
           // and zoom when calculating the new ones, so we need to reset these
           // things here before calling updateMetadata.
           this.setBrowserSize(kDefaultCSSViewportWidth, kDefaultCSSViewportHeight);
-          this.setResolution(gScreenWidth / this.browserWidth, false);
+          let zoom = this.restoredSessionZoom() || gScreenWidth / this.browserWidth;
+          this.setResolution(zoom, true);
           ViewportHandler.updateMetadata(this, true);
 
           // Note that if we draw without a display-port, things can go wrong. By the
           // time we execute this, it's almost certain a display-port has been set via
           // the MozScrolledAreaChanged event. If that didn't happen, the updateMetadata
           // call above does so at the end of the updateViewportSize function. As long
           // as that is happening, we don't need to do it again here.
 
--- a/mobile/android/tests/browser/junit3/moz.build
+++ b/mobile/android/tests/browser/junit3/moz.build
@@ -8,16 +8,17 @@ DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG
 
 jar = add_java_jar('browser-junit3')
 jar.sources += [
     'src/harness/BrowserInstrumentationTestRunner.java',
     'src/harness/BrowserTestListener.java',
     'src/tests/BrowserTestCase.java',
     'src/tests/TestGeckoSharedPrefs.java',
     'src/tests/TestJarReader.java',
+    'src/tests/TestRawResource.java',
     'src/tests/TestTopSitesCursorWrapper.java',
 ]
 jar.generated_sources = [] # None yet -- try to keep it this way.
 jar.javac_flags += ['-Xlint:all,-unchecked']
 
 # Android Eclipse project.
 main = add_android_eclipse_project('BrowserInstrumentationTests', OBJDIR + '/AndroidManifest.xml')
 # The package name doesn't really matter, but it looks nicest if the
new file mode 100644
--- /dev/null
+++ b/mobile/android/tests/browser/junit3/src/tests/TestRawResource.java
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.gecko.browser.tests;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.mock.MockContext;
+import android.test.mock.MockResources;
+import android.util.TypedValue;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.mozilla.gecko.util.RawResource;
+
+/**
+ * Tests whether RawResource.getAsString() produces the right String
+ * result after reading the returned raw resource's InputStream.
+ */
+public class TestRawResource extends BrowserTestCase {
+    private static final int RAW_RESOURCE_ID = 1;
+    private static final String RAW_CONTENTS = "RAW";
+
+    private static class TestContext extends MockContext {
+        private final Resources resources;
+
+        public TestContext() {
+            resources = new TestResources();
+        }
+
+        @Override
+        public Resources getResources() {
+            return resources;
+        }
+    }
+
+    /**
+     * Browser instrumentation tests can't have access to test-only
+     * resources (bug 994135) yet so we mock the access to resources
+     * for now.
+     */
+    private static class TestResources extends MockResources {
+        @Override
+        public InputStream openRawResource(int id) {
+            if (id == RAW_RESOURCE_ID) {
+                return new ByteArrayInputStream(RAW_CONTENTS.getBytes());
+            }
+
+            return null;
+        }
+    }
+
+    public void testGet() {
+        Context context = new TestContext();
+        String result;
+
+        try {
+            result = RawResource.getAsString(context, RAW_RESOURCE_ID);
+        } catch (IOException e) {
+            result = null;
+        }
+
+        assertEquals(RAW_CONTENTS, result);
+    }
+}
\ No newline at end of file
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -2,16 +2,17 @@
 /* vim: set sw=2 ts=8 et tw=80 ft=c: */
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PHttpChannel;
 include protocol PFTPChannel;
+include protocol PRtspChannel;
 include URIParams;
 include InputStreamParams;
 
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h";
 using struct nsHttpAtom from "nsHttp.h";
 
 namespace mozilla {
@@ -84,10 +85,20 @@ union FTPChannelCreationArgs
 };
 
 union ChannelDiverterArgs
 {
   PHttpChannel;
   PFTPChannel;
 };
 
+//-----------------------------------------------------------------------------
+// RTSP IPDL structs
+//-----------------------------------------------------------------------------
+
+struct RtspChannelConnectArgs
+{
+  URIParams uri;
+  uint32_t channelId;
+};
+
 } // namespace ipc
 } // namespace mozilla
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/net/DNSRequestChild.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
 #include "mozilla/net/ChannelDiverterChild.h"
 #include "mozilla/dom/network/TCPSocketChild.h"
 #include "mozilla/dom/network/TCPServerSocketChild.h"
 #include "mozilla/dom/network/UDPSocketChild.h"
 #ifdef NECKO_PROTOCOL_rtsp
 #include "mozilla/net/RtspControllerChild.h"
+#include "mozilla/net/RtspChannelChild.h"
 #endif
 #include "SerializedLoadContext.h"
 
 using mozilla::dom::TCPSocketChild;
 using mozilla::dom::TCPServerSocketChild;
 using mozilla::dom::UDPSocketChild;
 
 namespace mozilla {
@@ -176,16 +177,33 @@ NeckoChild::DeallocPRtspControllerChild(
 {
 #ifdef NECKO_PROTOCOL_rtsp
   RtspControllerChild* p = static_cast<RtspControllerChild*>(child);
   p->ReleaseIPDLReference();
 #endif
   return true;
 }
 
+PRtspChannelChild*
+NeckoChild::AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs)
+{
+  NS_NOTREACHED("AllocPRtspController should not be called");
+  return nullptr;
+}
+
+bool
+NeckoChild::DeallocPRtspChannelChild(PRtspChannelChild* child)
+{
+#ifdef NECKO_PROTOCOL_rtsp
+  RtspChannelChild* p = static_cast<RtspChannelChild*>(child);
+  p->ReleaseIPDLReference();
+#endif
+  return true;
+}
+
 PTCPSocketChild*
 NeckoChild::AllocPTCPSocketChild()
 {
   TCPSocketChild* p = new TCPSocketChild();
   p->AddIPDLReference();
   return p;
 }
 
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -57,16 +57,20 @@ protected:
                                                   const uint32_t& aFlags) MOZ_OVERRIDE;
   virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) MOZ_OVERRIDE;
   virtual PRemoteOpenFileChild*
     AllocPRemoteOpenFileChild(const URIParams&,
                               const OptionalURIParams&) MOZ_OVERRIDE;
   virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*) MOZ_OVERRIDE;
   virtual PRtspControllerChild* AllocPRtspControllerChild() MOZ_OVERRIDE;
   virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) MOZ_OVERRIDE;
+  virtual PRtspChannelChild*
+    AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs)
+                           MOZ_OVERRIDE;
+  virtual bool DeallocPRtspChannelChild(PRtspChannelChild*) MOZ_OVERRIDE;
   virtual PChannelDiverterChild*
   AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) MOZ_OVERRIDE;
   virtual bool
   DeallocPChannelDiverterChild(PChannelDiverterChild* actor) MOZ_OVERRIDE;
 };
 
 /**
  * Reference to the PNecko Child protocol.
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/net/HttpChannelParent.h"
 #include "mozilla/net/CookieServiceParent.h"
 #include "mozilla/net/WyciwygChannelParent.h"
 #include "mozilla/net/FTPChannelParent.h"
 #include "mozilla/net/WebSocketChannelParent.h"
 #ifdef NECKO_PROTOCOL_rtsp
 #include "mozilla/net/RtspControllerParent.h"
+#include "mozilla/net/RtspChannelParent.h"
 #endif
 #include "mozilla/net/DNSRequestParent.h"
 #include "mozilla/net/RemoteOpenFileParent.h"
 #include "mozilla/net/ChannelDiverterParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/network/TCPSocketParent.h"
 #include "mozilla/dom/network/TCPServerSocketParent.h"
@@ -331,16 +332,52 @@ NeckoParent::DeallocPRtspControllerParen
 {
 #ifdef NECKO_PROTOCOL_rtsp
   RtspControllerParent* p = static_cast<RtspControllerParent*>(actor);
   p->Release();
 #endif
   return true;
 }
 
+PRtspChannelParent*
+NeckoParent::AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs)
+{
+#ifdef NECKO_PROTOCOL_rtsp
+  nsCOMPtr<nsIURI> uri = DeserializeURI(aArgs.uri());
+  RtspChannelParent *p = new RtspChannelParent(uri);
+  p->AddRef();
+  return p;
+#else
+  return nullptr;
+#endif
+}
+
+bool
+NeckoParent::RecvPRtspChannelConstructor(
+                      PRtspChannelParent* aActor,
+                      const RtspChannelConnectArgs& aConnectArgs)
+{
+#ifdef NECKO_PROTOCOL_rtsp
+  RtspChannelParent* p = static_cast<RtspChannelParent*>(aActor);
+  return p->Init(aConnectArgs);
+#else
+  return nullptr;
+#endif
+}
+
+bool
+NeckoParent::DeallocPRtspChannelParent(PRtspChannelParent* actor)
+{
+#ifdef NECKO_PROTOCOL_rtsp
+  RtspChannelParent* p = static_cast<RtspChannelParent*>(actor);
+  p->Release();
+#endif
+  return true;
+}
+
 PTCPSocketParent*
 NeckoParent::AllocPTCPSocketParent()
 {
   TCPSocketParent* p = new TCPSocketParent();
   p->AddIPDLReference();
   return p;
 }
 
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -139,16 +139,25 @@ protected:
                                          const nsresult& reason) MOZ_OVERRIDE;
 
   virtual mozilla::ipc::IProtocol*
   CloneProtocol(Channel* aChannel,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
   virtual PRtspControllerParent* AllocPRtspControllerParent() MOZ_OVERRIDE;
   virtual bool DeallocPRtspControllerParent(PRtspControllerParent*) MOZ_OVERRIDE;
 
+  virtual PRtspChannelParent*
+    AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs)
+                            MOZ_OVERRIDE;
+  virtual bool
+    RecvPRtspChannelConstructor(PRtspChannelParent* aActor,
+                                const RtspChannelConnectArgs& aArgs)
+                                MOZ_OVERRIDE;
+  virtual bool DeallocPRtspChannelParent(PRtspChannelParent*) MOZ_OVERRIDE;
+
   virtual PChannelDiverterParent*
   AllocPChannelDiverterParent(const ChannelDiverterArgs& channel) MOZ_OVERRIDE;
   virtual bool
   RecvPChannelDiverterConstructor(PChannelDiverterParent* actor,
                                   const ChannelDiverterArgs& channel) MOZ_OVERRIDE;
   virtual bool DeallocPChannelDiverterParent(PChannelDiverterParent* actor)
                                                                 MOZ_OVERRIDE;
 
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -17,16 +17,17 @@ include protocol PTCPServerSocket;
 include protocol PUDPSocket;
 include protocol PRemoteOpenFile;
 include protocol PDNSRequest;
 include protocol PChannelDiverter;
 include protocol PBlob; //FIXME: bug #792908
 include protocol PFileDescriptorSet;
 
 include protocol PRtspController;
+include protocol PRtspChannel;
 include URIParams;
 include InputStreamParams;
 include NeckoChannelParams;
 
 
 using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
 
 namespace mozilla {
@@ -42,16 +43,17 @@ sync protocol PNecko
   manages PFTPChannel;
   manages PWebSocket;
   manages PTCPSocket;
   manages PTCPServerSocket;
   manages PUDPSocket;
   manages PDNSRequest;
   manages PRemoteOpenFile;
   manages PRtspController;
+  manages PRtspChannel;
   manages PChannelDiverter;
 
 parent:
   __delete__();
 
   PCookieService();
   PHttpChannel(nullable PBrowser browser,
                SerializedLoadContext loadContext,
@@ -66,16 +68,17 @@ parent:
 
   PDNSRequest(nsCString hostName, uint32_t flags);
 
   PRemoteOpenFile(URIParams fileuri, OptionalURIParams appuri);
 
   HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
   PRtspController();
+  PRtspChannel(RtspChannelConnectArgs args);
   PChannelDiverter(ChannelDiverterArgs channel);
 
 both:
   PTCPSocket();
 };
 
 
 } // namespace net
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/PRtspChannel.ipdl
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PNecko;
+include URIParams;
+
+namespace mozilla {
+namespace net {
+
+async protocol PRtspChannel
+{
+  manager PNecko;
+
+parent:
+  // Note: channels are opened during construction, so no open method here:
+  // see PNecko.ipdl
+  __delete__();
+};
+
+} // namespace net
+} // namespace mozilla
--- a/netwerk/ipc/moz.build
+++ b/netwerk/ipc/moz.build
@@ -29,16 +29,17 @@ UNIFIED_SOURCES += [
     'RemoteOpenFileParent.cpp',
 ]
 
 IPDL_SOURCES = [
     'NeckoChannelParams.ipdlh',
     'PChannelDiverter.ipdl',
     'PNecko.ipdl',
     'PRemoteOpenFile.ipdl',
+    'PRtspChannel.ipdl',
     'PRtspController.ipdl',
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'necko'
--- a/netwerk/protocol/rtsp/RtspChannelChild.cpp
+++ b/netwerk/protocol/rtsp/RtspChannelChild.cpp
@@ -1,62 +1,271 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RtspChannelChild.h"
-#include "nsIURI.h"
-#include "nsAutoPtr.h"
-#include "nsStandardURL.h"
+#include "mozilla/ipc/URIUtils.h"
+
+using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
-NS_IMPL_ISUPPORTS_INHERITED1(RtspChannelChild,
-                             nsBaseChannel,
-                             nsIChannel)
+//-----------------------------------------------------------------------------
+// RtspChannelChild
+//-----------------------------------------------------------------------------
+RtspChannelChild::RtspChannelChild(nsIURI *aUri)
+  : mIPCOpen(false)
+  , mCanceled(false)
+{
+  nsBaseChannel::SetURI(aUri);
+}
+
+RtspChannelChild::~RtspChannelChild()
+{
+}
+
+nsIStreamingProtocolController*
+RtspChannelChild::GetController()
+{
+  return mMediaStreamController;
+}
+
+void
+RtspChannelChild::ReleaseController()
+{
+  if (mMediaStreamController) {
+    mMediaStreamController = nullptr;
+  }
+}
 
 //-----------------------------------------------------------------------------
-// RtspChannelChild::nsIChannel
+// IPDL
 //-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
+void
+RtspChannelChild::AddIPDLReference()
 {
-  MOZ_ASSERT(aListener);
-
-  nsCOMPtr<nsIURI> uri = nsBaseChannel::URI();
-  NS_ENSURE_TRUE(uri, NS_ERROR_ILLEGAL_VALUE);
-
-  nsAutoCString uriSpec;
-  uri->GetSpec(uriSpec);
-
-  mListener = aListener;
-  mListenerContext = aContext;
-
-  // Call OnStartRequest directly. mListener is expected to create/load an
-  // RtspMediaResource which will create an RtspMediaController. This controller
-  // manages the control and data streams to and from the network.
-  mListener->OnStartRequest(this, aContext);
-  return NS_OK;
+  NS_ABORT_IF_FALSE(!mIPCOpen,
+                    "Attempt to retain more than one IPDL reference");
+  mIPCOpen = true;
+  AddRef();
 }
 
+void
+RtspChannelChild::ReleaseIPDLReference()
+{
+  NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
+  mIPCOpen = false;
+  Release();
+}
+
+//-----------------------------------------------------------------------------
+// nsISupports
+//-----------------------------------------------------------------------------
+NS_IMPL_ISUPPORTS_INHERITED2(RtspChannelChild,
+                             nsBaseChannel,
+                             nsIChannel,
+                             nsIChildChannel)
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIChannel
+//-----------------------------------------------------------------------------
 NS_IMETHODIMP
 RtspChannelChild::GetContentType(nsACString& aContentType)
 {
   aContentType.AssignLiteral("RTSP");
   return NS_OK;
 }
 
+class CallListenerOnStartRequestEvent : public nsRunnable
+{
+public:
+  CallListenerOnStartRequestEvent(nsIStreamListener *aListener,
+                                  nsIRequest *aRequest, nsISupports *aContext)
+    : mListener(aListener)
+    , mRequest(aRequest)
+    , mContext(aContext)
+  {
+    MOZ_RELEASE_ASSERT(aListener);
+  }
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    mListener->OnStartRequest(mRequest, mContext);
+    return NS_OK;
+  }
+private:
+  nsRefPtr<nsIStreamListener> mListener;
+  nsRefPtr<nsIRequest> mRequest;
+  nsRefPtr<nsISupports> mContext;
+};
+
 NS_IMETHODIMP
-RtspChannelChild::Init(nsIURI* aUri)
+RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
 {
-  MOZ_ASSERT(aUri);
+  // Precondition checks.
+  MOZ_ASSERT(aListener);
+  nsCOMPtr<nsIURI> uri = nsBaseChannel::URI();
+  NS_ENSURE_TRUE(uri, NS_ERROR_ILLEGAL_VALUE);
+
+  // Create RtspController.
+  nsCOMPtr<nsIStreamingProtocolControllerService> mediaControllerService =
+    do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID);
+  MOZ_RELEASE_ASSERT(mediaControllerService,
+    "Cannot proceed if media controller service is unavailable!");
+  mediaControllerService->Create(this, getter_AddRefs(mMediaStreamController));
+  MOZ_ASSERT(mMediaStreamController);
 
-  nsBaseChannel::Init();
-  nsBaseChannel::SetURI(aUri);
+  // Add ourselves to the load group.
+  if (mLoadGroup) {
+    mLoadGroup->AddRequest(this, nullptr);
+  }
+
+  // Dispatch mListener's OnStartRequest directly. mListener is expected to
+  // create an RtspMediaResource and use the RtspController we just created to
+  // manage the control and data streams to and from the network.
+  mListener = aListener;
+  mListenerContext = aContext;
+  NS_DispatchToMainThread(
+    new CallListenerOnStartRequestEvent(mListener, this, mListenerContext));
+
   return NS_OK;
 }
 
-} // namespace mozilla::net
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIStreamListener::nsIRequestObserver
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelChild::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+NS_IMETHODIMP
+RtspChannelChild::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
+                                nsresult aStatusCode)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIStreamListener
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelChild::OnDataAvailable(nsIRequest *aRequest,
+                                  nsISupports *aContext,
+                                  nsIInputStream *aInputStream,
+                                  uint64_t aOffset,
+                                  uint32_t aCount)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIChannel::nsIRequest
+//-----------------------------------------------------------------------------
+class CallListenerOnStopRequestEvent : public nsRunnable
+{
+public:
+  CallListenerOnStopRequestEvent(nsIStreamListener *aListener,
+                                 nsIRequest *aRequest,
+                                 nsISupports *aContext, nsresult aStatus)
+    : mListener(aListener)
+    , mRequest(aRequest)
+    , mContext(aContext)
+    , mStatus(aStatus)
+  {
+    MOZ_RELEASE_ASSERT(aListener);
+  }
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    mListener->OnStopRequest(mRequest, mContext, mStatus);
+    return NS_OK;
+  }
+private:
+  nsRefPtr<nsIStreamListener> mListener;
+  nsRefPtr<nsIRequest> mRequest;
+  nsRefPtr<nsISupports> mContext;
+  nsresult mStatus;
+};
+
+NS_IMETHODIMP
+RtspChannelChild::Cancel(nsresult status)
+{
+  if (mCanceled) {
+    return NS_OK;
+  }
+
+  mCanceled = true;
+  // Stop RtspController.
+  if (mMediaStreamController) {
+    mMediaStreamController->Stop();
+  }
+
+  // Call mListener's OnStopRequest to do clean up.
+  NS_DispatchToMainThread(
+    new CallListenerOnStopRequestEvent(mListener, this,
+                                       mListenerContext, status));
+  mListener = nullptr;
+  mListenerContext = nullptr;
+
+  // Remove ourselves from the load group.
+  if (mLoadGroup) {
+    mLoadGroup->RemoveRequest(this, nullptr, status);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+RtspChannelChild::Suspend()
+{
+  MOZ_CRASH("Should never be called");
+}
+
+NS_IMETHODIMP
+RtspChannelChild::Resume()
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelChild::OpenContentStream(bool aAsync,
+                                    nsIInputStream **aStream,
+                                    nsIChannel **aChannel)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsIChildChannel
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelChild::ConnectParent(uint32_t id)
+{
+  // Create RtspChannelParent for redirection.
+  AddIPDLReference();
+  RtspChannelConnectArgs connectArgs;
+  SerializeURI(nsBaseChannel::URI(), connectArgs.uri());
+  connectArgs.channelId() = id;
+  if (!gNeckoChild->SendPRtspChannelConstructor(this, connectArgs)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+RtspChannelChild::CompleteRedirectSetup(nsIStreamListener *aListener,
+                                        nsISupports *aContext)
+{
+  return AsyncOpen(aListener, aContext);
+}
+
+} // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/rtsp/RtspChannelChild.h
+++ b/netwerk/protocol/rtsp/RtspChannelChild.h
@@ -2,74 +2,87 @@
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef RtspChannelChild_h
 #define RtspChannelChild_h
 
+#include "mozilla/net/PRtspChannelChild.h"
+#include "mozilla/net/NeckoChild.h"
 #include "nsBaseChannel.h"
+#include "nsIChildChannel.h"
+#include "nsIStreamingProtocolController.h"
+#include "nsIStreamingProtocolService.h"
 
 namespace mozilla {
 namespace net {
 
 //-----------------------------------------------------------------------------
 // RtspChannelChild is a dummy channel used to aid MediaResource creation in
-// HTMLMediaElement. Actual network control and data flows are managed by an
-// RtspController object created and owned by RtspMediaResource.
-// Therefore, when RtspChannelChild::AsyncOpen is called, mListener->OnStartRequest
-// will be called immediately. It is expected that an RtspMediaResource object
-// will be created in that calling context or after; the RtspController object
-// will be created internally by RtspMediaResource."
+// HTMLMediaElement. Network control and data flows are managed by an
+// RtspController object, which is created by us and manipulated by
+// RtspMediaResource. This object is also responsible for inter-process
+// communication with the parent process.
+// When RtspChannelChild::AsyncOpen is called, it should create an
+// RtspController object, dispatch an OnStartRequest and immediately return.
+// We expect an RtspMediaResource object will be created in the calling context
+// and it will use the RtpController we create.
 
-class RtspChannelChild : public nsBaseChannel
+class RtspChannelChild : public PRtspChannelChild
+                       , public nsBaseChannel
+                       , public nsIChildChannel
 {
 public:
   NS_DECL_ISUPPORTS
-
-  RtspChannelChild() { }
-
-  ~RtspChannelChild() { }
+  NS_DECL_NSICHILDCHANNEL
 
-  // Overrides nsBaseChannel::AsyncOpen and call listener's OnStartRequest immediately.
-  NS_IMETHOD AsyncOpen(nsIStreamListener *listener,
-                       nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL;
-  // Set Rtsp URL.
-  NS_IMETHOD Init(nsIURI* uri);
-  // Overrides nsBaseChannel::GetContentType, return streaming protocol type "RTSP".
-  NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL;
+  RtspChannelChild(nsIURI *aUri);
+  ~RtspChannelChild();
 
-  NS_IMETHOD OpenContentStream(bool aAsync,
-                               nsIInputStream **aStream,
-                               nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
+  // nsBaseChannel::nsIChannel
+  NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
+                       MOZ_OVERRIDE MOZ_FINAL;
 
-  // nsIRequestObserver
-  NS_IMETHOD OnStartRequest(nsIRequest *aRequest,
-                            nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
+  // nsBaseChannel::nsIStreamListener::nsIRequestObserver
+  NS_IMETHOD OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
+                            MOZ_OVERRIDE MOZ_FINAL;
   NS_IMETHOD OnStopRequest(nsIRequest *aRequest,
                            nsISupports *aContext,
-                           nsresult aStatusCode) MOZ_OVERRIDE MOZ_FINAL
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
+                           nsresult aStatusCode) MOZ_OVERRIDE MOZ_FINAL;
 
-  // nsIStreamListener
+  // nsBaseChannel::nsIStreamListener
   NS_IMETHOD OnDataAvailable(nsIRequest *aRequest,
                              nsISupports *aContext,
                              nsIInputStream *aInputStream,
                              uint64_t aOffset,
-                             uint32_t aCount) MOZ_OVERRIDE MOZ_FINAL
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
+                             uint32_t aCount) MOZ_OVERRIDE MOZ_FINAL;
+
+  // nsBaseChannel::nsIChannel::nsIRequest
+  NS_IMETHOD Cancel(nsresult status) MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD Suspend() MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD Resume() MOZ_OVERRIDE MOZ_FINAL;
+
+  // nsBaseChannel
+  NS_IMETHOD OpenContentStream(bool aAsync,
+                               nsIInputStream **aStream,
+                               nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL;
+
+  // IPDL
+  void AddIPDLReference();
+  void ReleaseIPDLReference();
+
+  // RtspChannelChild
+  nsIStreamingProtocolController* GetController();
+  void ReleaseController();
+
+private:
+  bool mIPCOpen;
+  bool mCanceled;
+  nsCOMPtr<nsIStreamingProtocolController> mMediaStreamController;
 };
 
-}
-} // namespace mozilla::net
+} // namespace net
+} // namespace mozilla
+
 #endif // RtspChannelChild_h
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/rtsp/RtspChannelParent.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RtspChannelParent.h"
+
+using namespace mozilla::ipc;
+
+namespace mozilla {
+namespace net {
+
+//-----------------------------------------------------------------------------
+// RtspChannelParent
+//-----------------------------------------------------------------------------
+RtspChannelParent::RtspChannelParent(nsIURI *aUri)
+  : mIPCClosed(false)
+{
+  nsBaseChannel::SetURI(aUri);
+}
+
+RtspChannelParent::~RtspChannelParent()
+{
+}
+
+void
+RtspChannelParent::ActorDestroy(ActorDestroyReason why)
+{
+  mIPCClosed = true;
+}
+
+//-----------------------------------------------------------------------------
+// nsISupports
+//-----------------------------------------------------------------------------
+NS_IMPL_ISUPPORTS_INHERITED1(RtspChannelParent,
+                             nsBaseChannel,
+                             nsIParentChannel)
+
+//-----------------------------------------------------------------------------
+// RtspChannelParent methods
+//-----------------------------------------------------------------------------
+bool
+RtspChannelParent::Init(const RtspChannelConnectArgs& aArgs)
+{
+  return ConnectChannel(aArgs.channelId());
+}
+
+bool
+RtspChannelParent::ConnectChannel(const uint32_t& channelId)
+{
+  nsresult rv;
+  nsCOMPtr<nsIChannel> channel;
+  rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
+
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIChannel
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelParent::GetContentType(nsACString& aContentType)
+{
+  aContentType.AssignLiteral("RTSP");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+RtspChannelParent::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
+{
+  return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIStreamListener::nsIRequestObserver
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelParent::OnStartRequest(nsIRequest *aRequest,
+                            nsISupports *aContext)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+NS_IMETHODIMP
+RtspChannelParent::OnStopRequest(nsIRequest *aRequest,
+                           nsISupports *aContext,
+                           nsresult aStatusCode)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIStreamListener
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelParent::OnDataAvailable(nsIRequest *aRequest,
+                             nsISupports *aContext,
+                             nsIInputStream *aInputStream,
+                             uint64_t aOffset,
+                             uint32_t aCount)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel::nsIChannel::nsIRequeset
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelParent::Cancel(nsresult status)
+{
+  // FIXME: This method will be called by
+  // nsXMLHttpRequest::CloseRequestWithError while closing the browser app.
+  // However, the root cause is RtspChannelParent will be created by
+  // nsXMLHttpRequest::Open when we navigate away from an RTSP web page.
+  // We should find out why it happens and decide how to fix it.
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+RtspChannelParent::Suspend()
+{
+  MOZ_CRASH("Should never be called");
+}
+
+NS_IMETHODIMP
+RtspChannelParent::Resume()
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsBaseChannel
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelParent::OpenContentStream(bool aAsync,
+                               nsIInputStream **aStream,
+                               nsIChannel **aChannel)
+{
+  MOZ_CRASH("Should never be called");
+}
+
+//-----------------------------------------------------------------------------
+// nsIParentChannel
+//-----------------------------------------------------------------------------
+NS_IMETHODIMP
+RtspChannelParent::SetParentListener(HttpChannelParentListener *aListener)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+RtspChannelParent::Delete()
+{
+  return NS_OK;
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/rtsp/RtspChannelParent.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef RtspChannelParent_h
+#define RtspChannelParent_h
+
+#include "mozilla/net/PRtspChannelParent.h"
+#include "mozilla/net/NeckoParent.h"
+#include "nsBaseChannel.h"
+#include "nsIParentChannel.h"
+
+namespace mozilla {
+namespace net {
+
+//-----------------------------------------------------------------------------
+// Note: RtspChannel doesn't transport streams as normal channel does.
+// (See RtspChannelChild.h for detail).
+// The reason for the existence of RtspChannelParent is to support HTTP->RTSP
+// redirection.
+// When redirection happens, two instances of RtspChannelParent will be created:
+// - One will be created when HTTP creates the new channel for redirects, and
+//   will be registered as an nsIChannel.
+// - The other will be created via IPDL by RtspChannelChild, and will be
+//   registered as an nsIParentChannel.
+class RtspChannelParent : public PRtspChannelParent
+                        , public nsBaseChannel
+                        , public nsIParentChannel
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPARENTCHANNEL
+
+  RtspChannelParent(nsIURI *aUri);
+  ~RtspChannelParent();
+
+  // nsBaseChannel::nsIChannel
+  NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD AsyncOpen(nsIStreamListener *listener,
+                       nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL;
+
+  // nsBaseChannel::nsIStreamListener::nsIRequestObserver
+  NS_IMETHOD OnStartRequest(nsIRequest *aRequest,
+                            nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD OnStopRequest(nsIRequest *aRequest,
+                           nsISupports *aContext,
+                           nsresult aStatusCode) MOZ_OVERRIDE MOZ_FINAL;
+
+  // nsBaseChannel::nsIStreamListener
+  NS_IMETHOD OnDataAvailable(nsIRequest *aRequest,
+                             nsISupports *aContext,
+                             nsIInputStream *aInputStream,
+                             uint64_t aOffset,
+                             uint32_t aCount) MOZ_OVERRIDE MOZ_FINAL;
+
+  // nsBaseChannel::nsIChannel::nsIRequest
+  NS_IMETHOD Cancel(nsresult status) MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD Suspend() MOZ_OVERRIDE MOZ_FINAL;
+  NS_IMETHOD Resume() MOZ_OVERRIDE MOZ_FINAL;
+
+  // nsBaseChannel
+  NS_IMETHOD OpenContentStream(bool aAsync,
+                               nsIInputStream **aStream,
+                               nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL;
+
+  // RtspChannelParent
+  bool Init(const RtspChannelConnectArgs& aArgs);
+
+protected:
+  // Used to connect redirected-to channel in parent with just created
+  // ChildChannel. Used during HTTP->RTSP redirection.
+  bool ConnectChannel(const uint32_t& channelId);
+
+private:
+  bool mIPCClosed;
+  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // RtspChannelParent_h
--- a/netwerk/protocol/rtsp/RtspHandler.cpp
+++ b/netwerk/protocol/rtsp/RtspHandler.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RtspChannelChild.h"
+#include "RtspChannelParent.h"
 #include "RtspHandler.h"
 #include "nsILoadGroup.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsStandardURL.h"
 #include "mozilla/net/NeckoChild.h"
 
@@ -63,25 +64,29 @@ RtspHandler::NewURI(const nsACString & a
   url.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 RtspHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult)
 {
   bool isRtsp = false;
-  nsRefPtr<RtspChannelChild> rtspChannel;
+  nsRefPtr<nsBaseChannel> rtspChannel;
 
   nsresult rv = aURI->SchemeIs("rtsp", &isRtsp);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(isRtsp, NS_ERROR_UNEXPECTED);
 
-  rtspChannel = new RtspChannelChild();
+  if (IsNeckoChild()) {
+    rtspChannel = new RtspChannelChild(aURI);
+  } else {
+    rtspChannel = new RtspChannelParent(aURI);
+  }
 
-  rv = rtspChannel->Init(aURI);
+  rv = rtspChannel->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rtspChannel.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 RtspHandler::AllowPort(int32_t port, const char *scheme, bool *aResult)
--- a/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp
+++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp
@@ -73,16 +73,22 @@ RtspControllerChild::RtspControllerChild
   gNeckoChild->SendPRtspControllerConstructor(this);
 }
 
 RtspControllerChild::~RtspControllerChild()
 {
   LOG(("RtspControllerChild::~RtspControllerChild()"));
 }
 
+void
+RtspControllerChild::ReleaseChannel()
+{
+  static_cast<RtspChannelChild*>(mChannel.get())->ReleaseController();
+}
+
 bool
 RtspControllerChild::OKToSendIPC()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mIPCOpen == false) {
     return false;
   }
   return mIPCAllowed;
@@ -169,27 +175,29 @@ RtspControllerChild::RecvOnDisconnected(
                        const uint8_t& index,
                        const nsresult& reason)
 {
   DisallowIPC();
   LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason));
   if (mListener) {
     mListener->OnDisconnected(index, reason);
   }
+  ReleaseChannel();
   return true;
 }
 
 bool
 RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason)
 {
   DisallowIPC();
   LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason));
   if (mListener) {
     mListener->OnDisconnected(0, NS_ERROR_CONNECTION_REFUSED);
   }
+  ReleaseChannel();
   return true;
 }
 
 void
 RtspControllerChild::AddIPDLReference()
 {
   NS_ABORT_IF_FALSE(!mIPCOpen,
                     "Attempt to retain more than one IPDL reference");
--- a/netwerk/protocol/rtsp/controller/RtspControllerChild.h
+++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.h
@@ -8,16 +8,17 @@
 #define RtspControllerChild_h
 
 #include "mozilla/net/PRtspControllerChild.h"
 #include "nsIStreamingProtocolController.h"
 #include "nsIChannel.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
+#include "mozilla/net/RtspChannelChild.h"
 
 namespace mozilla {
 namespace net {
 
 class RtspControllerChild : public nsIStreamingProtocolController
                           , public nsIStreamingProtocolListener
                           , public PRtspControllerChild
 {
@@ -65,13 +66,15 @@ class RtspControllerChild : public nsISt
   // Array refer to metadata of the media stream.
   nsTArray<nsCOMPtr<nsIStreamingProtocolMetaData>> mMetaArray;
   // ASCII encoded URL spec
   nsCString mSpec;
   // The total tracks for the given media stream session.
   uint32_t mTotalTracks;
   // Current suspension depth for this channel object
   uint32_t mSuspendCount;
+  // Detach channel-controller relationship.
+  void ReleaseChannel();
 };
 } // namespace net
 } // namespace mozilla
 
 #endif // RtspControllerChild_h
--- a/netwerk/protocol/rtsp/moz.build
+++ b/netwerk/protocol/rtsp/moz.build
@@ -5,26 +5,28 @@
 
 EXPORTS.mozilla.net += [
     'controller/RtspController.h',
     'controller/RtspControllerChild.h',
     'controller/RtspControllerParent.h',
     'controller/RtspMetaData.h',
     'rtsp/RTSPSource.h',
     'RtspChannelChild.h',
+    'RtspChannelParent.h',
     'RtspHandler.h',
 ]
 
 # These files cannot be built in unified mode because they force NSPR logging.
 SOURCES += [
     'controller/RtspController.cpp',
     'controller/RtspControllerChild.cpp',
     'controller/RtspControllerParent.cpp',
     'controller/RtspMetaData.cpp',
     'RtspChannelChild.cpp',
+    'RtspChannelParent.cpp',
     'RtspHandler.cpp',
 ]
 
 # Android sources
 SOURCES += [
     'rtsp/AAMRAssembler.cpp',
     'rtsp/AAVCAssembler.cpp',
     'rtsp/AH263Assembler.cpp',
--- a/toolkit/components/places/PlacesTransactions.jsm
+++ b/toolkit/components/places/PlacesTransactions.jsm
@@ -346,26 +346,30 @@ let PlacesTransactions = {
    * @note All PlacesTransactions operations are serialized. This means that the
    * transactions history state may change by the time the transaction/generator
    * is processed.  It's guaranteed, however, that a generator function "blocks"
    * the queue: that is, it is assured that no other operations are performed
    * by or on PlacesTransactions until the generator returns.  Keep in mind you
    * are not protected from consumers who use the raw places APIs directly.
    */
   transact: function (aToTransact) {
-    let generatorMode = typeof(aToTransact) == "function";
-    if (generatorMode) {
-      if (!aToTransact.isGenerator())
+    let isGeneratorObj =
+      o => Object.prototype.toString.call(o) ==  "[object Generator]";
+
+    let generator = null;
+    if (typeof(aToTransact) == "function") {
+      generator = aToTransact();
+      if (!isGeneratorObj(generator))
         throw new Error("aToTransact is not a generator function");
     }
-    else {
-      if (!TransactionsHistory.isProxifiedTransactionObject(aToTransact))
-        throw new Error("aToTransact is not a valid transaction object");
-      if (executedTransactions.has(aToTransact))
-        throw new Error("Transactions objects may not be recycled.");
+    else if (!TransactionsHistory.isProxifiedTransactionObject(aToTransact)) {
+      throw new Error("aToTransact is not a valid transaction object");
+    }
+    else if (executedTransactions.has(aToTransact)) {
+      throw new Error("Transactions objects may not be recycled.");
     }
 
     return Serialize(function* () {
       // The entry in the transactions history is created once the first
       // transaction is committed. This means that if |transact| is called
       // in its "generator mode" and no transactions are committed by the
       // generator, the transactions history is left unchanged.
       // Bug 982115: Depending on how this API is actually used we may revise
@@ -382,17 +386,17 @@ let PlacesTransactions = {
 
       function* transactBatch(aGenerator) {
         let error = false;
         let sendValue = undefined;
         while (true) {
           let next = error ?
                      aGenerator.throw(sendValue) : aGenerator.next(sendValue);
           sendValue = next.value;
-          if (Object.prototype.toString.call(sendValue) == "[object Generator]") {
+          if (isGeneratorObj(sendValue)) {
             sendValue = yield transactBatch(sendValue);
           }
           else if (typeof(sendValue) == "object" && sendValue) {
             if (TransactionsHistory.isProxifiedTransactionObject(sendValue)) {
               if (executedTransactions.has(sendValue)) {
                 sendValue = new Error("Transactions may not be recycled.");
                 error = true;
               }
@@ -405,18 +409,18 @@ let PlacesTransactions = {
             }
           }
           if (next.done)
             break;
         }
         return sendValue;
       }
 
-      if (generatorMode)
-        return yield transactBatch(aToTransact());
+      if (generator)
+        return yield transactBatch(generator);
       else
         return yield transactOneTransaction(aToTransact);
     }.bind(this));
   },
 
   /**
    * Asynchronously undo the transaction immediately after the current undo
    * position in the transactions history in the reverse order, if any, and
@@ -882,19 +886,20 @@ PT.NewLivemark.prototype = Object.seal({
     };
     return guid;
   }
 });
 
 /**
  * Transaction for moving an item.
  *
- * Required Input Properties: GUID, newParentGUID, newIndex.
+ * Required Input Properties: GUID, newParentGUID.
+ * Optional Input Properties  newIndex.
  */
-PT.MoveItem = DefineTransaction(["GUID", "newParentGUID", "newIndex"]);
+PT.MoveItem = DefineTransaction(["GUID", "newParentGUID"], ["newIndex"]);
 PT.MoveItem.prototype = Object.seal({
   execute: function* (aGUID, aNewParentGUID, aNewIndex) {
     let itemId = yield PlacesUtils.promiseItemId(aGUID),
         oldParentId = PlacesUtils.bookmarks.getFolderIdForItem(itemId),
         oldIndex = PlacesUtils.bookmarks.getItemIndex(itemId),
         newParentId = yield PlacesUtils.promiseItemId(aNewParentGUID);
 
     PlacesUtils.bookmarks.moveItem(itemId, newParentId, aNewIndex);
--- a/toolkit/components/places/tests/unit/test_async_transactions.js
+++ b/toolkit/components/places/tests/unit/test_async_transactions.js
@@ -449,18 +449,17 @@ add_task(function* test_move_items_to_fo
     let bkm_b_txn = PT.NewBookmark(bkm_b_info);
     bkm_b_info.GUID = yield bkm_b_txn;
     return [folder_a_txn, bkm_a_txn, bkm_b_txn];
   });
 
   ensureUndoState([[bkm_b_txn, bkm_a_txn, folder_a_txn]], 0);
 
   let moveTxn = PT.MoveItem({ GUID:          bkm_a_info.GUID
-                            , newParentGUID: folder_a_info.GUID
-                            , newIndex:      bmsvc.DEFAULT_INDEX });
+                            , newParentGUID: folder_a_info.GUID });
   yield PT.transact(moveTxn);
 
   let ensureDo = () => {
     ensureUndoState([[moveTxn], [bkm_b_txn, bkm_a_txn, folder_a_txn]], 0);
     ensureItemsMoved({ GUID:          bkm_a_info.GUID
                      , oldParentGUID: folder_a_info.GUID
                      , newParentGUID: folder_a_info.GUID
                      , oldIndex:      0
--- a/toolkit/themes/windows/mozapps/jar.mn
+++ b/toolkit/themes/windows/mozapps/jar.mn
@@ -8,17 +8,17 @@ toolkit.jar:
 # NOTE: If you add a new file here, you'll need to add it to the aero
 # section at the bottom of this file
         skin/classic/mozapps/downloads/downloadButtons.png         (downloads/downloadButtons.png)
         skin/classic/mozapps/downloads/downloadIcon.png            (downloads/downloadIcon.png)
         skin/classic/mozapps/downloads/downloads.css               (downloads/downloads.css)
         skin/classic/mozapps/downloads/unknownContentType.css      (downloads/unknownContentType.css)
         skin/classic/mozapps/extensions/about.css                  (extensions/about.css)
         skin/classic/mozapps/extensions/blocklist.css              (extensions/blocklist.css)
-        skin/classic/mozapps/extensions/extensions.css             (extensions/extensions.css)
+*       skin/classic/mozapps/extensions/extensions.css             (extensions/extensions.css)
 *       skin/classic/mozapps/extensions/selectAddons.css           (extensions/selectAddons.css)
         skin/classic/mozapps/extensions/update.css                 (extensions/update.css)
         skin/classic/mozapps/extensions/extensions.svg             (extensions/extensions.svg)
         skin/classic/mozapps/extensions/category-search.png        (extensions/category-search.png)
         skin/classic/mozapps/extensions/category-discover.png      (extensions/category-discover.png)
         skin/classic/mozapps/extensions/category-languages.png     (extensions/localeGeneric.png)
         skin/classic/mozapps/extensions/category-searchengines.png (extensions/category-searchengines.png)
         skin/classic/mozapps/extensions/category-extensions.png    (extensions/extensionGeneric.png)