event dispatching in HTMLMediaElement.
In order to support asynchronous events dispatched by HTMLTrackElement
there is a need for a generalized implementation of an event queue to
be used for both HTMLMediaElement and Text Tracks.
https://bugs.webkit.org/show_bug.cgi?id=76110
Patch by Victor Carbune <victor@rosedu.org> on 2012-01-27
Reviewed by Eric Carlson.
No new tests. No new functionality, only refactoring.
* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/GenericEventQueue.cpp: Added. Implements the abstract class EventQueue.
(WebCore::GenericEventQueue::GenericEventQueue):
(WebCore::GenericEventQueue::~GenericEventQueue):
(WebCore::GenericEventQueue::enqueueEvent): Append an event to the current
pending event list.
(WebCore::GenericEventQueue::cancelEvent): Removes an event from the current
pending event list.
(WebCore::GenericEventQueue::timerFired): Callback method when the timer fires.
Dispatches all events that are currently pending.
(WebCore::GenericEventQueue::close): Closes the event queue such that it cannot
be used anymore.
(WebCore::GenericEventQueue::cancelAllEvents): Removes all pending events.
(WebCore::GenericEventQueue::hasPendingEvents): True if there are pending events.
* dom/GenericEventQueue.h: Added.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::scheduleEvent): Refactored method to enqueue
the scheduled event on the GenericEventQueue instance.
(WebCore::HTMLMediaElement::cancelPendingEventsAndCallbacks): Ditto.
(WebCore::HTMLMediaElement::hasPendingActivity): Ditto.
(WebCore::HTMLMediaElement::dispatchEvent): This method is overriden
to keep an evidence when a canPlay event is fired.
* html/HTMLMediaElement.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106156
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
dom/EventTarget.cpp
dom/ExceptionBase.cpp
dom/ExceptionCodePlaceholder.cpp
+ dom/GenericEventQueue.cpp
dom/IconURL.cpp
dom/KeyboardEvent.cpp
dom/MessageChannel.cpp
+2012-01-27 Victor Carbune <victor@rosedu.org>
+
+ Added the GenericEventQueue class in order to generalize asynchronous
+ event dispatching in HTMLMediaElement.
+
+ In order to support asynchronous events dispatched by HTMLTrackElement
+ there is a need for a generalized implementation of an event queue to
+ be used for both HTMLMediaElement and Text Tracks.
+
+ https://bugs.webkit.org/show_bug.cgi?id=76110
+
+ Reviewed by Eric Carlson.
+
+ No new tests. No new functionality, only refactoring.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * Target.pri:
+ * WebCore.gypi:
+ * WebCore.vcproj/WebCore.vcproj:
+ * WebCore.xcodeproj/project.pbxproj:
+
+ * dom/GenericEventQueue.cpp: Added. Implements the abstract class EventQueue.
+ (WebCore::GenericEventQueue::GenericEventQueue):
+ (WebCore::GenericEventQueue::~GenericEventQueue):
+ (WebCore::GenericEventQueue::enqueueEvent): Append an event to the current
+ pending event list.
+ (WebCore::GenericEventQueue::cancelEvent): Removes an event from the current
+ pending event list.
+ (WebCore::GenericEventQueue::timerFired): Callback method when the timer fires.
+ Dispatches all events that are currently pending.
+ (WebCore::GenericEventQueue::close): Closes the event queue such that it cannot
+ be used anymore.
+ (WebCore::GenericEventQueue::cancelAllEvents): Removes all pending events.
+ (WebCore::GenericEventQueue::hasPendingEvents): True if there are pending events.
+ * dom/GenericEventQueue.h: Added.
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::HTMLMediaElement):
+ (WebCore::HTMLMediaElement::scheduleEvent): Refactored method to enqueue
+ the scheduled event on the GenericEventQueue instance.
+ (WebCore::HTMLMediaElement::cancelPendingEventsAndCallbacks): Ditto.
+ (WebCore::HTMLMediaElement::hasPendingActivity): Ditto.
+ (WebCore::HTMLMediaElement::dispatchEvent): This method is overriden
+ to keep an evidence when a canPlay event is fired.
+ * html/HTMLMediaElement.h:
+
2012-01-27 Martin Robinson <mrobinson@igalia.com>
Fix a warning in the GTK+ build.
Source/WebCore/dom/FragmentScriptingPermission.h \
Source/WebCore/dom/IgnoreDestructiveWriteCountIncrementer.h \
Source/WebCore/dom/ExceptionCodePlaceholder.h \
+ Source/WebCore/dom/GenericEventQueue.cpp \
+ Source/WebCore/dom/GenericEventQueue.h \
Source/WebCore/dom/IconURL.cpp \
Source/WebCore/dom/IconURL.h \
Source/WebCore/dom/HashChangeEvent.h \
dom/EventTarget.cpp \
dom/ExceptionBase.cpp \
dom/ExceptionCodePlaceholder.cpp \
+ dom/GenericEventQueue.cpp \
dom/IconURL.cpp \
dom/KeyboardEvent.cpp \
dom/MessageChannel.cpp \
'dom/ExceptionBase.cpp',
'dom/ExceptionBase.h',
'dom/ExceptionCodePlaceholder.cpp',
+ 'dom/GenericEventQueue.cpp',
+ 'dom/GenericEventQueue.h',
'dom/HashChangeEvent.h',
'dom/IgnoreDestructiveWriteCountIncrementer.h',
'dom/IconURL.cpp',
>
</File>
<File
+ RelativePath="..\dom\GenericEventQueue.h"
+ >
+ </File>
+ <File
+ RelativePath="..\dom\GenericEventQueue.cpp"
+ >
+ </File>
+ <File
RelativePath="..\dom\HashChangeEvent.h"
>
</File>
070756DF14239B4E00414161 /* JSTextTrackCueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 070756D914239B4C00414161 /* JSTextTrackCueList.cpp */; };
070756E014239B4E00414161 /* JSTextTrackCueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 070756DA14239B4E00414161 /* JSTextTrackCueList.h */; };
0709FC4E1025DEE30059CDBA /* AccessibilitySlider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0709FC4D1025DEE30059CDBA /* AccessibilitySlider.h */; };
+ 0720B0A014D3323500642955 /* GenericEventQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0720B09E14D3323500642955 /* GenericEventQueue.cpp */; };
+ 0720B0A114D3323500642955 /* GenericEventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0720B09F14D3323500642955 /* GenericEventQueue.h */; settings = {ATTRIBUTES = (Private, ); }; };
07230CBC14C10ED900F6B702 /* JSInternalsCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07230CBB14C10ED900F6B702 /* JSInternalsCustom.cpp */; };
072C8B11131C518600A4FCE9 /* MediaPlayerPrivateAVFoundation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 076F0D0912B8192700C26AA4 /* MediaPlayerPrivateAVFoundation.cpp */; };
0735EE6A0F40C5E4004A2604 /* MediaPlayerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0735EE690F40C5E4004A2604 /* MediaPlayerProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D3C5240B576B4B002CA450 /* PasteboardHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D3C5230B576B4B002CA450 /* PasteboardHelper.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D6B3490F61104500B79FD1 /* WorkerScriptLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D6B3470F61104500B79FD1 /* WorkerScriptLoader.h */; };
A7D6B34A0F61104500B79FD1 /* WorkerScriptLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D6B3480F61104500B79FD1 /* WorkerScriptLoader.cpp */; };
- A7DB418214CE1F0A00A2E316 /* ShadowRoot.idl in Resources */ = {isa = PBXBuildFile; fileRef = A7DB418114CE1F0A00A2E316 /* ShadowRoot.idl */; };
A7DBF8DD1276919C006B6008 /* TextCheckingHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7DBF8DB1276919C006B6008 /* TextCheckingHelper.cpp */; };
A7DBF8DE1276919C006B6008 /* TextCheckingHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DBF8DC1276919C006B6008 /* TextCheckingHelper.h */; };
A7F5D94F1384F02D00A29A87 /* NodeRenderingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F5D94D1384F02D00A29A87 /* NodeRenderingContext.cpp */; };
070756DA14239B4E00414161 /* JSTextTrackCueList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTextTrackCueList.h; sourceTree = "<group>"; };
0709FC4D1025DEE30059CDBA /* AccessibilitySlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySlider.h; sourceTree = "<group>"; };
070DD8F50F01868000727DEB /* mediaControls.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mediaControls.css; sourceTree = "<group>"; };
+ 0720B09E14D3323500642955 /* GenericEventQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericEventQueue.cpp; sourceTree = "<group>"; };
+ 0720B09F14D3323500642955 /* GenericEventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericEventQueue.h; sourceTree = "<group>"; };
07230CBB14C10ED900F6B702 /* JSInternalsCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInternalsCustom.cpp; sourceTree = "<group>"; };
0735EE690F40C5E4004A2604 /* MediaPlayerProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerProxy.h; sourceTree = "<group>"; };
0753860014489E9800B78452 /* CachedTextTrack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedTextTrack.cpp; sourceTree = "<group>"; };
A7CACDB013CE875B00BBBE3F /* ExceptionCodePlaceholder.cpp */,
A74BB76A13BDA86300FF7BF0 /* ExceptionCodePlaceholder.h */,
A853123C11D0471B00D4D077 /* FragmentScriptingPermission.h */,
+ 0720B09E14D3323500642955 /* GenericEventQueue.cpp */,
+ 0720B09F14D3323500642955 /* GenericEventQueue.h */,
2442BBF81194C9D300D49469 /* HashChangeEvent.h */,
8482B7441198C32E00BFB005 /* HashChangeEvent.idl */,
45099C401370A7800058D513 /* IconURL.cpp */,
8AD0A59514C88336000D83C5 /* JSWebKitCSSRegionRule.h in Headers */,
8AD0A59614C88358000D83C5 /* DOMWebKitCSSRegionRule.h in Headers */,
8AD0A59814C88358000D83C5 /* DOMWebKitCSSRegionRuleInternal.h in Headers */,
+ 0720B0A114D3323500642955 /* GenericEventQueue.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
977E2E0E12F0FC9C00C13379 /* XSSAuditor.cpp in Sources */,
FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
573D134714CE39FF0057ABCA /* InspectorTypeBuilder.cpp in Sources */,
+ 0720B0A014D3323500642955 /* GenericEventQueue.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+/*
+ * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
+ *
+ * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "GenericEventQueue.h"
+
+#include "Event.h"
+
+namespace WebCore {
+
+GenericEventQueue::GenericEventQueue()
+ : m_timer(this, &GenericEventQueue::timerFired)
+ , m_isClosed(false)
+{
+}
+
+GenericEventQueue::~GenericEventQueue()
+{
+}
+
+bool GenericEventQueue::enqueueEvent(PassRefPtr<Event> event)
+{
+ if (m_isClosed)
+ return false;
+
+ ASSERT(event->target());
+ m_pendingEvents.append(event);
+
+ if (!m_timer.isActive())
+ m_timer.startOneShot(0);
+
+ return true;
+}
+
+bool GenericEventQueue::cancelEvent(Event* event)
+{
+ bool found = m_pendingEvents.contains(event);
+
+ if (found)
+ m_pendingEvents.remove(m_pendingEvents.find(event));
+
+ if (m_pendingEvents.isEmpty())
+ m_timer.stop();
+
+ return found;
+}
+
+void GenericEventQueue::timerFired(Timer<GenericEventQueue>*)
+{
+ ASSERT(!m_timer.isActive());
+ ASSERT(!m_pendingEvents.isEmpty());
+
+ Vector<RefPtr<Event> > pendingEvents;
+ m_pendingEvents.swap(pendingEvents);
+
+ for (unsigned i = 0; i < pendingEvents.size(); ++i)
+ pendingEvents[i]->target()->dispatchEvent(pendingEvents[i].release());
+}
+
+void GenericEventQueue::close()
+{
+ m_isClosed = true;
+
+ m_timer.stop();
+ m_pendingEvents.clear();
+}
+
+void GenericEventQueue::cancelAllEvents()
+{
+ m_timer.stop();
+ m_pendingEvents.clear();
+}
+
+bool GenericEventQueue::hasPendingEvents() const
+{
+ return m_pendingEvents.size();
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
+ *
+ * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef GenericEventQueue_h
+#define GenericEventQueue_h
+
+#include "EventQueue.h"
+#include "Timer.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class GenericEventQueue : public EventQueue {
+
+public:
+ GenericEventQueue();
+ virtual ~GenericEventQueue();
+
+ // EventQueue
+ virtual bool enqueueEvent(PassRefPtr<Event>) OVERRIDE;
+ virtual bool cancelEvent(Event*) OVERRIDE;
+ virtual void close() OVERRIDE;
+
+ void cancelAllEvents();
+ bool hasPendingEvents() const;
+
+private:
+ void timerFired(Timer<GenericEventQueue>*);
+
+ Vector<RefPtr<Event> > m_pendingEvents;
+ Timer<GenericEventQueue> m_timer;
+
+ bool m_isClosed;
+};
+
+}
+
+#endif
: HTMLElement(tagName, document)
, ActiveDOMObject(document, this)
, m_loadTimer(this, &HTMLMediaElement::loadTimerFired)
- , m_asyncEventTimer(this, &HTMLMediaElement::asyncEventTimerFired)
, m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired)
, m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFired)
, m_playedTimeRanges()
#if LOG_MEDIA_EVENTS
LOG(Media, "HTMLMediaElement::scheduleEvent - scheduling '%s'", eventName.string().ascii().data());
#endif
- m_pendingEvents.append(Event::create(eventName, false, true));
- if (!m_asyncEventTimer.isActive())
- m_asyncEventTimer.startOneShot(0);
-}
-
-void HTMLMediaElement::asyncEventTimerFired(Timer<HTMLMediaElement>*)
-{
- Vector<RefPtr<Event> > pendingEvents;
- ExceptionCode ec = 0;
+ RefPtr<Event> event = Event::create(eventName, false, true);
+ event->setTarget(this);
- m_pendingEvents.swap(pendingEvents);
- unsigned count = pendingEvents.size();
- for (unsigned ndx = 0; ndx < count; ++ndx) {
-#if LOG_MEDIA_EVENTS
- LOG(Media, "HTMLMediaElement::asyncEventTimerFired - dispatching '%s'", pendingEvents[ndx]->type().string().ascii().data());
-#endif
- if (pendingEvents[ndx]->type() == eventNames().canplayEvent) {
- m_dispatchingCanPlayEvent = true;
- dispatchEvent(pendingEvents[ndx].release(), ec);
- m_dispatchingCanPlayEvent = false;
- } else
- dispatchEvent(pendingEvents[ndx].release(), ec);
- }
+ m_asyncEventQueue.enqueueEvent(event.release());
}
void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*)
void HTMLMediaElement::cancelPendingEventsAndCallbacks()
{
LOG(Media, "HTMLMediaElement::cancelPendingEventsAndCallbacks");
-
- m_pendingEvents.clear();
+ m_asyncEventQueue.cancelAllEvents();
for (Node* node = firstChild(); node; node = node->nextSibling()) {
if (node->hasTagName(sourceTag))
bool HTMLMediaElement::hasPendingActivity() const
{
- // Return true when we have pending events so we can't fire events after the JS
- // object gets collected.
- bool pending = m_pendingEvents.size();
- LOG(Media, "HTMLMediaElement::hasPendingActivity -> %s", boolString(pending));
- return pending;
+ return m_asyncEventQueue.hasPendingEvents();
}
void HTMLMediaElement::mediaVolumeDidChange()
m_mediaController->reportControllerState();
}
+bool HTMLMediaElement::dispatchEvent(PassRefPtr<Event> event)
+{
+ bool dispatchResult;
+ bool isCanPlayEvent;
+
+ isCanPlayEvent = (event->type() == eventNames().canplayEvent);
+
+ if (isCanPlayEvent)
+ m_dispatchingCanPlayEvent = true;
+
+ dispatchResult = HTMLElement::dispatchEvent(event);
+
+ if (isCanPlayEvent)
+ m_dispatchingCanPlayEvent = false;
+
+ return dispatchResult;
+}
+
bool HTMLMediaElement::isBlocked() const
{
// A media element is a blocked media element if its readyState attribute is in the
#include "HTMLElement.h"
#include "ActiveDOMObject.h"
+#include "GenericEventQueue.h"
#include "MediaCanStartListener.h"
#include "MediaControllerInterface.h"
#include "MediaPlayer.h"
virtual void trackWasAdded(HTMLTrackElement*);
virtual void trackWasRemoved(HTMLTrackElement*);
-
+
void configureTextTrack(HTMLTrackElement*);
void configureTextTracks();
bool textTracksAreReady() const;
MediaController* controller() const;
void setController(PassRefPtr<MediaController>);
+ virtual bool dispatchEvent(PassRefPtr<Event>);
+
protected:
HTMLMediaElement(const QualifiedName&, Document*, bool);
virtual ~HTMLMediaElement();
#endif
void loadTimerFired(Timer<HTMLMediaElement>*);
- void asyncEventTimerFired(Timer<HTMLMediaElement>*);
void progressEventTimerFired(Timer<HTMLMediaElement>*);
void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
void startPlaybackProgressTimer();
#endif
Timer<HTMLMediaElement> m_loadTimer;
- Timer<HTMLMediaElement> m_asyncEventTimer;
Timer<HTMLMediaElement> m_progressEventTimer;
Timer<HTMLMediaElement> m_playbackProgressTimer;
- Vector<RefPtr<Event> > m_pendingEvents;
RefPtr<TimeRanges> m_playedTimeRanges;
+ GenericEventQueue m_asyncEventQueue;
float m_playbackRate;
float m_defaultPlaybackRate;