This commit is contained in:
Wes Kocher 2014-05-08 19:17:20 -07:00
Родитель a58ca99144 7e3c640525
Коммит d8189ee58f
59 изменённых файлов: 776 добавлений и 160 удалений

Просмотреть файл

@ -120,6 +120,16 @@ this.FxAccountsMgmtService = {
} }
).then(null, Components.utils.reportError); ).then(null, Components.utils.reportError);
break; break;
case "resendVerificationEmail":
FxAccountsManager.resendVerificationEmail().then(
() => {
self._onFulfill(msg.id);
},
reason => {
self._onReject(msg.id, reason);
}
).then(null, Components.utils.reportError);
break;
case "signIn": case "signIn":
case "signUp": case "signUp":
case "refreshAuthentication": case "refreshAuthentication":

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/> <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba"> <project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/> <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>

Просмотреть файл

@ -18,7 +18,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/> <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
@ -119,7 +119,7 @@
<!-- Flame specific things --> <!-- Flame specific things -->
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/> <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
<project name="device/qcom/common" path="device/qcom/common" revision="234ed34543345f58c0d4dcb1aa012de68802b9dc"/> <project name="device/qcom/common" path="device/qcom/common" revision="234ed34543345f58c0d4dcb1aa012de68802b9dc"/>
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="2a3f4c782daad9740f1b78766b636e0e00a0ff30"/> <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="ecc08b2f0efea93c778e3525553bcd4bd5f2cf49"/>
<project name="kernel/msm" path="kernel" revision="1f47f3a180ed8b070f3cf3c4d11ff2523cca6c8a"/> <project name="kernel/msm" path="kernel" revision="1f47f3a180ed8b070f3cf3c4d11ff2523cca6c8a"/>
<project name="platform/bootable/recovery" path="bootable/recovery" revision="f2914eacee9120680a41463708bb6ee8291749fc"/> <project name="platform/bootable/recovery" path="bootable/recovery" revision="f2914eacee9120680a41463708bb6ee8291749fc"/>
<project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="fa892235a9bd8983f8b591129fc1a9398f64e514"/> <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="fa892235a9bd8983f8b591129fc1a9398f64e514"/>

Просмотреть файл

@ -4,6 +4,6 @@
"remote": "", "remote": "",
"branch": "" "branch": ""
}, },
"revision": "18441d7d35b6a96732575fb5c28cedfed8269fb2", "revision": "5476e49adf00cafde6cb68e876f0514dac4b993d",
"repo_path": "/integration/gaia-central" "repo_path": "/integration/gaia-central"
} }

Просмотреть файл

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

Просмотреть файл

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

Просмотреть файл

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/> <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>

Просмотреть файл

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f352142a54f7f7ae2c460aad9049eda4b0edb14"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="15ac34804eb8b3c9b2582d7cf754c57e23182df6"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

Просмотреть файл

@ -250,17 +250,6 @@ class B2GRemoteAutomation(Automation):
if 'b2g' not in session: if 'b2g' not in session:
raise Exception("bad session value %s returned by start_session" % session) raise Exception("bad session value %s returned by start_session" % session)
if self._is_emulator:
# Disable offline status management (bug 777145), otherwise the network
# will be 'offline' when the mochitests start. Presumably, the network
# won't be offline on a real device, so we only do this for emulators.
self.marionette.set_context(self.marionette.CONTEXT_CHROME)
self.marionette.execute_script("""
Components.utils.import("resource://gre/modules/Services.jsm");
Services.io.manageOfflineStatus = false;
Services.io.offline = false;
""")
if self.context_chrome: if self.context_chrome:
self.marionette.set_context(self.marionette.CONTEXT_CHROME) self.marionette.set_context(self.marionette.CONTEXT_CHROME)
else: else:

Просмотреть файл

@ -29,6 +29,7 @@
#include "mozilla/dom/MediaStreamBinding.h" #include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/GetUserMediaRequestBinding.h" #include "mozilla/dom/GetUserMediaRequestBinding.h"
#include "mozilla/Preferences.h"
#include "MediaTrackConstraints.h" #include "MediaTrackConstraints.h"
#include "Latency.h" #include "Latency.h"
@ -730,7 +731,7 @@ static SourceSet *
GetSources(MediaEngine *engine, GetSources(MediaEngine *engine,
ConstraintsType &aConstraints, ConstraintsType &aConstraints,
void (MediaEngine::* aEnumerate)(nsTArray<nsRefPtr<SourceType> >*), void (MediaEngine::* aEnumerate)(nsTArray<nsRefPtr<SourceType> >*),
char* media_device_name = nullptr) const char* media_device_name = nullptr)
{ {
ScopedDeletePtr<SourceSet> result(new SourceSet); ScopedDeletePtr<SourceSet> result(new SourceSet);
@ -748,7 +749,6 @@ static SourceSet *
* to. * to.
*/ */
for (uint32_t len = sources.Length(), i = 0; i < len; i++) { for (uint32_t len = sources.Length(), i = 0; i < len; i++) {
#ifdef DEBUG
sources[i]->GetName(deviceName); sources[i]->GetName(deviceName);
if (media_device_name && strlen(media_device_name) > 0) { if (media_device_name && strlen(media_device_name) > 0) {
if (deviceName.EqualsASCII(media_device_name)) { if (deviceName.EqualsASCII(media_device_name)) {
@ -756,11 +756,8 @@ static SourceSet *
break; break;
} }
} else { } else {
#endif
candidateSet.AppendElement(MediaDevice::Create(sources[i])); candidateSet.AppendElement(MediaDevice::Create(sources[i]));
#ifdef DEBUG
} }
#endif
} }
} }
@ -1146,7 +1143,8 @@ public:
const MediaStreamConstraints& aConstraints, const MediaStreamConstraints& aConstraints,
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess, already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess,
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError, already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
uint64_t aWindowId, char* aAudioLoopbackDev, char* aVideoLoopbackDev) uint64_t aWindowId, nsACString& aAudioLoopbackDev,
nsACString& aVideoLoopbackDev)
: mConstraints(aConstraints) : mConstraints(aConstraints)
, mSuccess(aSuccess) , mSuccess(aSuccess)
, mError(aError) , mError(aError)
@ -1171,14 +1169,14 @@ public:
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo)); VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
ScopedDeletePtr<SourceSet> s(GetSources(backend, constraints, ScopedDeletePtr<SourceSet> s(GetSources(backend, constraints,
&MediaEngine::EnumerateVideoDevices, &MediaEngine::EnumerateVideoDevices,
mLoopbackVideoDevice)); mLoopbackVideoDevice.get()));
final->MoveElementsFrom(*s); final->MoveElementsFrom(*s);
} }
if (IsOn(mConstraints.mAudio)) { if (IsOn(mConstraints.mAudio)) {
AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio)); AudioTrackConstraintsN constraints(GetInvariant(mConstraints.mAudio));
ScopedDeletePtr<SourceSet> s (GetSources(backend, constraints, ScopedDeletePtr<SourceSet> s (GetSources(backend, constraints,
&MediaEngine::EnumerateAudioDevices, &MediaEngine::EnumerateAudioDevices,
mLoopbackAudioDevice)); mLoopbackAudioDevice.get()));
final->MoveElementsFrom(*s); final->MoveElementsFrom(*s);
} }
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId, NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
@ -1199,8 +1197,8 @@ private:
// Audio & Video loopback devices to be used based on // Audio & Video loopback devices to be used based on
// the preference settings. This is currently used for // the preference settings. This is currently used for
// automated media tests only. // automated media tests only.
char* mLoopbackAudioDevice; nsCString mLoopbackAudioDevice;
char* mLoopbackVideoDevice; nsCString mLoopbackVideoDevice;
}; };
MediaManager::MediaManager() MediaManager::MediaManager()
@ -1584,22 +1582,12 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess); nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError);
char* loopbackAudioDevice = nullptr;
char* loopbackVideoDevice = nullptr;
#ifdef DEBUG
nsresult rv;
// Check if the preference for using loopback devices is enabled. // Check if the preference for using loopback devices is enabled.
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); nsAdoptingCString loopbackAudioDevice =
if (NS_SUCCEEDED(rv)) { Preferences::GetCString("media.audio_loopback_dev");
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); nsAdoptingCString loopbackVideoDevice =
if (branch) { Preferences::GetCString("media.video_loopback_dev");
branch->GetCharPref("media.audio_loopback_dev", &loopbackAudioDevice);
branch->GetCharPref("media.video_loopback_dev", &loopbackVideoDevice);
}
}
#endif
nsCOMPtr<nsIRunnable> gUMDRunnable = new GetUserMediaDevicesRunnable( nsCOMPtr<nsIRunnable> gUMDRunnable = new GetUserMediaDevicesRunnable(
aConstraints, onSuccess.forget(), onError.forget(), aConstraints, onSuccess.forget(), onError.forget(),

Просмотреть файл

@ -8,6 +8,16 @@ var Cr = SpecialPowers.Cr;
// Specifies whether we are using fake streams to run this automation // Specifies whether we are using fake streams to run this automation
var FAKE_ENABLED = true; var FAKE_ENABLED = true;
try {
var audioDevice = SpecialPowers.getCharPref('media.audio_loopback_dev');
var videoDevice = SpecialPowers.getCharPref('media.video_loopback_dev');
dump('TEST DEVICES: Using media devices:\n');
dump('audio: ' + audioDevice + '\nvideo: ' + videoDevice + '\n');
FAKE_ENABLED = false;
} catch (e) {
dump('TEST DEVICES: No test devices found (in media.{audio,video}_loopback_dev, using fake streams.\n');
FAKE_ENABLED = true;
}
/** /**
@ -97,7 +107,7 @@ function createMediaElement(type, label) {
* The error callback if the stream fails to be retrieved * The error callback if the stream fails to be retrieved
*/ */
function getUserMedia(constraints, onSuccess, onError) { function getUserMedia(constraints, onSuccess, onError) {
if (!("fake" in constraints)) { if (!("fake" in constraints) && FAKE_ENABLED) {
constraints["fake"] = FAKE_ENABLED; constraints["fake"] = FAKE_ENABLED;
} }

Просмотреть файл

@ -737,6 +737,7 @@ static const dom::ConstantSpec gWinProperties[] =
INT_CONSTANT(DACL_SECURITY_INFORMATION), INT_CONSTANT(DACL_SECURITY_INFORMATION),
// Errors // Errors
INT_CONSTANT(ERROR_SUCCESS),
INT_CONSTANT(ERROR_INVALID_HANDLE), INT_CONSTANT(ERROR_INVALID_HANDLE),
INT_CONSTANT(ERROR_ACCESS_DENIED), INT_CONSTANT(ERROR_ACCESS_DENIED),
INT_CONSTANT(ERROR_DIR_NOT_EMPTY), INT_CONSTANT(ERROR_DIR_NOT_EMPTY),
@ -746,6 +747,7 @@ static const dom::ConstantSpec gWinProperties[] =
INT_CONSTANT(ERROR_NO_MORE_FILES), INT_CONSTANT(ERROR_NO_MORE_FILES),
INT_CONSTANT(ERROR_PATH_NOT_FOUND), INT_CONSTANT(ERROR_PATH_NOT_FOUND),
INT_CONSTANT(ERROR_BAD_ARGUMENTS), INT_CONSTANT(ERROR_BAD_ARGUMENTS),
INT_CONSTANT(ERROR_SHARING_VIOLATION),
INT_CONSTANT(ERROR_NOT_SUPPORTED), INT_CONSTANT(ERROR_NOT_SUPPORTED),
PROP_END PROP_END

Просмотреть файл

@ -3,7 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/telephony/TelephonyChild.h" #include "TelephonyChild.h"
#include "TelephonyIPCProvider.h"
USING_TELEPHONY_NAMESPACE USING_TELEPHONY_NAMESPACE
@ -11,16 +12,23 @@ USING_TELEPHONY_NAMESPACE
* TelephonyChild * TelephonyChild
******************************************************************************/ ******************************************************************************/
TelephonyChild::TelephonyChild(nsITelephonyListener* aListener) TelephonyChild::TelephonyChild(TelephonyIPCProvider* aProvider)
: mListener(aListener) : mProvider(aProvider)
{
MOZ_ASSERT(aProvider);
}
TelephonyChild::~TelephonyChild()
{ {
MOZ_ASSERT(aListener);
} }
void void
TelephonyChild::ActorDestroy(ActorDestroyReason aWhy) TelephonyChild::ActorDestroy(ActorDestroyReason aWhy)
{ {
mListener = nullptr; if (mProvider) {
mProvider->NoteActorDestroyed();
mProvider = nullptr;
}
} }
PTelephonyRequestChild* PTelephonyRequestChild*
@ -41,9 +49,9 @@ TelephonyChild::RecvNotifyCallError(const uint32_t& aClientId,
const int32_t& aCallIndex, const int32_t& aCallIndex,
const nsString& aError) const nsString& aError)
{ {
MOZ_ASSERT(mListener); MOZ_ASSERT(mProvider);
mListener->NotifyError(aClientId, aCallIndex, aError); mProvider->NotifyError(aClientId, aCallIndex, aError);
return true; return true;
} }
@ -51,9 +59,9 @@ bool
TelephonyChild::RecvNotifyCallStateChanged(const uint32_t& aClientId, TelephonyChild::RecvNotifyCallStateChanged(const uint32_t& aClientId,
const IPCCallStateData& aData) const IPCCallStateData& aData)
{ {
MOZ_ASSERT(mListener); MOZ_ASSERT(mProvider);
mListener->CallStateChanged(aClientId, mProvider->CallStateChanged(aClientId,
aData.callIndex(), aData.callIndex(),
aData.callState(), aData.callState(),
aData.number(), aData.number(),
@ -70,18 +78,18 @@ bool
TelephonyChild::RecvNotifyCdmaCallWaiting(const uint32_t& aClientId, TelephonyChild::RecvNotifyCdmaCallWaiting(const uint32_t& aClientId,
const nsString& aNumber) const nsString& aNumber)
{ {
MOZ_ASSERT(mListener); MOZ_ASSERT(mProvider);
mListener->NotifyCdmaCallWaiting(aClientId, aNumber); mProvider->NotifyCdmaCallWaiting(aClientId, aNumber);
return true; return true;
} }
bool bool
TelephonyChild::RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState) TelephonyChild::RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState)
{ {
MOZ_ASSERT(mListener); MOZ_ASSERT(mProvider);
mListener->ConferenceCallStateChanged(aCallState); mProvider->ConferenceCallStateChanged(aCallState);
return true; return true;
} }
@ -89,9 +97,9 @@ bool
TelephonyChild::RecvNotifyConferenceError(const nsString& aName, TelephonyChild::RecvNotifyConferenceError(const nsString& aName,
const nsString& aMessage) const nsString& aMessage)
{ {
MOZ_ASSERT(mListener); MOZ_ASSERT(mProvider);
mListener->NotifyConferenceError(aName, aMessage); mProvider->NotifyConferenceError(aName, aMessage);
return true; return true;
} }
@ -100,9 +108,9 @@ TelephonyChild::RecvNotifySupplementaryService(const uint32_t& aClientId,
const int32_t& aCallIndex, const int32_t& aCallIndex,
const uint16_t& aNotification) const uint16_t& aNotification)
{ {
MOZ_ASSERT(mListener); MOZ_ASSERT(mProvider);
mListener->SupplementaryServiceNotification(aClientId, aCallIndex, mProvider->SupplementaryServiceNotification(aClientId, aCallIndex,
aNotification); aNotification);
return true; return true;
} }

Просмотреть файл

@ -13,13 +13,15 @@
BEGIN_TELEPHONY_NAMESPACE BEGIN_TELEPHONY_NAMESPACE
class TelephonyIPCProvider;
class TelephonyChild : public PTelephonyChild class TelephonyChild : public PTelephonyChild
{ {
public: public:
TelephonyChild(nsITelephonyListener* aListener); TelephonyChild(TelephonyIPCProvider* aProvider);
protected: protected:
virtual ~TelephonyChild() {} virtual ~TelephonyChild();
virtual void virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
@ -55,7 +57,7 @@ protected:
const uint16_t& aNotification) MOZ_OVERRIDE; const uint16_t& aNotification) MOZ_OVERRIDE;
private: private:
nsCOMPtr<nsITelephonyListener> mListener; nsRefPtr<TelephonyIPCProvider> mProvider;
}; };
class TelephonyRequestChild : public PTelephonyRequestChild class TelephonyRequestChild : public PTelephonyRequestChild

Просмотреть файл

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ipc/TelephonyIPCProvider.h" #include "TelephonyIPCProvider.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/telephony/TelephonyChild.h" #include "mozilla/dom/telephony/TelephonyChild.h"
@ -53,7 +53,17 @@ TelephonyIPCProvider::TelephonyIPCProvider()
TelephonyIPCProvider::~TelephonyIPCProvider() TelephonyIPCProvider::~TelephonyIPCProvider()
{ {
mPTelephonyChild->Send__delete__(mPTelephonyChild); if (mPTelephonyChild) {
mPTelephonyChild->Send__delete__(mPTelephonyChild);
mPTelephonyChild = nullptr;
}
}
void
TelephonyIPCProvider::NoteActorDestroyed()
{
MOZ_ASSERT(mPTelephonyChild);
mPTelephonyChild = nullptr; mPTelephonyChild = nullptr;
} }
@ -94,6 +104,11 @@ TelephonyIPCProvider::RegisterListener(nsITelephonyListener *aListener)
{ {
MOZ_ASSERT(!mListeners.Contains(aListener)); MOZ_ASSERT(!mListeners.Contains(aListener));
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
// nsTArray doesn't fail. // nsTArray doesn't fail.
mListeners.AppendElement(aListener); mListeners.AppendElement(aListener);
@ -108,6 +123,11 @@ TelephonyIPCProvider::UnregisterListener(nsITelephonyListener *aListener)
{ {
MOZ_ASSERT(mListeners.Contains(aListener)); MOZ_ASSERT(mListeners.Contains(aListener));
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
// We always have the element here, so it can't fail. // We always have the element here, so it can't fail.
mListeners.RemoveElement(aListener); mListeners.RemoveElement(aListener);
@ -122,6 +142,11 @@ TelephonyIPCProvider::SendRequest(nsITelephonyListener *aListener,
nsITelephonyCallback *aCallback, nsITelephonyCallback *aCallback,
const IPCTelephonyRequest& aRequest) const IPCTelephonyRequest& aRequest)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
// Life time of newly allocated TelephonyRequestChild instance is managed by // Life time of newly allocated TelephonyRequestChild instance is managed by
// IPDL itself. // IPDL itself.
TelephonyRequestChild* actor = new TelephonyRequestChild(aListener, aCallback); TelephonyRequestChild* actor = new TelephonyRequestChild(aListener, aCallback);
@ -146,6 +171,11 @@ TelephonyIPCProvider::Dial(uint32_t aClientId, const nsAString& aNumber,
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::HangUp(uint32_t aClientId, uint32_t aCallIndex) TelephonyIPCProvider::HangUp(uint32_t aClientId, uint32_t aCallIndex)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendHangUpCall(aClientId, aCallIndex); mPTelephonyChild->SendHangUpCall(aClientId, aCallIndex);
return NS_OK; return NS_OK;
} }
@ -153,6 +183,11 @@ TelephonyIPCProvider::HangUp(uint32_t aClientId, uint32_t aCallIndex)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::AnswerCall(uint32_t aClientId, uint32_t aCallIndex) TelephonyIPCProvider::AnswerCall(uint32_t aClientId, uint32_t aCallIndex)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendAnswerCall(aClientId, aCallIndex); mPTelephonyChild->SendAnswerCall(aClientId, aCallIndex);
return NS_OK; return NS_OK;
} }
@ -160,6 +195,11 @@ TelephonyIPCProvider::AnswerCall(uint32_t aClientId, uint32_t aCallIndex)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::RejectCall(uint32_t aClientId, uint32_t aCallIndex) TelephonyIPCProvider::RejectCall(uint32_t aClientId, uint32_t aCallIndex)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendRejectCall(aClientId, aCallIndex); mPTelephonyChild->SendRejectCall(aClientId, aCallIndex);
return NS_OK; return NS_OK;
} }
@ -167,6 +207,11 @@ TelephonyIPCProvider::RejectCall(uint32_t aClientId, uint32_t aCallIndex)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::HoldCall(uint32_t aClientId, uint32_t aCallIndex) TelephonyIPCProvider::HoldCall(uint32_t aClientId, uint32_t aCallIndex)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendHoldCall(aClientId, aCallIndex); mPTelephonyChild->SendHoldCall(aClientId, aCallIndex);
return NS_OK; return NS_OK;
} }
@ -174,6 +219,11 @@ TelephonyIPCProvider::HoldCall(uint32_t aClientId, uint32_t aCallIndex)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::ResumeCall(uint32_t aClientId, uint32_t aCallIndex) TelephonyIPCProvider::ResumeCall(uint32_t aClientId, uint32_t aCallIndex)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendResumeCall(aClientId, aCallIndex); mPTelephonyChild->SendResumeCall(aClientId, aCallIndex);
return NS_OK; return NS_OK;
} }
@ -181,6 +231,11 @@ TelephonyIPCProvider::ResumeCall(uint32_t aClientId, uint32_t aCallIndex)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::ConferenceCall(uint32_t aClientId) TelephonyIPCProvider::ConferenceCall(uint32_t aClientId)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendConferenceCall(aClientId); mPTelephonyChild->SendConferenceCall(aClientId);
return NS_OK; return NS_OK;
} }
@ -188,6 +243,11 @@ TelephonyIPCProvider::ConferenceCall(uint32_t aClientId)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::SeparateCall(uint32_t aClientId, uint32_t aCallIndex) TelephonyIPCProvider::SeparateCall(uint32_t aClientId, uint32_t aCallIndex)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendSeparateCall(aClientId, aCallIndex); mPTelephonyChild->SendSeparateCall(aClientId, aCallIndex);
return NS_OK; return NS_OK;
} }
@ -195,6 +255,11 @@ TelephonyIPCProvider::SeparateCall(uint32_t aClientId, uint32_t aCallIndex)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::HoldConference(uint32_t aClientId) TelephonyIPCProvider::HoldConference(uint32_t aClientId)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendHoldConference(aClientId); mPTelephonyChild->SendHoldConference(aClientId);
return NS_OK; return NS_OK;
} }
@ -202,6 +267,11 @@ TelephonyIPCProvider::HoldConference(uint32_t aClientId)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::ResumeConference(uint32_t aClientId) TelephonyIPCProvider::ResumeConference(uint32_t aClientId)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendResumeConference(aClientId); mPTelephonyChild->SendResumeConference(aClientId);
return NS_OK; return NS_OK;
} }
@ -209,6 +279,11 @@ TelephonyIPCProvider::ResumeConference(uint32_t aClientId)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::StartTone(uint32_t aClientId, const nsAString& aDtmfChar) TelephonyIPCProvider::StartTone(uint32_t aClientId, const nsAString& aDtmfChar)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendStartTone(aClientId, nsString(aDtmfChar)); mPTelephonyChild->SendStartTone(aClientId, nsString(aDtmfChar));
return NS_OK; return NS_OK;
} }
@ -216,6 +291,11 @@ TelephonyIPCProvider::StartTone(uint32_t aClientId, const nsAString& aDtmfChar)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::StopTone(uint32_t aClientId) TelephonyIPCProvider::StopTone(uint32_t aClientId)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendStopTone(aClientId); mPTelephonyChild->SendStopTone(aClientId);
return NS_OK; return NS_OK;
} }
@ -223,6 +303,11 @@ TelephonyIPCProvider::StopTone(uint32_t aClientId)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::GetMicrophoneMuted(bool* aMuted) TelephonyIPCProvider::GetMicrophoneMuted(bool* aMuted)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendGetMicrophoneMuted(aMuted); mPTelephonyChild->SendGetMicrophoneMuted(aMuted);
return NS_OK; return NS_OK;
} }
@ -230,6 +315,11 @@ TelephonyIPCProvider::GetMicrophoneMuted(bool* aMuted)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::SetMicrophoneMuted(bool aMuted) TelephonyIPCProvider::SetMicrophoneMuted(bool aMuted)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendSetMicrophoneMuted(aMuted); mPTelephonyChild->SendSetMicrophoneMuted(aMuted);
return NS_OK; return NS_OK;
} }
@ -237,6 +327,11 @@ TelephonyIPCProvider::SetMicrophoneMuted(bool aMuted)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::GetSpeakerEnabled(bool* aEnabled) TelephonyIPCProvider::GetSpeakerEnabled(bool* aEnabled)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendGetSpeakerEnabled(aEnabled); mPTelephonyChild->SendGetSpeakerEnabled(aEnabled);
return NS_OK; return NS_OK;
} }
@ -244,6 +339,11 @@ TelephonyIPCProvider::GetSpeakerEnabled(bool* aEnabled)
NS_IMETHODIMP NS_IMETHODIMP
TelephonyIPCProvider::SetSpeakerEnabled(bool aEnabled) TelephonyIPCProvider::SetSpeakerEnabled(bool aEnabled)
{ {
if (!mPTelephonyChild) {
NS_WARNING("TelephonyProvider used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendSetSpeakerEnabled(aEnabled); mPTelephonyChild->SendSetSpeakerEnabled(aEnabled);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -28,10 +28,11 @@ public:
TelephonyIPCProvider(); TelephonyIPCProvider();
protected: void NoteActorDestroyed();
virtual ~TelephonyIPCProvider();
private: private:
~TelephonyIPCProvider();
nsTArray<nsCOMPtr<nsITelephonyListener> > mListeners; nsTArray<nsCOMPtr<nsITelephonyListener> > mListeners;
PTelephonyChild* mPTelephonyChild; PTelephonyChild* mPTelephonyChild;
uint32_t mDefaultServiceId; uint32_t mDefaultServiceId;

Просмотреть файл

@ -6,6 +6,8 @@
#include "nsMimeTypes.h" #include "nsMimeTypes.h"
#include "Image.h" #include "Image.h"
#include "nsRefreshDriver.h"
#include "mozilla/TimeStamp.h"
namespace mozilla { namespace mozilla {
namespace image { namespace image {
@ -128,6 +130,26 @@ ImageResource::SetAnimationModeInternal(uint16_t aAnimationMode)
return NS_OK; return NS_OK;
} }
bool
ImageResource::HadRecentRefresh(const TimeStamp& aTime)
{
// Our threshold for "recent" is 1/2 of the default refresh-driver interval.
// This ensures that we allow for frame rates at least as fast as the
// refresh driver's default rate.
static TimeDuration recentThreshold =
TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval() / 2.0);
if (!mLastRefreshTime.IsNull() &&
aTime - mLastRefreshTime < recentThreshold) {
return true;
}
// else, we can proceed with a refresh.
// But first, update our last refresh time:
mLastRefreshTime = aTime;
return false;
}
void void
ImageResource::EvaluateAnimation() ImageResource::EvaluateAnimation()
{ {

Просмотреть файл

@ -186,6 +186,17 @@ protected:
nsresult GetAnimationModeInternal(uint16_t *aAnimationMode); nsresult GetAnimationModeInternal(uint16_t *aAnimationMode);
nsresult SetAnimationModeInternal(uint16_t aAnimationMode); nsresult SetAnimationModeInternal(uint16_t aAnimationMode);
/**
* Helper for RequestRefresh.
*
* If we've had a "recent" refresh (i.e. if this image is being used in
* multiple documents & some other document *just* called RequestRefresh() on
* this image with a timestamp close to aTime), this method returns true.
*
* Otherwise, this method updates mLastRefreshTime to aTime & returns false.
*/
bool HadRecentRefresh(const mozilla::TimeStamp& aTime);
/** /**
* Decides whether animation should or should not be happening, * Decides whether animation should or should not be happening,
* and makes sure the right thing is being done. * and makes sure the right thing is being done.
@ -206,6 +217,7 @@ protected:
// Member data shared by all implementations of this abstract class // Member data shared by all implementations of this abstract class
nsRefPtr<imgStatusTracker> mStatusTracker; nsRefPtr<imgStatusTracker> mStatusTracker;
nsRefPtr<ImageURL> mURI; nsRefPtr<ImageURL> mURI;
TimeStamp mLastRefreshTime;
uint64_t mInnerWindowId; uint64_t mInnerWindowId;
uint32_t mAnimationConsumers; uint32_t mAnimationConsumers;
uint16_t mAnimationMode; // Enum values in imgIContainer uint16_t mAnimationMode; // Enum values in imgIContainer

Просмотреть файл

@ -543,6 +543,10 @@ RasterImage::Init(const char* aMimeType,
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime) RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
{ {
if (HadRecentRefresh(aTime)) {
return;
}
EvaluateAnimation(); EvaluateAnimation();
if (!mAnimating) { if (!mAnimating) {

Просмотреть файл

@ -527,6 +527,10 @@ VectorImage::GetWidth(int32_t* aWidth)
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime) VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime)
{ {
if (HadRecentRefresh(aTime)) {
return;
}
EvaluateAnimation(); EvaluateAnimation();
mSVGDocumentWrapper->TickRefreshDriver(); mSVGDocumentWrapper->TickRefreshDriver();

Просмотреть файл

@ -47,6 +47,8 @@ class TestActorPunningPunnedParent :
public: public:
TestActorPunningPunnedParent() {} TestActorPunningPunnedParent() {}
virtual ~TestActorPunningPunnedParent() {} virtual ~TestActorPunningPunnedParent() {}
protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
}; };
class TestActorPunningSubParent : class TestActorPunningSubParent :
@ -55,6 +57,8 @@ class TestActorPunningSubParent :
public: public:
TestActorPunningSubParent() {} TestActorPunningSubParent() {}
virtual ~TestActorPunningSubParent() {} virtual ~TestActorPunningSubParent() {}
protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
}; };

Просмотреть файл

@ -51,6 +51,7 @@ public:
virtual ~TestBadActorSubParent() { } virtual ~TestBadActorSubParent() { }
protected: protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
virtual bool RecvPing(); virtual bool RecvPing();
}; };

Просмотреть файл

@ -80,8 +80,8 @@ public:
virtual ~TestDescSubParent() { } virtual ~TestDescSubParent() { }
protected: protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
virtual PTestDescSubsubParent* AllocPTestDescSubsubParent() MOZ_OVERRIDE; virtual PTestDescSubsubParent* AllocPTestDescSubsubParent() MOZ_OVERRIDE;
virtual bool DeallocPTestDescSubsubParent(PTestDescSubsubParent* actor) MOZ_OVERRIDE; virtual bool DeallocPTestDescSubsubParent(PTestDescSubsubParent* actor) MOZ_OVERRIDE;
}; };
@ -108,6 +108,9 @@ class TestDescSubsubParent :
public: public:
TestDescSubsubParent() { } TestDescSubsubParent() { }
virtual ~TestDescSubsubParent() { } virtual ~TestDescSubsubParent() { }
protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
}; };
class TestDescSubsubChild : class TestDescSubsubChild :

Просмотреть файл

@ -18,6 +18,9 @@ class TestHandleParent :
public: public:
TestHandleParent() { } TestHandleParent() { }
virtual ~TestHandleParent() { } virtual ~TestHandleParent() { }
protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
}; };
class TestJSONParent : class TestJSONParent :

Просмотреть файл

@ -72,6 +72,7 @@ public:
virtual ~TestManyChildAllocsSubParent() { } virtual ~TestManyChildAllocsSubParent() { }
protected: protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
virtual bool RecvHello() MOZ_OVERRIDE { return true; } virtual bool RecvHello() MOZ_OVERRIDE { return true; }
}; };

Просмотреть файл

@ -25,6 +25,9 @@ class TestMultiMgrsBottomParent :
public: public:
TestMultiMgrsBottomParent() { } TestMultiMgrsBottomParent() { }
virtual ~TestMultiMgrsBottomParent() { } virtual ~TestMultiMgrsBottomParent() { }
protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
}; };
class TestMultiMgrsLeftParent : class TestMultiMgrsLeftParent :
@ -40,6 +43,8 @@ public:
} }
protected: protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() MOZ_OVERRIDE virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() MOZ_OVERRIDE
{ {
return new TestMultiMgrsBottomParent(); return new TestMultiMgrsBottomParent();
@ -65,6 +70,8 @@ public:
} }
protected: protected:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE {}
virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() MOZ_OVERRIDE virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() MOZ_OVERRIDE
{ {
return new TestMultiMgrsBottomParent(); return new TestMultiMgrsBottomParent();

Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "jit/IonLinker.h" #include "jit/IonLinker.h"
#include "jit/PerfSpewer.h"
#include "jit/IonFrames-inl.h" #include "jit/IonFrames-inl.h"
#include "vm/Stack-inl.h" #include "vm/Stack-inl.h"

Просмотреть файл

@ -5688,6 +5688,9 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
return true; return true;
} }
// Try to add a getter stub. We don't handle scripted getters yet; if this
// changes we need to make sure IonBuilder::getPropTryCommonGetter (which
// requires a Baseline stub) handles non-outerized this objects correctly.
bool isScripted; bool isScripted;
if (IsCacheableGetPropCall(cx, global, global, shape, &isScripted) && !isScripted) if (IsCacheableGetPropCall(cx, global, global, shape, &isScripted) && !isScripted)
{ {
@ -5741,6 +5744,10 @@ TryAttachScopeNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *s
scopeChain = scopeChain->enclosingScope(); scopeChain = scopeChain->enclosingScope();
} }
// We don't handle getters here. When this changes, we need to make sure
// IonBuilder::getPropTryCommonGetter (which requires a Baseline stub to
// work) handles non-outerized this objects correctly.
if (!IsCacheableGetPropReadSlot(scopeChain, scopeChain, shape)) if (!IsCacheableGetPropReadSlot(scopeChain, scopeChain, shape))
return true; return true;

Просмотреть файл

@ -8605,6 +8605,10 @@ IonBuilder::jsop_getprop(PropertyName *name)
if (!getPropTryInlineAccess(&emitted, obj, name, barrier, types) || emitted) if (!getPropTryInlineAccess(&emitted, obj, name, barrier, types) || emitted)
return emitted; return emitted;
// Try to optimize accesses on outer window proxies, for example window.foo.
if (!getPropTryInnerize(&emitted, obj, name, types) || emitted)
return emitted;
// Try to emit a polymorphic cache. // Try to emit a polymorphic cache.
if (!getPropTryCache(&emitted, obj, name, barrier, types) || emitted) if (!getPropTryCache(&emitted, obj, name, barrier, types) || emitted)
return emitted; return emitted;
@ -9074,6 +9078,79 @@ IonBuilder::getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name,
return true; return true;
} }
MDefinition *
IonBuilder::tryInnerizeWindow(MDefinition *obj)
{
// Try to optimize accesses on outer window proxies (window.foo, for
// example) to go directly to the inner window, the global.
//
// Callers should be careful not to pass the inner object to getters or
// setters that require outerization.
if (obj->type() != MIRType_Object)
return obj;
types::TemporaryTypeSet *types = obj->resultTypeSet();
if (!types)
return obj;
JSObject *singleton = types->getSingleton();
if (!singleton)
return obj;
JSObject *inner = GetInnerObject(singleton);
if (inner == singleton || inner != &script()->global())
return obj;
// When we navigate, the outer object is brain transplanted and we'll mark
// its TypeObject as having unknown properties. The type constraint we add
// here will invalidate JIT code when this happens.
types::TypeObjectKey *objType = types::TypeObjectKey::get(singleton);
if (objType->hasFlags(constraints(), types::OBJECT_FLAG_UNKNOWN_PROPERTIES))
return obj;
obj->setImplicitlyUsedUnchecked();
return constant(ObjectValue(script()->global()));
}
bool
IonBuilder::getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *name,
types::TemporaryTypeSet *types)
{
// See the comment in tryInnerizeWindow for how this works.
MOZ_ASSERT(*emitted == false);
MDefinition *inner = tryInnerizeWindow(obj);
if (inner == obj)
return true;
// Note: the Baseline ICs don't know about this optimization, so it's
// possible the global property's HeapTypeSet has not been initialized
// yet. In this case we'll fall back to getPropTryCache for now.
//
// Also note that we don't call getPropTryCommonGetter below, because
// (a) it requires a Baseline getter stub, which we don't have for outer
// window proxies and (b) we have to be careful not to pass the inner
// object to scripted getters etc. See bug 1007631.
if (!getPropTryConstant(emitted, inner, name, types) || *emitted)
return *emitted;
if (!getStaticName(&script()->global(), name, emitted) || *emitted)
return *emitted;
// Passing the inner object to GetProperty IC is safe, see the
// needsOuterizedThisObject check in IsCacheableGetPropCallNative.
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
inner, name, types);
if (!getPropTryCache(emitted, inner, name, barrier, types) || *emitted)
return *emitted;
MOZ_ASSERT(*emitted == false);
return true;
}
bool bool
IonBuilder::needsToMonitorMissingProperties(types::TemporaryTypeSet *types) IonBuilder::needsToMonitorMissingProperties(types::TemporaryTypeSet *types)
{ {

Просмотреть файл

@ -397,6 +397,8 @@ class IonBuilder : public MIRGenerator
bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier, bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier,
MIRType slotType = MIRType_None); MIRType slotType = MIRType_None);
MDefinition *tryInnerizeWindow(MDefinition *obj);
// jsop_getprop() helpers. // jsop_getprop() helpers.
bool getPropTryArgumentsLength(bool *emitted, MDefinition *obj); bool getPropTryArgumentsLength(bool *emitted, MDefinition *obj);
bool getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name, bool getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name,
@ -418,6 +420,8 @@ class IonBuilder : public MIRGenerator
TypeDescrSet fieldTypeReprs, TypeDescrSet fieldTypeReprs,
size_t fieldIndex, size_t fieldIndex,
types::TemporaryTypeSet *resultTypes); types::TemporaryTypeSet *resultTypes);
bool getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *name,
types::TemporaryTypeSet *types);
bool getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name, bool getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name,
BarrierKind barrier, types::TemporaryTypeSet *types); BarrierKind barrier, types::TemporaryTypeSet *types);
bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types); bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);

Просмотреть файл

@ -1161,6 +1161,12 @@ CanAttachNativeGetProp(typename GetPropCache::Context cx, const GetPropCache &ca
// IonBuilder guarantees that it's impossible to generate a GetPropertyIC with // IonBuilder guarantees that it's impossible to generate a GetPropertyIC with
// allowGetters() true and cache.output().hasValue() false. If this isn't true, // allowGetters() true and cache.output().hasValue() false. If this isn't true,
// we will quickly assert during stub generation. // we will quickly assert during stub generation.
//
// Be careful when adding support for other getters here: for outer window
// proxies, IonBuilder can innerize and pass us the inner window (the global),
// see IonBuilder::getPropTryInnerize. This is fine for native getters because
// IsCacheableGetPropCallNative checks they can handle both the inner and
// outer object, but scripted getters would need a similar mechanism.
if (cache.allowGetters() && if (cache.allowGetters() &&
(IsCacheableGetPropCallNative(obj, holder, shape) || (IsCacheableGetPropCallNative(obj, holder, shape) ||
IsCacheableGetPropCallPropertyOp(obj, holder, shape))) IsCacheableGetPropCallPropertyOp(obj, holder, shape)))

Просмотреть файл

@ -1238,6 +1238,18 @@ MarkJitActivations(JSRuntime *rt, JSTracer *trc)
MarkJitActivation(trc, activations); MarkJitActivation(trc, activations);
} }
JSCompartment *
TopmostIonActivationCompartment(JSRuntime *rt)
{
for (JitActivationIterator activations(rt); !activations.done(); ++activations) {
for (JitFrameIterator frames(activations); !frames.done(); ++frames) {
if (frames.type() == JitFrame_IonJS)
return activations.activation()->compartment();
}
}
return nullptr;
}
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
void void
UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc) UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc)

Просмотреть файл

@ -268,6 +268,9 @@ void EnsureExitFrame(IonCommonFrameLayout *frame);
void MarkJitActivations(JSRuntime *rt, JSTracer *trc); void MarkJitActivations(JSRuntime *rt, JSTracer *trc);
void MarkIonCompilerRoots(JSTracer *trc); void MarkIonCompilerRoots(JSTracer *trc);
JSCompartment *
TopmostIonActivationCompartment(JSRuntime *rt);
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
void UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc); void UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc);
#endif #endif

Просмотреть файл

@ -292,6 +292,11 @@ MDefinition::dump(FILE *fp) const
fprintf(fp, " = "); fprintf(fp, " = ");
printOpcode(fp); printOpcode(fp);
fprintf(fp, "\n"); fprintf(fp, "\n");
if (isInstruction()) {
if (MResumePoint *resume = toInstruction()->resumePoint())
resume->dump(fp);
}
} }
void void
@ -2306,6 +2311,41 @@ MResumePoint::inherit(MBasicBlock *block)
} }
} }
void MResumePoint::dump(FILE *fp) const
{
fprintf(fp, "resumepoint mode=");
switch (mode()) {
case MResumePoint::ResumeAt:
fprintf(fp, "At");
break;
case MResumePoint::ResumeAfter:
fprintf(fp, "After");
break;
case MResumePoint::Outer:
fprintf(fp, "Outer");
break;
}
if (MResumePoint *c = caller())
fprintf(fp, " (caller in block%u)", c->block()->id());
for (size_t i = 0; i < numOperands(); i++) {
fprintf(fp, " ");
if (operands_[i].hasProducer())
getOperand(i)->printName(fp);
else
fprintf(fp, "(null)");
}
fprintf(fp, "\n");
}
void
MResumePoint::dump() const
{
dump(stderr);
}
MDefinition * MDefinition *
MToInt32::foldsTo(TempAllocator &alloc, bool useValueNumbers) MToInt32::foldsTo(TempAllocator &alloc, bool useValueNumbers)
{ {

Просмотреть файл

@ -217,6 +217,9 @@ class MNode : public TempObject
virtual bool writeRecoverData(CompactBufferWriter &writer) const; virtual bool writeRecoverData(CompactBufferWriter &writer) const;
virtual void dump(FILE *fp) const = 0;
virtual void dump() const = 0;
protected: protected:
// Sets an unset operand, updating use information. // Sets an unset operand, updating use information.
virtual void setOperand(size_t index, MDefinition *operand) = 0; virtual void setOperand(size_t index, MDefinition *operand) = 0;
@ -613,6 +616,7 @@ class MDefinition : public MNode
# undef OPCODE_CASTS # undef OPCODE_CASTS
inline MInstruction *toInstruction(); inline MInstruction *toInstruction();
inline const MInstruction *toInstruction() const;
bool isInstruction() const { bool isInstruction() const {
return !isPhi(); return !isPhi();
} }
@ -9669,7 +9673,7 @@ class MResumePoint MOZ_FINAL : public MNode, public InlineForwardListNode<MResum
uint32_t stackDepth() const { uint32_t stackDepth() const {
return stackDepth_; return stackDepth_;
} }
MResumePoint *caller() { MResumePoint *caller() const {
return caller_; return caller_;
} }
void setCaller(MResumePoint *caller) { void setCaller(MResumePoint *caller) {
@ -9699,6 +9703,9 @@ class MResumePoint MOZ_FINAL : public MNode, public InlineForwardListNode<MResum
} }
bool writeRecoverData(CompactBufferWriter &writer) const; bool writeRecoverData(CompactBufferWriter &writer) const;
virtual void dump(FILE *fp) const;
virtual void dump() const;
}; };
class MIsCallable class MIsCallable
@ -10206,6 +10213,12 @@ MInstruction *MDefinition::toInstruction()
return (MInstruction *)this; return (MInstruction *)this;
} }
const MInstruction *MDefinition::toInstruction() const
{
JS_ASSERT(!isPhi());
return (const MInstruction *)this;
}
typedef Vector<MDefinition *, 8, IonAllocPolicy> MDefinitionVector; typedef Vector<MDefinition *, 8, IonAllocPolicy> MDefinitionVector;
// Helper functions used to decide how to build MIR. // Helper functions used to decide how to build MIR.

Просмотреть файл

@ -1278,6 +1278,9 @@ void
MBasicBlock::dump(FILE *fp) MBasicBlock::dump(FILE *fp)
{ {
#ifdef DEBUG #ifdef DEBUG
if (MResumePoint *resume = entryResumePoint()) {
resume->dump();
}
for (MPhiIterator iter(phisBegin()); iter != phisEnd(); iter++) { for (MPhiIterator iter(phisBegin()); iter != phisEnd(); iter++) {
iter->dump(fp); iter->dump(fp);
} }

Просмотреть файл

@ -2828,6 +2828,13 @@ BeginMarkPhase(JSRuntime *rt)
c->zone()->setPreservingCode(true); c->zone()->setPreservingCode(true);
} }
if (!rt->gc.shouldCleanUpEverything) {
#ifdef JS_ION
if (JSCompartment *comp = jit::TopmostIonActivationCompartment(rt))
comp->zone()->setPreservingCode(true);
#endif
}
/* /*
* Atoms are not in the cross-compartment map. So if there are any * Atoms are not in the cross-compartment map. So if there are any
* zones that are not being collected, we are not allowed to collect * zones that are not being collected, we are not allowed to collect

Просмотреть файл

@ -1394,7 +1394,7 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
// Otherwise, always show the transition. // Otherwise, always show the transition.
if (!animate.EqualsLiteral("false") && if (!animate.EqualsLiteral("false") &&
(!animate.EqualsLiteral("cancel") || aIsRollup)) { (!animate.EqualsLiteral("cancel") || aIsRollup)) {
nsCOMPtr<TransitionEnder> ender = new TransitionEnder(aPopup, aDeselectMenu); nsRefPtr<TransitionEnder> ender = new TransitionEnder(aPopup, aDeselectMenu);
aPopup->AddSystemEventListener(NS_LITERAL_STRING("transitionend"), aPopup->AddSystemEventListener(NS_LITERAL_STRING("transitionend"),
ender, false, false); ender, false, false);
return; return;

Просмотреть файл

@ -4123,4 +4123,4 @@ pref("beacon.enabled", true);
// Camera prefs // Camera prefs
pref("camera.control.autofocus_moving_callback.enabled", false); pref("camera.control.autofocus_moving_callback.enabled", false);
pref("camera.control.face_detection.enabled", false); pref("camera.control.face_detection.enabled", true);

Просмотреть файл

@ -377,8 +377,7 @@ nsAsyncStreamCopier::AsyncCopy(nsIRequestObserver *observer, nsISupports *ctx)
if (NS_IsMainThread()) { if (NS_IsMainThread()) {
// Don't perform buffer sniffing on the main thread // Don't perform buffer sniffing on the main thread
nsCOMPtr<AsyncApplyBufferingPolicyEvent> event nsCOMPtr<nsIRunnable> event = new AsyncApplyBufferingPolicyEvent(this);
= new AsyncApplyBufferingPolicyEvent(this);
rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL); rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
Cancel(rv); Cancel(rv);

Просмотреть файл

@ -171,7 +171,7 @@ nsAboutCache::VisitNextStorage()
// from visitor callback. The cache v1 service doesn't like it. // from visitor callback. The cache v1 service doesn't like it.
// TODO - mayhemer, bug 913828, remove this dispatch and call // TODO - mayhemer, bug 913828, remove this dispatch and call
// directly. // directly.
nsCOMPtr<nsRunnableMethod<nsAboutCache> > event = nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &nsAboutCache::FireVisitStorage); NS_NewRunnableMethod(this, &nsAboutCache::FireVisitStorage);
return NS_DispatchToMainThread(event); return NS_DispatchToMainThread(event);
} }

Просмотреть файл

@ -322,7 +322,7 @@ main(int32_t argc, char *argv[])
if (NS_WARN_IF(!timer)) { if (NS_WARN_IF(!timer)) {
return -1; return -1;
} }
nsCOMPtr<MulticastTimerCallback> timerCb = new MulticastTimerCallback(); nsRefPtr<MulticastTimerCallback> timerCb = new MulticastTimerCallback();
// The following multicast tests using multiple sockets require a firewall // The following multicast tests using multiple sockets require a firewall
// exception on Windows XP before they pass. For now, we'll skip them here. // exception on Windows XP before they pass. For now, we'll skip them here.

Просмотреть файл

@ -250,6 +250,17 @@ this.FxAccountsManager = {
return this._signOut(); return this._signOut();
}, },
resendVerificationEmail: function() {
return this._fxAccounts.resendVerificationEmail().then(
(result) => {
return result;
},
(error) => {
return this._error(ERROR_SERVER_ERROR, error);
}
);
},
getAccount: function() { getAccount: function() {
// We check first if we have session details cached. // We check first if we have session details cached.
if (this._activeSession) { if (this._activeSession) {

Просмотреть файл

@ -122,6 +122,15 @@ FxAccountsManager._fxAccounts = {
return deferred.promise; return deferred.promise;
}, },
resendVerificationEmail: function() {
return this.getSignedInUser().then(data => {
if (data) {
return Promise.resolve(true);
}
throw new Error("Cannot resend verification email; no signed-in user");
});
},
setSignedInUser: function(user) { setSignedInUser: function(user) {
this._setSignedInUserCalled = true; this._setSignedInUserCalled = true;
let deferred = Promise.defer(); let deferred = Promise.defer();
@ -580,6 +589,33 @@ add_test(function(test_signIn_already_signed_user) {
); );
}); });
add_test(function(test_resendVerificationEmail_error_handling) {
do_print("= resendVerificationEmail smoke test =");
let user = FxAccountsManager._fxAccounts._signedInUser;
FxAccountsManager._fxAccounts._signedInUser.verified = false;
FxAccountsManager.resendVerificationEmail().then(
(success) => {
do_check_true(success);
},
(error) => {
do_throw("Unexpected failure");
}
);
// Here we verify that when FxAccounts.resendVerificationEmail
// throws an error, we gracefully handle it in the reject() channel.
FxAccountsManager._fxAccounts._signedInUser = null;
FxAccountsManager.resendVerificationEmail().then(
(success) => {
do_throw("Unexpected success");
},
(error) => {
do_check_eq(error.error, ERROR_SERVER_ERROR);
}
);
FxAccountsManager._fxAccounts._signedInUser = user;
run_next_test();
});
add_test(function(test_verificationStatus_unverified_session_unverified_user) { add_test(function(test_verificationStatus_unverified_session_unverified_user) {
do_print("= verificationStatus unverified session and user ="); do_print("= verificationStatus unverified session and user =");
FakeFxAccountsClient._verified = false; FakeFxAccountsClient._verified = false;

Просмотреть файл

@ -190,7 +190,8 @@ class MochitestRunner(MozbuildObject):
jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None, jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None,
e10s=False, dmd=False, dump_output_directory=None, e10s=False, dmd=False, dump_output_directory=None,
dump_about_memory_after_test=False, dump_dmd_after_test=False, dump_about_memory_after_test=False, dump_dmd_after_test=False,
install_extension=None, quiet=False, environment=[], app_override=None, **kwargs): install_extension=None, quiet=False, environment=[], app_override=None,
useTestMediaDevices=False, **kwargs):
"""Runs a mochitest. """Runs a mochitest.
test_paths are path to tests. They can be a relative path from the test_paths are path to tests. They can be a relative path from the
@ -315,6 +316,7 @@ class MochitestRunner(MozbuildObject):
options.dumpOutputDirectory = dump_output_directory options.dumpOutputDirectory = dump_output_directory
options.quiet = quiet options.quiet = quiet
options.environment = environment options.environment = environment
options.useTestMediaDevices = useTestMediaDevices
options.failureFile = failure_file_path options.failureFile = failure_file_path
if install_extension != None: if install_extension != None:
@ -526,6 +528,12 @@ def MochitestCommand(func):
help="Sets the given variable in the application's environment") help="Sets the given variable in the application's environment")
func = setenv(func) func = setenv(func)
test_media = CommandArgument('--use-test-media-devices', default=False,
action='store_true',
dest='useTestMediaDevices',
help='Use test media device drivers for media testing.')
func = test_media(func)
app_override = CommandArgument('--app-override', default=None, action='store', app_override = CommandArgument('--app-override', default=None, action='store',
help="Override the default binary used to run tests with the path you provide, e.g. " \ help="Override the default binary used to run tests with the path you provide, e.g. " \
" --app-override /usr/bin/firefox . " \ " --app-override /usr/bin/firefox . " \

Просмотреть файл

@ -416,6 +416,12 @@ class MochitestOptions(optparse.OptionParser):
"help": "name of the pidfile to generate", "help": "name of the pidfile to generate",
"default": "", "default": "",
}], }],
[["--use-test-media-devices"],
{ "action": "store_true",
"default": False,
"dest": "useTestMediaDevices",
"help": "Use test media device drivers for media testing.",
}],
] ]
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -574,6 +580,13 @@ class MochitestOptions(optparse.OptionParser):
self.error('--dump-output-directory not a directory: %s' % self.error('--dump-output-directory not a directory: %s' %
options.dumpOutputDirectory) options.dumpOutputDirectory)
if options.useTestMediaDevices:
if not mozinfo.isLinux:
self.error('--use-test-media-devices is only supported on Linux currently')
for f in ['/usr/bin/gst-launch-0.10', '/usr/bin/pactl']:
if not os.path.isfile(f):
self.error('Missing binary %s required for --use-test-media-devices')
return options return options

Просмотреть файл

@ -12,6 +12,7 @@ import sys
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__))) SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
sys.path.insert(0, SCRIPT_DIR); sys.path.insert(0, SCRIPT_DIR);
import ctypes
import glob import glob
import json import json
import mozcrash import mozcrash
@ -754,11 +755,123 @@ class SSLTunnel:
if os.path.exists(self.configFile): if os.path.exists(self.configFile):
os.remove(self.configFile) os.remove(self.configFile)
def checkAndConfigureV4l2loopback(device):
'''
Determine if a given device path is a v4l2loopback device, and if so
toggle a few settings on it via fcntl. Very linux-specific.
Returns (status, device name) where status is a boolean.
'''
if not mozinfo.isLinux:
return False, ''
libc = ctypes.cdll.LoadLibrary('libc.so.6')
O_RDWR = 2
# These are from linux/videodev2.h
class v4l2_capability(ctypes.Structure):
_fields_ = [
('driver', ctypes.c_char * 16),
('card', ctypes.c_char * 32),
('bus_info', ctypes.c_char * 32),
('version', ctypes.c_uint32),
('capabilities', ctypes.c_uint32),
('device_caps', ctypes.c_uint32),
('reserved', ctypes.c_uint32 * 3)
]
VIDIOC_QUERYCAP = 0x80685600
fd = libc.open(device, O_RDWR)
if fd < 0:
return False, ''
vcap = v4l2_capability()
if libc.ioctl(fd, VIDIOC_QUERYCAP, ctypes.byref(vcap)) != 0:
return False, ''
if vcap.driver != 'v4l2 loopback':
return False, ''
class v4l2_control(ctypes.Structure):
_fields_ = [
('id', ctypes.c_uint32),
('value', ctypes.c_int32)
]
# These are private v4l2 control IDs, see:
# https://github.com/umlaeute/v4l2loopback/blob/fd822cf0faaccdf5f548cddd9a5a3dcebb6d584d/v4l2loopback.c#L131
KEEP_FORMAT = 0x8000000
SUSTAIN_FRAMERATE = 0x8000001
VIDIOC_S_CTRL = 0xc008561c
control = v4l2_control()
control.id = KEEP_FORMAT
control.value = 1
libc.ioctl(fd, VIDIOC_S_CTRL, ctypes.byref(control))
control.id = SUSTAIN_FRAMERATE
control.value = 1
libc.ioctl(fd, VIDIOC_S_CTRL, ctypes.byref(control))
libc.close(fd)
return True, vcap.card
def findTestMediaDevices():
'''
Find the test media devices configured on this system, and return a dict
containing information about them. The dict will have keys for 'audio'
and 'video', each containing the name of the media device to use.
If audio and video devices could not be found, return None.
This method is only currently implemented for Linux.
'''
if not mozinfo.isLinux:
return None
info = {}
# Look for a v4l2loopback device.
name = None
device = None
for dev in sorted(glob.glob('/dev/video*')):
result, name_ = checkAndConfigureV4l2loopback(dev)
if result:
name = name_
device = dev
break
if not (name and device):
log.error('Couldn\'t find a v4l2loopback video device')
return None
# Feed it a frame of output so it has something to display
subprocess.check_call(['/usr/bin/gst-launch-0.10', 'videotestsrc',
'pattern=green', 'num-buffers=1', '!',
'v4l2sink', 'device=%s' % device])
info['video'] = name
# Use pactl to see if the PulseAudio module-sine-source module is loaded.
def sine_source_loaded():
o = subprocess.check_output(['/usr/bin/pactl', 'list', 'short', 'modules'])
return filter(lambda x: 'module-sine-source' in x, o.splitlines())
if not sine_source_loaded():
# Load module-sine-source
subprocess.check_call(['/usr/bin/pactl', 'load-module',
'module-sine-source'])
if not sine_source_loaded():
log.error('Couldn\'t load module-sine-source')
return None
# Hardcode the name since it's always the same.
info['audio'] = 'Sine source at 440 Hz'
return info
class Mochitest(MochitestUtilsMixin): class Mochitest(MochitestUtilsMixin):
certdbNew = False certdbNew = False
sslTunnel = None sslTunnel = None
vmwareHelper = None vmwareHelper = None
DEFAULT_TIMEOUT = 60.0 DEFAULT_TIMEOUT = 60.0
mediaDevices = None
# XXX use automation.py for test name to avoid breaking legacy # XXX use automation.py for test name to avoid breaking legacy
# TODO: replace this with 'runtests.py' or 'mochitest' or the like # TODO: replace this with 'runtests.py' or 'mochitest' or the like
@ -877,6 +990,11 @@ class Mochitest(MochitestUtilsMixin):
'ws': options.sslPort 'ws': options.sslPort
} }
# See if we should use fake media devices.
if options.useTestMediaDevices:
prefs['media.audio_loopback_dev'] = self.mediaDevices['audio']
prefs['media.video_loopback_dev'] = self.mediaDevices['video']
# create a profile # create a profile
self.profile = Profile(profile=options.profilePath, self.profile = Profile(profile=options.profilePath,
@ -1225,6 +1343,13 @@ class Mochitest(MochitestUtilsMixin):
options.debuggerArgs, options.debuggerArgs,
options.debuggerInteractive) options.debuggerInteractive)
if options.useTestMediaDevices:
devices = findTestMediaDevices()
if not devices:
log.error("Could not find test media devices to use")
return 1
self.mediaDevices = devices
self.leak_report_file = os.path.join(options.profilePath, "runtests_leaks.log") self.leak_report_file = os.path.join(options.profilePath, "runtests_leaks.log")
browserEnv = self.buildBrowserEnv(options, debuggerInfo is not None) browserEnv = self.buildBrowserEnv(options, debuggerInfo is not None)

Просмотреть файл

@ -117,10 +117,22 @@ if (LINUX) {
yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true }); yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true });
} }
yield OS.File.removeDir(installPath, { ignoreAbsent: true }); let removed = false;
do {
try {
yield OS.File.removeDir(installPath, { ignoreAbsent: true });
yield OS.File.remove(desktopShortcut, { ignoreAbsent: true }); yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true }); yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
removed = true;
} catch (ex if ex instanceof OS.File.Error &&
(ex.winLastError == OS.Constants.Win.ERROR_SUCCESS ||
ex.winLastError == OS.Constants.Win.ERROR_SHARING_VIOLATION)) {
// Wait 100 ms before attempting to remove again.
yield wait(100);
}
} while (!removed);
}); });
}; };
} else if (MAC) { } else if (MAC) {

Просмотреть файл

@ -117,10 +117,22 @@ if (LINUX) {
yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true }); yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true });
} }
yield OS.File.removeDir(installPath, { ignoreAbsent: true }); let removed = false;
do {
try {
yield OS.File.removeDir(installPath, { ignoreAbsent: true });
yield OS.File.remove(desktopShortcut, { ignoreAbsent: true }); yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true }); yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
removed = true;
} catch (ex if ex instanceof OS.File.Error &&
(ex.winLastError == OS.Constants.Win.ERROR_SUCCESS ||
ex.winLastError == OS.Constants.Win.ERROR_SHARING_VIOLATION)) {
// Wait 100 ms before attempting to remove again.
yield wait(100);
}
} while (!removed);
}); });
}; };
} else if (MAC) { } else if (MAC) {

Просмотреть файл

@ -122,10 +122,22 @@ if (LINUX) {
yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true }); yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true });
} }
yield OS.File.removeDir(installPath, { ignoreAbsent: true }); let removed = false;
do {
try {
yield OS.File.removeDir(installPath, { ignoreAbsent: true });
yield OS.File.remove(desktopShortcut, { ignoreAbsent: true }); yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true }); yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
removed = true;
} catch (ex if ex instanceof OS.File.Error &&
(ex.winLastError == OS.Constants.Win.ERROR_SUCCESS ||
ex.winLastError == OS.Constants.Win.ERROR_SHARING_VIOLATION)) {
// Wait 100 ms before attempting to remove again.
yield wait(100);
}
} while (!removed);
}); });
}; };
} else if (MAC) { } else if (MAC) {

Просмотреть файл

@ -127,10 +127,22 @@ if (LINUX) {
yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true }); yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true });
} }
yield OS.File.removeDir(installPath, { ignoreAbsent: true }); let removed = false;
do {
try {
yield OS.File.removeDir(installPath, { ignoreAbsent: true });
yield OS.File.remove(desktopShortcut, { ignoreAbsent: true }); yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true }); yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
removed = true;
} catch (ex if ex instanceof OS.File.Error &&
(ex.winLastError == OS.Constants.Win.ERROR_SUCCESS ||
ex.winLastError == OS.Constants.Win.ERROR_SHARING_VIOLATION)) {
// Wait 100 ms before attempting to remove again.
yield wait(100);
}
} while (!removed);
}); });
}; };
} else if (MAC) { } else if (MAC) {

Просмотреть файл

@ -127,10 +127,22 @@ if (LINUX) {
yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true }); yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true });
} }
yield OS.File.removeDir(installPath, { ignoreAbsent: true }); let removed = false;
do {
try {
yield OS.File.removeDir(installPath, { ignoreAbsent: true });
yield OS.File.remove(desktopShortcut, { ignoreAbsent: true }); yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true }); yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
removed = true;
} catch (ex if ex instanceof OS.File.Error &&
(ex.winLastError == OS.Constants.Win.ERROR_SUCCESS ||
ex.winLastError == OS.Constants.Win.ERROR_SHARING_VIOLATION)) {
// Wait 100 ms before attempting to remove again.
yield wait(100);
}
} while (!removed);
}); });
}; };
} else if (MAC) { } else if (MAC) {

Просмотреть файл

@ -135,10 +135,22 @@ if (LINUX) {
yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true }); yield OS.File.removeDir(profileDir.parent.parent.path, { ignoreAbsent: true });
} }
yield OS.File.removeDir(installPath, { ignoreAbsent: true }); let removed = false;
do {
try {
yield OS.File.removeDir(installPath, { ignoreAbsent: true });
yield OS.File.remove(desktopShortcut, { ignoreAbsent: true }); yield OS.File.remove(desktopShortcut, { ignoreAbsent: true });
yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true }); yield OS.File.remove(startMenuShortcut, { ignoreAbsent: true });
removed = true;
} catch (ex if ex instanceof OS.File.Error &&
(ex.winLastError == OS.Constants.Win.ERROR_SUCCESS ||
ex.winLastError == OS.Constants.Win.ERROR_SHARING_VIOLATION)) {
// Wait 100 ms before attempting to remove again.
yield wait(100);
}
} while (!removed);
}); });
}; };
} else if (MAC) { } else if (MAC) {

Просмотреть файл

@ -1243,6 +1243,8 @@ private:
void MarkRoots(SliceBudget &aBudget); void MarkRoots(SliceBudget &aBudget);
void ScanRoots(bool aFullySynchGraphBuild); void ScanRoots(bool aFullySynchGraphBuild);
void ScanIncrementalRoots(); void ScanIncrementalRoots();
void ScanWhiteNodes(bool aFullySynchGraphBuild);
void ScanBlackNodes();
void ScanWeakMaps(); void ScanWeakMaps();
// returns whether anything was collected // returns whether anything was collected
@ -2680,50 +2682,6 @@ FloodBlackNode(uint32_t& aWhiteNodeCount, bool& aFailed, PtrInfo* aPi)
MOZ_ASSERT(aPi->mColor == black || !aPi->mParticipant, "FloodBlackNode should make aPi black"); MOZ_ASSERT(aPi->mColor == black || !aPi->mParticipant, "FloodBlackNode should make aPi black");
} }
struct scanVisitor
{
scanVisitor(uint32_t &aWhiteNodeCount, bool &aFailed, bool aWasIncremental)
: mWhiteNodeCount(aWhiteNodeCount), mFailed(aFailed),
mWasIncremental(aWasIncremental)
{
}
bool ShouldVisitNode(PtrInfo const *pi)
{
return pi->mColor == grey;
}
MOZ_NEVER_INLINE void VisitNode(PtrInfo *pi)
{
if (pi->mInternalRefs > pi->mRefCount && pi->mRefCount > 0) {
// If we found more references to an object than its ref count, then
// the object should have already been marked as an incremental
// root. Note that this is imprecise, because pi could have been
// marked black for other reasons. Always fault if we weren't
// incremental, as there were no incremental roots in that case.
if (!mWasIncremental || pi->mColor != black) {
Fault("traversed refs exceed refcount", pi);
}
}
if (pi->mInternalRefs == pi->mRefCount || pi->mRefCount == 0) {
pi->mColor = white;
++mWhiteNodeCount;
} else {
FloodBlackNode(mWhiteNodeCount, mFailed, pi);
}
}
void Failed() {
mFailed = true;
}
private:
uint32_t &mWhiteNodeCount;
bool &mFailed;
bool mWasIncremental;
};
// Iterate over the WeakMaps. If we mark anything while iterating // Iterate over the WeakMaps. If we mark anything while iterating
// over the WeakMaps, we must iterate over all of the WeakMaps again. // over the WeakMaps, we must iterate over all of the WeakMaps again.
void void
@ -2742,10 +2700,6 @@ nsCycleCollector::ScanWeakMaps()
uint32_t kdColor = wm->mKeyDelegate ? wm->mKeyDelegate->mColor : black; uint32_t kdColor = wm->mKeyDelegate ? wm->mKeyDelegate->mColor : black;
uint32_t vColor = wm->mVal ? wm->mVal->mColor : black; uint32_t vColor = wm->mVal ? wm->mVal->mColor : black;
// All non-null weak mapping maps, keys and values are
// roots (in the sense of WalkFromRoots) in the cycle
// collector graph, and thus should have been colored
// either black or white in ScanRoots().
MOZ_ASSERT(mColor != grey, "Uncolored weak map"); MOZ_ASSERT(mColor != grey, "Uncolored weak map");
MOZ_ASSERT(kColor != grey, "Uncolored weak map key"); MOZ_ASSERT(kColor != grey, "Uncolored weak map key");
MOZ_ASSERT(kdColor != grey, "Uncolored weak map key delegate"); MOZ_ASSERT(kdColor != grey, "Uncolored weak map key delegate");
@ -2895,6 +2849,68 @@ nsCycleCollector::ScanIncrementalRoots()
} }
} }
// Mark nodes white and make sure their refcounts are ok.
// No nodes are marked black during this pass to ensure that refcount
// checking is run on all nodes not marked black by ScanIncrementalRoots.
void
nsCycleCollector::ScanWhiteNodes(bool aFullySynchGraphBuild)
{
NodePool::Enumerator nodeEnum(mGraph.mNodes);
while (!nodeEnum.IsDone()) {
PtrInfo* pi = nodeEnum.GetNext();
if (pi->mColor == black) {
// Incremental roots can be in a nonsensical state, so don't
// check them. This will miss checking nodes that are merely
// reachable from incremental roots.
MOZ_ASSERT(!aFullySynchGraphBuild,
"In a synch CC, no nodes should be marked black early on.");
continue;
}
MOZ_ASSERT(pi->mColor == grey);
if (!pi->mParticipant) {
// This node has been deleted, so it could be in a mangled state, but
// that's okay because we're not going to look at it again.
continue;
}
if (pi->mInternalRefs == pi->mRefCount || pi->mRefCount == 0) {
pi->mColor = white;
++mWhiteNodeCount;
continue;
}
if (MOZ_LIKELY(pi->mInternalRefs < pi->mRefCount)) {
// This node will get marked black in the next pass.
continue;
}
Fault("Traversed refs exceed refcount", pi);
}
}
// Any remaining grey nodes that haven't already been deleted must be alive,
// so mark them and their children black. Any nodes that are black must have
// already had their children marked black, so there's no need to look at them
// again. This pass may turn some white nodes to black.
void
nsCycleCollector::ScanBlackNodes()
{
bool failed = false;
NodePool::Enumerator nodeEnum(mGraph.mNodes);
while (!nodeEnum.IsDone()) {
PtrInfo* pi = nodeEnum.GetNext();
if (pi->mColor == grey && pi->mParticipant) {
FloodBlackNode(mWhiteNodeCount, failed, pi);
}
}
if (failed) {
NS_ASSERTION(false, "Ran out of memory in ScanBlackNodes");
CC_TELEMETRY(_OOM, true);
}
}
void void
nsCycleCollector::ScanRoots(bool aFullySynchGraphBuild) nsCycleCollector::ScanRoots(bool aFullySynchGraphBuild)
{ {
@ -2909,19 +2925,11 @@ nsCycleCollector::ScanRoots(bool aFullySynchGraphBuild)
} }
TimeLog timeLog; TimeLog timeLog;
ScanWhiteNodes(aFullySynchGraphBuild);
timeLog.Checkpoint("ScanRoots::ScanWhiteNodes");
// On the assumption that most nodes will be black, it's ScanBlackNodes();
// probably faster to use a GraphWalker than a timeLog.Checkpoint("ScanRoots::ScanBlackNodes");
// NodePool::Enumerator.
bool failed = false;
scanVisitor sv(mWhiteNodeCount, failed, !aFullySynchGraphBuild);
GraphWalker<scanVisitor>(sv).WalkFromRoots(mGraph);
timeLog.Checkpoint("ScanRoots::WalkFromRoots");
if (failed) {
NS_ASSERTION(false, "Ran out of memory in ScanRoots");
CC_TELEMETRY(_OOM, true);
}
// Scanning weak maps must be done last. // Scanning weak maps must be done last.
ScanWeakMaps(); ScanWeakMaps();