Upstream version 7.36.149.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 GamepadService::GamepadService()
19     : num_active_consumers_(0),
20       gesture_callback_pending_(false) {
21 }
22
23 GamepadService::GamepadService(scoped_ptr<GamepadDataFetcher> fetcher)
24     : provider_(new GamepadProvider(fetcher.Pass())),
25       num_active_consumers_(0),
26       gesture_callback_pending_(false) {
27   thread_checker_.DetachFromThread();
28 }
29
30 GamepadService::~GamepadService() {
31 }
32
33 GamepadService* GamepadService::GetInstance() {
34   return Singleton<GamepadService,
35                    LeakySingletonTraits<GamepadService> >::get();
36 }
37
38 void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
39   DCHECK(thread_checker_.CalledOnValidThread());
40
41   if (!provider_)
42     provider_.reset(new GamepadProvider);
43
44   std::pair<ConsumerSet::iterator, bool> insert_result =
45       consumers_.insert(consumer);
46   insert_result.first->is_active = true;
47   if (!insert_result.first->did_observe_user_gesture &&
48       !gesture_callback_pending_) {
49     provider_->RegisterForUserGesture(
50           base::Bind(&GamepadService::OnUserGesture,
51                      base::Unretained(this)));
52   }
53
54   if (num_active_consumers_++ == 0)
55     provider_->Resume();
56 }
57
58 void GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
59   DCHECK(provider_);
60   DCHECK(num_active_consumers_ > 0);
61   DCHECK(consumers_.count(consumer) > 0);
62   DCHECK(consumers_.find(consumer)->is_active);
63
64   consumers_.find(consumer)->is_active = false;
65   if (--num_active_consumers_ == 0)
66     provider_->Pause();
67 }
68
69 void GamepadService::RemoveConsumer(GamepadConsumer* consumer) {
70   DCHECK(thread_checker_.CalledOnValidThread());
71
72   ConsumerSet::iterator it = consumers_.find(consumer);
73   if (it->is_active && --num_active_consumers_ == 0)
74     provider_->Pause();
75   consumers_.erase(it);
76 }
77
78 void GamepadService::RegisterForUserGesture(const base::Closure& closure) {
79   DCHECK(consumers_.size() > 0);
80   DCHECK(thread_checker_.CalledOnValidThread());
81   provider_->RegisterForUserGesture(closure);
82 }
83
84 void GamepadService::Terminate() {
85   provider_.reset();
86 }
87
88 void GamepadService::OnGamepadConnected(
89     int index,
90     const blink::WebGamepad& pad) {
91   DCHECK(thread_checker_.CalledOnValidThread());
92
93   for (ConsumerSet::iterator it = consumers_.begin();
94        it != consumers_.end(); ++it) {
95     if (it->did_observe_user_gesture && it->is_active)
96       it->consumer->OnGamepadConnected(index, pad);
97   }
98 }
99
100 void GamepadService::OnGamepadDisconnected(
101     int index,
102     const blink::WebGamepad& pad) {
103   DCHECK(thread_checker_.CalledOnValidThread());
104
105   for (ConsumerSet::iterator it = consumers_.begin();
106        it != consumers_.end(); ++it) {
107     if (it->did_observe_user_gesture && it->is_active)
108       it->consumer->OnGamepadDisconnected(index, pad);
109   }
110 }
111
112 base::SharedMemoryHandle GamepadService::GetSharedMemoryHandleForProcess(
113     base::ProcessHandle handle) {
114   DCHECK(thread_checker_.CalledOnValidThread());
115   return provider_->GetSharedMemoryHandleForProcess(handle);
116 }
117
118 void GamepadService::OnUserGesture() {
119   DCHECK(thread_checker_.CalledOnValidThread());
120
121   gesture_callback_pending_ = false;
122
123   if (!provider_ ||
124       num_active_consumers_ == 0)
125     return;
126
127   for (ConsumerSet::iterator it = consumers_.begin();
128        it != consumers_.end(); ++it) {
129     if (!it->did_observe_user_gesture && it->is_active) {
130       const ConsumerInfo& info = *it;
131       info.did_observe_user_gesture = true;
132       blink::WebGamepads gamepads;
133       provider_->GetCurrentGamepadData(&gamepads);
134       for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) {
135         const blink::WebGamepad& pad = gamepads.items[i];
136         if (pad.connected)
137           info.consumer->OnGamepadConnected(i, pad);
138       }
139     }
140   }
141 }
142
143 }  // namespace content