Home | History | Annotate | Download | only in frame
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "config.h"
      6 #include "core/frame/PlatformEventDispatcher.h"
      7 
      8 #include "core/frame/PlatformEventController.h"
      9 #include "wtf/TemporaryChange.h"
     10 
     11 namespace blink {
     12 
     13 PlatformEventDispatcher::PlatformEventDispatcher()
     14     : m_needsPurge(false)
     15     , m_isDispatching(false)
     16 {
     17 }
     18 
     19 PlatformEventDispatcher::~PlatformEventDispatcher()
     20 {
     21 }
     22 
     23 void PlatformEventDispatcher::addController(PlatformEventController* controller)
     24 {
     25     bool wasEmpty = m_controllers.isEmpty();
     26     if (!m_controllers.contains(controller))
     27         m_controllers.append(controller);
     28     if (wasEmpty)
     29         startListening();
     30 }
     31 
     32 void PlatformEventDispatcher::removeController(PlatformEventController* controller)
     33 {
     34     // Do not actually remove the controller from the vector, instead zero them out.
     35     // The zeros are removed in these two cases:
     36     // 1. either immediately if we are not dispatching any events,
     37     // 2. or after events to all controllers have dispatched (see notifyControllers()).
     38     // This is to correctly handle the re-entrancy case when a controller is destroyed
     39     // while the events are still being dispatched.
     40     size_t index = m_controllers.find(controller);
     41     if (index == kNotFound)
     42         return;
     43 
     44     m_controllers[index] = 0;
     45     m_needsPurge = true;
     46 
     47     if (!m_isDispatching)
     48         purgeControllers();
     49 }
     50 
     51 void PlatformEventDispatcher::purgeControllers()
     52 {
     53     ASSERT(m_needsPurge);
     54 
     55     size_t i = 0;
     56     while (i < m_controllers.size()) {
     57         if (!m_controllers[i]) {
     58             m_controllers[i] = m_controllers.last();
     59             m_controllers.removeLast();
     60         } else {
     61             ++i;
     62         }
     63     }
     64 
     65     m_needsPurge = false;
     66 
     67     if (m_controllers.isEmpty())
     68         stopListening();
     69 }
     70 
     71 void PlatformEventDispatcher::notifyControllers()
     72 {
     73     {
     74         TemporaryChange<bool> changeIsDispatching(m_isDispatching, true);
     75         // Don't notify controllers removed or added during event dispatch.
     76         size_t size = m_controllers.size();
     77         for (size_t i = 0; i < size; ++i) {
     78             if (m_controllers[i])
     79                 m_controllers[i]->didUpdateData();
     80         }
     81     }
     82 
     83     if (m_needsPurge)
     84         purgeControllers();
     85 }
     86 
     87 } // namespace blink
     88