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.
5 #include "content/browser/gamepad/gamepad_service.h"
8 #include "base/logging.h"
9 #include "base/memory/singleton.h"
10 #include "content/browser/gamepad/gamepad_consumer.h"
11 #include "content/browser/gamepad/gamepad_data_fetcher.h"
12 #include "content/browser/gamepad/gamepad_provider.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/render_process_host.h"
19 GamepadService
* g_gamepad_service
= 0;
22 GamepadService::GamepadService()
23 : num_active_consumers_(0),
24 gesture_callback_pending_(false) {
28 GamepadService::GamepadService(scoped_ptr
<GamepadDataFetcher
> fetcher
)
29 : provider_(new GamepadProvider(fetcher
.Pass())),
30 num_active_consumers_(0),
31 gesture_callback_pending_(false) {
33 thread_checker_
.DetachFromThread();
36 GamepadService::~GamepadService() {
40 void GamepadService::SetInstance(GamepadService
* instance
) {
41 // Unit tests can create multiple instances but only one should exist at any
42 // given time so g_gamepad_service should only go from NULL to non-NULL and
44 CHECK(!!instance
!= !!g_gamepad_service
);
45 g_gamepad_service
= instance
;
48 GamepadService
* GamepadService::GetInstance() {
49 if (!g_gamepad_service
)
50 g_gamepad_service
= new GamepadService
;
51 return g_gamepad_service
;
54 void GamepadService::ConsumerBecameActive(GamepadConsumer
* consumer
) {
55 DCHECK(thread_checker_
.CalledOnValidThread());
58 provider_
.reset(new GamepadProvider
);
60 std::pair
<ConsumerSet::iterator
, bool> insert_result
=
61 consumers_
.insert(consumer
);
62 insert_result
.first
->is_active
= true;
63 if (!insert_result
.first
->did_observe_user_gesture
&&
64 !gesture_callback_pending_
) {
65 gesture_callback_pending_
= true;
66 provider_
->RegisterForUserGesture(
67 base::Bind(&GamepadService::OnUserGesture
,
68 base::Unretained(this)));
71 if (num_active_consumers_
++ == 0)
75 void GamepadService::ConsumerBecameInactive(GamepadConsumer
* consumer
) {
77 DCHECK(num_active_consumers_
> 0);
78 DCHECK(consumers_
.count(consumer
) > 0);
79 DCHECK(consumers_
.find(consumer
)->is_active
);
81 consumers_
.find(consumer
)->is_active
= false;
82 if (--num_active_consumers_
== 0)
86 void GamepadService::RemoveConsumer(GamepadConsumer
* consumer
) {
87 DCHECK(thread_checker_
.CalledOnValidThread());
89 ConsumerSet::iterator it
= consumers_
.find(consumer
);
90 if (it
->is_active
&& --num_active_consumers_
== 0)
95 void GamepadService::RegisterForUserGesture(const base::Closure
& closure
) {
96 DCHECK(consumers_
.size() > 0);
97 DCHECK(thread_checker_
.CalledOnValidThread());
98 provider_
->RegisterForUserGesture(closure
);
101 void GamepadService::Terminate() {
105 void GamepadService::OnGamepadConnected(
107 const blink::WebGamepad
& pad
) {
108 DCHECK(thread_checker_
.CalledOnValidThread());
110 for (ConsumerSet::iterator it
= consumers_
.begin();
111 it
!= consumers_
.end(); ++it
) {
112 if (it
->did_observe_user_gesture
&& it
->is_active
)
113 it
->consumer
->OnGamepadConnected(index
, pad
);
117 void GamepadService::OnGamepadDisconnected(
119 const blink::WebGamepad
& pad
) {
120 DCHECK(thread_checker_
.CalledOnValidThread());
122 for (ConsumerSet::iterator it
= consumers_
.begin();
123 it
!= consumers_
.end(); ++it
) {
124 if (it
->did_observe_user_gesture
&& it
->is_active
)
125 it
->consumer
->OnGamepadDisconnected(index
, pad
);
129 base::SharedMemoryHandle
GamepadService::GetSharedMemoryHandleForProcess(
130 base::ProcessHandle handle
) {
131 DCHECK(thread_checker_
.CalledOnValidThread());
132 return provider_
->GetSharedMemoryHandleForProcess(handle
);
135 void GamepadService::OnUserGesture() {
136 DCHECK(thread_checker_
.CalledOnValidThread());
138 gesture_callback_pending_
= false;
141 num_active_consumers_
== 0)
144 for (ConsumerSet::iterator it
= consumers_
.begin();
145 it
!= consumers_
.end(); ++it
) {
146 if (!it
->did_observe_user_gesture
&& it
->is_active
) {
147 const ConsumerInfo
& info
= *it
;
148 info
.did_observe_user_gesture
= true;
149 blink::WebGamepads gamepads
;
150 provider_
->GetCurrentGamepadData(&gamepads
);
151 for (unsigned i
= 0; i
< blink::WebGamepads::itemsLengthCap
; ++i
) {
152 const blink::WebGamepad
& pad
= gamepads
.items
[i
];
154 info
.consumer
->OnGamepadConnected(i
, pad
);
160 } // namespace content