Merge b2g-inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 10 Feb 2014 15:37:54 -0500
changeset 167875 07739c5c874f
parent 167838 f5726434eedc (current diff)
parent 167874 fea1fd2679a8 (diff)
child 167907 d812f80a0f1d
push id26190
push userryanvm@gmail.com
push date2014-02-10 20:37 +0000
treeherdermozilla-central@07739c5c874f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone30.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 b2g-inbound to m-c.
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,23 +7,23 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -6,20 +6,20 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,23 +7,23 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "25b78e722d958fe667061a2d9e0733d0877607ac", 
+    "revision": "500d57309898b0514b1ad1a61a8d8274909428a4", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,22 +6,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,22 +7,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,22 +6,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
   <project name="platform/development" path="development" revision="b1025ec93beeb480caaf3049d171283c3846461d"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,20 +6,20 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -6,22 +6,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="7ef494164bcd840dc23c7db106dff0a98f8ff15f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9fc36dde3a4a3c5ca200275b68ffb56b4173bec3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="0a8bdd0f43e2d8fc7d45b3b0d97125834c0ac72f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="788d9ce293a9b44f64536130cf4ad577e8101dbe"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/content/media/omx/RtspOmxReader.cpp
+++ b/content/media/omx/RtspOmxReader.cpp
@@ -169,16 +169,17 @@ status_t RtspMediaSource::read(MediaBuff
 class RtspExtractor: public MediaExtractor
 {
 public:
   virtual size_t countTracks() MOZ_FINAL MOZ_OVERRIDE;
   virtual sp<android::MediaSource> getTrack(size_t index)
     MOZ_FINAL MOZ_OVERRIDE;
   virtual sp<MetaData> getTrackMetaData(
     size_t index, uint32_t flag = 0) MOZ_FINAL MOZ_OVERRIDE;
+  virtual uint32_t flags() const MOZ_FINAL MOZ_OVERRIDE;
 
   RtspExtractor(RtspMediaResource *aResource)
     : mRtspResource(aResource) {
     MOZ_COUNT_CTOR(RtspExtractor);
     MOZ_ASSERT(aResource);
     mController = mRtspResource->GetMediaStreamController();
     MOZ_ASSERT(mController);
   }
@@ -251,25 +252,34 @@ sp<MetaData> RtspExtractor::getTrackMeta
     rtspMetadata->GetAvccData(tempCString);
     if (tempCString.Length()) {
       meta->setData(kKeyAVCC, 0, tempCString.get(), tempCString.Length());
     }
   }
   return meta;
 }
 
+uint32_t RtspExtractor::flags() const
+{
+  if (mRtspResource->IsRealTime()) {
+    return 0;
+  } else {
+    return MediaExtractor::CAN_SEEK;
+  }
+}
+
 nsresult RtspOmxReader::InitOmxDecoder()
 {
   if (!mOmxDecoder.get()) {
     NS_ASSERTION(mDecoder, "RtspOmxReader mDecoder is null.");
     NS_ASSERTION(mDecoder->GetResource(),
                  "RtspOmxReader mDecoder->GetResource() is null.");
-    sp<MediaExtractor> extractor = new RtspExtractor(mRtspResource);
+    mExtractor = new RtspExtractor(mRtspResource);
     mOmxDecoder = new OmxDecoder(mDecoder->GetResource(), mDecoder);
-    if (!mOmxDecoder->Init(extractor)) {
+    if (!mOmxDecoder->Init(mExtractor)) {
       return NS_ERROR_FAILURE;
     }
   }
   return NS_OK;
 }
 
 nsresult RtspOmxReader::Seek(int64_t aTime, int64_t aStartTime,
                              int64_t aEndTime, int64_t aCurrentTime)
--- a/content/media/test/test_new_audio.html
+++ b/content/media/test/test_new_audio.html
@@ -20,21 +20,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 /** Test for Bug 528566 **/
 
 var manager = new MediaTestManager;
 
 var player = new Audio();
 
 function startTest(test, token) {
-  if (!player.canPlayType(test.type))
+  if (!player.canPlayType(test.type)) {
     return;
+  }
   manager.started(token);
   var a = new Audio(test.name);
-  a.setAttribute("autoplay", false);
   a.addEventListener("canplaythrough",
                      function(e){ e.target.play(); },
                       false);
   a.addEventListener("ended",
                      function(e){
                         ok(true, "We should get to the end. Oh look we did.");
                         manager.finished(token);
                      },
--- a/dom/network/src/NetworkStatsDB.jsm
+++ b/dom/network/src/NetworkStatsDB.jsm
@@ -11,17 +11,17 @@ function debug(s) { dump("-*- NetworkSta
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 Cu.importGlobalProperties(["indexedDB"]);
 
 const DB_NAME = "net_stats";
-const DB_VERSION = 6;
+const DB_VERSION = 7;
 const DEPRECATED_STORE_NAME = "net_stats";
 const STATS_STORE_NAME = "net_stats_store";
 const ALARMS_STORE_NAME = "net_alarm";
 
 // Constant defining the maximum values allowed per interface. If more, older
 // will be erased.
 const VALUES_MAX_LENGTH = 6 * 30;
 
@@ -208,16 +208,104 @@ NetworkStatsDB.prototype = {
           newStats.serviceType = "";
           newObjectStore.put(newStats);
           cursor.continue();
         };
 
         if (DEBUG) {
           debug("Added new key 'serviceType' for version 6");
         }
+      } else if (currVersion == 6) {
+        // Replace threshold attribute of alarm index by relativeThreshold in alarms DB.
+        // Now alarms are indexed by relativeThreshold, which is the threshold relative
+        // to current system stats.
+        let alarmsStore = aTransaction.objectStore(ALARMS_STORE_NAME);
+
+        // Delete "alarm" index.
+        if (alarmsStore.indexNames.contains("alarm")) {
+          alarmsStore.deleteIndex("alarm");
+        }
+
+        // Create new "alarm" index.
+        alarmsStore.createIndex("alarm", ['networkId','relativeThreshold'], { unique: false });
+
+        // Populate new "alarm" index attributes.
+        alarmsStore.openCursor().onsuccess = function(event) {
+          let cursor = event.target.result;
+          if (!cursor) {
+            return;
+          }
+
+          cursor.value.relativeThreshold = cursor.value.threshold;
+          cursor.value.absoluteThreshold = cursor.value.threshold;
+          delete cursor.value.threshold;
+
+          cursor.update(cursor.value);
+          cursor.continue();
+        }
+
+        // Previous versions save accumulative totalBytes, increasing althought the system
+        // reboots or resets stats. But is necessary to reset the total counters when reset
+        // through 'clearInterfaceStats'.
+        let statsStore = aTransaction.objectStore(STATS_STORE_NAME);
+        let networks = [];
+        // Find networks stored in the database.
+        statsStore.index("network").openKeyCursor(null, "nextunique").onsuccess = function(event) {
+          let cursor = event.target.result;
+          if (cursor) {
+            networks.push(cursor.key);
+            cursor.continue();
+            return;
+          }
+
+          networks.forEach(function(network) {
+            let lowerFilter = [0, "", network, 0];
+            let upperFilter = [0, "", network, ""];
+            let range = IDBKeyRange.bound(lowerFilter, upperFilter, false, false);
+
+            // Find number of samples for a given network.
+            statsStore.count(range).onsuccess = function(event) {
+              // If there are more samples than the max allowed, there is no way to know
+              // when does reset take place.
+              if (event.target.result >= VALUES_MAX_LENGTH) {
+                return;
+              }
+
+              let last = null;
+              // Reset detected if the first sample totalCounters are different than bytes
+              // counters. If so, the total counters should be recalculated.
+              statsStore.openCursor(range).onsuccess = function(event) {
+                let cursor = event.target.result;
+                if (!cursor) {
+                  return;
+                }
+                if (!last) {
+                  if (cursor.value.rxTotalBytes == cursor.value.rxBytes &&
+                      cursor.value.txTotalBytes == cursor.value.txBytes) {
+                    return;
+                  }
+
+                  cursor.value.rxTotalBytes = cursor.value.rxBytes;
+                  cursor.value.txTotalBytes = cursor.value.txBytes;
+                  cursor.update(cursor.value);
+                  last = cursor.value;
+                  cursor.continue();
+                  return;
+                }
+
+                // Recalculate the total counter for last / current sample
+                cursor.value.rxTotalBytes = last.rxTotalBytes + cursor.value.rxBytes;
+                cursor.value.txTotalBytes = last.txTotalBytes + cursor.value.txBytes;
+                cursor.update(cursor.value);
+                last = cursor.value;
+                cursor.continue();
+              }
+            }
+          }, this);
+        };
       }
     }
   },
 
   importData: function importData(aStats) {
     let stats = { appId:         aStats.appId,
                   serviceType:   aStats.serviceType,
                   network:       [aStats.networkId, aStats.networkType],
@@ -510,16 +598,18 @@ NetworkStatsDB.prototype = {
         if (sample) {
           let timestamp = new Date();
           timestamp = self.normalizeDate(timestamp);
           sample.timestamp = timestamp;
           sample.appId = 0;
           sample.serviceType = "";
           sample.rxBytes = 0;
           sample.txBytes = 0;
+          sample.rxTotalBytes = 0;
+          sample.txTotalBytes = 0;
 
           self._saveStats(aTxn, aStore, sample);
         }
       };
     }, aResultCb);
   },
 
   clearStats: function clearStats(aNetworks, aResultCb) {
@@ -545,34 +635,88 @@ NetworkStatsDB.prototype = {
     this.clearInterfaceStats(aNetworks[index], callback);
   },
 
   getCurrentStats: function getCurrentStats(aNetwork, aDate, aResultCb) {
     if (DEBUG) {
       debug("Get current stats for " + JSON.stringify(aNetwork) + " since " + aDate);
     }
 
+    let network = [aNetwork.id, aNetwork.type];
+    if (aDate) {
+      this._getCurrentStatsFromDate(network, aDate, aResultCb);
+      return;
+    }
+
+    this._getCurrentStats(network, aResultCb);
+  },
+
+  _getCurrentStats: function _getCurrentStats(aNetwork, aResultCb) {
+    this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
+      let request = null;
+      let upperFilter = [0, "", aNetwork, Date.now()];
+      let range = IDBKeyRange.upperBound(upperFilter, false);
+      request = store.openCursor(range, "prev");
+
+      let result = { rxBytes:      0, txBytes:      0,
+                     rxTotalBytes: 0, txTotalBytes: 0 };
+
+      request.onsuccess = function onsuccess(event) {
+        let cursor = event.target.result;
+        if (cursor) {
+          result.rxBytes = result.rxTotalBytes = cursor.value.rxTotalBytes;
+          result.txBytes = result.txTotalBytes = cursor.value.txTotalBytes;
+        }
+
+        txn.result = result;
+      };
+    }.bind(this), aResultCb);
+  },
+
+  _getCurrentStatsFromDate: function _getCurrentStatsFromDate(aNetwork, aDate, aResultCb) {
+    aDate = new Date(aDate);
     this.dbNewTxn(STATS_STORE_NAME, "readonly", function(txn, store) {
       let request = null;
-      let network = [aNetwork.id, aNetwork.type];
-      if (aDate) {
-        let start = this.normalizeDate(aDate);
-        let lowerFilter = [0, network, start];
-        let range = this.dbGlobal.IDBKeyRange.lowerBound(lowerFilter, false);
-        request = store.openCursor(range);
-      } else {
-        request = store.index("network").openCursor(network, "prev");
-      }
+      let start = this.normalizeDate(aDate);
+      let lowerFilter = [0, "", aNetwork, start];
+      let upperFilter = [0, "", aNetwork, Date.now()];
+
+      let range = IDBKeyRange.upperBound(upperFilter, false);
+
+      let result = { rxBytes:      0, txBytes:      0,
+                     rxTotalBytes: 0, txTotalBytes: 0 };
+
+      request = store.openCursor(range, "prev");
 
       request.onsuccess = function onsuccess(event) {
-        txn.result = null;
         let cursor = event.target.result;
         if (cursor) {
-          txn.result = cursor.value;
+          result.rxBytes = result.rxTotalBytes = cursor.value.rxTotalBytes;
+          result.txBytes = result.txTotalBytes = cursor.value.txTotalBytes;
         }
+
+        let timestamp = cursor.value.timestamp;
+        let range = IDBKeyRange.lowerBound(lowerFilter, false);
+        request = store.openCursor(range);
+
+        request.onsuccess = function onsuccess(event) {
+          let cursor = event.target.result;
+          if (cursor) {
+            if (cursor.value.timestamp == timestamp) {
+              // There is one sample only.
+              result.rxBytes = cursor.value.rxBytes;
+              result.txBytes = cursor.value.txBytes;
+            } else {
+              result.rxBytes -= cursor.value.rxTotalBytes;
+              result.txBytes -= cursor.value.txTotalBytes;
+            }
+          }
+
+          txn.result = result;
+        };
       };
     }.bind(this), aResultCb);
   },
 
   find: function find(aResultCb, aAppId, aServiceType, aNetwork,
                       aStart, aEnd, aAppManifestURL) {
     let offset = (new Date()).getTimezoneOffset() * 60 * 1000;
     let start = this.normalizeDate(aStart);
@@ -666,17 +810,17 @@ NetworkStatsDB.prototype = {
   },
 
   isNetworkAvailable: function isNetworkAvailable(aNetwork, aResultCb) {
     this.dbNewTxn(STATS_STORE_NAME, "readonly", function(aTxn, aStore) {
       if (!aTxn.result) {
         aTxn.result = false;
       }
 
-      var network = [aNetwork.id, aNetwork.type];
+      let network = [aNetwork.id, aNetwork.type];
       let request = aStore.index("network").openKeyCursor(IDBKeyRange.only(network));
       request.onsuccess = function onsuccess(event) {
         if (event.target.result) {
           aTxn.result = true;
         }
       };
     }, aResultCb);
   },
@@ -712,31 +856,33 @@ NetworkStatsDB.prototype = {
       aStore.mozGetAll().onsuccess = function onsuccess(event) {
         aTxn.result = event.target.result;
       };
     }, aResultCb);
   },
 
   alarmToRecord: function alarmToRecord(aAlarm) {
     let record = { networkId: aAlarm.networkId,
-                   threshold: aAlarm.threshold,
+                   absoluteThreshold: aAlarm.absoluteThreshold,
+                   relativeThreshold: aAlarm.relativeThreshold,
                    data: aAlarm.data,
                    manifestURL: aAlarm.manifestURL,
                    pageURL: aAlarm.pageURL };
 
     if (aAlarm.id) {
       record.id = aAlarm.id;
     }
 
     return record;
   },
 
   recordToAlarm: function recordToalarm(aRecord) {
     let alarm = { networkId: aRecord.networkId,
-                  threshold: aRecord.threshold,
+                  absoluteThreshold: aRecord.absoluteThreshold,
+                  relativeThreshold: aRecord.relativeThreshold,
                   data: aRecord.data,
                   manifestURL: aRecord.manifestURL,
                   pageURL: aRecord.pageURL };
 
     if (aRecord.id) {
       alarm.id = aRecord.id;
     }
 
@@ -832,35 +978,31 @@ NetworkStatsDB.prototype = {
           cursor.update(record);
           txn.result = true;
         }
       }
     }, aResultCb);
   },
 
   getAlarms: function getAlarms(aNetworkId, aManifestURL, aResultCb) {
+    let self = this;
     this.dbNewTxn(ALARMS_STORE_NAME, "readonly", function(txn, store) {
       if (DEBUG) {
         debug("Get alarms for " + aManifestURL);
       }
 
       txn.result = [];
       store.index("manifestURL").openCursor(aManifestURL)
                                 .onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
         if (!cursor) {
           return;
         }
 
         if (!aNetworkId || cursor.value.networkId == aNetworkId) {
-          let alarm = { id: cursor.value.id,
-                        networkId: cursor.value.networkId,
-                        threshold: cursor.value.threshold,
-                        data: cursor.value.data };
-
-          txn.result.push(alarm);
+          txn.result.push(self.recordToAlarm(cursor.value));
         }
 
         cursor.continue();
       }
     }, aResultCb);
   }
 };
--- a/dom/network/src/NetworkStatsManager.js
+++ b/dom/network/src/NetworkStatsManager.js
@@ -232,16 +232,20 @@ NetworkStatsManager.prototype = {
 
   addAlarm: function addAlarm(aNetwork, aThreshold, aOptions) {
     this.checkPrivileges();
 
     if (!aOptions) {
       aOptions = Object.create(null);
     }
 
+    if (aOptions.startTime && aOptions.startTime.constructor.name !== "Date") {
+      throw Components.results.NS_ERROR_INVALID_ARG;
+    }
+
     let request = this.createRequest();
     cpmm.sendAsyncMessage("NetworkStats:SetAlarm",
                           {id: this.getRequestId(request),
                            data: {network: aNetwork,
                                   threshold: aThreshold,
                                   startTime: aOptions.startTime,
                                   data: aOptions.data,
                                   manifestURL: this.manifestURL,
--- a/dom/network/src/NetworkStatsService.jsm
+++ b/dom/network/src/NetworkStatsService.jsm
@@ -326,20 +326,21 @@ this.NetworkStatsService = {
     // Check if network is available in the DB.
     this._db.isNetworkAvailable(aNetwork, function(aError, aResult) {
       if (aResult) {
         this._networks[netId] = Object.create(null);
         this._networks[netId].network = aNetwork;
         this._networks[netId].status = NETWORK_STATUS_AWAY;
         this._currentAlarms[netId] = Object.create(null);
         aCallback(netId);
+        return;
       }
 
       aCallback(null);
-    });
+    }.bind(this));
   },
 
   getAvailableNetworks: function getAvailableNetworks(mm, msg) {
     let self = this;
     let rilNetworks = this.getRilNetworks();
     this._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
 
       // Also return the networks that are valid but have not
@@ -858,17 +859,17 @@ this.NetworkStatsService = {
       }
 
       let alarms = []
       // NetworkStatsManager must return the network instead of the networkId.
       for (let i = 0; i < result.length; i++) {
         let alarm = result[i];
         alarms.push({ id: alarm.id,
                       network: self._networks[alarm.networkId].network,
-                      threshold: alarm.threshold,
+                      threshold: alarm.absoluteThreshold,
                       data: alarm.data });
       }
 
       mm.sendAsyncMessage("NetworkStats:GetAlarms:Return",
                           { id: msg.id, error: null, result: alarms });
     });
   },
 
@@ -926,32 +927,31 @@ this.NetworkStatsService = {
         mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
                             { id: msg.id, error: "InvalidiConnectionType", result: null });
         return;
       }
 
       let newAlarm = {
         id: null,
         networkId: aNetId,
-        threshold: threshold,
-        absoluteThreshold: null,
+        absoluteThreshold: threshold,
+        relativeThreshold: null,
         startTime: options.startTime,
         data: options.data,
         pageURL: options.pageURL,
         manifestURL: options.manifestURL
       };
 
-      self._updateThreshold(newAlarm, function onUpdate(error, _threshold) {
+      self._getAlarmQuota(newAlarm, function onUpdate(error, quota) {
         if (error) {
           mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
                               { id: msg.id, error: error, result: null });
           return;
         }
 
-        newAlarm.absoluteThreshold = _threshold.absoluteThreshold;
         self._db.addAlarm(newAlarm, function addSuccessCb(error, newId) {
           if (error) {
             mm.sendAsyncMessage("NetworkStats:SetAlarm:Return",
                                 { id: msg.id, error: error, result: null });
             return;
           }
 
           newAlarm.id = newId;
@@ -966,25 +966,25 @@ this.NetworkStatsService = {
         });
       });
     });
   },
 
   _setAlarm: function _setAlarm(aAlarm, aCallback) {
     let currentAlarm = this._currentAlarms[aAlarm.networkId];
     if ((Object.getOwnPropertyNames(currentAlarm).length !== 0 &&
-         aAlarm.absoluteThreshold > currentAlarm.alarm.absoluteThreshold) ||
+         aAlarm.relativeThreshold > currentAlarm.alarm.relativeThreshold) ||
         this._networks[aAlarm.networkId].status != NETWORK_STATUS_READY) {
       aCallback(null, true);
       return;
     }
 
     let self = this;
 
-    this._updateThreshold(aAlarm, function onUpdate(aError, aThreshold) {
+    this._getAlarmQuota(aAlarm, function onUpdate(aError, aQuota) {
       if (aError) {
         aCallback(aError, null);
         return;
       }
 
       let callback = function onAlarmSet(aError) {
         if (aError) {
           debug("Set alarm error: " + aError);
@@ -996,60 +996,51 @@ this.NetworkStatsService = {
 
         aCallback(null, true);
       };
 
       debug("Set alarm " + JSON.stringify(aAlarm));
       let interfaceName = self._networks[aAlarm.networkId].interfaceName;
       if (interfaceName) {
         networkService.setNetworkInterfaceAlarm(interfaceName,
-                                                aThreshold.systemThreshold,
+                                                aQuota,
                                                 callback);
         return;
       }
 
       aCallback(null, true);
     });
   },
 
-  _updateThreshold: function _updateThreshold(aAlarm, aCallback) {
+  _getAlarmQuota: function _getAlarmQuota(aAlarm, aCallback) {
     let self = this;
     this.updateStats(aAlarm.networkId, function onStatsUpdated(aResult, aMessage) {
       self._db.getCurrentStats(self._networks[aAlarm.networkId].network,
                                aAlarm.startTime,
                                function onStatsFound(error, result) {
         if (error) {
           debug("Error getting stats for " +
                 JSON.stringify(self._networks[aAlarm.networkId]) + ": " + error);
           aCallback(error, result);
           return;
         }
 
-        if (!result) {
-          // There are no stats for the network of the alarm, set them to default 0 in
-          // order to be able to calculate the offset, systemThreshold and
-          // absoluteThreshold.
-          result = { rxTotalBytes:  0, txTotalBytes:  0,
-                     rxSystemBytes: 0, txSystemBytes: 0 };
-        }
-
-        let offset = aAlarm.threshold - result.rxTotalBytes - result.txTotalBytes;
+        let quota = aAlarm.absoluteThreshold - result.rxBytes - result.txBytes;
 
         // Alarm set to a threshold lower than current rx/tx bytes.
-        if (offset <= 0) {
+        if (quota <= 0) {
           aCallback("InvalidStateError", null);
           return;
         }
 
-        let threshold = {
-          systemThreshold: result.rxSystemBytes + result.txSystemBytes + offset,
-          absoluteThreshold: result.rxTotalBytes + result.txTotalBytes + offset
-        };
+        aAlarm.relativeThreshold = aAlarm.startTime
+                                 ? result.rxTotalBytes + result.txTotalBytes + quota
+                                 : aAlarm.absoluteThreshold;
 
-        aCallback(null, threshold);
+        aCallback(null, quota);
       });
     });
   },
 
   _fireAlarm: function _fireAlarm(aAlarm) {
     debug("Fire alarm");
 
     let self = this;
@@ -1091,15 +1082,15 @@ this.NetworkStatsService = {
 
   _fireSystemMessage: function _fireSystemMessage(aAlarm) {
     debug("Fire system message: " + JSON.stringify(aAlarm));
 
     let manifestURI = Services.io.newURI(aAlarm.manifestURL, null, null);
     let pageURI = Services.io.newURI(aAlarm.pageURL, null, null);
 
     let alarm = { "id":        aAlarm.id,
-                  "threshold": aAlarm.threshold,
+                  "threshold": aAlarm.absoluteThreshold,
                   "data":      aAlarm.data };
     messenger.sendMessage("networkstats-alarm", alarm, pageURI, manifestURI);
   }
 };
 
 NetworkStatsService.init();
--- a/dom/network/tests/unit_stats/test_networkstats_db.js
+++ b/dom/network/tests/unit_stats/test_networkstats_db.js
@@ -729,55 +729,60 @@ var networkWifi = '00';
 var networkMobile = '11';
 
 var examplePageURL = "http://example.com/index.html";
 var exampleManifestURL = "http://example.com/manifest.webapp";
 
 var testPageURL = "http://test.com/index.html";
 var testManifestURL = "http://test.com/manifest.webapp";
 
-var alarms = [{ id:             null,
-                networkId:      networkWifi,
-                threshold:      10000,
-                data:           {foo: "something"},
-                pageURL:        examplePageURL,
-                manifestURL:    exampleManifestURL },
-              { id:             null,
-                networkId:      networkWifi,
-                threshold:      1000,
-                data:           {foo: "else"},
-                pageURL:        examplePageURL,
-                manifestURL:    exampleManifestURL },
-              { id:             null,
-                networkId:      networkMobile,
-                threshold:      100,
-                data:           {foo: "to"},
-                pageURL:        examplePageURL,
-                manifestURL:    exampleManifestURL },
-              { id:             null,
-                networkId:      networkMobile,
-                threshold:      10,
-                data:           {foo: "test"},
-                pageURL:        testPageURL,
-                manifestURL:    testManifestURL }];
+var alarms = [{ id:                null,
+                networkId:         networkWifi,
+                absoluteThreshold: 10000,
+                relativeThreshold: 10000,
+                data:              {foo: "something"},
+                pageURL:           examplePageURL,
+                manifestURL:       exampleManifestURL },
+              { id:                null,
+                networkId:         networkWifi,
+                absoluteThreshold: 1000,
+                relativeThreshold: 1000,
+                data:              {foo: "else"},
+                pageURL:           examplePageURL,
+                manifestURL:       exampleManifestURL },
+              { id:                null,
+                networkId:         networkMobile,
+                absoluteThreshold: 100,
+                relativeThreshold: 100,
+                data:              {foo: "to"},
+                pageURL:           examplePageURL,
+                manifestURL:       exampleManifestURL },
+              { id:                null,
+                networkId:         networkMobile,
+                absoluteThreshold: 10,
+                relativeThreshold: 10,
+                data:              {foo: "test"},
+                pageURL:           testPageURL,
+                manifestURL:       testManifestURL }];
 
 var alarmsDbId = 1;
 
 add_test(function test_addAlarm() {
   // Add alarms[0] -> DB: [ alarms[0] (id: 1) ]
   // Check the insertion is OK.
   netStatsDb.addAlarm(alarms[0], function(error, result) {
     do_check_eq(error, null);
     alarmsDbId = result;
     netStatsDb.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, exampleManifestURL, function(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.length, 1);
       do_check_eq(result[0].id, alarmsDbId);
       do_check_eq(result[0].networkId, alarms[0].networkId);
-      do_check_eq(result[0].threshold, alarms[0].threshold);
+      do_check_eq(result[0].absoluteThreshold, alarms[0].absoluteThreshold);
+      do_check_eq(result[0].relativeThreshold, alarms[0].relativeThreshold);
       do_check_eq(result[0].data.foo, alarms[0].data.foo);
       run_next_test();
     });
   });
 });
 
 add_test(function test_getFirstAlarm() {
   // Add alarms[1] -> DB: [ alarms[0] (id: 1), alarms[1] (id: 2) ]
@@ -785,17 +790,18 @@ add_test(function test_getFirstAlarm() {
   alarmsDbId += 1;
   netStatsDb.addAlarm(alarms[1], function (error, result) {
     do_check_eq(error, null);
     do_check_eq(result, alarmsDbId);
     netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.id, alarmsDbId);
       do_check_eq(result.networkId, alarms[1].networkId);
-      do_check_eq(result.threshold, alarms[1].threshold);
+      do_check_eq(result.absoluteThreshold, alarms[1].absoluteThreshold);
+      do_check_eq(result.relativeThreshold, alarms[1].relativeThreshold);
       do_check_eq(result.data.foo, alarms[1].data.foo);
       do_check_eq(result.pageURL, alarms[1].pageURL);
       do_check_eq(result.manifestURL, alarms[1].manifestURL);
       run_next_test();
     });
   });
 });
 
@@ -803,17 +809,18 @@ add_test(function test_removeAlarm() {
   // Remove alarms[1] (id: 2) -> DB: [ alarms[0] (id: 1) ]
   // Check get first return alarms[0].
   netStatsDb.removeAlarm(alarmsDbId, alarms[0].manifestURL, function (error, result) {
     do_check_eq(error, null);
     netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.id, alarmsDbId - 1);
       do_check_eq(result.networkId, alarms[0].networkId);
-      do_check_eq(result.threshold, alarms[0].threshold);
+      do_check_eq(result.absoluteThreshold, alarms[0].absoluteThreshold);
+      do_check_eq(result.relativeThreshold, alarms[0].relativeThreshold);
       do_check_eq(result.data.foo, alarms[0].data.foo);
       do_check_eq(result.pageURL, alarms[0].pageURL);
       do_check_eq(result.manifestURL, alarms[0].manifestURL);
       run_next_test();
     });
   });
 });
 
@@ -892,17 +899,18 @@ add_test(function test_updateAlarm() {
   updatedAlarm.threshold = 10;
 
   netStatsDb.updateAlarm(updatedAlarm, function (error, result) {
     do_check_eq(error, null);
     netStatsDb.getFirstAlarm(networkWifi, function(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.id, updatedAlarm.id);
       do_check_eq(result.networkId, updatedAlarm.networkId);
-      do_check_eq(result.threshold, updatedAlarm.threshold);
+      do_check_eq(result.absoluteThreshold, updatedAlarm.absoluteThreshold);
+      do_check_eq(result.relativeThreshold, updatedAlarm.relativeThreshold);
       do_check_eq(result.data.foo, updatedAlarm.data.foo);
       do_check_eq(result.pageURL, updatedAlarm.pageURL);
       do_check_eq(result.manifestURL, updatedAlarm.manifestURL);
       run_next_test();
     });
   });
 });
 
--- a/dom/network/tests/unit_stats/test_networkstats_service.js
+++ b/dom/network/tests/unit_stats/test_networkstats_service.js
@@ -2,16 +2,18 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 const NETWORK_STATUS_READY   = 0;
 const NETWORK_STATUS_STANDBY = 1;
 const NETWORK_STATUS_AWAY    = 2;
 
+var wifiId = '00';
+
 function getNetworks(callback) {
   NetworkStatsService._db.getAvailableNetworks(function onGetNetworks(aError, aResult) {
     callback(aError, aResult);
   });
 }
 
 add_test(function test_clearDB() {
   getNetworks(function onGetNetworks(error, result) {
@@ -117,61 +119,87 @@ add_test(function test_updateStats_ok() 
 
 add_test(function test_updateStats_failure() {
   NetworkStatsService.updateStats(-1, function(success, msg){
     do_check_eq(success, false);
     run_next_test();
   });
 });
 
+// Define Mockup function to simulate a request to netd
+function MockNetdRequest(aCallback) {
+  var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  var event = {
+    notify: function (timer) {
+      aCallback();
+    }
+  };
+
+  timer.initWithCallback(event, 100, Ci.nsITimer.TYPE_ONE_SHOT);
+}
+
 add_test(function test_queue() {
-  // Fill networks with fake network interfaces
-  // to enable netd async requests
+
+  // Overwrite update function of NetworkStatsService to avoid netd errors due to use
+  // fake interfaces. First, original function is stored to restore it at the end of the
+  // test.
+  var updateFunctionBackup = NetworkStatsService.update;
+
+  NetworkStatsService.update = function update(aNetId, aCallback) {
+    MockNetdRequest(function () {
+      if (aCallback) {
+        aCallback(true, "ok");
+      }
+    });
+  };
+
+  // Fill networks with fake network interfaces to enable netd async requests.
   var network = {id: "1234", type: Ci.nsIDOMMozNetworkStatsManager.MOBILE};
   var netId1 = NetworkStatsService.getNetworkId(network.id, network.type);
   NetworkStatsService._networks[netId1] = { network: network,
                                             interfaceName: "net1" };
 
   network = {id: "5678", type: Ci.nsIDOMMozNetworkStatsManager.MOBILE};
   var netId2 = NetworkStatsService.getNetworkId(network.id, network.type);
   NetworkStatsService._networks[netId2] = { network: network,
                                             interfaceName: "net2" };
 
   NetworkStatsService.updateStats(netId1);
   NetworkStatsService.updateStats(netId2);
   do_check_eq(NetworkStatsService.updateQueue.length, 2);
   do_check_eq(NetworkStatsService.updateQueue[0].callbacks.length, 1);
 
+  var i = 0;
+  var updateCount = 0;
   var callback = function(success, msg) {
-    return;
+    i++;
+    if (i >= updateCount) {
+      NetworkStatsService.update = updateFunctionBackup;
+      run_next_test();
+    }
   };
 
   NetworkStatsService.updateStats(netId1, callback);
+  updateCount++;
   NetworkStatsService.updateStats(netId2, callback);
+  updateCount++;
 
   do_check_eq(NetworkStatsService.updateQueue.length, 2);
   do_check_eq(NetworkStatsService.updateQueue[0].callbacks.length, 2);
   do_check_eq(NetworkStatsService.updateQueue[0].callbacks[0], null);
   do_check_neq(NetworkStatsService.updateQueue[0].callbacks[1], null);
-
-  // Clear queue because in test environment requests for mobile networks
-  // can not be handled.
-  NetworkStatsService.updateQueue =  [];
-  run_next_test();
 });
 
-var wifiId = '00';
-
-add_test(function test_updateThreshold() {
-  let alarm = { networkId: wifiId, threshold: 10000 };
+add_test(function test_getAlarmQuota() {
+  let alarm = { networkId: wifiId, absoluteThreshold: 10000 };
 
-  NetworkStatsService._updateThreshold(alarm, function onSet(error, threshold){
+  NetworkStatsService._getAlarmQuota(alarm, function onSet(error, quota){
     do_check_eq(error, null);
-    do_check_neq(threshold.systemThreshold, undefined);
-    do_check_neq(threshold.absoluteThreshold, undefined);
+    do_check_neq(quota, undefined);
+    do_check_eq(alarm.absoluteThreshold, alarm.relativeThreshold);
     run_next_test();
   });
 });
 
 var testPageURL = "http://test.com";
 var testManifestURL = "http://test.com/manifest.webapp";
 
 add_test(function test_setAlarm() {
@@ -217,16 +245,19 @@ add_test(function test_fireAlarm() {
                 threshold: 10000,
                 absoluteThreshold: null,
                 alarmStart: null,
                 alarmEnd: null,
                 data: null,
                 pageURL: testPageURL,
                 manifestURL: testManifestURL };
 
+  // Set wifi status to standby to avoid connecting to netd when adding an alarm.
+  NetworkStatsService._networks[wifiId].status = NETWORK_STATUS_STANDBY;
+
   NetworkStatsService._db.addAlarm(alarm, function addSuccessCb(error, newId) {
     NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
                                       testManifestURL, function onGet(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.length, 1);
 
       // Result of getAlarms is based on expected child's data format, so
       // some changes are needed to be able to use it.
--- a/gfx/layers/LayerScope.cpp
+++ b/gfx/layers/LayerScope.cpp
@@ -5,16 +5,17 @@
 
 /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
 #include "LayerScope.h"
 
 #include "Composer2D.h"
 #include "Effects.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Endian.h"
 #include "TexturePoolOGL.h"
 #include "mozilla/layers/TextureHostOGL.h"
 
 #include "gfxColor.h"
 #include "gfxContext.h"
 #include "gfxUtils.h"
 #include "gfxPlatform.h"
 #include "nsIWidget.h"
@@ -24,21 +25,26 @@
 #include "GLReadTexImageHelper.h"
 
 #include "nsIServiceManager.h"
 #include "nsIConsoleService.h"
 
 #include <memory>
 #include "mozilla/Compression.h"
 #include "mozilla/LinkedList.h"
+#include "mozilla/Base64.h"
+#include "mozilla/SHA1.h"
+#include "mozilla/StaticPtr.h"
 #include "nsThreadUtils.h"
 #include "nsISocketTransport.h"
 #include "nsIServerSocket.h"
+#include "nsReadLine.h"
 #include "nsNetCID.h"
 #include "nsIOutputStream.h"
+#include "nsIAsyncInputStream.h"
 #include "nsIEventTarget.h"
 #include "nsProxyRelease.h"
 
 #ifdef __GNUC__
 #define PACKED_STRUCT __attribute__((packed))
 #else
 #define PACKED_STRUCT
 #endif
@@ -47,23 +53,277 @@ namespace mozilla {
 namespace layers {
 
 using namespace mozilla::Compression;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 using namespace mozilla;
 
 class DebugDataSender;
+class DebugGLData;
 
-static bool gDebugConnected = false;
-static nsCOMPtr<nsIServerSocket> gDebugServerSocket;
-static nsCOMPtr<nsIThread> gDebugSenderThread;
-static nsCOMPtr<nsISocketTransport> gDebugSenderTransport;
-static nsCOMPtr<nsIOutputStream> gDebugStream;
-static nsCOMPtr<DebugDataSender> gCurrentSender;
+/* This class handle websocket protocol which included
+ * handshake and data frame's header
+ */
+class LayerScopeWebSocketHandler : public nsIInputStreamCallback {
+public:
+    NS_DECL_THREADSAFE_ISUPPORTS
+
+    enum SocketStateType {
+        NoHandshake,
+        HandshakeSuccess,
+        HandshakeFailed
+    };
+
+    LayerScopeWebSocketHandler()
+        : mState(NoHandshake)
+    { }
+
+    virtual ~LayerScopeWebSocketHandler()
+    {
+        if (mTransport) {
+            mTransport->Close(NS_OK);
+        }
+    }
+
+    void OpenStream(nsISocketTransport* aTransport) {
+        MOZ_ASSERT(aTransport);
+
+        mTransport = aTransport;
+        mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
+                                     0,
+                                     0,
+                                     getter_AddRefs(mOutputStream));
+
+        nsCOMPtr<nsIInputStream> debugInputStream;
+        mTransport->OpenInputStream(0,
+                                    0,
+                                    0,
+                                    getter_AddRefs(debugInputStream));
+        mInputStream = do_QueryInterface(debugInputStream);
+        mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
+    }
+
+    bool WriteToStream(void *ptr, uint32_t size) {
+        if (mState == NoHandshake) {
+            // Not yet handshake, just return true in case of
+            // LayerScope remove this handle
+            return true;
+        } else if (mState == HandshakeFailed) {
+            return false;
+        }
+
+        // Generate WebSocket header
+        uint8_t wsHeader[10];
+        int wsHeaderSize = 0;
+        const uint8_t opcode = 0x2;
+        wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
+        if (size <= 125) {
+            wsHeaderSize = 2;
+            wsHeader[1] = size;
+        } else if (size < 65536) {
+            wsHeaderSize = 4;
+            wsHeader[1] = 0x7E;
+            NetworkEndian::writeUint16(wsHeader + 2, size);
+        } else {
+            wsHeaderSize = 10;
+            wsHeader[1] = 0x7F;
+            NetworkEndian::writeUint64(wsHeader + 2, size);
+        }
+
+        // Send WebSocket header
+        nsresult rv;
+        uint32_t cnt;
+        rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
+                                 wsHeaderSize, &cnt);
+        if (NS_FAILED(rv))
+            return false;
+
+        uint32_t written = 0;
+        while (written < size) {
+            uint32_t cnt;
+            rv = mOutputStream->Write(reinterpret_cast<char*>(ptr) + written,
+                                     size - written, &cnt);
+            if (NS_FAILED(rv))
+                return false;
+
+            written += cnt;
+        }
+
+        return true;
+    }
+
+    // nsIInputStreamCallback
+    NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *stream) MOZ_OVERRIDE
+    {
+        nsTArray<nsCString> protocolString;
+        ReadInputStreamData(protocolString);
+
+        if (WebSocketHandshake(protocolString)) {
+            mState = HandshakeSuccess;
+        } else {
+            mState = HandshakeFailed;
+        }
+        return NS_OK;
+    }
+private:
+    void ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
+    {
+        nsLineBuffer<char> lineBuffer;
+        nsCString line;
+        bool more = true;
+        do {
+            NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
+
+            if (line.Length() > 0) {
+                aProtocolString.AppendElement(line);
+            }
+        } while (more && line.Length() > 0);
+    }
+
+    bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
+    {
+        nsresult rv;
+        bool isWebSocket = false;
+        nsCString version;
+        nsCString wsKey;
+        nsCString protocol;
+
+        // Validate WebSocket client request.
+        if (aProtocolString.Length() == 0)
+            return false;
+
+        // Check that the HTTP method is GET
+        const char* HTTP_METHOD = "GET ";
+        if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
+            return false;
+        }
+
+        for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
+            const char* line = aProtocolString[i].get();
+            const char* prop_pos = strchr(line, ':');
+            if (prop_pos != nullptr) {
+                nsCString key(line, prop_pos - line);
+                nsCString value(prop_pos + 2);
+                if (key.EqualsIgnoreCase("upgrade") &&
+                    value.EqualsIgnoreCase("websocket")) {
+                    isWebSocket = true;
+                } else if (key.EqualsIgnoreCase("sec-websocket-version")) {
+                    version = value;
+                } else if (key.EqualsIgnoreCase("sec-websocket-key")) {
+                    wsKey = value;
+                } else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
+                    protocol = value;
+                }
+            }
+        }
+
+        if (!isWebSocket) {
+            return false;
+        }
+
+        if (!(version.Equals("7") || version.Equals("8") || version.Equals("13"))) {
+            return false;
+        }
+
+        if (!(protocol.EqualsIgnoreCase("binary"))) {
+            return false;
+        }
+
+        // Client request is valid. Start to generate and send server response.
+        nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
+        nsAutoCString res;
+        SHA1Sum sha1;
+        nsCString combined(wsKey + guid);
+        sha1.update(combined.get(), combined.Length());
+        uint8_t digest[SHA1Sum::HashSize]; // SHA1 digests are 20 bytes long.
+        sha1.finish(digest);
+        nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::HashSize);
+        Base64Encode(newString, res);
+
+        nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
+        response.Append("Upgrade: websocket\r\n");
+        response.Append("Connection: Upgrade\r\n");
+        response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
+        response.Append("Sec-WebSocket-Protocol: binary\r\n\r\n");
+        uint32_t written = 0;
+        uint32_t size = response.Length();
+        while (written < size) {
+            uint32_t cnt;
+            rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
+                                     size - written, &cnt);
+            if (NS_FAILED(rv))
+                return false;
+
+            written += cnt;
+        }
+        mOutputStream->Flush();
+
+        return true;
+    }
+
+    nsCOMPtr<nsIOutputStream> mOutputStream;
+    nsCOMPtr<nsIAsyncInputStream> mInputStream;
+    nsCOMPtr<nsISocketTransport> mTransport;
+    SocketStateType mState;
+};
+
+NS_IMPL_ISUPPORTS1(LayerScopeWebSocketHandler, nsIInputStreamCallback);
+
+class LayerScopeWebSocketManager {
+public:
+    LayerScopeWebSocketManager();
+    ~LayerScopeWebSocketManager();
+
+    void AddConnection(nsISocketTransport *aTransport)
+    {
+        MOZ_ASSERT(aTransport);
+        nsRefPtr<LayerScopeWebSocketHandler> temp = new LayerScopeWebSocketHandler();
+        temp->OpenStream(aTransport);
+        mHandlers.AppendElement(temp.get());
+    }
+
+    void RemoveConnection(uint32_t aIndex)
+    {
+        MOZ_ASSERT(aIndex < mHandlers.Length());
+        mHandlers.RemoveElementAt(aIndex);
+    }
+
+    void RemoveAllConnections()
+    {
+        mHandlers.Clear();
+    }
+
+    bool WriteAll(void *ptr, uint32_t size)
+    {
+        for (int32_t i = mHandlers.Length() - 1; i >= 0; --i) {
+            if (!mHandlers[i]->WriteToStream(ptr, size)) {
+                // Send failed, remove this handler
+                RemoveConnection(i);
+            }
+        }
+
+        return true;
+    }
+
+    bool IsConnected()
+    {
+        return (mHandlers.Length() != 0) ? true : false;
+    }
+
+    void AppendDebugData(DebugGLData *aDebugData);
+    void DispatchDebugData();
+private:
+    nsTArray<nsRefPtr<LayerScopeWebSocketHandler> > mHandlers;
+    nsCOMPtr<nsIThread> mDebugSenderThread;
+    nsCOMPtr<DebugDataSender> mCurrentSender;
+    nsCOMPtr<nsIServerSocket> mServerSocket;
+};
+
+static StaticAutoPtr<LayerScopeWebSocketManager> gLayerScopeWebSocketManager;
 
 class DebugGLData : public LinkedListElement<DebugGLData> {
 public:
     typedef enum {
         FrameStart,
         FrameEnd,
         TextureData,
         ColorData
@@ -106,29 +366,19 @@ public:
         packet.type = mDataType;
         packet.ptr = static_cast<uint64_t>(mContextAddress);
         packet.value = mValue;
 
         return WriteToStream(&packet, sizeof(packet));
     }
 
     static bool WriteToStream(void *ptr, uint32_t size) {
-        uint32_t written = 0;
-        nsresult rv;
-        while (written < size) {
-            uint32_t cnt;
-            rv = gDebugStream->Write(reinterpret_cast<char*>(ptr) + written,
-                                     size - written, &cnt);
-            if (NS_FAILED(rv))
-                return false;
-
-            written += cnt;
-        }
-
-        return true;
+        if (!gLayerScopeWebSocketManager)
+            return true;
+        return gLayerScopeWebSocketManager->WriteAll(ptr, size);
     }
 
 protected:
     DataType mDataType;
     intptr_t mContextAddress;
     int64_t mValue;
 
 public:
@@ -279,51 +529,44 @@ protected:
     void *mLayerRef;
     uint32_t mColor;
     nsIntSize mSize;
 };
 
 static bool
 CheckSender()
 {
-    if (!gDebugConnected)
+    if (!gLayerScopeWebSocketManager)
         return false;
 
-    // At some point we may want to support sending
-    // data in between frames.
-#if 1
-    if (!gCurrentSender)
+    if (!gLayerScopeWebSocketManager->IsConnected())
         return false;
-#else
-    if (!gCurrentSender)
-        gCurrentSender = new DebugDataSender();
-#endif
 
     return true;
 }
 
-
 class DebugListener : public nsIServerSocketListener
 {
 public:
 
     NS_DECL_THREADSAFE_ISUPPORTS
 
     DebugListener() { }
     virtual ~DebugListener() { }
 
     /* nsIServerSocketListener */
 
     NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
                                    nsISocketTransport *aTransport)
     {
+        if (!gLayerScopeWebSocketManager)
+            return NS_OK;
+
         printf_stderr("*** LayerScope: Accepted connection\n");
-        gDebugConnected = true;
-        gDebugSenderTransport = aTransport;
-        aTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(gDebugStream));
+        gLayerScopeWebSocketManager->AddConnection(aTransport);
         return NS_OK;
     }
 
     NS_IMETHODIMP OnStopListening(nsIServerSocket *aServ,
                                   nsresult aStatus)
     {
         return NS_OK;
     }
@@ -363,38 +606,28 @@ public:
     }
 
     /* nsIRunnable impl; send the data */
 
     NS_IMETHODIMP Run() {
         DebugGLData *d;
         nsresult rv = NS_OK;
 
-        // If we got closed while trying to write some stuff earlier, just
-        // throw away everything.
-        if (!gDebugStream) {
-            Cleanup();
-            return NS_OK;
-        }
-
         while ((d = mList->popFirst()) != nullptr) {
             std::auto_ptr<DebugGLData> cleaner(d);
             if (!d->Write()) {
                 rv = NS_ERROR_FAILURE;
                 break;
             }
         }
 
         Cleanup();
 
         if (NS_FAILED(rv)) {
-            gDebugSenderTransport->Close(rv);
-            gDebugConnected = false;
-            gDebugStream = nullptr;
-            gDebugServerSocket = nullptr;
+            LayerScope::DestroyServerSocket();
         }
 
         return NS_OK;
     }
 
 protected:
     LinkedList<DebugGLData> *mList;
 };
@@ -403,72 +636,66 @@ NS_IMPL_ISUPPORTS1(DebugDataSender, nsIR
 
 void
 LayerScope::CreateServerSocket()
 {
     if (!Preferences::GetBool("gfx.layerscope.enabled", false)) {
         return;
     }
 
-    if (!gDebugSenderThread) {
-        NS_NewThread(getter_AddRefs(gDebugSenderThread));
-    }
-
-    if (!gDebugServerSocket) {
-        gDebugServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
-        int port = Preferences::GetInt("gfx.layerscope.port", 23456);
-        gDebugServerSocket->Init(port, false, -1);
-        gDebugServerSocket->AsyncListen(new DebugListener);
+    if (!gLayerScopeWebSocketManager) {
+        gLayerScopeWebSocketManager = new LayerScopeWebSocketManager();
     }
 }
 
 void
 LayerScope::DestroyServerSocket()
 {
-    gDebugConnected = false;
-    gDebugStream = nullptr;
-    gDebugServerSocket = nullptr;
+    if (gLayerScopeWebSocketManager) {
+        gLayerScopeWebSocketManager->RemoveAllConnections();
+    }
 }
 
 void
 LayerScope::BeginFrame(GLContext* aGLContext, int64_t aFrameStamp)
 {
-    if (!gDebugConnected)
+    if (!gLayerScopeWebSocketManager)
+        return;
+
+    if (!gLayerScopeWebSocketManager->IsConnected())
         return;
 
 #if 0
     // if we're sending data in between frames, flush the list down the socket,
     // and start a new one
     if (gCurrentSender) {
         gDebugSenderThread->Dispatch(gCurrentSender, NS_DISPATCH_NORMAL);
     }
 #endif
 
-    gCurrentSender = new DebugDataSender();
-    gCurrentSender->Append(new DebugGLData(DebugGLData::FrameStart, aGLContext, aFrameStamp));
+    gLayerScopeWebSocketManager->AppendDebugData(new DebugGLData(DebugGLData::FrameStart, aGLContext, aFrameStamp));
 }
 
 void
 LayerScope::EndFrame(GLContext* aGLContext)
 {
     if (!CheckSender())
         return;
 
-    gCurrentSender->Append(new DebugGLData(DebugGLData::FrameEnd, aGLContext));
-    gDebugSenderThread->Dispatch(gCurrentSender, NS_DISPATCH_NORMAL);
-    gCurrentSender = nullptr;
+    gLayerScopeWebSocketManager->AppendDebugData(new DebugGLData(DebugGLData::FrameEnd, aGLContext));
+    gLayerScopeWebSocketManager->DispatchDebugData();
 }
 
 static void
 SendColor(void* aLayerRef, const gfxRGBA& aColor, int aWidth, int aHeight)
 {
     if (!CheckSender())
         return;
 
-    gCurrentSender->Append(
+    gLayerScopeWebSocketManager->AppendDebugData(
         new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
 }
 
 static void
 SendTextureSource(GLContext* aGLContext,
                   void* aLayerRef,
                   TextureSourceOGL* aSource,
                   bool aFlipY)
@@ -495,17 +722,17 @@ SendTextureSource(GLContext* aGLContext,
 
     // By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
     // texture correctly. textureId is used for tracking in DebugGLTextureData.
     nsRefPtr<gfxImageSurface> img =
         aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
                                                        gfxIntSize(size.width, size.height),
                                                        shaderProgram, aFlipY);
 
-    gCurrentSender->Append(
+    gLayerScopeWebSocketManager->AppendDebugData(
         new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
                                textureId, img));
 }
 
 static void
 SendTexturedEffect(GLContext* aGLContext,
                    void* aLayerRef,
                    const TexturedEffect* aEffect)
@@ -580,10 +807,39 @@ LayerScope::SendEffectChain(GLContext* a
     default:
         break;
     }
 
     //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EFFECT_MASK];
     // TODO:
 }
 
+LayerScopeWebSocketManager::LayerScopeWebSocketManager()
+{
+    NS_NewThread(getter_AddRefs(mDebugSenderThread));
+
+    mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
+    int port = Preferences::GetInt("gfx.layerscope.port", 23456);
+    mServerSocket->Init(port, false, -1);
+    mServerSocket->AsyncListen(new DebugListener);
+}
+
+LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
+{
+}
+
+void LayerScopeWebSocketManager::AppendDebugData(DebugGLData *aDebugData)
+{
+    if (!mCurrentSender) {
+        mCurrentSender = new DebugDataSender();
+    }
+
+    mCurrentSender->Append(aDebugData);
+}
+
+void LayerScopeWebSocketManager::DispatchDebugData()
+{
+    mDebugSenderThread->Dispatch(mCurrentSender, NS_DISPATCH_NORMAL);
+    mCurrentSender = nullptr;
+}
+
 } /* layers */
 } /* mozilla */
--- a/mozglue/build/Nuwa.cpp
+++ b/mozglue/build/Nuwa.cpp
@@ -10,16 +10,17 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <poll.h>
 #include <pthread.h>
 #include <alloca.h>
 #include <sys/epoll.h>
+#include <sys/mman.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
 #include <vector>
 
 #include "mozilla/LinkedList.h"
@@ -136,17 +137,19 @@ typedef std::vector<std::pair<pthread_ke
 TLSInfoList;
 
 /**
  * The stack size is chosen carefully so the frozen threads doesn't consume too
  * much memory in the Nuwa process. The threads shouldn't run deep recursive
  * methods or do large allocations on the stack to avoid stack overflow.
  */
 #ifndef NUWA_STACK_SIZE
-#define NUWA_STACK_SIZE (1024 * 32)
+#define PAGE_SIZE 4096
+#define PAGE_ALIGN_MASK 0xfffff000
+#define NUWA_STACK_SIZE (1024 * 128)
 #endif
 
 #define NATIVE_THREAD_NAME_LENGTH 16
 
 struct thread_info : public mozilla::LinkedListElement<thread_info> {
   pthread_t origThreadID;
   pthread_t recreatedThreadID;
   pthread_attr_t threadAttr;
@@ -484,17 +487,28 @@ thread_info_new(void) {
   /* link tinfo to sAllThreads */
   thread_info_t *tinfo = new thread_info_t();
   tinfo->flags = 0;
   tinfo->recrFunc = nullptr;
   tinfo->recrArg = nullptr;
   tinfo->recreatedThreadID = 0;
   tinfo->recreatedNativeThreadID = 0;
   tinfo->reacquireMutex = nullptr;
-  tinfo->stk = malloc(NUWA_STACK_SIZE);
+  tinfo->stk = malloc(NUWA_STACK_SIZE + PAGE_SIZE);
+
+  // We use a smaller stack size. Add protection to stack overflow: mprotect()
+  // stack top (the page at the lowest address) so we crash instead of corrupt
+  // other content that is malloc()'d.
+  unsigned long long pageGuard = ((unsigned long long)tinfo->stk);
+  pageGuard &= PAGE_ALIGN_MASK;
+  if (pageGuard != (unsigned long long) tinfo->stk) {
+    pageGuard += PAGE_SIZE; // Round up to be page-aligned.
+  }
+  mprotect((void*)pageGuard, PAGE_SIZE, PROT_READ);
+
   pthread_attr_init(&tinfo->threadAttr);
 
   REAL(pthread_mutex_lock)(&sThreadCountLock);
   // Insert to the tail.
   sAllThreads.insertBack(tinfo);
 
   sThreadCount++;
   pthread_cond_signal(&sThreadChangeCond);