Nullptr crash accessing Document in GenericEventQueue::dispatchOneEvent()
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Jul 2018 03:31:29 +0000 (03:31 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Jul 2018 03:31:29 +0000 (03:31 +0000)
commit1d40b5d0b8e074c3ca48df8ade5015b9d1156afc
treec1a85df916e056e800a081ac7712b24615551801
parent9bdff3e4d0936497dff8365f915db8e0e47955d0
Nullptr crash accessing Document in GenericEventQueue::dispatchOneEvent()
https://bugs.webkit.org/show_bug.cgi?id=187284

Reviewed by Eric Carlson.

Source/WebCore:

The null pointer crash was caused by some GenericEventQueue dispatching an event in a stopped document,
which does not have a valid script execution context because some uses of GenericEventQueue in media code
was not closing the queue upon stopping of all active DOM objects.

Fixed all uses of GenericEventQueue which did not suspend or stop the queue with active DOM objects.
Made SourceBufferList and TrackListBase (along with AudioTrackList, TextTrackList, and VideoTrackList)
inherit from ActiveDOMObject instead of ContextDestructionObserver to do this.

Also fixed a bug that media elements inside a template element (and other cases where the document doesn't
have a browsing context) were scheduling events since this would hit the newly added debug assertion in
GenericEventQueue::dispatchOneEvent.

Test: media/track/video-track-addition-and-frame-removal.html

* Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp:
(WebCore::WebKitMediaKeySession::suspend): Assert that we never try to suspend when the document has
this object alive since canSuspendForDocumentSuspension always returns false.
(WebCore::WebKitMediaKeySession::resume): Ditto.
(WebCore::WebKitMediaKeySession::stop): Stop the event queue to avoid the crash.
* Modules/encryptedmedia/legacy/WebKitMediaKeySession.h:
* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::removeSourceBuffer): Don't do any work to update tracks when the active DOM
objects are stopped since this MediaSource and the related media objects are about to be destructed.
(WebCore::MediaSource::suspend): Assert that m_asyncEventQueue is empty as canSuspendForDocumentSuspension
returns false whenever the queue is not empty.
(WebCore::MediaSource::resume): Ditto.
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::suspend): Ditto.
(WebCore::SourceBuffer::resume): Ditto.
(WebCore::SourceBuffer::stop): Stop the event queue to avoid the crash.
* Modules/mediasource/SourceBuffer.h:
* Modules/mediasource/SourceBufferList.cpp:
(WebCore::SourceBufferList): Made this an active DOM object.
(WebCore::SourceBufferList::SourceBufferList):
(WebCore::SourceBufferList::canSuspendForDocumentSuspension const): Added. Return false when there are
pending events to match other media code.
(WebCore::SourceBufferList::suspend): Added. Assert that the event queue is empty here.
(WebCore::SourceBufferList::resume): Ditto.
(WebCore::SourceBufferList::stop): Added. Stop the event queue to avoid the crash.
(WebCore::SourceBufferList::activeDOMObjectName const): Added.
* Modules/mediasource/SourceBufferList.h:
(WebCore::SourceBufferList): Made this an active DOM object.
* Modules/mediasource/SourceBufferList.idl:
* dom/Document.h:
(WebCore::Document::hasBrowsingContext const): Added.
* dom/GenericEventQueue.cpp:
(WebCore::GenericEventQueue::dispatchOneEvent): Added an assertion to catch when an event is dispatched
inside a stopped document, which is never correct and causes this crash down the line.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::playInternal): Exit early when the document doesn't have a browsing context;
e.g. when the media element is inside a template element.
(WebCore::HTMLMediaElement::pauseInternal): Ditto.
(WebCore::HTMLMediaElement::sourceWasAdded): Ditto.
* html/track/AudioTrackList.cpp:
(AudioTrackList::activeDOMObjectName const): Added.
* html/track/AudioTrackList.h:
* html/track/AudioTrackList.idl:
* html/track/TextTrackList.cpp::
(TextTrackList::activeDOMObjectName const): Added.
* html/track/TextTrackList.h:
* html/track/TextTrackList.idl:
* html/track/TrackListBase.cpp:
(WebCore::TrackListBase): Made this an active DOM object.
(WebCore::TrackListBase::TrackListBase):
(WebCore::TrackListBase::canSuspendForDocumentSuspension const): Added. Return false when there are pending events
to match other media code.
(WebCore::TrackListBase::suspend): Added. Assert that the event queue is empty here.
(WebCore::TrackListBase::resume): Ditto.
(WebCore::TrackListBase::stop): Added. Stop the event queue to avoid the crash.
* html/track/TrackListBase.h:
* html/track/VideoTrackList.cpp:
(VideoTrackList::activeDOMObjectName const): Added.
* html/track/VideoTrackList.h:
* html/track/VideoTrackList.idl:

LayoutTests:

Added a regression test which reliably hits the newly added debug assertion.

* media/track/video-track-addition-and-frame-removal-expected.txt: Added.
* media/track/video-track-addition-and-frame-removal.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@233496 268f45cc-cd09-0410-ab3c-d52691b4dbfc
27 files changed:
LayoutTests/ChangeLog
LayoutTests/media/track/video-track-addition-and-frame-removal-expected.txt [new file with mode: 0644]
LayoutTests/media/track/video-track-addition-and-frame-removal.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp
Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h
Source/WebCore/Modules/mediasource/MediaSource.cpp
Source/WebCore/Modules/mediasource/MediaSource.h
Source/WebCore/Modules/mediasource/SourceBuffer.cpp
Source/WebCore/Modules/mediasource/SourceBuffer.h
Source/WebCore/Modules/mediasource/SourceBufferList.cpp
Source/WebCore/Modules/mediasource/SourceBufferList.h
Source/WebCore/Modules/mediasource/SourceBufferList.idl
Source/WebCore/dom/Document.h
Source/WebCore/dom/GenericEventQueue.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/track/AudioTrackList.cpp
Source/WebCore/html/track/AudioTrackList.h
Source/WebCore/html/track/AudioTrackList.idl
Source/WebCore/html/track/TextTrackList.cpp
Source/WebCore/html/track/TextTrackList.h
Source/WebCore/html/track/TextTrackList.idl
Source/WebCore/html/track/TrackListBase.cpp
Source/WebCore/html/track/TrackListBase.h
Source/WebCore/html/track/VideoTrackList.cpp
Source/WebCore/html/track/VideoTrackList.h
Source/WebCore/html/track/VideoTrackList.idl