Merge b2g-inbound to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 07 Aug 2014 18:06:14 -0700
changeset 198445 18f408a5984e13d56c73310fb4663f97464bd1c7
parent 198397 bd44d84142e86ba844fa01f498d080b0f7c7a395 (current diff)
parent 198444 cbe4158e14b38a35ec889113b19bf2c555855379 (diff)
child 198462 964310cfef76ccf350f33f3186aaebd44dd117b0
child 198500 d382d31075bee8cd4b4d6dac4fd1ee6dcb453afa
child 198552 c576aa671d07789d4951c0edc52a2b41fc4bba12
push id27271
push userkwierso@gmail.com
push dateFri, 08 Aug 2014 01:06:28 +0000
treeherdermozilla-central@18f408a5984e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.0a1
first release with
nightly linux32
18f408a5984e / 34.0a1 / 20140808030201 / files
nightly linux64
18f408a5984e / 34.0a1 / 20140808030201 / files
nightly mac
18f408a5984e / 34.0a1 / 20140808030201 / files
nightly win32
18f408a5984e / 34.0a1 / 20140808030201 / files
nightly win64
18f408a5984e / 34.0a1 / 20140808030201 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b2g-inbound to m-c a=merge
--- a/b2g/chrome/content/devtools.js
+++ b/b2g/chrome/content/devtools.js
@@ -549,17 +549,17 @@ let memoryWatcher = {
         // TODO Also count images size (bug #976007).
 
         target.update({name: 'memory', value: total});
       }, err => {
         console.error(err);
       });
     }
 
-    let timer = setTimeout(() => this.measure(target), 300);
+    let timer = setTimeout(() => this.measure(target), 500);
     this._timers.set(target, timer);
   },
 
   trackTarget: function mw_trackTarget(target) {
     target.register('uss');
     target.register('memory');
     this._fronts.set(target, MemoryFront(this._client, target.actor));
     if (this._active) {
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,18 +12,18 @@
   <!--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="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <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="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,19 +10,19 @@
   <!--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="7945ca73e687be5edbc7b928dc7fe3a208242144">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,18 +12,18 @@
   <!--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="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "d581b7149d25fcff1786f914ed6b83d499999645", 
+    "revision": "41b3413a893fef684b380bb344f9d4a5f491f858", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- 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"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,18 +10,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <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"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,18 +12,18 @@
   <!--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="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <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="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="54c3c19d439f7dbafda5c6cc3b4850b545a068ba"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6822004d07064ea3ebbc0c94cd2e15be6a02069d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c45627132ae7f00026e361a14d5d084a1236af24"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b0b5df8c194be48fc8a2f8d1c4310c36388eec9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <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"/>
--- a/dom/mobilemessage/src/gonk/MobileMessageDB.jsm
+++ b/dom/mobilemessage/src/gonk/MobileMessageDB.jsm
@@ -93,23 +93,16 @@ MobileMessageDB.prototype = {
   db: null,
 
   /**
    * Last sms/mms object store key value in the database.
    */
   lastMessageId: 0,
 
   /**
-   * An optional hook to check if device storage is full.
-   *
-   * @return true if full.
-   */
-  isDiskFull: null,
-
-  /**
    * Prepare the database. This may include opening the database and upgrading
    * it to the latest schema version.
    *
    * @param callback
    *        Function that takes an error and db argument. It is called when
    *        the database is ready to use or if an error occurs while preparing
    *        the database.
    *
@@ -261,17 +254,17 @@ MobileMessageDB.prototype = {
             callback(Cr.NS_ERROR_FAILURE, null);
             break;
         }
       }
 
       update(currentVersion);
     };
     request.onerror = function(event) {
-      //TODO look at event.target.Code and change error constant accordingly
+      // TODO look at event.target.Code and change error constant accordingly.
       if (DEBUG) debug("Error opening database!");
       callback(Cr.NS_ERROR_FAILURE, null);
     };
     request.onblocked = function(event) {
       if (DEBUG) debug("Opening database request is blocked.");
       callback(Cr.NS_ERROR_FAILURE, null);
     };
   },
@@ -289,36 +282,31 @@ MobileMessageDB.prototype = {
    */
   newTxn: function(txn_type, callback, storeNames) {
     if (!storeNames) {
       storeNames = [MESSAGE_STORE_NAME];
     }
     if (DEBUG) debug("Opening transaction for object stores: " + storeNames);
     let self = this;
     this.ensureDB(function(error, db) {
-      if (!error &&
-          txn_type === READ_WRITE &&
-          self.isDiskFull && self.isDiskFull()) {
-        error = Cr.NS_ERROR_FILE_NO_DEVICE_SPACE;
-      }
       if (error) {
         if (DEBUG) debug("Could not open database: " + error);
         callback(error);
         return;
       }
       let txn = db.transaction(storeNames, txn_type);
       if (DEBUG) debug("Started transaction " + txn + " of type " + txn_type);
       if (DEBUG) {
-        txn.oncomplete = function oncomplete(event) {
+        txn.oncomplete = function(event) {
           debug("Transaction " + txn + " completed.");
         };
-        txn.onerror = function onerror(event) {
-          //TODO check event.target.errorCode and show an appropiate error
-          //     message according to it.
-          debug("Error occurred during transaction: " + event.target.errorCode);
+        txn.onerror = function(event) {
+          // TODO check event.target.error.name and show an appropiate error
+          // message according to it.
+          debug("Error occurred during transaction: " + event.target.error.name);
         };
       }
       let stores;
       if (storeNames.length == 1) {
         if (DEBUG) debug("Retrieving object store " + storeNames[0]);
         stores = txn.objectStore(storeNames[0]);
       } else {
         stores = [];
@@ -360,32 +348,32 @@ MobileMessageDB.prototype = {
         txn.oncomplete = function() {
           aCallback(null);
         };
       }
 
       // In order to get the highest key value, we open a key cursor in reverse
       // order and get only the first pointed value.
       let request = messageStore.openCursor(null, PREV);
-      request.onsuccess = function onsuccess(event) {
+      request.onsuccess = function(event) {
         let cursor = event.target.result;
         if (!cursor) {
           if (DEBUG) {
             debug("Could not get the last key from mobile message database. " +
                   "Probably empty database");
           }
           return;
         }
         self.lastMessageId = cursor.key || 0;
         if (DEBUG) debug("Last assigned message ID was " + self.lastMessageId);
       };
-      request.onerror = function onerror(event) {
+      request.onerror = function(event) {
         if (DEBUG) {
           debug("Could not get the last key from mobile message database " +
-                event.target.errorCode);
+                event.target.error.name);
         }
       };
     });
   },
 
   close: function() {
     if (!this.db) {
       return;
@@ -838,17 +826,17 @@ MobileMessageDB.prototype = {
         return;
       }
 
       let threadRecord = cursor.value;
       let lastMessageId = threadRecord.lastMessageId;
       let messageStore = transaction.objectStore(MESSAGE_STORE_NAME);
       let request = messageStore.mozGetAll(lastMessageId);
 
-      request.onsuccess = function onsuccess() {
+      request.onsuccess = function() {
         let messageRecord = request.result[0];
         if (!messageRecord) {
           if (DEBUG) debug("Message ID " + lastMessageId + " not found");
           return;
         }
         if (messageRecord.id != lastMessageId) {
           if (DEBUG) {
             debug("Requested message ID (" + lastMessageId + ") is different from" +
@@ -856,20 +844,20 @@ MobileMessageDB.prototype = {
           }
           return;
         }
         threadRecord.lastMessageType = messageRecord.type;
         cursor.update(threadRecord);
         cursor.continue();
       };
 
-      request.onerror = function onerror(event) {
+      request.onerror = function(event) {
         if (DEBUG) {
           if (event.target) {
-            debug("Caught error on transaction", event.target.errorCode);
+            debug("Caught error on transaction", event.target.error.name);
           }
         }
         cursor.continue();
       };
     };
   },
 
   /**
@@ -2063,18 +2051,21 @@ MobileMessageDB.prototype = {
         return;
       }
 
       let capture = {};
       aTransaction.oncomplete = function(event) {
         notifyResult(Cr.NS_OK, capture.messageRecord);
       };
       aTransaction.onabort = function(event) {
-        // TODO bug 832140 check event.target.errorCode
-        notifyResult(Cr.NS_ERROR_FAILURE, null);
+        if (DEBUG) debug("transaction abort due to " + event.target.error.name);
+        let error = (event.target.error.name === 'QuotaExceededError')
+                    ? Cr.NS_ERROR_FILE_NO_DEVICE_SPACE
+                    : Cr.NS_ERROR_FAILURE;
+        notifyResult(error, null);
       };
 
       aFunc(capture, aStores);
     }, aStoreNames);
   },
 
   saveRecord: function(aMessageRecord, aThreadParticipants, aCallback) {
     if (DEBUG) debug("Going to store " + JSON.stringify(aMessageRecord));
@@ -2092,26 +2083,29 @@ MobileMessageDB.prototype = {
 
       if (error) {
         notifyResult(error, null);
         return;
       }
 
       let deletedInfo = { messageIds: [], threadIds: [] };
 
-      txn.oncomplete = function oncomplete(event) {
+      txn.oncomplete = function(event) {
         if (aMessageRecord.id > self.lastMessageId) {
           self.lastMessageId = aMessageRecord.id;
         }
         notifyResult(Cr.NS_OK, aMessageRecord);
         self.notifyDeletedInfo(deletedInfo);
       };
-      txn.onabort = function onabort(event) {
-        // TODO bug 832140 check event.target.errorCode
-        notifyResult(Cr.NS_ERROR_FAILURE, null);
+      txn.onabort = function(event) {
+        if (DEBUG) debug("transaction abort due to " + event.target.error.name);
+        let error = (event.target.error.name === 'QuotaExceededError')
+                    ? Cr.NS_ERROR_FILE_NO_DEVICE_SPACE
+                    : Cr.NS_ERROR_FAILURE;
+        notifyResult(error, null);
       };
 
       let messageStore = stores[0];
       let participantStore = stores[1];
       let threadStore = stores[2];
       self.replaceShortMessageOnSave(txn, messageStore, participantStore,
                                      threadStore, aMessageRecord,
                                      aThreadParticipants, deletedInfo);
@@ -2157,17 +2151,17 @@ MobileMessageDB.prototype = {
                             aThreadStore, aMessageRecord, aThreadParticipants,
                             aDeletedInfo);
         return;
       }
 
       let participantId = participantRecord.id;
       let range = IDBKeyRange.bound([participantId, 0], [participantId, ""]);
       let request = aMessageStore.index("participantIds").openCursor(range);
-      request.onsuccess = function onsuccess(event) {
+      request.onsuccess = function(event) {
         let cursor = event.target.result;
         if (!cursor) {
           self.realSaveRecord(aTransaction, aMessageStore, aParticipantStore,
                               aThreadStore, aMessageRecord, aThreadParticipants,
                               aDeletedInfo);
           return;
         }
 
@@ -2232,18 +2226,18 @@ MobileMessageDB.prototype = {
         // message record, we need to retrieve it before overriding it.
         aMessageStore.get(aMessageRecord.id).onsuccess = function(event) {
           let oldMessageRecord = event.target.result;
           aMessageStore.put(aMessageRecord);
           if (oldMessageRecord) {
             self.updateThreadByMessageChange(aMessageStore,
                                              aThreadStore,
                                              oldMessageRecord.threadId,
-                                             aMessageRecord.id,
-                                             oldMessageRecord.read,
+                                             [aMessageRecord.id],
+                                             oldMessageRecord.read ? 0 : 1,
                                              aDeletedInfo);
           }
         };
       };
 
       if (threadRecord) {
         let needsUpdate = false;
 
@@ -2356,17 +2350,17 @@ MobileMessageDB.prototype = {
     this.newTxnWithCallback(callback, function(aCapture, aMessageStore) {
       let getRequest;
       if (type === "messageId") {
         getRequest = aMessageStore.get(id);
       } else if (type === "envelopeId") {
         getRequest = aMessageStore.index("envelopeId").get(id);
       }
 
-      getRequest.onsuccess = function onsuccess(event) {
+      getRequest.onsuccess = function(event) {
         let messageRecord = event.target.result;
         if (!messageRecord) {
           if (DEBUG) debug("type = " + id + " is not found");
           throw Cr.NS_ERROR_FAILURE;
         }
 
         let isRecordUpdated = false;
 
@@ -2484,37 +2478,42 @@ MobileMessageDB.prototype = {
         return {
           address: aAddress,
           type: MMS.Address.resolveType(aAddress)
         };
       });
   },
 
   updateThreadByMessageChange: function(messageStore, threadStore, threadId,
-                                        messageId, messageRead, deletedInfo) {
+                                        removedMsgIds, ignoredUnreadCount, deletedInfo) {
     let self = this;
     threadStore.get(threadId).onsuccess = function(event) {
       // This must exist.
       let threadRecord = event.target.result;
       if (DEBUG) debug("Updating thread record " + JSON.stringify(threadRecord));
 
-      if (!messageRead) {
-        threadRecord.unreadCount--;
+      if (ignoredUnreadCount > 0) {
+        if (DEBUG) {
+          debug("Updating unread count : " + threadRecord.unreadCount +
+                " -> " + (threadRecord.unreadCount - ignoredUnreadCount));
+        }
+        threadRecord.unreadCount -= ignoredUnreadCount;
       }
 
-      if (threadRecord.lastMessageId == messageId) {
+      if (removedMsgIds.indexOf(threadRecord.lastMessageId) >= 0) {
+        if (DEBUG) debug("MRU entry was deleted.");
         // Check most recent sender/receiver.
         let range = IDBKeyRange.bound([threadId, 0], [threadId, ""]);
         let request = messageStore.index("threadId")
                                   .openCursor(range, PREV);
         request.onsuccess = function(event) {
           let cursor = event.target.result;
           if (!cursor) {
             if (DEBUG) {
-              debug("Deleting mru entry for thread id " + threadId);
+              debug("All messages were deleted. Delete this thread.");
             }
             threadStore.delete(threadId);
             if (deletedInfo) {
               deletedInfo.threadIds.push(threadId);
             }
             return;
           }
 
@@ -2529,23 +2528,18 @@ MobileMessageDB.prototype = {
           threadRecord.body = nextMsg.body;
           threadRecord.lastMessageType = nextMsg.type;
           if (DEBUG) {
             debug("Updating mru entry: " +
                   JSON.stringify(threadRecord));
           }
           threadStore.put(threadRecord);
         };
-      } else if (!messageRead) {
-        // Shortcut, just update the unread count.
-        if (DEBUG) {
-          debug("Updating unread count for thread id " + threadId + ": " +
-                (threadRecord.unreadCount + 1) + " -> " +
-                threadRecord.unreadCount);
-        }
+      } else if (ignoredUnreadCount > 0) {
+        if (DEBUG) debug("Shortcut, just update the unread count.");
         threadStore.put(threadRecord);
       }
     };
   },
 
   notifyDeletedInfo: function(info) {
     if (!info ||
         (info.messageIds.length === 0 && info.threadIds.length === 0)) {
@@ -2727,17 +2721,17 @@ MobileMessageDB.prototype = {
     if (DEBUG) {
       debug("Setting message's read status by envelopeId = " + aEnvelopeId +
             ", receiver: " + aReceiver + ", readStatus: " + aReadStatus);
     }
 
     let self = this;
     this.newTxnWithCallback(aCallback, function(aCapture, aMessageStore) {
       let getRequest = aMessageStore.index("envelopeId").get(aEnvelopeId);
-      getRequest.onsuccess = function onsuccess(event) {
+      getRequest.onsuccess = function(event) {
         let messageRecord = event.target.result;
         if (!messageRecord) {
           if (DEBUG) debug("envelopeId '" + aEnvelopeId + "' not found");
           throw Cr.NS_ERROR_FAILURE;
         }
 
         aCapture.messageRecord = messageRecord;
 
@@ -2778,33 +2772,33 @@ MobileMessageDB.prototype = {
     this.newTxn(READ_ONLY, function(error, txn, messageStore) {
       if (error) {
         if (DEBUG) debug(error);
         aCallback.notify(error, null, null);
         return;
       }
       let request = messageStore.index("transactionId").get(aTransactionId);
 
-      txn.oncomplete = function oncomplete(event) {
+      txn.oncomplete = function(event) {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         let messageRecord = request.result;
         if (!messageRecord) {
           if (DEBUG) debug("Transaction ID " + aTransactionId + " not found");
           aCallback.notify(Cr.NS_ERROR_FILE_NOT_FOUND, null, null);
           return;
         }
         // In this case, we don't need a dom message. Just pass null to the
         // third argument.
         aCallback.notify(Cr.NS_OK, messageRecord, null);
       };
 
-      txn.onerror = function onerror(event) {
+      txn.onerror = function(event) {
         if (DEBUG) {
           if (event.target) {
-            debug("Caught error on transaction", event.target.errorCode);
+            debug("Caught error on transaction", event.target.error.name);
           }
         }
         aCallback.notify(Cr.NS_ERROR_FAILURE, null, null);
       };
     });
   },
 
   getMessageRecordById: function(aMessageId, aCallback) {
@@ -2813,17 +2807,17 @@ MobileMessageDB.prototype = {
     this.newTxn(READ_ONLY, function(error, txn, messageStore) {
       if (error) {
         if (DEBUG) debug(error);
         aCallback.notify(error, null, null);
         return;
       }
       let request = messageStore.mozGetAll(aMessageId);
 
-      txn.oncomplete = function oncomplete() {
+      txn.oncomplete = function() {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         if (request.result.length > 1) {
           if (DEBUG) debug("Got too many results for id " + aMessageId);
           aCallback.notify(Cr.NS_ERROR_UNEXPECTED, null, null);
           return;
         }
         let messageRecord = request.result[0];
         if (!messageRecord) {
@@ -2838,20 +2832,20 @@ MobileMessageDB.prototype = {
           }
           aCallback.notify(Cr.NS_ERROR_UNEXPECTED, null, null);
           return;
         }
         let domMessage = self.createDomMessageFromRecord(messageRecord);
         aCallback.notify(Cr.NS_OK, messageRecord, domMessage);
       };
 
-      txn.onerror = function onerror(event) {
+      txn.onerror = function(event) {
         if (DEBUG) {
           if (event.target) {
-            debug("Caught error on transaction", event.target.errorCode);
+            debug("Caught error on transaction", event.target.error.name);
           }
         }
         aCallback.notify(Cr.NS_ERROR_FAILURE, null, null);
       };
     });
   },
 
   translateCrErrorToMessageCallbackError: function(aCrError) {
@@ -2873,17 +2867,17 @@ MobileMessageDB.prototype = {
     let completeMessage = null;
     this.newTxn(READ_WRITE, function(error, txn, segmentStore) {
       if (error) {
         if (DEBUG) debug(error);
         aCallback.notify(error, null);
         return;
       }
 
-      txn.oncomplete = function oncomplete(event) {
+      txn.oncomplete = function(event) {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         if (completeMessage) {
           // Rebuild full body
           if (completeMessage.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
             // Uint8Array doesn't have `concat`, so
             // we have to merge all segements by hand.
             let fullDataLen = 0;
             for (let i = 1; i <= completeMessage.segmentMaxSeq; i++) {
@@ -2905,19 +2899,22 @@ MobileMessageDB.prototype = {
           delete completeMessage.id;
           delete completeMessage.hash;
           delete completeMessage.receivedSegments;
           delete completeMessage.segments;
         }
         aCallback.notify(Cr.NS_OK, completeMessage);
       };
 
-      txn.onabort = function onerror(event) {
-        if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
-        aCallback.notify(Cr.NS_ERROR_FAILURE, null, null);
+      txn.onabort = function(event) {
+        if (DEBUG) debug("transaction abort due to " + event.target.error.name);
+        let error = (event.target.error.name === 'QuotaExceededError')
+                    ? Cr.NS_ERROR_FILE_NO_DEVICE_SPACE
+                    : Cr.NS_ERROR_FAILURE;
+        aCallback.notify(error, null);
       };
 
       aSmsSegment.hash = aSmsSegment.sender + ":" +
                          aSmsSegment.segmentRef + ":" +
                          aSmsSegment.segmentMaxSeq + ":" +
                          aSmsSegment.iccId;
       let seq = aSmsSegment.segmentSeq;
       if (DEBUG) {
@@ -3020,59 +3017,93 @@ MobileMessageDB.prototype = {
         if (DEBUG) debug("deleteMessage: failed to open transaction");
         aRequest.notifyDeleteMessageFailed(
           self.translateCrErrorToMessageCallbackError(error));
         return;
       }
 
       let deletedInfo = { messageIds: [], threadIds: [] };
 
-      txn.onerror = function onerror(event) {
-        if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
-        //TODO look at event.target.errorCode, pick appropriate error constant
-        aRequest.notifyDeleteMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
+      txn.onabort = function(event) {
+        if (DEBUG) debug("transaction abort due to " + event.target.error.name);
+        let error = (event.target.error.name === 'QuotaExceededError')
+                    ? Ci.nsIMobileMessageCallback.STORAGE_FULL_ERROR
+                    : Ci.nsIMobileMessageCallback.INTERNAL_ERROR;
+        aRequest.notifyDeleteMessageFailed(error);
       };
 
       const messageStore = stores[0];
       const threadStore = stores[1];
 
-      txn.oncomplete = function oncomplete(event) {
+      txn.oncomplete = function(event) {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         aRequest.notifyMessageDeleted(deleted, length);
         self.notifyDeletedInfo(deletedInfo);
       };
 
+      let threadsToUpdate = {};
+      let numOfMessagesToDelete = length;
+      let updateThreadInfo = function() {
+        for (let threadId in threadsToUpdate) {
+          let threadInfo = threadsToUpdate[threadId];
+          self.updateThreadByMessageChange(messageStore,
+                                           threadStore,
+                                           threadInfo.threadId,
+                                           threadInfo.removedMsgIds,
+                                           threadInfo.ignoredUnreadCount,
+                                           deletedInfo);
+        }
+      };
+
       for (let i = 0; i < length; i++) {
         let messageId = messageIds[i];
         deleted[i] = false;
         messageStore.get(messageId).onsuccess = function(messageIndex, event) {
           let messageRecord = event.target.result;
           let messageId = messageIds[messageIndex];
           if (messageRecord) {
             if (DEBUG) debug("Deleting message id " + messageId);
 
             // First actually delete the message.
             messageStore.delete(messageId).onsuccess = function(event) {
               if (DEBUG) debug("Message id " + messageId + " deleted");
-              if (deletedInfo) {
-                deletedInfo.messageIds.push(messageId);
-              }
-
+
+              numOfMessagesToDelete--;
               deleted[messageIndex] = true;
-
-              // Then update unread count and most recent message.
-              self.updateThreadByMessageChange(messageStore,
-                                               threadStore,
-                                               messageRecord.threadId,
-                                               messageId,
-                                               messageRecord.read,
-                                               deletedInfo);
+              deletedInfo.messageIds.push(messageId);
+
+              // Cache thread info to be updated.
+              let threadId = messageRecord.threadId;
+              if (!threadsToUpdate[threadId]) {
+                threadsToUpdate[threadId] = {
+                  threadId: threadId,
+                  removedMsgIds: [messageId],
+                  ignoredUnreadCount: (!messageRecord.read) ? 1 : 0
+                };
+              } else {
+                let threadInfo = threadsToUpdate[threadId];
+                threadInfo.removedMsgIds.push(messageId);
+                if (!messageRecord.read) {
+                  threadInfo.ignoredUnreadCount++;
+                }
+              }
+
+              // After all messsages are deleted, update unread count and most
+              // recent message of related threads at once.
+              if (!numOfMessagesToDelete) {
+                updateThreadInfo();
+              }
             };
-          } else if (DEBUG) {
-            debug("Message id " + messageId + " does not exist");
+          } else {
+            if (DEBUG) debug("Message id " + messageId + " does not exist");
+
+            numOfMessagesToDelete--;
+            if (!numOfMessagesToDelete) {
+              updateThreadInfo();
+            }
           }
         }.bind(null, i);
       }
     }, [MESSAGE_STORE_NAME, THREAD_STORE_NAME]);
   },
 
   createMessageCursor: function(filter, reverse, callback) {
     if (DEBUG) {
@@ -3104,24 +3135,27 @@ MobileMessageDB.prototype = {
     this.newTxn(READ_WRITE, function(error, txn, stores) {
       if (error) {
         if (DEBUG) debug(error);
         aRequest.notifyMarkMessageReadFailed(
           self.translateCrErrorToMessageCallbackError(error));
         return;
       }
 
-      txn.onerror = function onerror(event) {
-        if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
-        aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
+      txn.onabort = function(event) {
+        if (DEBUG) debug("transaction abort due to " + event.target.error.name);
+        let error = (event.target.error.name === 'QuotaExceededError')
+                    ? Ci.nsIMobileMessageCallback.STORAGE_FULL_ERROR
+                    : Ci.nsIMobileMessageCallback.INTERNAL_ERROR;
+        aRequest.notifyMarkMessageReadFailed(error);
       };
 
       let messageStore = stores[0];
       let threadStore = stores[1];
-      messageStore.get(messageId).onsuccess = function onsuccess(event) {
+      messageStore.get(messageId).onsuccess = function(event) {
         let messageRecord = event.target.result;
         if (!messageRecord) {
           if (DEBUG) debug("Message ID " + messageId + " not found");
           aRequest.notifyMarkMessageReadFailed(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
           return;
         }
 
         if (messageRecord.id != messageId) {
@@ -3153,17 +3187,17 @@ MobileMessageDB.prototype = {
           messageRecord.isReadReportSent = true;
 
           let from = messageRecord.headers["from"];
           readReportTo = from && from.address;
           readReportMessageId = messageRecord.headers["message-id"];
         }
 
         if (DEBUG) debug("Message.read set to: " + value);
-        messageStore.put(messageRecord).onsuccess = function onsuccess(event) {
+        messageStore.put(messageRecord).onsuccess = function(event) {
           if (DEBUG) {
             debug("Update successfully completed. Message: " +
                   JSON.stringify(event.target.result));
           }
 
           // Now update the unread count.
           let threadId = messageRecord.threadId;
 
@@ -3196,18 +3230,18 @@ MobileMessageDB.prototype = {
 
     let cursor = new GetThreadsCursor(this, callback);
     this.newTxn(READ_ONLY, function(error, txn, threadStore) {
       let collector = cursor.collector;
       if (error) {
         collector.collect(null, COLLECT_ID_ERROR, COLLECT_TIMESTAMP_UNUSED);
         return;
       }
-      txn.onerror = function onerror(event) {
-        if (DEBUG) debug("Caught error on transaction ", event.target.errorCode);
+      txn.onerror = function(event) {
+        if (DEBUG) debug("Caught error on transaction ", event.target.error.name);
         collector.collect(null, COLLECT_ID_ERROR, COLLECT_TIMESTAMP_UNUSED);
       };
       let request = threadStore.index("lastTimestamp").openKeyCursor(null, PREV);
       request.onsuccess = function(event) {
         let cursor = event.target.result;
         if (cursor) {
           if (collector.collect(txn, cursor.primaryKey, cursor.key)) {
             cursor.continue();
@@ -3235,31 +3269,31 @@ let FilterSearcherHelper = {
    *        Ongoing IDBTransaction context object.
    * @param collect
    *        Result colletor function. It takes three parameters -- txn, message
    *        id, and message timestamp.
    */
   filterIndex: function(index, range, direction, txn, collect) {
     let messageStore = txn.objectStore(MESSAGE_STORE_NAME);
     let request = messageStore.index(index).openKeyCursor(range, direction);
-    request.onsuccess = function onsuccess(event) {
+    request.onsuccess = function(event) {
       let cursor = event.target.result;
       // Once the cursor has retrieved all keys that matches its key range,
       // the filter search is done.
       if (cursor) {
         let timestamp = Array.isArray(cursor.key) ? cursor.key[1] : cursor.key;
         if (collect(txn, cursor.primaryKey, timestamp)) {
           cursor.continue();
         }
       } else {
         collect(txn, COLLECT_ID_END, COLLECT_TIMESTAMP_UNUSED);
       }
     };
-    request.onerror = function onerror(event) {
-      if (DEBUG && event) debug("IDBRequest error " + event.target.errorCode);
+    request.onerror = function(event) {
+      if (DEBUG && event) debug("IDBRequest error " + event.target.error.name);
       collect(txn, COLLECT_ID_ERROR, COLLECT_TIMESTAMP_UNUSED);
     };
   },
 
   /**
    * Explicitly fiter message on the timestamp index.
    *
    * @param startDate
@@ -3301,18 +3335,18 @@ let FilterSearcherHelper = {
    *        A boolean value indicating whether we should filter message in
    *        reversed order.
    * @param collect
    *        Result colletor function. It takes three parameters -- txn, message
    *        id, and message timestamp.
    */
   transact: function(mmdb, txn, error, filter, reverse, collect) {
     if (error) {
-      //TODO look at event.target.errorCode, pick appropriate error constant.
-      if (DEBUG) debug("IDBRequest error " + error.target.errorCode);
+      // TODO look at event.target.error.name, pick appropriate error constant.
+      if (DEBUG) debug("IDBRequest error " + event.target.error.name);
       collect(txn, COLLECT_ID_ERROR, COLLECT_TIMESTAMP_UNUSED);
       return;
     }
 
     let direction = reverse ? PREV : NEXT;
 
     // We support filtering by date range only (see `else` block below) or by
     // number/delivery status/read status with an optional date range.
@@ -3740,25 +3774,25 @@ GetMessagesCursor.prototype = {
   callback: null,
   collector: null,
 
   getMessageTxn: function(messageStore, messageId) {
     if (DEBUG) debug ("Fetching message " + messageId);
 
     let getRequest = messageStore.get(messageId);
     let self = this;
-    getRequest.onsuccess = function onsuccess(event) {
+    getRequest.onsuccess = function(event) {
       if (DEBUG) {
         debug("notifyNextMessageInListGot - messageId: " + messageId);
       }
       let domMessage =
         self.mmdb.createDomMessageFromRecord(event.target.result);
       self.callback.notifyCursorResult(domMessage);
     };
-    getRequest.onerror = function onerror(event) {
+    getRequest.onerror = function(event) {
       if (DEBUG) {
         debug("notifyCursorError - messageId: " + messageId);
       }
       self.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
     };
   },
 
   notify: function(txn, messageId) {
@@ -3814,32 +3848,32 @@ GetThreadsCursor.prototype = {
   callback: null,
   collector: null,
 
   getThreadTxn: function(threadStore, threadId) {
     if (DEBUG) debug ("Fetching thread " + threadId);
 
     let getRequest = threadStore.get(threadId);
     let self = this;
-    getRequest.onsuccess = function onsuccess(event) {
+    getRequest.onsuccess = function(event) {
       let threadRecord = event.target.result;
       if (DEBUG) {
         debug("notifyCursorResult: " + JSON.stringify(threadRecord));
       }
       let thread =
         gMobileMessageService.createThread(threadRecord.id,
                                            threadRecord.participantAddresses,
                                            threadRecord.lastTimestamp,
                                            threadRecord.lastMessageSubject || "",
                                            threadRecord.body,
                                            threadRecord.unreadCount,
                                            threadRecord.lastMessageType);
       self.callback.notifyCursorResult(thread);
     };
-    getRequest.onerror = function onerror(event) {
+    getRequest.onerror = function(event) {
       if (DEBUG) {
         debug("notifyCursorError - threadId: " + threadId);
       }
       self.callback.notifyCursorError(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
     };
   },
 
   notify: function(txn, threadId) {
--- a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
+++ b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
@@ -12,35 +12,28 @@ Cu.import("resource://gre/modules/Servic
 let MMDB = {};
 Cu.import("resource://gre/modules/MobileMessageDB.jsm", MMDB);
 
 const RIL_MOBILEMESSAGEDATABASESERVICE_CONTRACTID =
   "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1";
 const RIL_MOBILEMESSAGEDATABASESERVICE_CID =
   Components.ID("{29785f90-6b5b-11e2-9201-3b280170b2ec}");
 
-XPCOMUtils.defineLazyServiceGetter(this, "gDiskSpaceWatcher",
-                                   "@mozilla.org/toolkit/disk-space-watcher;1",
-                                   "nsIDiskSpaceWatcher");
-
 const DB_NAME = "sms";
 
 /**
  * MobileMessageDatabaseService
  */
 function MobileMessageDatabaseService() {
   // Prime the directory service's cache to ensure that the ProfD entry exists
   // by the time IndexedDB queries for it off the main thread. (See bug 743635.)
   Services.dirsvc.get("ProfD", Ci.nsIFile);
 
   let mmdb = new MMDB.MobileMessageDB();
   mmdb.init(DB_NAME, 0, mmdb.updatePendingTransactionToError.bind(mmdb));
-  mmdb.isDiskFull = function() {
-    return gDiskSpaceWatcher.isDiskFull;
-  };
   this.mmdb = mmdb;
 }
 MobileMessageDatabaseService.prototype = {
 
   classID: RIL_MOBILEMESSAGEDATABASESERVICE_CID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIRilMobileMessageDatabaseService,
                                          Ci.nsIMobileMessageDatabaseService,
                                          Ci.nsIObserver]),
--- a/dom/mobilemessage/tests/marionette/mmdb_head.js
+++ b/dom/mobilemessage/tests/marionette/mmdb_head.js
@@ -230,16 +230,54 @@ function markMessageRead(aMmdb, aMessage
       deferred.resolve(Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR);
     }
   });
 
   return deferred.promise;
 }
 
 /**
+ * A convenient function for calling |mmdb.deleteMessage(...)|.
+ *
+ * Fulfill params: array of deleted flags.
+ * Reject params: Ci.nsIMobileMessageCallback.FOO.
+ *
+ * @return A deferred promise.
+ */
+function deleteMessage(aMmdb, aMessageIds, aLength) {
+  let deferred = Promise.defer();
+
+  aMmdb.deleteMessage(aMessageIds, aLength, {
+    notifyDeleteMessageFailed: function(aRv) {
+      ok(true, "deleteMessage returns a unsuccessful code: " + aRv);
+      deferred.reject(aRv);
+    },
+
+    notifyMessageDeleted: function(aDeleted, aLength) {
+      ok(true, "deleteMessage successfully!");
+      deferred.resolve(aDeleted);
+    }
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * A convenient function for calling |mmdb.saveSmsSegment(...)|.
+ *
+ * Fulfill params: [<Cr.NS_ERROR_FOO>, <completeMessage>].
+ * Reject params: same as fulfill params.
+ *
+ * @return A deferred promise.
+ */
+function saveSmsSegment(aMmdb, aSmsSegment) {
+  return callMmdbMethod(aMmdb, "saveSmsSegment", aSmsSegment);
+}
+
+/**
  * Utility function for calling cursor-based MMDB methods.
  *
  * Resolve when the target method notifies us with |notifyCursorDone|,
  * reject otherwise.
  *
  * Fulfill params: [<Ci.nsIMobileMessageCallback.FOO>, [<DOM message/thread>]]
  * Reject params: same as fulfill params.
  *
--- a/dom/mobilemessage/tests/marionette/test_mmdb_full_storage.js
+++ b/dom/mobilemessage/tests/marionette/test_mmdb_full_storage.js
@@ -1,119 +1,195 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'mmdb_head.js';
 
 const DBNAME = "test_mmdb_full_storage:" + newUUID();
 
-let gIsDiskFull = true;
-
-function newSavableMessage() {
+function newSavableMessage(aSender, aReceiver) {
   return {
     type: "sms",
-    sender: "+0987654321",
-    receiver: "+1234567890",
+    sender: aSender ? aSender : "+0987654321",
+    receiver: aReceiver? aReceiver : "+1234567890",
     body: "quick fox jump over the lazy dog",
     deliveryStatusRequested: false,
     messageClass: "normal",
     timestamp: Date.now(),
     iccId: "1029384756"
   };
 }
 
+function setStorageFull(aFull) {
+  SpecialPowers.notifyObserversInParentProcess(null,
+                                               "disk-space-watcher",
+                                               aFull ? "full" : "free");
+}
+
 function isFileNoDeviceSpaceError(aErrorResult) {
   is(aErrorResult, Cr.NS_ERROR_FILE_NO_DEVICE_SPACE, "Database error code");
 }
 
 function isCallbackStorageFullError(aErrorCode) {
   is(aErrorCode, Ci.nsIMobileMessageCallback.STORAGE_FULL_ERROR,
      "nsIMobileMessageCallback error code");
 }
 
 function testSaveSendingMessage(aMmdb) {
   log("testSaveSendingMessage()");
 
-  gIsDiskFull = true;
+  setStorageFull(true);
   return saveSendingMessage(aMmdb, newSavableMessage())
     // Resolved/rejected results are both [<Cr.NS_ERROR_FOO>, <DOM message>],
     // and we need only the error code in both cases.
     .then((aValue) => aValue[0],
           (aValue) => aValue[0])
-    .then(isFileNoDeviceSpaceError);
+    .then(isFileNoDeviceSpaceError)
+    .then(() => setStorageFull(false));
 }
 
 function testSaveReceivedMessage(aMmdb) {
   log("testSaveReceivedMessage()");
 
-  gIsDiskFull = true;
+  setStorageFull(true);
   return saveReceivedMessage(aMmdb, newSavableMessage())
     // Resolved/rejected results are both [<Cr.NS_ERROR_FOO>, <DOM message>],
     // and we need only the error code in both cases.
     .then((aValue) => aValue[0],
           (aValue) => aValue[0])
-    .then(isFileNoDeviceSpaceError);
+    .then(isFileNoDeviceSpaceError)
+    .then(() => setStorageFull(false));
 }
 
 function testGetMessageRecordById(aMmdb) {
   log("testGetMessageRecordById()");
 
-  gIsDiskFull = false;
+  setStorageFull(false);
   return saveReceivedMessage(aMmdb, newSavableMessage())
     // Resolved result is [<Cr.NS_ERROR_FOO>, <DOM message>],
     .then(function(aValue) {
       let domMessage = aValue[1];
 
-      gIsDiskFull = true;
-      return getMessageRecordById(aMmdb, domMessage.id);
+      setStorageFull(true);
+      return getMessageRecordById(aMmdb, domMessage.id)
+        .then(() => setStorageFull(false));
     });
 }
 
 function testMarkMessageRead(aMmdb) {
   log("testMarkMessageRead()");
 
-  gIsDiskFull = false;
+  setStorageFull(false);
   return saveReceivedMessage(aMmdb, newSavableMessage())
     // Resolved/rejected results are both [<Cr.NS_ERROR_FOO>, <DOM message>].
     .then(function(aValue) {
       let domMessage = aValue[1];
 
-      gIsDiskFull = true;
+      setStorageFull(true);
       return markMessageRead(aMmdb, domMessage.id, true)
         .then(null, (aValue) => aValue)
-        .then(isCallbackStorageFullError);
+        .then(isCallbackStorageFullError)
+        .then(() => setStorageFull(false));
     });
 }
 
+function testDeleteMessage(aMmdb) {
+  log("testDeleteMessage()");
+
+  // Note:
+  // Due to thread-based design in MobileMessageDB and transaction-based design
+  // in indexedDB, There are 2 restrictions to delete a message when storage full
+  // in the following condition:
+  // If the deletion won't remove all the messages in a thead and
+  // 1. the last message of the thread or
+  // 2. an unread message
+  // are to be deleted.
+  //
+  // This will trigger an update of the thread's subject, message body,
+  // unread count, etc but update operation is restricted when storage is full.
+
+  let testAddress = "1111111111";
+  let savedMsgIds = [];
+  let promises = [];
+  let numOfTestMessages = 5;
+
+  setStorageFull(false);
+  // Save several unread messages to the same thread then delete them.
+  for (let i = 0; i < numOfTestMessages; i++) {
+    promises.push(saveReceivedMessage(aMmdb, newSavableMessage(testAddress))
+      .then((aValue) => { savedMsgIds.push(aValue[1].id); }));
+  }
+
+  return Promise.all(promises)
+    .then(() => setStorageFull(true))
+
+    // Failure is expected when deleting the last one.
+    .then(() => deleteMessage(aMmdb, [savedMsgIds[numOfTestMessages - 1]], 1))
+    .then(null, (aValue) => aValue)
+    .then(isCallbackStorageFullError)
+
+    // Failure is expected when deleting an unread message.
+    .then(() => deleteMessage(aMmdb, [savedMsgIds[0]], 1))
+    .then(null, (aValue) => aValue)
+    .then(isCallbackStorageFullError)
+
+    // Delete all messages in the thread.
+    .then(() => deleteMessage(aMmdb, savedMsgIds, savedMsgIds.length))
+
+    .then(() => setStorageFull(false));
+}
+
+function testSaveSmsSegment(aMmdb) {
+  log("testSaveSmsSegment()");
+
+  let smsSegment = {
+    sender: "+0987654321",
+    encoding: 0x00, // GSM 7bit alphabet
+    iccId: "1029384756",
+    segmentRef: 0,
+    segmentSeq: 1,
+    segmentMaxSeq: 3,
+    body: "quick fox jump over the lazy dog"
+  }
+
+  setStorageFull(true);
+  return saveSmsSegment(aMmdb, smsSegment)
+    // Resolved/rejected results are both [<Cr.NS_ERROR_FOO>, <completeMessage>],
+    // and we need only the error code in both cases.
+    .then((aValue) => aValue[0],
+          (aValue) => aValue[0])
+    .then(isFileNoDeviceSpaceError)
+    .then(() => setStorageFull(false));
+}
+
 function testCreateMessageCursor(aMmdb) {
   log("testCreateMessageCursor()");
 
-  gIsDiskFull = true;
-  return createMessageCursor(aMmdb, {}, false);
+  setStorageFull(true);
+  return createMessageCursor(aMmdb, {}, false)
+    .then(() => setStorageFull(false));
 }
 
 function testCreateThreadCursor(aMmdb) {
   log("testCreateThreadCursor()");
 
-  gIsDiskFull = true;
-  return createThreadCursor(aMmdb);
+  setStorageFull(true);
+  return createThreadCursor(aMmdb)
+    .then(() => setStorageFull(false));
 }
 
 startTestBase(function testCaseMain() {
 
   let mmdb = newMobileMessageDB();
   return initMobileMessageDB(mmdb, DBNAME, 0)
-    .then(function() {
-      mmdb.isDiskFull = function() {
-        return gIsDiskFull;
-      };
-    })
 
     .then(() => testSaveSendingMessage(mmdb))
     .then(() => testSaveReceivedMessage(mmdb))
     .then(() => testGetMessageRecordById(mmdb))
     .then(() => testMarkMessageRead(mmdb))
+    .then(() => testDeleteMessage(mmdb))
+    .then(() => testSaveSmsSegment(mmdb))
     .then(() => testCreateMessageCursor(mmdb))
     .then(() => testCreateThreadCursor(mmdb))
 
     .then(() => closeMobileMessageDB(mmdb));
 });
--- a/dom/mobilemessage/tests/marionette/test_mmdb_upgradeSchema_22.js
+++ b/dom/mobilemessage/tests/marionette/test_mmdb_upgradeSchema_22.js
@@ -187,18 +187,19 @@ let LEGACY = {
         // message record, we need to retrieve it before overriding it.
         aMessageStore.get(aMessageRecord.id).onsuccess = function(event) {
           let oldMessageRecord = event.target.result;
           aMessageStore.put(aMessageRecord);
           if (oldMessageRecord) {
             self.updateThreadByMessageChange(aMessageStore,
                                              aThreadStore,
                                              oldMessageRecord.threadId,
-                                             aMessageRecord.id,
-                                             oldMessageRecord.read);
+                                             [aMessageRecord.id],
+                                             oldMessageRecord.read ? 0 : 1,
+                                             null);
           }
         };
       };
 
       if (threadRecord) {
         let needsUpdate = false;
 
         if (threadRecord.lastTimestamp <= timestamp) {
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -805,36 +805,32 @@ XPCOMUtils.defineLazyGetter(this, "gData
       if (!this.isSwitchingDataClientId() ||
           clientId != this._currentDataClientId) {
         return;
       }
 
       let connHandler = this._connectionHandlers[this._currentDataClientId];
       if (connHandler.allDataDisconnected() &&
           typeof this._pendingDataCallRequest === "function") {
-        if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
-          let radioInterface = connHandler.radioInterface;
-          radioInterface.setDataRegistration(false);
-        }
         if (DEBUG) {
-          this.debug("All data calls disconnected, setup pending data call.");
+          this.debug("All data calls disconnected, process pending data settings.");
         }
         this._pendingDataCallRequest();
         this._pendingDataCallRequest = null;
       }
     },
 
     _handleDataClientIdChange: function(newDefault) {
       if (this._dataDefaultClientId === newDefault) {
          return;
       }
       this._dataDefaultClientId = newDefault;
 
+      // This is to handle boot up stage.
       if (this._currentDataClientId == -1) {
-        // This is to handle boot up stage.
         this._currentDataClientId = this._dataDefaultClientId;
         let connHandler = this._connectionHandlers[this._currentDataClientId];
         let radioInterface = connHandler.radioInterface;
         if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
             RILQUIRKS_SUBSCRIPTION_CONTROL) {
           radioInterface.setDataRegistration(true);
         }
         if (this._dataEnabled) {
@@ -848,63 +844,56 @@ XPCOMUtils.defineLazyGetter(this, "gData
 
       let oldConnHandler = this._connectionHandlers[this._currentDataClientId];
       let oldIface = oldConnHandler.radioInterface;
       let oldSettings = oldConnHandler.dataCallSettings;
       let newConnHandler = this._connectionHandlers[this._dataDefaultClientId];
       let newIface = newConnHandler.radioInterface;
       let newSettings = newConnHandler.dataCallSettings;
 
-      if (!this._dataEnabled) {
+      let applyPendingDataSettings = (function() {
         if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
             RILQUIRKS_SUBSCRIPTION_CONTROL) {
-          oldIface.setDataRegistration(false);
-          newIface.setDataRegistration(true);
+          oldIface.setDataRegistration(false)
+            .then(() => {
+              if (this._dataEnabled) {
+                newSettings.oldEnabled = newSettings.enabled;
+                newSettings.enabled = true;
+              }
+              this._currentDataClientId = this._dataDefaultClientId;
+              return newIface.setDataRegistration(true);
+            })
+            .then(() => newConnHandler.updateRILNetworkInterface());
+          return;
+        }
+
+        if (this._dataEnabled) {
+          newSettings.oldEnabled = newSettings.enabled;
+          newSettings.enabled = true;
         }
         this._currentDataClientId = this._dataDefaultClientId;
-        return;
+        newConnHandler.updateRILNetworkInterface();
+      }).bind(this);
+
+      if (this._dataEnabled) {
+        oldSettings.oldEnabled = oldSettings.enabled;
+        oldSettings.enabled = false;
       }
 
-      oldSettings.oldEnabled = oldSettings.enabled;
-      oldSettings.enabled = false;
-
       if (oldConnHandler.anyDataConnected()) {
-        this._pendingDataCallRequest = function () {
-          if (DEBUG) {
-            this.debug("Executing pending data call request.");
-          }
-          if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
-              RILQUIRKS_SUBSCRIPTION_CONTROL) {
-            newIface.setDataRegistration(true);
-          }
-          newSettings.oldEnabled = newSettings.enabled;
-          newSettings.enabled = this._dataEnabled;
-
-          this._currentDataClientId = this._dataDefaultClientId;
-          newConnHandler.updateRILNetworkInterface();
-        };
-
+        this._pendingDataCallRequest = applyPendingDataSettings;
         if (DEBUG) {
           this.debug("_handleDataClientIdChange: existing data call(s) active" +
                      ", wait for them to get disconnected.");
         }
         oldConnHandler.deactivateDataCalls();
         return;
       }
 
-      newSettings.oldEnabled = newSettings.enabled;
-      newSettings.enabled = true;
-
-      this._currentDataClientId = this._dataDefaultClientId;
-      if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND ||
-          RILQUIRKS_SUBSCRIPTION_CONTROL) {
-        oldIface.setDataRegistration(false);
-        newIface.setDataRegistration(true);
-      }
-      newConnHandler.updateRILNetworkInterface();
+      applyPendingDataSettings();
     },
 
     _shutdown: function() {
       for (let handler of this._connectionHandlers) {
         handler.shutdown();
       }
       this._connectionHandlers = null;
       Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
@@ -2816,17 +2805,25 @@ RadioInterface.prototype = {
       return;
     }
     this.rilContext.detailedRadioState = state;
     gMessageManager.sendMobileConnectionMessage("RIL:RadioStateChanged",
                                                 this.clientId, state);
   },
 
   setDataRegistration: function(attach) {
-    this.workerMessenger.send("setDataRegistration", {attach: attach});
+    let deferred = Promise.defer();
+    this.workerMessenger.send("setDataRegistration",
+                              {attach: attach},
+                              (function(response) {
+      // Always resolve to proceed with the following steps.
+      deferred.resolve(response.errorMsg ? response.errorMsg : null);
+    }).bind(this));
+
+    return deferred.promise;
   },
 
   /**
    * TODO: Bug 911713 - B2G NetworkManager: Move policy control logic to
    *                    NetworkManager
    */
   updateRILNetworkInterface: function() {
     let connHandler = gDataConnectionManager.getConnectionHandler(this.clientId);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -2312,17 +2312,17 @@ RilObject.prototype = {
    *        Boolean value indicating attach or detach.
    */
   setDataRegistration: function(options) {
     this._attachDataRegistration = options.attach;
 
     if (RILQUIRKS_DATA_REGISTRATION_ON_DEMAND) {
       let request = options.attach ? RIL_REQUEST_GPRS_ATTACH :
                                      RIL_REQUEST_GPRS_DETACH;
-      this.context.Buf.simpleRequest(request);
+      this.context.Buf.simpleRequest(request, options);
     } else if (RILQUIRKS_SUBSCRIPTION_CONTROL && options.attach) {
       this.context.Buf.simpleRequest(REQUEST_SET_DATA_SUBSCRIPTION, options);
     }
   },
 
   /**
    * Get failure casue code for the most recently failed PDP context.
    */
@@ -6683,29 +6683,55 @@ RilObject.prototype[REQUEST_VOICE_RADIO_
   this._processRadioTech(radioTech[0]);
 };
 RilObject.prototype[REQUEST_SET_UICC_SUBSCRIPTION] = function REQUEST_SET_UICC_SUBSCRIPTION(length, options) {
   // Resend data subscription after uicc subscription.
   if (this._attachDataRegistration) {
     this.setDataRegistration({attach: true});
   }
 };
-RilObject.prototype[REQUEST_SET_DATA_SUBSCRIPTION] = null;
+RilObject.prototype[REQUEST_SET_DATA_SUBSCRIPTION] = function REQUEST_SET_DATA_SUBSCRIPTION(length, options) {
+  if (!options.rilMessageType) {
+    // The request was made by ril_worker itself. Don't report.
+    return;
+  }
+  options.success = (options.rilRequestError === 0);
+  if (!options.success) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+  }
+  this.sendChromeMessage(options);
+};
 RilObject.prototype[REQUEST_GET_UICC_SUBSCRIPTION] = null;
 RilObject.prototype[REQUEST_GET_DATA_SUBSCRIPTION] = null;
 RilObject.prototype[REQUEST_GET_UNLOCK_RETRY_COUNT] = function REQUEST_GET_UNLOCK_RETRY_COUNT(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
   this.sendChromeMessage(options);
 };
-RilObject.prototype[RIL_REQUEST_GPRS_ATTACH] = null;
-RilObject.prototype[RIL_REQUEST_GPRS_DETACH] = null;
+RilObject.prototype[RIL_REQUEST_GPRS_ATTACH] = function RIL_REQUEST_GPRS_ATTACH(length, options) {
+  if (!options.rilMessageType) {
+    // The request was made by ril_worker itself. Don't report.
+    return;
+  }
+  options.success = (options.rilRequestError === 0);
+  if (!options.success) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+  }
+  this.sendChromeMessage(options);
+};
+RilObject.prototype[RIL_REQUEST_GPRS_DETACH] = function RIL_REQUEST_GPRS_DETACH(length, options) {
+  options.success = (options.rilRequestError === 0);
+  if (!options.success) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+  }
+  this.sendChromeMessage(options);
+};
 RilObject.prototype[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
   let radioState = this.context.Buf.readInt32();
   let newState;
   if (radioState == RADIO_STATE_UNAVAILABLE) {
     newState = GECKO_RADIOSTATE_UNAVAILABLE;
   } else if (radioState == RADIO_STATE_OFF) {
     newState = GECKO_RADIOSTATE_OFF;
   } else {
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -397,19 +397,26 @@ function createExecuteContentSandbox(aWi
     try {
       sandbox[fn] = marionette[fn].bind(marionette);
     }
     catch(e) {
       sandbox[fn] = marionette[fn];
     }
   });
 
-  XPCOMUtils.defineLazyGetter(sandbox, 'SpecialPowers', function() {
-    return new SpecialPowers(aWindow);
-  });
+  if (aWindow.wrappedJSObject.SpecialPowers != undefined) {
+    XPCOMUtils.defineLazyGetter(sandbox, 'SpecialPowers', function() {
+      return aWindow.wrappedJSObject.SpecialPowers;
+    });
+  }
+  else {
+    XPCOMUtils.defineLazyGetter(sandbox, 'SpecialPowers', function() {
+      return new SpecialPowers(aWindow);
+    });
+  }
 
   sandbox.asyncComplete = function sandbox_asyncComplete(value, status, stack, commandId) {
     if (commandId == asyncTestCommandId) {
       curFrame.removeEventListener("unload", onunload, false);
       curFrame.clearTimeout(asyncTestTimeoutId);
 
       if (inactivityTimeoutId != null) {
         curFrame.clearTimeout(inactivityTimeoutId);
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -751,17 +751,17 @@ class B2GOptions(MochitestOptions):
         defaults["httpPort"] = DEFAULT_PORTS['http']
         defaults["sslPort"] = DEFAULT_PORTS['https']
         defaults["logFile"] = "mochitest.log"
         defaults["autorun"] = True
         defaults["closeWhenDone"] = True
         defaults["testPath"] = ""
         defaults["extensionsToExclude"] = ["specialpowers"]
         # See dependencies of bug 1038943.
-        defaults["leakThreshold"] = 5099
+        defaults["leakThreshold"] = 4991
         self.set_defaults(**defaults)
 
     def verifyRemoteOptions(self, options):
         if options.remoteWebServer == None:
             if os.name != "nt":
                 options.remoteWebServer = moznetwork.get_ip()
             else:
                 self.error("You must specify a --remote-webserver=<ip address>")