| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2011, Google Inc. All rights reserved. | 2  * Copyright (C) 2011, Google Inc. All rights reserved. | 
| 3  * | 3  * | 
| 4  * Redistribution and use in source and binary forms, with or without | 4  * Redistribution and use in source and binary forms, with or without | 
| 5  * modification, are permitted provided that the following conditions are met: | 5  * modification, are permitted provided that the following conditions are met: | 
| 6  * | 6  * | 
| 7  * 1. Redistributions of source code must retain the above copyright | 7  * 1. Redistributions of source code must retain the above copyright | 
| 8  *    notice, this list of conditions and the following disclaimer. | 8  *    notice, this list of conditions and the following disclaimer. | 
| 9  * 2. Redistributions in binary form must reproduce the above copyright | 9  * 2. Redistributions in binary form must reproduce the above copyright | 
| 10  *    notice, this list of conditions and the following disclaimer in the | 10  *    notice, this list of conditions and the following disclaimer in the | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 29 #include "RuntimeEnabledFeatures.h" | 29 #include "RuntimeEnabledFeatures.h" | 
| 30 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" | 
| 31 #include "core/frame/DOMWindow.h" | 31 #include "core/frame/DOMWindow.h" | 
| 32 #include "core/frame/LocalFrame.h" | 32 #include "core/frame/LocalFrame.h" | 
| 33 #include "core/frame/Navigator.h" | 33 #include "core/frame/Navigator.h" | 
| 34 #include "core/page/Page.h" | 34 #include "core/page/Page.h" | 
| 35 #include "modules/gamepad/GamepadDispatcher.h" | 35 #include "modules/gamepad/GamepadDispatcher.h" | 
| 36 #include "modules/gamepad/GamepadEvent.h" | 36 #include "modules/gamepad/GamepadEvent.h" | 
| 37 #include "modules/gamepad/GamepadList.h" | 37 #include "modules/gamepad/GamepadList.h" | 
| 38 #include "modules/gamepad/WebKitGamepadList.h" | 38 #include "modules/gamepad/WebKitGamepadList.h" | 
|  | 39 #include "wtf/TemporaryChange.h" | 
| 39 | 40 | 
| 40 namespace WebCore { | 41 namespace WebCore { | 
| 41 | 42 | 
| 42 template<typename T> | 43 template<typename T> | 
| 43 static void sampleGamepad(unsigned index, T& gamepad, const blink::WebGamepad& w
     ebGamepad) | 44 static void sampleGamepad(unsigned index, T& gamepad, const blink::WebGamepad& w
     ebGamepad) | 
| 44 { | 45 { | 
| 45     gamepad.setId(webGamepad.id); | 46     gamepad.setId(webGamepad.id); | 
| 46     gamepad.setIndex(index); | 47     gamepad.setIndex(index); | 
| 47     gamepad.setConnected(webGamepad.connected); | 48     gamepad.setConnected(webGamepad.connected); | 
| 48     gamepad.setTimestamp(webGamepad.timestamp); | 49     gamepad.setTimestamp(webGamepad.timestamp); | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 127     visitor->trace(m_gamepads); | 128     visitor->trace(m_gamepads); | 
| 128     visitor->trace(m_webkitGamepads); | 129     visitor->trace(m_webkitGamepads); | 
| 129     WillBeHeapSupplement<Navigator>::trace(visitor); | 130     WillBeHeapSupplement<Navigator>::trace(visitor); | 
| 130 } | 131 } | 
| 131 | 132 | 
| 132 void NavigatorGamepad::didConnectOrDisconnectGamepad(unsigned index, const blink
     ::WebGamepad& webGamepad, bool connected) | 133 void NavigatorGamepad::didConnectOrDisconnectGamepad(unsigned index, const blink
     ::WebGamepad& webGamepad, bool connected) | 
| 133 { | 134 { | 
| 134     ASSERT(index < blink::WebGamepads::itemsLengthCap); | 135     ASSERT(index < blink::WebGamepads::itemsLengthCap); | 
| 135     ASSERT(connected == webGamepad.connected); | 136     ASSERT(connected == webGamepad.connected); | 
| 136 | 137 | 
| 137     // We should stop listening once we detached. |  | 
| 138     ASSERT(window()); |  | 
| 139 |  | 
| 140     // We register to the dispatcher before sampling gamepads so we need to chec
     k if we actually have an event listener. | 138     // We register to the dispatcher before sampling gamepads so we need to chec
     k if we actually have an event listener. | 
| 141     if (!m_hasEventListener) | 139     if (!m_hasEventListener) | 
| 142         return; | 140         return; | 
| 143 | 141 | 
| 144     if (window()->document()->activeDOMObjectsAreStopped() || window()->document
     ()->activeDOMObjectsAreSuspended()) |  | 
| 145         return; |  | 
| 146 |  | 
| 147     if (!m_gamepads) | 142     if (!m_gamepads) | 
| 148         m_gamepads = GamepadList::create(); | 143         m_gamepads = GamepadList::create(); | 
| 149 | 144 | 
| 150     Gamepad* gamepad = m_gamepads->item(index); | 145     Gamepad* gamepad = m_gamepads->item(index); | 
| 151     if (!gamepad) | 146     if (!gamepad) | 
| 152         gamepad = Gamepad::create(); | 147         gamepad = Gamepad::create(); | 
| 153     sampleGamepad(index, *gamepad, webGamepad); | 148     sampleGamepad(index, *gamepad, webGamepad); | 
| 154     m_gamepads->set(index, gamepad); | 149     m_gamepads->set(index, gamepad); | 
| 155 | 150 | 
| 156     const AtomicString& eventName = connected ? EventTypeNames::gamepadconnected
      : EventTypeNames::gamepaddisconnected; | 151     const AtomicString& eventName = connected ? EventTypeNames::gamepadconnected
      : EventTypeNames::gamepaddisconnected; | 
| 157     RefPtrWillBeRawPtr<GamepadEvent> event = GamepadEvent::create(eventName, fal
     se, true, gamepad); | 152     dispatchDeviceEvent(GamepadEvent::create(eventName, false, true, gamepad)); | 
| 158     window()->dispatchEvent(event); |  | 
| 159 } | 153 } | 
| 160 | 154 | 
| 161 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) | 155 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) | 
| 162     : DOMWindowProperty(frame) | 156     : DOMWindowProperty(frame) | 
| 163     , DeviceSensorEventController(frame ? frame->page() : 0) | 157     , DeviceSensorEventController(frame ? frame->page() : 0) | 
| 164     , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) | 158     , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) | 
|  | 159     , m_canContinueDispatchingSentinelPtr(0) | 
| 165 { | 160 { | 
| 166 } | 161 } | 
| 167 | 162 | 
| 168 NavigatorGamepad::~NavigatorGamepad() | 163 NavigatorGamepad::~NavigatorGamepad() | 
| 169 { | 164 { | 
| 170 } | 165 } | 
| 171 | 166 | 
| 172 const char* NavigatorGamepad::supplementName() | 167 const char* NavigatorGamepad::supplementName() | 
| 173 { | 168 { | 
| 174     return "NavigatorGamepad"; | 169     return "NavigatorGamepad"; | 
| 175 } | 170 } | 
| 176 | 171 | 
| 177 void NavigatorGamepad::willDestroyGlobalObjectInFrame() | 172 void NavigatorGamepad::willDestroyGlobalObjectInFrame() | 
| 178 { | 173 { | 
| 179     stopUpdating(); | 174     stopUpdating(); | 
|  | 175     invalidateCanContinueDispatchingSentinel(); | 
| 180     DOMWindowProperty::willDestroyGlobalObjectInFrame(); | 176     DOMWindowProperty::willDestroyGlobalObjectInFrame(); | 
| 181 } | 177 } | 
| 182 | 178 | 
| 183 void NavigatorGamepad::willDetachGlobalObjectFromFrame() | 179 void NavigatorGamepad::willDetachGlobalObjectFromFrame() | 
| 184 { | 180 { | 
| 185     stopUpdating(); | 181     stopUpdating(); | 
|  | 182     invalidateCanContinueDispatchingSentinel(); | 
| 186     DOMWindowProperty::willDetachGlobalObjectFromFrame(); | 183     DOMWindowProperty::willDetachGlobalObjectFromFrame(); | 
| 187 } | 184 } | 
| 188 | 185 | 
| 189 void NavigatorGamepad::registerWithDispatcher() | 186 void NavigatorGamepad::registerWithDispatcher() | 
| 190 { | 187 { | 
| 191     GamepadDispatcher::instance().addClient(this); | 188     GamepadDispatcher::instance().addClient(this); | 
| 192 } | 189 } | 
| 193 | 190 | 
| 194 void NavigatorGamepad::unregisterWithDispatcher() | 191 void NavigatorGamepad::unregisterWithDispatcher() | 
| 195 { | 192 { | 
| 196     GamepadDispatcher::instance().removeClient(this); | 193     GamepadDispatcher::instance().removeClient(this); | 
| 197 } | 194 } | 
| 198 | 195 | 
| 199 bool NavigatorGamepad::hasLastData() | 196 bool NavigatorGamepad::hasLastData() | 
| 200 { | 197 { | 
| 201     // Gamepad data is polled instead of pushed. | 198     // Gamepad data is polled instead of pushed. | 
| 202     return false; | 199     return false; | 
| 203 } | 200 } | 
| 204 | 201 | 
| 205 PassRefPtrWillBeRawPtr<Event> NavigatorGamepad::getLastEvent() | 202 PassRefPtrWillBeRawPtr<Event> NavigatorGamepad::getLastEvent() | 
| 206 { | 203 { | 
| 207     // This is called only when hasLastData() is true. | 204     // This is called only when hasLastData() is true. | 
| 208     ASSERT_NOT_REACHED(); | 205     ASSERT_NOT_REACHED(); | 
| 209     return nullptr; | 206     return nullptr; | 
| 210 } | 207 } | 
| 211 | 208 | 
| 212 bool NavigatorGamepad::isNullEvent(Event*) | 209 bool NavigatorGamepad::isNullEvent(Event*) | 
| 213 { | 210 { | 
| 214     // This is called only when hasLastData() is true. |  | 
| 215     ASSERT_NOT_REACHED(); |  | 
| 216     return false; | 211     return false; | 
| 217 } | 212 } | 
| 218 | 213 | 
| 219 Document* NavigatorGamepad::document() | 214 Document* NavigatorGamepad::document() | 
| 220 { | 215 { | 
| 221     return window() ? window()->document() : 0; | 216     return window() ? window()->document() : 0; | 
| 222 } | 217 } | 
| 223 | 218 | 
| 224 static bool isGamepadEvent(const AtomicString& eventType) | 219 static bool isGamepadEvent(const AtomicString& eventType) | 
| 225 { | 220 { | 
| 226     return eventType == EventTypeNames::gamepadconnected || eventType == EventTy
     peNames::gamepaddisconnected; | 221     return eventType == EventTypeNames::gamepadconnected || eventType == EventTy
     peNames::gamepaddisconnected; | 
| 227 } | 222 } | 
| 228 | 223 | 
| 229 void NavigatorGamepad::didAddEventListener(DOMWindow*, const AtomicString& event
     Type) | 224 void NavigatorGamepad::didAddEventListener(DOMWindow*, const AtomicString& event
     Type) | 
| 230 { | 225 { | 
| 231     if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) { | 226     if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) { | 
| 232         if (page() && page()->visibilityState() == PageVisibilityStateVisible) | 227         if (page() && page()->visibilityState() == PageVisibilityStateVisible) | 
| 233             startUpdating(); | 228             startUpdating(); | 
| 234         m_hasEventListener = true; | 229         m_hasEventListener = true; | 
| 235     } | 230     } | 
| 236 } | 231 } | 
| 237 | 232 | 
| 238 void NavigatorGamepad::didRemoveEventListener(DOMWindow*, const AtomicString& ev
     entType) | 233 void NavigatorGamepad::didRemoveEventListener(DOMWindow* window, const AtomicStr
     ing& eventType) | 
| 239 { | 234 { | 
| 240     if (isGamepadEvent(eventType)) | 235     if (!isGamepadEvent(eventType) || window->hasEventListeners(EventTypeNames::
     gamepadconnected) || window->hasEventListeners(EventTypeNames::gamepaddisconnect
     ed)) | 
| 241         m_hasEventListener = false; | 236         return; | 
|  | 237     m_hasEventListener = false; | 
| 242 } | 238 } | 
| 243 | 239 | 
| 244 void NavigatorGamepad::didRemoveAllEventListeners(DOMWindow*) | 240 void NavigatorGamepad::didRemoveAllEventListeners(DOMWindow*) | 
| 245 { | 241 { | 
| 246     m_hasEventListener = false; | 242     m_hasEventListener = false; | 
| 247 } | 243 } | 
| 248 | 244 | 
|  | 245 void NavigatorGamepad::willBeDestroyed() | 
|  | 246 { | 
|  | 247     invalidateCanContinueDispatchingSentinel(); | 
|  | 248 } | 
|  | 249 | 
|  | 250 void NavigatorGamepad::pageVisibilityChanged() | 
|  | 251 { | 
|  | 252     DeviceSensorEventController::pageVisibilityChanged(); | 
|  | 253 | 
|  | 254     if (page()->visibilityState() != PageVisibilityStateVisible || !m_hasEventLi
     stener) | 
|  | 255         return; | 
|  | 256 | 
|  | 257     // Tell the page what has changed. m_gamepads contains the state before we b
     ecame hidden. | 
|  | 258     // We create a new snapshot and compare them. | 
|  | 259     GamepadList* oldGamepads = m_gamepads.release(); | 
|  | 260     gamepads(); | 
|  | 261     GamepadList* newGamepads = m_gamepads.get(); | 
|  | 262     ASSERT(newGamepads); | 
|  | 263 | 
|  | 264     // Set m_gamepads to null so that if we are polled while dispatching it does
     n't mess up our snapshot. | 
|  | 265     // After we are done, set it back to the new snapshot otherwise we could rep
     ort these changes multiple | 
|  | 266     // times after we go hidden and then visible again. | 
|  | 267     WTF::TemporaryChange<PersistentWillBeMember<GamepadList> > padsScope(m_gamep
     ads, nullptr); | 
|  | 268 | 
|  | 269     // We need to dispatch multiple events to the page and we have to deal with 
     the fact that we can be destroyed by the event handler. | 
|  | 270     // We use a fancy version of the protecting RefPtr idiom because Supplement'
     s are not RefCounted. Before we die we change the value | 
|  | 271     // of a local variable via our member pointer. After dispatching the event w
     e check this local variable which is safe even if we have died. | 
|  | 272     // TODO(b.kelemen): simplify this when we can rely on Oilpan. | 
|  | 273     bool canContinueDispatchingSentinel = true; | 
|  | 274     WTF::TemporaryChange<bool*> sentinelScope(m_canContinueDispatchingSentinelPt
     r, &canContinueDispatchingSentinel); | 
|  | 275 | 
|  | 276     for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { | 
|  | 277         Gamepad* oldGamepad = oldGamepads ? oldGamepads->item(i) : 0; | 
|  | 278         Gamepad* newGamepad = newGamepads->item(i); | 
|  | 279         bool oldWasConnected = oldGamepad && oldGamepad->connected(); | 
|  | 280         bool newIsConnected = newGamepad && newGamepad->connected(); | 
|  | 281         bool connectedGamepadChanged = oldWasConnected && newIsConnected && oldG
     amepad->id() != newGamepad->id(); | 
|  | 282 | 
|  | 283         if (connectedGamepadChanged || (oldWasConnected && !newIsConnected)) { | 
|  | 284             const AtomicString& eventName = EventTypeNames::gamepaddisconnected; | 
|  | 285             dispatchDeviceEvent(GamepadEvent::create(eventName, false, true, old
     Gamepad)); | 
|  | 286             if (!canContinueDispatchingSentinel || !m_hasEventListener) | 
|  | 287                 return; | 
|  | 288         } | 
|  | 289         if (connectedGamepadChanged || (!oldWasConnected && newIsConnected)) { | 
|  | 290             const AtomicString& eventName = EventTypeNames::gamepadconnected; | 
|  | 291             dispatchDeviceEvent(GamepadEvent::create(eventName, false, true, new
     Gamepad)); | 
|  | 292             if (!canContinueDispatchingSentinel || !m_hasEventListener) | 
|  | 293                 return; | 
|  | 294         } | 
|  | 295     } | 
|  | 296 } | 
|  | 297 | 
|  | 298 void NavigatorGamepad::invalidateCanContinueDispatchingSentinel() | 
|  | 299 { | 
|  | 300     if (m_canContinueDispatchingSentinelPtr) | 
|  | 301         *m_canContinueDispatchingSentinelPtr = false; | 
|  | 302 } | 
|  | 303 | 
| 249 } // namespace WebCore | 304 } // namespace WebCore | 
| OLD | NEW | 
|---|