Changeset 233496 in webkit


Ignore:
Timestamp:
Jul 3, 2018, 8:31:29 PM (6 years ago)
Author:
rniwa@webkit.org
Message:

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.
Location:
trunk
Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r233495 r233496  
     12018-07-03  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Nullptr crash accessing Document in GenericEventQueue::dispatchOneEvent()
     4        https://bugs.webkit.org/show_bug.cgi?id=187284
     5
     6        Reviewed by Eric Carlson.
     7
     8        Added a regression test which reliably hits the newly added debug assertion.
     9
     10        * media/track/video-track-addition-and-frame-removal-expected.txt: Added.
     11        * media/track/video-track-addition-and-frame-removal.html: Added.
     12
    1132018-07-03  Fujii Hironori  <Hironori.Fujii@sony.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r233495 r233496  
     12018-07-03  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Nullptr crash accessing Document in GenericEventQueue::dispatchOneEvent()
     4        https://bugs.webkit.org/show_bug.cgi?id=187284
     5
     6        Reviewed by Eric Carlson.
     7
     8        The null pointer crash was caused by some GenericEventQueue dispatching an event in a stopped document,
     9        which does not have a valid script execution context because some uses of GenericEventQueue in media code
     10        was not closing the queue upon stopping of all active DOM objects.
     11
     12        Fixed all uses of GenericEventQueue which did not suspend or stop the queue with active DOM objects.
     13        Made SourceBufferList and TrackListBase (along with AudioTrackList, TextTrackList, and VideoTrackList)
     14        inherit from ActiveDOMObject instead of ContextDestructionObserver to do this.
     15
     16        Also fixed a bug that media elements inside a template element (and other cases where the document doesn't
     17        have a browsing context) were scheduling events since this would hit the newly added debug assertion in
     18        GenericEventQueue::dispatchOneEvent.
     19
     20        Test: media/track/video-track-addition-and-frame-removal.html
     21
     22        * Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp:
     23        (WebCore::WebKitMediaKeySession::suspend): Assert that we never try to suspend when the document has
     24        this object alive since canSuspendForDocumentSuspension always returns false.
     25        (WebCore::WebKitMediaKeySession::resume): Ditto.
     26        (WebCore::WebKitMediaKeySession::stop): Stop the event queue to avoid the crash.
     27        * Modules/encryptedmedia/legacy/WebKitMediaKeySession.h:
     28        * Modules/mediasource/MediaSource.cpp:
     29        (WebCore::MediaSource::removeSourceBuffer): Don't do any work to update tracks when the active DOM
     30        objects are stopped since this MediaSource and the related media objects are about to be destructed.
     31        (WebCore::MediaSource::suspend): Assert that m_asyncEventQueue is empty as canSuspendForDocumentSuspension
     32        returns false whenever the queue is not empty.
     33        (WebCore::MediaSource::resume): Ditto.
     34        * Modules/mediasource/MediaSource.h:
     35        * Modules/mediasource/SourceBuffer.cpp:
     36        (WebCore::SourceBuffer::suspend): Ditto.
     37        (WebCore::SourceBuffer::resume): Ditto.
     38        (WebCore::SourceBuffer::stop): Stop the event queue to avoid the crash.
     39        * Modules/mediasource/SourceBuffer.h:
     40        * Modules/mediasource/SourceBufferList.cpp:
     41        (WebCore::SourceBufferList): Made this an active DOM object.
     42        (WebCore::SourceBufferList::SourceBufferList):
     43        (WebCore::SourceBufferList::canSuspendForDocumentSuspension const): Added. Return false when there are
     44        pending events to match other media code.
     45        (WebCore::SourceBufferList::suspend): Added. Assert that the event queue is empty here.
     46        (WebCore::SourceBufferList::resume): Ditto.
     47        (WebCore::SourceBufferList::stop): Added. Stop the event queue to avoid the crash.
     48        (WebCore::SourceBufferList::activeDOMObjectName const): Added.
     49        * Modules/mediasource/SourceBufferList.h:
     50        (WebCore::SourceBufferList): Made this an active DOM object.
     51        * Modules/mediasource/SourceBufferList.idl:
     52        * dom/Document.h:
     53        (WebCore::Document::hasBrowsingContext const): Added.
     54        * dom/GenericEventQueue.cpp:
     55        (WebCore::GenericEventQueue::dispatchOneEvent): Added an assertion to catch when an event is dispatched
     56        inside a stopped document, which is never correct and causes this crash down the line.
     57        * html/HTMLMediaElement.cpp:
     58        (WebCore::HTMLMediaElement::playInternal): Exit early when the document doesn't have a browsing context;
     59        e.g. when the media element is inside a template element.
     60        (WebCore::HTMLMediaElement::pauseInternal): Ditto.
     61        (WebCore::HTMLMediaElement::sourceWasAdded): Ditto.
     62        * html/track/AudioTrackList.cpp:
     63        (AudioTrackList::activeDOMObjectName const): Added.
     64        * html/track/AudioTrackList.h:
     65        * html/track/AudioTrackList.idl:
     66        * html/track/TextTrackList.cpp::
     67        (TextTrackList::activeDOMObjectName const): Added.
     68        * html/track/TextTrackList.h:
     69        * html/track/TextTrackList.idl:
     70        * html/track/TrackListBase.cpp:
     71        (WebCore::TrackListBase): Made this an active DOM object.
     72        (WebCore::TrackListBase::TrackListBase):
     73        (WebCore::TrackListBase::canSuspendForDocumentSuspension const): Added. Return false when there are pending events
     74        to match other media code.
     75        (WebCore::TrackListBase::suspend): Added. Assert that the event queue is empty here.
     76        (WebCore::TrackListBase::resume): Ditto.
     77        (WebCore::TrackListBase::stop): Added. Stop the event queue to avoid the crash.
     78        * html/track/TrackListBase.h:
     79        * html/track/VideoTrackList.cpp:
     80        (VideoTrackList::activeDOMObjectName const): Added.
     81        * html/track/VideoTrackList.h:
     82        * html/track/VideoTrackList.idl:
     83
    1842018-07-03  Fujii Hironori  <Hironori.Fujii@sony.com>
    285
  • trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp

    r229979 r233496  
    240240}
    241241
     242void WebKitMediaKeySession::suspend(ReasonForSuspension)
     243{
     244    ASSERT_NOT_REACHED();
     245}
     246
     247void WebKitMediaKeySession::resume()
     248{
     249    ASSERT_NOT_REACHED();
     250}
     251
    242252void WebKitMediaKeySession::stop()
    243253{
     254    m_asyncEventQueue.close();
    244255    close();
    245256}
  • trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h

    r228218 r233496  
    7777    void derefEventTarget() final { deref(); }
    7878
     79    void suspend(ReasonForSuspension) final;
     80    void resume() final;
    7981    void stop() final;
    8082    bool canSuspendForDocumentSuspension() const final;
  • trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp

    r230909 r233496  
    693693    buffer.abortIfUpdating();
    694694
    695     // 4. Let SourceBuffer audioTracks list equal the AudioTrackList object returned by sourceBuffer.audioTracks.
    696     auto& audioTracks = buffer.audioTracks();
    697 
    698     // 5. If the SourceBuffer audioTracks list is not empty, then run the following steps:
    699     if (audioTracks.length()) {
    700         // 5.1 Let HTMLMediaElement audioTracks list equal the AudioTrackList object returned by the audioTracks
    701         // attribute on the HTMLMediaElement.
    702         // 5.2 Let the removed enabled audio track flag equal false.
    703         bool removedEnabledAudioTrack = false;
    704 
    705         // 5.3 For each AudioTrack object in the SourceBuffer audioTracks list, run the following steps:
    706         while (audioTracks.length()) {
    707             auto& track = *audioTracks.lastItem();
    708 
    709             // 5.3.1 Set the sourceBuffer attribute on the AudioTrack object to null.
    710             track.setSourceBuffer(nullptr);
    711 
    712             // 5.3.2 If the enabled attribute on the AudioTrack object is true, then set the removed enabled
    713             // audio track flag to true.
    714             if (track.enabled())
    715                 removedEnabledAudioTrack = true;
    716 
    717             // 5.3.3 Remove the AudioTrack object from the HTMLMediaElement audioTracks list.
    718             // 5.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
    719             // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement audioTracks list.
    720             if (mediaElement())
    721                 mediaElement()->removeAudioTrack(track);
    722 
    723             // 5.3.5 Remove the AudioTrack object from the SourceBuffer audioTracks list.
    724             // 5.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
    725             // cancelable, and that uses the TrackEvent interface, at the SourceBuffer audioTracks list.
    726             audioTracks.remove(track);
     695    ASSERT(scriptExecutionContext());
     696    if (!scriptExecutionContext()->activeDOMObjectsAreStopped()) {
     697        // 4. Let SourceBuffer audioTracks list equal the AudioTrackList object returned by sourceBuffer.audioTracks.
     698        auto& audioTracks = buffer.audioTracks();
     699
     700        // 5. If the SourceBuffer audioTracks list is not empty, then run the following steps:
     701        if (audioTracks.length()) {
     702            // 5.1 Let HTMLMediaElement audioTracks list equal the AudioTrackList object returned by the audioTracks
     703            // attribute on the HTMLMediaElement.
     704            // 5.2 Let the removed enabled audio track flag equal false.
     705            bool removedEnabledAudioTrack = false;
     706
     707            // 5.3 For each AudioTrack object in the SourceBuffer audioTracks list, run the following steps:
     708            while (audioTracks.length()) {
     709                auto& track = *audioTracks.lastItem();
     710
     711                // 5.3.1 Set the sourceBuffer attribute on the AudioTrack object to null.
     712                track.setSourceBuffer(nullptr);
     713
     714                // 5.3.2 If the enabled attribute on the AudioTrack object is true, then set the removed enabled
     715                // audio track flag to true.
     716                if (track.enabled())
     717                    removedEnabledAudioTrack = true;
     718
     719                // 5.3.3 Remove the AudioTrack object from the HTMLMediaElement audioTracks list.
     720                // 5.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
     721                // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement audioTracks list.
     722                if (mediaElement())
     723                    mediaElement()->removeAudioTrack(track);
     724
     725                // 5.3.5 Remove the AudioTrack object from the SourceBuffer audioTracks list.
     726                // 5.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
     727                // cancelable, and that uses the TrackEvent interface, at the SourceBuffer audioTracks list.
     728                audioTracks.remove(track);
     729            }
     730
     731            // 5.4 If the removed enabled audio track flag equals true, then queue a task to fire a simple event
     732            // named change at the HTMLMediaElement audioTracks list.
     733            if (removedEnabledAudioTrack)
     734                mediaElement()->audioTracks().scheduleChangeEvent();
    727735        }
    728736
    729         // 5.4 If the removed enabled audio track flag equals true, then queue a task to fire a simple event
    730         // named change at the HTMLMediaElement audioTracks list.
    731         if (removedEnabledAudioTrack)
    732             mediaElement()->audioTracks().scheduleChangeEvent();
    733     }
    734 
    735     // 6. Let SourceBuffer videoTracks list equal the VideoTrackList object returned by sourceBuffer.videoTracks.
    736     auto& videoTracks = buffer.videoTracks();
    737 
    738     // 7. If the SourceBuffer videoTracks list is not empty, then run the following steps:
    739     if (videoTracks.length()) {
    740         // 7.1 Let HTMLMediaElement videoTracks list equal the VideoTrackList object returned by the videoTracks
    741         // attribute on the HTMLMediaElement.
    742         // 7.2 Let the removed selected video track flag equal false.
    743         bool removedSelectedVideoTrack = false;
    744 
    745         // 7.3 For each VideoTrack object in the SourceBuffer videoTracks list, run the following steps:
    746         while (videoTracks.length()) {
    747             auto& track = *videoTracks.lastItem();
    748 
    749             // 7.3.1 Set the sourceBuffer attribute on the VideoTrack object to null.
    750             track.setSourceBuffer(nullptr);
    751 
    752             // 7.3.2 If the selected attribute on the VideoTrack object is true, then set the removed selected
    753             // video track flag to true.
    754             if (track.selected())
    755                 removedSelectedVideoTrack = true;
    756 
    757             // 7.3.3 Remove the VideoTrack object from the HTMLMediaElement videoTracks list.
    758             // 7.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
    759             // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement videoTracks list.
    760             if (mediaElement())
    761                 mediaElement()->removeVideoTrack(track);
    762 
    763             // 7.3.5 Remove the VideoTrack object from the SourceBuffer videoTracks list.
    764             // 7.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
    765             // cancelable, and that uses the TrackEvent interface, at the SourceBuffer videoTracks list.
    766             videoTracks.remove(track);
     737        // 6. Let SourceBuffer videoTracks list equal the VideoTrackList object returned by sourceBuffer.videoTracks.
     738        auto& videoTracks = buffer.videoTracks();
     739
     740        // 7. If the SourceBuffer videoTracks list is not empty, then run the following steps:
     741        if (videoTracks.length()) {
     742            // 7.1 Let HTMLMediaElement videoTracks list equal the VideoTrackList object returned by the videoTracks
     743            // attribute on the HTMLMediaElement.
     744            // 7.2 Let the removed selected video track flag equal false.
     745            bool removedSelectedVideoTrack = false;
     746
     747            // 7.3 For each VideoTrack object in the SourceBuffer videoTracks list, run the following steps:
     748            while (videoTracks.length()) {
     749                auto& track = *videoTracks.lastItem();
     750
     751                // 7.3.1 Set the sourceBuffer attribute on the VideoTrack object to null.
     752                track.setSourceBuffer(nullptr);
     753
     754                // 7.3.2 If the selected attribute on the VideoTrack object is true, then set the removed selected
     755                // video track flag to true.
     756                if (track.selected())
     757                    removedSelectedVideoTrack = true;
     758
     759                // 7.3.3 Remove the VideoTrack object from the HTMLMediaElement videoTracks list.
     760                // 7.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
     761                // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement videoTracks list.
     762                if (mediaElement())
     763                    mediaElement()->removeVideoTrack(track);
     764
     765                // 7.3.5 Remove the VideoTrack object from the SourceBuffer videoTracks list.
     766                // 7.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
     767                // cancelable, and that uses the TrackEvent interface, at the SourceBuffer videoTracks list.
     768                videoTracks.remove(track);
     769            }
     770
     771            // 7.4 If the removed selected video track flag equals true, then queue a task to fire a simple event
     772            // named change at the HTMLMediaElement videoTracks list.
     773            if (removedSelectedVideoTrack)
     774                mediaElement()->videoTracks().scheduleChangeEvent();
    767775        }
    768776
    769         // 7.4 If the removed selected video track flag equals true, then queue a task to fire a simple event
    770         // named change at the HTMLMediaElement videoTracks list.
    771         if (removedSelectedVideoTrack)
    772             mediaElement()->videoTracks().scheduleChangeEvent();
    773     }
    774 
    775     // 8. Let SourceBuffer textTracks list equal the TextTrackList object returned by sourceBuffer.textTracks.
    776     auto& textTracks = buffer.textTracks();
    777 
    778     // 9. If the SourceBuffer textTracks list is not empty, then run the following steps:
    779     if (textTracks.length()) {
    780         // 9.1 Let HTMLMediaElement textTracks list equal the TextTrackList object returned by the textTracks
    781         // attribute on the HTMLMediaElement.
    782         // 9.2 Let the removed enabled text track flag equal false.
    783         bool removedEnabledTextTrack = false;
    784 
    785         // 9.3 For each TextTrack object in the SourceBuffer textTracks list, run the following steps:
    786         while (textTracks.length()) {
    787             auto& track = *textTracks.lastItem();
    788 
    789             // 9.3.1 Set the sourceBuffer attribute on the TextTrack object to null.
    790             track.setSourceBuffer(nullptr);
    791 
    792             // 9.3.2 If the mode attribute on the TextTrack object is set to "showing" or "hidden", then
    793             // set the removed enabled text track flag to true.
    794             if (track.mode() == TextTrack::Mode::Showing || track.mode() == TextTrack::Mode::Hidden)
    795                 removedEnabledTextTrack = true;
    796 
    797             // 9.3.3 Remove the TextTrack object from the HTMLMediaElement textTracks list.
    798             // 9.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
    799             // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement textTracks list.
    800             if (mediaElement())
    801                 mediaElement()->removeTextTrack(track);
    802 
    803             // 9.3.5 Remove the TextTrack object from the SourceBuffer textTracks list.
    804             // 9.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
    805             // cancelable, and that uses the TrackEvent interface, at the SourceBuffer textTracks list.
    806             textTracks.remove(track);
     777        // 8. Let SourceBuffer textTracks list equal the TextTrackList object returned by sourceBuffer.textTracks.
     778        auto& textTracks = buffer.textTracks();
     779
     780        // 9. If the SourceBuffer textTracks list is not empty, then run the following steps:
     781        if (textTracks.length()) {
     782            // 9.1 Let HTMLMediaElement textTracks list equal the TextTrackList object returned by the textTracks
     783            // attribute on the HTMLMediaElement.
     784            // 9.2 Let the removed enabled text track flag equal false.
     785            bool removedEnabledTextTrack = false;
     786
     787            // 9.3 For each TextTrack object in the SourceBuffer textTracks list, run the following steps:
     788            while (textTracks.length()) {
     789                auto& track = *textTracks.lastItem();
     790
     791                // 9.3.1 Set the sourceBuffer attribute on the TextTrack object to null.
     792                track.setSourceBuffer(nullptr);
     793
     794                // 9.3.2 If the mode attribute on the TextTrack object is set to "showing" or "hidden", then
     795                // set the removed enabled text track flag to true.
     796                if (track.mode() == TextTrack::Mode::Showing || track.mode() == TextTrack::Mode::Hidden)
     797                    removedEnabledTextTrack = true;
     798
     799                // 9.3.3 Remove the TextTrack object from the HTMLMediaElement textTracks list.
     800                // 9.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
     801                // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement textTracks list.
     802                if (mediaElement())
     803                    mediaElement()->removeTextTrack(track);
     804
     805                // 9.3.5 Remove the TextTrack object from the SourceBuffer textTracks list.
     806                // 9.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
     807                // cancelable, and that uses the TrackEvent interface, at the SourceBuffer textTracks list.
     808                textTracks.remove(track);
     809            }
     810
     811            // 9.4 If the removed enabled text track flag equals true, then queue a task to fire a simple event
     812            // named change at the HTMLMediaElement textTracks list.
     813            if (removedEnabledTextTrack)
     814                mediaElement()->textTracks().scheduleChangeEvent();
    807815        }
    808 
    809         // 9.4 If the removed enabled text track flag equals true, then queue a task to fire a simple event
    810         // named change at the HTMLMediaElement textTracks list.
    811         if (removedEnabledTextTrack)
    812             mediaElement()->textTracks().scheduleChangeEvent();
    813816    }
    814817
     
    931934    return m_private || m_asyncEventQueue.hasPendingEvents()
    932935        || ActiveDOMObject::hasPendingActivity();
     936}
     937
     938void MediaSource::suspend(ReasonForSuspension)
     939{
     940    ASSERT(!m_asyncEventQueue.hasPendingEvents());
     941}
     942
     943void MediaSource::resume()
     944{
     945    ASSERT(!m_asyncEventQueue.hasPendingEvents());
    933946}
    934947
  • trunk/Source/WebCore/Modules/mediasource/MediaSource.h

    r230805 r233496  
    108108    explicit MediaSource(ScriptExecutionContext&);
    109109
     110    void suspend(ReasonForSuspension) final;
     111    void resume() final;
    110112    void stop() final;
    111113    bool canSuspendForDocumentSuspension() const final;
  • trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp

    r230951 r233496  
    459459}
    460460
     461void SourceBuffer::suspend(ReasonForSuspension)
     462{
     463    ASSERT(!hasPendingActivity());
     464}
     465
     466void SourceBuffer::resume()
     467{
     468    ASSERT(!hasPendingActivity());
     469}
     470
    461471void SourceBuffer::stop()
    462472{
     473    m_asyncEventQueue.close();
    463474    m_appendBufferTimer.stop();
    464475    m_removeTimer.stop();
  • trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h

    r230909 r233496  
    124124    void derefEventTarget() final { deref(); }
    125125
     126    void suspend(ReasonForSuspension) final;
     127    void resume() final;
    126128    void stop() final;
    127129    const char* activeDOMObjectName() const final;
  • trunk/Source/WebCore/Modules/mediasource/SourceBufferList.cpp

    r216084 r233496  
    4141
    4242SourceBufferList::SourceBufferList(ScriptExecutionContext* context)
    43     : ContextDestructionObserver(context)
     43    : ActiveDOMObject(context)
    4444    , m_asyncEventQueue(*this)
    4545{
     46    suspendIfNeeded();
    4647}
    4748
     
    9899}
    99100
     101bool SourceBufferList::canSuspendForDocumentSuspension() const
     102{
     103    return !m_asyncEventQueue.hasPendingEvents();
     104}
     105
     106void SourceBufferList::suspend(ReasonForSuspension)
     107{
     108    ASSERT(!m_asyncEventQueue.hasPendingEvents());
     109}
     110
     111void SourceBufferList::resume()
     112{
     113    ASSERT(!m_asyncEventQueue.hasPendingEvents());
     114}
     115
     116void SourceBufferList::stop()
     117{
     118    m_asyncEventQueue.close();
     119}
     120
     121const char* SourceBufferList::activeDOMObjectName() const
     122{
     123    return "SourceBufferList";
     124}
    100125
    101126} // namespace WebCore
  • trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h

    r218803 r233496  
    3333#if ENABLE(MEDIA_SOURCE)
    3434
    35 #include "ContextDestructionObserver.h"
     35#include "ActiveDOMObject.h"
    3636#include "EventTarget.h"
    3737#include "GenericEventQueue.h"
     
    4343class SourceBuffer;
    4444
    45 class SourceBufferList final : public RefCounted<SourceBufferList>, public EventTargetWithInlineData, public ContextDestructionObserver {
     45class SourceBufferList final : public RefCounted<SourceBufferList>, public EventTargetWithInlineData, public ActiveDOMObject {
    4646public:
    4747    static Ref<SourceBufferList> create(ScriptExecutionContext* context)
     
    7878    void derefEventTarget() override { deref(); }
    7979
     80    bool canSuspendForDocumentSuspension() const final;
     81    void suspend(ReasonForSuspension) final;
     82    void resume() final;
     83    void stop() final;
     84    const char* activeDOMObjectName() const final;
     85
    8086    GenericEventQueue m_asyncEventQueue;
    8187
  • trunk/Source/WebCore/Modules/mediasource/SourceBufferList.idl

    r215403 r233496  
    3030 
    3131[
     32    ActiveDOMObject,
    3233    Conditional=MEDIA_SOURCE,
    3334    GenerateIsReachable=Impl,
  • trunk/Source/WebCore/dom/Document.h

    r233163 r233496  
    804804    WEBCORE_EXPORT WindowProxy* windowProxy() const;
    805805
     806    bool hasBrowsingContext() const { return !!frame(); }
     807
    806808    Document& contextDocument() const;
    807809    void setContextDocument(Document& document) { m_contextDocument = makeWeakPtr(document); }
  • trunk/Source/WebCore/dom/GenericEventQueue.cpp

    r225037 r233496  
    2727#include "GenericEventQueue.h"
    2828
     29#include "Document.h"
    2930#include "Event.h"
    3031#include "EventTarget.h"
     32#include "Node.h"
    3133#include "ScriptExecutionContext.h"
    3234#include "Timer.h"
     
    6668    RefPtr<Event> event = m_pendingEvents.takeFirst();
    6769    EventTarget& target = event->target() ? *event->target() : m_owner;
     70    ASSERT_WITH_MESSAGE(!target.scriptExecutionContext()->activeDOMObjectsAreStopped(),
     71        "An attempt to dispatch an event on a stopped target by EventTargetInterface=%d (nodeName=%s target=%p owner=%p)",
     72        m_owner.eventTargetInterface(), m_owner.isNode() ? static_cast<Node&>(m_owner).nodeName().ascii().data() : "", &target, &m_owner);
    6873    target.dispatchEvent(*event);
    6974}
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r233485 r233496  
    13001300    m_currentSourceNode = nullptr;
    13011301
     1302    if (!document().hasBrowsingContext())
     1303        return;
     1304
    13021305    createMediaPlayer();
    13031306
     
    14161419    // put into the background.
    14171420    m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
    1418 
    14191421
    14201422    m_resourceSelectionTaskQueue.enqueueTask([this]  {
     
    28942896{
    28952897    INFO_LOG(LOGIDENTIFIER);
    2896     if (m_havePreparedToPlay)
     2898    if (m_havePreparedToPlay || !document().hasBrowsingContext())
    28972899        return;
    28982900    m_havePreparedToPlay = true;
     
    34863488    if (isSuspended()) {
    34873489        ALWAYS_LOG(LOGIDENTIFIER, "  returning because context is suspended");
     3490        return;
     3491    }
     3492
     3493    if (!document().hasBrowsingContext()) {
     3494        INFO_LOG(LOGIDENTIFIER, "  returning because there is no browsing context");
    34883495        return;
    34893496    }
     
    35773584    if (isSuspended()) {
    35783585        ALWAYS_LOG(LOGIDENTIFIER, "  returning because context is suspended");
     3586        return;
     3587    }
     3588
     3589    if (!document().hasBrowsingContext()) {
     3590        INFO_LOG(LOGIDENTIFIER, "  returning because there is no browsing context");
    35793591        return;
    35803592    }
     
    46404652        URL url = source.getNonEmptyURLAttribute(srcAttr);
    46414653        INFO_LOG(LOGIDENTIFIER, "'src' is ", url);
     4654    }
     4655
     4656    if (!document().hasBrowsingContext()) {
     4657        INFO_LOG(LOGIDENTIFIER, "<source> inserted inside a document without a browsing context is not loaded");
     4658        return;
    46424659    }
    46434660
  • trunk/Source/WebCore/html/track/AudioTrackList.cpp

    r223728 r233496  
    8282}
    8383
     84const char* AudioTrackList::activeDOMObjectName() const
     85{
     86    return "AudioTrackList";
     87}
     88
    8489#endif
  • trunk/Source/WebCore/html/track/AudioTrackList.h

    r208179 r233496  
    5353private:
    5454    AudioTrackList(HTMLMediaElement*, ScriptExecutionContext*);
     55    const char* activeDOMObjectName() const final;
    5556};
    5657
  • trunk/Source/WebCore/html/track/AudioTrackList.idl

    r196621 r233496  
    2525
    2626[
     27    ActiveDOMObject,
    2728    Conditional=VIDEO_TRACK,
    2829    GenerateIsReachable=ImplElementRoot,
  • trunk/Source/WebCore/html/track/TextTrackList.cpp

    r224320 r233496  
    266266}
    267267
     268const char* TextTrackList::activeDOMObjectName() const
     269{
     270    return "TextTrackList";
     271}
     272
    268273#endif
  • trunk/Source/WebCore/html/track/TextTrackList.h

    r208179 r233496  
    6363
    6464    void invalidateTrackIndexesAfterTrack(TextTrack&);
     65    const char* activeDOMObjectName() const final;
    6566
    6667    Vector<RefPtr<TrackBase>> m_addTrackTracks;
  • trunk/Source/WebCore/html/track/TextTrackList.idl

    r196568 r233496  
    2525
    2626[
     27    ActiveDOMObject,
    2728    Conditional=VIDEO_TRACK,
    2829    GenerateIsReachable=ImplElementRoot,
  • trunk/Source/WebCore/html/track/TrackListBase.cpp

    r216084 r233496  
    3535#include "TrackEvent.h"
    3636
    37 using namespace WebCore;
     37namespace WebCore {
    3838
    3939TrackListBase::TrackListBase(HTMLMediaElement* element, ScriptExecutionContext* context)
    40     : ContextDestructionObserver(context)
     40    : ActiveDOMObject(context)
    4141    , m_element(element)
    4242    , m_asyncEventQueue(*this)
    4343{
    44     ASSERT(is<Document>(context));
     44    ASSERT(!context || is<Document>(context));
     45    suspendIfNeeded();
    4546}
    4647
     
    175176}
    176177
     178bool TrackListBase::canSuspendForDocumentSuspension() const
     179{
     180    return !m_asyncEventQueue.hasPendingEvents();
     181}
     182
     183void TrackListBase::suspend(ReasonForSuspension)
     184{
     185    ASSERT(!m_asyncEventQueue.hasPendingEvents());
     186}
     187
     188void TrackListBase::resume()
     189{
     190    ASSERT(!m_asyncEventQueue.hasPendingEvents());
     191}
     192
     193void TrackListBase::stop()
     194{
     195    m_asyncEventQueue.close();
     196}
     197
     198} // namespace WebCore
     199
    177200#endif
  • trunk/Source/WebCore/html/track/TrackListBase.h

    r218748 r233496  
    2828#if ENABLE(VIDEO_TRACK)
    2929
    30 #include "ContextDestructionObserver.h"
     30#include "ActiveDOMObject.h"
    3131#include "EventTarget.h"
    3232#include "GenericEventQueue.h"
     
    4040class TrackBase;
    4141
    42 class TrackListBase : public RefCounted<TrackListBase>, public EventTargetWithInlineData, public ContextDestructionObserver {
     42class TrackListBase : public RefCounted<TrackListBase>, public EventTargetWithInlineData, public ActiveDOMObject {
    4343public:
    4444    virtual ~TrackListBase();
     
    7575    void scheduleTrackEvent(const AtomicString& eventName, Ref<TrackBase>&&);
    7676
     77    bool canSuspendForDocumentSuspension() const final;
     78    void suspend(ReasonForSuspension) final;
     79    void resume() final;
     80    void stop() final;
     81
    7782    // EventTarget
    7883    void refEventTarget() final { ref(); }
  • trunk/Source/WebCore/html/track/VideoTrackList.cpp

    r223728 r233496  
    9595}
    9696
     97const char* VideoTrackList::activeDOMObjectName() const
     98{
     99    return "VideoTrackList";
     100}
     101
    97102#endif
  • trunk/Source/WebCore/html/track/VideoTrackList.h

    r208179 r233496  
    5454private:
    5555    VideoTrackList(HTMLMediaElement*, ScriptExecutionContext*);
     56    const char* activeDOMObjectName() const final;
    5657};
    5758
  • trunk/Source/WebCore/html/track/VideoTrackList.idl

    r196621 r233496  
    2525
    2626[
     27    ActiveDOMObject,
    2728    Conditional=VIDEO_TRACK,
    2829    GenerateIsReachable=ImplElementRoot,
Note: See TracChangeset for help on using the changeset viewer.