Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / gamepad / gamepad_service.cc
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 #include "content/browser/gamepad/gamepad_service.h"
6
7 #include "base/bind.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"
15
16 namespace content {
17
18 namespace {
19 GamepadService* g_gamepad_service = 0;
20 }
21
22 GamepadService::GamepadService()
23     : num_active_consumers_(0),
24       gesture_callback_pending_(false) {
25   SetInstance(this);
26 }
27
28 GamepadService::GamepadService(scoped_ptr<GamepadDataFetcher> fetcher)
29     : provider_(new GamepadProvider(fetcher.Pass())),
30       num_active_consumers_(0),
31       gesture_callback_pending_(false) {
32   SetInstance(this);
33   thread_checker_.DetachFromThread();
34 }
35
36 GamepadService::~GamepadService() {
37   SetInstance(NULL);
38 }
39
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
43   // vica versa.
44   CHECK(!!instance != !!g_gamepad_service);
45   g_gamepad_service = instance;
46 }
47
48 GamepadService* GamepadService::GetInstance() {
49   if (!g_gamepad_service)
50     g_gamepad_service = new GamepadService;
51   return g_gamepad_service;
52 }
53
54 void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
55   DCHECK(thread_checker_.CalledOnValidThread());
56
57   if (!provider_)
58     provider_.reset(new GamepadProvider);
59
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)));
69   }
70
71   if (num_active_consumers_++ == 0)
72     provider_->Resume();
73 }
74
75 void GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
76   DCHECK(provider_);
77   DCHECK(num_active_consumers_ > 0);
78   DCHECK(consumers_.count(consumer) > 0);
79   DCHECK(consumers_.find(consumer)->is_active);
80
81   consumers_.find(consumer)->is_active = false;
82   if (--num_active_consumers_ == 0)
83     provider_->Pause();
84 }
85
86 void GamepadService::RemoveConsumer(GamepadConsumer* consumer) {
87   DCHECK(thread_checker_.CalledOnValidThread());
88
89   ConsumerSet::iterator it = consumers_.find(consumer);
90   if (it->is_active && --num_active_consumers_ == 0)
91     provider_->Pause();
92   consumers_.erase(it);
93 }
94
95 void GamepadService::RegisterForUserGesture(const base::Closure& closure) {
96   DCHECK(consumers_.size() > 0);
97   DCHECK(thread_checker_.CalledOnValidThread());
98   provider_->RegisterForUserGesture(closure);
99 }
100
101 void GamepadService::Terminate() {
102   provider_.reset();
103 }
104
105 void GamepadService::OnGamepadConnected(
106     int index,
107     const blink::WebGamepad& pad) {
108   DCHECK(thread_checker_.CalledOnValidThread());
109
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);
114   }
115 }
116
117 void GamepadService::OnGamepadDisconnected(
118     int index,
119     const blink::WebGamepad& pad) {
120   DCHECK(thread_checker_.CalledOnValidThread());
121
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);
126   }
127 }
128
129 base::SharedMemoryHandle GamepadService::GetSharedMemoryHandleForProcess(
130     base::ProcessHandle handle) {
131   DCHECK(thread_checker_.CalledOnValidThread());
132   return provider_->GetSharedMemoryHandleForProcess(handle);
133 }
134
135 void GamepadService::OnUserGesture() {
136   DCHECK(thread_checker_.CalledOnValidThread());
137
138   gesture_callback_pending_ = false;
139
140   if (!provider_ ||
141       num_active_consumers_ == 0)
142     return;
143
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];
153         if (pad.connected)
154           info.consumer->OnGamepadConnected(i, pad);
155       }
156     }
157   }
158 }
159
160 }  // namespace content