OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/gamepad/gamepad_service.h" | 5 #include "device/gamepad/gamepad_service.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/memory/singleton.h" | 12 #include "base/memory/singleton.h" |
13 #include "content/browser/gamepad/gamepad_shared_buffer_impl.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "content/common/gamepad_hardware_buffer.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
15 #include "content/public/browser/browser_thread.h" | |
16 #include "content/public/browser/render_process_host.h" | |
17 #include "device/gamepad/gamepad_consumer.h" | 15 #include "device/gamepad/gamepad_consumer.h" |
18 #include "device/gamepad/gamepad_data_fetcher.h" | 16 #include "device/gamepad/gamepad_data_fetcher.h" |
19 #include "device/gamepad/gamepad_provider.h" | 17 #include "device/gamepad/gamepad_provider.h" |
20 #include "mojo/public/cpp/system/platform_handle.h" | 18 #include "mojo/public/cpp/system/platform_handle.h" |
21 | 19 |
22 namespace content { | 20 namespace device { |
23 | 21 |
24 namespace { | 22 namespace { |
25 GamepadService* g_gamepad_service = 0; | 23 GamepadService* g_gamepad_service = 0; |
26 } | 24 } |
27 | 25 |
28 GamepadService::GamepadService() | 26 GamepadService::GamepadService() |
29 : num_active_consumers_(0), | 27 : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 28 num_active_consumers_(0), |
30 gesture_callback_pending_(false) { | 29 gesture_callback_pending_(false) { |
31 SetInstance(this); | 30 SetInstance(this); |
32 } | 31 } |
33 | 32 |
34 GamepadService::GamepadService( | 33 GamepadService::GamepadService( |
35 std::unique_ptr<device::GamepadDataFetcher> fetcher) | 34 std::unique_ptr<device::GamepadDataFetcher> fetcher) |
36 : provider_(new device::GamepadProvider( | 35 : provider_(new device::GamepadProvider(this, std::move(fetcher))), |
37 base::MakeUnique<GamepadSharedBufferImpl>(), this, std::move(fetcher))), | 36 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
38 num_active_consumers_(0), | 37 num_active_consumers_(0), |
39 gesture_callback_pending_(false) { | 38 gesture_callback_pending_(false) { |
40 SetInstance(this); | 39 SetInstance(this); |
41 thread_checker_.DetachFromThread(); | |
42 } | 40 } |
43 | 41 |
44 GamepadService::~GamepadService() { | 42 GamepadService::~GamepadService() { |
45 SetInstance(NULL); | 43 SetInstance(NULL); |
46 } | 44 } |
47 | 45 |
48 void GamepadService::SetInstance(GamepadService* instance) { | 46 void GamepadService::SetInstance(GamepadService* instance) { |
49 // Unit tests can create multiple instances but only one should exist at any | 47 // Unit tests can create multiple instances but only one should exist at any |
50 // given time so g_gamepad_service should only go from NULL to non-NULL and | 48 // given time so g_gamepad_service should only go from NULL to non-NULL and |
51 // vica versa. | 49 // vica versa. |
52 CHECK(!!instance != !!g_gamepad_service); | 50 CHECK(!!instance != !!g_gamepad_service); |
53 g_gamepad_service = instance; | 51 g_gamepad_service = instance; |
54 } | 52 } |
55 | 53 |
56 GamepadService* GamepadService::GetInstance() { | 54 GamepadService* GamepadService::GetInstance() { |
57 if (!g_gamepad_service) | 55 if (!g_gamepad_service) |
58 g_gamepad_service = new GamepadService; | 56 g_gamepad_service = new GamepadService; |
59 return g_gamepad_service; | 57 return g_gamepad_service; |
60 } | 58 } |
61 | 59 |
62 void GamepadService::ConsumerBecameActive(device::GamepadConsumer* consumer) { | 60 void GamepadService::ConsumerBecameActive(device::GamepadConsumer* consumer) { |
63 DCHECK(thread_checker_.CalledOnValidThread()); | 61 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
64 | 62 |
65 if (!provider_) | 63 if (!provider_) |
66 provider_.reset(new device::GamepadProvider( | 64 provider_.reset(new device::GamepadProvider(this)); |
67 base::MakeUnique<GamepadSharedBufferImpl>(), this)); | |
68 | 65 |
69 std::pair<ConsumerSet::iterator, bool> insert_result = | 66 std::pair<ConsumerSet::iterator, bool> insert_result = |
70 consumers_.insert(consumer); | 67 consumers_.insert(consumer); |
71 insert_result.first->is_active = true; | 68 insert_result.first->is_active = true; |
72 if (!insert_result.first->did_observe_user_gesture && | 69 if (!insert_result.first->did_observe_user_gesture && |
73 !gesture_callback_pending_) { | 70 !gesture_callback_pending_) { |
74 gesture_callback_pending_ = true; | 71 gesture_callback_pending_ = true; |
75 provider_->RegisterForUserGesture( | 72 provider_->RegisterForUserGesture( |
76 base::Bind(&GamepadService::OnUserGesture, | 73 base::Bind(&GamepadService::OnUserGesture, base::Unretained(this))); |
77 base::Unretained(this))); | |
78 } | 74 } |
79 | 75 |
80 if (num_active_consumers_++ == 0) | 76 if (num_active_consumers_++ == 0) |
81 provider_->Resume(); | 77 provider_->Resume(); |
82 } | 78 } |
83 | 79 |
84 void GamepadService::ConsumerBecameInactive(device::GamepadConsumer* consumer) { | 80 void GamepadService::ConsumerBecameInactive(device::GamepadConsumer* consumer) { |
85 DCHECK(provider_); | 81 DCHECK(provider_); |
86 DCHECK(num_active_consumers_ > 0); | 82 DCHECK(num_active_consumers_ > 0); |
87 DCHECK(consumers_.count(consumer) > 0); | 83 DCHECK(consumers_.count(consumer) > 0); |
88 DCHECK(consumers_.find(consumer)->is_active); | 84 DCHECK(consumers_.find(consumer)->is_active); |
89 | 85 |
90 consumers_.find(consumer)->is_active = false; | 86 consumers_.find(consumer)->is_active = false; |
91 if (--num_active_consumers_ == 0) | 87 if (--num_active_consumers_ == 0) |
92 provider_->Pause(); | 88 provider_->Pause(); |
93 } | 89 } |
94 | 90 |
95 void GamepadService::RemoveConsumer(device::GamepadConsumer* consumer) { | 91 void GamepadService::RemoveConsumer(device::GamepadConsumer* consumer) { |
96 DCHECK(thread_checker_.CalledOnValidThread()); | 92 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
97 | 93 |
98 ConsumerSet::iterator it = consumers_.find(consumer); | 94 ConsumerSet::iterator it = consumers_.find(consumer); |
99 if (it->is_active && --num_active_consumers_ == 0) | 95 if (it->is_active && --num_active_consumers_ == 0) |
100 provider_->Pause(); | 96 provider_->Pause(); |
101 consumers_.erase(it); | 97 consumers_.erase(it); |
102 } | 98 } |
103 | 99 |
104 void GamepadService::RegisterForUserGesture(const base::Closure& closure) { | 100 void GamepadService::RegisterForUserGesture(const base::Closure& closure) { |
105 DCHECK(consumers_.size() > 0); | 101 DCHECK(consumers_.size() > 0); |
106 DCHECK(thread_checker_.CalledOnValidThread()); | 102 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
107 provider_->RegisterForUserGesture(closure); | 103 provider_->RegisterForUserGesture(closure); |
108 } | 104 } |
109 | 105 |
110 void GamepadService::Terminate() { | 106 void GamepadService::Terminate() { |
111 provider_.reset(); | 107 provider_.reset(); |
112 } | 108 } |
113 | 109 |
114 void GamepadService::OnGamepadConnectionChange(bool connected, | 110 void GamepadService::OnGamepadConnectionChange(bool connected, |
115 int index, | 111 int index, |
116 const blink::WebGamepad& pad) { | 112 const blink::WebGamepad& pad) { |
117 if (connected) { | 113 if (connected) { |
118 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 114 main_thread_task_runner_->PostTask( |
119 base::Bind(&GamepadService::OnGamepadConnected, | 115 FROM_HERE, base::Bind(&GamepadService::OnGamepadConnected, |
120 base::Unretained(this), index, pad)); | 116 base::Unretained(this), index, pad)); |
121 } else { | 117 } else { |
122 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 118 main_thread_task_runner_->PostTask( |
123 base::Bind(&GamepadService::OnGamepadDisconnected, | 119 FROM_HERE, base::Bind(&GamepadService::OnGamepadDisconnected, |
124 base::Unretained(this), index, pad)); | 120 base::Unretained(this), index, pad)); |
125 } | 121 } |
126 } | 122 } |
127 | 123 |
128 void GamepadService::OnGamepadConnected( | 124 void GamepadService::OnGamepadConnected(int index, |
129 int index, | 125 const blink::WebGamepad& pad) { |
130 const blink::WebGamepad& pad) { | 126 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
131 DCHECK(thread_checker_.CalledOnValidThread()); | |
132 | 127 |
133 for (ConsumerSet::iterator it = consumers_.begin(); | 128 for (ConsumerSet::iterator it = consumers_.begin(); it != consumers_.end(); |
134 it != consumers_.end(); ++it) { | 129 ++it) { |
135 if (it->did_observe_user_gesture && it->is_active) | 130 if (it->did_observe_user_gesture && it->is_active) |
136 it->consumer->OnGamepadConnected(index, pad); | 131 it->consumer->OnGamepadConnected(index, pad); |
137 } | 132 } |
138 } | 133 } |
139 | 134 |
140 void GamepadService::OnGamepadDisconnected( | 135 void GamepadService::OnGamepadDisconnected(int index, |
141 int index, | 136 const blink::WebGamepad& pad) { |
142 const blink::WebGamepad& pad) { | 137 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
143 DCHECK(thread_checker_.CalledOnValidThread()); | |
144 | 138 |
145 for (ConsumerSet::iterator it = consumers_.begin(); | 139 for (ConsumerSet::iterator it = consumers_.begin(); it != consumers_.end(); |
146 it != consumers_.end(); ++it) { | 140 ++it) { |
147 if (it->did_observe_user_gesture && it->is_active) | 141 if (it->did_observe_user_gesture && it->is_active) |
148 it->consumer->OnGamepadDisconnected(index, pad); | 142 it->consumer->OnGamepadDisconnected(index, pad); |
149 } | 143 } |
150 } | 144 } |
151 | 145 |
152 base::SharedMemoryHandle GamepadService::GetSharedMemoryHandleForProcess( | 146 base::SharedMemoryHandle GamepadService::GetSharedMemoryHandleForProcess( |
153 base::ProcessHandle handle) { | 147 base::ProcessHandle handle) { |
154 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
155 return provider_->GetSharedMemoryHandleForProcess(handle); | 149 return provider_->GetSharedMemoryHandleForProcess(handle); |
156 } | 150 } |
157 | 151 |
158 mojo::ScopedSharedBufferHandle GamepadService::GetSharedBufferHandle() { | 152 mojo::ScopedSharedBufferHandle GamepadService::GetSharedBufferHandle() { |
159 DCHECK(thread_checker_.CalledOnValidThread()); | 153 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
160 | 154 |
161 // TODO(heke): Use mojo::SharedBuffer rather than base::SharedMemory in | 155 // TODO(heke): Use mojo::SharedBuffer rather than base::SharedMemory in |
162 // GamepadSharedBuffer. See crbug.com/670655 for details. | 156 // GamepadSharedBuffer. See crbug.com/670655 for details. |
163 return mojo::WrapSharedMemoryHandle(provider_->GetSharedMemoryHandle(), | 157 return mojo::WrapSharedMemoryHandle(provider_->GetSharedMemoryHandle(), |
164 sizeof(GamepadHardwareBuffer), | 158 sizeof(GamepadHardwareBuffer), |
165 true /* read_only */); | 159 true /* read_only */); |
166 } | 160 } |
167 | 161 |
168 void GamepadService::OnUserGesture() { | 162 void GamepadService::OnUserGesture() { |
169 DCHECK(thread_checker_.CalledOnValidThread()); | 163 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
170 | 164 |
171 gesture_callback_pending_ = false; | 165 gesture_callback_pending_ = false; |
172 | 166 |
173 if (!provider_ || | 167 if (!provider_ || num_active_consumers_ == 0) |
174 num_active_consumers_ == 0) | |
175 return; | 168 return; |
176 | 169 |
177 for (ConsumerSet::iterator it = consumers_.begin(); | 170 for (ConsumerSet::iterator it = consumers_.begin(); it != consumers_.end(); |
178 it != consumers_.end(); ++it) { | 171 ++it) { |
179 if (!it->did_observe_user_gesture && it->is_active) { | 172 if (!it->did_observe_user_gesture && it->is_active) { |
180 const ConsumerInfo& info = *it; | 173 const ConsumerInfo& info = *it; |
181 info.did_observe_user_gesture = true; | 174 info.did_observe_user_gesture = true; |
182 blink::WebGamepads gamepads; | 175 blink::WebGamepads gamepads; |
183 provider_->GetCurrentGamepadData(&gamepads); | 176 provider_->GetCurrentGamepadData(&gamepads); |
184 for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { | 177 for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { |
185 const blink::WebGamepad& pad = gamepads.items[i]; | 178 const blink::WebGamepad& pad = gamepads.items[i]; |
186 if (pad.connected) | 179 if (pad.connected) |
187 info.consumer->OnGamepadConnected(i, pad); | 180 info.consumer->OnGamepadConnected(i, pad); |
188 } | 181 } |
189 } | 182 } |
190 } | 183 } |
191 } | 184 } |
192 | 185 |
193 void GamepadService::SetSanitizationEnabled(bool sanitize) { | 186 void GamepadService::SetSanitizationEnabled(bool sanitize) { |
194 provider_->SetSanitizationEnabled(sanitize); | 187 provider_->SetSanitizationEnabled(sanitize); |
195 } | 188 } |
196 | 189 |
197 } // namespace content | 190 } // namespace device |
OLD | NEW |