+2016-05-10 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r200627.
+ https://bugs.webkit.org/show_bug.cgi?id=157531
+
+ This change has caused crashes in existing LayoutTests
+ (Requested by ryanhaddad on #webkit).
+
+ Reverted changeset:
+
+ "Return a Promise from HTMLMediaElement.play()"
+ https://bugs.webkit.org/show_bug.cgi?id=157400
+ http://trac.webkit.org/changeset/200627
+
2016-05-10 Simon Fraser <simon.fraser@apple.com>
Fix scrolling tree dumping
+2016-05-10 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r200627.
+ https://bugs.webkit.org/show_bug.cgi?id=157531
+
+ This change has caused crashes in existing LayoutTests
+ (Requested by ryanhaddad on #webkit).
+
+ Reverted changeset:
+
+ "Return a Promise from HTMLMediaElement.play()"
+ https://bugs.webkit.org/show_bug.cgi?id=157400
+ http://trac.webkit.org/changeset/200627
+
2016-05-06 Jer Noble <jer.noble@apple.com>
Return a Promise from HTMLMediaElement.play()
PASS HTMLMediaElement interface: attribute ended
PASS HTMLMediaElement interface: attribute autoplay
PASS HTMLMediaElement interface: attribute loop
-FAIL HTMLMediaElement interface: operation play() assert_throws: calling operation with this = null didn't throw TypeError function "function () {
- fn.apply(obj, args);
- }" did not throw
+PASS HTMLMediaElement interface: operation play()
PASS HTMLMediaElement interface: operation pause()
PASS HTMLMediaElement interface: attribute mediaGroup
PASS HTMLMediaElement interface: attribute controller
+++ /dev/null
-
-RUN(mediaElement.src = findMediaFile("video", "content/invalid"))
-RUN(mediaElement.play().then(failTest).catch(promiseRejected))
-Promise rejected. OK
-EXPECTED (error.name == 'NotSupportedError') OK
-END OF TEST
-
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- var error;
- function start()
- {
- findMediaElement();
- run('mediaElement.src = findMediaFile("video", "content/invalid")');
- run('mediaElement.play().then(failTest).catch(promiseRejected)');
- }
- function promiseRejected(e)
- {
- error = e;
- logResult(true, "Promise rejected.");
- testExpected('error.name', 'NotSupportedError');
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
+++ /dev/null
-
-RUN(mediaElement.play().then(failTest).catch(promiseRejected))
-RUN(mediaElement.src = findMediaFile("video", "content/test"))
-Promise rejected. OK
-EXPECTED (error.name == 'AbortError') OK
-END OF TEST
-
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- var error;
- function start()
- {
- findMediaElement();
- run('mediaElement.play().then(failTest).catch(promiseRejected)');
- run('mediaElement.src = findMediaFile("video", "content/test")');
- }
- function promiseRejected(e)
- {
- error = e;
- logResult(true, "Promise rejected.");
- testExpected('error.name', 'AbortError');
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
+++ /dev/null
-
-RUN(mediaElement.play().then(failTest).catch(promiseRejected))
-RUN(mediaElement.pause())
-Promise rejected. OK
-EXPECTED (error.name == 'AbortError') OK
-END OF TEST
-
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- var error;
- function start()
- {
- findMediaElement();
- run('mediaElement.play().then(failTest).catch(promiseRejected)');
- run('mediaElement.pause()');
- }
- function promiseRejected(e)
- {
- error = e;
- logResult(true, "Promise rejected.");
- testExpected('error.name', 'AbortError');
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
+++ /dev/null
-
-RUN(internals.setMediaElementRestrictions(mediaElement, "RequireUserGestureForVideoRateChange"))
-RUN(mediaElement.src = findMediaFile("video", "content/test"))
-RUN(mediaElement.play().then(failTest).catch(promiseRejected))
-Promise rejected. OK
-EXPECTED (error.name == 'NotAllowedError') OK
-END OF TEST
-
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- var error;
- function start()
- {
- findMediaElement();
- if (window.internals)
- run('internals.setMediaElementRestrictions(mediaElement, "RequireUserGestureForVideoRateChange")');
-
- run('mediaElement.src = findMediaFile("video", "content/test")');
- run('mediaElement.play().then(failTest).catch(promiseRejected)');
- }
-
- function promiseRejected(e)
- {
- error = e;
- logResult(true, "Promise rejected.");
- testExpected('error.name', 'NotAllowedError');
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
+++ /dev/null
-
-RUN(mediaElement.src = findMediaFile("video", "content/invalid"))
-EVENT(error)
-RUN(mediaElement.play().then(failTest).catch(promiseRejected))
-Promise rejected. OK
-EXPECTED (error.name == 'NotSupportedError') OK
-END OF TEST
-
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- var error;
- function start()
- {
- findMediaElement();
- run('mediaElement.src = findMediaFile("video", "content/invalid")');
- waitForEventOnce('error', error);
- }
-
- function error()
- {
- run('mediaElement.play().then(failTest).catch(promiseRejected)');
- }
-
- function promiseRejected(e)
- {
- error = e;
- logResult(true, "Promise rejected.");
- testExpected('error.name', 'NotSupportedError');
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
+++ /dev/null
-
-RUN(mediaElement.src = findMediaFile("video", "content/test"))
-RUN(mediaElement.play().then(promiseResolved).catch(failTest))
-Promise resolved. OK
-END OF TEST
-
+++ /dev/null
-
-RUN(mediaElement.src = findMediaFile("video", "content/test"))
-RUN(mediaElement.play())
-EVENT(playing)
-RUN(mediaElement.play().then(promiseResolved).catch(failTest))
-Promise resolved. OK
-END OF TEST
-
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- function start()
- {
- findMediaElement();
- run('mediaElement.src = findMediaFile("video", "content/test")');
- run('mediaElement.play()');
- waitForEventOnce('playing', playing);
- }
-
- function playing()
- {
- run('mediaElement.play().then(promiseResolved).catch(failTest)');
- }
-
- function promiseResolved()
- {
- logResult(true, "Promise resolved.");
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <script src=media-file.js></script>
- <script src=video-test.js></script>
-
- <script>
- var promise;
- function start()
- {
- findMediaElement();
- run('mediaElement.src = findMediaFile("video", "content/test")');
- run('mediaElement.play().then(promiseResolved).catch(failTest)');
- }
-
- function promiseResolved()
- {
- logResult(true, "Promise resolved.");
- endTest();
- }
- </script>
- </head>
-
- <body onload="start()">
-
- <video></video>
-
- </body>
-</html>
platform/FileChooser.cpp
platform/FileStream.cpp
platform/FileSystem.cpp
- platform/GenericTaskQueue.cpp
platform/Language.cpp
platform/Length.cpp
platform/LengthBox.cpp
+2016-05-10 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r200627.
+ https://bugs.webkit.org/show_bug.cgi?id=157531
+
+ This change has caused crashes in existing LayoutTests
+ (Requested by ryanhaddad on #webkit).
+
+ Reverted changeset:
+
+ "Return a Promise from HTMLMediaElement.play()"
+ https://bugs.webkit.org/show_bug.cgi?id=157400
+ http://trac.webkit.org/changeset/200627
+
2016-05-10 Simon Fraser <simon.fraser@apple.com>
Fix scrolling tree dumping
CD3E252318046BCD00E27F56 /* CSSGridTemplateAreasValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3E252118046BCD00E27F56 /* CSSGridTemplateAreasValue.cpp */; };
CD3E252418046BCD00E27F56 /* CSSGridTemplateAreasValue.h in Headers */ = {isa = PBXBuildFile; fileRef = CD3E252218046BCD00E27F56 /* CSSGridTemplateAreasValue.h */; };
CD4AC52A1496AE9A0087C4EF /* Composite.wav in Copy Audio Resources */ = {isa = PBXBuildFile; fileRef = CD4AC5281496AE2F0087C4EF /* Composite.wav */; };
- CD4BE52A1CE136EF009D87DA /* GenericTaskQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD4BE5291CE13425009D87DA /* GenericTaskQueue.cpp */; };
CD5209E41B0BD8380077184E /* MediaPlayerEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5209E31B0BD8380077184E /* MediaPlayerEnums.h */; settings = {ATTRIBUTES = (Private, ); }; };
CD5209E61B0BD9E10077184E /* HTMLMediaElementEnums.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5209E51B0BD9E10077184E /* HTMLMediaElementEnums.h */; settings = {ATTRIBUTES = (Private, ); }; };
CD52481A18E200ED0008A07D /* DisplaySleepDisabler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD52481818E200ED0008A07D /* DisplaySleepDisabler.cpp */; };
CD3E252218046BCD00E27F56 /* CSSGridTemplateAreasValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSGridTemplateAreasValue.h; sourceTree = "<group>"; };
CD4097FF1A8C855F004C65E9 /* CFNSURLConnectionSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFNSURLConnectionSPI.h; sourceTree = "<group>"; };
CD4AC5281496AE2F0087C4EF /* Composite.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = Composite.wav; path = platform/audio/resources/Composite.wav; sourceTree = SOURCE_ROOT; };
- CD4BE5291CE13425009D87DA /* GenericTaskQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericTaskQueue.cpp; sourceTree = "<group>"; };
CD4E0AFA11F7BC27009D3811 /* fullscreen.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = fullscreen.css; sourceTree = "<group>"; };
CD5209E31B0BD8380077184E /* MediaPlayerEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerEnums.h; sourceTree = "<group>"; };
CD5209E51B0BD9E10077184E /* HTMLMediaElementEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLMediaElementEnums.h; sourceTree = "<group>"; };
5179CE23195C81420019C198 /* GamepadProvider.h */,
5179CE29195C91860019C198 /* GamepadProviderClient.h */,
CD62FB941AF018E70012ED7D /* GenericTaskQueue.h */,
- CD4BE5291CE13425009D87DA /* GenericTaskQueue.cpp */,
A8748BDF12CBF2DC001FBA41 /* HashTools.h */,
BC3BC29B0E91AB0F00835588 /* HostWindow.h */,
862F129F18C1DCE4005C54AF /* HysteresisActivity.h */,
D70AD65713E1342B005B50B4 /* RenderRegion.cpp in Sources */,
BCE93F471517C6D5008CCF74 /* RenderRegionSet.cpp in Sources */,
A871DFE20A15376B00B12A68 /* RenderReplaced.cpp in Sources */,
- CD4BE52A1CE136EF009D87DA /* GenericTaskQueue.cpp in Sources */,
BCA846D60DC67A350026C309 /* RenderReplica.cpp in Sources */,
1479FAED109AE37500DED655 /* RenderRuby.cpp in Sources */,
1479FAEF109AE37500DED655 /* RenderRubyBase.cpp in Sources */,
#include "Event.h"
#include "EventTarget.h"
-#include "ScriptExecutionContext.h"
#include "Timer.h"
#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>
GenericEventQueue::GenericEventQueue(EventTarget& owner)
: m_owner(owner)
+ , m_weakPtrFactory(this)
, m_isClosed(false)
{
}
if (m_isSuspended)
return;
- m_taskQueue.enqueueTask(std::bind(&GenericEventQueue::dispatchOneEvent, this));
+ pendingQueues().append(m_weakPtrFactory.createWeakPtr());
+ if (!sharedTimer().isActive())
+ sharedTimer().startOneShot(0);
+}
+
+Timer& GenericEventQueue::sharedTimer()
+{
+ ASSERT(isMainThread());
+ static NeverDestroyed<Timer> timer(GenericEventQueue::sharedTimerFired);
+ return timer.get();
+}
+
+void GenericEventQueue::sharedTimerFired()
+{
+ ASSERT(!sharedTimer().isActive());
+ ASSERT(!pendingQueues().isEmpty());
+
+ // Copy the pending events first because we don't want to process synchronously the new events
+ // queued by the JS events handlers that are executed in the loop below.
+ Deque<WeakPtr<GenericEventQueue>> queuedEvents;
+ std::swap(queuedEvents, pendingQueues());
+ while (!queuedEvents.isEmpty()) {
+ WeakPtr<GenericEventQueue> queue = queuedEvents.takeFirst();
+ if (!queue)
+ continue;
+ queue->dispatchOneEvent();
+ }
+}
+
+Deque<WeakPtr<GenericEventQueue>>& GenericEventQueue::pendingQueues()
+{
+ ASSERT(isMainThread());
+ static NeverDestroyed<Deque<WeakPtr<GenericEventQueue>>> queues;
+ return queues.get();
}
void GenericEventQueue::dispatchOneEvent()
{
m_isClosed = true;
- m_taskQueue.close();
+ m_weakPtrFactory.revokeAll();
m_pendingEvents.clear();
}
void GenericEventQueue::cancelAllEvents()
{
- m_taskQueue.cancelAllTasks();
+ m_weakPtrFactory.revokeAll();
m_pendingEvents.clear();
}
{
ASSERT(!m_isSuspended);
m_isSuspended = true;
- m_taskQueue.cancelAllTasks();
+ m_weakPtrFactory.revokeAll();
}
void GenericEventQueue::resume()
return;
for (unsigned i = 0; i < m_pendingEvents.size(); ++i)
- m_taskQueue.enqueueTask(std::bind(&GenericEventQueue::dispatchOneEvent, this));
+ pendingQueues().append(m_weakPtrFactory.createWeakPtr());
+
+ if (!sharedTimer().isActive())
+ sharedTimer().startOneShot(0);
}
}
#ifndef GenericEventQueue_h
#define GenericEventQueue_h
-#include "GenericTaskQueue.h"
#include <wtf/Deque.h>
#include <wtf/Forward.h>
#include <wtf/RefPtr.h>
void resume();
private:
+ static Timer& sharedTimer();
+ static void sharedTimerFired();
+ static Deque<WeakPtr<GenericEventQueue>>& pendingQueues();
+
void dispatchOneEvent();
EventTarget& m_owner;
- GenericTaskQueue<Timer> m_taskQueue;
Deque<RefPtr<Event>> m_pendingEvents;
+ WeakPtrFactory<GenericEventQueue> m_weakPtrFactory;
bool m_isClosed;
bool m_isSuspended { false };
};
#include "FrameView.h"
#include "HTMLSourceElement.h"
#include "HTMLVideoElement.h"
-#include "JSDOMError.h"
#include "JSHTMLMediaElement.h"
#include "Language.h"
#include "Logging.h"
, m_progressEventTimer(*this, &HTMLMediaElement::progressEventTimerFired)
, m_playbackProgressTimer(*this, &HTMLMediaElement::playbackProgressTimerFired)
, m_scanTimer(*this, &HTMLMediaElement::scanTimerFired)
+ , m_pauseAfterDetachedTimer(*this, &HTMLMediaElement::pauseAfterDetachedTimerFired)
+ , m_seekTaskQueue(document)
+ , m_resizeTaskQueue(document)
+ , m_shadowDOMTaskQueue(document)
, m_playedTimeRanges()
, m_asyncEventQueue(*this)
, m_requestedPlaybackRate(1)
#endif
m_seekTaskQueue.close();
- m_promiseTaskQueue.close();
- m_pauseAfterDetachedTaskQueue.close();
m_completelyLoaded = true;
}
return InsertionDone;
}
-void HTMLMediaElement::pauseAfterDetachedTask()
+void HTMLMediaElement::pauseAfterDetachedTimerFired()
{
// If we were re-inserted into an active document, no need to pause.
if (m_inActiveDocument)
m_inActiveDocument = false;
if (insertionPoint.inDocument()) {
// Pause asynchronously to let the operation that removed us finish, in case we get inserted back into a document.
- m_pauseAfterDetachedTaskQueue.enqueueTask(std::bind(&HTMLMediaElement::pauseAfterDetachedTask, this));
+ m_pauseAfterDetachedTimer.startOneShot(0);
}
HTMLElement::removedFrom(insertionPoint);
m_asyncEventQueue.enqueueEvent(WTFMove(event));
}
-void HTMLMediaElement::scheduleResolvePendingPlayPromises()
-{
- m_promiseTaskQueue.enqueueTask(std::bind(&HTMLMediaElement::resolvePendingPlayPromises, this));
-}
-
-void HTMLMediaElement::rejectPendingPlayPromises(DOMError& error)
-{
- Vector<PlayPromise> pendingPlayPromises = WTFMove(m_pendingPlayPromises);
-
- for (auto& promise : pendingPlayPromises)
- promise.reject(error);
-}
-
-void HTMLMediaElement::resolvePendingPlayPromises()
-{
- Vector<PlayPromise> pendingPlayPromises = WTFMove(m_pendingPlayPromises);
-
- for (auto& promise : pendingPlayPromises)
- promise.resolve(nullptr);
-}
-
-void HTMLMediaElement::scheduleNotifyAboutPlaying()
-{
- m_promiseTaskQueue.enqueueTask(std::bind(&HTMLMediaElement::notifyAboutPlaying, this));
-}
-
-void HTMLMediaElement::notifyAboutPlaying()
-{
- dispatchEvent(Event::create(eventNames().playingEvent, false, true));
- resolvePendingPlayPromises();
-}
-
void HTMLMediaElement::pendingActionTimerFired()
{
Ref<HTMLMediaElement> protect(*this); // loadNextSourceChild may fire 'beforeload', which can make arbitrary DOM mutations.
// 7 - Queue a task to fire a simple event named error at the media element.
scheduleEvent(eventNames().errorEvent);
- rejectPendingPlayPromises(DOMError::create("NotSupportedError", "The operation is not supported."));
-
#if ENABLE(MEDIA_SOURCE)
closeMediaSource();
#endif
for (auto& source : childrenOfType<HTMLSourceElement>(*this))
source.cancelPendingErrorEvent();
-
- rejectPendingPlayPromises(DOMError::create("AbortError", "The operation was aborted."));
}
void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*)
if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady) {
scheduleEvent(eventNames().canplayEvent);
if (isPotentiallyPlaying)
- scheduleNotifyAboutPlaying();
+ scheduleEvent(eventNames().playingEvent);
shouldUpdateDisplayState = true;
}
scheduleEvent(eventNames().canplaythroughEvent);
if (isPotentiallyPlaying && oldState <= HAVE_CURRENT_DATA)
- scheduleNotifyAboutPlaying();
+ scheduleEvent(eventNames().playingEvent);
if (canTransitionFromAutoplayToPlay()) {
m_paused = false;
invalidateCachedTime();
scheduleEvent(eventNames().playEvent);
- scheduleNotifyAboutPlaying();
+ scheduleEvent(eventNames().playingEvent);
}
shouldUpdateDisplayState = true;
setAttribute(preloadAttr, preload);
}
-void HTMLMediaElement::play(PlayPromise&& promise)
-{
- LOG(Media, "HTMLMediaElement::play(%p)", this);
-
- if (!m_mediaSession->playbackPermitted(*this)) {
- promise.reject(DOMError::create("NotAllowedError", "The request is not allowed by the user agent or the platform in the current context."));
- return;
- }
-
- if (m_error && m_error->code() == MediaError::MEDIA_ERR_SRC_NOT_SUPPORTED) {
- promise.reject(DOMError::create("NotSupportedError", "The operation is not supported.."));
- return;
- }
-
- if (ScriptController::processingUserGestureForMedia())
- removeBehaviorsRestrictionsAfterFirstUserGesture();
-
- if (!playInternal())
- promise.reject(DOMError::create("NotAllowedError", "The request is not allowed by the user agent or the platform in the current context."));
-
- m_pendingPlayPromises.append(WTFMove(promise));
-}
-
void HTMLMediaElement::play()
{
LOG(Media, "HTMLMediaElement::play(%p)", this);
playInternal();
}
-bool HTMLMediaElement::playInternal()
+void HTMLMediaElement::playInternal()
{
LOG(Media, "HTMLMediaElement::playInternal(%p)", this);
if (!m_mediaSession->clientWillBeginPlayback()) {
LOG(Media, " returning because of interruption");
- return false;
+ return;
}
// 4.8.10.9. Playing the media resource
if (m_readyState <= HAVE_CURRENT_DATA)
scheduleEvent(eventNames().waitingEvent);
else if (m_readyState >= HAVE_FUTURE_DATA)
- scheduleNotifyAboutPlaying();
+ scheduleEvent(eventNames().playingEvent);
#if ENABLE(MEDIA_SESSION)
// 6.3 Activating a media session from a media element
if (!m_session->invoke()) {
pause();
- return false;
+ return;
}
}
}
#endif
- } else if (m_readyState >= HAVE_FUTURE_DATA)
- scheduleResolvePendingPlayPromises();
-
+ }
m_autoplaying = false;
updatePlayState();
updateMediaController();
- return true;
}
void HTMLMediaElement::pause()
m_paused = true;
scheduleTimeupdateEvent(false);
scheduleEvent(eventNames().pauseEvent);
- rejectPendingPlayPromises(DOMError::create("AbortError", "The operation was aborted."));
if (MemoryPressureHandler::singleton().isUnderMemoryPressure())
purgeBufferedDataIfPossible();
m_seekTaskQueue.close();
m_resizeTaskQueue.close();
m_shadowDOMTaskQueue.close();
- m_promiseTaskQueue.close();
- m_pauseAfterDetachedTaskQueue.close();
ActiveDOMObject::contextDestroyed();
}
stopWithoutDestroyingMediaPlayer();
m_asyncEventQueue.close();
- m_promiseTaskQueue.close();
// Once an active DOM object has been stopped it can not be restarted, so we can deallocate
// the media player now. Note that userCancelledLoad will already called clearMediaPlayer
#include "GenericEventQueue.h"
#include "GenericTaskQueue.h"
#include "HTMLMediaElementEnums.h"
-#include "JSDOMPromise.h"
#include "MediaCanStartListener.h"
#include "MediaControllerInterface.h"
#include "MediaElementSession.h"
class AudioSourceProvider;
class MediaElementAudioSourceNode;
#endif
-class DOMError;
class DisplaySleepDisabler;
class Event;
class HTMLSourceElement;
using HTMLMediaElementEnums::DelayedActionType;
void scheduleDelayedAction(DelayedActionType);
- void scheduleResolvePendingPlayPromises();
- void rejectPendingPlayPromises(DOMError&);
- void resolvePendingPlayPromises();
- void scheduleNotifyAboutPlaying();
- void notifyAboutPlaying();
MediaPlayerEnums::MovieLoadType movieLoadType() const;
bool isAutoplaying() const { return m_autoplaying; }
bool loop() const;
void setLoop(bool b);
-
- typedef DOMPromise<std::nullptr_t, DOMError&> PlayPromise;
- void play(PlayPromise&&);
-
WEBCORE_EXPORT void play() override;
WEBCORE_EXPORT void pause() override;
void setShouldBufferData(bool) override;
// These "internal" functions do not check user gesture restrictions.
void loadInternal();
- bool playInternal();
+ void playInternal();
void pauseInternal();
void prepareForLoad();
void isVisibleInViewportChanged() final;
void updateShouldAutoplay();
- void pauseAfterDetachedTask();
+ void pauseAfterDetachedTimerFired();
Timer m_pendingActionTimer;
Timer m_progressEventTimer;
Timer m_playbackProgressTimer;
Timer m_scanTimer;
- GenericTaskQueue<Timer> m_seekTaskQueue;
- GenericTaskQueue<Timer> m_resizeTaskQueue;
- GenericTaskQueue<Timer> m_shadowDOMTaskQueue;
- GenericTaskQueue<Timer> m_promiseTaskQueue;
- GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue;
+ Timer m_pauseAfterDetachedTimer;
+ GenericTaskQueue<ScriptExecutionContext> m_seekTaskQueue;
+ GenericTaskQueue<ScriptExecutionContext> m_resizeTaskQueue;
+ GenericTaskQueue<ScriptExecutionContext> m_shadowDOMTaskQueue;
RefPtr<TimeRanges> m_playedTimeRanges;
GenericEventQueue m_asyncEventQueue;
- Vector<PlayPromise> m_pendingPlayPromises;
-
double m_requestedPlaybackRate;
double m_reportedPlaybackRate;
double m_defaultPlaybackRate;
readonly attribute boolean ended;
[Reflect] attribute boolean autoplay;
[Reflect] attribute boolean loop;
- Promise play();
+ void play();
void pause();
void fastSeek(unrestricted double time);
+++ /dev/null
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "GenericTaskQueue.h"
-
-#include <wtf/MainThread.h>
-#include <wtf/NeverDestroyed.h>
-
-namespace WebCore {
-
-TaskDispatcher<Timer>::~TaskDispatcher()
-{
- Deque<TaskDispatcher<Timer>*> replacementQueue;
- for (auto* dispatcher : pendingDispatchers()) {
- if (dispatcher != this)
- replacementQueue.append(dispatcher);
- }
- if (replacementQueue.isEmpty())
- sharedTimer().stop();
- pendingDispatchers() = WTFMove(replacementQueue);
-}
-
-void TaskDispatcher<Timer>::postTask(std::function<void()> function)
-{
- m_pendingTasks.append(WTFMove(function));
- pendingDispatchers().append(this);
- if (!sharedTimer().isActive())
- sharedTimer().startOneShot(0);
-}
-
-Timer& TaskDispatcher<Timer>::sharedTimer()
-{
- ASSERT(isMainThread());
- static NeverDestroyed<Timer> timer(TaskDispatcher<Timer>::sharedTimerFired);
- return timer.get();
-}
-
-void TaskDispatcher<Timer>::sharedTimerFired()
-{
- ASSERT(!sharedTimer().isActive());
- ASSERT(!pendingDispatchers().isEmpty());
-
- // Copy the pending events first because we don't want to process synchronously the new events
- // queued by the JS events handlers that are executed in the loop below.
- Deque<TaskDispatcher<Timer>*> queuedDispatchers = WTFMove(pendingDispatchers());
- while (!queuedDispatchers.isEmpty()) {
- TaskDispatcher<Timer>* dispatcher = queuedDispatchers.takeFirst();
- if (!dispatcher)
- continue;
- dispatcher->dispatchOneTask();
- }
-}
-
-Deque<TaskDispatcher<Timer>*>& TaskDispatcher<Timer>::pendingDispatchers()
-{
- ASSERT(isMainThread());
- static NeverDestroyed<Deque<TaskDispatcher<Timer>*>> dispatchers;
- return dispatchers.get();
-}
-
-void TaskDispatcher<Timer>::dispatchOneTask()
-{
- ASSERT(!m_pendingTasks.isEmpty());
- std::function<void()> task = m_pendingTasks.takeFirst();
- task();
-}
-
-}
-
template<>
class TaskDispatcher<Timer> {
public:
- ~TaskDispatcher();
- void postTask(std::function<void()>);
+ TaskDispatcher()
+ : m_timer(*this, &TaskDispatcher<Timer>::timerFired)
+ {
+ }
-private:
- static Timer& sharedTimer();
- static void sharedTimerFired();
- static Deque<TaskDispatcher<Timer>*>& pendingDispatchers();
+ void postTask(std::function<void()> function)
+ {
+ m_queue.append(function);
+ m_timer.startOneShot(0);
+ }
- void dispatchOneTask();
+ void timerFired()
+ {
+ Deque<std::function<void()>> queue;
+ queue.swap(m_queue);
+ for (std::function<void()>& function : queue)
+ function();
+ }
- Deque<std::function<void()>> m_pendingTasks;
+ Timer m_timer;
+ Deque<std::function<void()>> m_queue;
};
template <typename T>