Enable Enterprise enrollment on desktop builds.
[chromium-blink-merge.git] / chrome / browser / extensions / api / idle / idle_manager.cc
blob6e97ec0bca44a863295a9a00854472a4fea2401a
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 "chrome/browser/extensions/api/idle/idle_manager.h"
7 #include <utility>
9 #include "base/stl_util.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/api/idle/idle_api_constants.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/common/extensions/api/idle.h"
14 #include "chrome/common/extensions/extension_constants.h"
15 #include "content/public/browser/notification_details.h"
16 #include "content/public/browser/notification_source.h"
17 #include "extensions/browser/event_router.h"
18 #include "extensions/common/extension.h"
20 namespace keys = extensions::idle_api_constants;
21 namespace idle = extensions::api::idle;
23 namespace extensions {
25 namespace {
27 const int kDefaultIdleThreshold = 60;
28 const int kPollInterval = 1;
30 class DefaultEventDelegate : public IdleManager::EventDelegate {
31 public:
32 explicit DefaultEventDelegate(Profile* profile);
33 virtual ~DefaultEventDelegate();
35 virtual void OnStateChanged(const std::string& extension_id,
36 IdleState new_state) OVERRIDE;
37 virtual void RegisterObserver(EventRouter::Observer* observer) OVERRIDE;
38 virtual void UnregisterObserver(EventRouter::Observer* observer) OVERRIDE;
40 private:
41 Profile* profile_;
44 DefaultEventDelegate::DefaultEventDelegate(Profile* profile)
45 : profile_(profile) {
48 DefaultEventDelegate::~DefaultEventDelegate() {
51 void DefaultEventDelegate::OnStateChanged(const std::string& extension_id,
52 IdleState new_state) {
53 scoped_ptr<base::ListValue> args(new base::ListValue());
54 args->Append(IdleManager::CreateIdleValue(new_state));
55 scoped_ptr<Event> event(new Event(idle::OnStateChanged::kEventName,
56 args.Pass()));
57 event->restrict_to_browser_context = profile_;
58 EventRouter::Get(profile_)
59 ->DispatchEventToExtension(extension_id, event.Pass());
62 void DefaultEventDelegate::RegisterObserver(
63 EventRouter::Observer* observer) {
64 EventRouter::Get(profile_)
65 ->RegisterObserver(observer, idle::OnStateChanged::kEventName);
68 void DefaultEventDelegate::UnregisterObserver(EventRouter::Observer* observer) {
69 EventRouter::Get(profile_)->UnregisterObserver(observer);
72 class DefaultIdleProvider : public IdleManager::IdleTimeProvider {
73 public:
74 DefaultIdleProvider();
75 virtual ~DefaultIdleProvider();
77 virtual void CalculateIdleState(int idle_threshold,
78 IdleCallback notify) OVERRIDE;
79 virtual void CalculateIdleTime(IdleTimeCallback notify) OVERRIDE;
80 virtual bool CheckIdleStateIsLocked() OVERRIDE;
83 DefaultIdleProvider::DefaultIdleProvider() {
86 DefaultIdleProvider::~DefaultIdleProvider() {
89 void DefaultIdleProvider::CalculateIdleState(int idle_threshold,
90 IdleCallback notify) {
91 ::CalculateIdleState(idle_threshold, notify);
94 void DefaultIdleProvider::CalculateIdleTime(IdleTimeCallback notify) {
95 ::CalculateIdleTime(notify);
98 bool DefaultIdleProvider::CheckIdleStateIsLocked() {
99 return ::CheckIdleStateIsLocked();
102 IdleState IdleTimeToIdleState(bool locked, int idle_time, int idle_threshold) {
103 IdleState state;
105 if (locked) {
106 state = IDLE_STATE_LOCKED;
107 } else if (idle_time >= idle_threshold) {
108 state = IDLE_STATE_IDLE;
109 } else {
110 state = IDLE_STATE_ACTIVE;
112 return state;
115 } // namespace
117 IdleMonitor::IdleMonitor(IdleState initial_state)
118 : last_state(initial_state),
119 listeners(0),
120 threshold(kDefaultIdleThreshold) {
123 IdleManager::IdleManager(Profile* profile)
124 : profile_(profile),
125 last_state_(IDLE_STATE_ACTIVE),
126 weak_factory_(this),
127 idle_time_provider_(new DefaultIdleProvider()),
128 event_delegate_(new DefaultEventDelegate(profile)) {
131 IdleManager::~IdleManager() {
134 void IdleManager::Init() {
135 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
136 content::Source<Profile>(profile_->GetOriginalProfile()));
137 event_delegate_->RegisterObserver(this);
140 void IdleManager::Shutdown() {
141 DCHECK(thread_checker_.CalledOnValidThread());
142 event_delegate_->UnregisterObserver(this);
145 void IdleManager::Observe(int type,
146 const content::NotificationSource& source,
147 const content::NotificationDetails& details) {
148 DCHECK(thread_checker_.CalledOnValidThread());
150 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED) {
151 const Extension* extension =
152 content::Details<extensions::UnloadedExtensionInfo>(details)->extension;
153 monitors_.erase(extension->id());
154 } else {
155 NOTREACHED();
159 void IdleManager::OnListenerAdded(const EventListenerInfo& details) {
160 DCHECK(thread_checker_.CalledOnValidThread());
162 ++GetMonitor(details.extension_id)->listeners;
163 StartPolling();
166 void IdleManager::OnListenerRemoved(const EventListenerInfo& details) {
167 DCHECK(thread_checker_.CalledOnValidThread());
169 // During unload the monitor could already have been deleted. No need to do
170 // anything in that case.
171 MonitorMap::iterator it = monitors_.find(details.extension_id);
172 if (it != monitors_.end()) {
173 DCHECK_GT(it->second.listeners, 0);
174 // Note: Deliberately leave the listener count as 0 rather than erase()ing
175 // this record so that the threshold doesn't get reset when all listeners
176 // are removed.
177 --it->second.listeners;
181 void IdleManager::QueryState(int threshold, QueryStateCallback notify) {
182 DCHECK(thread_checker_.CalledOnValidThread());
183 idle_time_provider_->CalculateIdleState(threshold, notify);
186 void IdleManager::SetThreshold(const std::string& extension_id,
187 int threshold) {
188 DCHECK(thread_checker_.CalledOnValidThread());
189 GetMonitor(extension_id)->threshold = threshold;
192 // static
193 base::StringValue* IdleManager::CreateIdleValue(IdleState idle_state) {
194 const char* description;
196 if (idle_state == IDLE_STATE_ACTIVE) {
197 description = keys::kStateActive;
198 } else if (idle_state == IDLE_STATE_IDLE) {
199 description = keys::kStateIdle;
200 } else {
201 description = keys::kStateLocked;
204 return new base::StringValue(description);
207 void IdleManager::SetEventDelegateForTest(
208 scoped_ptr<EventDelegate> event_delegate) {
209 DCHECK(thread_checker_.CalledOnValidThread());
210 event_delegate_ = event_delegate.Pass();
213 void IdleManager::SetIdleTimeProviderForTest(
214 scoped_ptr<IdleTimeProvider> idle_time_provider) {
215 DCHECK(thread_checker_.CalledOnValidThread());
216 idle_time_provider_ = idle_time_provider.Pass();
219 IdleMonitor* IdleManager::GetMonitor(const std::string& extension_id) {
220 DCHECK(thread_checker_.CalledOnValidThread());
221 MonitorMap::iterator it = monitors_.find(extension_id);
223 if (it == monitors_.end()) {
224 it = monitors_.insert(std::make_pair(extension_id,
225 IdleMonitor(last_state_))).first;
227 return &it->second;
230 void IdleManager::StartPolling() {
231 DCHECK(thread_checker_.CalledOnValidThread());
232 if (!poll_timer_.IsRunning()) {
233 poll_timer_.Start(FROM_HERE,
234 base::TimeDelta::FromSeconds(kPollInterval),
235 this,
236 &IdleManager::UpdateIdleState);
240 void IdleManager::StopPolling() {
241 DCHECK(thread_checker_.CalledOnValidThread());
242 poll_timer_.Stop();
245 void IdleManager::UpdateIdleState() {
246 DCHECK(thread_checker_.CalledOnValidThread());
247 idle_time_provider_->CalculateIdleTime(
248 base::Bind(
249 &IdleManager::UpdateIdleStateCallback,
250 weak_factory_.GetWeakPtr()));
253 void IdleManager::UpdateIdleStateCallback(int idle_time) {
254 DCHECK(thread_checker_.CalledOnValidThread());
255 bool locked = idle_time_provider_->CheckIdleStateIsLocked();
256 int listener_count = 0;
258 // Remember this state for initializing new event listeners.
259 last_state_ = IdleTimeToIdleState(locked,
260 idle_time,
261 kDefaultIdleThreshold);
263 for (MonitorMap::iterator it = monitors_.begin();
264 it != monitors_.end(); ++it) {
265 IdleMonitor& monitor = it->second;
266 IdleState new_state =
267 IdleTimeToIdleState(locked, idle_time, monitor.threshold);
268 // TODO(kalman): Use EventRouter::HasListeners for these sorts of checks.
269 if (monitor.listeners > 0 && monitor.last_state != new_state)
270 event_delegate_->OnStateChanged(it->first, new_state);
271 monitor.last_state = new_state;
272 listener_count += monitor.listeners;
275 if (listener_count == 0)
276 StopPolling();
279 } // namespace extensions