author | Wes 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 id | 27271 |
push user | kwierso@gmail.com |
push date | Fri, 08 Aug 2014 01:06:28 +0000 |
treeherder | mozilla-central@18f408a5984e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 34.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
34.0a1
/
20140808030201
/
pushlog to previous
nightly linux64
34.0a1
/
20140808030201
/
pushlog to previous
nightly mac
34.0a1
/
20140808030201
/
pushlog to previous
nightly win32
34.0a1
/
20140808030201
/
pushlog to previous
nightly win64
34.0a1
/
20140808030201
/
pushlog to previous
|
--- 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>")