Diff
Modified: trunk/LayoutTests/ChangeLog (234373 => 234374)
--- trunk/LayoutTests/ChangeLog 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/LayoutTests/ChangeLog 2018-07-30 18:17:12 UTC (rev 234374)
@@ -1,3 +1,14 @@
+2018-07-30 Chris Dumez <[email protected]>
+
+ Nullptr crash accessing Document in GenericEventQueue::dispatchOneEvent()
+ https://bugs.webkit.org/show_bug.cgi?id=187284
+
+ Unreviewed, roll r233496 and r233571 now that all known issues have been fixed via
+ dependency bugs.
+
+ * media/track/video-track-addition-and-frame-removal-expected.txt: Added.
+ * media/track/video-track-addition-and-frame-removal.html: Added.
+
2018-07-30 Per Arne Vollan <[email protected]>
[Win] Layout test http/tests/security/canvas-remote-read-remote-video-hls.html is failing.
Added: trunk/LayoutTests/media/track/video-track-addition-and-frame-removal-expected.txt (0 => 234374)
--- trunk/LayoutTests/media/track/video-track-addition-and-frame-removal-expected.txt (rev 0)
+++ trunk/LayoutTests/media/track/video-track-addition-and-frame-removal-expected.txt 2018-07-30 18:17:12 UTC (rev 234374)
@@ -0,0 +1,4 @@
+This tests removing a frame immediately after inserting a new track element.
+WebKit should not hit any assertions.
+
+
Added: trunk/LayoutTests/media/track/video-track-addition-and-frame-removal.html (0 => 234374)
--- trunk/LayoutTests/media/track/video-track-addition-and-frame-removal.html (rev 0)
+++ trunk/LayoutTests/media/track/video-track-addition-and-frame-removal.html 2018-07-30 18:17:12 UTC (rev 234374)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This tests removing a frame immediately after inserting a new track element.<br>
+WebKit should not hit any assertions.</p>
+<script src=""
+<script>
+
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+function startTest()
+{
+ const doc = frame.contentDocument;
+ const trackElement = doc.createElement('track');
+ doc.querySelector('video').appendChild(trackElement);
+
+ frame.remove();
+ gc();
+ setTimeout(() => {
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }, 100);
+}
+
+</script>
+<iframe id="frame" src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (234373 => 234374)
--- trunk/Source/WebCore/ChangeLog 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/ChangeLog 2018-07-30 18:17:12 UTC (rev 234374)
@@ -1,5 +1,70 @@
2018-07-30 Chris Dumez <[email protected]>
+ Nullptr crash accessing Document in GenericEventQueue::dispatchOneEvent()
+ https://bugs.webkit.org/show_bug.cgi?id=187284
+
+ Unreviewed, roll r233496 and r233571 now that all known issues have been fixed via
+ dependency bugs.
+
+ Test: media/track/video-track-addition-and-frame-removal.html
+
+ * Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp:
+ (WebCore::WebKitMediaKeySession::suspend):
+ (WebCore::WebKitMediaKeySession::resume):
+ (WebCore::WebKitMediaKeySession::stop):
+ * Modules/encryptedmedia/legacy/WebKitMediaKeySession.h:
+ * Modules/mediasource/MediaSource.cpp:
+ (WebCore::MediaSource::removeSourceBuffer):
+ (WebCore::MediaSource::suspend):
+ (WebCore::MediaSource::resume):
+ * Modules/mediasource/MediaSource.h:
+ * Modules/mediasource/SourceBuffer.cpp:
+ (WebCore::SourceBuffer::suspend):
+ (WebCore::SourceBuffer::resume):
+ (WebCore::SourceBuffer::stop):
+ * Modules/mediasource/SourceBuffer.h:
+ * Modules/mediasource/SourceBufferList.cpp:
+ (WebCore::SourceBufferList::SourceBufferList):
+ (WebCore::SourceBufferList::canSuspendForDocumentSuspension const):
+ (WebCore::SourceBufferList::suspend):
+ (WebCore::SourceBufferList::resume):
+ (WebCore::SourceBufferList::stop):
+ (WebCore::SourceBufferList::activeDOMObjectName const):
+ * Modules/mediasource/SourceBufferList.h:
+ * Modules/mediasource/SourceBufferList.idl:
+ * dom/Document.h:
+ (WebCore::Document::hasBrowsingContext const):
+ * dom/GenericEventQueue.cpp:
+ (WebCore::GenericEventQueue::dispatchOneEvent):
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::prepareForLoad):
+ (WebCore::HTMLMediaElement::selectMediaResource):
+ (WebCore::HTMLMediaElement::prepareToPlay):
+ (WebCore::HTMLMediaElement::playInternal):
+ (WebCore::HTMLMediaElement::pauseInternal):
+ (WebCore::HTMLMediaElement::sourceWasAdded):
+ * html/track/AudioTrackList.cpp:
+ (AudioTrackList::activeDOMObjectName const):
+ * html/track/AudioTrackList.h:
+ * html/track/AudioTrackList.idl:
+ * html/track/TextTrackList.cpp:
+ (TextTrackList::activeDOMObjectName const):
+ * html/track/TextTrackList.h:
+ * html/track/TextTrackList.idl:
+ * html/track/TrackListBase.cpp:
+ (WebCore::TrackListBase::TrackListBase):
+ (WebCore::TrackListBase::canSuspendForDocumentSuspension const):
+ (WebCore::TrackListBase::suspend):
+ (WebCore::TrackListBase::resume):
+ (WebCore::TrackListBase::stop):
+ * html/track/TrackListBase.h:
+ * html/track/VideoTrackList.cpp:
+ (VideoTrackList::activeDOMObjectName const):
+ * html/track/VideoTrackList.h:
+ * html/track/VideoTrackList.idl:
+
+2018-07-30 Chris Dumez <[email protected]>
+
Unreviewed internal build fix after r234347.
* html/StepRange.cpp:
Modified: trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp (234373 => 234374)
--- trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -239,8 +239,19 @@
return (m_keys && m_session) || m_asyncEventQueue.hasPendingEvents();
}
+void WebKitMediaKeySession::suspend(ReasonForSuspension)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void WebKitMediaKeySession::resume()
+{
+ ASSERT_NOT_REACHED();
+}
+
void WebKitMediaKeySession::stop()
{
+ m_asyncEventQueue.close();
close();
}
Modified: trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h (234373 => 234374)
--- trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -76,6 +76,8 @@
void refEventTarget() final { ref(); }
void derefEventTarget() final { deref(); }
+ void suspend(ReasonForSuspension) final;
+ void resume() final;
void stop() final;
bool canSuspendForDocumentSuspension() const final;
const char* activeDOMObjectName() const final;
Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -692,124 +692,127 @@
// 3. If the sourceBuffer.updating attribute equals true, then run the following steps: ...
buffer.abortIfUpdating();
- // 4. Let SourceBuffer audioTracks list equal the AudioTrackList object returned by sourceBuffer.audioTracks.
- auto& audioTracks = buffer.audioTracks();
+ ASSERT(scriptExecutionContext());
+ if (!scriptExecutionContext()->activeDOMObjectsAreStopped()) {
+ // 4. Let SourceBuffer audioTracks list equal the AudioTrackList object returned by sourceBuffer.audioTracks.
+ auto& audioTracks = buffer.audioTracks();
- // 5. If the SourceBuffer audioTracks list is not empty, then run the following steps:
- if (audioTracks.length()) {
- // 5.1 Let HTMLMediaElement audioTracks list equal the AudioTrackList object returned by the audioTracks
- // attribute on the HTMLMediaElement.
- // 5.2 Let the removed enabled audio track flag equal false.
- bool removedEnabledAudioTrack = false;
+ // 5. If the SourceBuffer audioTracks list is not empty, then run the following steps:
+ if (audioTracks.length()) {
+ // 5.1 Let HTMLMediaElement audioTracks list equal the AudioTrackList object returned by the audioTracks
+ // attribute on the HTMLMediaElement.
+ // 5.2 Let the removed enabled audio track flag equal false.
+ bool removedEnabledAudioTrack = false;
- // 5.3 For each AudioTrack object in the SourceBuffer audioTracks list, run the following steps:
- while (audioTracks.length()) {
- auto& track = *audioTracks.lastItem();
+ // 5.3 For each AudioTrack object in the SourceBuffer audioTracks list, run the following steps:
+ while (audioTracks.length()) {
+ auto& track = *audioTracks.lastItem();
- // 5.3.1 Set the sourceBuffer attribute on the AudioTrack object to null.
- track.setSourceBuffer(nullptr);
+ // 5.3.1 Set the sourceBuffer attribute on the AudioTrack object to null.
+ track.setSourceBuffer(nullptr);
- // 5.3.2 If the enabled attribute on the AudioTrack object is true, then set the removed enabled
- // audio track flag to true.
- if (track.enabled())
- removedEnabledAudioTrack = true;
+ // 5.3.2 If the enabled attribute on the AudioTrack object is true, then set the removed enabled
+ // audio track flag to true.
+ if (track.enabled())
+ removedEnabledAudioTrack = true;
- // 5.3.3 Remove the AudioTrack object from the HTMLMediaElement audioTracks list.
- // 5.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
- // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement audioTracks list.
- if (mediaElement())
- mediaElement()->removeAudioTrack(track);
+ // 5.3.3 Remove the AudioTrack object from the HTMLMediaElement audioTracks list.
+ // 5.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
+ // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement audioTracks list.
+ if (mediaElement())
+ mediaElement()->removeAudioTrack(track);
- // 5.3.5 Remove the AudioTrack object from the SourceBuffer audioTracks list.
- // 5.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
- // cancelable, and that uses the TrackEvent interface, at the SourceBuffer audioTracks list.
- audioTracks.remove(track);
+ // 5.3.5 Remove the AudioTrack object from the SourceBuffer audioTracks list.
+ // 5.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
+ // cancelable, and that uses the TrackEvent interface, at the SourceBuffer audioTracks list.
+ audioTracks.remove(track);
+ }
+
+ // 5.4 If the removed enabled audio track flag equals true, then queue a task to fire a simple event
+ // named change at the HTMLMediaElement audioTracks list.
+ if (removedEnabledAudioTrack)
+ mediaElement()->ensureAudioTracks().scheduleChangeEvent();
}
- // 5.4 If the removed enabled audio track flag equals true, then queue a task to fire a simple event
- // named change at the HTMLMediaElement audioTracks list.
- if (removedEnabledAudioTrack)
- mediaElement()->ensureAudioTracks().scheduleChangeEvent();
- }
+ // 6. Let SourceBuffer videoTracks list equal the VideoTrackList object returned by sourceBuffer.videoTracks.
+ auto& videoTracks = buffer.videoTracks();
- // 6. Let SourceBuffer videoTracks list equal the VideoTrackList object returned by sourceBuffer.videoTracks.
- auto& videoTracks = buffer.videoTracks();
+ // 7. If the SourceBuffer videoTracks list is not empty, then run the following steps:
+ if (videoTracks.length()) {
+ // 7.1 Let HTMLMediaElement videoTracks list equal the VideoTrackList object returned by the videoTracks
+ // attribute on the HTMLMediaElement.
+ // 7.2 Let the removed selected video track flag equal false.
+ bool removedSelectedVideoTrack = false;
- // 7. If the SourceBuffer videoTracks list is not empty, then run the following steps:
- if (videoTracks.length()) {
- // 7.1 Let HTMLMediaElement videoTracks list equal the VideoTrackList object returned by the videoTracks
- // attribute on the HTMLMediaElement.
- // 7.2 Let the removed selected video track flag equal false.
- bool removedSelectedVideoTrack = false;
+ // 7.3 For each VideoTrack object in the SourceBuffer videoTracks list, run the following steps:
+ while (videoTracks.length()) {
+ auto& track = *videoTracks.lastItem();
- // 7.3 For each VideoTrack object in the SourceBuffer videoTracks list, run the following steps:
- while (videoTracks.length()) {
- auto& track = *videoTracks.lastItem();
+ // 7.3.1 Set the sourceBuffer attribute on the VideoTrack object to null.
+ track.setSourceBuffer(nullptr);
- // 7.3.1 Set the sourceBuffer attribute on the VideoTrack object to null.
- track.setSourceBuffer(nullptr);
+ // 7.3.2 If the selected attribute on the VideoTrack object is true, then set the removed selected
+ // video track flag to true.
+ if (track.selected())
+ removedSelectedVideoTrack = true;
- // 7.3.2 If the selected attribute on the VideoTrack object is true, then set the removed selected
- // video track flag to true.
- if (track.selected())
- removedSelectedVideoTrack = true;
+ // 7.3.3 Remove the VideoTrack object from the HTMLMediaElement videoTracks list.
+ // 7.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
+ // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement videoTracks list.
+ if (mediaElement())
+ mediaElement()->removeVideoTrack(track);
- // 7.3.3 Remove the VideoTrack object from the HTMLMediaElement videoTracks list.
- // 7.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
- // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement videoTracks list.
- if (mediaElement())
- mediaElement()->removeVideoTrack(track);
+ // 7.3.5 Remove the VideoTrack object from the SourceBuffer videoTracks list.
+ // 7.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
+ // cancelable, and that uses the TrackEvent interface, at the SourceBuffer videoTracks list.
+ videoTracks.remove(track);
+ }
- // 7.3.5 Remove the VideoTrack object from the SourceBuffer videoTracks list.
- // 7.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
- // cancelable, and that uses the TrackEvent interface, at the SourceBuffer videoTracks list.
- videoTracks.remove(track);
+ // 7.4 If the removed selected video track flag equals true, then queue a task to fire a simple event
+ // named change at the HTMLMediaElement videoTracks list.
+ if (removedSelectedVideoTrack)
+ mediaElement()->ensureVideoTracks().scheduleChangeEvent();
}
- // 7.4 If the removed selected video track flag equals true, then queue a task to fire a simple event
- // named change at the HTMLMediaElement videoTracks list.
- if (removedSelectedVideoTrack)
- mediaElement()->ensureVideoTracks().scheduleChangeEvent();
- }
+ // 8. Let SourceBuffer textTracks list equal the TextTrackList object returned by sourceBuffer.textTracks.
+ auto& textTracks = buffer.textTracks();
- // 8. Let SourceBuffer textTracks list equal the TextTrackList object returned by sourceBuffer.textTracks.
- auto& textTracks = buffer.textTracks();
+ // 9. If the SourceBuffer textTracks list is not empty, then run the following steps:
+ if (textTracks.length()) {
+ // 9.1 Let HTMLMediaElement textTracks list equal the TextTrackList object returned by the textTracks
+ // attribute on the HTMLMediaElement.
+ // 9.2 Let the removed enabled text track flag equal false.
+ bool removedEnabledTextTrack = false;
- // 9. If the SourceBuffer textTracks list is not empty, then run the following steps:
- if (textTracks.length()) {
- // 9.1 Let HTMLMediaElement textTracks list equal the TextTrackList object returned by the textTracks
- // attribute on the HTMLMediaElement.
- // 9.2 Let the removed enabled text track flag equal false.
- bool removedEnabledTextTrack = false;
+ // 9.3 For each TextTrack object in the SourceBuffer textTracks list, run the following steps:
+ while (textTracks.length()) {
+ auto& track = *textTracks.lastItem();
- // 9.3 For each TextTrack object in the SourceBuffer textTracks list, run the following steps:
- while (textTracks.length()) {
- auto& track = *textTracks.lastItem();
+ // 9.3.1 Set the sourceBuffer attribute on the TextTrack object to null.
+ track.setSourceBuffer(nullptr);
- // 9.3.1 Set the sourceBuffer attribute on the TextTrack object to null.
- track.setSourceBuffer(nullptr);
+ // 9.3.2 If the mode attribute on the TextTrack object is set to "showing" or "hidden", then
+ // set the removed enabled text track flag to true.
+ if (track.mode() == TextTrack::Mode::Showing || track.mode() == TextTrack::Mode::Hidden)
+ removedEnabledTextTrack = true;
- // 9.3.2 If the mode attribute on the TextTrack object is set to "showing" or "hidden", then
- // set the removed enabled text track flag to true.
- if (track.mode() == TextTrack::Mode::Showing || track.mode() == TextTrack::Mode::Hidden)
- removedEnabledTextTrack = true;
+ // 9.3.3 Remove the TextTrack object from the HTMLMediaElement textTracks list.
+ // 9.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
+ // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement textTracks list.
+ if (mediaElement())
+ mediaElement()->removeTextTrack(track);
- // 9.3.3 Remove the TextTrack object from the HTMLMediaElement textTracks list.
- // 9.3.4 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
- // cancelable, and that uses the TrackEvent interface, at the HTMLMediaElement textTracks list.
- if (mediaElement())
- mediaElement()->removeTextTrack(track);
+ // 9.3.5 Remove the TextTrack object from the SourceBuffer textTracks list.
+ // 9.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
+ // cancelable, and that uses the TrackEvent interface, at the SourceBuffer textTracks list.
+ textTracks.remove(track);
+ }
- // 9.3.5 Remove the TextTrack object from the SourceBuffer textTracks list.
- // 9.3.6 Queue a task to fire a trusted event named removetrack, that does not bubble and is not
- // cancelable, and that uses the TrackEvent interface, at the SourceBuffer textTracks list.
- textTracks.remove(track);
+ // 9.4 If the removed enabled text track flag equals true, then queue a task to fire a simple event
+ // named change at the HTMLMediaElement textTracks list.
+ if (removedEnabledTextTrack)
+ mediaElement()->ensureTextTracks().scheduleChangeEvent();
}
-
- // 9.4 If the removed enabled text track flag equals true, then queue a task to fire a simple event
- // named change at the HTMLMediaElement textTracks list.
- if (removedEnabledTextTrack)
- mediaElement()->ensureTextTracks().scheduleChangeEvent();
}
// 10. If sourceBuffer is in activeSourceBuffers, then remove sourceBuffer from activeSourceBuffers ...
@@ -932,6 +935,25 @@
|| ActiveDOMObject::hasPendingActivity();
}
+void MediaSource::suspend(ReasonForSuspension reason)
+{
+ switch (reason) {
+ case ReasonForSuspension::PageCache:
+ case ReasonForSuspension::PageWillBeSuspended:
+ m_asyncEventQueue.suspend();
+ break;
+ case ReasonForSuspension::_javascript_DebuggerPaused:
+ case ReasonForSuspension::WillDeferLoading:
+ // Do nothing, we don't pause media playback in these cases.
+ break;
+ }
+}
+
+void MediaSource::resume()
+{
+ m_asyncEventQueue.resume();
+}
+
void MediaSource::stop()
{
m_asyncEventQueue.close();
Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.h (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/MediaSource.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -107,6 +107,8 @@
private:
explicit MediaSource(ScriptExecutionContext&);
+ void suspend(ReasonForSuspension) final;
+ void resume() final;
void stop() final;
bool canSuspendForDocumentSuspension() const final;
const char* activeDOMObjectName() const final;
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -458,8 +458,28 @@
return m_source || m_asyncEventQueue.hasPendingEvents();
}
+void SourceBuffer::suspend(ReasonForSuspension reason)
+{
+ switch (reason) {
+ case ReasonForSuspension::PageCache:
+ case ReasonForSuspension::PageWillBeSuspended:
+ m_asyncEventQueue.suspend();
+ break;
+ case ReasonForSuspension::_javascript_DebuggerPaused:
+ case ReasonForSuspension::WillDeferLoading:
+ // Do nothing, we don't pause media playback in these cases.
+ break;
+ }
+}
+
+void SourceBuffer::resume()
+{
+ m_asyncEventQueue.resume();
+}
+
void SourceBuffer::stop()
{
+ m_asyncEventQueue.close();
m_appendBufferTimer.stop();
m_removeTimer.stop();
}
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -123,6 +123,8 @@
void refEventTarget() final { ref(); }
void derefEventTarget() final { deref(); }
+ void suspend(ReasonForSuspension) final;
+ void resume() final;
void stop() final;
const char* activeDOMObjectName() const final;
bool canSuspendForDocumentSuspension() const final;
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBufferList.cpp (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/SourceBufferList.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBufferList.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -40,9 +40,10 @@
namespace WebCore {
SourceBufferList::SourceBufferList(ScriptExecutionContext* context)
- : ContextDestructionObserver(context)
+ : ActiveDOMObject(context)
, m_asyncEventQueue(*this)
{
+ suspendIfNeeded();
}
SourceBufferList::~SourceBufferList()
@@ -97,7 +98,40 @@
m_asyncEventQueue.enqueueEvent(WTFMove(event));
}
+bool SourceBufferList::canSuspendForDocumentSuspension() const
+{
+ return !m_asyncEventQueue.hasPendingEvents();
+}
+void SourceBufferList::suspend(ReasonForSuspension reason)
+{
+ switch (reason) {
+ case ReasonForSuspension::PageCache:
+ case ReasonForSuspension::PageWillBeSuspended:
+ m_asyncEventQueue.suspend();
+ break;
+ case ReasonForSuspension::_javascript_DebuggerPaused:
+ case ReasonForSuspension::WillDeferLoading:
+ // Do nothing, we don't pause media playback in these cases.
+ break;
+ }
+}
+
+void SourceBufferList::resume()
+{
+ m_asyncEventQueue.resume();
+}
+
+void SourceBufferList::stop()
+{
+ m_asyncEventQueue.close();
+}
+
+const char* SourceBufferList::activeDOMObjectName() const
+{
+ return "SourceBufferList";
+}
+
} // namespace WebCore
#endif
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -32,7 +32,7 @@
#if ENABLE(MEDIA_SOURCE)
-#include "ContextDestructionObserver.h"
+#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "GenericEventQueue.h"
#include <wtf/RefCounted.h>
@@ -42,7 +42,7 @@
class SourceBuffer;
-class SourceBufferList final : public RefCounted<SourceBufferList>, public EventTargetWithInlineData, public ContextDestructionObserver {
+class SourceBufferList final : public RefCounted<SourceBufferList>, public EventTargetWithInlineData, public ActiveDOMObject {
public:
static Ref<SourceBufferList> create(ScriptExecutionContext* context)
{
@@ -77,6 +77,12 @@
void refEventTarget() override { ref(); }
void derefEventTarget() override { deref(); }
+ bool canSuspendForDocumentSuspension() const final;
+ void suspend(ReasonForSuspension) final;
+ void resume() final;
+ void stop() final;
+ const char* activeDOMObjectName() const final;
+
GenericEventQueue m_asyncEventQueue;
Vector<RefPtr<SourceBuffer>> m_list;
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBufferList.idl (234373 => 234374)
--- trunk/Source/WebCore/Modules/mediasource/SourceBufferList.idl 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBufferList.idl 2018-07-30 18:17:12 UTC (rev 234374)
@@ -29,6 +29,7 @@
*/
[
+ ActiveDOMObject,
Conditional=MEDIA_SOURCE,
GenerateIsReachable=Impl,
] interface SourceBufferList : EventTarget {
Modified: trunk/Source/WebCore/dom/Document.h (234373 => 234374)
--- trunk/Source/WebCore/dom/Document.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/dom/Document.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -813,6 +813,8 @@
// In DOM Level 2, the Document's DOMWindow is called the defaultView.
WEBCORE_EXPORT WindowProxy* windowProxy() const;
+ bool hasBrowsingContext() const { return !!frame(); }
+
Document& contextDocument() const;
void setContextDocument(Document& document) { m_contextDocument = makeWeakPtr(document); }
Modified: trunk/Source/WebCore/dom/GenericEventQueue.cpp (234373 => 234374)
--- trunk/Source/WebCore/dom/GenericEventQueue.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/dom/GenericEventQueue.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -26,8 +26,10 @@
#include "config.h"
#include "GenericEventQueue.h"
+#include "Document.h"
#include "Event.h"
#include "EventTarget.h"
+#include "Node.h"
#include "ScriptExecutionContext.h"
#include "Timer.h"
#include <wtf/MainThread.h>
@@ -65,6 +67,9 @@
Ref<EventTarget> protect(m_owner);
RefPtr<Event> event = m_pendingEvents.takeFirst();
EventTarget& target = event->target() ? *event->target() : m_owner;
+ ASSERT_WITH_MESSAGE(!target.scriptExecutionContext()->activeDOMObjectsAreStopped(),
+ "An attempt to dispatch an event on a stopped target by EventTargetInterface=%d (nodeName=%s target=%p owner=%p)",
+ m_owner.eventTargetInterface(), m_owner.isNode() ? static_cast<Node&>(m_owner).nodeName().ascii().data() : "", &target, &m_owner);
target.dispatchEvent(*event);
}
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (234373 => 234374)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -1299,6 +1299,9 @@
m_loadState = WaitingForSource;
m_currentSourceNode = nullptr;
+ if (!document().hasBrowsingContext())
+ return;
+
createMediaPlayer();
// 2 - Let pending tasks be a list of all tasks from the media element's media element event task source in one of the task queues.
@@ -1416,7 +1419,6 @@
// put into the background.
m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
-
m_resourceSelectionTaskQueue.enqueueTask([this] {
// 5. If the media element’s blocked-on-parser flag is false, then populate the list of pending text tracks.
#if ENABLE(VIDEO_TRACK)
@@ -2893,7 +2895,7 @@
void HTMLMediaElement::prepareToPlay()
{
INFO_LOG(LOGIDENTIFIER);
- if (m_havePreparedToPlay)
+ if (m_havePreparedToPlay || !document().hasBrowsingContext())
return;
m_havePreparedToPlay = true;
if (m_player)
@@ -3488,6 +3490,11 @@
return;
}
+ if (!document().hasBrowsingContext()) {
+ INFO_LOG(LOGIDENTIFIER, " returning because there is no browsing context");
+ return;
+ }
+
if (!m_mediaSession->clientWillBeginPlayback()) {
ALWAYS_LOG(LOGIDENTIFIER, " returning because of interruption");
return;
@@ -3579,6 +3586,11 @@
return;
}
+ if (!document().hasBrowsingContext()) {
+ INFO_LOG(LOGIDENTIFIER, " returning because there is no browsing context");
+ return;
+ }
+
if (!m_mediaSession->clientWillPausePlayback()) {
ALWAYS_LOG(LOGIDENTIFIER, " returning because of interruption");
return;
@@ -4641,6 +4653,11 @@
INFO_LOG(LOGIDENTIFIER, "'src' is ", url);
}
+ if (!document().hasBrowsingContext()) {
+ INFO_LOG(LOGIDENTIFIER, "<source> inserted inside a document without a browsing context is not loaded");
+ return;
+ }
+
// We should only consider a <source> element when there is not src attribute at all.
if (hasAttributeWithoutSynchronization(srcAttr))
return;
Modified: trunk/Source/WebCore/html/track/AudioTrackList.cpp (234373 => 234374)
--- trunk/Source/WebCore/html/track/AudioTrackList.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/AudioTrackList.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -81,4 +81,9 @@
return AudioTrackListEventTargetInterfaceType;
}
+const char* AudioTrackList::activeDOMObjectName() const
+{
+ return "AudioTrackList";
+}
+
#endif
Modified: trunk/Source/WebCore/html/track/AudioTrackList.h (234373 => 234374)
--- trunk/Source/WebCore/html/track/AudioTrackList.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/AudioTrackList.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -52,6 +52,7 @@
private:
AudioTrackList(HTMLMediaElement*, ScriptExecutionContext*);
+ const char* activeDOMObjectName() const final;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/track/AudioTrackList.idl (234373 => 234374)
--- trunk/Source/WebCore/html/track/AudioTrackList.idl 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/AudioTrackList.idl 2018-07-30 18:17:12 UTC (rev 234374)
@@ -24,6 +24,7 @@
*/
[
+ ActiveDOMObject,
Conditional=VIDEO_TRACK,
GenerateIsReachable=ImplElementRoot,
JSCustomMarkFunction,
Modified: trunk/Source/WebCore/html/track/TextTrackList.cpp (234373 => 234374)
--- trunk/Source/WebCore/html/track/TextTrackList.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/TextTrackList.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -265,4 +265,9 @@
return TextTrackListEventTargetInterfaceType;
}
+const char* TextTrackList::activeDOMObjectName() const
+{
+ return "TextTrackList";
+}
+
#endif
Modified: trunk/Source/WebCore/html/track/TextTrackList.h (234373 => 234374)
--- trunk/Source/WebCore/html/track/TextTrackList.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/TextTrackList.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -62,6 +62,7 @@
TextTrackList(HTMLMediaElement*, ScriptExecutionContext*);
void invalidateTrackIndexesAfterTrack(TextTrack&);
+ const char* activeDOMObjectName() const final;
Vector<RefPtr<TrackBase>> m_addTrackTracks;
Vector<RefPtr<TrackBase>> m_elementTracks;
Modified: trunk/Source/WebCore/html/track/TextTrackList.idl (234373 => 234374)
--- trunk/Source/WebCore/html/track/TextTrackList.idl 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/TextTrackList.idl 2018-07-30 18:17:12 UTC (rev 234374)
@@ -24,6 +24,7 @@
*/
[
+ ActiveDOMObject,
Conditional=VIDEO_TRACK,
GenerateIsReachable=ImplElementRoot,
JSCustomMarkFunction,
Modified: trunk/Source/WebCore/html/track/TrackListBase.cpp (234373 => 234374)
--- trunk/Source/WebCore/html/track/TrackListBase.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/TrackListBase.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -34,14 +34,15 @@
#include "ScriptExecutionContext.h"
#include "TrackEvent.h"
-using namespace WebCore;
+namespace WebCore {
TrackListBase::TrackListBase(HTMLMediaElement* element, ScriptExecutionContext* context)
- : ContextDestructionObserver(context)
+ : ActiveDOMObject(context)
, m_element(element)
, m_asyncEventQueue(*this)
{
- ASSERT(is<Document>(context));
+ ASSERT(!context || is<Document>(context));
+ suspendIfNeeded();
}
TrackListBase::~TrackListBase()
@@ -174,4 +175,35 @@
return false;
}
+bool TrackListBase::canSuspendForDocumentSuspension() const
+{
+ return !m_asyncEventQueue.hasPendingEvents();
+}
+
+void TrackListBase::suspend(ReasonForSuspension reason)
+{
+ switch (reason) {
+ case ReasonForSuspension::PageCache:
+ case ReasonForSuspension::PageWillBeSuspended:
+ m_asyncEventQueue.suspend();
+ break;
+ case ReasonForSuspension::_javascript_DebuggerPaused:
+ case ReasonForSuspension::WillDeferLoading:
+ // Do nothing, we don't pause media playback in these cases.
+ break;
+ }
+}
+
+void TrackListBase::resume()
+{
+ m_asyncEventQueue.resume();
+}
+
+void TrackListBase::stop()
+{
+ m_asyncEventQueue.close();
+}
+
+} // namespace WebCore
+
#endif
Modified: trunk/Source/WebCore/html/track/TrackListBase.h (234373 => 234374)
--- trunk/Source/WebCore/html/track/TrackListBase.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/TrackListBase.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -27,7 +27,7 @@
#if ENABLE(VIDEO_TRACK)
-#include "ContextDestructionObserver.h"
+#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "GenericEventQueue.h"
#include <wtf/RefCounted.h>
@@ -39,7 +39,7 @@
class Element;
class TrackBase;
-class TrackListBase : public RefCounted<TrackListBase>, public EventTargetWithInlineData, public ContextDestructionObserver {
+class TrackListBase : public RefCounted<TrackListBase>, public EventTargetWithInlineData, public ActiveDOMObject {
public:
virtual ~TrackListBase();
@@ -74,6 +74,11 @@
private:
void scheduleTrackEvent(const AtomicString& eventName, Ref<TrackBase>&&);
+ bool canSuspendForDocumentSuspension() const final;
+ void suspend(ReasonForSuspension) final;
+ void resume() final;
+ void stop() final;
+
// EventTarget
void refEventTarget() final { ref(); }
void derefEventTarget() final { deref(); }
Modified: trunk/Source/WebCore/html/track/VideoTrackList.cpp (234373 => 234374)
--- trunk/Source/WebCore/html/track/VideoTrackList.cpp 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/VideoTrackList.cpp 2018-07-30 18:17:12 UTC (rev 234374)
@@ -94,4 +94,9 @@
return VideoTrackListEventTargetInterfaceType;
}
+const char* VideoTrackList::activeDOMObjectName() const
+{
+ return "VideoTrackList";
+}
+
#endif
Modified: trunk/Source/WebCore/html/track/VideoTrackList.h (234373 => 234374)
--- trunk/Source/WebCore/html/track/VideoTrackList.h 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/VideoTrackList.h 2018-07-30 18:17:12 UTC (rev 234374)
@@ -53,6 +53,7 @@
private:
VideoTrackList(HTMLMediaElement*, ScriptExecutionContext*);
+ const char* activeDOMObjectName() const final;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/track/VideoTrackList.idl (234373 => 234374)
--- trunk/Source/WebCore/html/track/VideoTrackList.idl 2018-07-30 17:16:26 UTC (rev 234373)
+++ trunk/Source/WebCore/html/track/VideoTrackList.idl 2018-07-30 18:17:12 UTC (rev 234374)
@@ -24,6 +24,7 @@
*/
[
+ ActiveDOMObject,
Conditional=VIDEO_TRACK,
GenerateIsReachable=ImplElementRoot,
JSCustomMarkFunction,