Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / idle / idle_manager.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 "chrome/browser/extensions/api/idle/idle_manager.h"
6
7 #include <utility>
8
9 #include "base/stl_util.h"
10 #include "chrome/browser/extensions/api/idle/idle_api_constants.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/extensions/api/idle.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "extensions/browser/event_router.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/common/extension.h"
17
18 namespace keys = extensions::idle_api_constants;
19 namespace idle = extensions::api::idle;
20
21 namespace extensions {
22
23 namespace {
24
25 const int kDefaultIdleThreshold = 60;
26 const int kPollInterval = 1;
27
28 class DefaultEventDelegate : public IdleManager::EventDelegate {
29  public:
30   explicit DefaultEventDelegate(Profile* profile);
31   ~DefaultEventDelegate() override;
32
33   void OnStateChanged(const std::string& extension_id,
34                       IdleState new_state) override;
35   void RegisterObserver(EventRouter::Observer* observer) override;
36   void UnregisterObserver(EventRouter::Observer* observer) override;
37
38  private:
39   Profile* profile_;
40 };
41
42 DefaultEventDelegate::DefaultEventDelegate(Profile* profile)
43     : profile_(profile) {
44 }
45
46 DefaultEventDelegate::~DefaultEventDelegate() {
47 }
48
49 void DefaultEventDelegate::OnStateChanged(const std::string& extension_id,
50                                           IdleState new_state) {
51   scoped_ptr<base::ListValue> args(new base::ListValue());
52   args->Append(IdleManager::CreateIdleValue(new_state));
53   scoped_ptr<Event> event(new Event(idle::OnStateChanged::kEventName,
54                                     args.Pass()));
55   event->restrict_to_browser_context = profile_;
56   EventRouter::Get(profile_)
57       ->DispatchEventToExtension(extension_id, event.Pass());
58 }
59
60 void DefaultEventDelegate::RegisterObserver(
61     EventRouter::Observer* observer) {
62   EventRouter::Get(profile_)
63       ->RegisterObserver(observer, idle::OnStateChanged::kEventName);
64 }
65
66 void DefaultEventDelegate::UnregisterObserver(EventRouter::Observer* observer) {
67   EventRouter::Get(profile_)->UnregisterObserver(observer);
68 }
69
70 class DefaultIdleProvider : public IdleManager::IdleTimeProvider {
71  public:
72   DefaultIdleProvider();
73   ~DefaultIdleProvider() override;
74
75   void CalculateIdleState(int idle_threshold, IdleCallback notify) override;
76   void CalculateIdleTime(IdleTimeCallback notify) override;
77   bool CheckIdleStateIsLocked() override;
78 };
79
80 DefaultIdleProvider::DefaultIdleProvider() {
81 }
82
83 DefaultIdleProvider::~DefaultIdleProvider() {
84 }
85
86 void DefaultIdleProvider::CalculateIdleState(int idle_threshold,
87                                              IdleCallback notify) {
88   ::CalculateIdleState(idle_threshold, notify);
89 }
90
91 void DefaultIdleProvider::CalculateIdleTime(IdleTimeCallback notify) {
92   ::CalculateIdleTime(notify);
93 }
94
95 bool DefaultIdleProvider::CheckIdleStateIsLocked() {
96   return ::CheckIdleStateIsLocked();
97 }
98
99 IdleState IdleTimeToIdleState(bool locked, int idle_time, int idle_threshold) {
100   IdleState state;
101
102   if (locked) {
103     state = IDLE_STATE_LOCKED;
104   } else if (idle_time >= idle_threshold) {
105     state = IDLE_STATE_IDLE;
106   } else {
107     state = IDLE_STATE_ACTIVE;
108   }
109   return state;
110 }
111
112 }  // namespace
113
114 IdleMonitor::IdleMonitor(IdleState initial_state)
115     : last_state(initial_state),
116       listeners(0),
117       threshold(kDefaultIdleThreshold) {
118 }
119
120 IdleManager::IdleManager(Profile* profile)
121     : profile_(profile),
122       last_state_(IDLE_STATE_ACTIVE),
123       idle_time_provider_(new DefaultIdleProvider()),
124       event_delegate_(new DefaultEventDelegate(profile)),
125       extension_registry_observer_(this),
126       weak_factory_(this) {
127 }
128
129 IdleManager::~IdleManager() {
130 }
131
132 void IdleManager::Init() {
133   extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
134   event_delegate_->RegisterObserver(this);
135 }
136
137 void IdleManager::Shutdown() {
138   DCHECK(thread_checker_.CalledOnValidThread());
139   event_delegate_->UnregisterObserver(this);
140 }
141
142 void IdleManager::OnExtensionUnloaded(content::BrowserContext* browser_context,
143                                       const Extension* extension,
144                                       UnloadedExtensionInfo::Reason reason) {
145   DCHECK(thread_checker_.CalledOnValidThread());
146   monitors_.erase(extension->id());
147 }
148
149 void IdleManager::OnListenerAdded(const EventListenerInfo& details) {
150   DCHECK(thread_checker_.CalledOnValidThread());
151
152   ++GetMonitor(details.extension_id)->listeners;
153   StartPolling();
154 }
155
156 void IdleManager::OnListenerRemoved(const EventListenerInfo& details) {
157   DCHECK(thread_checker_.CalledOnValidThread());
158
159   // During unload the monitor could already have been deleted. No need to do
160   // anything in that case.
161   MonitorMap::iterator it = monitors_.find(details.extension_id);
162   if (it != monitors_.end()) {
163     DCHECK_GT(it->second.listeners, 0);
164     // Note: Deliberately leave the listener count as 0 rather than erase()ing
165     // this record so that the threshold doesn't get reset when all listeners
166     // are removed.
167     --it->second.listeners;
168   }
169 }
170
171 void IdleManager::QueryState(int threshold, QueryStateCallback notify) {
172   DCHECK(thread_checker_.CalledOnValidThread());
173   idle_time_provider_->CalculateIdleState(threshold, notify);
174 }
175
176 void IdleManager::SetThreshold(const std::string& extension_id,
177                                int threshold) {
178   DCHECK(thread_checker_.CalledOnValidThread());
179   GetMonitor(extension_id)->threshold = threshold;
180 }
181
182 // static
183 base::StringValue* IdleManager::CreateIdleValue(IdleState idle_state) {
184   const char* description;
185
186   if (idle_state == IDLE_STATE_ACTIVE) {
187     description = keys::kStateActive;
188   } else if (idle_state == IDLE_STATE_IDLE) {
189     description = keys::kStateIdle;
190   } else {
191     description = keys::kStateLocked;
192   }
193
194   return new base::StringValue(description);
195 }
196
197 void IdleManager::SetEventDelegateForTest(
198     scoped_ptr<EventDelegate> event_delegate) {
199   DCHECK(thread_checker_.CalledOnValidThread());
200   event_delegate_ = event_delegate.Pass();
201 }
202
203 void IdleManager::SetIdleTimeProviderForTest(
204     scoped_ptr<IdleTimeProvider> idle_time_provider) {
205   DCHECK(thread_checker_.CalledOnValidThread());
206   idle_time_provider_ = idle_time_provider.Pass();
207 }
208
209 IdleMonitor* IdleManager::GetMonitor(const std::string& extension_id) {
210   DCHECK(thread_checker_.CalledOnValidThread());
211   MonitorMap::iterator it = monitors_.find(extension_id);
212
213   if (it == monitors_.end()) {
214     it = monitors_.insert(std::make_pair(extension_id,
215                                          IdleMonitor(last_state_))).first;
216   }
217   return &it->second;
218 }
219
220 void IdleManager::StartPolling() {
221   DCHECK(thread_checker_.CalledOnValidThread());
222   if (!poll_timer_.IsRunning()) {
223     poll_timer_.Start(FROM_HERE,
224                       base::TimeDelta::FromSeconds(kPollInterval),
225                       this,
226                       &IdleManager::UpdateIdleState);
227   }
228 }
229
230 void IdleManager::StopPolling() {
231   DCHECK(thread_checker_.CalledOnValidThread());
232   poll_timer_.Stop();
233 }
234
235 void IdleManager::UpdateIdleState() {
236   DCHECK(thread_checker_.CalledOnValidThread());
237   idle_time_provider_->CalculateIdleTime(
238       base::Bind(
239           &IdleManager::UpdateIdleStateCallback,
240           weak_factory_.GetWeakPtr()));
241 }
242
243 void IdleManager::UpdateIdleStateCallback(int idle_time) {
244   DCHECK(thread_checker_.CalledOnValidThread());
245   bool locked = idle_time_provider_->CheckIdleStateIsLocked();
246   int listener_count = 0;
247
248   // Remember this state for initializing new event listeners.
249   last_state_ = IdleTimeToIdleState(locked,
250                                     idle_time,
251                                     kDefaultIdleThreshold);
252
253   for (MonitorMap::iterator it = monitors_.begin();
254        it != monitors_.end(); ++it) {
255     IdleMonitor& monitor = it->second;
256     IdleState new_state =
257         IdleTimeToIdleState(locked, idle_time, monitor.threshold);
258     // TODO(kalman): Use EventRouter::HasListeners for these sorts of checks.
259     if (monitor.listeners > 0 && monitor.last_state != new_state)
260       event_delegate_->OnStateChanged(it->first, new_state);
261     monitor.last_state = new_state;
262     listener_count += monitor.listeners;
263   }
264
265   if (listener_count == 0)
266     StopPolling();
267 }
268
269 }  // namespace extensions