Home | History | Annotate | Download | only in events
      1 /*
      2  * Copyright (C) 2010 Google Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  *
     25  */
     26 
     27 #include "config.h"
     28 #include "core/events/DOMWindowEventQueue.h"
     29 
     30 #include "core/events/Event.h"
     31 #include "core/frame/LocalDOMWindow.h"
     32 #include "core/frame/SuspendableTimer.h"
     33 #include "core/inspector/InspectorInstrumentation.h"
     34 
     35 namespace blink {
     36 
     37 class DOMWindowEventQueueTimer : public NoBaseWillBeGarbageCollectedFinalized<DOMWindowEventQueueTimer>, public SuspendableTimer {
     38     WTF_MAKE_NONCOPYABLE(DOMWindowEventQueueTimer);
     39 public:
     40     DOMWindowEventQueueTimer(DOMWindowEventQueue* eventQueue, ExecutionContext* context)
     41         : SuspendableTimer(context)
     42         , m_eventQueue(eventQueue) { }
     43     void trace(Visitor* visitor) { visitor->trace(m_eventQueue); }
     44 
     45 private:
     46     virtual void fired() { m_eventQueue->pendingEventTimerFired(); }
     47 
     48     RawPtrWillBeMember<DOMWindowEventQueue> m_eventQueue;
     49 };
     50 
     51 PassRefPtrWillBeRawPtr<DOMWindowEventQueue> DOMWindowEventQueue::create(ExecutionContext* context)
     52 {
     53     return adoptRefWillBeNoop(new DOMWindowEventQueue(context));
     54 }
     55 
     56 DOMWindowEventQueue::DOMWindowEventQueue(ExecutionContext* context)
     57     : m_pendingEventTimer(adoptPtrWillBeNoop(new DOMWindowEventQueueTimer(this, context)))
     58     , m_isClosed(false)
     59 {
     60     m_pendingEventTimer->suspendIfNeeded();
     61 }
     62 
     63 DOMWindowEventQueue::~DOMWindowEventQueue()
     64 {
     65 }
     66 
     67 void DOMWindowEventQueue::trace(Visitor* visitor)
     68 {
     69 #if ENABLE(OILPAN)
     70     visitor->trace(m_pendingEventTimer);
     71     visitor->trace(m_queuedEvents);
     72 #endif
     73     EventQueue::trace(visitor);
     74 }
     75 
     76 bool DOMWindowEventQueue::enqueueEvent(PassRefPtrWillBeRawPtr<Event> event)
     77 {
     78     if (m_isClosed)
     79         return false;
     80 
     81     ASSERT(event->target());
     82     InspectorInstrumentation::didEnqueueEvent(event->target(), event.get());
     83 
     84     bool wasAdded = m_queuedEvents.add(event).isNewEntry;
     85     ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list.
     86 
     87     if (!m_pendingEventTimer->isActive())
     88         m_pendingEventTimer->startOneShot(0, FROM_HERE);
     89 
     90     return true;
     91 }
     92 
     93 bool DOMWindowEventQueue::cancelEvent(Event* event)
     94 {
     95     WillBeHeapListHashSet<RefPtrWillBeMember<Event>, 16>::iterator it = m_queuedEvents.find(event);
     96     bool found = it != m_queuedEvents.end();
     97     if (found) {
     98         InspectorInstrumentation::didRemoveEvent(event->target(), event);
     99         m_queuedEvents.remove(it);
    100     }
    101     if (m_queuedEvents.isEmpty())
    102         m_pendingEventTimer->stop();
    103     return found;
    104 }
    105 
    106 void DOMWindowEventQueue::close()
    107 {
    108     m_isClosed = true;
    109     m_pendingEventTimer->stop();
    110     if (InspectorInstrumentation::hasFrontends()) {
    111         WillBeHeapListHashSet<RefPtrWillBeMember<Event>, 16>::iterator it = m_queuedEvents.begin();
    112         for (; it != m_queuedEvents.end(); ++it) {
    113             RefPtrWillBeRawPtr<Event> event = *it;
    114             if (event)
    115                 InspectorInstrumentation::didRemoveEvent(event->target(), event.get());
    116         }
    117     }
    118     m_queuedEvents.clear();
    119 }
    120 
    121 void DOMWindowEventQueue::pendingEventTimerFired()
    122 {
    123     ASSERT(!m_pendingEventTimer->isActive());
    124     ASSERT(!m_queuedEvents.isEmpty());
    125 
    126     // Insert a marker for where we should stop.
    127     ASSERT(!m_queuedEvents.contains(nullptr));
    128     bool wasAdded = m_queuedEvents.add(nullptr).isNewEntry;
    129     ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list.
    130 
    131     RefPtrWillBeRawPtr<DOMWindowEventQueue> protector(this);
    132 
    133     while (!m_queuedEvents.isEmpty()) {
    134         WillBeHeapListHashSet<RefPtrWillBeMember<Event>, 16>::iterator iter = m_queuedEvents.begin();
    135         RefPtrWillBeRawPtr<Event> event = *iter;
    136         m_queuedEvents.remove(iter);
    137         if (!event)
    138             break;
    139         dispatchEvent(event.get());
    140         InspectorInstrumentation::didRemoveEvent(event->target(), event.get());
    141     }
    142 }
    143 
    144 void DOMWindowEventQueue::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
    145 {
    146     EventTarget* eventTarget = event->target();
    147     if (eventTarget->toDOMWindow())
    148         eventTarget->toDOMWindow()->dispatchEvent(event, nullptr);
    149     else
    150         eventTarget->dispatchEvent(event);
    151 }
    152 
    153 }
    154