| 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 |