Title: [269039] trunk
- Revision
- 269039
- Author
- [email protected]
- Date
- 2020-10-27 08:26:01 -0700 (Tue, 27 Oct 2020)
Log Message
AudioContext.suspend() should not reject promise when audio session is interrupted
https://bugs.webkit.org/show_bug.cgi?id=218235
Reviewed by Darin Adler.
Source/WebCore:
AudioContext.suspend() should not reject promise when audio session is interrupted. Being
"interrupted" is an internal WebKit concept and rejecting the promise here is confusing
to Web developers.
We now no longer throw when AudioContext.suspend() is called while interrupted. Instead,
we set the 'wasSuspendedByJavascript' flag and register a state change listener to resolve
the promise when the state changes to "suspended".
When the interruption ends, AudioContext::mayResumePlayback() gets called with
shouldResume=false, causing us to update the state from "interrupted" to "suspended",
which resolves the suspend promise.
Test: webaudio/suspend-context-while-interrupted.html
* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::suspendRendering):
LayoutTests:
Add layout test coverage.
* webaudio/suspend-context-while-interrupted-expected.txt: Added.
* webaudio/suspend-context-while-interrupted.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (269038 => 269039)
--- trunk/LayoutTests/ChangeLog 2020-10-27 13:56:30 UTC (rev 269038)
+++ trunk/LayoutTests/ChangeLog 2020-10-27 15:26:01 UTC (rev 269039)
@@ -1,3 +1,15 @@
+2020-10-27 Chris Dumez <[email protected]>
+
+ AudioContext.suspend() should not reject promise when audio session is interrupted
+ https://bugs.webkit.org/show_bug.cgi?id=218235
+
+ Reviewed by Darin Adler.
+
+ Add layout test coverage.
+
+ * webaudio/suspend-context-while-interrupted-expected.txt: Added.
+ * webaudio/suspend-context-while-interrupted.html: Added.
+
2020-10-27 Zalan Bujtas <[email protected]>
Remove unneeded whitespace between content and <br>
Added: trunk/LayoutTests/webaudio/suspend-context-while-interrupted-expected.txt (0 => 269039)
--- trunk/LayoutTests/webaudio/suspend-context-while-interrupted-expected.txt (rev 0)
+++ trunk/LayoutTests/webaudio/suspend-context-while-interrupted-expected.txt 2020-10-27 15:26:01 UTC (rev 269039)
@@ -0,0 +1,25 @@
+Tests that media session interruption does not cause AudioContext.suspend() to throw
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Did start rendering
+internals.beginMediaSessionInterruption('enteringbackground')
+PASS Did begin interruption
+PASS context.state is "interrupted"
+PASS context.state is "interrupted"
+PASS didResolveSuspendPromise is false
+PASS context.state is "interrupted"
+PASS didResolveSuspendPromise is false
+internals.endMediaSessionInterruption('mayresumeplaying')
+PASS context.suspend() promise was resolved
+PASS Did end interruption
+PASS context.state is "suspended"
+PASS didResolveSuspendPromise is true
+PASS context.state is "suspended"
+PASS resume() promise was resolved
+PASS context.state is "running"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/webaudio/suspend-context-while-interrupted.html (0 => 269039)
--- trunk/LayoutTests/webaudio/suspend-context-while-interrupted.html (rev 0)
+++ trunk/LayoutTests/webaudio/suspend-context-while-interrupted.html 2020-10-27 15:26:01 UTC (rev 269039)
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Tests that media session interruption does not cause AudioContext.suspend() to throw");
+jsTestIsAsync = true;
+
+let didResolveSuspendPromise = false;
+
+function didEndInterruption()
+{
+ testPassed("Did end interruption");
+ context._onstatechange_ = null;
+ // Interruption has ended but the script has called suspend() so we should move to "suspended"
+ // state.
+ shouldBeEqualToString("context.state", "suspended");
+ shouldBeTrue("didResolveSuspendPromise");
+
+ setTimeout(() => {
+ shouldBeEqualToString("context.state", "suspended");
+
+ context.resume().then(() => {
+ testPassed("resume() promise was resolved");
+ shouldBeEqualToString("context.state", "running");
+ finishJSTest();
+ }, (e) => {
+ testFailed("context.resume() call after uninterrupted threw an unexpected exception: " + e);
+ finishJSTest();
+ });
+ }, 10);
+}
+
+function didBeginInterruption()
+{
+ testPassed("Did begin interruption");
+ context._onstatechange_ = null;
+ shouldBeEqualToString("context.state", "interrupted");
+ context.suspend().then(() => {
+ testPassed("context.suspend() promise was resolved");
+ didResolveSuspendPromise = true;
+ }, (e) => {
+ testFailed("context.suspend() call while interrupted threw an unexpected exception: " + e);
+ finishJSTest();
+ });
+
+ shouldBeEqualToString("context.state", "interrupted");
+ shouldBeFalse("didResolveSuspendPromise");
+ setTimeout(() => {
+ shouldBeEqualToString("context.state", "interrupted");
+ shouldBeFalse("didResolveSuspendPromise");
+
+ context._onstatechange_ = didEndInterruption;
+ if (window.internals)
+ evalAndLog("internals.endMediaSessionInterruption('mayresumeplaying')");
+ }, 10);
+}
+
+function didStartRendering()
+{
+ testPassed("Did start rendering");
+ context._onstatechange_ = didBeginInterruption;
+ if (window.internals)
+ evalAndLog("internals.beginMediaSessionInterruption('enteringbackground')");
+}
+
+let context = new AudioContext;
+var source = context.createConstantSource();
+source.connect(context.destination);
+
+context._onstatechange_ = didStartRendering;
+source.start();
+</script>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (269038 => 269039)
--- trunk/Source/WebCore/ChangeLog 2020-10-27 13:56:30 UTC (rev 269038)
+++ trunk/Source/WebCore/ChangeLog 2020-10-27 15:26:01 UTC (rev 269039)
@@ -1,3 +1,27 @@
+2020-10-27 Chris Dumez <[email protected]>
+
+ AudioContext.suspend() should not reject promise when audio session is interrupted
+ https://bugs.webkit.org/show_bug.cgi?id=218235
+
+ Reviewed by Darin Adler.
+
+ AudioContext.suspend() should not reject promise when audio session is interrupted. Being
+ "interrupted" is an internal WebKit concept and rejecting the promise here is confusing
+ to Web developers.
+
+ We now no longer throw when AudioContext.suspend() is called while interrupted. Instead,
+ we set the 'wasSuspendedByJavascript' flag and register a state change listener to resolve
+ the promise when the state changes to "suspended".
+
+ When the interruption ends, AudioContext::mayResumePlayback() gets called with
+ shouldResume=false, causing us to update the state from "interrupted" to "suspended",
+ which resolves the suspend promise.
+
+ Test: webaudio/suspend-context-while-interrupted.html
+
+ * Modules/webaudio/AudioContext.cpp:
+ (WebCore::AudioContext::suspendRendering):
+
2020-10-27 Antti Koivisto <[email protected]>
Assert in BoxTree::layoutBoxForRenderer() under RenderLayer::updateScrollCornerStyle()
Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (269038 => 269039)
--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp 2020-10-27 13:56:30 UTC (rev 269038)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp 2020-10-27 15:26:01 UTC (rev 269039)
@@ -209,7 +209,7 @@
return;
}
- if (isStopped() || state() == State::Closed || state() == State::Interrupted || !destinationNode()) {
+ if (isStopped() || state() == State::Closed || !destinationNode()) {
promise.reject(Exception { InvalidStateError, "Context is closed"_s });
return;
}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes