Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / dom / DocumentEventQueue.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All Rights Reserved.
3  * Copyright (C) 2013 Apple Inc. All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  *
26  */
27
28 #include "config.h"
29 #include "DocumentEventQueue.h"
30
31 #include "DOMWindow.h"
32 #include "Document.h"
33 #include "Event.h"
34 #include "SuspendableTimer.h"
35 #include <wtf/Ref.h>
36
37 namespace WebCore {
38     
39 class DocumentEventQueue::Timer final : public SuspendableTimer {
40 public:
41     Timer(DocumentEventQueue& eventQueue)
42         : SuspendableTimer(eventQueue.m_document)
43         , m_eventQueue(eventQueue)
44     {
45     }
46
47 private:
48     virtual void fired() override
49     {
50         ASSERT(!isSuspended());
51         m_eventQueue.pendingEventTimerFired();
52     }
53
54     const char* activeDOMObjectName() const override { return "DocumentEventQueueTimer"; }
55
56     DocumentEventQueue& m_eventQueue;
57 };
58
59 DocumentEventQueue::DocumentEventQueue(Document& document)
60     : m_document(document)
61     , m_pendingEventTimer(std::make_unique<Timer>(*this))
62     , m_isClosed(false)
63 {
64     m_pendingEventTimer->suspendIfNeeded();
65 }
66
67 DocumentEventQueue::~DocumentEventQueue()
68 {
69 }
70
71 bool DocumentEventQueue::enqueueEvent(Ref<Event>&& event)
72 {
73     ASSERT(event->target());
74     ASSERT(!m_queuedEvents.contains(event.ptr()));
75
76     if (m_isClosed)
77         return false;
78
79     m_queuedEvents.add(event.ptr());
80     if (!m_pendingEventTimer->isActive())
81         m_pendingEventTimer->startOneShot(0);
82     return true;
83 }
84
85 void DocumentEventQueue::enqueueOrDispatchScrollEvent(Node& target)
86 {
87     ASSERT(&target.document() == &m_document);
88
89     if (m_isClosed)
90         return;
91
92     if (!m_document.hasListenerType(Document::SCROLL_LISTENER))
93         return;
94
95     if (!m_nodesWithQueuedScrollEvents.add(&target).isNewEntry)
96         return;
97
98     // Per the W3C CSSOM View Module, scroll events fired at the document should bubble, others should not.
99     bool bubbles = target.isDocumentNode();
100     bool cancelable = false;
101
102     Ref<Event> scrollEvent = Event::create(eventNames().scrollEvent, bubbles, cancelable);
103     scrollEvent->setTarget(&target);
104     enqueueEvent(WTFMove(scrollEvent));
105 }
106
107 bool DocumentEventQueue::cancelEvent(Event& event)
108 {
109     bool found = m_queuedEvents.remove(&event);
110     if (m_queuedEvents.isEmpty())
111         m_pendingEventTimer->cancel();
112     return found;
113 }
114
115 void DocumentEventQueue::close()
116 {
117     m_isClosed = true;
118     m_pendingEventTimer->cancel();
119     m_queuedEvents.clear();
120 }
121
122 void DocumentEventQueue::pendingEventTimerFired()
123 {
124     ASSERT(!m_pendingEventTimer->isActive());
125     ASSERT(!m_queuedEvents.isEmpty());
126
127     m_nodesWithQueuedScrollEvents.clear();
128
129     // Insert a marker for where we should stop.
130     ASSERT(!m_queuedEvents.contains(nullptr));
131     m_queuedEvents.add(nullptr);
132
133     Ref<Document> protect(m_document);
134
135     while (!m_queuedEvents.isEmpty()) {
136         RefPtr<Event> event = m_queuedEvents.takeFirst();
137         if (!event)
138             break;
139         dispatchEvent(*event);
140     }
141 }
142
143 void DocumentEventQueue::dispatchEvent(Event& event)
144 {
145     // FIXME: Where did this special case for the DOM window come from?
146     // Why do we have this special case here instead of a virtual function on EventTarget?
147     EventTarget& eventTarget = *event.target();
148     if (DOMWindow* window = eventTarget.toDOMWindow())
149         window->dispatchEvent(event, nullptr);
150     else
151         eventTarget.dispatchEvent(event);
152 }
153
154 }