Merge b-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Fri, 11 Sep 2015 20:27:20 -0700
changeset 294574 a4c276cfaf9a8d449f764dac210fd169ab4cf726
parent 294536 19f806034f67e8fc84b352db10f1a21ab982670f (current diff)
parent 294573 f885500efb5b4ac19c8fd78e7dde3f6a15579740 (diff)
child 294575 9771bd5e56edd07e21cf008dcadc20d7ed970ce3
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.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 b-i to m-c, a=merge
dom/base/nsDocument.cpp
testing/docker/centos6-build/system-setup.sh
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/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="e935894ef5f27e2f04b9e929a45a958e6288a223">
+  <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/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="e935894ef5f27e2f04b9e929a45a958e6288a223">
+  <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <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="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="067c08fb3e5744b42b68d1f861245f7d507109bc"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -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="e935894ef5f27e2f04b9e929a45a958e6288a223">
+  <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
@@ -124,17 +124,17 @@
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="f313503b5c91aaa6fcf962d4ec9bf260e0c00bf1"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="8586f55fe4b015911b48e731b69c592ad82a0807"/>
   <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="8d4018ebd33ac3f1a043b2d54bc578028656a659"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="96f78964a9a317a6c8b494ab71e10e0276d02490"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="b2d449276b015d8fe6cd9ea60c389c7e6975f841"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
   <project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="3453472769d6e9b43c84f98b56f8c63afe2b129e"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="7132bc11fbc68acfebcd509095562ca04fad5584"/>
   <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="5f4b68c799927b6e078f987b12722c3a6ccd4a45"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <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="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="067c08fb3e5744b42b68d1f861245f7d507109bc"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -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="e935894ef5f27e2f04b9e929a45a958e6288a223">
+  <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "758c75ee087ea3722213ea2c185cca1d952c8a29", 
+        "git_revision": "e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "df25432ca94953b1b9072fe01b705ebbf34478d1", 
+    "revision": "c0f536773eca24b5eaf30ceffe3bb8d41c51827f", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="758c75ee087ea3722213ea2c185cca1d952c8a29"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e938ac2795efeeb2ecec8c47b33c9f7f8183e4eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c6cace53426b5be7e56c0fd202118009689bc707"/>
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -153,16 +153,17 @@ StaticRefPtr<AudioChannelService> gAudio
 static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = {
   { "normal",             (int16_t)AudioChannel::Normal },
   { "content",            (int16_t)AudioChannel::Content },
   { "notification",       (int16_t)AudioChannel::Notification },
   { "alarm",              (int16_t)AudioChannel::Alarm },
   { "telephony",          (int16_t)AudioChannel::Telephony },
   { "ringer",             (int16_t)AudioChannel::Ringer },
   { "publicnotification", (int16_t)AudioChannel::Publicnotification },
+  { "system",             (int16_t)AudioChannel::System },
   { nullptr }
 };
 
 /* static */ void
 AudioChannelService::CreateServiceIfNeeded()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -7887,19 +7887,19 @@ nsDocument::GetViewportInfo(const Screen
   // widget scale and the full zoom.
   nsPresContext* context = mPresShell->GetPresContext();
   // When querying the full zoom, get it from the device context rather than
   // directly from the pres context, because the device context's value can
   // include an adjustment necessay to keep the number of app units per device
   // pixel an integer, and we want the adjusted value.
   float fullZoom = context ? context->DeviceContext()->GetFullZoom() : 1.0;
   fullZoom = (fullZoom == 0.0) ? 1.0 : fullZoom;
-  nsIWidget *widget = nsContentUtils::WidgetForDocument(this);
-  float widgetScale = widget ? widget->GetDefaultScale().scale : 1.0f;
-  CSSToLayoutDeviceScale layoutDeviceScale(widgetScale * fullZoom);
+  CSSToLayoutDeviceScale layoutDeviceScale(
+    (float)nsPresContext::AppUnitsPerCSSPixel() /
+    context->AppUnitsPerDevPixel());
 
   CSSToScreenScale defaultScale = layoutDeviceScale
                                 * LayoutDeviceToScreenScale(1.0);
 
   // Special behaviour for desktop mode, provided we are not on an about: page
   nsPIDOMWindow* win = GetWindow();
   if (win && win->IsDesktopModeViewport() && !IsAboutPage())
   {
--- a/dom/bluetooth/bluedroid/BluetoothMapSmsManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothMapSmsManager.cpp
@@ -328,35 +328,35 @@ BluetoothMapSmsManager::MasDataHandler(U
         BT_LOGR("Type: %s", NS_ConvertUTF16toUTF8(type).get());
         ReplyToPut();
 
         if (type.EqualsLiteral("x-bt/MAP-NotificationRegistration")) {
           HandleNotificationRegistration(pktHeaders);
         } else if (type.EqualsLiteral("x-bt/MAP-event-report")) {
           HandleEventReport(pktHeaders);
         } else if (type.EqualsLiteral("x-bt/messageStatus")) {
-          HandleMessageStatus(pktHeaders);
+          HandleSetMessageStatus(pktHeaders);
         }
       }
       break;
     case ObexRequestCode::Get:
     case ObexRequestCode::GetFinal: {
         // [opcode:1][length:2][Headers:var]
         if (receivedLength < 3 ||
           !ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
           ReplyError(ObexResponseCode::BadRequest);
           return;
         }
         pktHeaders.GetContentType(type);
         if (type.EqualsLiteral("x-obex/folder-listing")) {
           HandleSmsMmsFolderListing(pktHeaders);
         } else if (type.EqualsLiteral("x-bt/MAP-msg-listing")) {
           HandleSmsMmsMsgListing(pktHeaders);
-        } else if (type.EqualsLiteral("x-bt/message"))  {
-          // TODO: Implement this feature in Bug 1166679
+        } else if (type.EqualsLiteral("x-bt/message")) {
+          HandleSmsMmsGetMessage(pktHeaders);
         } else {
           BT_LOGR("Unknown MAP request type: %s",
             NS_ConvertUTF16toUTF8(type).get());
         }
       }
       break;
     default:
       ReplyError(ObexResponseCode::NotImplemented);
@@ -780,16 +780,50 @@ BluetoothMapSmsManager::AppendBtNamedVal
     case Map::AppParametersTagId::FilterPriority: {
       uint8_t filterPriority = *((uint8_t *)buf);
       // convert big endian to little endian
       filterPriority = (filterPriority >> 8) | (filterPriority << 8);
       BT_LOGR("msg filter priority: %d", filterPriority);
       AppendNamedValue(aValues, "filterPriority", filterPriority);
       break;
     }
+    case Map::AppParametersTagId::Attachment: {
+      uint8_t attachment = *((uint8_t *)buf);
+      // convert big endian to little endian
+      attachment = (attachment >> 8) | (attachment << 8);
+      BT_LOGR("msg filter attachment: %d", attachment);
+      AppendNamedValue(aValues, "attachment", attachment);
+      break;
+    }
+    case Map::AppParametersTagId::Charset: {
+      uint8_t charset = *((uint8_t *)buf);
+      // convert big endian to little endian
+      charset = (charset >> 8) | (charset << 8);
+      BT_LOGR("msg filter charset: %d", charset);
+      AppendNamedValue(aValues, "charset", charset);
+      break;
+    }
+    case Map::AppParametersTagId::StatusIndicator: {
+      uint8_t statusIndicator = *((uint8_t *)buf);
+      // convert big endian to little endian
+      statusIndicator = (statusIndicator >> 8) | (statusIndicator << 8);
+      BT_LOGR("msg filter statusIndicator: %d", statusIndicator);
+      AppendNamedValue(aValues, "statusIndicator",
+                       static_cast<uint32_t>(statusIndicator));
+      break;
+    }
+    case Map::AppParametersTagId::StatusValue: {
+      uint8_t statusValue = *((uint8_t *)buf);
+      // convert big endian to little endian
+      statusValue = (statusValue >> 8) | (statusValue << 8);
+      BT_LOGR("msg filter statusvalue: %d", statusValue);
+      AppendNamedValue(aValues, "statusValue",
+                       static_cast<uint32_t>(statusValue));
+      break;
+    }
     default:
       BT_LOGR("Unsupported AppParameterTag: %x", aTagId);
       break;
   }
 }
 
 void
 BluetoothMapSmsManager::HandleSmsMmsMsgListing(const ObexHeaderSet& aHeader)
@@ -819,16 +853,39 @@ BluetoothMapSmsManager::HandleSmsMmsMsgL
   }
 
   bs->DistributeSignal(NS_LITERAL_STRING(MAP_MESSAGES_LISTING_REQ_ID),
                        NS_LITERAL_STRING(KEY_ADAPTER),
                        data);
 }
 
 void
+BluetoothMapSmsManager::HandleSmsMmsGetMessage(const ObexHeaderSet& aHeader)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothService* bs = BluetoothService::Get();
+  NS_ENSURE_TRUE_VOID(bs);
+
+  InfallibleTArray<BluetoothNamedValue> data;
+  nsString name;
+  aHeader.GetName(name);
+  AppendNamedValue(data, "handle", name);
+
+  AppendBtNamedValueByTagId(aHeader, data,
+                            Map::AppParametersTagId::Attachment);
+  AppendBtNamedValueByTagId(aHeader, data,
+                            Map::AppParametersTagId::Charset);
+
+  bs->DistributeSignal(NS_LITERAL_STRING(MAP_GET_MESSAGE_REQ_ID),
+                       NS_LITERAL_STRING(KEY_ADAPTER),
+                       data);
+}
+
+void
 BluetoothMapSmsManager::BuildDefaultFolderStructure()
 {
   /* MAP specification defines virtual folders structure
    * /
    * /telecom
    * /telecom/msg
    * /telecom/msg/inbox
    * /telecom/msg/draft
@@ -893,19 +950,39 @@ BluetoothMapSmsManager::HandleNotificati
 
 void
 BluetoothMapSmsManager::HandleEventReport(const ObexHeaderSet& aHeader)
 {
   // TODO: Handle event report in Bug 1166666
 }
 
 void
-BluetoothMapSmsManager::HandleMessageStatus(const ObexHeaderSet& aHeader)
+BluetoothMapSmsManager::HandleSetMessageStatus(const ObexHeaderSet& aHeader)
 {
-  // TODO: Handle MessageStatus update in Bug 1186836
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothService* bs = BluetoothService::Get();
+  NS_ENSURE_TRUE_VOID(bs);
+
+  InfallibleTArray<BluetoothNamedValue> data;
+  nsString name;
+  aHeader.GetName(name);
+  /* The Name header shall contain the handle of the message the status of which
+   * shall be modified. The handle shall be represented by a null-terminated
+   * Unicode text string with 16 hexadecimal digits.
+   */
+  AppendNamedValue(data, "handle", name);
+
+  AppendBtNamedValueByTagId(aHeader, data,
+                            Map::AppParametersTagId::StatusIndicator);
+  AppendBtNamedValueByTagId(aHeader, data,
+                            Map::AppParametersTagId::StatusValue);
+
+  bs->DistributeSignal(NS_LITERAL_STRING(MAP_SET_MESSAGE_STATUS_REQ_ID),
+                       NS_LITERAL_STRING(KEY_ADAPTER), data);
 }
 
 void
 BluetoothMapSmsManager::ReplyError(uint8_t aError)
 {
   BT_LOGR("[0x%x]", aError);
 
   // Section 3.2 "Response Format", IrOBEX 1.2
--- a/dom/bluetooth/bluedroid/BluetoothMapSmsManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothMapSmsManager.h
@@ -89,19 +89,20 @@ private:
   void ReplyToConnect();
   void ReplyToDisconnectOrAbort();
   void ReplyToSetPath();
   void ReplyToPut();
   void ReplyError(uint8_t aError);
 
   void HandleNotificationRegistration(const ObexHeaderSet& aHeader);
   void HandleEventReport(const ObexHeaderSet& aHeader);
-  void HandleMessageStatus(const ObexHeaderSet& aHeader);
+  void HandleSetMessageStatus(const ObexHeaderSet& aHeader);
   void HandleSmsMmsFolderListing(const ObexHeaderSet& aHeader);
   void HandleSmsMmsMsgListing(const ObexHeaderSet& aHeader);
+  void HandleSmsMmsGetMessage(const ObexHeaderSet& aHeader);
   void AppendBtNamedValueByTagId(const ObexHeaderSet& aHeader,
     InfallibleTArray<BluetoothNamedValue>& aValues,
     const Map::AppParametersTagId aTagId);
   void SendMasObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
   void SendMnsObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
 
   uint8_t SetPath(uint8_t flags, const ObexHeaderSet& aHeader);
   bool CompareHeaderTarget(const ObexHeaderSet& aHeader);
--- a/dom/bluetooth/common/BluetoothCommon.h
+++ b/dom/bluetooth/common/BluetoothCommon.h
@@ -187,16 +187,28 @@ extern bool gBluetoothDebugFlag;
 
 /**
  * When receiving a MAP request of 'messages listing' from a remote device,
  * we'll dispatch an event.
  */
 #define MAP_MESSAGES_LISTING_REQ_ID          "mapmessageslistingreq"
 
 /**
+ * When receiving a MAP request of 'get message' from a remote device,
+ * we'll dispatch an event.
+ */
+#define MAP_GET_MESSAGE_REQ_ID               "mapgetmessagereq"
+
+/**
+ * When receiving a MAP request of 'set message' from a remote device,
+ * we'll dispatch an event.
+ */
+#define MAP_SET_MESSAGE_STATUS_REQ_ID        "mapsetmessagestatusreq"
+
+/**
  * When the value of a characteristic of a remote BLE device changes, we'll
  * dispatch an event
  */
 #define GATT_CHARACTERISTIC_CHANGED_ID       "characteristicchanged"
 
 /**
  * When a remote BLE device gets connected / disconnected, we'll dispatch an
  * event.
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -145,17 +145,17 @@ class VersionChangeTransaction;
  ******************************************************************************/
 
 // If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
 // schema version.
 static_assert(JS_STRUCTURED_CLONE_VERSION == 5,
               "Need to update the major schema version.");
 
 // Major schema version. Bump for almost everything.
-const uint32_t kMajorSchemaVersion = 20;
+const uint32_t kMajorSchemaVersion = 21;
 
 // Minor schema version. Should almost always be 0 (maybe bump on release
 // branches if we have to).
 const uint32_t kMinorSchemaVersion = 0;
 
 // The schema version we store in the SQLite database is a (signed) 32-bit
 // integer. The major version is left-shifted 4 bits so the max value is
 // 0xFFFFFFF. The minor version occupies the lower 4 bits and its max is 0xF.
@@ -3621,18 +3621,19 @@ UpgradeSchemaFrom17_0To18_0(mozIStorageC
 
 nsresult
 UpgradeSchemaFrom18_0To19_0(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aConnection);
 
   nsresult rv;
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom17_0To18_0",
-    js::ProfileEntry::Category::STORAGE);
+  PROFILER_LABEL("IndexedDB",
+                 "UpgradeSchemaFrom18_0To19_0",
+                 js::ProfileEntry::Category::STORAGE);
 
   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "ALTER TABLE object_store_index "
     "ADD COLUMN locale TEXT;"
   ));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -3729,17 +3730,17 @@ private:
 nsresult
 UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
                             mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aConnection);
 
   PROFILER_LABEL("IndexedDB",
-                 "UpgradeSchemaFrom18_0To19_0",
+                 "UpgradeSchemaFrom19_0To20_0",
                  js::ProfileEntry::Category::STORAGE);
 
 #if defined(MOZ_B2G)
 
   // We don't have to do the upgrade of file ids on B2G. The old format was
   // only used by the previous single process implementation and B2G was
   // always multi process. This is a nice optimization since the upgrade needs
   // to deserialize all structured clones which reference a stored file or
@@ -3849,16 +3850,227 @@ UpgradeSchemaFrom19_0To20_0(nsIFile* aFM
     return rv;
   }
 
 #endif // MOZ_B2G
 
   return NS_OK;
 }
 
+class UpgradeIndexDataValuesFunction final
+  : public mozIStorageFunction
+{
+public:
+  UpgradeIndexDataValuesFunction()
+  {
+    AssertIsOnIOThread();
+  }
+
+  NS_DECL_ISUPPORTS
+
+private:
+  ~UpgradeIndexDataValuesFunction()
+  {
+    AssertIsOnIOThread();
+  }
+
+  nsresult
+  ReadOldCompressedIDVFromBlob(const uint8_t* aBlobData,
+                               uint32_t aBlobDataLength,
+                               FallibleTArray<IndexDataValue>& aIndexValues);
+
+  NS_IMETHOD
+  OnFunctionCall(mozIStorageValueArray* aArguments,
+                 nsIVariant** aResult) override;
+};
+
+NS_IMPL_ISUPPORTS(UpgradeIndexDataValuesFunction, mozIStorageFunction)
+
+nsresult
+UpgradeIndexDataValuesFunction::ReadOldCompressedIDVFromBlob(
+                                   const uint8_t* aBlobData,
+                                   uint32_t aBlobDataLength,
+                                   FallibleTArray<IndexDataValue>& aIndexValues)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(!IsOnBackgroundThread());
+  MOZ_ASSERT(aBlobData);
+  MOZ_ASSERT(aBlobDataLength);
+  MOZ_ASSERT(aIndexValues.IsEmpty());
+
+  const uint8_t* blobDataIter = aBlobData;
+  const uint8_t* blobDataEnd = aBlobData + aBlobDataLength;
+
+  int64_t indexId;
+  bool unique;
+  bool nextIndexIdAlreadyRead = false;
+
+  while (blobDataIter < blobDataEnd) {
+    if (!nextIndexIdAlreadyRead) {
+      ReadCompressedIndexId(&blobDataIter, blobDataEnd, &indexId, &unique);
+    }
+    nextIndexIdAlreadyRead = false;
+
+    if (NS_WARN_IF(blobDataIter == blobDataEnd)) {
+      IDB_REPORT_INTERNAL_ERR();
+      return NS_ERROR_FILE_CORRUPTED;
+    }
+
+    // Read key buffer length.
+    const uint64_t keyBufferLength =
+      ReadCompressedNumber(&blobDataIter, blobDataEnd);
+
+    if (NS_WARN_IF(blobDataIter == blobDataEnd) ||
+        NS_WARN_IF(keyBufferLength > uint64_t(UINT32_MAX)) ||
+        NS_WARN_IF(blobDataIter + keyBufferLength > blobDataEnd)) {
+      IDB_REPORT_INTERNAL_ERR();
+      return NS_ERROR_FILE_CORRUPTED;
+    }
+
+    nsCString keyBuffer(reinterpret_cast<const char*>(blobDataIter),
+                        uint32_t(keyBufferLength));
+    blobDataIter += keyBufferLength;
+
+    IndexDataValue idv(indexId, unique, Key(keyBuffer));
+
+    if (blobDataIter < blobDataEnd) {
+      // Read either a sort key buffer length or an index id.
+      uint64_t maybeIndexId = ReadCompressedNumber(&blobDataIter, blobDataEnd);
+
+      // Locale-aware indexes haven't been around long enough to have any users,
+      // we can safely assume all sort key buffer lengths will be zero.
+      if (maybeIndexId != 0) {
+        if (maybeIndexId % 2) {
+          unique = true;
+          maybeIndexId--;
+        } else {
+          unique = false;
+        }
+        indexId = maybeIndexId/2;
+        nextIndexIdAlreadyRead = true;
+      }
+    }
+
+    if (NS_WARN_IF(!aIndexValues.InsertElementSorted(idv, fallible))) {
+      IDB_REPORT_INTERNAL_ERR();
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+  }
+
+  MOZ_ASSERT(blobDataIter == blobDataEnd);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UpgradeIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
+                                               nsIVariant** aResult)
+{
+  MOZ_ASSERT(aArguments);
+  MOZ_ASSERT(aResult);
+
+  PROFILER_LABEL("IndexedDB",
+                 "UpgradeIndexDataValuesFunction::OnFunctionCall",
+                 js::ProfileEntry::Category::STORAGE);
+
+  uint32_t argc;
+  nsresult rv = aArguments->GetNumEntries(&argc);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (argc != 1) {
+    NS_WARNING("Don't call me with the wrong number of arguments!");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  int32_t type;
+  rv = aArguments->GetTypeOfIndex(0, &type);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (type != mozIStorageStatement::VALUE_TYPE_BLOB) {
+    NS_WARNING("Don't call me with the wrong type of arguments!");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  const uint8_t* oldBlob;
+  uint32_t oldBlobLength;
+  rv = aArguments->GetSharedBlob(0, &oldBlobLength, &oldBlob);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  AutoFallibleTArray<IndexDataValue, 32> oldIdv;
+  rv = ReadOldCompressedIDVFromBlob(oldBlob, oldBlobLength, oldIdv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  UniqueFreePtr<uint8_t> newIdv;
+  uint32_t newIdvLength;
+  rv = MakeCompressedIndexDataValues(oldIdv, newIdv, &newIdvLength);
+
+  std::pair<uint8_t*, int> data(newIdv.get(), newIdvLength);
+  
+  nsCOMPtr<nsIVariant> result = new storage::AdoptedBlobVariant(data);
+
+  newIdv.release();
+
+  result.forget(aResult);
+  return NS_OK;
+}
+
+nsresult
+UpgradeSchemaFrom20_0To21_0(mozIStorageConnection* aConnection)
+{
+  // This should have been part of the 18 to 19 upgrade, where we changed the
+  // layout of the index_data_values blobs but didn't upgrade the existing data.
+  // See bug 1202788.
+
+  AssertIsOnIOThread();
+  MOZ_ASSERT(aConnection);
+
+  PROFILER_LABEL("IndexedDB",
+                 "UpgradeSchemaFrom20_0To21_0",
+                 js::ProfileEntry::Category::STORAGE);
+
+  nsRefPtr<UpgradeIndexDataValuesFunction> function =
+    new UpgradeIndexDataValuesFunction();
+
+  NS_NAMED_LITERAL_CSTRING(functionName, "upgrade_idv");
+
+  nsresult rv = aConnection->CreateFunction(functionName, 1, function);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+    "UPDATE object_data "
+      "SET index_data_values = upgrade_idv(index_data_values) "
+      "WHERE index_data_values IS NOT NULL;"
+  ));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = aConnection->RemoveFunction(functionName);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = aConnection->SetSchemaVersion(MakeSchemaVersion(21, 0));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
 nsresult
 GetDatabaseFileURL(nsIFile* aDatabaseFile,
                    PersistenceType aPersistenceType,
                    const nsACString& aGroup,
                    const nsACString& aOrigin,
                    uint32_t aTelemetryId,
                    nsIFileURL** aResult)
 {
@@ -4341,17 +4553,17 @@ CreateStorageConnection(nsIFile* aDBFile
       }
 
       rv = stmt->Execute();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     } else  {
       // This logic needs to change next time we change the schema!
-      static_assert(kSQLiteSchemaVersion == int32_t((20 << 4) + 0),
+      static_assert(kSQLiteSchemaVersion == int32_t((21 << 4) + 0),
                     "Upgrade function needed due to schema version increase.");
 
       while (schemaVersion != kSQLiteSchemaVersion) {
         if (schemaVersion == 4) {
           rv = UpgradeSchemaFrom4To5(connection);
         } else if (schemaVersion == 5) {
           rv = UpgradeSchemaFrom5To6(connection);
         } else if (schemaVersion == 6) {
@@ -4379,16 +4591,18 @@ CreateStorageConnection(nsIFile* aDBFile
           rv = UpgradeSchemaFrom16_0To17_0(connection);
         } else if (schemaVersion == MakeSchemaVersion(17, 0)) {
           rv = UpgradeSchemaFrom17_0To18_0(connection, aOrigin);
           vacuumNeeded = true;
         } else if (schemaVersion == MakeSchemaVersion(18, 0)) {
           rv = UpgradeSchemaFrom18_0To19_0(connection);
         } else if (schemaVersion == MakeSchemaVersion(19, 0)) {
           rv = UpgradeSchemaFrom19_0To20_0(aFMDirectory, connection);
+        } else if (schemaVersion == MakeSchemaVersion(20, 0)) {
+          rv = UpgradeSchemaFrom20_0To21_0(connection);
         } else {
           IDB_WARNING("Unable to open IndexedDB database, no upgrade path is "
                       "available!");
           return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
         }
 
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
--- a/dom/mobileconnection/tests/marionette/test_mobile_data_ipv6.js
+++ b/dom/mobileconnection/tests/marionette/test_mobile_data_ipv6.js
@@ -38,22 +38,22 @@ function doTest(aApnSettings, aHaveV4Add
       let num = networkInfo.getAddresses(ips, prefixLengths);
       log("  Num addresses: " + num);
       log("  Addresses: " + JSON.stringify(ips.value));
       log("  PrefixLengths: " + JSON.stringify(prefixLengths.value));
 
       if (aHaveV4Address) {
         ok(ips.value.reduce(function(aFound, aAddress) {
           return aFound || aAddress.indexOf(":") < 0;
-        }), "IPv4 address");
+        }, false), "IPv4 address");
       }
       if (aHaveV6Address) {
         ok(ips.value.reduce(function(aFound, aAddress) {
           return aFound || aAddress.indexOf(":") > 0;
-        }), "IPv6 address");
+        }, false), "IPv6 address");
       }
     })
     .then(() => setDataEnabledAndWait(false));
 }
 
 function doTestHome(aApnSettings, aProtocol) {
   log("Testing \"" + aProtocol + "\"@HOME... ");
 
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -339,28 +339,31 @@ PresentationSessionInfo::NotifyData(cons
 
   return mListener->NotifyMessage(mSessionId, aData);
 }
 
 /*
  * Implementation of PresentationRequesterInfo
  *
  * During presentation session establishment, the sender expects the following
- * after trying to establish the control channel: (The order between step 2 and
- * 3 is not guaranteed.)
+ * after trying to establish the control channel: (The order between step 3 and
+ * 4 is not guaranteed.)
  * 1. |Init| is called to open a socket |mServerSocket| for data transport
- *    channel and send the offer to the receiver via the control channel.
- * 2.1 |OnSocketAccepted| of |nsIServerSocketListener| is called to indicate the
+ *    channel.
+ * 2. |NotifyOpened| of |nsIPresentationControlChannelListener| is called to
+ *    indicate the control channel is ready to use. Then send the offer to the
+ *    receiver via the control channel.
+ * 3.1 |OnSocketAccepted| of |nsIServerSocketListener| is called to indicate the
  *     data transport channel is connected. Then initialize |mTransport|.
- * 2.2 |NotifyTransportReady| of |nsIPresentationSessionTransportCallback| is
+ * 3.2 |NotifyTransportReady| of |nsIPresentationSessionTransportCallback| is
  *     called.
- * 3. |OnAnswer| of |nsIPresentationControlChannelListener| is called to
+ * 4. |OnAnswer| of |nsIPresentationControlChannelListener| is called to
  *    indicate the receiver is ready. Close the control channel since it's no
  *    longer needed.
- * 4. Once both step 2 and 3 are done, the presentation session is ready to use.
+ * 5. Once both step 3 and 4 are done, the presentation session is ready to use.
  *    So notify the listener of CONNECTED state.
  */
 
 NS_IMPL_ISUPPORTS_INHERITED(PresentationRequesterInfo,
                             PresentationSessionInfo,
                             nsIServerSocketListener)
 
 nsresult
@@ -380,36 +383,16 @@ PresentationRequesterInfo::Init(nsIPrese
     return rv;
   }
 
   rv = mServerSocket->AsyncListen(this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  // Prepare and send the offer.
-  int32_t port;
-  rv = mServerSocket->GetPort(&port);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  nsCString address;
-  rv = GetAddress(address);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  nsRefPtr<PresentationChannelDescription> description =
-    new PresentationChannelDescription(address, static_cast<uint16_t>(port));
-  rv = mControlChannel->SendOffer(description);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   return NS_OK;
 }
 
 void
 PresentationRequesterInfo::Shutdown(nsresult aReason)
 {
   PresentationSessionInfo::Shutdown(aReason);
 
@@ -491,18 +474,32 @@ PresentationRequesterInfo::OnAnswer(nsIP
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationRequesterInfo::NotifyOpened()
 {
-  // Do nothing and wait for receiver to be ready.
-  return NS_OK;
+  // Prepare and send the offer.
+  int32_t port;
+  nsresult rv = mServerSocket->GetPort(&port);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCString address;
+  rv = GetAddress(address);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsRefPtr<PresentationChannelDescription> description =
+    new PresentationChannelDescription(address, static_cast<uint16_t>(port));
+  return mControlChannel->SendOffer(description);
 }
 
 NS_IMETHODIMP
 PresentationRequesterInfo::NotifyClosed(nsresult aReason)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Unset control channel here so it won't try to re-close it in potential
@@ -661,34 +658,29 @@ PresentationResponderInfo::InitTransport
   // Prepare and send the answer.
   // TODO bug 1148307 Implement PresentationSessionTransport with DataChannel.
   // In the current implementation of |PresentationSessionTransport|,
   // |GetSelfAddress| cannot return the real info when it's initialized via
   // |InitWithChannelDescription|. Yet this deficiency only affects the channel
   // description for the answer, which is not actually checked at requester side.
   nsCOMPtr<nsINetAddr> selfAddr;
   rv = mTransport->GetSelfAddress(getter_AddRefs(selfAddr));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
+  NS_WARN_IF(NS_FAILED(rv));
 
   nsCString address;
-  selfAddr->GetAddress(address);
-  uint16_t port;
-  selfAddr->GetPort(&port);
+  uint16_t port = 0;
+  if (NS_SUCCEEDED(rv)) {
+    selfAddr->GetAddress(address);
+    selfAddr->GetPort(&port);
+  }
   nsCOMPtr<nsIPresentationChannelDescription> description =
     new PresentationChannelDescription(address, port);
 
-  rv = mControlChannel->SendAnswer(description);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  return NS_OK;
- }
+  return mControlChannel->SendAnswer(description);
+}
 
 nsresult
 PresentationResponderInfo::UntrackFromService()
 {
   // Remove the OOP responding info (if it has never been used).
   if (mContentParent) {
     NS_WARN_IF(!static_cast<ContentParent*>(mContentParent.get())->SendNotifyPresentationReceiverCleanUp(mSessionId));
   }
--- a/dom/presentation/interfaces/nsIPresentationControlChannel.idl
+++ b/dom/presentation/interfaces/nsIPresentationControlChannel.idl
@@ -11,17 +11,17 @@ interface nsIInputStream;
 interface nsIPresentationChannelDescription: nsISupports
 {
   const unsigned short TYPE_TCP = 1;
   const unsigned short TYPE_DATACHANNEL = 2;
 
   // Type of transport channel.
   readonly attribute uint8_t type;
 
-  // Addresses for TCP channel.
+  // Addresses for TCP channel (as a list of nsISupportsCString).
   // Should only be used while type == TYPE_TCP.
   readonly attribute nsIArray tcpAddress;
 
   // Port number for TCP channel.
   // Should only be used while type == TYPE_TCP.
   readonly attribute uint16_t tcpPort;
 
   // SDP for Data Channel.
--- a/dom/presentation/provider/TCPPresentationServer.js
+++ b/dom/presentation/provider/TCPPresentationServer.js
@@ -259,18 +259,18 @@ TCPPresentationServer.prototype = {
 
 function ChannelDescription(aInit) {
   this._type = aInit.type;
   switch (this._type) {
     case Ci.nsIPresentationChannelDescription.TYPE_TCP:
       this._tcpAddresses = Cc["@mozilla.org/array;1"]
                            .createInstance(Ci.nsIMutableArray);
       for (let address of aInit.tcpAddress) {
-        let wrapper = Cc["@mozilla.org/supports-string;1"]
-                      .createInstance(Ci.nsISupportsString);
+        let wrapper = Cc["@mozilla.org/supports-cstring;1"]
+                      .createInstance(Ci.nsISupportsCString);
         wrapper.data = address;
         this._tcpAddresses.appendElement(wrapper, false);
       }
 
       this._tcpPort = aInit.tcpPort;
       break;
     case Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL:
       this._dataChannelSDP = aInit.dataChannelSDP;
@@ -308,17 +308,17 @@ ChannelDescription.prototype = {
 function discriptionAsJson(aDescription) {
   let json = {};
   json.type = aDescription.type;
   switch(aDescription.type) {
     case Ci.nsIPresentationChannelDescription.TYPE_TCP:
       let addresses = aDescription.tcpAddress.QueryInterface(Ci.nsIArray);
       json.tcpAddress = [];
       for (let idx = 0; idx < addresses.length; idx++) {
-        let address = addresses.queryElementAt(idx, Ci.nsISupportsString);
+        let address = addresses.queryElementAt(idx, Ci.nsISupportsCString);
         json.tcpAddress.push(address.data);
       }
       json.tcpPort = aDescription.tcpPort;
       break;
     case Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL:
       json.dataChannelSDP = aDescription.dataChannelSDP;
       break;
   }
@@ -536,21 +536,21 @@ TCPControlChannel.prototype = {
         this._presentationServer.onSessionRequest(aMsg.id,
                                                   aMsg.url,
                                                   aMsg.presentationId,
                                                   this);
         this._notifyOpened();
         break;
       }
       case "requestSession:Offer": {
-        this._listener.onOffer(new ChannelDescription(aMsg.offer));
+        this._onOffer(aMsg.offer);
         break;
       }
       case "requestSession:Answer": {
-        this._listener.onAnswer(new ChannelDescription(aMsg.answer));
+        this._onAnswer(aMsg.answer);
         break;
       }
     }
   },
 
   get listener() {
     return this._listener;
   },
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -95,19 +95,51 @@ const mockedControlChannel = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
   set listener(listener) {
     this._listener = listener;
   },
   get listener() {
     return this._listener;
   },
   sendOffer: function(offer) {
-    sendAsyncMessage('offer-sent');
+    var isValid = false;
+    try {
+      var addresses = offer.tcpAddress;
+      if (addresses.length > 0) {
+        for (var i = 0; i < addresses.length; i++) {
+          // Ensure CString addresses are used. Otherwise, an error will be thrown.
+          addresses.queryElementAt(i, Ci.nsISupportsCString);
+        }
+
+        isValid = true;
+      }
+    } catch (e) {
+      isValid = false;
+    }
+
+    sendAsyncMessage('offer-sent', isValid);
   },
   sendAnswer: function(answer) {
+    var isValid = false;
+    try {
+      var addresses = answer.tcpAddress;
+      if (addresses.length > 0) {
+        for (var i = 0; i < addresses.length; i++) {
+          // Ensure CString addresses are used. Otherwise, an error will be thrown.
+          addresses.queryElementAt(i, Ci.nsISupportsCString);
+        }
+
+        isValid = true;
+      }
+    } catch (e) {
+      isValid = false;
+    }
+
+    sendAsyncMessage('answer-sent', isValid);
+
     this._listener.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
   },
   close: function(reason) {
     sendAsyncMessage('control-channel-closed', reason);
     this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).notifyClosed(reason);
   },
   simulateReceiverReady: function() {
     this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).notifyReceiverReady();
@@ -115,16 +147,20 @@ const mockedControlChannel = {
   simulateOnOffer: function() {
     sendAsyncMessage('offer-received');
     this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).onOffer(mockedChannelDescription);
   },
   simulateOnAnswer: function() {
     sendAsyncMessage('answer-received');
     this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).onAnswer(mockedChannelDescription);
   },
+  simulateNotifyOpened: function() {
+    sendAsyncMessage('control-channel-opened');
+    this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).notifyOpened();
+  },
 };
 
 const mockedDevice = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
   id: 'id',
   name: 'name',
   type: 'type',
   establishControlChannel: function(url, presentationId) {
@@ -332,16 +368,20 @@ addMessageListener('trigger-incoming-off
 addMessageListener('trigger-incoming-answer', function() {
   mockedControlChannel.simulateOnAnswer();
 });
 
 addMessageListener('trigger-incoming-transport', function() {
   mockedServerSocket.simulateOnSocketAccepted(mockedServerSocket, mockedSocketTransport);
 });
 
+addMessageListener('trigger-control-channel-open', function(reason) {
+  mockedControlChannel.simulateNotifyOpened();
+});
+
 addMessageListener('trigger-control-channel-close', function(reason) {
   mockedControlChannel.close(reason);
 });
 
 addMessageListener('trigger-data-transport-close', function(reason) {
   mockedSessionTransport.close(reason);
 });
 
--- a/dom/presentation/tests/mochitest/test_presentation_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_receiver.html
@@ -57,16 +57,21 @@ function setup() {
     });
     obs.notifyObservers(promise, 'setup-request-promise', null);
 
     gScript.addMessageListener('offer-received', function offerReceivedHandler() {
       gScript.removeMessageListener('offer-received', offerReceivedHandler);
       info("An offer is received.");
     });
 
+    gScript.addMessageListener('answer-sent', function answerSentHandler(aIsValid) {
+      gScript.removeMessageListener('answer-sent', answerSentHandler);
+      ok(aIsValid, "A valid answer is sent.");
+    });
+
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
     });
 
     gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
       gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
       info("Data notification is enabled for data transport channel.");
--- a/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html
@@ -106,16 +106,21 @@ function setup() {
 
     document.body.appendChild(nonReceiverIframe);
 
     gScript.addMessageListener('offer-received', function offerReceivedHandler() {
       gScript.removeMessageListener('offer-received', offerReceivedHandler);
       info("An offer is received.");
     });
 
+    gScript.addMessageListener('answer-sent', function answerSentHandler(aIsValid) {
+      gScript.removeMessageListener('answer-sent', answerSentHandler);
+      ok(aIsValid, "A valid answer is sent.");
+    });
+
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
     });
 
     gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
       gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
       info("Data notification is enabled for data transport channel.");
--- a/dom/presentation/tests/mochitest/test_presentation_sender.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender.html
@@ -36,26 +36,32 @@ function testStartSession() {
       gScript.removeMessageListener('device-prompt', devicePromptHandler);
       info("Device prompt is triggered.");
       gScript.sendAsyncMessage('trigger-device-prompt-select');
     });
 
     gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
       info("A control channel is established.");
+      gScript.sendAsyncMessage('trigger-control-channel-open');
+    });
+
+    gScript.addMessageListener('control-channel-opened', function controlChannelOpenedHandler(aReason) {
+      gScript.removeMessageListener('control-channel-opened', controlChannelOpenedHandler);
+      info("The control channel is opened.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       info("The control channel is closed. " + aReason);
     });
 
-    gScript.addMessageListener('offer-sent', function offerSentHandler() {
+    gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
-      info("An offer is sent out.");
+      ok(aIsValid, "A valid offer is sent out.");
       gScript.sendAsyncMessage('trigger-incoming-transport');
     });
 
     gScript.addMessageListener('answer-received', function answerReceivedHandler() {
       gScript.removeMessageListener('answer-received', answerReceivedHandler);
       info("An answer is received.");
     });
 
--- a/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html
@@ -36,26 +36,32 @@ function testStartSession() {
       gScript.removeMessageListener('device-prompt', devicePromptHandler);
       info("Device prompt is triggered.");
       gScript.sendAsyncMessage('trigger-device-prompt-select');
     });
 
     gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
       info("A control channel is established.");
+      gScript.sendAsyncMessage('trigger-control-channel-open');
+    });
+
+    gScript.addMessageListener('control-channel-opened', function controlChannelOpenedHandler(aReason) {
+      gScript.removeMessageListener('control-channel-opened', controlChannelOpenedHandler);
+      info("The control channel is opened.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       info("The control channel is closed. " + aReason);
     });
 
-    gScript.addMessageListener('offer-sent', function offerSentHandler() {
+    gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
-      info("An offer is sent out.");
+      ok(aIsValid, "A valid offer is sent out.");
       gScript.sendAsyncMessage('trigger-incoming-answer');
     });
 
     gScript.addMessageListener('answer-received', function answerReceivedHandler() {
       gScript.removeMessageListener('answer-received', answerReceivedHandler);
       info("An answer is received.");
       gScript.sendAsyncMessage('trigger-incoming-transport');
     });
--- a/dom/presentation/tests/mochitest/test_presentation_sender_start_session_error.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender_start_session_error.html
@@ -71,26 +71,32 @@ function testStartSessionUnexpectedContr
       gScript.removeMessageListener('device-prompt', devicePromptHandler);
       info("Device prompt is triggered.");
       gScript.sendAsyncMessage('trigger-device-prompt-select');
     });
 
     gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
       info("A control channel is established.");
+      gScript.sendAsyncMessage('trigger-control-channel-open');
+    });
+
+    gScript.addMessageListener('control-channel-opened', function controlChannelOpenedHandler(aReason) {
+      gScript.removeMessageListener('control-channel-opened', controlChannelOpenedHandler);
+      info("The control channel is opened.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       info("The control channel is closed. " + aReason);
     });
 
-    gScript.addMessageListener('offer-sent', function offerSentHandler() {
+    gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
-      info("An offer is sent out.");
+      ok(aIsValid, "A valid offer is sent out.");
       gScript.sendAsyncMessage('trigger-control-channel-close', SpecialPowers.Cr.NS_ERROR_FAILURE);
     });
 
     presentation.startSession("http://example.com").then(
       function(aSession) {
         ok(false, "startSession shouldn't succeed in this case.");
         aReject();
       },
@@ -108,26 +114,32 @@ function testStartSessionUnexpectedContr
       gScript.removeMessageListener('device-prompt', devicePromptHandler);
       info("Device prompt is triggered.");
       gScript.sendAsyncMessage('trigger-device-prompt-select');
     });
 
     gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
       info("A control channel is established.");
+      gScript.sendAsyncMessage('trigger-control-channel-open');
+    });
+
+    gScript.addMessageListener('control-channel-opened', function controlChannelOpenedHandler(aReason) {
+      gScript.removeMessageListener('control-channel-opened', controlChannelOpenedHandler);
+      info("The control channel is opened.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       info("The control channel is closed. " + aReason);
     });
 
-    gScript.addMessageListener('offer-sent', function offerSentHandler() {
+    gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
-      info("An offer is sent out.");
+      ok(aIsValid, "A valid offer is sent out.");
       gScript.sendAsyncMessage('trigger-incoming-transport');
     });
 
     gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
       gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
       info("Data transport channel is initialized.");
       gScript.sendAsyncMessage('trigger-control-channel-close', SpecialPowers.Cr.NS_ERROR_ABORT);
     });
@@ -156,26 +168,32 @@ function testStartSessionUnexpectedDataT
       gScript.removeMessageListener('device-prompt', devicePromptHandler);
       info("Device prompt is triggered.");
       gScript.sendAsyncMessage('trigger-device-prompt-select');
     });
 
     gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
       info("A control channel is established.");
+      gScript.sendAsyncMessage('trigger-control-channel-open');
+    });
+
+    gScript.addMessageListener('control-channel-opened', function controlChannelOpenedHandler(aReason) {
+      gScript.removeMessageListener('control-channel-opened', controlChannelOpenedHandler);
+      info("The control channel is opened.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       info("The control channel is closed. " + aReason);
     });
 
-    gScript.addMessageListener('offer-sent', function offerSentHandler() {
+    gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
-      info("An offer is sent out.");
+      ok(aIsValid, "A valid offer is sent out.");
       gScript.sendAsyncMessage('trigger-incoming-transport');
     });
 
     gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
       gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
       info("Data transport channel is initialized.");
       gScript.sendAsyncMessage('trigger-data-transport-close', SpecialPowers.Cr.NS_ERROR_UNEXPECTED);
     });
--- a/dom/presentation/tests/xpcshell/test_tcp_control_channel.js
+++ b/dom/presentation/tests/xpcshell/test_tcp_control_channel.js
@@ -24,18 +24,18 @@ function makeJointSuccess(names) {
   return funcs;
 }
 
 function TestDescription(aType, aTcpAddress, aTcpPort) {
   this.type = aType;
   this.tcpAddress = Cc["@mozilla.org/array;1"]
                       .createInstance(Ci.nsIMutableArray);
   for (let address of aTcpAddress) {
-    let wrapper = Cc["@mozilla.org/supports-string;1"]
-                    .createInstance(Ci.nsISupportsString);
+    let wrapper = Cc["@mozilla.org/supports-cstring;1"]
+                    .createInstance(Ci.nsISupportsCString);
     wrapper.data = address;
     this.tcpAddress.appendElement(wrapper, false);
   }
   this.tcpPort = aTcpPort;
 }
 
 TestDescription.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationChannelDescription]),
@@ -86,17 +86,17 @@ function testPresentationServer() {
 
       controllerControlChannel.listener = {
         status: 'created',
         onOffer: function(aOffer) {
           Assert.equal(this.status, 'opened', '1. controllerControlChannel: get offer, send answer');
           this.status = 'onOffer';
 
           let offer = aOffer.QueryInterface(Ci.nsIPresentationChannelDescription);
-          Assert.strictEqual(offer.tcpAddress.queryElementAt(0,Ci.nsISupportsString).data,
+          Assert.strictEqual(offer.tcpAddress.queryElementAt(0,Ci.nsISupportsCString).data,
                              OFFER_ADDRESS,
                              'expected offer address array');
           Assert.equal(offer.tcpPort, OFFER_PORT, 'expected offer port');
           try {
             let tcpType = Ci.nsIPresentationChannelDescription.TYPE_TCP;
             let answer = new TestDescription(tcpType, [ANSWER_ADDRESS], ANSWER_PORT);
             controllerControlChannel.sendAnswer(answer);
           } catch (e) {
@@ -143,17 +143,17 @@ function testPresentationServer() {
     status: 'created',
     onOffer: function(offer) {
       Assert.ok(false, 'get offer');
     },
     onAnswer: function(aAnswer) {
       Assert.equal(this.status, 'opened', '2. presenterControlChannel: get answer, close channel');
 
       let answer = aAnswer.QueryInterface(Ci.nsIPresentationChannelDescription);
-      Assert.strictEqual(answer.tcpAddress.queryElementAt(0,Ci.nsISupportsString).data,
+      Assert.strictEqual(answer.tcpAddress.queryElementAt(0,Ci.nsISupportsCString).data,
                          ANSWER_ADDRESS,
                          'expected answer address array');
       Assert.equal(answer.tcpPort, ANSWER_PORT, 'expected answer port');
 
       presenterControlChannel.close(Cr.NS_OK);
     },
     notifyOpened: function() {
       Assert.equal(this.status, 'created', '0. presenterControlChannel: opened, send offer');
new file mode 100644
--- /dev/null
+++ b/gfx/doc/B2GInputFlow.svg
@@ -0,0 +1,349 @@
+<?xml version="1.0"?>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="800">
+ <title>Touch input event flow on B2G</title>
+ <g id="arrows"></g>
+ <style type="text/css"><![CDATA[
+    text {
+        fill: black;
+        text-anchor: middle;
+        white-space: pre-line;
+        font-size: 14px;
+    }
+    rect {
+        fill: none;
+    }
+    line {
+        stroke: black;
+    }
+    .parentinput rect {
+        stroke: black;
+    }
+    text.parentinput {
+        fill: black;
+        text-anchor: start;
+    }
+    .parentmain rect {
+        stroke: orange;
+    }
+    text.parentmain {
+        fill: orange;
+        text-anchor: start;
+    }
+    .parentcompositor rect {
+        stroke: green;
+    }
+    text.parentcompositor {
+        fill: green;
+        text-anchor: start;
+    }
+    .childmain rect {
+        stroke: red;
+    }
+    text.childmain {
+        fill: red;
+        text-anchor: start;
+    }
+    .bothmain rect {
+        stroke: blue;
+    }
+    text.bothmain {
+        fill: blue;
+        text-anchor: start;
+    }
+ ]]></style>
+ <script type="text/javascript"><![CDATA[
+    var svg = "http://www.w3.org/2000/svg";
+    var maxY = 0;
+
+    function breaks(text) {
+        var count = 0;
+        for (var i = text.length - 1; i >= 0; i--) {
+            if (text.charAt(i) == '\n') {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    function makeAction(text, x, y, thread) {
+        maxY = Math.max(maxY, y);
+        var g = document.createElementNS(svg, "g");
+        g.setAttribute("class", "action " + thread);
+        g.setAttribute("transform", "translate(" + x + ", " + (y + 30) + ")");
+        var r = document.createElementNS(svg, "rect");
+        r.setAttribute("width", "100");
+        r.setAttribute("height", "40");
+        var t = document.createElementNS(svg, "text");
+        t.setAttribute("x", "50");
+        t.setAttribute("y", 25 - (7 * breaks(text)));
+        t.appendChild(document.createTextNode(text));
+        g.appendChild(r);
+        g.appendChild(t);
+        return g;
+    }
+
+    function makeChoice(text, x, y, thread) {
+        maxY = Math.max(maxY, y);
+        var g = document.createElementNS(svg, "g");
+        g.setAttribute("class", "choice " + thread);
+        g.setAttribute("transform", "translate(" + (x + 15) + ", " + (y + 15) + ")");
+        var g2 = document.createElementNS(svg, "g");
+        g2.setAttribute("transform", "rotate(-45, 35, 35)");
+        var r = document.createElementNS(svg, "rect");
+        r.setAttribute("width", "70");
+        r.setAttribute("height", "70");
+        g2.appendChild(r);
+        var t = document.createElementNS(svg, "text");
+        t.setAttribute("x", "35");
+        t.setAttribute("y", 40 - (7 * breaks(text)));
+        t.appendChild(document.createTextNode(text));
+        g.appendChild(g2);
+        g.appendChild(t);
+        return g;
+    }
+
+    function makeLabelChoice(label, point) {
+        var t = document.createElementNS(svg, "text");
+        t.setAttribute("x", point.x);
+        t.setAttribute("y", point.y);
+        t.appendChild(document.createTextNode(label));
+        return t;
+    }
+
+    function makeLine(sx, sy, ex, ey) {
+        maxY = Math.max(maxY, sy, ey);
+        var l = document.createElementNS(svg, "line");
+        l.setAttribute("x1", sx);
+        l.setAttribute("y1", sy);
+        l.setAttribute("x2", ex);
+        l.setAttribute("y2", ey);
+        return l;
+    }
+
+    function makeArrow(start, end) {
+        var g = document.createElementNS(svg, "g");
+        g.appendChild(makeLine(start.x, start.y, end.x, end.y));
+        if (start.x != end.x) {
+            start.x = end.x + (4 * Math.sign(start.x - end.x));
+            g.appendChild(makeLine(start.x, start.y - 4, end.x, end.y));
+            g.appendChild(makeLine(start.x, start.y + 4, end.x, end.y));
+        } else if (start.y != end.y) {
+            start.y = end.y + (4 * Math.sign(start.y - end.y));
+            g.appendChild(makeLine(start.x - 4, start.y, end.x, end.y));
+            g.appendChild(makeLine(start.x + 4, start.y, end.x, end.y));
+        }
+        return g;
+    }
+
+    function makeVHArrow(start, end) {
+        var g = document.createElementNS(svg, "g");
+        g.appendChild(makeLine(start.x, start.y, start.x, end.y));
+        start.y = end.y;
+        g.appendChild(makeArrow(start, end));
+        return g;
+    }
+
+    function makeHVArrow(start, end) {
+        var g = document.createElementNS(svg, "g");
+        g.appendChild(makeLine(start.x, start.y, end.x, start.y));
+        start.x = end.x;
+        g.appendChild(makeArrow(start, end));
+        return g;
+    }
+
+    function makeVHVArrow(start, end, length) {
+        var g = document.createElementNS(svg, "g");
+        g.appendChild(makeLine(start.x, start.y, start.x, start.y + length));
+        start.y += length;
+        g.appendChild(makeLine(start.x, start.y, end.x, start.y));
+        start.x = end.x;
+        g.appendChild(makeArrow(start, end));
+        return g;
+    }
+
+    function makeHVHArrow(start, end, length) {
+        var g = document.createElementNS(svg, "g");
+        g.appendChild(makeLine(start.x, start.y, start.x + length, start.y));
+        start.x += length;
+        g.appendChild(makeLine(start.x, start.y, start.x, end.y));
+        start.y = end.y;
+        g.appendChild(makeArrow(start, end));
+        return g;
+    }
+
+    function translation(group) {
+        var r = new RegExp("translate\\((\\d+), (\\d+)\\)");
+        var result = r.exec(group.getAttribute("transform"));
+        return { x: parseInt(result[1]), y: parseInt(result[2]) };
+    }
+
+    function isAction(group) {
+        return group.classList.contains("action");
+    }
+
+    function isChoice(group) {
+        return group.classList.contains("choice");
+    }
+
+    function offset(point, x, y) {
+        point.x += x;
+        point.y += y;
+        return point;
+    }
+
+    function rightOf(group) {
+        var t = translation(group);
+        if (isAction(group)) {
+            return offset(t, 100, 20);
+        }
+        if (isChoice(group)) {
+            return offset(t, 85, 35);
+        }
+        return t;
+    }
+
+    function leftOf(group) {
+        var t = translation(group);
+        if (isAction(group)) {
+            return offset(t, 0, 20);
+        }
+        if (isChoice(group)) {
+            return offset(t, -15, 35);
+        }
+        return t;
+    }
+
+    function topOf(group) {
+        var t = translation(group);
+        if (isAction(group)) {
+            return offset(t, 50, 0);
+        }
+        if (isChoice(group)) {
+            return offset(t, 35, -15);
+        }
+        return t;
+    }
+
+    function bottomOf(group) {
+        var t = translation(group);
+        if (isAction(group)) {
+            return offset(t, 50, 40);
+        }
+        if (isChoice(group)) {
+            return offset(t, 35, 85);
+        }
+        return t;
+    }
+
+    function midpoint(start, end) {
+        return { x: (start.x + end.x) / 2,
+                 y: (start.y + end.y) / 2 };
+    }
+
+    function makeLegend(label, thread) {
+        var t = document.createElementNS(svg, "text");
+        t.setAttribute("x", "10");
+        t.setAttribute("y", maxY);
+        t.setAttribute("class", thread);
+        maxY += 15;
+        t.appendChild(document.createTextNode(label));
+        return t;
+    }
+
+    var android = makeAction("Android/Gonk", 20, 0, "parentinput");
+    var sendNative = makeAction("DOMWindowUtils\nsendNativeTouchPoint", 20, 100, "parentmain");
+    var apzHitTest = makeAction("APZ hit test", 150, 0, "parentcompositor");
+    var apzUntransform = makeAction("APZ\nuntransform", 300, 0, "parentcompositor");
+    var apzGesture = makeAction("APZ gesture\ndetection", 450, 0, "parentcompositor");
+    var apzTransform = makeAction("APZ transform\nupdate", 600, 0, "parentcompositor");
+    var compositor = makeAction("Compositor", 750, 0, "parentcompositor");
+    var nsAppShell = makeAction("nsAppShell", 150, 100, "parentmain");
+    var rootHitTest = makeAction("Gecko hit test\n(root process)", 300, 100, "parentmain");
+    var rootEsm = makeAction("Gecko ESM\n(root process)", 450, 100, "parentmain");
+    var isEdgeGesture = makeChoice("Edge gesture?", 300, 200, "parentmain");
+    var edgeConsume = makeAction("Consume\nevent block", 150, 200, "parentmain");
+    var bepjsm = makeAction("BEParent.jsm\nsendTouchEvent", 450, 200, "parentmain");
+    var iframeSend = makeAction("HTMLIFrameElement\nsendTouchEvent", 20, 275, "parentmain");
+    var isApzTarget = makeChoice("Target\nhas APZ?", 600, 200, "parentmain");
+    var sendTouchEvent = makeAction("Target\nsendTouchEventToWindow", 750, 100, "parentmain");
+    var injectTouch = makeAction("injectTouchEvent", 750, 200, "parentmain");
+    var targetESM = makeAction("Target window\nESM", 750, 450, "bothmain");
+    var tabParent = makeAction("TabParent", 750, 350, "parentmain");
+    var geckoUntransform = makeAction("Gecko\nuntransform", 600, 350, "parentmain");
+    var tabChild = makeAction("TabChild", 450, 350, "childmain");
+    var isApzcEnabled = makeChoice("APZ\nenabled?", 300, 350, "childmain");
+    var tabGesture = makeAction("TabChild gesture\ndetection", 150, 350, "childmain");
+    var childHitTest = makeAction("Gecko hit test\n(child process)", 300, 450, "childmain");
+    var childEsm = makeAction("Gecko ESM\n(child process)", 450, 450, "childmain");
+    var childContent = makeAction("Content\n(child process)", 600, 450, "childmain");
+
+    document.documentElement.appendChild(android);
+    document.documentElement.appendChild(sendNative);
+    document.documentElement.appendChild(apzHitTest);
+    document.documentElement.appendChild(apzUntransform);
+    document.documentElement.appendChild(apzGesture);
+    document.documentElement.appendChild(apzTransform);
+    document.documentElement.appendChild(compositor);
+    document.documentElement.appendChild(nsAppShell);
+    document.documentElement.appendChild(rootHitTest);
+    document.documentElement.appendChild(rootEsm);
+    document.documentElement.appendChild(isEdgeGesture);
+    document.documentElement.appendChild(edgeConsume);
+    document.documentElement.appendChild(bepjsm);
+    document.documentElement.appendChild(iframeSend);
+    document.documentElement.appendChild(isApzTarget);
+    document.documentElement.appendChild(sendTouchEvent);
+    document.documentElement.appendChild(injectTouch);
+    document.documentElement.appendChild(targetESM);
+    document.documentElement.appendChild(tabParent);
+    document.documentElement.appendChild(geckoUntransform);
+    document.documentElement.appendChild(tabChild);
+    document.documentElement.appendChild(isApzcEnabled);
+    document.documentElement.appendChild(tabGesture);
+    document.documentElement.appendChild(childHitTest);
+    document.documentElement.appendChild(childEsm);
+    document.documentElement.appendChild(childContent);
+
+    document.documentElement.appendChild(makeLabelChoice("Y", offset(leftOf(isEdgeGesture), -5, -5)));
+    document.documentElement.appendChild(makeLabelChoice("N", offset(rightOf(isEdgeGesture), 5, -5)));
+    document.documentElement.appendChild(makeLabelChoice("N", offset(topOf(isApzTarget), 8, -10)));
+    document.documentElement.appendChild(makeLabelChoice("Y", offset(rightOf(isApzTarget), 10, 14)));
+    document.documentElement.appendChild(makeLabelChoice("N", offset(leftOf(isApzcEnabled), -5, -5)));
+    document.documentElement.appendChild(makeLabelChoice("Y", offset(bottomOf(isApzcEnabled), 10, 14)));
+
+    var arrows = document.getElementById('arrows');
+    arrows.appendChild(makeArrow(rightOf(android), leftOf(apzHitTest)));
+    arrows.appendChild(makeVHVArrow(topOf(sendNative), midpoint(rightOf(android), leftOf(apzHitTest)), -20));
+    arrows.appendChild(makeArrow(rightOf(apzHitTest), leftOf(apzUntransform)));
+    arrows.appendChild(makeArrow(rightOf(apzUntransform), leftOf(apzGesture)));
+    arrows.appendChild(makeArrow(rightOf(apzGesture), leftOf(apzTransform)));
+    arrows.appendChild(makeArrow(rightOf(apzTransform), leftOf(compositor)));
+    arrows.appendChild(makeVHVArrow(midpoint(leftOf(apzUntransform), rightOf(apzGesture)), topOf(nsAppShell), 40));
+    arrows.appendChild(makeArrow(rightOf(nsAppShell), leftOf(rootHitTest)));
+    arrows.appendChild(makeArrow(rightOf(rootHitTest), leftOf(rootEsm)));
+    arrows.appendChild(makeVHVArrow(bottomOf(rootEsm), topOf(isEdgeGesture), 15));
+    arrows.appendChild(makeArrow(leftOf(isEdgeGesture), rightOf(edgeConsume)));
+    arrows.appendChild(makeArrow(rightOf(isEdgeGesture), leftOf(bepjsm), 20));
+    arrows.appendChild(makeHVArrow(rightOf(iframeSend), bottomOf(bepjsm)));
+    arrows.appendChild(makeArrow(rightOf(bepjsm), leftOf(isApzTarget)));
+    arrows.appendChild(makeArrow(rightOf(isApzTarget), leftOf(injectTouch)));
+    arrows.appendChild(makeArrow(bottomOf(injectTouch), topOf(tabParent)));
+    arrows.appendChild(makeVHArrow(topOf(isApzTarget), leftOf(sendTouchEvent)));
+    arrows.appendChild(makeHVHArrow(rightOf(sendTouchEvent), rightOf(targetESM), 30));
+    arrows.appendChild(makeArrow(leftOf(tabParent), rightOf(geckoUntransform)));
+    arrows.appendChild(makeArrow(leftOf(geckoUntransform), rightOf(tabChild)));
+    arrows.appendChild(makeArrow(leftOf(tabChild), rightOf(isApzcEnabled)));
+    arrows.appendChild(makeArrow(leftOf(isApzcEnabled), rightOf(tabGesture)));
+    arrows.appendChild(makeArrow(bottomOf(isApzcEnabled), topOf(childHitTest)));
+    arrows.appendChild(makeVHArrow(bottomOf(tabGesture), leftOf(childHitTest)));
+    arrows.appendChild(makeArrow(rightOf(childHitTest), leftOf(childEsm)));
+    arrows.appendChild(makeArrow(rightOf(childEsm), leftOf(childContent)));
+    arrows.appendChild(makeVHVArrow(midpoint(leftOf(apzGesture), rightOf(apzTransform)), topOf(tabChild), 300));
+
+    document.documentElement.appendChild(makeLegend("Main process input thread", "parentinput"));
+    document.documentElement.appendChild(makeLegend("Main process main thread", "parentmain"));
+    document.documentElement.appendChild(makeLegend("Main process compositor thread", "parentcompositor"));
+    document.documentElement.appendChild(makeLegend("Child process main thread", "childmain"));
+    document.documentElement.appendChild(makeLegend("Undetermined process main thread", "bothmain"));
+ ]]></script>
+</svg>
--- a/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
@@ -2,24 +2,25 @@
 /* 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 "nsDNSServiceDiscovery.h"
 #include <cutils/properties.h>
 #include "MDNSResponderOperator.h"
 #include "nsICancelable.h"
+#include "nsXULAppAPI.h"
 #include "private/pprio.h"
 
 namespace mozilla {
 namespace net {
 
 namespace {
 
-void
+inline void
 StartService()
 {
   char value[PROPERTY_VALUE_MAX] = { '\0' };
   property_get("init.svc.mdnsd", value, "");
 
   if (strcmp(value, "running") == 0) {
     return;
   }
@@ -33,17 +34,49 @@ StopService()
   property_get("init.svc.mdnsd", value, "");
 
   if (strcmp(value, "stopped") == 0) {
     return;
   }
   property_set("ctl.stop", "mdnsd");
 }
 
+class ServiceCounter
+{
+public:
+  static bool IsServiceRunning()
+  {
+    return !!sUseCount;
+  }
+
+private:
+  static uint32_t sUseCount;
+
+protected:
+  ServiceCounter()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    if (!sUseCount++) {
+      StartService();
+    }
+  }
+
+  virtual ~ServiceCounter()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    if (!--sUseCount) {
+      StopService();
+    }
+  }
+};
+
+uint32_t ServiceCounter::sUseCount = 0;
+
 class DiscoveryRequest final : public nsICancelable
+                             , private ServiceCounter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICANCELABLE
 
   explicit DiscoveryRequest(nsDNSServiceDiscovery* aService,
                             nsIDNSServiceDiscoveryListener* aListener);
 
@@ -70,16 +103,17 @@ DiscoveryRequest::Cancel(nsresult aReaso
     mService->StopDiscovery(mListener);
   }
 
   mService = nullptr;
   return NS_OK;
 }
 
 class RegisterRequest final : public nsICancelable
+                            , private ServiceCounter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICANCELABLE
 
   explicit RegisterRequest(nsDNSServiceDiscovery* aService,
                            nsIDNSRegistrationListener* aListener);
 
@@ -119,41 +153,44 @@ nsDNSServiceDiscovery::~nsDNSServiceDisc
 #ifdef MOZ_WIDGET_GONK
   StopService();
 #endif
 }
 
 nsresult
 nsDNSServiceDiscovery::Init()
 {
-  StartService();
+  if (!XRE_IsParentProcess()) {
+    MOZ_ASSERT(false, "nsDNSServiceDiscovery can only be used in parent process");
+    return NS_ERROR_FAILURE;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSServiceDiscovery::StartDiscovery(const nsACString& aServiceType,
                                       nsIDNSServiceDiscoveryListener* aListener,
                                       nsICancelable** aRetVal)
 {
   MOZ_ASSERT(aRetVal);
 
   nsresult rv;
   if (NS_WARN_IF(NS_FAILED(rv = StopDiscovery(aListener)))) {
     return rv;
   }
 
+  nsCOMPtr<nsICancelable> req = new DiscoveryRequest(this, aListener);
   nsRefPtr<BrowseOperator> browserOp = new BrowseOperator(aServiceType,
                                                           aListener);
   if (NS_WARN_IF(NS_FAILED(rv = browserOp->Start()))) {
     return rv;
   }
 
   mDiscoveryMap.Put(aListener, browserOp);
 
-  nsCOMPtr<nsICancelable> req = new DiscoveryRequest(this, aListener);
   req.forget(aRetVal);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSServiceDiscovery::StopDiscovery(nsIDNSServiceDiscoveryListener* aListener)
 {
@@ -180,25 +217,25 @@ nsDNSServiceDiscovery::RegisterService(n
 {
   MOZ_ASSERT(aRetVal);
 
   nsresult rv;
   if (NS_WARN_IF(NS_FAILED(rv = UnregisterService(aListener)))) {
     return rv;
   }
 
+  nsCOMPtr<nsICancelable> req = new RegisterRequest(this, aListener);
   nsRefPtr<RegisterOperator> registerOp = new RegisterOperator(aServiceInfo,
                                                                aListener);
   if (NS_WARN_IF(NS_FAILED(rv = registerOp->Start()))) {
     return rv;
   }
 
   mRegisterMap.Put(aListener, registerOp);
 
-  nsCOMPtr<nsICancelable> req = new RegisterRequest(this, aListener);
   req.forget(aRetVal);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSServiceDiscovery::UnregisterService(nsIDNSRegistrationListener* aListener)
 {
@@ -217,16 +254,20 @@ nsDNSServiceDiscovery::UnregisterService
   mRegisterMap.Remove(aListener);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSServiceDiscovery::ResolveService(nsIDNSServiceInfo* aServiceInfo,
                                       nsIDNSServiceResolveListener* aListener)
 {
+  if (!ServiceCounter::IsServiceRunning()) {
+    return NS_ERROR_FAILURE;
+  }
+
   nsresult rv;
 
   nsRefPtr<ResolveOperator> resolveOp = new ResolveOperator(aServiceInfo,
                                                             aListener);
   if (NS_WARN_IF(NS_FAILED(rv = resolveOp->Start()))) {
     return rv;
   }
 
--- a/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
@@ -21,18 +21,18 @@ class nsDNSServiceDiscovery final : publ
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIDNSSERVICEDISCOVERY
 
   explicit nsDNSServiceDiscovery() = default;
 
   /*
-  ** The mDNS service is started in this function. However, the function returns
-  ** without waiting. Therefore, all operations before service started will fail
+  ** The mDNS service is started on demand. If no one uses, mDNS service will not
+  ** start. Therefore, all operations before service started will fail
   ** and get error code |kDNSServiceErr_ServiceNotRunning| defined in dns_sd.h.
   **/
   nsresult Init();
 
   nsresult StopDiscovery(nsIDNSServiceDiscoveryListener* aListener);
   nsresult UnregisterService(nsIDNSRegistrationListener* aListener);
 
 private:
--- a/testing/docker/builder/Dockerfile
+++ b/testing/docker/builder/Dockerfile
@@ -16,16 +16,16 @@ RUN hg clone http://hg.mozilla.org/build
       cd /tools/tools && \
       python setup.py install
 
 # Initialize git (makes repo happy)
 RUN git config --global user.email "mozilla@example.com" && \
     git config --global user.name "mozilla"
 
 # VCS Tools
-RUN npm install -g taskcluster-vcs@2.3.9
+RUN npm install -g taskcluster-vcs@2.3.12
 
 # TODO enable worker
 # TODO volume mount permissions will be an issue
 # USER worker
 
 COPY bin /home/worker/bin
 RUN chmod a+x /home/worker/bin/*
--- a/testing/docker/builder/VERSION
+++ b/testing/docker/builder/VERSION
@@ -1,1 +1,1 @@
-0.5.8
+0.5.9
--- a/testing/docker/centos6-build/system-setup.sh
+++ b/testing/docker/centos6-build/system-setup.sh
@@ -245,17 +245,17 @@ cat >requirements.txt <<'EOF'
 virtualenv==13.1.2
 
 # sha256: tQ9peOfTn-DLKY-j-j6c5B0jVnIdFV5SiPnFfl8T6ac
 mercurial==3.5
 EOF
 peep install -r requirements.txt
 
 # TC-VCS
-npm install -g taskcluster-vcs@2.3.8
+npm install -g taskcluster-vcs@2.3.12
 
 # note that TC will replace workspace with a cache mount; there's no sense
 # creating anything inside there
 mkdir -p /home/worker/workspace
 chown worker:worker /home/worker/workspace
 
 # /builds is *not* replaced with a mount in the docker container. The worker
 # user writes to lots of subdirectories, though, so it's owned by that user
--- a/testing/docker/phone-builder/Dockerfile
+++ b/testing/docker/phone-builder/Dockerfile
@@ -1,9 +1,9 @@
-FROM          taskcluster/builder:0.5.8
+FROM          taskcluster/builder:0.5.9
 MAINTAINER    Wander Lairson Costa <wcosta@mozilla.com>
 
 ENV           SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE /home/worker/socorro.token
 
 # Add utilities and configuration
 ADD           bin                   /home/worker/bin
 ADD           config                /home/worker/.aws/config
 ADD           socorro.token         /home/worker/socorro.token
--- a/testing/docker/phone-builder/VERSION
+++ b/testing/docker/phone-builder/VERSION
@@ -1,1 +1,1 @@
-0.0.19
+0.0.20
--- a/testing/docker/tester-device/Dockerfile
+++ b/testing/docker/tester-device/Dockerfile
@@ -26,17 +26,17 @@ RUN apt-get upgrade -y && apt-get instal
 RUN curl https://bootstrap.pypa.io/get-pip.py | python
 RUN pip install virtualenv
 
 RUN git config --global user.email "mozilla@example.com" && \
     git config --global user.name "mozilla"
 
 
 # Get node packages
-RUN npm install -g taskcluster-vcs@2.3.9
+RUN npm install -g taskcluster-vcs@2.3.12
 
 WORKDIR /home/worker
 
 ADD bin /home/worker/bin
 ADD data /home/worker/data
 ADD https://raw.githubusercontent.com/taskcluster/buildbot-step/master/buildbot_step /home/worker/bin/buildbot_step
 RUN chmod u+x /home/worker/bin/*
 
--- a/testing/docker/tester-device/VERSION
+++ b/testing/docker/tester-device/VERSION
@@ -1,1 +1,1 @@
-0.0.6
+0.0.7
--- a/testing/docker/tester/Dockerfile
+++ b/testing/docker/tester/Dockerfile
@@ -13,17 +13,17 @@ ADD            https://raw.githubusercon
 COPY           tc-vcs-config.yml /etc/taskcluster-vcs.yml
 
 # Run test setup script
 RUN chmod u+x /home/worker/bin/buildbot_step
 RUN chmod u+x /usr/local/bin/linux64-minidump_stackwalk
 RUN apt-get install -y python-pip && pip install virtualenv;
 RUN mkdir Documents; mkdir Pictures; mkdir Music; mkdir Videos; mkdir artifacts
 RUN npm install -g npm@^2.0.0
-RUN npm install -g taskcluster-vcs@2.3.9
+RUN npm install -g taskcluster-vcs@2.3.12
 RUN npm install -g taskcluster-npm-cache@1.1.14
 RUN rm -Rf .cache && mkdir -p .cache
 ENV PATH $PATH:/home/worker/bin
 
 # Remove once running under 'worker' user.  This is necessary for pulseaudio to start
 # XXX: change this back to worker:worker once permissions issues are resolved
 RUN            chown -R root:root /home/worker
 
--- a/testing/docker/tester/VERSION
+++ b/testing/docker/tester/VERSION
@@ -1,1 +1,1 @@
-0.3.7
+0.3.8
--- a/testing/docker/ubuntu-build/Dockerfile
+++ b/testing/docker/ubuntu-build/Dockerfile
@@ -6,17 +6,17 @@ RUN useradd -d /home/worker -s /bin/bash
 
 # install non-build specific dependencies in a single layer
 ADD           system-setup.sh   /tmp/system-setup.sh
 RUN           bash /tmp/system-setup.sh
 
 # configure git and install tc-vcs
 RUN git config --global user.email "nobody@mozilla.com" && \
     git config --global user.name "mozilla"
-RUN npm install -g taskcluster-vcs@2.3.9
+RUN npm install -g taskcluster-vcs@2.3.12
 
 # Ensure that build specific dependencies live in a single layer
 ADD           build-setup.sh   /tmp/build-setup.sh
 RUN           bash /tmp/build-setup.sh
 
 # Builds need the share module enabled
 ADD           hgrc /home/worker/.hgrc
 
--- a/testing/docker/ubuntu-build/VERSION
+++ b/testing/docker/ubuntu-build/VERSION
@@ -1,1 +1,1 @@
-0.0.6
+0.0.7
--- a/testing/docker/ubuntu32-build/Dockerfile
+++ b/testing/docker/ubuntu32-build/Dockerfile
@@ -6,17 +6,17 @@ RUN useradd -d /home/worker -s /bin/bash
 
 # install non-build specific dependencies in a single layer
 ADD           system-setup.sh   /tmp/system-setup.sh
 RUN           bash /tmp/system-setup.sh
 
 # configure git and install tc-vcs
 RUN git config --global user.email "nobody@mozilla.com" && \
     git config --global user.name "mozilla"
-RUN npm install -g taskcluster-vcs@2.3.9
+RUN npm install -g taskcluster-vcs@2.3.12
 
 # Ensure that build specific dependencies live in a single layer
 ADD           build-setup.sh   /tmp/build-setup.sh
 RUN           bash /tmp/build-setup.sh
 
 # Builds need the share module enabled
 ADD           hgrc /home/worker/.hgrc
 
--- a/testing/docker/ubuntu32-build/VERSION
+++ b/testing/docker/ubuntu32-build/VERSION
@@ -1,1 +1,1 @@
-0.0.6
+0.0.7
--- a/testing/taskcluster/mach_commands.py
+++ b/testing/taskcluster/mach_commands.py
@@ -184,16 +184,29 @@ def set_interactive_task(task, interacti
     if not interactive:
         return
 
     payload = task["task"]["payload"]
     if "features" not in payload:
         payload["features"] = {}
     payload["features"]["interactive"] = True
 
+def remove_caches_from_task(task):
+    r"""Remove all caches but tc-vcs from the task.
+
+    :param task: task definition.
+    """
+    try:
+        caches = task["task"]["payload"]["cache"]
+        for cache in caches.keys():
+            if cache != "tc-vcs":
+                caches.pop(cache)
+    except KeyError:
+        pass
+
 @CommandProvider
 class DecisionTask(object):
     @Command('taskcluster-decision', category="ci",
         description="Build a decision task")
     @CommandArgument('--project',
         required=True,
         help='Treeherder project name')
     @CommandArgument('--url',
@@ -360,16 +373,20 @@ class Graph(object):
 
         for build in job_graph:
             interactive = cmdline_interactive or build["interactive"]
             build_parameters = dict(parameters)
             build_parameters['build_slugid'] = slugid()
             build_task = templates.load(build['task'], build_parameters)
             set_interactive_task(build_task, interactive)
 
+            # try builds don't use cache
+            if project == "try":
+                remove_caches_from_task(build_task)
+
             if params['revision_hash']:
                 decorate_task_treeherder_routes(build_task['task'],
                                                 treeherder_route)
                 decorate_task_json_routes(build,
                                           build_task['task'],
                                           json_routes,
                                           build_parameters)