Merge m-c to fx-team. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-01-06 11:05:52 -05:00
commit b5a94e6300
269 changed files with 4482 additions and 2563 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<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="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<!-- 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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -19,13 +19,13 @@
<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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

View File

@ -17,10 +17,10 @@
</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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<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="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<!-- 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"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

View File

@ -19,13 +19,13 @@
<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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e0c735ec89df011ea7dd435087a9045ecff9ff9e">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<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="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<!-- 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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -17,10 +17,10 @@
</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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "c175a29477e68e70142687587844423a75dcf4cc",
"revision": "23fc9f3f470e238bacb1a6b8ca978db4e63e0b55",
"repo_path": "integration/gaia-central"
}

View File

@ -17,11 +17,11 @@
<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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>

View File

@ -15,7 +15,7 @@
<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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,10 +17,10 @@
</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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -17,12 +17,12 @@
<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="b77e0d56d197e0ee02d801a25c784130d888c9db"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="69ac77cfa938fae2763ac426a80ca6e5feb6ad25"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8aee09c106f479f36c57b2a29af72d455e359211"/>
<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="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f59d8671fff36da22236a4b270b93195889b7ff1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e48bfe5f59bd54597d8304c42391a7849b8361f"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>

View File

@ -1790,6 +1790,7 @@ pref("print.enable_e10s_testing", true);
#ifdef NIGHTLY_BUILD
// Enable e10s add-on interposition by default.
pref("extensions.interposition.enabled", true);
pref("extensions.interposition.prefetching", true);
#endif
pref("browser.defaultbrowser.notificationbar", false);

View File

@ -838,6 +838,7 @@ nsDocShell::nsDocShell():
mAllowKeywordFixup(false),
mIsOffScreenBrowser(false),
mIsActive(true),
mIsPrerendered(false),
mIsAppTab(false),
mUseGlobalHistory(false),
mInPrivateBrowsing(false),
@ -3386,6 +3387,11 @@ nsDocShell::SetDocLoaderParent(nsDocLoader * aParent)
{
SetIsActive(value);
}
if (NS_SUCCEEDED(parentAsDocShell->GetIsPrerendered(&value))) {
if (value) {
SetIsPrerendered(true);
}
}
if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))) {
value = false;
}
@ -6052,6 +6058,22 @@ nsDocShell::GetIsActive(bool *aIsActive)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetIsPrerendered(bool aPrerendered)
{
MOZ_ASSERT(!aPrerendered || !mIsPrerendered,
"SetIsPrerendered(true) called on already prerendered docshell");
mIsPrerendered = aPrerendered;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetIsPrerendered(bool *aIsPrerendered)
{
*aIsPrerendered = mIsPrerendered;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetIsAppTab(bool aIsAppTab)
{
@ -8553,8 +8575,8 @@ nsDocShell::RestoreFromHistory()
// this.AddChild(child) calls child.SetDocLoaderParent(this), meaning
// that the child inherits our state. Among other things, this means
// that the child inherits our mIsActive and mInPrivateBrowsing, which
// is what we want.
// that the child inherits our mIsActive, mIsPrerendered and mInPrivateBrowsing,
// which is what we want.
AddChild(childItem);
childShell->SetAllowPlugins(allowPlugins);

View File

@ -877,6 +877,7 @@ protected:
bool mAllowKeywordFixup;
bool mIsOffScreenBrowser;
bool mIsActive;
bool mIsPrerendered;
bool mIsAppTab;
bool mUseGlobalHistory;
bool mInPrivateBrowsing;

View File

@ -54,7 +54,7 @@ interface nsITabParent;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(c2756385-bc54-417b-9ae4-c5a40053a2a3)]
[scriptable, builtinclass, uuid(fef3bae1-6673-4c49-9f5a-fcc075926730)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -619,6 +619,13 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
attribute boolean isActive;
/**
* Puts the docshell in prerendering mode. noscript because we want only
* native code to be able to put a docshell in prerendering.
*/
[noscript] void SetIsPrerendered(in boolean prerendered);
readonly attribute boolean isPrerendered;
/**
* The ID of the docshell in the session history.
*/

View File

@ -60,14 +60,8 @@ AnimationTimeline::FastForward(const TimeStamp& aTimeStamp)
return;
}
// Bug 1113413: If the refresh driver has just been restored from test
// control it's possible that aTimeStamp could be before the most recent
// refresh.
if (refreshDriver &&
aTimeStamp < refreshDriver->MostRecentRefresh()) {
mFastForwardTime = refreshDriver->MostRecentRefresh();
return;
}
MOZ_ASSERT(!refreshDriver || aTimeStamp >= refreshDriver->MostRecentRefresh(),
"aTimeStamp must be >= the refresh driver time");
// FIXME: For all animations attached to this timeline, we should mark
// their target elements as needing restyling. Otherwise, tasks that run

View File

@ -67,4 +67,36 @@ async_test(function(t) {
}, 'ready promise is rejected when a transition is cancelled by updating'
+ ' transition-property');
async_test(function(t) {
var div = addDiv(t);
// Set up pending transition
div.style.marginLeft = '0px';
window.getComputedStyle(div).marginLeft;
div.style.transition = 'margin-left 100s';
div.style.marginLeft = '100px';
window.getComputedStyle(div).marginLeft;
var player = div.getAnimationPlayers()[0];
assert_equals(player.playState, 'pending', 'Player is initially pending');
// Set up listeners on ready promise
player.ready.then(t.step_func(function() {
assert_unreached('ready promise was fulfilled');
})).catch(t.step_func(function(err) {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after transition was cancelled');
})).then(t.step_func(function() {
t.done();
}));
// Now update the transition to animate to something not-interpolable
div.style.marginLeft = 'auto';
window.getComputedStyle(div).marginLeft;
}, 'ready promise is rejected when a transition is cancelled by changing'
+ ' the transition property to something not interpolable');
</script>

View File

@ -7,7 +7,7 @@ skip-if = buildapp == 'mulet'
[css-animations/test_animations-dynamic-changes.html]
[css-animations/test_animation-effect-name.html]
[css-animations/test_animation-pausing.html]
skip-if = os == "mac" && os_version == "10.8" # disabled until bug 1112480 lands
skip-if = os == "win" || (os == "mac" && os_version == "10.8") # disabled until bug 1112480 lands
[css-animations/test_animation-player-playstate.html]
[css-animations/test_animation-player-ready.html]
[css-animations/test_animation-target.html]

View File

@ -407,7 +407,13 @@ this.PermissionsTable = { geolocation: {
privileged: PROMPT_ACTION,
certified: ALLOW_ACTION
},
"nfc": {
"audio-capture:3gpp": {
app: DENY_ACTION,
trusted: DENY_ACTION,
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
"nfc": {
app: DENY_ACTION,
trusted: DENY_ACTION,
privileged: ALLOW_ACTION,

View File

@ -201,11 +201,7 @@ EventSource::Init(nsISupports* aOwner,
// The conditional here is historical and not necessarily sane.
if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
const char *filename;
if (nsJSUtils::GetCallingLocation(cx, &filename, &mScriptLine)) {
mScriptFile.AssignASCII(filename);
}
nsJSUtils::GetCallingLocation(cx, mScriptFile, &mScriptLine);
mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
}

View File

@ -83,8 +83,11 @@ WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx,
return true;
}
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy));
if (HasPropertyOnPrototype(aCx, aProxy, aId)) {
bool hasOnPrototype;
if (!HasPropertyOnPrototype(aCx, aProxy, aId, &hasOnPrototype)) {
return false;
}
if (hasOnPrototype) {
return true;
}
@ -94,6 +97,7 @@ WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx,
}
// Grab the DOM window.
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy));
nsGlobalWindow* win = xpc::WindowOrNull(global);
if (win->Length() > 0) {
nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str);

View File

@ -3364,12 +3364,7 @@ nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
if (!aLineNumber) {
JSContext *cx = GetCurrentJSContext();
if (cx) {
const char* filename;
uint32_t lineno;
if (nsJSUtils::GetCallingLocation(cx, &filename, &lineno)) {
spec = filename;
aLineNumber = lineno;
}
nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber);
}
}
if (spec.IsEmpty() && aURI)

View File

@ -112,6 +112,9 @@ nsElementFrameLoaderOwner::EnsureFrameLoader()
// Strangely enough, this method doesn't actually ensure that the
// frameloader exists. It's more of a best-effort kind of thing.
mFrameLoader = nsFrameLoader::Create(thisElement, mNetworkCreated);
if (mIsPrerendered) {
mFrameLoader->SetIsPrerendered();
}
}
NS_IMETHODIMP
@ -135,6 +138,14 @@ nsElementFrameLoaderOwner::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsElementFrameLoaderOwner::SetIsPrerendered()
{
MOZ_ASSERT(!mFrameLoader, "Please call SetIsPrerendered before frameLoader is created");
mIsPrerendered = true;
return NS_OK;
}
nsresult
nsElementFrameLoaderOwner::LoadSrc()
{

View File

@ -33,6 +33,7 @@ class nsElementFrameLoaderOwner : public nsIFrameLoaderOwner
public:
explicit nsElementFrameLoaderOwner(mozilla::dom::FromParser aFromParser)
: mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
, mIsPrerendered(false)
, mBrowserFrameListenersRegistered(false)
, mFrameLoaderCreationDisallowed(false)
{
@ -70,6 +71,7 @@ protected:
*/
bool mNetworkCreated;
bool mIsPrerendered;
bool mBrowserFrameListenersRegistered;
bool mFrameLoaderCreationDisallowed;
};

View File

@ -154,6 +154,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
: mOwnerContent(aOwner)
, mAppIdSentToPermissionManager(nsIScriptSecurityManager::NO_APP_ID)
, mDetachedSubdocViews(nullptr)
, mIsPrerendered(false)
, mDepthTooGreat(false)
, mIsTopLevelContent(false)
, mDestroyCalled(false)
@ -295,6 +296,15 @@ nsFrameLoader::LoadURI(nsIURI* aURI)
return rv;
}
NS_IMETHODIMP
nsFrameLoader::SetIsPrerendered()
{
MOZ_ASSERT(!mDocShell, "Please call SetIsPrerendered before docShell is created");
mIsPrerendered = true;
return NS_OK;
}
nsresult
nsFrameLoader::ReallyStartLoading()
{
@ -1613,6 +1623,11 @@ nsFrameLoader::MaybeCreateDocShell()
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
if (mIsPrerendered) {
nsresult rv = mDocShell->SetIsPrerendered(true);
NS_ENSURE_SUCCESS(rv,rv);
}
// Apply sandbox flags even if our owner is not an iframe, as this copies
// flags from our owning content's owning document.
uint32_t sandboxFlags = 0;

View File

@ -331,6 +331,7 @@ private:
// a reframe, so that we know not to restore the presentation.
nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
bool mIsPrerendered : 1;
bool mDepthTooGreat : 1;
bool mIsTopLevelContent : 1;
bool mDestroyCalled : 1;

View File

@ -951,6 +951,7 @@ GK_ATOM(precedingSibling, "preceding-sibling")
GK_ATOM(predicate, "predicate")
GK_ATOM(prefix, "prefix")
GK_ATOM(preload, "preload")
GK_ATOM(prerendered, "prerendered")
GK_ATOM(preserve, "preserve")
GK_ATOM(preserveSpace, "preserve-space")
GK_ATOM(preventdefault, "preventdefault")

View File

@ -1118,6 +1118,8 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mCanSkipCCGeneration(0),
mVRDevicesInitialized(false)
{
AssertIsOnMainThread();
nsLayoutStatics::AddRef();
// Initialize the PRCList (this).
@ -1218,10 +1220,23 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
}
}
#ifdef DEBUG
/* static */
void
nsGlobalWindow::AssertIsOnMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
}
#endif // DEBUG
/* static */
void
nsGlobalWindow::Init()
{
AssertIsOnMainThread();
CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID, &gEntropyCollector);
NS_ASSERTION(gEntropyCollector,
"gEntropyCollector should have been initialized!");
@ -1245,6 +1260,8 @@ DisconnectEventTargetObjects(nsPtrHashKey<DOMEventTargetHelper>* aKey,
nsGlobalWindow::~nsGlobalWindow()
{
AssertIsOnMainThread();
mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nullptr);
mEventTargetObjects.Clear();
@ -1363,6 +1380,8 @@ nsGlobalWindow::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
void
nsGlobalWindow::ShutDown()
{
AssertIsOnMainThread();
if (gDumpFile && gDumpFile != stdout) {
fclose(gDumpFile);
}

View File

@ -334,6 +334,14 @@ public:
typedef mozilla::TimeDuration TimeDuration;
typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
static void
AssertIsOnMainThread()
#ifdef DEBUG
;
#else
{ }
#endif
// public methods
nsPIDOMWindow* GetPrivateParent();
@ -670,6 +678,8 @@ public:
}
static nsGlobalWindow* GetOuterWindowWithId(uint64_t aWindowID) {
AssertIsOnMainThread();
if (!sWindowsById) {
return nullptr;
}
@ -679,6 +689,8 @@ public:
}
static nsGlobalWindow* GetInnerWindowWithId(uint64_t aInnerWindowID) {
AssertIsOnMainThread();
if (!sWindowsById) {
return nullptr;
}
@ -688,6 +700,8 @@ public:
}
static WindowByIdTable* GetWindowsTable() {
AssertIsOnMainThread();
return sWindowsById;
}

View File

@ -16,7 +16,7 @@ interface nsIDOMElement;
interface nsITabParent;
interface nsILoadContext;
[scriptable, builtinclass, uuid(7600aa92-88dc-491c-896d-0564159b6a66)]
[scriptable, builtinclass, uuid(28b6b043-46ec-412f-9be9-db22938b0d6d)]
interface nsIFrameLoader : nsISupports
{
/**
@ -49,6 +49,11 @@ interface nsIFrameLoader : nsISupports
*/
void loadURI(in nsIURI aURI);
/**
* Puts the frameloader in prerendering mode.
*/
void setIsPrerendered();
/**
* Destroy the frame loader and everything inside it. This will
* clear the weak owner content reference.
@ -192,7 +197,7 @@ class nsFrameLoader;
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
[scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)]
[scriptable, uuid(c4abebcf-55f3-47d4-af15-151311971255)]
interface nsIFrameLoaderOwner : nsISupports
{
/**
@ -201,6 +206,11 @@ interface nsIFrameLoaderOwner : nsISupports
readonly attribute nsIFrameLoader frameLoader;
[noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader();
/**
* Puts the FrameLoaderOwner in prerendering mode.
*/
void setIsPrerendered();
/**
* Swap frame loaders with the given nsIFrameLoaderOwner. This may
* only be posible in a very limited range of circumstances, or

View File

@ -173,11 +173,8 @@ CheckCSPForEval(JSContext* aCx, nsGlobalWindow* aWindow, ErrorResult& aError)
// Get the calling location.
uint32_t lineNum = 0;
const char *fileName;
nsAutoString fileNameString;
if (nsJSUtils::GetCallingLocation(aCx, &fileName, &lineNum)) {
AppendUTF8toUTF16(fileName, fileNameString);
} else {
if (!nsJSUtils::GetCallingLocation(aCx, fileNameString, &lineNum)) {
fileNameString.AssignLiteral("unknown");
}
@ -233,10 +230,7 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
}
// Get the calling location.
const char *filename;
if (nsJSUtils::GetCallingLocation(aCx, &filename, &mLineNo)) {
mFileName.Assign(filename);
}
nsJSUtils::GetCallingLocation(aCx, mFileName, &mLineNo);
}
nsJSScriptTimeoutHandler::~nsJSScriptTimeoutHandler()
@ -353,10 +347,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
AssignJSFlatString(mExpr, expr);
// Get the calling location.
const char *filename;
if (nsJSUtils::GetCallingLocation(cx, &filename, &mLineNo)) {
mFileName.Assign(filename);
}
nsJSUtils::GetCallingLocation(cx, mFileName, &mLineNo);
} else if (funobj) {
*aAllowEval = true;

View File

@ -34,19 +34,28 @@
using namespace mozilla::dom;
bool
nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
nsJSUtils::GetCallingLocation(JSContext* aContext, nsACString& aFilename,
uint32_t* aLineno)
{
JS::AutoFilename filename;
unsigned lineno = 0;
if (!JS::DescribeScriptedCaller(aContext, &filename, &lineno)) {
if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno)) {
return false;
}
*aFilename = filename.get();
*aLineno = lineno;
aFilename.Assign(filename.get());
return true;
}
bool
nsJSUtils::GetCallingLocation(JSContext* aContext, nsAString& aFilename,
uint32_t* aLineno)
{
JS::AutoFilename filename;
if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno)) {
return false;
}
aFilename.Assign(NS_ConvertUTF8toUTF16(filename.get()));
return true;
}

View File

@ -32,7 +32,9 @@ class Element;
class nsJSUtils
{
public:
static bool GetCallingLocation(JSContext* aContext, const char* *aFilename,
static bool GetCallingLocation(JSContext* aContext, nsACString& aFilename,
uint32_t* aLineno);
static bool GetCallingLocation(JSContext* aContext, nsAString& aFilename,
uint32_t* aLineno);
static nsIScriptGlobalObject *GetStaticScriptGlobal(JSObject* aObj);

View File

@ -324,6 +324,7 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
// if aDeep is true, deal with aNode's children (and recurse into their
// attributes and children).
nsAutoScriptBlocker scriptBlocker;
AutoJSContext cx;
nsresult rv;

View File

@ -1199,6 +1199,12 @@ nsObjectLoadingContent::GetFrameLoader()
return loader.forget();
}
NS_IMETHODIMP
nsObjectLoadingContent::SetIsPrerendered()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader)
{

View File

@ -366,6 +366,10 @@ nsresult TestPaths() {
"connect-src http://www.example.com/foo;sessionid=12,34" },
{ "connect-src http://test.com/pathIncludingAz19-._~!$&'()*+=:@",
"connect-src http://test.com/pathincludingaz19-._~!$&'()*+=:@" },
{ "script-src http://www.example.com:88/.js",
"script-src http://www.example.com:88/.js" },
{ "script-src https://foo.com/_abc/abc_/_/_a_b_c_",
"script-src https://foo.com/_abc/abc_/_/_a_b_c_" }
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -490,8 +494,6 @@ nsresult TestPoliciesWithInvalidSrc() {
"script-src 'none'" },
{ "script-src http://www.example.com:88//path-1",
"script-src 'none'" },
{ "script-src http://www.example.com:88/.js",
"script-src 'none'" },
{ "script-src http://www.example.com:88.js",
"script-src 'none'" },
{ "script-src http://www.example.com:*.js",

View File

@ -92,7 +92,10 @@ public:
protected:
JS::Rooted<JSObject*> mGlobalJSObject;
JSContext* mCx;
mutable nsISupports* mGlobalObject;
mutable nsISupports* MOZ_UNSAFE_REF("Valid because GlobalObject is a stack "
"class, and mGlobalObject points to the "
"global, so it won't be destroyed as long "
"as GlobalObject lives on the stack") mGlobalObject;
};
// Class for representing optional arguments.

View File

@ -1613,7 +1613,7 @@ NativePropertyHooks sWorkerNativePropertyHooks = {
bool
GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, bool* found,
JS::Value* vp)
JS::MutableHandle<JS::Value> vp)
{
JS::Rooted<JSObject*> proto(cx);
if (!js::GetObjectProto(cx, proxy, &proto)) {
@ -1624,33 +1624,31 @@ GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
return true;
}
bool hasProp;
if (!JS_HasPropertyById(cx, proto, id, &hasProp)) {
if (!JS_HasPropertyById(cx, proto, id, found)) {
return false;
}
*found = hasProp;
if (!hasProp || !vp) {
if (!*found) {
return true;
}
JS::Rooted<JS::Value> value(cx);
if (!JS_ForwardGetPropertyTo(cx, proto, id, proxy, &value)) {
return false;
}
*vp = value;
return true;
return JS_ForwardGetPropertyTo(cx, proto, id, proxy, vp);
}
bool
HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id)
JS::Handle<jsid> id, bool* has)
{
bool found;
// We ignore an error from GetPropertyOnPrototype. We pass nullptr
// for vp so that GetPropertyOnPrototype won't actually do a get.
return !GetPropertyOnPrototype(cx, proxy, id, &found, nullptr) || found;
JS::Rooted<JSObject*> proto(cx);
if (!js::GetObjectProto(cx, proxy, &proto)) {
return false;
}
if (!proto) {
*has = false;
return true;
}
return JS_HasPropertyById(cx, proto, id, has);
}
bool
@ -1670,7 +1668,16 @@ AppendNamedPropertyIds(JSContext* cx, JS::Handle<JSObject*> proxy,
return false;
}
if (shadowPrototypeProperties || !HasPropertyOnPrototype(cx, proxy, id)) {
bool shouldAppend = shadowPrototypeProperties;
if (!shouldAppend) {
bool has;
if (!HasPropertyOnPrototype(cx, proxy, id, &has)) {
return false;
}
shouldAppend = !has;
}
if (shouldAppend) {
if (!props.append(id)) {
return false;
}

View File

@ -1810,16 +1810,15 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
bool
ThrowConstructorWithoutNew(JSContext* cx, const char* name);
// vp is allowed to be null; in that case no get will be attempted,
// and *found will simply indicate whether the property exists.
bool
GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, bool* found,
JS::Value* vp);
JS::MutableHandle<JS::Value> vp);
//
bool
HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id);
JS::Handle<jsid> id, bool* has);
// Append the property names in "names" to "props". If

View File

@ -10104,15 +10104,41 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
"return true;\n" % (readonly, enumerable))
templateValues = {'jsvalRef': 'desc.value()', 'jsvalHandle': 'desc.value()',
'obj': 'proxy', 'successCode': fillDescriptor}
condition = "!HasPropertyOnPrototype(cx, proxy, id)"
computeCondition = dedent("""
bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
}
callNamedGetter = !hasOnProto;
""")
if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
condition = "(!isXray || %s)" % condition
condition = "!ignoreNamedProps && " + condition
computeCondition = fill("""
if (!isXray) {
callNamedGetter = true;
} else {
$*{hasOnProto}
}
""",
hasOnProto=computeCondition)
outerCondition = "!ignoreNamedProps"
if self.descriptor.supportsIndexedProperties():
condition = "!IsArrayIndex(index) && " + condition
namedGet = (CGIfWrapper(CGProxyNamedGetter(self.descriptor, templateValues),
condition).define() +
"\n")
outerCondition = "!IsArrayIndex(index) && " + outerCondition
namedGet = fill("""
bool callNamedGetter = false;
if (${outerCondition}) {
$*{computeCondition}
}
if (callNamedGetter) {
$*{namedGetCode}
}
""",
outerCondition=outerCondition,
computeCondition=computeCondition,
namedGetCode=CGProxyNamedGetter(self.descriptor, templateValues).define())
namedGet += "\n"
else:
namedGet = ""
@ -10345,8 +10371,16 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
""",
namedBody=namedBody)
if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
delete = CGIfWrapper(CGGeneric(delete),
"!HasPropertyOnPrototype(cx, proxy, id)").define()
delete = fill("""
bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
}
if (!hasOnProto) {
$*{delete}
}
""",
delete=delete)
delete += dedent("""
@ -10485,8 +10519,17 @@ class CGDOMJSProxyHandler_hasOwn(ClassMethod):
""",
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define())
if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
named = CGIfWrapper(CGGeneric(named + "return true;\n"),
"!HasPropertyOnPrototype(cx, proxy, id)").define()
named = fill("""
bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
}
if (!hasOnProto) {
$*{protoLacksProperty}
return true;
}
""",
protoLacksProperty=named)
named += "*bp = false;\n"
else:
named += "\n"
@ -10593,7 +10636,7 @@ class CGDOMJSProxyHandler_get(ClassMethod):
getOnPrototype = dedent("""
bool foundOnPrototype;
if (!GetPropertyOnPrototype(cx, proxy, id, &foundOnPrototype, vp.address())) {
if (!GetPropertyOnPrototype(cx, proxy, id, &foundOnPrototype, vp)) {
return false;
}

View File

@ -146,15 +146,22 @@ static const double THRESHOLD_LOW_PLAYBACKRATE_AUDIO = 0.5;
// start playing afterward, so we need to stay alive.
// 4) If autoplay could start playback in this element (if we got enough data),
// then we need to stay alive.
// 5) if the element is currently loading and not suspended,
// script might be waiting for progress events or a 'suspend' event,
// so we need to stay alive. If we're already suspended then (all other
// conditions being met) it's OK to just disappear without firing any more
// events, since we have the freedom to remain suspended indefinitely. Note
// 5) if the element is currently loading, not suspended, and its source is
// not a MediaSource, then script might be waiting for progress events or a
// 'stalled' or 'suspend' event, so we need to stay alive.
// If we're already suspended then (all other conditions being met),
// it's OK to just disappear without firing any more events,
// since we have the freedom to remain suspended indefinitely. Note
// that we could use this 'suspended' loophole to garbage-collect a suspended
// element in case 4 even if it had 'autoplay' set, but we choose not to.
// If someone throws away all references to a loading 'autoplay' element
// sound should still eventually play.
// 6) If the source is a MediaSource, most loading events will not fire unless
// appendBuffer() is called on a SourceBuffer, in which case something is
// already referencing the SourceBuffer, which keeps the associated media
// element alive. Further, a MediaSource will never time out the resource
// fetch, and so should not keep the media element alive if it is
// unreferenced. A pending 'stalled' event keeps the media element alive.
//
// Media elements owned by inactive documents (i.e. documents not contained in any
// document viewer) should never hold a self-reference because none of the
@ -684,7 +691,7 @@ void HTMLMediaElement::AbortExistingLoads()
DispatchAsyncEvent(NS_LITERAL_STRING("emptied"));
}
// We may have changed mPaused, mAutoplaying, mNetworkState and other
// We may have changed mPaused, mAutoplaying, and other
// things which can affect AddRemoveSelfReference
AddRemoveSelfReference();
@ -699,7 +706,6 @@ void HTMLMediaElement::NoSupportedMediaSourceError()
mError = new MediaError(this, nsIDOMMediaError::MEDIA_ERR_SRC_NOT_SUPPORTED);
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE);
DispatchAsyncEvent(NS_LITERAL_STRING("error"));
// This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
ChangeDelayLoadStatus(false);
}
@ -814,7 +820,6 @@ void HTMLMediaElement::SelectResource()
// The media element has neither a src attribute nor any source
// element children, abort the load.
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
// This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
ChangeDelayLoadStatus(false);
return;
}
@ -822,8 +827,6 @@ void HTMLMediaElement::SelectResource()
ChangeDelayLoadStatus(true);
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_LOADING);
// Load event was delayed, and still is, so no need to call
// AddRemoveSelfReference, since it must still be held
DispatchAsyncEvent(NS_LITERAL_STRING("loadstart"));
// Delay setting mIsRunningSeletResource until after UpdatePreloadAction
@ -2133,7 +2136,6 @@ HTMLMediaElement::ResetConnectionState()
FireTimeUpdate(false);
DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
AddRemoveSelfReference();
ChangeDelayLoadStatus(false);
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
}
@ -2858,7 +2860,6 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
AddRemoveSelfReference();
// FirstFrameLoaded() will be called when the stream has current data.
}
@ -3010,7 +3011,6 @@ void HTMLMediaElement::Error(uint16_t aErrorCode)
} else {
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
}
AddRemoveSelfReference();
ChangeDelayLoadStatus(false);
}
@ -3084,7 +3084,6 @@ void HTMLMediaElement::DownloadSuspended()
}
if (mBegun) {
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
AddRemoveSelfReference();
}
}
@ -3092,7 +3091,6 @@ void HTMLMediaElement::DownloadResumed(bool aForceNetworkLoading)
{
if (mBegun || aForceNetworkLoading) {
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_LOADING);
AddRemoveSelfReference();
}
}
@ -3145,6 +3143,8 @@ void HTMLMediaElement::CheckProgress(bool aHaveNewProgress)
// is more progress.
StopProgress();
}
AddRemoveSelfReference();
}
/* static */
@ -3358,6 +3358,9 @@ void HTMLMediaElement::ChangeNetworkState(nsMediaNetworkState aState)
// Fire 'suspend' event when entering NETWORK_IDLE and no error presented.
DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
}
// Changing mNetworkState affects AddRemoveSelfReference().
AddRemoveSelfReference();
}
bool HTMLMediaElement::CanActivateAutoplay()
@ -3628,7 +3631,8 @@ void HTMLMediaElement::AddRemoveSelfReference()
(!mPaused && mSrcStream && !mSrcStream->IsFinished()) ||
(mDecoder && mDecoder->IsSeeking()) ||
CanActivateAutoplay() ||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING);
(mMediaSource ? mProgressTimer :
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING));
if (needSelfReference != mHasSelfReference) {
mHasSelfReference = needSelfReference;

View File

@ -94,6 +94,18 @@ ASSERT_ICC_CONTACT_TYPE_EQUALITY(Sdn, CARD_CONTACT_TYPE_SDN);
#undef ASSERT_ICC_CONTACT_TYPE_EQUALITY
/**
* Enum IccMvnoType
*/
#define ASSERT_ICC_MVNO_TYPE_EQUALITY(webidlState, xpidlState) \
ASSERT_EQUALITY(IccMvnoType, webidlState, xpidlState)
ASSERT_ICC_MVNO_TYPE_EQUALITY(Imsi, CARD_MVNO_TYPE_IMSI);
ASSERT_ICC_MVNO_TYPE_EQUALITY(Spn, CARD_MVNO_TYPE_SPN);
ASSERT_ICC_MVNO_TYPE_EQUALITY(Gid, CARD_MVNO_TYPE_GID);
#undef ASSERT_ICC_MVNO_TYPE_EQUALITY
#undef ASSERT_EQUALITY
} // namespace icc

View File

@ -384,8 +384,7 @@ Icc::UpdateContact(const JSContext* aCx, IccContactType aContactType,
}
already_AddRefed<DOMRequest>
Icc::MatchMvno(const nsAString& aMvnoType,
const nsAString& aMvnoData,
Icc::MatchMvno(IccMvnoType aMvnoType, const nsAString& aMvnoData,
ErrorResult& aRv)
{
if (!mProvider) {
@ -395,8 +394,8 @@ Icc::MatchMvno(const nsAString& aMvnoType,
nsRefPtr<nsIDOMDOMRequest> request;
nsresult rv = mProvider->MatchMvno(mClientId, GetOwner(),
aMvnoType, aMvnoData,
getter_AddRefs(request));
static_cast<uint32_t>(aMvnoType),
aMvnoData, getter_AddRefs(request));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;

View File

@ -98,7 +98,7 @@ public:
ErrorResult& aRv);
already_AddRefed<DOMRequest>
MatchMvno(const nsAString& aMvnoType, const nsAString& aMatchData,
MatchMvno(IccMvnoType aMvnoType, const nsAString& aMatchData,
ErrorResult& aRv);
IMPL_EVENT_HANDLER(iccinfochange)

View File

@ -17,10 +17,48 @@ interface nsIIccListener : nsISupports
void notifyIccInfoChanged();
};
[scriptable, uuid(6136acab-b50e-494a-a86d-df392a032897)]
interface nsIIccChannelCallback : nsISupports
{
/**
* Callback function to notify on successfully opening a logical channel.
*
* @param channel
* The Channel Number/Handle that is successfully opened.
*/
void notifyOpenChannelSuccess(in long channel);
/**
* Callback function to notify on successfully closing the logical channel.
*
*/
void notifyCloseChannelSuccess();
/**
* Callback function to notify the status of 'iccExchangeAPDU' command.
*
* @param sw1
* Response's First Status Byte
* @param sw2
* Response's Second Status Byte
* @param data
* Response's data
*/
void notifyExchangeAPDUResponse(in octet sw1,
in octet sw2,
in DOMString data);
/**
* Callback function to notify error
*
*/
void notifyError(in DOMString error);
};
/**
* XPCOM component (in the content process) that provides the ICC information.
*/
[scriptable, uuid(937213c3-f64e-4f58-b4e0-3010f219d0c3)]
[scriptable, uuid(bf985ee1-14c9-43c6-a471-8ab52fb24b0d)]
interface nsIIccProvider : nsISupports
{
// MUST match enum IccCardState in MozIcc.webidl!
@ -85,6 +123,11 @@ interface nsIIccProvider : nsISupports
const unsigned long CARD_CONTACT_TYPE_FDN = 1;
const unsigned long CARD_CONTACT_TYPE_SDN = 2;
// MUST match with enum IccMvnoType in MozIcc.webidl
const unsigned long CARD_MVNO_TYPE_IMSI = 0;
const unsigned long CARD_MVNO_TYPE_SPN = 1;
const unsigned long CARD_MVNO_TYPE_GID = 2;
/**
* Called when a content process registers receiving unsolicited messages from
* RadioInterfaceLayer in the chrome process. Only a content process that has
@ -161,27 +204,39 @@ interface nsIIccProvider : nsISupports
in jsval contact,
in DOMString pin2);
/**
/**
* Secure Card Icc communication channel
*/
nsIDOMDOMRequest iccOpenChannel(in unsigned long clientId,
in nsIDOMWindow window,
in DOMString aid);
void iccOpenChannel(in unsigned long clientId,
in DOMString aid,
in nsIIccChannelCallback callback);
nsIDOMDOMRequest iccExchangeAPDU(in unsigned long clientId,
in nsIDOMWindow window,
in long channel,
in jsval apdu);
/**
* Exchange Command APDU (C-APDU) with SIM on the given logical channel.
* Note that 'P3' parameter could be Le/Lc depending on command APDU case.
* For Case 1 scenario (when only command header is present), the value
* of 'P3' should be set to '-1' explicitly.
* Refer to 3G TS 31.101 , 10.2 'Command APDU Structure' for all the cases.
*/
void iccExchangeAPDU(in unsigned long clientId,
in long channel,
in octet cla,
in octet ins,
in octet p1,
in octet p2,
in short p3,
in DOMString data,
in nsIIccChannelCallback callback);
nsIDOMDOMRequest iccCloseChannel(in unsigned long clientId,
in nsIDOMWindow window,
in long channel);
void iccCloseChannel(in unsigned long clientId,
in long channel,
in nsIIccChannelCallback callback);
/**
* Helpers
*/
nsIDOMDOMRequest matchMvno(in unsigned long clientId,
in nsIDOMWindow window,
in DOMString mvnoType,
in unsigned long mvnoType,
in DOMString mvnoData);
};

View File

@ -168,16 +168,7 @@ IDBRequest::CaptureCaller(nsAString& aFilename, uint32_t* aLineNo)
MOZ_ASSERT(aLineNo);
ThreadsafeAutoJSContext cx;
const char* filename = nullptr;
uint32_t lineNo = 0;
if (!nsJSUtils::GetCallingLocation(cx, &filename, &lineNo)) {
*aLineNo = 0;
return;
}
aFilename.Assign(NS_ConvertUTF8toUTF16(filename));
*aLineNo = lineNo;
nsJSUtils::GetCallingLocation(cx, aFilename, aLineNo);
}
void

View File

@ -20,6 +20,7 @@
#include "mozilla/dom/VideoStreamTrack.h"
#include "nsError.h"
#include "nsIDocument.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsMimeTypes.h"
#include "nsProxyRelease.h"
@ -545,6 +546,33 @@ private:
}
}
bool Check3gppPermission()
{
nsCOMPtr<nsIDocument> doc = mRecorder->GetOwner()->GetExtantDoc();
if (!doc) {
return false;
}
uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
doc->NodePrincipal()->GetAppStatus(&appStatus);
// Certified applications can always assign AUDIO_3GPP
if (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED) {
return true;
}
nsCOMPtr<nsIPermissionManager> pm =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
if (!pm) {
return false;
}
uint32_t perm = nsIPermissionManager::DENY_ACTION;
pm->TestExactPermissionFromPrincipal(doc->NodePrincipal(), "audio-capture:3gpp", &perm);
return perm == nsIPermissionManager::ALLOW_ACTION;
}
void InitEncoder(uint8_t aTrackTypes)
{
LOG(PR_LOG_DEBUG, ("Session.InitEncoder %p", this));
@ -553,14 +581,8 @@ private:
// Allocate encoder and bind with union stream.
// At this stage, the API doesn't allow UA to choose the output mimeType format.
nsCOMPtr<nsIDocument> doc = mRecorder->GetOwner()->GetExtantDoc();
uint16_t appStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
if (doc) {
doc->NodePrincipal()->GetAppStatus(&appStatus);
}
// Only allow certificated application can assign AUDIO_3GPP
if (appStatus == nsIPrincipal::APP_STATUS_CERTIFIED &&
mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP)) {
// Make sure the application has permission to assign AUDIO_3GPP
if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP) && Check3gppPermission()) {
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP), aTrackTypes);
} else {
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes);

View File

@ -148,6 +148,8 @@ private:
// Register MediaRecorder into Document to listen the activity changes.
void RegisterActivityObserver();
void UnRegisterActivityObserver();
bool Check3gppPermission();
};
}

View File

@ -220,6 +220,13 @@ nsresult RtspTrackBuffer::ReadBuffer(uint8_t* aToBuffer, uint32_t aToBufferSize,
// 3. No data in this buffer
// 4. mIsStarted is not set
while (1) {
// Make sure the track buffer is started.
// It could be stopped when RTSP connection is disconnected.
if (!mIsStarted) {
RTSPMLOG("ReadBuffer: mIsStarted is false");
return NS_ERROR_FAILURE;
}
// Do not read from buffer if we are still in the playout delay duration.
if (mDuringPlayoutDelay) {
monitor.Wait();
@ -261,10 +268,6 @@ nsresult RtspTrackBuffer::ReadBuffer(uint8_t* aToBuffer, uint32_t aToBufferSize,
mConsumerIdx = (mConsumerIdx + 1) % BUFFER_SLOT_NUM;
RTSPMLOG("BUFFER_SLOT_INVALID move forward");
} else {
// No data, and disconnected.
if (!mIsStarted) {
return NS_ERROR_FAILURE;
}
// No data, the decode thread is blocked here until we receive
// OnMediaDataAvailable. The OnMediaDataAvailable will call WriteBuffer()
// to wake up the decode thread.
@ -616,6 +619,11 @@ RtspMediaResource::ReadFrameFromTrack(uint8_t* aBuffer, uint32_t aBufferSize,
"ReadTrack index > mTrackBuffer");
MOZ_ASSERT(aBuffer);
if (!mIsConnected) {
RTSPMLOG("ReadFrameFromTrack: RTSP not connected");
return NS_ERROR_FAILURE;
}
return mTrackBuffer[aTrackIdx]->ReadBuffer(aBuffer, aBufferSize, aBytes,
aTime, aFrameSize);
}
@ -769,6 +777,7 @@ RtspMediaResource::OnDisconnected(uint8_t aTrackIdx, nsresult aReason)
aReason == NS_ERROR_NET_TIMEOUT) {
// Report error code to Decoder.
RTSPMLOG("Error in OnDisconnected 0x%x", aReason);
mIsConnected = false;
mDecoder->NetworkError();
} else {
// Resetting the decoder and media element when the connection

View File

@ -312,9 +312,12 @@ MediaSource::Attach(MediaSourceDecoder* aDecoder)
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("MediaSource(%p)::Attach(aDecoder=%p) owner=%p", this, aDecoder, aDecoder->GetOwner());
MOZ_ASSERT(aDecoder);
MOZ_ASSERT(aDecoder->GetOwner());
if (mReadyState != MediaSourceReadyState::Closed) {
return false;
}
MOZ_ASSERT(!mMediaElement);
mMediaElement = aDecoder->GetOwner()->GetMediaElement();
MOZ_ASSERT(!mDecoder);
mDecoder = aDecoder;
mDecoder->AttachMediaSource(this);
@ -335,6 +338,7 @@ MediaSource::Detach()
}
mDecoder->DetachMediaSource();
mDecoder = nullptr;
mMediaElement = nullptr;
mFirstSourceBufferInitialized = false;
SetReadyState(MediaSourceReadyState::Closed);
if (mActiveSourceBuffers) {
@ -487,6 +491,7 @@ MediaSource::WrapObject(JSContext* aCx)
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaSource, DOMEventTargetHelper,
mMediaElement,
mSourceBuffers, mActiveSourceBuffers)
NS_IMPL_ADDREF_INHERITED(MediaSource, DOMEventTargetHelper)

View File

@ -128,6 +128,9 @@ private:
nsRefPtr<SourceBufferList> mActiveSourceBuffers;
nsRefPtr<MediaSourceDecoder> mDecoder;
// Ensures the media element remains alive to dispatch progress and
// durationchanged events.
nsRefPtr<HTMLMediaElement> mMediaElement;
nsRefPtr<nsIPrincipal> mPrincipal;

View File

@ -0,0 +1,230 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function addInitialDataChannel(chain) {
chain.insertBefore('PC_LOCAL_CREATE_OFFER', [
['PC_LOCAL_CREATE_DATA_CHANNEL',
function (test) {
var channel = test.pcLocal.createDataChannel({});
is(channel.binaryType, "blob", channel + " is of binary type 'blob'");
is(channel.readyState, "connecting", channel + " is in state: 'connecting'");
is(test.pcLocal.signalingState, STABLE,
"Create datachannel does not change signaling state");
test.next();
}
]
]);
chain.insertAfter('PC_REMOTE_CREATE_ANSWER', [
[
'PC_LOCAL_SETUP_DATA_CHANNEL_CALLBACK',
function (test) {
test.waitForInitialDataChannel(test.pcLocal, function () {
ok(true, test.pcLocal + " dataChannels[0] switched to 'open'");
},
// At this point a timeout failure will be of no value
null);
test.next();
}
],
[
'PC_REMOTE_SETUP_DATA_CHANNEL_CALLBACK',
function (test) {
test.waitForInitialDataChannel(test.pcRemote, function () {
ok(true, test.pcRemote + " dataChannels[0] switched to 'open'");
},
// At this point a timeout failure will be of no value
null);
test.next();
}
]
]);
chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS', [
[
'PC_LOCAL_VERIFY_DATA_CHANNEL_STATE',
function (test) {
test.waitForInitialDataChannel(test.pcLocal, function() {
test.next();
}, function() {
ok(false, test.pcLocal + " initial dataChannels[0] failed to switch to 'open'");
//TODO: use stopAndExit() once bug 1019323 has landed
unexpectedEventAndFinish(this, 'timeout')
// to prevent test framework timeouts
test.next();
});
}
],
[
'PC_REMOTE_VERIFY_DATA_CHANNEL_STATE',
function (test) {
test.waitForInitialDataChannel(test.pcRemote, function() {
test.next();
}, function() {
ok(false, test.pcRemote + " initial dataChannels[0] failed to switch to 'open'");
//TODO: use stopAndExit() once bug 1019323 has landed
unexpectedEventAndFinish(this, 'timeout');
// to prevent test framework timeouts
test.next();
});
}
]
]);
chain.removeAfter('PC_REMOTE_CHECK_ICE_CONNECTIONS');
chain.append([
[
'SEND_MESSAGE',
function (test) {
var message = "Lorem ipsum dolor sit amet";
test.send(message, function (channel, data) {
is(data, message, "Message correctly transmitted from pcLocal to pcRemote.");
test.next();
});
}
],
[
'SEND_BLOB',
function (test) {
var contents = ["At vero eos et accusam et justo duo dolores et ea rebum."];
var blob = new Blob(contents, { "type" : "text/plain" });
test.send(blob, function (channel, data) {
ok(data instanceof Blob, "Received data is of instance Blob");
is(data.size, blob.size, "Received data has the correct size.");
getBlobContent(data, function (recv_contents) {
is(recv_contents, contents, "Received data has the correct content.");
test.next();
});
});
}
],
[
'CREATE_SECOND_DATA_CHANNEL',
function (test) {
test.createDataChannel({ }, function (sourceChannel, targetChannel) {
is(sourceChannel.readyState, "open", sourceChannel + " is in state: 'open'");
is(targetChannel.readyState, "open", targetChannel + " is in state: 'open'");
is(targetChannel.binaryType, "blob", targetChannel + " is of binary type 'blob'");
is(targetChannel.readyState, "open", targetChannel + " is in state: 'open'");
test.next();
});
}
],
[
'SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL',
function (test) {
var channels = test.pcRemote.dataChannels;
var message = "Lorem ipsum dolor sit amet";
test.send(message, function (channel, data) {
is(channels.indexOf(channel), channels.length - 1, "Last channel used");
is(data, message, "Received message has the correct content.");
test.next();
});
}
],
[
'SEND_MESSAGE_THROUGH_FIRST_CHANNEL',
function (test) {
var message = "Message through 1st channel";
var options = {
sourceChannel: test.pcLocal.dataChannels[0],
targetChannel: test.pcRemote.dataChannels[0]
};
test.send(message, function (channel, data) {
is(test.pcRemote.dataChannels.indexOf(channel), 0, "1st channel used");
is(data, message, "Received message has the correct content.");
test.next();
}, options);
}
],
[
'SEND_MESSAGE_BACK_THROUGH_FIRST_CHANNEL',
function (test) {
var message = "Return a message also through 1st channel";
var options = {
sourceChannel: test.pcRemote.dataChannels[0],
targetChannel: test.pcLocal.dataChannels[0]
};
test.send(message, function (channel, data) {
is(test.pcLocal.dataChannels.indexOf(channel), 0, "1st channel used");
is(data, message, "Return message has the correct content.");
test.next();
}, options);
}
],
[
'CREATE_NEGOTIATED_DATA_CHANNEL',
function (test) {
var options = {negotiated:true, id: 5, protocol:"foo/bar", ordered:false,
maxRetransmits:500};
test.createDataChannel(options, function (sourceChannel2, targetChannel2) {
is(sourceChannel2.readyState, "open", sourceChannel2 + " is in state: 'open'");
is(targetChannel2.readyState, "open", targetChannel2 + " is in state: 'open'");
is(targetChannel2.binaryType, "blob", targetChannel2 + " is of binary type 'blob'");
is(targetChannel2.readyState, "open", targetChannel2 + " is in state: 'open'");
if (options.id != undefined) {
is(sourceChannel2.id, options.id, sourceChannel2 + " id is:" + sourceChannel2.id);
}
else {
options.id = sourceChannel2.id;
}
var reliable = !options.ordered ? false : (options.maxRetransmits || options.maxRetransmitTime);
is(sourceChannel2.protocol, options.protocol, sourceChannel2 + " protocol is:" + sourceChannel2.protocol);
is(sourceChannel2.reliable, reliable, sourceChannel2 + " reliable is:" + sourceChannel2.reliable);
/*
These aren't exposed by IDL yet
is(sourceChannel2.ordered, options.ordered, sourceChannel2 + " ordered is:" + sourceChannel2.ordered);
is(sourceChannel2.maxRetransmits, options.maxRetransmits, sourceChannel2 + " maxRetransmits is:" +
sourceChannel2.maxRetransmits);
is(sourceChannel2.maxRetransmitTime, options.maxRetransmitTime, sourceChannel2 + " maxRetransmitTime is:" +
sourceChannel2.maxRetransmitTime);
*/
is(targetChannel2.id, options.id, targetChannel2 + " id is:" + targetChannel2.id);
is(targetChannel2.protocol, options.protocol, targetChannel2 + " protocol is:" + targetChannel2.protocol);
is(targetChannel2.reliable, reliable, targetChannel2 + " reliable is:" + targetChannel2.reliable);
/*
These aren't exposed by IDL yet
is(targetChannel2.ordered, options.ordered, targetChannel2 + " ordered is:" + targetChannel2.ordered);
is(targetChannel2.maxRetransmits, options.maxRetransmits, targetChannel2 + " maxRetransmits is:" +
targetChannel2.maxRetransmits);
is(targetChannel2.maxRetransmitTime, options.maxRetransmitTime, targetChannel2 + " maxRetransmitTime is:" +
targetChannel2.maxRetransmitTime);
*/
test.next();
});
}
],
[
'SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL2',
function (test) {
var channels = test.pcRemote.dataChannels;
var message = "Lorem ipsum dolor sit amet";
test.send(message, function (channel, data) {
is(channels.indexOf(channel), channels.length - 1, "Last channel used");
is(data, message, "Received message has the correct content.");
test.next();
});
}
]
]);
}

View File

@ -4,6 +4,7 @@ skip-if = (os == 'win' && strictContentSandbox) || android_version == '10'
support-files =
head.js
constraints.js
dataChannel.js
mediaStreamPlayback.js
nonTrickleIce.js
pc.js

View File

@ -584,7 +584,7 @@ function PeerConnectionTest(options) {
* @param {Function} onSuccess
* Callback to execute when the peer connection has been closed successfully
*/
PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
PeerConnectionTest.prototype.closePC = function PCT_closePC(onSuccess) {
info("Closing peer connections");
var self = this;
@ -655,6 +655,316 @@ PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
closeEverything();
};
/**
* Close the open data channels, followed by the underlying peer connection
*
* @param {Function} onSuccess
* Callback to execute when all connections have been closed
*/
PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
var self = this;
var pendingDcClose = []
var closeTimeout = null;
info("PeerConnectionTest.close() called");
function _closePeerConnection() {
info("Now closing PeerConnection");
self.closePC.call(self, onSuccess);
}
function _closePeerConnectionCallback(index) {
info("_closePeerConnection called with index " + index);
var pos = pendingDcClose.indexOf(index);
if (pos != -1) {
pendingDcClose.splice(pos, 1);
}
else {
info("_closePeerConnection index " + index + " is missing from pendingDcClose: " + pendingDcClose);
}
if (pendingDcClose.length === 0) {
clearTimeout(closeTimeout);
_closePeerConnection();
}
}
var myDataChannels = null;
if (self.pcLocal) {
myDataChannels = self.pcLocal.dataChannels;
}
else if (self.pcRemote) {
myDataChannels = self.pcRemote.dataChannels;
}
var length = myDataChannels.length;
for (var i = 0; i < length; i++) {
var dataChannel = myDataChannels[i];
if (dataChannel.readyState !== "closed") {
pendingDcClose.push(i);
self.closeDataChannels(i, _closePeerConnectionCallback);
}
}
if (pendingDcClose.length === 0) {
_closePeerConnection();
}
else {
closeTimeout = setTimeout(function() {
ok(false, "Failed to properly close data channels: " +
pendingDcClose);
_closePeerConnection();
}, 60000);
}
};
/**
* Close the specified data channels
*
* @param {Number} index
* Index of the data channels to close on both sides
* @param {Function} onSuccess
* Callback to execute when the data channels has been closed
*/
PeerConnectionTest.prototype.closeDataChannels = function PCT_closeDataChannels(index, onSuccess) {
info("closeDataChannels called with index: " + index);
var localChannel = null;
if (this.pcLocal) {
localChannel = this.pcLocal.dataChannels[index];
}
var remoteChannel = null;
if (this.pcRemote) {
remoteChannel = this.pcRemote.dataChannels[index];
}
var self = this;
var wait = false;
var pollingMode = false;
var everythingClosed = false;
var verifyInterval = null;
var remoteCloseTimer = null;
function _allChannelsAreClosed() {
var ret = null;
if (localChannel) {
ret = (localChannel.readyState === "closed");
}
if (remoteChannel) {
if (ret !== null) {
ret = (ret && (remoteChannel.readyState === "closed"));
}
else {
ret = (remoteChannel.readyState === "closed");
}
}
return ret;
}
function verifyClosedChannels() {
if (everythingClosed) {
// safety protection against events firing late
return;
}
if (_allChannelsAreClosed()) {
ok(true, "DataChannel(s) have reached 'closed' state for data channel " + index);
if (remoteCloseTimer !== null) {
clearTimeout(remoteCloseTimer);
}
if (verifyInterval !== null) {
clearInterval(verifyInterval);
}
everythingClosed = true;
onSuccess(index);
}
else {
info("Still waiting for DataChannel closure");
}
}
if ((localChannel) && (localChannel.readyState !== "closed")) {
// in case of steeplechase there is no far end, so we can only poll
if (remoteChannel) {
remoteChannel.onclose = function () {
is(remoteChannel.readyState, "closed", "remoteChannel is in state 'closed'");
verifyClosedChannels();
};
}
else {
pollingMode = true;
verifyInterval = setInterval(verifyClosedChannels, 1000);
}
localChannel.close();
wait = true;
}
if ((remoteChannel) && (remoteChannel.readyState !== "closed")) {
if (localChannel) {
localChannel.onclose = function () {
is(localChannel.readyState, "closed", "localChannel is in state 'closed'");
verifyClosedChannels();
};
// Apparently we are running a local test which has both ends of the
// data channel locally available, so by default lets wait for the
// remoteChannel.onclose handler from above to confirm closure on both
// ends.
remoteCloseTimer = setTimeout(function() {
todo(false, "localChannel.close() did not resulted in close signal on remote side");
remoteChannel.close();
verifyClosedChannels();
}, 30000);
}
else {
pollingMode = true;
verifyTimer = setInterval(verifyClosedChannels, 1000);
remoteChannel.close();
}
wait = true;
}
if (!wait) {
onSuccess(index);
}
};
/**
* Wait for the initial data channel to get into the open state
*
* @param {PeerConnectionWrapper} peer
* The peer connection wrapper to run the command on
* @param {Function} onSuccess
* Callback when the creation was successful
*/
PeerConnectionTest.prototype.waitForInitialDataChannel =
function PCT_waitForInitialDataChannel(peer, onSuccess, onFailure) {
var dcConnectionTimeout = null;
var dcOpened = false;
function dataChannelConnected(channel) {
// in case the switch statement below had called onSuccess already we
// don't want to call it again
if (!dcOpened) {
clearTimeout(dcConnectionTimeout);
is(channel.readyState, "open", peer + " dataChannels[0] switched to state: 'open'");
dcOpened = true;
onSuccess();
} else {
info("dataChannelConnected() called, but data channel was open already");
}
}
// TODO: drno: convert dataChannels into an object and make
// registerDataChannelOpenEvent a generic function
if (peer == this.pcLocal) {
peer.dataChannels[0].onopen = dataChannelConnected;
} else {
peer.registerDataChannelOpenEvents(dataChannelConnected);
}
if (peer.dataChannels.length >= 1) {
// snapshot of the live value as it might change during test execution
const readyState = peer.dataChannels[0].readyState;
switch (readyState) {
case "open": {
is(readyState, "open", peer + " dataChannels[0] is already in state: 'open'");
dcOpened = true;
onSuccess();
break;
}
case "connecting": {
is(readyState, "connecting", peer + " dataChannels[0] is in state: 'connecting'");
if (onFailure) {
dcConnectionTimeout = setTimeout(function () {
is(peer.dataChannels[0].readyState, "open", peer + " timed out while waiting for dataChannels[0] to open");
onFailure();
}, 60000);
}
break;
}
default: {
ok(false, "dataChannels[0] is in unexpected state " + readyState);
if (onFailure) {
onFailure()
}
}
}
}
};
/**
* Send data (message or blob) to the other peer
*
* @param {String|Blob} data
* Data to send to the other peer. For Blobs the MIME type will be lost.
* @param {Function} onSuccess
* Callback to execute when data has been sent
* @param {Object} [options={ }]
* Options to specify the data channels to be used
* @param {DataChannelWrapper} [options.sourceChannel=pcLocal.dataChannels[length - 1]]
* Data channel to use for sending the message
* @param {DataChannelWrapper} [options.targetChannel=pcRemote.dataChannels[length - 1]]
* Data channel to use for receiving the message
*/
PeerConnectionTest.prototype.send = function PCT_send(data, onSuccess, options) {
options = options || { };
var source = options.sourceChannel ||
this.pcLocal.dataChannels[this.pcLocal.dataChannels.length - 1];
var target = options.targetChannel ||
this.pcRemote.dataChannels[this.pcRemote.dataChannels.length - 1];
// Register event handler for the target channel
target.onmessage = function (recv_data) {
onSuccess(target, recv_data);
};
source.send(data);
};
/**
* Create a data channel
*
* @param {Dict} options
* Options for the data channel (see nsIPeerConnection)
* @param {Function} onSuccess
* Callback when the creation was successful
*/
PeerConnectionTest.prototype.createDataChannel = function DCT_createDataChannel(options, onSuccess) {
var localChannel = null;
var remoteChannel = null;
var self = this;
// Method to synchronize all asynchronous events.
function check_next_test() {
if (localChannel && remoteChannel) {
onSuccess(localChannel, remoteChannel);
}
}
if (!options.negotiated) {
// Register handlers for the remote peer
this.pcRemote.registerDataChannelOpenEvents(function (channel) {
remoteChannel = channel;
check_next_test();
});
}
// Create the datachannel and handle the local 'onopen' event
this.pcLocal.createDataChannel(options, function (channel) {
localChannel = channel;
if (options.negotiated) {
// externally negotiated - we need to open from both ends
options.id = options.id || channel.id; // allow for no id to let the impl choose
self.pcRemote.createDataChannel(options, function (channel) {
remoteChannel = channel;
check_next_test();
});
} else {
check_next_test();
}
});
};
/**
* Executes the next command.
*/
@ -995,372 +1305,6 @@ PCT_getSignalingMessage(messageType, onMessage) {
this.registerSignalingCallback(messageType, onMessage);
}
/**
* This class handles tests for data channels.
*
* @constructor
* @param {object} [options={}]
* Optional options for the peer connection test
* @param {object} [options.commands=commandsDataChannel]
* Commands to run for the test
* @param {object} [options.config_local=undefined]
* Configuration for the local peer connection instance
* @param {object} [options.config_remote=undefined]
* Configuration for the remote peer connection instance. If not defined
* the configuration from the local instance will be used
*/
function DataChannelTest(options) {
options = options || { };
options.commands = options.commands || commandsDataChannel;
PeerConnectionTest.call(this, options);
}
DataChannelTest.prototype = Object.create(PeerConnectionTest.prototype, {
close : {
/**
* Close the open data channels, followed by the underlying peer connection
*
* @param {Function} onSuccess
* Callback to execute when all connections have been closed
*/
value : function DCT_close(onSuccess) {
var self = this;
var pendingDcClose = []
var closeTimeout = null;
info("DataChannelTest.close() called");
function _closePeerConnection() {
info("DataChannelTest closing PeerConnection");
PeerConnectionTest.prototype.close.call(self, onSuccess);
}
function _closePeerConnectionCallback(index) {
info("_closePeerConnection called with index " + index);
var pos = pendingDcClose.indexOf(index);
if (pos != -1) {
pendingDcClose.splice(pos, 1);
}
else {
info("_closePeerConnection index " + index + " is missing from pendingDcClose: " + pendingDcClose);
}
if (pendingDcClose.length === 0) {
clearTimeout(closeTimeout);
_closePeerConnection();
}
}
var myDataChannels = null;
if (self.pcLocal) {
myDataChannels = self.pcLocal.dataChannels;
}
else if (self.pcRemote) {
myDataChannels = self.pcRemote.dataChannels;
}
var length = myDataChannels.length;
for (var i = 0; i < length; i++) {
var dataChannel = myDataChannels[i];
if (dataChannel.readyState !== "closed") {
pendingDcClose.push(i);
self.closeDataChannels(i, _closePeerConnectionCallback);
}
}
if (pendingDcClose.length === 0) {
_closePeerConnection();
}
else {
closeTimeout = setTimeout(function() {
ok(false, "Failed to properly close data channels: " +
pendingDcClose);
_closePeerConnection();
}, 60000);
}
}
},
closeDataChannels : {
/**
* Close the specified data channels
*
* @param {Number} index
* Index of the data channels to close on both sides
* @param {Function} onSuccess
* Callback to execute when the data channels has been closed
*/
value : function DCT_closeDataChannels(index, onSuccess) {
info("_closeDataChannels called with index: " + index);
var localChannel = null;
if (this.pcLocal) {
localChannel = this.pcLocal.dataChannels[index];
}
var remoteChannel = null;
if (this.pcRemote) {
remoteChannel = this.pcRemote.dataChannels[index];
}
var self = this;
var wait = false;
var pollingMode = false;
var everythingClosed = false;
var verifyInterval = null;
var remoteCloseTimer = null;
function _allChannelsAreClosed() {
var ret = null;
if (localChannel) {
ret = (localChannel.readyState === "closed");
}
if (remoteChannel) {
if (ret !== null) {
ret = (ret && (remoteChannel.readyState === "closed"));
}
else {
ret = (remoteChannel.readyState === "closed");
}
}
return ret;
}
function verifyClosedChannels() {
if (everythingClosed) {
// safety protection against events firing late
return;
}
if (_allChannelsAreClosed) {
ok(true, "DataChannel(s) have reached 'closed' state for data channel " + index);
if (remoteCloseTimer !== null) {
clearTimeout(remoteCloseTimer);
}
if (verifyInterval !== null) {
clearInterval(verifyInterval);
}
everythingClosed = true;
onSuccess(index);
}
else {
info("Still waiting for DataChannel closure");
}
}
if ((localChannel) && (localChannel.readyState !== "closed")) {
// in case of steeplechase there is no far end, so we can only poll
if (remoteChannel) {
remoteChannel.onclose = function () {
is(remoteChannel.readyState, "closed", "remoteChannel is in state 'closed'");
verifyClosedChannels();
};
}
else {
pollingMode = true;
verifyInterval = setInterval(verifyClosedChannels, 1000);
}
localChannel.close();
wait = true;
}
if ((remoteChannel) && (remoteChannel.readyState !== "closed")) {
if (localChannel) {
localChannel.onclose = function () {
is(localChannel.readyState, "closed", "localChannel is in state 'closed'");
verifyClosedChannels();
};
// Apparently we are running a local test which has both ends of the
// data channel locally available, so by default lets wait for the
// remoteChannel.onclose handler from above to confirm closure on both
// ends.
remoteCloseTimer = setTimeout(function() {
todo(false, "localChannel.close() did not resulted in close signal on remote side");
remoteChannel.close();
verifyClosedChannels();
}, 30000);
}
else {
pollingMode = true;
verifyTimer = setInterval(verifyClosedChannels, 1000);
remoteChannel.close();
}
wait = true;
}
if (!wait) {
onSuccess(index);
}
}
},
createDataChannel : {
/**
* Create a data channel
*
* @param {Dict} options
* Options for the data channel (see nsIPeerConnection)
* @param {Function} onSuccess
* Callback when the creation was successful
*/
value : function DCT_createDataChannel(options, onSuccess) {
var localChannel = null;
var remoteChannel = null;
var self = this;
// Method to synchronize all asynchronous events.
function check_next_test() {
if (localChannel && remoteChannel) {
onSuccess(localChannel, remoteChannel);
}
}
if (!options.negotiated) {
// Register handlers for the remote peer
this.pcRemote.registerDataChannelOpenEvents(function (channel) {
remoteChannel = channel;
check_next_test();
});
}
// Create the datachannel and handle the local 'onopen' event
this.pcLocal.createDataChannel(options, function (channel) {
localChannel = channel;
if (options.negotiated) {
// externally negotiated - we need to open from both ends
options.id = options.id || channel.id; // allow for no id to let the impl choose
self.pcRemote.createDataChannel(options, function (channel) {
remoteChannel = channel;
check_next_test();
});
} else {
check_next_test();
}
});
}
},
send : {
/**
* Send data (message or blob) to the other peer
*
* @param {String|Blob} data
* Data to send to the other peer. For Blobs the MIME type will be lost.
* @param {Function} onSuccess
* Callback to execute when data has been sent
* @param {Object} [options={ }]
* Options to specify the data channels to be used
* @param {DataChannelWrapper} [options.sourceChannel=pcLocal.dataChannels[length - 1]]
* Data channel to use for sending the message
* @param {DataChannelWrapper} [options.targetChannel=pcRemote.dataChannels[length - 1]]
* Data channel to use for receiving the message
*/
value : function DCT_send(data, onSuccess, options) {
options = options || { };
var source = options.sourceChannel ||
this.pcLocal.dataChannels[this.pcLocal.dataChannels.length - 1];
var target = options.targetChannel ||
this.pcRemote.dataChannels[this.pcRemote.dataChannels.length - 1];
// Register event handler for the target channel
target.onmessage = function (recv_data) {
onSuccess(target, recv_data);
};
source.send(data);
}
},
createOffer : {
value : function DCT_createOffer(peer, onSuccess) {
PeerConnectionTest.prototype.createOffer.call(this, peer, onSuccess);
}
},
setLocalDescription : {
/**
* Sets the local description for the specified peer connection instance
* and automatically handles the failure case.
*
* @param {PeerConnectionWrapper} peer
The peer connection wrapper to run the command on
* @param {mozRTCSessionDescription} desc
* Session description for the local description request
* @param {function} onSuccess
* Callback to execute if the local description was set successfully
*/
value : function DCT_setLocalDescription(peer, desc, state, onSuccess) {
PeerConnectionTest.prototype.setLocalDescription.call(this, peer,
desc, state, onSuccess);
}
},
waitForInitialDataChannel : {
/**
* Wait for the initial data channel to get into the open state
*
* @param {PeerConnectionWrapper} peer
* The peer connection wrapper to run the command on
* @param {Function} onSuccess
* Callback when the creation was successful
*/
value : function DCT_waitForInitialDataChannel(peer, onSuccess, onFailure) {
var dcConnectionTimeout = null;
var dcOpened = false;
function dataChannelConnected(channel) {
// in case the switch statement below had called onSuccess already we
// don't want to call it again
if (!dcOpened) {
clearTimeout(dcConnectionTimeout);
is(channel.readyState, "open", peer + " dataChannels[0] switched to state: 'open'");
dcOpened = true;
onSuccess();
} else {
info("dataChannelConnected() called, but data channel was open already");
}
}
// TODO: drno: convert dataChannels into an object and make
// registerDataChannelOpenEvent a generic function
if (peer == this.pcLocal) {
peer.dataChannels[0].onopen = dataChannelConnected;
} else {
peer.registerDataChannelOpenEvents(dataChannelConnected);
}
if (peer.dataChannels.length >= 1) {
// snapshot of the live value as it might change during test execution
const readyState = peer.dataChannels[0].readyState;
switch (readyState) {
case "open": {
is(readyState, "open", peer + " dataChannels[0] is already in state: 'open'");
dcOpened = true;
onSuccess();
break;
}
case "connecting": {
is(readyState, "connecting", peer + " dataChannels[0] is in state: 'connecting'");
if (onFailure) {
dcConnectionTimeout = setTimeout(function () {
is(peer.dataChannels[0].readyState, "open", peer + " timed out while waiting for dataChannels[0] to open");
onFailure();
}, 60000);
}
break;
}
default: {
ok(false, "dataChannels[0] is in unexpected state " + readyState);
if (onFailure) {
onFailure()
}
}
}
}
}
}
});
/**
* This class acts as a wrapper around a DataChannel instance.
@ -2574,6 +2518,7 @@ PeerConnectionWrapper.prototype = {
"Spec and MapClass variant of RTCStatsReport enumeration agree");
var nin = numTracks(this._pc.getRemoteStreams());
var nout = numTracks(this._pc.getLocalStreams());
var ndata = this.dataChannels.length;
// TODO(Bug 957145): Restore stronger inboundrtp test once Bug 948249 is fixed
//is(toNum(counters["inboundrtp"]), nin, "Have " + nin + " inboundrtp stat(s)");
@ -2584,7 +2529,7 @@ PeerConnectionWrapper.prototype = {
var numLocalCandidates = toNum(counters.localcandidate);
var numRemoteCandidates = toNum(counters.remotecandidate);
// If there are no tracks, there will be no stats either.
if (nin + nout > 0) {
if (nin + nout + ndata > 0) {
ok(numLocalCandidates, "Have localcandidate stat(s)");
ok(numRemoteCandidates, "Have remotecandidate stat(s)");
} else {
@ -2648,7 +2593,7 @@ PeerConnectionWrapper.prototype = {
* The SDP answer to check for SDP bundle support
*/
checkStatsIceConnections : function PCW_checkStatsIceConnections(stats,
offerConstraintsList, offerOptions, numDataTracks, answer) {
offerConstraintsList, offerOptions, answer) {
var numIceConnections = 0;
Object.keys(stats).forEach(function(key) {
if ((stats[key].type === "candidatepair") && stats[key].selected) {
@ -2669,6 +2614,8 @@ PeerConnectionWrapper.prototype = {
this.countVideoTracksInMediaConstraint(offerConstraintsList) ||
this.videoInOfferOptions(offerOptions);
var numDataTracks = this.dataChannels.length;
var numAudioVideoDataTracks = numAudioTracks + numVideoTracks + numDataTracks;
info("expected audio + video + data tracks: " + numAudioVideoDataTracks);
is(numAudioVideoDataTracks, numIceConnections, "stats ICE connections matches expected A/V tracks");

View File

@ -535,7 +535,6 @@ var commandsPeerConnection = [
test.pcLocal.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
0,
test.originalAnswer);
test.next();
});
@ -548,7 +547,6 @@ var commandsPeerConnection = [
test.pcRemote.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
0,
test.originalAnswer);
test.next();
});
@ -724,626 +722,3 @@ var commandsPeerConnection = [
]
];
/**
* Default list of commands to execute for a Datachannel test.
*/
var commandsDataChannel = [
[
'PC_LOCAL_SETUP_ICE_LOGGER',
function (test) {
test.pcLocal.logIceConnectionState();
test.next();
}
],
[
'PC_REMOTE_SETUP_ICE_LOGGER',
function (test) {
test.pcRemote.logIceConnectionState();
test.next();
}
],
[
'PC_LOCAL_SETUP_SIGNALING_LOGGER',
function (test) {
test.pcLocal.logSignalingState();
test.next();
}
],
[
'PC_REMOTE_SETUP_SIGNALING_LOGGER',
function (test) {
test.pcRemote.logSignalingState();
test.next();
}
],
[
'PC_LOCAL_GUM',
function (test) {
test.pcLocal.getAllUserMedia(test.pcLocal.constraints, function () {
test.next();
});
}
],
[
'PC_LOCAL_INITIAL_SIGNALINGSTATE',
function (test) {
is(test.pcLocal.signalingState, STABLE,
"Initial local signalingState is stable");
test.next();
}
],
[
'PC_LOCAL_CHECK_INITIAL_ICE_STATE',
function (test) {
is(test.pcLocal.iceConnectionState, ICE_NEW,
"Initial local ICE connection state is 'new'");
test.next();
}
],
[
'PC_REMOTE_GUM',
function (test) {
test.pcRemote.getAllUserMedia(test.pcRemote.constraints, function () {
test.next();
});
}
],
[
'PC_REMOTE_INITIAL_SIGNALINGSTATE',
function (test) {
is(test.pcRemote.signalingState, STABLE,
"Initial remote signalingState is stable");
test.next();
}
],
[
'PC_REMOTE_CHECK_INITIAL_ICE_STATE',
function (test) {
is(test.pcRemote.iceConnectionState, ICE_NEW,
"Initial remote ICE connection state is 'new'");
test.next();
}
],
[
'PC_LOCAL_SETUP_ICE_HANDLER',
function (test) {
test.pcLocal.setupIceCandidateHandler(test);
test.next();
}
],
[
'PC_REMOTE_SETUP_ICE_HANDLER',
function (test) {
test.pcRemote.setupIceCandidateHandler(test);
test.next();
}
],
[
'PC_LOCAL_CREATE_DATA_CHANNEL',
function (test) {
var channel = test.pcLocal.createDataChannel({});
is(channel.binaryType, "blob", channel + " is of binary type 'blob'");
is(channel.readyState, "connecting", channel + " is in state: 'connecting'");
is(test.pcLocal.signalingState, STABLE,
"Create datachannel does not change signaling state");
test.next();
}
],
[
'PC_LOCAL_CREATE_OFFER',
function (test) {
test.createOffer(test.pcLocal, function (offer) {
is(test.pcLocal.signalingState, STABLE,
"Local create offer does not change signaling state");
ok(offer.sdp.contains("m=application"),
"m=application is contained in the SDP");
test.next();
});
}
],
[
'PC_LOCAL_STEEPLECHASE_SIGNAL_OFFER',
function (test) {
if (test.steeplechase) {
send_message({"type": "offer",
"offer": test.originalOffer,
"offer_constraints": test.pcLocal.constraints,
"offer_options": test.pcLocal.offerOptions});
test._local_offer = test.originalOffer;
test._offer_constraints = test.pcLocal.constraints;
test._offer_options = test.pcLocal.offerOptions;
}
test.next();
}
],
[
'PC_LOCAL_SET_LOCAL_DESCRIPTION',
function (test) {
test.setLocalDescription(test.pcLocal, test.originalOffer, HAVE_LOCAL_OFFER,
function () {
is(test.pcLocal.signalingState, HAVE_LOCAL_OFFER,
"signalingState after local setLocalDescription is 'have-local-offer'");
test.next();
});
}
],
[
'PC_REMOTE_GET_OFFER',
function (test) {
if (!test.steeplechase) {
test._local_offer = test.originalOffer;
test._offer_constraints = test.pcLocal.constraints;
test._offer_options = test.pcLocal.offerOptions;
test.next();
} else {
test.getSignalingMessage("offer", function (message) {
ok("offer" in message, "Got an offer message");
test._local_offer = new mozRTCSessionDescription(message.offer);
test._offer_constraints = message.offer_constraints;
test._offer_options = message.offer_options;
test.next();
});
}
}
],
[
'PC_REMOTE_SET_REMOTE_DESCRIPTION',
function (test) {
test.setRemoteDescription(test.pcRemote, test._local_offer, HAVE_REMOTE_OFFER,
function () {
is(test.pcRemote.signalingState, HAVE_REMOTE_OFFER,
"signalingState after remote setRemoteDescription is 'have-remote-offer'");
test.next();
});
}
],
[
'PC_LOCAL_SANE_LOCAL_SDP',
function (test) {
test.pcLocal.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._offer_options,
function(trickle) {
test.pcLocal.localRequiresTrickleIce = trickle;
});
test.next();
}
],
[
'PC_REMOTE_SANE_REMOTE_SDP',
function (test) {
test.pcRemote.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcRemote.remoteRequiresTrickleIce = trickle;
});
test.next();
}
],
[
'PC_REMOTE_CREATE_ANSWER',
function (test) {
test.createAnswer(test.pcRemote, function (answer) {
is(test.pcRemote.signalingState, HAVE_REMOTE_OFFER,
"Remote createAnswer does not change signaling state");
ok(answer.sdp.contains("m=application"),
"m=application is contained in the SDP");
if (test.steeplechase) {
send_message({"type":"answer",
"answer": test.originalAnswer,
"answer_constraints": test.pcRemote.constraints});
test._remote_answer = test.pcRemote._last_answer;
test._answer_constraints = test.pcRemote.constraints;
}
test.next();
});
}
],
[
'PC_LOCAL_SETUP_DATA_CHANNEL_CALLBACK',
function (test) {
test.waitForInitialDataChannel(test.pcLocal, function () {
ok(true, test.pcLocal + " dataChannels[0] switched to 'open'");
},
// At this point a timeout failure will be of no value
null);
test.next();
}
],
[
'PC_REMOTE_SETUP_DATA_CHANNEL_CALLBACK',
function (test) {
test.waitForInitialDataChannel(test.pcRemote, function () {
ok(true, test.pcRemote + " dataChannels[0] switched to 'open'");
},
// At this point a timeout failure will be of no value
null);
test.next();
}
],
[
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
function (test) {
test.setLocalDescription(test.pcRemote, test.originalAnswer, STABLE,
function () {
is(test.pcRemote.signalingState, STABLE,
"signalingState after remote setLocalDescription is 'stable'");
test.next();
}
);
}
],
[
'PC_LOCAL_GET_ANSWER',
function (test) {
if (!test.steeplechase) {
test._remote_answer = test.originalAnswer;
test._answer_constraints = test.pcRemote.constraints;
test.next();
} else {
test.getSignalingMessage("answer", function (message) {
ok("answer" in message, "Got an answer message");
test._remote_answer = new mozRTCSessionDescription(message.answer);
test._answer_constraints = message.answer_constraints;
test.next();
});
}
}
],
[
'PC_LOCAL_SET_REMOTE_DESCRIPTION',
function (test) {
test.setRemoteDescription(test.pcLocal, test._remote_answer, STABLE,
function () {
is(test.pcLocal.signalingState, STABLE,
"signalingState after local setRemoteDescription is 'stable'");
test.next();
}
);
}
],
[
'PC_REMOTE_SANE_LOCAL_SDP',
function (test) {
test.pcRemote.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcRemote.localRequiresTrickleIce = trickle;
});
test.next();
}
],
[
'PC_LOCAL_SANE_REMOTE_SDP',
function (test) {
test.pcLocal.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._offer_options,
function (trickle) {
test.pcLocal.remoteRequiresTrickleIce = trickle;
});
test.next();
}
],
[
'PC_LOCAL_WAIT_FOR_ICE_CONNECTED',
function (test) {
var myTest = test;
var myPc = myTest.pcLocal;
function onIceConnectedSuccess () {
info("pcLocal ICE connection state log: " + test.pcLocal.iceConnectionLog);
ok(true, "pc_local: ICE switched to 'connected' state");
myTest.next();
};
function onIceConnectedFailed () {
dumpSdp(myTest);
ok(false, "pc_local: ICE failed to switch to 'connected' state: " + myPc.iceConnectionState);
myTest.next();
};
if (myPc.isIceConnected()) {
info("pcLocal ICE connection state log: " + test.pcLocal.iceConnectionLog);
ok(true, "pc_local: ICE is in connected state");
myTest.next();
} else if (myPc.isIceConnectionPending()) {
myPc.waitForIceConnected(onIceConnectedSuccess, onIceConnectedFailed);
} else {
dumpSdp(myTest);
ok(false, "pc_local: ICE is already in bad state: " + myPc.iceConnectionState);
myTest.next();
}
}
],
[
'PC_LOCAL_VERIFY_ICE_GATHERING',
function (test) {
if (test.pcLocal.localRequiresTrickleIce) {
ok(test.pcLocal._local_ice_candidates.length > 0, "Received local trickle ICE candidates");
}
isnot(test.pcLocal._pc.iceGatheringState, GATH_NEW, "ICE gathering state is not 'new'");
test.next();
}
],
[
'PC_REMOTE_WAIT_FOR_ICE_CONNECTED',
function (test) {
var myTest = test;
var myPc = myTest.pcRemote;
function onIceConnectedSuccess () {
info("pcRemote ICE connection state log: " + test.pcRemote.iceConnectionLog);
ok(true, "pc_remote: ICE switched to 'connected' state");
myTest.next();
};
function onIceConnectedFailed () {
dumpSdp(myTest);
ok(false, "pc_remote: ICE failed to switch to 'connected' state: " + myPc.iceConnectionState);
myTest.next();
};
if (myPc.isIceConnected()) {
info("pcRemote ICE connection state log: " + test.pcRemote.iceConnectionLog);
ok(true, "pc_remote: ICE is in connected state");
myTest.next();
} else if (myPc.isIceConnectionPending()) {
myPc.waitForIceConnected(onIceConnectedSuccess, onIceConnectedFailed);
} else {
dumpSdp(myTest);
ok(false, "pc_remote: ICE is already in bad state: " + myPc.iceConnectionState);
myTest.next();
}
}
],
[
'PC_REMOTE_VERIFY_ICE_GATHERING',
function (test) {
if (test.pcRemote.localRequiresTrickleIce) {
ok(test.pcRemote._local_ice_candidates.length > 0, "Received local trickle ICE candidates");
}
isnot(test.pcRemote._pc.iceGatheringState, GATH_NEW, "ICE gathering state is not 'new'");
test.next();
}
],
[
'PC_LOCAL_VERIFY_DATA_CHANNEL_STATE',
function (test) {
test.waitForInitialDataChannel(test.pcLocal, function() {
test.next();
}, function() {
ok(false, test.pcLocal + " initial dataChannels[0] failed to switch to 'open'");
//TODO: use stopAndExit() once bug 1019323 has landed
unexpectedEventAndFinish(this, 'timeout')
// to prevent test framework timeouts
test.next();
});
}
],
[
'PC_REMOTE_VERIFY_DATA_CHANNEL_STATE',
function (test) {
test.waitForInitialDataChannel(test.pcRemote, function() {
test.next();
}, function() {
ok(false, test.pcRemote + " initial dataChannels[0] failed to switch to 'open'");
//TODO: use stopAndExit() once bug 1019323 has landed
unexpectedEventAndFinish(this, 'timeout');
// to prevent test framework timeouts
test.next();
});
}
],
[
'PC_LOCAL_CHECK_MEDIA_TRACKS',
function (test) {
test.pcLocal.checkMediaTracks(test._answer_constraints, function () {
test.next();
});
}
],
[
'PC_REMOTE_CHECK_MEDIA_TRACKS',
function (test) {
test.pcRemote.checkMediaTracks(test._offer_constraints, function () {
test.next();
});
}
],
[
'PC_LOCAL_CHECK_MEDIA_FLOW_PRESENT',
function (test) {
test.pcLocal.checkMediaFlowPresent(function () {
test.next();
});
}
],
[
'PC_REMOTE_CHECK_MEDIA_FLOW_PRESENT',
function (test) {
test.pcRemote.checkMediaFlowPresent(function () {
test.next();
});
}
],
[
'PC_LOCAL_CHECK_ICE_CONNECTIONS',
function (test) {
test.pcLocal.getStats(null, function(stats) {
test.pcLocal.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
1,
test.originalAnswer);
test.next();
});
}
],
[
'PC_REMOTE_CHECK_ICE_CONNECTIONS',
function (test) {
test.pcRemote.getStats(null, function(stats) {
test.pcRemote.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
1,
test.originalAnswer);
test.next();
});
}
],
[
'SEND_MESSAGE',
function (test) {
var message = "Lorem ipsum dolor sit amet";
test.send(message, function (channel, data) {
is(data, message, "Message correctly transmitted from pcLocal to pcRemote.");
test.next();
});
}
],
[
'SEND_BLOB',
function (test) {
var contents = ["At vero eos et accusam et justo duo dolores et ea rebum."];
var blob = new Blob(contents, { "type" : "text/plain" });
test.send(blob, function (channel, data) {
ok(data instanceof Blob, "Received data is of instance Blob");
is(data.size, blob.size, "Received data has the correct size.");
getBlobContent(data, function (recv_contents) {
is(recv_contents, contents, "Received data has the correct content.");
test.next();
});
});
}
],
[
'CREATE_SECOND_DATA_CHANNEL',
function (test) {
test.createDataChannel({ }, function (sourceChannel, targetChannel) {
is(sourceChannel.readyState, "open", sourceChannel + " is in state: 'open'");
is(targetChannel.readyState, "open", targetChannel + " is in state: 'open'");
is(targetChannel.binaryType, "blob", targetChannel + " is of binary type 'blob'");
is(targetChannel.readyState, "open", targetChannel + " is in state: 'open'");
test.next();
});
}
],
[
'SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL',
function (test) {
var channels = test.pcRemote.dataChannels;
var message = "Lorem ipsum dolor sit amet";
test.send(message, function (channel, data) {
is(channels.indexOf(channel), channels.length - 1, "Last channel used");
is(data, message, "Received message has the correct content.");
test.next();
});
}
],
[
'SEND_MESSAGE_THROUGH_FIRST_CHANNEL',
function (test) {
var message = "Message through 1st channel";
var options = {
sourceChannel: test.pcLocal.dataChannels[0],
targetChannel: test.pcRemote.dataChannels[0]
};
test.send(message, function (channel, data) {
is(test.pcRemote.dataChannels.indexOf(channel), 0, "1st channel used");
is(data, message, "Received message has the correct content.");
test.next();
}, options);
}
],
[
'SEND_MESSAGE_BACK_THROUGH_FIRST_CHANNEL',
function (test) {
var message = "Return a message also through 1st channel";
var options = {
sourceChannel: test.pcRemote.dataChannels[0],
targetChannel: test.pcLocal.dataChannels[0]
};
test.send(message, function (channel, data) {
is(test.pcLocal.dataChannels.indexOf(channel), 0, "1st channel used");
is(data, message, "Return message has the correct content.");
test.next();
}, options);
}
],
[
'CREATE_NEGOTIATED_DATA_CHANNEL',
function (test) {
var options = {negotiated:true, id: 5, protocol:"foo/bar", ordered:false,
maxRetransmits:500};
test.createDataChannel(options, function (sourceChannel2, targetChannel2) {
is(sourceChannel2.readyState, "open", sourceChannel2 + " is in state: 'open'");
is(targetChannel2.readyState, "open", targetChannel2 + " is in state: 'open'");
is(targetChannel2.binaryType, "blob", targetChannel2 + " is of binary type 'blob'");
is(targetChannel2.readyState, "open", targetChannel2 + " is in state: 'open'");
if (options.id != undefined) {
is(sourceChannel2.id, options.id, sourceChannel2 + " id is:" + sourceChannel2.id);
}
else {
options.id = sourceChannel2.id;
}
var reliable = !options.ordered ? false : (options.maxRetransmits || options.maxRetransmitTime);
is(sourceChannel2.protocol, options.protocol, sourceChannel2 + " protocol is:" + sourceChannel2.protocol);
is(sourceChannel2.reliable, reliable, sourceChannel2 + " reliable is:" + sourceChannel2.reliable);
/*
These aren't exposed by IDL yet
is(sourceChannel2.ordered, options.ordered, sourceChannel2 + " ordered is:" + sourceChannel2.ordered);
is(sourceChannel2.maxRetransmits, options.maxRetransmits, sourceChannel2 + " maxRetransmits is:" +
sourceChannel2.maxRetransmits);
is(sourceChannel2.maxRetransmitTime, options.maxRetransmitTime, sourceChannel2 + " maxRetransmitTime is:" +
sourceChannel2.maxRetransmitTime);
*/
is(targetChannel2.id, options.id, targetChannel2 + " id is:" + targetChannel2.id);
is(targetChannel2.protocol, options.protocol, targetChannel2 + " protocol is:" + targetChannel2.protocol);
is(targetChannel2.reliable, reliable, targetChannel2 + " reliable is:" + targetChannel2.reliable);
/*
These aren't exposed by IDL yet
is(targetChannel2.ordered, options.ordered, targetChannel2 + " ordered is:" + targetChannel2.ordered);
is(targetChannel2.maxRetransmits, options.maxRetransmits, targetChannel2 + " maxRetransmits is:" +
targetChannel2.maxRetransmits);
is(targetChannel2.maxRetransmitTime, options.maxRetransmitTime, targetChannel2 + " maxRetransmitTime is:" +
targetChannel2.maxRetransmitTime);
*/
test.next();
});
}
],
[
'SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL2',
function (test) {
var channels = test.pcRemote.dataChannels;
var message = "Lorem ipsum dolor sit amet";
test.send(message, function (channel, data) {
is(channels.indexOf(channel), channels.length - 1, "Last channel used");
is(data, message, "Received message has the correct content.");
test.next();
});
}
]
];

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -17,8 +18,9 @@
});
var test;
runNetworkTest(function () {
test = new DataChannelTest();
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
});

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -17,8 +18,9 @@
});
var test;
runNetworkTest(function () {
test = new DataChannelTest();
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.run();

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -17,8 +18,9 @@
});
var test;
runNetworkTest(function () {
test = new DataChannelTest();
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
test.setMediaConstraints([{audio: true, video: true}],
[{audio: true, video: true}]);
test.run();

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -11,8 +12,6 @@
<body>
<pre id="test">
<script type="application/javascript">
SimpleTest.requestFlakyTimeout("untriaged");
createHTML({
bug: "1016476",
title: "Basic data channel audio/video connection without bundle"
@ -20,9 +19,8 @@
var test;
runNetworkTest(function () {
test = new DataChannelTest();
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test = new PeerConnectionTest();
addInitialDataChannel(test.chain);
test.chain.insertAfter("PC_LOCAL_CREATE_OFFER",
[[
'PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER',
@ -35,6 +33,8 @@
}
]]
);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.run();
});

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -17,8 +18,9 @@
});
var test;
runNetworkTest(function () {
test = new DataChannelTest();
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
test.run();
});

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -17,8 +18,9 @@
});
var test;
runNetworkTest(function () {
test = new DataChannelTest();
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
test.setMediaConstraints([{video: true}], [{video: true}]);
test.run();
});

View File

@ -3,6 +3,7 @@
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="dataChannel.js"></script>
<script type="application/javascript" src="head.js"></script>
<script type="application/javascript" src="pc.js"></script>
<script type="application/javascript" src="templates.js"></script>
@ -17,8 +18,9 @@
});
var test;
runNetworkTest(function () {
test = new DataChannelTest();
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
var sld = test.chain.remove("PC_REMOTE_SET_LOCAL_DESCRIPTION");
test.chain.insertAfter("PC_LOCAL_SET_REMOTE_DESCRIPTION", sld);
test.setMediaConstraints([{audio: true}], [{audio: true}]);

View File

@ -192,6 +192,10 @@ MozNFCTagImpl.prototype = {
return callback.promise;
},
notifyLost: function notifyLost() {
this.isLost = true;
},
classID: Components.ID("{4e1e2e90-3137-11e3-aa6e-0800200c9a66}"),
contractID: "@mozilla.org/nfc/tag;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
@ -244,6 +248,10 @@ MozNFCPeerImpl.prototype = {
return callback.promise;
},
notifyLost: function notifyLost() {
this.isLost = true;
},
classID: Components.ID("{c1b2bcf0-35eb-11e3-aa6e-0800200c9a66}"),
contractID: "@mozilla.org/nfc/peer;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
@ -432,7 +440,7 @@ MozNFCImpl.prototype = {
this, /* useCapture */false);
}
this.nfcTag.isLost = true;
this.nfcTag.notifyLost();
this.nfcTag = null;
debug("fire ontaglost " + sessionToken);
@ -491,7 +499,7 @@ MozNFCImpl.prototype = {
this, /* useCapture */false);
}
this.nfcPeer.isLost = true;
this.nfcPeer.notifyLost();
this.nfcPeer = null;
debug("fire onpeerlost");

View File

@ -260,7 +260,7 @@ anp_audio_newTrack(uint32_t sampleRate, // sampling rate in Hz
if (autoFrame.CheckForException() || obj == nullptr) {
jenv->DeleteGlobalRef(s->at_class);
free(s);
delete s;
return nullptr;
}
@ -268,7 +268,7 @@ anp_audio_newTrack(uint32_t sampleRate, // sampling rate in Hz
if (autoFrame.CheckForException() || state == STATE_UNINITIALIZED) {
jenv->DeleteGlobalRef(s->at_class);
free(s);
delete s;
return nullptr;
}
@ -310,7 +310,7 @@ anp_audio_start(ANPAudioTrack* s)
if (autoFrame.CheckForException()) {
jenv->DeleteGlobalRef(s->at_class);
free(s);
delete s;
return;
}

View File

@ -62,7 +62,10 @@ BrowserStreamChild::StreamConstructed(
&mStream, seekable, stype);
if (rv != NPERR_NO_ERROR) {
mState = DELETING;
mStreamNotify = nullptr;
if (mStreamNotify) {
mStreamNotify->SetAssociatedStream(nullptr);
mStreamNotify = nullptr;
}
}
else {
mState = ALIVE;

View File

@ -2440,7 +2440,6 @@ StreamNotifyChild::ActorDestroy(ActorDestroyReason why)
void
StreamNotifyChild::SetAssociatedStream(BrowserStreamChild* bs)
{
NS_ASSERTION(bs, "Shouldn't be null");
NS_ASSERTION(!mBrowserStream, "Two streams for one streamnotify?");
mBrowserStream = bs;

View File

@ -35,8 +35,9 @@
#include "nsPluginTags.h"
#ifdef XP_WIN
#include "PluginHangUIParent.h"
#include "mozilla/widget/AudioSession.h"
#include "nsWindowsHelpers.h"
#include "PluginHangUIParent.h"
#endif
#ifdef MOZ_ENABLE_PROFILER_SPS
@ -2481,7 +2482,7 @@ PluginModuleChromeParent::InitializeInjector()
return;
TimeStamp th32Start = TimeStamp::Now();
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
nsAutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (INVALID_HANDLE_VALUE == snapshot)
return;
TimeStamp th32End = TimeStamp::Now();

View File

@ -444,7 +444,7 @@ nsCSPParser::path(nsCSPHostSrc* aCspHost)
}
// path can begin with "/" but not "//"
// see http://tools.ietf.org/html/rfc3986#section-3.3
if (!hostChar()) {
if (peek(SLASH)) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
params, ArrayLength(params));

View File

@ -122,6 +122,7 @@ static bool gPending = false;
static nsTArray<nsCString> gReason;
static NetworkParams *gWifiTetheringParms = 0;
static nsTArray<CommandChain*> gCommandChainQueue;
const CommandFunc NetworkUtils::sWifiEnableChain[] = {
NetworkUtils::clearWifiTetherParms,
@ -385,6 +386,18 @@ static void postMessage(NetworkParams& aOptions, NetworkResultOptions& aResult)
(*(gNetworkUtils->getMessageCallback()))(aResult);
}
void NetworkUtils::runNextQueuedCommandChain()
{
if (gCommandChainQueue.IsEmpty()) {
NU_DBG("No command chain left in the queue. Done!");
return;
}
NU_DBG("Process the queued command chain.");
CommandChain* nextChain = gCommandChainQueue[0];
NetworkResultOptions newResult;
next(nextChain, false, newResult);
}
void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions& aResult)
{
if (aError) {
@ -394,11 +407,15 @@ void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions&
(*onError)(aChain->getParams(), aResult);
}
delete aChain;
gCommandChainQueue.RemoveElementAt(0);
runNextQueuedCommandChain();
return;
}
CommandFunc f = aChain->getNextCommand();
if (!f) {
delete aChain;
gCommandChainQueue.RemoveElementAt(0);
runNextQueuedCommandChain();
return;
}
@ -809,13 +826,16 @@ void NetworkUtils::startTethering(CommandChain* aChain,
if (aResult.mResultReason.Find("started") != kNotFound) {
snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
} else {
snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s", GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
// If usbStartIp/usbEndIp is not valid, don't append them since
// the trailing white spaces will be parsed to extra empty args
// See: http://androidxref.com/4.3_r2.1/xref/system/core/libsysutils/src/FrameworkListener.cpp#78
if (!GET_FIELD(mUsbStartIp).IsEmpty() && !GET_FIELD(mUsbEndIp).IsEmpty()) {
snprintf(command, MAX_COMMAND_SIZE - 1, "%s %s %s", command, GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s %s %s",
GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp),
GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
} else {
snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s",
GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
}
}
@ -937,11 +957,29 @@ void NetworkUtils::setInterfaceDns(CommandChain* aChain,
#define ASSIGN_FIELD(prop) aResult.prop = aChain->getParams().prop;
#define ASSIGN_FIELD_VALUE(prop, value) aResult.prop = value;
#define RUN_CHAIN(param, cmds, err) \
uint32_t size = sizeof(cmds) / sizeof(CommandFunc); \
CommandChain* chain = new CommandChain(param, cmds, size, err); \
NetworkResultOptions result; \
next(chain, false, result);
template<size_t N>
void NetworkUtils::runChain(const NetworkParams& aParams,
const CommandFunc (&aCmds)[N],
ErrorCallback aError)
{
CommandChain* chain = new CommandChain(aParams, aCmds, N, aError);
gCommandChainQueue.AppendElement(chain);
if (gCommandChainQueue.Length() > 1) {
NU_DBG("%d command chains are queued. Wait!", gCommandChainQueue.Length());
return;
}
NetworkResultOptions result;
NetworkUtils::next(gCommandChainQueue[0], false, result);
}
// Called to clean up the command chain and process the queued command chain if any.
void NetworkUtils::finalizeSuccess(CommandChain* aChain,
NetworkResultOptions& aResult)
{
next(aChain, false, aResult);
}
void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
{
@ -951,7 +989,7 @@ void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptio
// If one of the stages fails, we try roll back to ensure
// we don't leave the network systems in limbo.
ASSIGN_FIELD_VALUE(mEnable, false)
RUN_CHAIN(aOptions, sWifiFailChain, nullptr)
runChain(aOptions, sWifiFailChain, nullptr);
}
void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
@ -965,6 +1003,7 @@ void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
gWifiTetheringParms = new NetworkParams(aChain->getParams());
}
postMessage(aChain->getParams(), aResult);
finalizeSuccess(aChain, aResult);
}
void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
@ -977,7 +1016,7 @@ void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
// This parameter is used to disable ipforwarding.
{
aOptions.mEnable = false;
RUN_CHAIN(aOptions, sUSBFailChain, nullptr)
runChain(aOptions, sUSBFailChain, nullptr);
}
// Disable usb rndis function.
@ -995,6 +1034,7 @@ void NetworkUtils::usbTetheringSuccess(CommandChain* aChain,
{
ASSIGN_FIELD(mEnable)
postMessage(aChain->getParams(), aResult);
finalizeSuccess(aChain, aResult);
}
void NetworkUtils::networkInterfaceAlarmFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
@ -1009,6 +1049,7 @@ void NetworkUtils::networkInterfaceAlarmSuccess(CommandChain* aChain,
// TODO : error is not used , and it is conflict with boolean type error.
// params.error = parseFloat(params.resultReason);
postMessage(aChain->getParams(), aResult);
finalizeSuccess(aChain, aResult);
}
void NetworkUtils::updateUpStreamFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
@ -1023,6 +1064,7 @@ void NetworkUtils::updateUpStreamSuccess(CommandChain* aChain,
ASSIGN_FIELD(mCurExternalIfname)
ASSIGN_FIELD(mCurInternalIfname)
postMessage(aChain->getParams(), aResult);
finalizeSuccess(aChain, aResult);
}
void NetworkUtils::setDhcpServerFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
@ -1035,6 +1077,7 @@ void NetworkUtils::setDhcpServerSuccess(CommandChain* aChain, CommandCallback aC
{
aResult.mSuccess = true;
postMessage(aChain->getParams(), aResult);
finalizeSuccess(aChain, aResult);
}
void NetworkUtils::wifiOperationModeFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
@ -1047,6 +1090,7 @@ void NetworkUtils::wifiOperationModeSuccess(CommandChain* aChain,
NetworkResultOptions& aResult)
{
postMessage(aChain->getParams(), aResult);
finalizeSuccess(aChain, aResult);
}
void NetworkUtils::setDnsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
@ -1188,7 +1232,7 @@ void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
if (!strcmp(reason, linkdownReason)) {
NU_DBG("Wifi link down, restarting tethering.");
RUN_CHAIN(*gWifiTetheringParms, sWifiRetryChain, wifiTetheringFail)
runChain(*gWifiTetheringParms, sWifiRetryChain, wifiTetheringFail);
}
}
}
@ -1242,9 +1286,9 @@ CommandResult NetworkUtils::setDhcpServer(NetworkParams& aOptions)
aOptions.mPrefix = aOptions.mMaskLength;
aOptions.mLink = NS_ConvertUTF8toUTF16("up");
RUN_CHAIN(aOptions, sStartDhcpServerChain, setDhcpServerFail)
runChain(aOptions, sStartDhcpServerChain, setDhcpServerFail);
} else {
RUN_CHAIN(aOptions, sStopDhcpServerChain, setDhcpServerFail)
runChain(aOptions, sStopDhcpServerChain, setDhcpServerFail);
}
return CommandResult::Pending();
}
@ -1283,7 +1327,7 @@ CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
// DNS needs to be set through netd since JellyBean (4.3).
if (SDK_VERSION >= 18) {
RUN_CHAIN(aOptions, sSetDnsChain, setDnsFail)
runChain(aOptions, sSetDnsChain, setDnsFail);
return CommandResult::Pending();
}
@ -1600,21 +1644,21 @@ CommandResult NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
{
NU_DBG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
RUN_CHAIN(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
runChain(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
return CommandResult::Pending();
}
CommandResult NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
{
NU_DBG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
RUN_CHAIN(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
runChain(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
return CommandResult::Pending();
}
CommandResult NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
{
NU_DBG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
RUN_CHAIN(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
runChain(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
return CommandResult::Pending();
}
@ -1624,7 +1668,7 @@ CommandResult NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions
CommandResult NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
{
NU_DBG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
RUN_CHAIN(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
runChain(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
return CommandResult::Pending();
}
@ -1654,11 +1698,11 @@ CommandResult NetworkUtils::setWifiTethering(NetworkParams& aOptions)
if (enable) {
NU_DBG("Starting Wifi Tethering on %s <-> %s",
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
RUN_CHAIN(aOptions, sWifiEnableChain, wifiTetheringFail)
runChain(aOptions, sWifiEnableChain, wifiTetheringFail);
} else {
NU_DBG("Stopping Wifi Tethering on %s <-> %s",
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
RUN_CHAIN(aOptions, sWifiDisableChain, wifiTetheringFail)
runChain(aOptions, sWifiDisableChain, wifiTetheringFail);
}
return CommandResult::Pending();
}
@ -1686,11 +1730,11 @@ CommandResult NetworkUtils::setUSBTethering(NetworkParams& aOptions)
if (enable) {
NU_DBG("Starting USB Tethering on %s <-> %s",
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
RUN_CHAIN(aOptions, sUSBEnableChain, usbTetheringFail)
runChain(aOptions, sUSBEnableChain, usbTetheringFail);
} else {
NU_DBG("Stopping USB Tethering on %s <-> %s",
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
RUN_CHAIN(aOptions, sUSBDisableChain, usbTetheringFail)
runChain(aOptions, sUSBDisableChain, usbTetheringFail);
}
return CommandResult::Pending();
}
@ -1800,7 +1844,7 @@ CommandResult NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
*/
CommandResult NetworkUtils::updateUpStream(NetworkParams& aOptions)
{
RUN_CHAIN(aOptions, sUpdateUpStreamChain, updateUpStreamFail)
runChain(aOptions, sUpdateUpStreamChain, updateUpStreamFail);
return CommandResult::Pending();
}

View File

@ -360,6 +360,15 @@ private:
inline bool isComplete(uint32_t code);
inline bool isProceeding(uint32_t code);
void Shutdown();
static void runNextQueuedCommandChain();
static void finalizeSuccess(CommandChain* aChain,
mozilla::dom::NetworkResultOptions& aResult);
template<size_t N>
static void runChain(const NetworkParams& aParams,
const CommandFunc (&aCmds)[N],
ErrorCallback aError);
/**
* Callback function to send netd result to main thread.
*/

View File

@ -62,6 +62,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsISyncMessageSender");
XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function() {
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
let isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime)
@ -410,14 +414,9 @@ RILContentHelper.prototype = {
});
},
iccOpenChannel: function(clientId, window, aid) {
if (window == null) {
throw Components.Exception("Can't get window object",
Cr.NS_ERROR_UNEXPECTED);
}
let request = Services.DOMRequest.createRequest(window);
let requestId = this.getRequestId(request);
iccOpenChannel: function(clientId, aid, callback) {
let requestId = UUIDGenerator.generateUUID().toString();
this._addIccChannelCallback(requestId, callback);
cpmm.sendAsyncMessage("RIL:IccOpenChannel", {
clientId: clientId,
@ -426,17 +425,24 @@ RILContentHelper.prototype = {
aid: aid
}
});
return request;
},
iccExchangeAPDU: function(clientId, window, channel, apdu) {
if (window == null) {
throw Components.Exception("Can't get window object",
Cr.NS_ERROR_UNEXPECTED);
iccExchangeAPDU: function(clientId, channel, cla, ins, p1, p2, p3, data, callback) {
let requestId = UUIDGenerator.generateUUID().toString();
this._addIccChannelCallback(requestId, callback);
if (!data) {
if (DEBUG) debug('data is not set , p3 : ' + p3);
}
let request = Services.DOMRequest.createRequest(window);
let requestId = this.getRequestId(request);
let apdu = {
cla: cla,
command: ins,
p1: p1,
p2: p2,
p3: p3,
data: data
};
//Potentially you need serialization here and can't pass the jsval through
cpmm.sendAsyncMessage("RIL:IccExchangeAPDU", {
@ -447,17 +453,11 @@ RILContentHelper.prototype = {
apdu: apdu
}
});
return request;
},
iccCloseChannel: function(clientId, window, channel) {
if (window == null) {
throw Components.Exception("Can't get window object",
Cr.NS_ERROR_UNEXPECTED);
}
let request = Services.DOMRequest.createRequest(window);
let requestId = this.getRequestId(request);
iccCloseChannel: function(clientId, channel, callback) {
let requestId = UUIDGenerator.generateUUID().toString();
this._addIccChannelCallback(requestId, callback);
cpmm.sendAsyncMessage("RIL:IccCloseChannel", {
clientId: clientId,
@ -466,7 +466,6 @@ RILContentHelper.prototype = {
channel: channel
}
});
return request;
},
readContacts: function(clientId, window, contactType) {
@ -572,6 +571,22 @@ RILContentHelper.prototype = {
}
},
_addIccChannelCallback: function(requestId, channelCb) {
let cbInterfaces = this._iccChannelCallback;
if (!cbInterfaces[requestId] && channelCb) {
cbInterfaces[requestId] = channelCb;
return;
}
if (DEBUG) debug("Unable to add channelCbInterface for requestId : " + requestId);
},
_getIccChannelCallback: function(requestId) {
let cb = this._iccChannelCallback[requestId];
delete this._iccChannelCallback[requestId];
return cb;
},
registerIccMsg: function(clientId, listener) {
if (DEBUG) debug("Registering for ICC related messages");
this.registerListener("_iccListeners", clientId, listener);
@ -740,11 +755,10 @@ RILContentHelper.prototype = {
this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
break;
case "RIL:IccOpenChannel":
this.handleSimpleRequest(data.requestId, data.errorMsg,
data.channel);
this.handleIccOpenChannel(data);
break;
case "RIL:IccCloseChannel":
this.handleSimpleRequest(data.requestId, data.errorMsg, null);
this.handleIccCloseChannel(data);
break;
case "RIL:IccExchangeAPDU":
this.handleIccExchangeAPDU(data);
@ -769,13 +783,38 @@ RILContentHelper.prototype = {
}
},
handleIccExchangeAPDU: function(message) {
if (message.errorMsg) {
this.fireRequestError(message.requestId, message.errorMsg);
} else {
var result = [message.sw1, message.sw2, message.simResponse];
this.fireRequestSuccess(message.requestId, result);
handleIccOpenChannel: function(message) {
let requestId = message.requestId;
let callback = this._getIccChannelCallback(requestId);
if (!callback) {
return;
}
return !message.errorMsg ? callback.notifyOpenChannelSuccess(message.channel) :
callback.notifyError(message.errorMsg);
},
handleIccCloseChannel: function(message) {
let requestId = message.requestId;
let callback = this._getIccChannelCallback(requestId);
if (!callback) {
return;
}
return !message.errorMsg ? callback.notifyCloseChannelSuccess() :
callback.notifyError(message.errorMsg);
},
handleIccExchangeAPDU: function(message) {
let requestId = message.requestId;
let callback = this._getIccChannelCallback(requestId);
if (!callback) {
return;
}
return !message.errorMsg ?
callback.notifyExchangeAPDUResponse(message.sw1, message.sw2, message.simResponse) :
callback.notifyError(message.errorMsg);
},
handleReadIccContacts: function(message) {

View File

@ -1993,20 +1993,20 @@ RadioInterface.prototype = {
matchMvno: function(target, message) {
if (DEBUG) this.debug("matchMvno: " + JSON.stringify(message));
if (!message || !message.mvnoType || !message.mvnoData) {
if (!message || !message.mvnoData) {
message.errorMsg = RIL.GECKO_ERROR_INVALID_PARAMETER;
}
if (!message.errorMsg) {
switch (message.mvnoType) {
case "imsi":
case RIL.GECKO_CARDMVNO_TYPE_IMSI:
if (!this.rilContext.imsi) {
message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
break;
}
message.result = this.isImsiMatches(message.mvnoData);
break;
case "spn":
case RIL.GECKO_CARDMVNO_TYPE_SPN:
let spn = this.rilContext.iccInfo && this.rilContext.iccInfo.spn;
if (!spn) {
message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
@ -2014,7 +2014,7 @@ RadioInterface.prototype = {
}
message.result = spn == message.mvnoData;
break;
case "gid":
case RIL.GECKO_CARDMVNO_TYPE_GID:
this.workerMessenger.send("getGID1", null, (function(response) {
let gid = response.gid1;
let mvnoDataLength = message.mvnoData.length;

View File

@ -1316,6 +1316,7 @@ this.GECKO_ICC_SERVICES = {
},
// @see 3GPP2 C.S0023-D 3.4.18 (RUIM).
ruim: {
FDN: 3,
ENHANCED_PHONEBOOK: 6,
SPN: 17,
SDN: 18
@ -2645,6 +2646,11 @@ this.GECKO_CARDCONTACT_TYPE_ADN = 0;
this.GECKO_CARDCONTACT_TYPE_FDN = 1;
this.GECKO_CARDCONTACT_TYPE_SDN = 2;
// See nsIIccProvider::CARD_MVNO_TYPE_*
this.GECKO_CARDMVNO_TYPE_IMSI = 0;
this.GECKO_CARDMVNO_TYPE_SPN = 1;
this.GECKO_CARDMVNO_TYPE_GID = 2;
// See ril.h RIL_PersoSubstate
this.PERSONSUBSTATE = {};
PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN;

View File

@ -1687,7 +1687,7 @@ RilObject.prototype = {
*/
hangUpAll: function() {
for (let callIndex in this.currentCalls) {
this.hangUp({callIndex: callIndex});
this.hangUpCall({callIndex: callIndex});
}
},
@ -1697,9 +1697,14 @@ RilObject.prototype = {
* @param callIndex
* Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS.
*/
hangUp: function(options) {
hangUpCall: function(options) {
let call = this.currentCalls[options.callIndex];
if (!call) {
// |hangUpCall()| is used to remove a call from the current call list,
// so we consider it as an successful case when hanging up a call that
// doesn't exist in the current call list.
options.success = true;
this.sendChromeMessage(options);
return;
}
@ -1781,6 +1786,9 @@ RilObject.prototype = {
answerCall: function(options) {
let call = this.currentCalls[options.callIndex];
if (!call) {
options.success = false;
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
this.sendChromeMessage(options);
return;
}
@ -1791,13 +1799,19 @@ RilObject.prototype = {
switch (call.state) {
case CALL_STATE_INCOMING:
this.telephonyRequestQueue.push(REQUEST_ANSWER, () => {
this.context.Buf.simpleRequest(REQUEST_ANSWER);
this.context.Buf.simpleRequest(REQUEST_ANSWER, options);
});
break;
case CALL_STATE_WAITING:
// Answer the waiting (second) call, and hold the first call.
this.switchActiveCall(options);
break;
default:
if (DEBUG) this.context.debug("AnswerCall: Invalid call state");
options.success = false;
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
this.sendChromeMessage(options);
}
},
@ -1808,12 +1822,13 @@ RilObject.prototype = {
* Call index of the call to reject.
*/
rejectCall: function(options) {
// Check for races. Since we dispatched the incoming/waiting call
// notification the incoming/waiting call may have changed. The main
// thread thinks that it is rejecting the call with the given index,
// so only reject if that is still incoming/waiting.
let call = this.currentCalls[options.callIndex];
if (!call) {
// |hangUpCall()| is used to remove an imcoming call from the current
// call list, so we consider it as an successful case when rejecting
// a call that doesn't exist in the current call list.
options.success = true;
this.sendChromeMessage(options);
return;
}
@ -1825,6 +1840,10 @@ RilObject.prototype = {
return;
}
// Check for races. Since we dispatched the incoming/waiting call
// notification the incoming/waiting call may have changed. The main
// thread thinks that it is rejecting the call with the given index,
// so only reject if that is still incoming/waiting.
switch (call.state) {
case CALL_STATE_INCOMING:
this.udub(options);
@ -1833,6 +1852,12 @@ RilObject.prototype = {
// Reject the waiting (second) call, and remain the first call.
this.hangUpBackground(options);
break;
default:
if (DEBUG) this.context.debug("RejectCall: Invalid call state");
options.success = false;
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
this.sendChromeMessage(options);
}
},
@ -1921,7 +1946,7 @@ RilObject.prototype = {
}
options.callIndex = 1;
this.hangUp(options);
this.hangUpCall(options);
return;
}
@ -5487,6 +5512,10 @@ RilObject.prototype[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, option
this.sendChromeMessage(options);
};
RilObject.prototype[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
if (options.rilMessageType == null) {
return;
}
options.success = (options.rilRequestError === 0);
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
this.sendChromeMessage(options);
@ -5514,6 +5543,11 @@ RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, op
this.sendChromeMessage(options);
};
RilObject.prototype[REQUEST_UDUB] = function REQUEST_UDUB(length, options) {
options.success = (options.rilRequestError === 0);
if (!options.success) {
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
}
this.sendChromeMessage(options);
};
RilObject.prototype[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
let Buf = this.context.Buf;
@ -5968,6 +6002,11 @@ RilObject.prototype[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV(length, op
this.IMEISV = this.context.Buf.readString();
};
RilObject.prototype[REQUEST_ANSWER] = function REQUEST_ANSWER(length, options) {
options.success = (options.rilRequestError === 0);
if (!options.success) {
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
}
this.sendChromeMessage(options);
};
RilObject.prototype[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
if (options.rilRequestError) {
@ -15232,6 +15271,7 @@ ICCContactHelperObject.prototype = {
*/
readICCContacts: function(appType, contactType, onsuccess, onerror) {
let ICCRecordHelper = this.context.ICCRecordHelper;
let ICCUtilsHelper = this.context.ICCUtilsHelper;
switch (contactType) {
case GECKO_CARDCONTACT_TYPE_ADN:
@ -15242,10 +15282,13 @@ ICCContactHelperObject.prototype = {
}
break;
case GECKO_CARDCONTACT_TYPE_FDN:
if (!ICCUtilsHelper.isICCServiceAvailable("FDN")) {
onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
break;
}
ICCRecordHelper.readADNLike(ICC_EF_FDN, onsuccess, onerror);
break;
case GECKO_CARDCONTACT_TYPE_SDN:
let ICCUtilsHelper = this.context.ICCUtilsHelper;
if (!ICCUtilsHelper.isICCServiceAvailable("SDN")) {
onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
break;
@ -15372,6 +15415,7 @@ ICCContactHelperObject.prototype = {
*/
updateICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
let ICCRecordHelper = this.context.ICCRecordHelper;
let ICCUtilsHelper = this.context.ICCUtilsHelper;
switch (contactType) {
case GECKO_CARDCONTACT_TYPE_ADN:
@ -15386,6 +15430,10 @@ ICCContactHelperObject.prototype = {
onerror(GECKO_ERROR_SIM_PIN2);
return;
}
if (!ICCUtilsHelper.isICCServiceAvailable("FDN")) {
onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
break;
}
ICCRecordHelper.updateADNLike(ICC_EF_FDN, contact, pin2, onsuccess, onerror);
break;
default:

View File

@ -130,8 +130,12 @@ add_test(function test_read_icc_contacts() {
ril.appType = aSimType;
ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ?
[0x0, 0x0C, 0x0, 0x0, 0x0]:
[0x0, 0x00, 0x0, 0x0, 0x0];
[0x20, 0x0C, 0x0, 0x0, 0x0]:
[0x20, 0x00, 0x0, 0x0, 0x0];
ril.iccInfoPrivate.sst = (aSimType === CARD_APPTYPE_SIM)?
[0x20, 0x0, 0x0, 0x0, 0x0]:
[0x2, 0x0, 0x0, 0x0, 0x0];
// Override some functions to test.
contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
@ -242,8 +246,11 @@ add_test(function test_update_icc_contact() {
function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
ril.appType = aSimType;
ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x0, 0x0C, 0x0, 0x0, 0x0]
: [0x0, 0x00, 0x0, 0x0, 0x0];
ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x20, 0x0C, 0x0, 0x0, 0x0]
: [0x20, 0x00, 0x0, 0x0, 0x0];
ril.iccInfoPrivate.sst = (aSimType === CARD_APPTYPE_SIM)?
[0x20, 0x0, 0x0, 0x0, 0x0]:
[0x2, 0x0, 0x0, 0x0, 0x0];
recordHelper.readPBR = function(onsuccess, onerror) {
if (aFileType === ICC_USIM_TYPE1_TAG) {

View File

@ -7,6 +7,7 @@
#include "TelephonyCall.h"
#include "mozilla/dom/CallEvent.h"
#include "mozilla/dom/TelephonyCallBinding.h"
#include "mozilla/dom/telephony/TelephonyCallback.h"
#include "mozilla/dom/DOMError.h"
@ -14,6 +15,7 @@
#include "TelephonyCallGroup.h"
using namespace mozilla::dom;
using namespace mozilla::dom::telephony;
using mozilla::ErrorResult;
// static
@ -226,100 +228,140 @@ TelephonyCall::GetGroup() const
return group.forget();
}
void
already_AddRefed<Promise>
TelephonyCall::Answer(ErrorResult& aRv)
{
if (mCallState != nsITelephonyService::CALL_STATE_INCOMING) {
NS_WARNING("Answer on non-incoming call ignored!");
return;
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsresult rv = mTelephony->Service()->AnswerCall(mServiceId, mCallIndex);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
if (mCallState != nsITelephonyService::CALL_STATE_INCOMING) {
NS_WARNING("Answer on non-incoming call is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mTelephony->Service()->AnswerCall(mServiceId, mCallIndex, callback);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
ChangeStateInternal(nsITelephonyService::CALL_STATE_CONNECTING, true);
return promise.forget();
}
void
already_AddRefed<Promise>
TelephonyCall::HangUp(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTING ||
mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
NS_WARNING("HangUp on previously disconnected call ignored!");
return;
NS_WARNING("HangUp on previously disconnected call is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsresult rv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
mTelephony->Service()->RejectCall(mServiceId, mCallIndex) :
mTelephony->Service()->HangUp(mServiceId, mCallIndex);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
mTelephony->Service()->RejectCall(mServiceId, mCallIndex, callback) :
mTelephony->Service()->HangUpCall(mServiceId, mCallIndex, callback);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
ChangeStateInternal(nsITelephonyService::CALL_STATE_DISCONNECTING, true);
return promise.forget();
}
void
already_AddRefed<Promise>
TelephonyCall::Hold(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
NS_WARNING("Hold non-connected call ignored!");
return;
NS_WARNING("Hold non-connected call is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
if (mGroup) {
NS_WARNING("Hold a call in conference ignored!");
return;
NS_WARNING("Hold a call in conference is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
if (!mSwitchable) {
NS_WARNING("Hold a non-switchable call ignored!");
return;
NS_WARNING("Hold a non-switchable call is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsresult rv = mTelephony->Service()->HoldCall(mServiceId, mCallIndex);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mTelephony->Service()->HoldCall(mServiceId, mCallIndex, callback);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
if (mSecondId) {
// No state transition when we switch two numbers within one TelephonyCall
// object. Otherwise, the state here will be inconsistent with the backend
// RIL and will never be right.
return;
return promise.forget();
}
ChangeStateInternal(nsITelephonyService::CALL_STATE_HOLDING, true);
return promise.forget();
}
void
already_AddRefed<Promise>
TelephonyCall::Resume(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
NS_WARNING("Resume non-held call ignored!");
return;
NS_WARNING("Resume non-held call is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
if (mGroup) {
NS_WARNING("Resume a call in conference ignored!");
return;
NS_WARNING("Resume a call in conference is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
if (!mSwitchable) {
NS_WARNING("Resume a non-switchable call ignored!");
return;
NS_WARNING("Resume a non-switchable call is rejected!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsresult rv = mTelephony->Service()->ResumeCall(mServiceId, mCallIndex);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mTelephony->Service()->ResumeCall(mServiceId, mCallIndex, callback);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
ChangeStateInternal(nsITelephonyService::CALL_STATE_RESUMING, true);
return promise.forget();
}

View File

@ -7,11 +7,10 @@
#ifndef mozilla_dom_telephony_telephonycall_h__
#define mozilla_dom_telephony_telephonycall_h__
#include "mozilla/dom/telephony/TelephonyCommon.h"
#include "mozilla/dom/DOMError.h"
#include "TelephonyCallId.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/TelephonyCallId.h"
#include "mozilla/dom/telephony/TelephonyCommon.h"
class nsPIDOMWindow;
@ -91,16 +90,16 @@ public:
already_AddRefed<TelephonyCallGroup>
GetGroup() const;
void
already_AddRefed<Promise>
Answer(ErrorResult& aRv);
void
already_AddRefed<Promise>
HangUp(ErrorResult& aRv);
void
already_AddRefed<Promise>
Hold(ErrorResult& aRv);
void
already_AddRefed<Promise>
Resume(ErrorResult& aRv);
IMPL_EVENT_HANDLER(statechange)

View File

@ -497,7 +497,7 @@ TelephonyService.prototype = {
} else if (aNumber === "1") {
this._sendToRilWorker(aClientId, "hangUpForeground", null, mmiCallback);
} else if (aNumber[0] === "1" && aNumber.length === 2) {
this._sendToRilWorker(aClientId, "hangUp",
this._sendToRilWorker(aClientId, "hangUpCall",
{ callIndex: parseInt(aNumber[1]) }, mmiCallback);
} else if (aNumber === "2") {
this._sendToRilWorker(aClientId, "switchActiveCall", null, mmiCallback);
@ -589,7 +589,9 @@ TelephonyService.prototype = {
if (activeCall.isConference) {
this.holdConference(aClientId);
} else {
this.holdCall(aClientId, activeCall.callIndex);
this.holdCall(aClientId, activeCall.callIndex,
{ notifySuccess: function () {},
notifyError: function (errorMsg) {} });
}
}
},
@ -879,14 +881,19 @@ TelephonyService.prototype = {
}
},
hangUp: function(aClientId, aCallIndex) {
let parentId = this._currentCalls[aClientId][aCallIndex].parentId;
if (parentId) {
// Should release both, child and parent, together. Since RIL holds only
// the parent call, we send 'parentId' to RIL.
this.hangUp(aClientId, parentId);
/**
* The default callback handler for call operations.
*
* @param aCallback
* An callback object including notifySuccess() and notifyError(aMsg)
* @param aResponse
* The response from ril_worker.
*/
_defaultCallbackHandler: function(aCallback, aResponse) {
if (!aResponse.success) {
aCallback.notifyError(aResponse.errorMsg);
} else {
this._sendToRilWorker(aClientId, "hangUp", { callIndex: aCallIndex });
aCallback.notifySuccess();
}
},
@ -898,34 +905,48 @@ TelephonyService.prototype = {
this._sendToRilWorker(aClientId, "stopTone");
},
answerCall: function(aClientId, aCallIndex) {
this._sendToRilWorker(aClientId, "answerCall", { callIndex: aCallIndex });
answerCall: function(aClientId, aCallIndex, aCallback) {
this._sendToRilWorker(aClientId, "answerCall", { callIndex: aCallIndex },
this._defaultCallbackHandler.bind(this, aCallback));
},
rejectCall: function(aClientId, aCallIndex) {
this._sendToRilWorker(aClientId, "rejectCall", { callIndex: aCallIndex });
rejectCall: function(aClientId, aCallIndex, aCallback) {
this._sendToRilWorker(aClientId, "rejectCall", { callIndex: aCallIndex },
this._defaultCallbackHandler.bind(this, aCallback));
},
holdCall: function(aClientId, aCallIndex) {
hangUpCall: function(aClientId, aCallIndex, aCallback) {
let parentId = this._currentCalls[aClientId][aCallIndex].parentId;
if (parentId) {
// Should release both, child and parent, together. Since RIL holds only
// the parent call, we send 'parentId' to RIL.
this.hangUpCall(aClientId, parentId, aCallback);
} else {
this._sendToRilWorker(aClientId, "hangUpCall", { callIndex: aCallIndex },
this._defaultCallbackHandler.bind(this, aCallback));
}
},
holdCall: function(aClientId, aCallIndex, aCallback) {
let call = this._currentCalls[aClientId][aCallIndex];
if (!call || !call.isSwitchable) {
// TODO: Bug 975949 - [B2G] Telephony should throw exceptions when some
// operations aren't allowed instead of simply ignoring them.
aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
return;
}
this._sendToRilWorker(aClientId, "holdCall", { callIndex: aCallIndex });
this._sendToRilWorker(aClientId, "holdCall", { callIndex: aCallIndex },
this._defaultCallbackHandler.bind(this, aCallback));
},
resumeCall: function(aClientId, aCallIndex) {
resumeCall: function(aClientId, aCallIndex, aCallback) {
let call = this._currentCalls[aClientId][aCallIndex];
if (!call || !call.isSwitchable) {
// TODO: Bug 975949 - [B2G] Telephony should throw exceptions when some
// operations aren't allowed instead of simply ignoring them.
aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
return;
}
this._sendToRilWorker(aClientId, "resumeCall", { callIndex: aCallIndex });
this._sendToRilWorker(aClientId, "resumeCall", { callIndex: aCallIndex },
this._defaultCallbackHandler.bind(this, aCallback));
},
conferenceCall: function(aClientId) {

View File

@ -35,12 +35,47 @@ struct HangUpConferenceRequest
uint32_t clientId;
};
struct AnswerCallRequest
{
uint32_t clientId;
uint32_t callIndex;
};
struct HangUpCallRequest
{
uint32_t clientId;
uint32_t callIndex;
};
struct RejectCallRequest
{
uint32_t clientId;
uint32_t callIndex;
};
struct HoldCallRequest
{
uint32_t clientId;
uint32_t callIndex;
};
struct ResumeCallRequest
{
uint32_t clientId;
uint32_t callIndex;
};
union IPCTelephonyRequest
{
EnumerateCallsRequest;
DialRequest;
USSDRequest;
HangUpConferenceRequest;
AnswerCallRequest;
HangUpCallRequest;
RejectCallRequest;
HoldCallRequest;
ResumeCallRequest;
};
sync protocol PTelephony {
@ -76,16 +111,6 @@ parent:
UnregisterListener();
HangUpCall(uint32_t aClientId, uint32_t aCallIndex);
AnswerCall(uint32_t aClientId, uint32_t aCallIndex);
RejectCall(uint32_t aClientId, uint32_t aCallIndex);
HoldCall(uint32_t aClientId, uint32_t aCallIndex);
ResumeCall(uint32_t aClientId, uint32_t aCallIndex);
ConferenceCall(uint32_t aClientId);
SeparateCall(uint32_t aClientId, uint32_t aCallIndex);

View File

@ -171,63 +171,63 @@ TelephonyIPCService::Dial(uint32_t aClientId, const nsAString& aNumber,
}
NS_IMETHODIMP
TelephonyIPCService::HangUp(uint32_t aClientId, uint32_t aCallIndex)
TelephonyIPCService::AnswerCall(uint32_t aClientId, uint32_t aCallIndex,
nsITelephonyCallback *aCallback)
{
if (!mPTelephonyChild) {
NS_WARNING("TelephonyService used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendHangUpCall(aClientId, aCallIndex);
return NS_OK;
return SendRequest(nullptr, aCallback, AnswerCallRequest(aClientId, aCallIndex));
}
NS_IMETHODIMP
TelephonyIPCService::AnswerCall(uint32_t aClientId, uint32_t aCallIndex)
TelephonyIPCService::HangUpCall(uint32_t aClientId, uint32_t aCallIndex,
nsITelephonyCallback *aCallback)
{
if (!mPTelephonyChild) {
NS_WARNING("TelephonyService used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendAnswerCall(aClientId, aCallIndex);
return NS_OK;
return SendRequest(nullptr, aCallback, HangUpCallRequest(aClientId, aCallIndex));
}
NS_IMETHODIMP
TelephonyIPCService::RejectCall(uint32_t aClientId, uint32_t aCallIndex)
TelephonyIPCService::RejectCall(uint32_t aClientId, uint32_t aCallIndex,
nsITelephonyCallback *aCallback)
{
if (!mPTelephonyChild) {
NS_WARNING("TelephonyService used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendRejectCall(aClientId, aCallIndex);
return NS_OK;
return SendRequest(nullptr, aCallback, RejectCallRequest(aClientId, aCallIndex));
}
NS_IMETHODIMP
TelephonyIPCService::HoldCall(uint32_t aClientId, uint32_t aCallIndex)
TelephonyIPCService::HoldCall(uint32_t aClientId, uint32_t aCallIndex,
nsITelephonyCallback *aCallback)
{
if (!mPTelephonyChild) {
NS_WARNING("TelephonyService used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendHoldCall(aClientId, aCallIndex);
return NS_OK;
return SendRequest(nullptr, aCallback, HoldCallRequest(aClientId, aCallIndex));
}
NS_IMETHODIMP
TelephonyIPCService::ResumeCall(uint32_t aClientId, uint32_t aCallIndex)
TelephonyIPCService::ResumeCall(uint32_t aClientId, uint32_t aCallIndex,
nsITelephonyCallback *aCallback)
{
if (!mPTelephonyChild) {
NS_WARNING("TelephonyService used after shutdown has begun!");
return NS_ERROR_FAILURE;
}
mPTelephonyChild->SendResumeCall(aClientId, aCallIndex);
return NS_OK;
return SendRequest(nullptr, aCallback, ResumeCallRequest(aClientId, aCallIndex));
}
NS_IMETHODIMP

View File

@ -37,16 +37,71 @@ TelephonyParent::RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActo
const IPCTelephonyRequest& aRequest)
{
TelephonyRequestParent* actor = static_cast<TelephonyRequestParent*>(aActor);
nsCOMPtr<nsITelephonyService> service = do_GetService(TELEPHONY_SERVICE_CONTRACTID);
if (!service) {
return NS_SUCCEEDED(actor->NotifyError(NS_LITERAL_STRING("InvalidStateError")));
}
switch (aRequest.type()) {
case IPCTelephonyRequest::TEnumerateCallsRequest:
return actor->DoRequest(aRequest.get_EnumerateCallsRequest());
case IPCTelephonyRequest::TDialRequest:
return actor->DoRequest(aRequest.get_DialRequest());
case IPCTelephonyRequest::TUSSDRequest:
return actor->DoRequest(aRequest.get_USSDRequest());
case IPCTelephonyRequest::THangUpConferenceRequest:
return actor->DoRequest(aRequest.get_HangUpConferenceRequest());
case IPCTelephonyRequest::TEnumerateCallsRequest: {
nsresult rv = service->EnumerateCalls(actor);
if (NS_FAILED(rv)) {
return NS_SUCCEEDED(EnumerateCallStateComplete());
} else {
return true;
}
}
case IPCTelephonyRequest::TDialRequest: {
const DialRequest& request = aRequest.get_DialRequest();
service->Dial(request.clientId(), request.number(),
request.isEmergency(), actor);
return true;
}
case IPCTelephonyRequest::TUSSDRequest: {
const USSDRequest& request = aRequest.get_USSDRequest();
service->SendUSSD(request.clientId(), request.ussd(), actor);
return true;
}
case IPCTelephonyRequest::THangUpConferenceRequest: {
const HangUpConferenceRequest& request = aRequest.get_HangUpConferenceRequest();
service->HangUpConference(request.clientId(), actor);
return true;
}
case IPCTelephonyRequest::TAnswerCallRequest: {
const AnswerCallRequest& request = aRequest.get_AnswerCallRequest();
service->AnswerCall(request.clientId(), request.callIndex(), actor);
return true;
}
case IPCTelephonyRequest::THangUpCallRequest: {
const HangUpCallRequest& request = aRequest.get_HangUpCallRequest();
service->HangUpCall(request.clientId(), request.callIndex(), actor);
return true;
}
case IPCTelephonyRequest::TRejectCallRequest: {
const RejectCallRequest& request = aRequest.get_RejectCallRequest();
service->RejectCall(request.clientId(), request.callIndex(), actor);
return true;
}
case IPCTelephonyRequest::THoldCallRequest: {
const HoldCallRequest& request = aRequest.get_HoldCallRequest();
service->HoldCall(request.clientId(), request.callIndex(), actor);
return true;
}
case IPCTelephonyRequest::TResumeCallRequest: {
const ResumeCallRequest& request = aRequest.get_ResumeCallRequest();
service->ResumeCall(request.clientId(), request.callIndex(), actor);
return true;
}
default:
MOZ_CRASH("Unknown type!");
}
@ -105,66 +160,6 @@ TelephonyParent::RecvUnregisterListener()
return true;
}
bool
TelephonyParent::RecvHangUpCall(const uint32_t& aClientId,
const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(service, true);
service->HangUp(aClientId, aCallIndex);
return true;
}
bool
TelephonyParent::RecvAnswerCall(const uint32_t& aClientId,
const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(service, true);
service->AnswerCall(aClientId, aCallIndex);
return true;
}
bool
TelephonyParent::RecvRejectCall(const uint32_t& aClientId,
const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(service, true);
service->RejectCall(aClientId, aCallIndex);
return true;
}
bool
TelephonyParent::RecvHoldCall(const uint32_t& aClientId,
const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(service, true);
service->HoldCall(aClientId, aCallIndex);
return true;
}
bool
TelephonyParent::RecvResumeCall(const uint32_t& aClientId,
const uint32_t& aCallIndex)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(service, true);
service->ResumeCall(aClientId, aCallIndex);
return true;
}
bool
TelephonyParent::RecvConferenceCall(const uint32_t& aClientId)
{
@ -406,67 +401,6 @@ TelephonyRequestParent::ActorDestroy(ActorDestroyReason why)
mActorDestroyed = true;
}
bool
TelephonyRequestParent::DoRequest(const EnumerateCallsRequest& aRequest)
{
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
if (service) {
rv = service->EnumerateCalls(this);
}
if (NS_FAILED(rv)) {
return NS_SUCCEEDED(EnumerateCallStateComplete());
}
return true;
}
bool
TelephonyRequestParent::DoRequest(const DialRequest& aRequest)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
if (service) {
service->Dial(aRequest.clientId(), aRequest.number(),
aRequest.isEmergency(), this);
} else {
return NS_SUCCEEDED(NotifyError(NS_LITERAL_STRING("InvalidStateError")));
}
return true;
}
bool
TelephonyRequestParent::DoRequest(const USSDRequest& aRequest)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
if (service) {
service->SendUSSD(aRequest.clientId(), aRequest.ussd(), this);
} else {
return NS_SUCCEEDED(NotifyError(NS_LITERAL_STRING("InvalidStateError")));
}
return true;
}
bool
TelephonyRequestParent::DoRequest(const HangUpConferenceRequest& aRequest)
{
nsCOMPtr<nsITelephonyService> service =
do_GetService(TELEPHONY_SERVICE_CONTRACTID);
if (service) {
service->HangUpConference(aRequest.clientId(), this);
} else {
return NS_SUCCEEDED(NotifyError(NS_LITERAL_STRING("InvalidStateError")));
}
return true;
}
nsresult
TelephonyRequestParent::SendResponse(const IPCTelephonyResponse& aResponse)
{

View File

@ -46,21 +46,6 @@ protected:
virtual bool
RecvUnregisterListener() MOZ_OVERRIDE;
virtual bool
RecvHangUpCall(const uint32_t& aClientId, const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvAnswerCall(const uint32_t& aClientId, const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvRejectCall(const uint32_t& aClientId, const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvHoldCall(const uint32_t& aClientId, const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvResumeCall(const uint32_t& aClientId, const uint32_t& aCallIndex) MOZ_OVERRIDE;
virtual bool
RecvConferenceCall(const uint32_t& aClientId) MOZ_OVERRIDE;
@ -120,18 +105,6 @@ protected:
private:
bool mActorDestroyed;
bool
DoRequest(const EnumerateCallsRequest& aRequest);
bool
DoRequest(const DialRequest& aRequest);
bool
DoRequest(const USSDRequest& aRequest);
bool
DoRequest(const HangUpConferenceRequest& aRequest);
};
END_TELEPHONY_NAMESPACE

View File

@ -10,7 +10,7 @@
"@mozilla.org/telephony/gonktelephonyservice;1"
%}
[scriptable, uuid(cbbe66d8-865b-11e4-94f1-ab441e55905b)]
[scriptable, uuid(aec05f05-0ca5-470b-8230-cdee0209eafd)]
interface nsIGonkTelephonyService : nsITelephonyService
{
void notifyAudioStateChanged(in unsigned long clientId, in short state);

View File

@ -251,7 +251,7 @@ interface nsITelephonyDialCallback : nsITelephonyCallback
* XPCOM component (in the content process) that provides the telephony
* information.
*/
[scriptable, uuid(6fa2d94b-80ee-4085-b6a0-535811ba9bb6)]
[scriptable, uuid(fd797bcc-54e2-4e4a-9ec7-3b72862d0d78)]
interface nsITelephonyService : nsISupports
{
const unsigned short CALL_STATE_UNKNOWN = 0;
@ -295,15 +295,25 @@ interface nsITelephonyService : nsISupports
*/
void dial(in unsigned long clientId, in DOMString number,
in boolean isEmergency, in nsITelephonyDialCallback callback);
void hangUp(in unsigned long clientId, in unsigned long callIndex);
void startTone(in unsigned long clientId, in DOMString dtmfChar);
void stopTone(in unsigned long clientId);
void answerCall(in unsigned long clientId, in unsigned long callIndex);
void rejectCall(in unsigned long clientId, in unsigned long callIndex);
void holdCall(in unsigned long clientId, in unsigned long callIndex);
void resumeCall(in unsigned long clientId, in unsigned long callIndex);
void answerCall(in unsigned long clientId,
in unsigned long callIndex,
in nsITelephonyCallback callback);
void rejectCall(in unsigned long clientId,
in unsigned long callIndex,
in nsITelephonyCallback callback);
void hangUpCall(in unsigned long clientId,
in unsigned long callIndex,
in nsITelephonyCallback callback);
void holdCall(in unsigned long clientId,
in unsigned long callIndex,
in nsITelephonyCallback callback);
void resumeCall(in unsigned long clientId,
in unsigned long callIndex,
in nsITelephonyCallback callback);
void conferenceCall(in unsigned long clientId);
void separateCall(in unsigned long clientId, in unsigned long callIndex);

View File

@ -520,7 +520,8 @@ let emulator = (function() {
promises.push(promise);
}
call.answer();
promise = call.answer();
promises.push(promise);
return Promise.all(promises).then(() => call);
}
@ -535,12 +536,16 @@ let emulator = (function() {
function hold(call) {
log("Putting the call on hold.");
let promises = [];
let promise = waitForNamedStateEvent(call, "holding")
.then(() => waitForNamedStateEvent(call, "held"));
promises.push(promise);
call.hold();
promise = call.hold();
promises.push(promise);
return promise;
return Promise.all(promises).then(() => call);
}
/**
@ -553,12 +558,16 @@ let emulator = (function() {
function resume(call) {
log("Resuming the held call.");
let promises = [];
let promise = waitForNamedStateEvent(call, "resuming")
.then(() => waitForNamedStateEvent(call, "connected"));
promises.push(promise);
call.resume();
promise = call.resume();
promises.push(promise);
return promise;
return Promise.all(promises).then(() => call);
}
/**
@ -571,12 +580,16 @@ let emulator = (function() {
function hangUp(call) {
log("Local hanging up the call: " + call.id.number);
let promises = [];
let promise = waitForNamedStateEvent(call, "disconnecting")
.then(() => waitForNamedStateEvent(call, "disconnected"));
promises.push(promise);
call.hangUp();
promise = call.hangUp();
promises.push(promise);
return promise;
return Promise.all(promises).then(() => call);
}
/**

View File

@ -15,9 +15,11 @@ function incoming() {
}
function connecting() {
let promise = gWaitForNamedStateEvent(inCall, "connecting");
inCall.answer();
return promise;
let promises = [
gWaitForNamedStateEvent(inCall, "connecting"),
inCall.answer()
];
return Promise.all(promises).then(() => inCall);
}
function hangUp() {

View File

@ -18,12 +18,13 @@ function checkUnexpected(msg, call, event1, event2, actionCallback) {
call.addEventListener(event1, error1);
call.addEventListener(event2, error2);
actionCallback();
return gDelay(2000).then(() => {
call.removeEventListener(event1, error1);
call.removeEventListener(event2, error2);
});
return actionCallback().then(
() => ok(false, msg + "should be rejected."),
() => gDelay(2000).then(() => {
call.removeEventListener(event1, error1);
call.removeEventListener(event2, error2);
}));
}
startTest(function() {

View File

@ -9,6 +9,7 @@ support-files =
[test_custom_element_callback_innerhtml.html]
[test_custom_element_clone_callbacks.html]
[test_custom_element_clone_callbacks_extended.html]
[test_custom_element_import_node_created_callback.html]
[test_nested_content_element.html]
[test_dest_insertion_points.html]
[test_dest_insertion_points_shadow.html]

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1093680
-->
<head>
<title>Test created callback order for imported custom element.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<template id="template"><x-foo><span></span></x-foo></template>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1093680">Bug 1093680</a>
<script>
var fooProtoCreatedCallbackCalled = false;
var fooProto = Object.create(HTMLElement.prototype);
fooProto.createdCallback = function() {
ok(this.firstElementChild, "When the created callback is called, the element should already have a child because the callback should only be called after cloning all the contents.");
fooProtoCreatedCallbackCalled = true;
};
document.registerElement("x-foo", { prototype: fooProto });
var template = document.getElementById("template");
// Importing node will implicityly clone the conent in the main document.
var adoptedFoo = document.importNode(template.content, true);
ok(fooProtoCreatedCallbackCalled, "Created callback should be called after importing custom element into document");
</script>
</body>
</html>

View File

@ -12,7 +12,7 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-applet-element
[NeedResolve]
[NeedResolve, UnsafeInPrerendering]
interface HTMLAppletElement : HTMLElement {
[Pure, SetterThrows]
attribute DOMString align;

View File

@ -13,7 +13,7 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-object-element
[NeedResolve]
[NeedResolve, UnsafeInPrerendering]
interface HTMLObjectElement : HTMLElement {
[Pure, SetterThrows]
attribute DOMString data;

View File

@ -82,6 +82,13 @@ enum IccContactType
"sdn" // Service Dialling Number.
};
enum IccMvnoType
{
"imsi",
"spn",
"gid"
};
dictionary IccUnlockCardLockOptions
{
required IccLockType lockType;
@ -315,17 +322,13 @@ interface MozIcc : EventTarget
*
* @param mvnoType
* Mvno type to use to compare the match data.
* Currently, we only support 'imsi'.
* @param matchData
* Data to be compared with ICC's field.
*
* @return a DOMRequest.
* The request's result will be a boolean indicating the matching
* result.
*
* TODO: change param mvnoType to WebIDL enum after Bug 864489 -
* B2G RIL: use ipdl as IPC in MozIccManager
*/
[Throws]
DOMRequest matchMvno(DOMString mvnoType, DOMString matchData);
DOMRequest matchMvno(IccMvnoType mvnoType, DOMString matchData);
};

View File

@ -73,7 +73,8 @@ interface MozNFCManager {
NavigatorProperty="mozNfc",
Func="Navigator::HasNFCSupport",
CheckPermissions="nfc nfc-share",
AvailableIn="PrivilegedApps"]
AvailableIn="PrivilegedApps",
UnsafeInPrerendering]
interface MozNFC : EventTarget {
/**
* Indicate if NFC is enabled.

View File

@ -10,6 +10,11 @@
[JSImplementation="@mozilla.org/nfc/peer;1", AvailableIn="PrivilegedApps"]
interface MozNFCPeer {
/**
* Indicate if this peer is already lost.
*/
readonly attribute boolean isLost;
/**
* Send NDEF data to peer device.
*/
@ -28,8 +33,6 @@ partial interface MozNFCPeer {
[ChromeOnly]
attribute DOMString session;
/**
* Indicate if this peer is already lost.
*/
readonly attribute boolean isLost;
[ChromeOnly]
void notifyLost();
};

View File

@ -8,28 +8,31 @@
* Copyright © 2013 Deutsche Telekom, Inc.
*/
/**
* The enumeration of NFC Tag technologies.
*/
enum NFCTechType {
"NFC_A",
"NFC_B",
"NFC_F",
"NFC_V",
"NFC_ISO_DEP",
"MIFARE_CLASSIC",
"MIFARE_ULTRALIGHT",
"NFC_BARCODE"
"NFC-A", // NFCForum-TS-DigitalProtocol-1.1 NFC-A.
"NFC-B", // NFCForum-TS-DigitalProtocol-1.1 NFC-B.
"NFC-F", // NFCForum-TS-DigitalProtocol-1.1 NFC-F.
"NFC-V", // ISO 15693.
"ISO-DEP", // NFCForum-TS-DigitalProtocol-1.1 ISO-DEP.
"MIFARE-Classic", // MIFARE Classic from NXP.
"MIFARE-Ultralight", // MIFARE Ultralight from NXP.
"NFC-Barcode" // NFC Barcode from Kovio.
};
/**
* The enumeration of the types of the tag, the type of a tag could be either
* one of those types defined in NFC Forum (type1 ~ type 4), or it could be a
* NXP-specific tag, like Mifare Classic.
* one of those types defined in NFC Forum Tag Types (Type1 ~ Type 4), or it
* could be a NXP-specific tag, like MIFARE Classic.
*/
enum NFCTagType {
"type1",
"type2",
"type3",
"type4",
"mifare_classic"
"Type1",
"Type2",
"Type3",
"Type4",
"MIFARE-Classic"
};
[JSImplementation="@mozilla.org/nfc/tag;1", AvailableIn="PrivilegedApps"]
@ -69,6 +72,11 @@ interface MozNFCTag {
*/
readonly attribute boolean? canBeMadeReadOnly;
/**
* Indicate if this tag is already lost.
*/
readonly attribute boolean isLost;
/**
* Read current NDEF data on the tag.
*/
@ -99,8 +107,6 @@ partial interface MozNFCTag {
[ChromeOnly]
attribute DOMString session;
/**
* Indicate if this tag is already lost.
*/
readonly attribute boolean isLost;
[ChromeOnly]
void notifyLost();
};

View File

@ -126,7 +126,8 @@ dictionary IPConfiguration {
[JSImplementation="@mozilla.org/wifimanager;1",
NavigatorProperty="mozWifiManager",
Func="Navigator::HasWifiManagerSupport"]
Func="Navigator::HasWifiManagerSupport",
UnsafeInPrerendering]
interface MozWifiManager : EventTarget {
/**
* Turn on/off wifi functionality.

View File

@ -193,7 +193,7 @@ partial interface Navigator {
readonly attribute boolean cookieEnabled;
[Throws]
readonly attribute DOMString buildID;
[Throws, CheckPermissions="power"]
[Throws, CheckPermissions="power", UnsafeInPrerendering]
readonly attribute MozPowerManager mozPower;
// WebKit/Blink/Trident/Presto support this.
@ -240,7 +240,7 @@ partial interface Navigator {
*
* @param aTopic resource name
*/
[Throws, Pref="dom.wakelock.enabled", Func="Navigator::HasWakeLockSupport"]
[Throws, Pref="dom.wakelock.enabled", Func="Navigator::HasWakeLockSupport", UnsafeInPrerendering]
MozWakeLock requestWakeLock(DOMString aTopic);
};
@ -344,7 +344,7 @@ partial interface Navigator {
#ifdef MOZ_TIME_MANAGER
// nsIDOMMozNavigatorTime
partial interface Navigator {
[Throws, CheckPermissions="time"]
[Throws, CheckPermissions="time", UnsafeInPrerendering]
readonly attribute MozTimeManager mozTime;
};
#endif // MOZ_TIME_MANAGER

View File

@ -33,14 +33,14 @@ interface TelephonyCall : EventTarget {
readonly attribute TelephonyCallGroup? group;
[Throws]
void answer();
[Throws]
void hangUp();
[Throws]
void hold();
[Throws]
void resume();
[NewObject, Throws]
Promise<void> answer();
[NewObject, Throws]
Promise<void> hangUp();
[NewObject, Throws]
Promise<void> hold();
[NewObject, Throws]
Promise<void> resume();
attribute EventHandler onstatechange;
attribute EventHandler ondialing;

View File

@ -122,6 +122,9 @@ interface MozFrameLoaderOwner {
[ChromeOnly]
readonly attribute MozFrameLoader? frameLoader;
[ChromeOnly]
void setIsPrerendered();
[ChromeOnly, Throws]
void swapFrameLoaders(XULElement aOtherOwner);
};

Some files were not shown because too many files have changed in this diff Show More