Media elements should not be paused right away when removed from the document
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 May 2016 21:33:45 +0000 (21:33 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 May 2016 21:33:45 +0000 (21:33 +0000)
commit611434a2e9dfa7782b7aba622e5a99584f292f80
treee4df19112211080253cda3e47ad891990ddb3e19
parentf59543963dd8168d035b44e0b926bac373511bc7
Media elements should not be paused right away when removed from the document
https://bugs.webkit.org/show_bug.cgi?id=157347
<rdar://problem/25888758>

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

Rebaseline now that more W3C tests are passing.

* web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document-expected.txt:
* web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document-expected.txt:
* web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-expected.txt:

Source/WebCore:

Media elements should not be paused right away when removed from the document.
Instead we should allow the task that removed the media element from the
document to finish because considering pausing.

This avoid inadvertently pausing media elements when the JS merely moves them
on the page (e.g. using Node.replaceChild()).

Text from the HTML specification:
"""
When a media element is removed from a Document, the user agent must run the
following steps:
1.  Await a stable state, allowing the task that removed the media element
    from the Document to continue. The synchronous section consists of all the
    remaining steps of this algorithm. (Steps in the synchronous section are
    marked with ⌛.)
2. ⌛ If the media element is in a Document, abort these steps.
3. ⌛ Run the internal pause steps for the media element.
"""

c.f. https://html.spec.whatwg.org/multipage/embedded-content.html#htmlmediaelement

Test: media/replaceChild-should-not-pause-video.html

* dom/GenericEventQueue.cpp:
(WebCore::GenericEventQueue::sharedTimerFired):
Copy the queue of events before processing it so that we don't fire events that
get scheduled by the event handlers as a result of us firing the pending events.
Otherwise, we end up firing events synchronously right after they've been queued,
which is wrong. This was causing several W3C tests to fail.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::pauseAfterDetachedTimerFired):
(WebCore::HTMLMediaElement::removedFrom):
* html/HTMLMediaElement.h:
After the media element gets removed from the document, schedule a 0 timer before
pausing the media element, to give the task that removed us a chance to finish.
When the timer fires, we check if we were added back into an active document and
avoid pausing in such case.

LayoutTests:

* media/remove-from-document-expected.txt:
* media/remove-from-document.html:
Check asynchronously if the video has been paused after removing it from
the document instead of synchronously as we no longer pause the video
synchronously in this case.

* media/replaceChild-should-not-pause-video-expected.txt: Added.
* media/replaceChild-should-not-pause-video.html: Added.
Add test case to make sure that calling replaceChild() on with a video
element as newChild does not pause the video if it is already playing.
This is a regression test for <rdar://problem/25888758>.

* webaudio/audiocontext-state-interrupted-expected.txt:
* webaudio/audiocontext-state-interrupted.html:
Add a missing call to
internals.setMediaSessionRestrictions("WebAudio", "InterruptedPlaybackNotPermitted")
before the fourth test. The fourth test was previously passing by
chance, due to a bug in GenericEventQueue sometimes firing events
synchronously after they are scheduled.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200431 268f45cc-cd09-0410-ab3c-d52691b4dbfc
15 files changed:
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-expected.txt
LayoutTests/media/remove-from-document-expected.txt
LayoutTests/media/remove-from-document.html
LayoutTests/media/replaceChild-should-not-pause-video-expected.txt [new file with mode: 0644]
LayoutTests/media/replaceChild-should-not-pause-video.html [new file with mode: 0644]
LayoutTests/webaudio/audiocontext-state-interrupted-expected.txt
LayoutTests/webaudio/audiocontext-state-interrupted.html
Source/WebCore/ChangeLog
Source/WebCore/dom/GenericEventQueue.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h