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 11namespace blink { 12 13PlatformEventDispatcher::PlatformEventDispatcher() 14 : m_needsPurge(false) 15 , m_isDispatching(false) 16{ 17} 18 19PlatformEventDispatcher::~PlatformEventDispatcher() 20{ 21} 22 23void 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 32void 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 51void 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 71void 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