Diff
Modified: trunk/Source/WebCore/ChangeLog (278391 => 278392)
--- trunk/Source/WebCore/ChangeLog 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/ChangeLog 2021-06-03 01:54:35 UTC (rev 278392)
@@ -1,3 +1,63 @@
+2021-06-02 Chris Dumez <cdu...@apple.com>
+
+ Port media code to the HTML event loop
+ https://bugs.webkit.org/show_bug.cgi?id=226543
+
+ Reviewed by Ryosuke Niwa.
+
+ Port media code to the HTML event loop so that event processing order is consistent
+ with non-media related events. To avoid having a very large patch, I made the following
+ changes:
+ - Update MainThreadGenericEventQueue to be based on the HTML event loop instead of a
+ global Timer.
+ - Introduce a EventLoopDeferrableTask which has the same API as DeferrableTask<Timer> but
+ uses the HTML event loop instead of a global Timer. Port media code to use
+ EventLoopDeferrableTask instead of DeferrableTask.
+ - Introduce an EventLoopTaskQueue which has the same API as GenericTaskQueue<Timer>
+ but uses the HTML event loop instead of a global Timer. Port media code to use
+ EventLoopTaskQueue instead of GenericTaskQueue<Timer>.
+
+ This effectively ports our entire media code to the HTML event loop. It allows new
+ media code to use the HTML event loop *directly* without fear of ordering issues. It also
+ allows us to refactor existing media code to use the HTML event loop *directly* when possible,
+ in an incremental fashion, without causing ordering issues.
+
+ * Headers.cmake:
+ * Modules/remoteplayback/RemotePlayback.cpp:
+ (WebCore::RemotePlayback::RemotePlayback):
+ * Modules/remoteplayback/RemotePlayback.h:
+ * animation/DocumentTimelinesController.cpp:
+ (WebCore::DocumentTimelinesController::DocumentTimelinesController):
+ * animation/DocumentTimelinesController.h:
+ * dom/FullscreenManager.cpp:
+ * dom/FullscreenManager.h:
+ * dom/GenericEventQueue.cpp:
+ (WebCore::MainThreadGenericEventQueue::MainThreadGenericEventQueue):
+ (WebCore::MainThreadGenericEventQueue::enqueueEvent):
+ (WebCore::MainThreadGenericEventQueue::close):
+ (WebCore::MainThreadGenericEventQueue::cancelAllEvents):
+ (WebCore::MainThreadGenericEventQueue::hasPendingEventsOfType const):
+ * dom/GenericEventQueue.h:
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::HTMLMediaElement):
+ * html/HTMLMediaElement.h:
+ * html/shadow/MediaControlTextTrackContainerElement.cpp:
+ (WebCore::MediaControlTextTrackContainerElement::MediaControlTextTrackContainerElement):
+ * html/shadow/MediaControlTextTrackContainerElement.h:
+ * platform/DeferrableTask.h:
+ (WebCore::DeferrableTaskBase::close):
+ (WebCore::DeferrableTaskBase::cancelTask):
+ (WebCore::DeferrableTaskBase::hasPendingTask const):
+ (WebCore::DeferrableTaskBase::isClosed const):
+ (WebCore::DeferrableTaskBase::setHasPendingTask):
+ * platform/GenericTaskQueue.h:
+ (WebCore::GenericTaskQueueBase::hasPendingTasks const):
+ (WebCore::GenericTaskQueueBase::isClosed const):
+ (WebCore::GenericTaskQueueBase::close):
+ (WebCore::GenericTaskQueueBase::cancelAllTasks):
+ (WebCore::GenericTaskQueueBase::incrementPendingTasks):
+ (WebCore::GenericTaskQueueBase::decremementPendingTasks):
+
2021-06-02 Alex Christensen <achristen...@webkit.org>
Fix WPT test resource-timing/cross-origin-redirects.html
Modified: trunk/Source/WebCore/Headers.cmake (278391 => 278392)
--- trunk/Source/WebCore/Headers.cmake 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/Headers.cmake 2021-06-03 01:54:35 UTC (rev 278392)
@@ -461,6 +461,7 @@
dom/EventListener.h
dom/EventListenerMap.h
dom/EventListenerOptions.h
+ dom/EventLoop.h
dom/EventModifierInit.h
dom/EventNames.h
dom/EventQueue.h
Modified: trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.cpp (278391 => 278392)
--- trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -51,6 +51,7 @@
: WebCore::ActiveDOMObject(element.scriptExecutionContext())
, m_mediaElement(makeWeakPtr(element))
, m_eventQueue(MainThreadGenericEventQueue::create(*this))
+ , m_taskQueue(element.scriptExecutionContext())
{
suspendIfNeeded();
}
Modified: trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.h (278391 => 278392)
--- trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -101,7 +101,7 @@
bool m_available { false };
UniqueRef<MainThreadGenericEventQueue> m_eventQueue;
- GenericTaskQueue<Timer> m_taskQueue;
+ EventLoopTaskQueue m_taskQueue;
};
}
Modified: trunk/Source/WebCore/animation/DocumentTimelinesController.cpp (278391 => 278392)
--- trunk/Source/WebCore/animation/DocumentTimelinesController.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/animation/DocumentTimelinesController.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -43,7 +43,8 @@
namespace WebCore {
DocumentTimelinesController::DocumentTimelinesController(Document& document)
- : m_document(document)
+ : m_currentTimeClearingTaskQueue(&document)
+ , m_document(document)
{
if (auto* page = document.page()) {
if (page->settings().hiddenPageCSSAnimationSuspensionEnabled() && !page->isVisible())
Modified: trunk/Source/WebCore/animation/DocumentTimelinesController.h (278391 => 278392)
--- trunk/Source/WebCore/animation/DocumentTimelinesController.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/animation/DocumentTimelinesController.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -67,7 +67,7 @@
void maybeClearCachedCurrentTime();
WeakHashSet<DocumentTimeline> m_timelines;
- GenericTaskQueue<Timer> m_currentTimeClearingTaskQueue;
+ EventLoopTaskQueue m_currentTimeClearingTaskQueue;
Document& m_document;
Markable<Seconds, Seconds::MarkableTraits> m_cachedCurrentTime;
bool m_isSuspended { false };
Modified: trunk/Source/WebCore/dom/FullscreenManager.cpp (278391 => 278392)
--- trunk/Source/WebCore/dom/FullscreenManager.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/dom/FullscreenManager.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -48,6 +48,7 @@
FullscreenManager::FullscreenManager(Document& document)
: m_document { document }
+ , m_fullscreenTaskQueue { &document }
#if !RELEASE_LOG_DISABLED
, m_logIdentifier(LoggerHelper::uniqueLogIdentifier())
#endif
Modified: trunk/Source/WebCore/dom/FullscreenManager.h (278391 => 278392)
--- trunk/Source/WebCore/dom/FullscreenManager.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/dom/FullscreenManager.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -119,7 +119,7 @@
RefPtr<Element> m_fullscreenElement;
Vector<RefPtr<Element>> m_fullscreenElementStack;
WeakPtr<RenderFullScreen> m_fullscreenRenderer { nullptr };
- GenericTaskQueue<Timer> m_fullscreenTaskQueue;
+ EventLoopTaskQueue m_fullscreenTaskQueue;
Deque<RefPtr<Node>> m_fullscreenChangeEventTargetQueue;
Deque<RefPtr<Node>> m_fullscreenErrorEventTargetQueue;
LayoutRect m_savedPlaceholderFrameRect;
Modified: trunk/Source/WebCore/dom/GenericEventQueue.cpp (278391 => 278392)
--- trunk/Source/WebCore/dom/GenericEventQueue.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/dom/GenericEventQueue.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -28,10 +28,12 @@
#include "Document.h"
#include "Event.h"
+#include "EventLoop.h"
#include "EventTarget.h"
#include "Node.h"
#include "ScriptExecutionContext.h"
#include "Timer.h"
+#include <wtf/Algorithms.h>
#include <wtf/MainThread.h>
#include <wtf/SetForScope.h>
@@ -40,13 +42,12 @@
MainThreadGenericEventQueue::MainThreadGenericEventQueue(EventTarget& owner)
: ActiveDOMObject(owner.scriptExecutionContext())
, m_owner(owner)
- , m_taskQueue(makeUniqueRef<GenericTaskQueue<Timer>>())
{
}
void MainThreadGenericEventQueue::enqueueEvent(RefPtr<Event>&& event)
{
- if (m_isClosed)
+ if (m_isClosed || !scriptExecutionContext())
return;
if (event->target() == &m_owner)
@@ -54,10 +55,10 @@
m_pendingEvents.append(WTFMove(event));
- if (isSuspendedOrPausedByClient())
- return;
-
- m_taskQueue->enqueueTask(std::bind(&MainThreadGenericEventQueue::dispatchOneEvent, this));
+ scriptExecutionContext()->eventLoop().queueTask(TaskSource::MediaElement, [weakThis = makeWeakPtr(*this)] {
+ if (weakThis)
+ weakThis->dispatchOneEvent();
+ });
}
void MainThreadGenericEventQueue::dispatchOneEvent()
@@ -78,14 +79,12 @@
void MainThreadGenericEventQueue::close()
{
m_isClosed = true;
-
- m_taskQueue->close();
- m_pendingEvents.clear();
+ cancelAllEvents();
}
void MainThreadGenericEventQueue::cancelAllEvents()
{
- m_taskQueue->cancelAllTasks();
+ weakPtrFactory().revokeAll();
m_pendingEvents.clear();
}
@@ -96,53 +95,9 @@
bool MainThreadGenericEventQueue::hasPendingEventsOfType(const AtomString& type) const
{
- for (auto& event : m_pendingEvents) {
- if (event->type() == type)
- return true;
- }
-
- return false;
+ return WTF::anyOf(m_pendingEvents, [&](auto& event) { return event->type() == type; });
}
-void MainThreadGenericEventQueue::setPaused(bool shouldPause)
-{
- if (m_isPausedByClient == shouldPause)
- return;
-
- m_isPausedByClient = shouldPause;
- if (shouldPause)
- m_taskQueue->cancelAllTasks();
- else
- rescheduleAllEventsIfNeeded();
-}
-
-void MainThreadGenericEventQueue::suspend(ReasonForSuspension)
-{
- if (m_isSuspended)
- return;
-
- m_isSuspended = true;
- m_taskQueue->cancelAllTasks();
-}
-
-void MainThreadGenericEventQueue::resume()
-{
- if (!m_isSuspended)
- return;
-
- m_isSuspended = false;
- rescheduleAllEventsIfNeeded();
-}
-
-void MainThreadGenericEventQueue::rescheduleAllEventsIfNeeded()
-{
- if (isSuspendedOrPausedByClient())
- return;
-
- for (unsigned i = 0; i < m_pendingEvents.size(); ++i)
- m_taskQueue->enqueueTask(std::bind(&MainThreadGenericEventQueue::dispatchOneEvent, this));
-}
-
void MainThreadGenericEventQueue::stop()
{
close();
Modified: trunk/Source/WebCore/dom/GenericEventQueue.h (278391 => 278392)
--- trunk/Source/WebCore/dom/GenericEventQueue.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/dom/GenericEventQueue.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -26,22 +26,20 @@
#pragma once
#include "ActiveDOMObject.h"
-#include "GenericTaskQueue.h"
#include <wtf/Deque.h>
#include <wtf/Forward.h>
#include <wtf/RefPtr.h>
#include <wtf/UniqueRef.h>
+#include <wtf/WeakPtr.h>
namespace WebCore {
class Event;
class EventTarget;
-class Timer;
class ScriptExecutionContext;
-// All instances of MainThreadGenericEventQueue use a shared Timer for dispatching events.
// FIXME: We should port call sites to the HTML event loop and remove this class.
-class MainThreadGenericEventQueue : public ActiveDOMObject {
+class MainThreadGenericEventQueue : public ActiveDOMObject, public CanMakeWeakPtr<MainThreadGenericEventQueue> {
WTF_MAKE_FAST_ALLOCATED;
public:
static UniqueRef<MainThreadGenericEventQueue> create(EventTarget&);
@@ -52,10 +50,6 @@
void cancelAllEvents();
bool hasPendingEventsOfType(const AtomString&) const;
- void setPaused(bool);
-
- bool isSuspended() const { return m_isSuspended; }
-
bool hasPendingActivity() const;
private:
@@ -66,18 +60,10 @@
const char* activeDOMObjectName() const final;
void stop() final;
- void suspend(ReasonForSuspension) final;
- void resume() final;
- void rescheduleAllEventsIfNeeded();
- bool isSuspendedOrPausedByClient() const { return m_isSuspended || m_isPausedByClient; }
-
EventTarget& m_owner;
- UniqueRef<GenericTaskQueue<Timer>> m_taskQueue;
Deque<RefPtr<Event>> m_pendingEvents;
bool m_isClosed { false };
- bool m_isPausedByClient { false };
- bool m_isSuspended { false };
bool m_isFiringEvent { false };
};
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (278391 => 278392)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -394,7 +394,21 @@
, m_scanTimer(*this, &HTMLMediaElement::scanTimerFired)
, m_playbackControlsManagerBehaviorRestrictionsTimer(*this, &HTMLMediaElement::playbackControlsManagerBehaviorRestrictionsTimerFired)
, m_seekToPlaybackPositionEndedTimer(*this, &HTMLMediaElement::seekToPlaybackPositionEndedTimerFired)
+ , m_configureTextTracksTask(&document)
+ , m_checkPlaybackTargetCompatibilityTask(&document)
+ , m_updateMediaStateTask(&document)
+ , m_mediaEngineUpdatedTask(&document)
, m_updatePlayStateTask(*this)
+ , m_resumeTask(&document)
+ , m_seekTask(&document)
+ , m_playbackControlsManagerBehaviorRestrictionsTask(&document)
+ , m_bufferedTimeRangesChangedTask(&document)
+ , m_promiseTaskQueue(&document)
+ , m_pauseAfterDetachedTaskQueue(&document)
+ , m_resourceSelectionTaskQueue(&document)
+ , m_visibilityChangeTaskQueue(&document)
+ , m_fullscreenTaskQueue(&document)
+ , m_playbackTargetIsWirelessQueue(&document)
, m_asyncEventQueue(MainThreadGenericEventQueue::create(*this))
, m_lastTimeUpdateEventMovieTime(MediaTime::positiveInfiniteTime())
, m_firstTimePlaying(true)
@@ -434,6 +448,9 @@
, m_processingPreferenceChange(false)
, m_shouldAudioPlaybackRequireUserGesture(document.topDocument().audioPlaybackRequiresUserGesture() && !processingUserGestureForMedia())
, m_shouldVideoPlaybackRequireUserGesture(document.topDocument().videoPlaybackRequiresUserGesture() && !processingUserGestureForMedia())
+#if ENABLE(ENCRYPTED_MEDIA)
+ , m_encryptedMediaQueue(&document)
+#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
, m_remote(RemotePlayback::create(*this))
#endif
@@ -567,11 +584,11 @@
if (m_isolatedWorld)
m_isolatedWorld->clearWrappers();
- m_seekTaskQueue.close();
- m_resumeTaskQueue.close();
+ m_seekTask.close();
+ m_resumeTask.close();
m_promiseTaskQueue.close();
m_pauseAfterDetachedTaskQueue.close();
- m_playbackControlsManagerBehaviorRestrictionsQueue.close();
+ m_playbackControlsManagerBehaviorRestrictionsTask.close();
m_resourceSelectionTaskQueue.close();
m_visibilityChangeTaskQueue.close();
#if ENABLE(ENCRYPTED_MEDIA)
@@ -980,16 +997,16 @@
void HTMLMediaElement::scheduleCheckPlaybackTargetCompatability()
{
- if (m_checkPlaybackTargetCompatablityTask.hasPendingTask())
+ if (m_checkPlaybackTargetCompatibilityTask.isPending())
return;
ALWAYS_LOG(LOGIDENTIFIER);
- m_checkPlaybackTargetCompatablityTask.scheduleTask([this] {
- checkPlaybackTargetCompatablity();
+ m_checkPlaybackTargetCompatibilityTask.scheduleTask([this] {
+ checkPlaybackTargetCompatibility();
});
}
-void HTMLMediaElement::checkPlaybackTargetCompatablity()
+void HTMLMediaElement::checkPlaybackTargetCompatibility()
{
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
if (m_isPlayingToWirelessTarget && !m_player->canPlayToWirelessPlaybackTarget()) {
@@ -2957,9 +2974,9 @@
// 3 - If the element's seeking IDL attribute is true, then another instance of this algorithm is
// already running. Abort that other instance of the algorithm without waiting for the step that
// it is running to complete.
- if (m_seekTaskQueue.hasPendingTask()) {
+ if (m_seekTask.isPending()) {
INFO_LOG(LOGIDENTIFIER, "cancelling pending seeks");
- m_seekTaskQueue.cancelTask();
+ m_seekTask.cancelTask();
if (m_pendingSeek) {
now = m_pendingSeek->now;
m_pendingSeek = nullptr;
@@ -2981,7 +2998,7 @@
m_pendingSeek = makeUnique<PendingSeek>(now, time, negativeTolerance, positiveTolerance);
if (fromDOM) {
INFO_LOG(LOGIDENTIFIER, "enqueuing seek from ", now, " to ", time);
- m_seekTaskQueue.scheduleTask(std::bind(&HTMLMediaElement::seekTask, this));
+ m_seekTask.scheduleTask(std::bind(&HTMLMediaElement::seekTask, this));
} else
seekTask();
@@ -3693,7 +3710,7 @@
auto oldVolume = m_volume;
m_volume = volume;
- if (m_volumeRevertTaskQueue.hasPendingTask())
+ if (m_volumeRevertTaskQueue.isPending())
return { };
m_volumeRevertTaskQueue.scheduleTask([this, oldVolume] {
@@ -4481,7 +4498,7 @@
void HTMLMediaElement::scheduleConfigureTextTracks()
{
- if (m_configureTextTracksTask.hasPendingTask())
+ if (m_configureTextTracksTask.isPending())
return;
auto logSiteIdentifier = LOGIDENTIFIER;
@@ -5029,7 +5046,7 @@
void HTMLMediaElement::scheduleMediaEngineWasUpdated()
{
- if (m_mediaEngineUpdatedTask.hasPendingTask())
+ if (m_mediaEngineUpdatedTask.isPending())
return;
auto logSiteIdentifier = LOGIDENTIFIER;
@@ -5322,7 +5339,7 @@
void HTMLMediaElement::scheduleUpdatePlayState()
{
- if (m_updatePlayStateTask.hasPendingTask())
+ if (m_updatePlayStateTask.isPending())
return;
auto logSiteIdentifier = LOGIDENTIFIER;
@@ -5460,7 +5477,7 @@
void HTMLMediaElement::cancelPendingTasks()
{
m_configureTextTracksTask.cancelTask();
- m_checkPlaybackTargetCompatablityTask.cancelTask();
+ m_checkPlaybackTargetCompatibilityTask.cancelTask();
m_updateMediaStateTask.cancelTask();
m_mediaEngineUpdatedTask.cancelTask();
m_updatePlayStateTask.cancelTask();
@@ -5622,15 +5639,15 @@
void HTMLMediaElement::closeTaskQueues()
{
m_configureTextTracksTask.close();
- m_checkPlaybackTargetCompatablityTask.close();
+ m_checkPlaybackTargetCompatibilityTask.close();
m_updateMediaStateTask.close();
m_mediaEngineUpdatedTask.close();
m_updatePlayStateTask.close();
- m_resumeTaskQueue.close();
- m_seekTaskQueue.close();
- m_playbackControlsManagerBehaviorRestrictionsQueue.close();
- m_seekTaskQueue.close();
- m_resumeTaskQueue.close();
+ m_resumeTask.close();
+ m_seekTask.close();
+ m_playbackControlsManagerBehaviorRestrictionsTask.close();
+ m_seekTask.close();
+ m_resumeTask.close();
m_promiseTaskQueue.close();
m_pauseAfterDetachedTaskQueue.close();
m_resourceSelectionTaskQueue.close();
@@ -5675,7 +5692,7 @@
ALWAYS_LOG(LOGIDENTIFIER);
Ref<HTMLMediaElement> protectedThis(*this);
- m_resumeTaskQueue.cancelTask();
+ m_resumeTask.cancelTask();
switch (reason) {
case ReasonForSuspension::BackForwardCache:
@@ -5708,13 +5725,13 @@
m_mediaSession->updateBufferingPolicy();
}
- if (m_error && m_error->code() == MediaError::MEDIA_ERR_ABORTED && !m_resumeTaskQueue.hasPendingTask()) {
+ if (m_error && m_error->code() == MediaError::MEDIA_ERR_ABORTED && !m_resumeTask.isPending()) {
// Restart the load if it was aborted in the middle by moving the document to the back/forward cache.
// m_error is only left at MEDIA_ERR_ABORTED when the document becomes inactive (it is set to
// MEDIA_ERR_ABORTED while the abortEvent is being sent, but cleared immediately afterwards).
// This behavior is not specified but it seems like a sensible thing to do.
// As it is not safe to immedately start loading now, let's schedule a load.
- m_resumeTaskQueue.scheduleTask(std::bind(&HTMLMediaElement::prepareForLoad, this));
+ m_resumeTask.scheduleTask(std::bind(&HTMLMediaElement::prepareForLoad, this));
}
updateRenderer();
@@ -7137,12 +7154,12 @@
void HTMLMediaElement::mediaPlayerBufferedTimeRangesChanged()
{
- if (!m_textTracks || m_bufferedTimeRangesChangedQueue.hasPendingTask())
+ if (!m_textTracks || m_bufferedTimeRangesChangedTask.isPending())
return;
auto logSiteIdentifier = LOGIDENTIFIER;
ALWAYS_LOG(logSiteIdentifier, "task scheduled");
- m_bufferedTimeRangesChangedQueue.scheduleTask([this, logSiteIdentifier] {
+ m_bufferedTimeRangesChangedTask.scheduleTask([this, logSiteIdentifier] {
UNUSED_PARAM(logSiteIdentifier);
ALWAYS_LOG(logSiteIdentifier, "lambda(), task fired");
if (!m_player || !m_textTracks)
@@ -7768,7 +7785,7 @@
void HTMLMediaElement::scheduleUpdateMediaState()
{
- if (m_updateMediaStateTask.hasPendingTask())
+ if (m_updateMediaStateTask.isPending())
return;
auto logSiteIdentifier = LOGIDENTIFIER;
@@ -8039,7 +8056,7 @@
void HTMLMediaElement::playbackControlsManagerBehaviorRestrictionsTimerFired()
{
- if (m_playbackControlsManagerBehaviorRestrictionsQueue.hasPendingTask())
+ if (m_playbackControlsManagerBehaviorRestrictionsTask.isPending())
return;
if (!mediaSession().hasBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager))
@@ -8046,7 +8063,7 @@
return;
RefPtr<HTMLMediaElement> protectedThis(this);
- m_playbackControlsManagerBehaviorRestrictionsQueue.scheduleTask([protectedThis] () {
+ m_playbackControlsManagerBehaviorRestrictionsTask.scheduleTask([protectedThis] () {
auto& mediaElementSession = protectedThis->mediaSession();
if (protectedThis->isPlaying() || mediaElementSession.state() == PlatformMediaSession::Autoplaying || mediaElementSession.state() == PlatformMediaSession::Playing)
return;
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (278391 => 278392)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -185,7 +185,7 @@
#endif
void scheduleCheckPlaybackTargetCompatability();
- void checkPlaybackTargetCompatablity();
+ void checkPlaybackTargetCompatibility();
void scheduleResolvePendingPlayPromises();
void scheduleRejectPendingPlayPromises(Ref<DOMException>&&);
using PlayPromiseVector = Vector<DOMPromiseDeferred<void>>;
@@ -944,21 +944,21 @@
Timer m_scanTimer;
Timer m_playbackControlsManagerBehaviorRestrictionsTimer;
Timer m_seekToPlaybackPositionEndedTimer;
- DeferrableTask<Timer> m_configureTextTracksTask;
- DeferrableTask<Timer> m_checkPlaybackTargetCompatablityTask;
- DeferrableTask<Timer> m_updateMediaStateTask;
- DeferrableTask<Timer> m_mediaEngineUpdatedTask;
+ EventLoopDeferrableTask m_configureTextTracksTask;
+ EventLoopDeferrableTask m_checkPlaybackTargetCompatibilityTask;
+ EventLoopDeferrableTask m_updateMediaStateTask;
+ EventLoopDeferrableTask m_mediaEngineUpdatedTask;
DeferrableTask<HTMLMediaElement> m_updatePlayStateTask;
- DeferrableTask<Timer> m_resumeTaskQueue;
- DeferrableTask<Timer> m_seekTaskQueue;
- DeferrableTask<Timer> m_playbackControlsManagerBehaviorRestrictionsQueue;
- DeferrableTask<Timer> m_bufferedTimeRangesChangedQueue;
- GenericTaskQueue<Timer> m_promiseTaskQueue;
- GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue;
- GenericTaskQueue<Timer> m_resourceSelectionTaskQueue;
- GenericTaskQueue<Timer> m_visibilityChangeTaskQueue;
- GenericTaskQueue<Timer> m_fullscreenTaskQueue;
- GenericTaskQueue<Timer> m_playbackTargetIsWirelessQueue;
+ EventLoopDeferrableTask m_resumeTask;
+ EventLoopDeferrableTask m_seekTask;
+ EventLoopDeferrableTask m_playbackControlsManagerBehaviorRestrictionsTask;
+ EventLoopDeferrableTask m_bufferedTimeRangesChangedTask;
+ EventLoopTaskQueue m_promiseTaskQueue;
+ EventLoopTaskQueue m_pauseAfterDetachedTaskQueue;
+ EventLoopTaskQueue m_resourceSelectionTaskQueue;
+ EventLoopTaskQueue m_visibilityChangeTaskQueue;
+ EventLoopTaskQueue m_fullscreenTaskQueue;
+ EventLoopTaskQueue m_playbackTargetIsWirelessQueue;
RefPtr<TimeRanges> m_playedTimeRanges;
UniqueRef<MainThreadGenericEventQueue> m_asyncEventQueue;
#if PLATFORM(IOS_FAMILY)
@@ -1162,7 +1162,7 @@
RefPtr<MediaKeys> m_mediaKeys;
bool m_attachingMediaKeys { false };
bool m_playbackBlockedWaitingForKey { false };
- GenericTaskQueue<Timer> m_encryptedMediaQueue;
+ EventLoopTaskQueue m_encryptedMediaQueue;
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
Modified: trunk/Source/WebCore/html/shadow/MediaControlTextTrackContainerElement.cpp (278391 => 278392)
--- trunk/Source/WebCore/html/shadow/MediaControlTextTrackContainerElement.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/html/shadow/MediaControlTextTrackContainerElement.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -75,6 +75,7 @@
MediaControlTextTrackContainerElement::MediaControlTextTrackContainerElement(Document& document, HTMLMediaElement& element)
: HTMLDivElement(divTag, document)
+ , m_taskQueue(&document)
, m_mediaElement(makeWeakPtr(&element))
{
}
Modified: trunk/Source/WebCore/html/shadow/MediaControlTextTrackContainerElement.h (278391 => 278392)
--- trunk/Source/WebCore/html/shadow/MediaControlTextTrackContainerElement.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/html/shadow/MediaControlTextTrackContainerElement.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -97,7 +97,7 @@
std::unique_ptr<TextTrackRepresentation> m_textTrackRepresentation;
- GenericTaskQueue<Timer> m_taskQueue;
+ EventLoopTaskQueue m_taskQueue;
WeakPtr<HTMLMediaElement> m_mediaElement;
IntRect m_videoDisplaySize;
int m_fontSize { 0 };
Modified: trunk/Source/WebCore/platform/DeferrableTask.h (278391 => 278392)
--- trunk/Source/WebCore/platform/DeferrableTask.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/platform/DeferrableTask.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,59 +25,95 @@
#pragma once
+#include "ContextDestructionObserver.h"
+#include "EventLoop.h"
#include "GenericTaskQueue.h"
+#include "ScriptExecutionContext.h"
namespace WebCore {
+class DeferrableTaskBase : public CanMakeWeakPtr<DeferrableTaskBase> {
+public:
+ void close()
+ {
+ cancelTask();
+ m_isClosed = true;
+ }
+
+ void cancelTask()
+ {
+ weakPtrFactory().revokeAll();
+ m_isPending = false;
+ }
+
+ bool isPending() const { return m_isPending; }
+
+protected:
+ ~DeferrableTaskBase() = default;
+ bool isClosed() const { return m_isClosed; }
+ void setIsPending(bool isPending) { m_isPending = isPending; }
+
+private:
+ bool m_isPending { false };
+ bool m_isClosed { false };
+};
+
template <typename T>
-class DeferrableTask : public CanMakeWeakPtr<DeferrableTask<T>> {
+class DeferrableTask : public DeferrableTaskBase {
public:
DeferrableTask()
: m_dispatcher()
- {
- }
+ { }
DeferrableTask(T& t)
: m_dispatcher(&t)
- {
- }
+ { }
- typedef WTF::Function<void ()> TaskFunction;
-
- void scheduleTask(TaskFunction&& task)
+ void scheduleTask(Function<void()>&& task)
{
- if (m_isClosed)
+ if (isClosed())
return;
cancelTask();
- m_pendingTask = true;
+ setIsPending(true);
m_dispatcher.postTask([weakThis = makeWeakPtr(*this), task = WTFMove(task)] {
if (!weakThis)
return;
- ASSERT(weakThis->m_pendingTask);
- weakThis->m_pendingTask = false;
+ ASSERT(weakThis->isPending());
+ weakThis->setIsPending(false);
task();
});
}
- void close()
+private:
+ TaskDispatcher<T> m_dispatcher;
+};
+
+// Similar to DeferrableTask but based on the HTML event loop.
+class EventLoopDeferrableTask : public DeferrableTaskBase, private ContextDestructionObserver {
+public:
+ EventLoopDeferrableTask(ScriptExecutionContext* context)
+ : ContextDestructionObserver(context)
+ { }
+
+ // FIXME: Pass TaskSource instead of assuming TaskSource::MediaElement.
+ void scheduleTask(Function<void()>&& task)
{
+ if (isClosed() || !scriptExecutionContext())
+ return;
+
cancelTask();
- m_isClosed = true;
- }
- void cancelTask()
- {
- CanMakeWeakPtr<DeferrableTask<T>>::weakPtrFactory().revokeAll();
- m_pendingTask = false;
+ setIsPending(true);
+ scriptExecutionContext()->eventLoop().queueTask(TaskSource::MediaElement, [weakThis = makeWeakPtr(*this), task = WTFMove(task)] {
+ if (!weakThis)
+ return;
+ ASSERT(weakThis->isPending());
+ weakThis->setIsPending(false);
+ task();
+ });
}
- bool hasPendingTask() const { return m_pendingTask; }
-
-private:
- TaskDispatcher<T> m_dispatcher;
- bool m_pendingTask { false };
- bool m_isClosed { false };
};
}
Modified: trunk/Source/WebCore/platform/GenericTaskQueue.h (278391 => 278392)
--- trunk/Source/WebCore/platform/GenericTaskQueue.h 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/platform/GenericTaskQueue.h 2021-06-03 01:54:35 UTC (rev 278392)
@@ -25,6 +25,9 @@
#pragma once
+#include "ContextDestructionObserver.h"
+#include "EventLoop.h"
+#include "ScriptExecutionContext.h"
#include "Timer.h"
#include <wtf/Deque.h>
#include <wtf/Function.h>
@@ -75,8 +78,35 @@
Deque<Function<void()>> m_pendingTasks WTF_GUARDED_BY_LOCK(s_sharedLock);
};
+class GenericTaskQueueBase : public CanMakeWeakPtr<GenericTaskQueueBase> {
+public:
+ bool hasPendingTasks() const { return m_pendingTasks; }
+ bool isClosed() const { return m_isClosed; }
+
+ void close()
+ {
+ cancelAllTasks();
+ m_isClosed = true;
+ }
+
+ void cancelAllTasks()
+ {
+ weakPtrFactory().revokeAll();
+ m_pendingTasks = 0;
+ }
+
+protected:
+ ~GenericTaskQueueBase() = default;
+ void incrementPendingTasks() { ++m_pendingTasks; }
+ void decrementPendingTasks() { ASSERT(m_pendingTasks); --m_pendingTasks; }
+
+private:
+ unsigned m_pendingTasks { 0 };
+ bool m_isClosed { false };
+};
+
template <typename T>
-class GenericTaskQueue : public CanMakeWeakPtr<GenericTaskQueue<T>> {
+class GenericTaskQueue : public GenericTaskQueueBase {
WTF_MAKE_FAST_ALLOCATED;
public:
GenericTaskQueue()
@@ -93,9 +123,10 @@
explicit GenericTaskQueue(T* t)
: m_dispatcher(makeUniqueRef<TaskDispatcher<T>>(t))
- , m_isClosed(!t)
{
ASSERT(isMainThread());
+ if (!t)
+ close();
}
~GenericTaskQueue()
@@ -104,42 +135,45 @@
m_dispatcher->postTask([dispatcher = WTFMove(m_dispatcher)] { });
}
- typedef WTF::Function<void ()> TaskFunction;
-
- void enqueueTask(TaskFunction&& task)
+ void enqueueTask(Function<void()>&& task)
{
- if (m_isClosed)
+ if (isClosed())
return;
- ++m_pendingTasks;
+ incrementPendingTasks();
m_dispatcher->postTask([weakThis = makeWeakPtr(*this), task = WTFMove(task)] {
if (!weakThis)
return;
- ASSERT(weakThis->m_pendingTasks);
- --weakThis->m_pendingTasks;
+ weakThis->decrementPendingTasks();
task();
});
}
- void close()
+private:
+ UniqueRef<TaskDispatcher<T>> m_dispatcher;
+};
+
+// Similar to GenericTaskQueue but based on the HTML event loop.
+class EventLoopTaskQueue : public GenericTaskQueueBase, private ContextDestructionObserver {
+public:
+ EventLoopTaskQueue(ScriptExecutionContext* context)
+ : ContextDestructionObserver(context)
+ { }
+
+ // FIXME: Pass a TaskSource instead of assuming TaskSource::MediaElement.
+ void enqueueTask(Function<void()>&& task)
{
- cancelAllTasks();
- m_isClosed = true;
- }
+ if (isClosed() || !scriptExecutionContext())
+ return;
- void cancelAllTasks()
- {
- CanMakeWeakPtr<GenericTaskQueue<T>>::weakPtrFactory().revokeAll();
- m_pendingTasks = 0;
+ incrementPendingTasks();
+ scriptExecutionContext()->eventLoop().queueTask(TaskSource::MediaElement, [weakThis = makeWeakPtr(*this), task = WTFMove(task)] {
+ if (!weakThis)
+ return;
+ weakThis->decrementPendingTasks();
+ task();
+ });
}
-
- bool hasPendingTasks() const { return m_pendingTasks; }
- bool isClosed() const { return m_isClosed; }
-
-private:
- UniqueRef<TaskDispatcher<T>> m_dispatcher;
- unsigned m_pendingTasks { 0 };
- bool m_isClosed { false };
};
}
Modified: trunk/Source/WebCore/platform/RemoteCommandListener.cpp (278391 => 278392)
--- trunk/Source/WebCore/platform/RemoteCommandListener.cpp 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/platform/RemoteCommandListener.cpp 2021-06-03 01:54:35 UTC (rev 278392)
@@ -71,7 +71,7 @@
void RemoteCommandListener::scheduleSupportedCommandsUpdate()
{
- if (!m_updateCommandsTask.hasPendingTask()) {
+ if (!m_updateCommandsTask.isPending()) {
m_updateCommandsTask.scheduleTask([this] () {
updateSupportedCommands();
});
Modified: trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm (278391 => 278392)
--- trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm 2021-06-03 01:54:35 UTC (rev 278392)
@@ -183,7 +183,7 @@
return;
}
- ASSERT(!m_mappingCallback && !m_mappingCallbackTask.hasPendingTask());
+ ASSERT(!m_mappingCallback && !m_mappingCallbackTask.isPending());
// An existing callback means this buffer is in the mapped state.
m_mappingCallback = PendingMappingCallback::create(WTFMove(callback));
Modified: trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm (278391 => 278392)
--- trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm 2021-06-03 01:25:53 UTC (rev 278391)
+++ trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUQueueMetal.mm 2021-06-03 01:54:35 UTC (rev 278392)
@@ -96,7 +96,7 @@
END_BLOCK_OBJC_EXCEPTIONS
}
- if (m_presentTask.hasPendingTask() || !m_device || !m_device->swapChain())
+ if (m_presentTask.isPending() || !m_device || !m_device->swapChain())
return;
// If a GPUSwapChain exists, ensure that a present is scheduled after all command buffers.