Added the GenericEventQueue class in order to generalize asynchronous
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2012 22:56:23 +0000 (22:56 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2012 22:56:23 +0000 (22:56 +0000)
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

Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/GenericEventQueue.cpp [new file with mode: 0644]
Source/WebCore/dom/GenericEventQueue.h [new file with mode: 0644]
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h

index 18306a7..01b02b3 100644 (file)
@@ -557,6 +557,7 @@ SET(WebCore_SOURCES
     dom/EventTarget.cpp
     dom/ExceptionBase.cpp
     dom/ExceptionCodePlaceholder.cpp
+    dom/GenericEventQueue.cpp
     dom/IconURL.cpp
     dom/KeyboardEvent.cpp
     dom/MessageChannel.cpp
index 3e87981..70ccd60 100644 (file)
@@ -1,3 +1,50 @@
+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.
index 680dbd6..8c4c1e0 100644 (file)
@@ -1567,6 +1567,8 @@ webcore_sources += \
        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 \
index 6f54465..d21ab66 100644 (file)
@@ -520,6 +520,7 @@ SOURCES += \
     dom/EventTarget.cpp \
     dom/ExceptionBase.cpp \
     dom/ExceptionCodePlaceholder.cpp \
+    dom/GenericEventQueue.cpp \
     dom/IconURL.cpp \
     dom/KeyboardEvent.cpp \
     dom/MessageChannel.cpp \
index bb9883d..5b69c36 100644 (file)
             'dom/ExceptionBase.cpp',
             'dom/ExceptionBase.h',
             'dom/ExceptionCodePlaceholder.cpp',
+            'dom/GenericEventQueue.cpp',
+            'dom/GenericEventQueue.h',
             'dom/HashChangeEvent.h',
             'dom/IgnoreDestructiveWriteCountIncrementer.h',
             'dom/IconURL.cpp',
index 0350399..4ed8c75 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\dom\GenericEventQueue.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\dom\GenericEventQueue.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\dom\HashChangeEvent.h"
                                >
                        </File>
index 7bda0ae..6516440 100644 (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;
                };
diff --git a/Source/WebCore/dom/GenericEventQueue.cpp b/Source/WebCore/dom/GenericEventQueue.cpp
new file mode 100644 (file)
index 0000000..71fcaf0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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();
+}
+
+}
diff --git a/Source/WebCore/dom/GenericEventQueue.h b/Source/WebCore/dom/GenericEventQueue.h
new file mode 100644 (file)
index 0000000..6b6f6b4
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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
index cc5c264..03bbca3 100644 (file)
@@ -174,7 +174,6 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
     : 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()
@@ -541,29 +540,10 @@ void HTMLMediaElement::scheduleEvent(const AtomicString& eventName)
 #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>*)
@@ -1192,8 +1172,7 @@ void HTMLMediaElement::mediaEngineError(PassRefPtr<MediaError> err)
 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))
@@ -3177,11 +3156,7 @@ void HTMLMediaElement::resume()
 
 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()
@@ -3692,6 +3667,24 @@ void HTMLMediaElement::updateMediaController()
         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
index da49c40..5f763b2 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "HTMLElement.h"
 #include "ActiveDOMObject.h"
+#include "GenericEventQueue.h"
 #include "MediaCanStartListener.h"
 #include "MediaControllerInterface.h"
 #include "MediaPlayer.h"
@@ -205,7 +206,7 @@ public:
 
     virtual void trackWasAdded(HTMLTrackElement*);
     virtual void trackWasRemoved(HTMLTrackElement*);
-    
+
     void configureTextTrack(HTMLTrackElement*);
     void configureTextTracks();
     bool textTracksAreReady() const;
@@ -273,6 +274,8 @@ public:
     MediaController* controller() const;
     void setController(PassRefPtr<MediaController>);
 
+    virtual bool dispatchEvent(PassRefPtr<Event>);
+
 protected:
     HTMLMediaElement(const QualifiedName&, Document*, bool);
     virtual ~HTMLMediaElement();
@@ -365,7 +368,6 @@ private:
 #endif
 
     void loadTimerFired(Timer<HTMLMediaElement>*);
-    void asyncEventTimerFired(Timer<HTMLMediaElement>*);
     void progressEventTimerFired(Timer<HTMLMediaElement>*);
     void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
     void startPlaybackProgressTimer();
@@ -470,11 +472,10 @@ private:
 #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;