1// Copyright (c) 2012 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#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_ 6#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_ 7 8#include <utility> 9#include <vector> 10 11#include "base/callback_forward.h" 12#include "base/memory/ref_counted.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/memory/shared_memory.h" 15#include "base/memory/weak_ptr.h" 16#include "base/message_loop/message_loop_proxy.h" 17#include "base/synchronization/lock.h" 18#include "base/system_monitor/system_monitor.h" 19#include "content/common/content_export.h" 20#include "third_party/WebKit/public/platform/WebGamepads.h" 21 22namespace base { 23class MessageLoopProxy; 24class Thread; 25} 26 27namespace content { 28 29class GamepadDataFetcher; 30struct GamepadHardwareBuffer; 31 32class CONTENT_EXPORT GamepadProvider : 33 public base::SystemMonitor::DevicesChangedObserver { 34 public: 35 GamepadProvider(); 36 37 // Manually specifies the data fetcher. Used for testing. 38 explicit GamepadProvider(scoped_ptr<GamepadDataFetcher> fetcher); 39 40 virtual ~GamepadProvider(); 41 42 // Returns the shared memory handle of the gamepad data duplicated into the 43 // given process. 44 base::SharedMemoryHandle GetSharedMemoryHandleForProcess( 45 base::ProcessHandle renderer_process); 46 47 void GetCurrentGamepadData(blink::WebGamepads* data); 48 49 // Pause and resume the background polling thread. Can be called from any 50 // thread. 51 void Pause(); 52 void Resume(); 53 54 // Registers the given closure for calling when the user has interacted with 55 // the device. This callback will only be issued once. 56 void RegisterForUserGesture(const base::Closure& closure); 57 58 // base::SystemMonitor::DevicesChangedObserver implementation. 59 virtual void OnDevicesChanged(base::SystemMonitor::DeviceType type) OVERRIDE; 60 61 private: 62 void Initialize(scoped_ptr<GamepadDataFetcher> fetcher); 63 64 // Method for setting up the platform-specific data fetcher. Takes ownership 65 // of |fetcher|. 66 void DoInitializePollingThread(scoped_ptr<GamepadDataFetcher> fetcher); 67 68 // Method for sending pause hints to the low-level data fetcher. Runs on 69 // polling_thread_. 70 void SendPauseHint(bool paused); 71 72 // Method for polling a GamepadDataFetcher. Runs on the polling_thread_. 73 void DoPoll(); 74 void ScheduleDoPoll(); 75 76 void OnGamepadConnectionChange(bool connected, 77 int index, 78 const blink::WebGamepad& pad); 79 void DispatchGamepadConnectionChange(bool connected, 80 int index, 81 const blink::WebGamepad& pad); 82 83 GamepadHardwareBuffer* SharedMemoryAsHardwareBuffer(); 84 85 // Checks the gamepad state to see if the user has interacted with it. 86 void CheckForUserGesture(); 87 88 enum { kDesiredSamplingIntervalMs = 16 }; 89 90 // Keeps track of when the background thread is paused. Access to is_paused_ 91 // must be guarded by is_paused_lock_. 92 base::Lock is_paused_lock_; 93 bool is_paused_; 94 95 // Keep track of when a polling task is schedlued, so as to prevent us from 96 // accidentally scheduling more than one at any time, when rapidly toggling 97 // |is_paused_|. 98 bool have_scheduled_do_poll_; 99 100 // Lists all observers registered for user gestures, and the thread which 101 // to issue the callbacks on. Since we always issue the callback on the 102 // thread which the registration happened, and this class lives on the I/O 103 // thread, the message loop proxies will normally just be the I/O thread. 104 // However, this will be the main thread for unit testing. 105 base::Lock user_gesture_lock_; 106 struct ClosureAndThread { 107 ClosureAndThread(const base::Closure& c, 108 const scoped_refptr<base::MessageLoopProxy>& m); 109 ~ClosureAndThread(); 110 111 base::Closure closure; 112 scoped_refptr<base::MessageLoopProxy> message_loop; 113 }; 114 typedef std::vector<ClosureAndThread> UserGestureObserverVector; 115 UserGestureObserverVector user_gesture_observers_; 116 117 // Updated based on notification from SystemMonitor when the system devices 118 // have been updated, and this notification is passed on to the data fetcher 119 // to enable it to avoid redundant (and possibly expensive) is-connected 120 // tests. Access to devices_changed_ must be guarded by 121 // devices_changed_lock_. 122 base::Lock devices_changed_lock_; 123 bool devices_changed_; 124 125 bool ever_had_user_gesture_; 126 127 class PadState { 128 public: 129 PadState() { 130 SetDisconnected(); 131 } 132 133 bool Match(const blink::WebGamepad& pad) const; 134 void SetPad(const blink::WebGamepad& pad); 135 void SetDisconnected(); 136 void AsWebGamepad(blink::WebGamepad* pad); 137 138 bool connected() const { return connected_; } 139 140 private: 141 bool connected_; 142 unsigned axes_length_; 143 unsigned buttons_length_; 144 blink::WebUChar id_[blink::WebGamepad::idLengthCap]; 145 blink::WebUChar mapping_[blink::WebGamepad::mappingLengthCap]; 146 }; 147 148 // Used to detect connections and disconnections. 149 scoped_ptr<PadState[]> pad_states_; 150 151 // Only used on the polling thread. 152 scoped_ptr<GamepadDataFetcher> data_fetcher_; 153 154 base::Lock shared_memory_lock_; 155 base::SharedMemory gamepad_shared_memory_; 156 157 // Polling is done on this background thread. 158 scoped_ptr<base::Thread> polling_thread_; 159 160 static GamepadProvider* instance_; 161 162 DISALLOW_COPY_AND_ASSIGN(GamepadProvider); 163}; 164 165} // namespace content 166 167#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_ 168