a81061a21f53c03be8251899b48e2b272d8fef75
[platform/framework/web/crosswalk.git] / src / content / browser / gamepad / gamepad_provider.h
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
22 namespace base {
23 class MessageLoopProxy;
24 class Thread;
25 }
26
27 namespace content {
28
29 class GamepadDataFetcher;
30 struct GamepadHardwareBuffer;
31
32 class 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   ~GamepadProvider() override;
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   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_