1 /* 2 * Copyright 2010, The Android Open Source Project 3 * Copyright (C) 2012 Samsung Electronics. 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. AND ITS CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "core/page/DeviceController.h" 29 30 #include "core/dom/Document.h" 31 #include "core/page/DeviceClient.h" 32 33 namespace WebCore { 34 35 // FIXME: Another alternative is to update copyToVector in HashCountedSet to allow the source 36 // and destination types to differ it the source type is convertible to the destination type. 37 Vector<RefPtr<DOMWindow> > copyKeysToReferencingVector(const HashCountedSet<DOMWindow*>& set) 38 { 39 Vector<RefPtr<DOMWindow> > vector; 40 vector.reserveCapacity(set.size()); 41 42 HashCountedSet<DOMWindow*>::const_iterator end= set.end(); 43 for (HashCountedSet<DOMWindow*>::const_iterator it = set.begin(); it != end; ++it) 44 vector.append((*it).key); 45 return vector; 46 } 47 48 DeviceController::DeviceController(DeviceClient* client) 49 : m_client(client) 50 , m_timer(this, &DeviceController::fireDeviceEvent) 51 { 52 ASSERT(m_client); 53 } 54 55 void DeviceController::addDeviceEventListener(DOMWindow* window) 56 { 57 bool wasEmpty = m_listeners.isEmpty(); 58 m_listeners.add(window); 59 60 if (hasLastData()) { 61 m_lastEventListeners.add(window); 62 if (!m_timer.isActive()) 63 m_timer.startOneShot(0); 64 } 65 66 if (wasEmpty) 67 m_client->startUpdating(); 68 } 69 70 void DeviceController::removeDeviceEventListener(DOMWindow* window) 71 { 72 m_listeners.remove(window); 73 m_lastEventListeners.remove(window); 74 if (m_listeners.isEmpty()) 75 m_client->stopUpdating(); 76 } 77 78 void DeviceController::removeAllDeviceEventListeners(DOMWindow* window) 79 { 80 m_listeners.removeAll(window); 81 m_lastEventListeners.removeAll(window); 82 if (m_listeners.isEmpty()) 83 m_client->stopUpdating(); 84 } 85 86 void DeviceController::dispatchDeviceEvent(PassRefPtr<Event> prpEvent) 87 { 88 RefPtr<Event> event = prpEvent; 89 Vector<RefPtr<DOMWindow> > listenerVector = copyKeysToReferencingVector(m_listeners); 90 for (size_t i = 0; i < listenerVector.size(); ++i) { 91 if (listenerVector[i]->document() 92 && !listenerVector[i]->document()->activeDOMObjectsAreSuspended() 93 && !listenerVector[i]->document()->activeDOMObjectsAreStopped()) 94 listenerVector[i]->dispatchEvent(event); 95 } 96 } 97 98 void DeviceController::fireDeviceEvent(Timer<DeviceController>* timer) 99 { 100 ASSERT_UNUSED(timer, timer == &m_timer); 101 ASSERT(hasLastData()); 102 103 m_timer.stop(); 104 Vector<RefPtr<DOMWindow> > listenerVector = copyKeysToReferencingVector(m_lastEventListeners); 105 m_lastEventListeners.clear(); 106 for (size_t i = 0; i < listenerVector.size(); ++i) { 107 if (listenerVector[i]->document() 108 && !listenerVector[i]->document()->activeDOMObjectsAreSuspended() 109 && !listenerVector[i]->document()->activeDOMObjectsAreStopped()) 110 listenerVector[i]->dispatchEvent(getLastEvent()); 111 } 112 } 113 114 } // namespace WebCore 115