make use of media_use_ffmpeg in BUILD.gn
[chromium-blink-merge.git] / extensions / browser / api / idle / idle_manager.cc
blob2eb16a84509556b2cf31747d901c11f9481cc4e4
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 "extensions/browser/api/idle/idle_manager.h"
7 #include <utility>
9 #include "base/stl_util.h"
10 #include "content/public/browser/browser_context.h"
11 #include "extensions/browser/api/idle/idle_api_constants.h"
12 #include "extensions/browser/event_router.h"
13 #include "extensions/browser/extension_registry.h"
14 #include "extensions/common/api/idle.h"
15 #include "extensions/common/extension.h"
17 namespace keys = extensions::idle_api_constants;
18 namespace idle = extensions::api::idle;
20 namespace extensions {
22 namespace {
24 const int kDefaultIdleThreshold = 60;
25 const int kPollInterval = 1;
27 class DefaultEventDelegate : public IdleManager::EventDelegate {
28 public:
29 explicit DefaultEventDelegate(content::BrowserContext* context);
30 ~DefaultEventDelegate() override;
32 void OnStateChanged(const std::string& extension_id,
33 ui::IdleState new_state) override;
34 void RegisterObserver(EventRouter::Observer* observer) override;
35 void UnregisterObserver(EventRouter::Observer* observer) override;
37 private:
38 content::BrowserContext* const context_;
41 DefaultEventDelegate::DefaultEventDelegate(content::BrowserContext* context)
42 : context_(context) {
45 DefaultEventDelegate::~DefaultEventDelegate() {
48 void DefaultEventDelegate::OnStateChanged(const std::string& extension_id,
49 ui::IdleState new_state) {
50 scoped_ptr<base::ListValue> args(new base::ListValue());
51 args->Append(IdleManager::CreateIdleValue(new_state));
52 scoped_ptr<Event> event(new Event(events::IDLE_ON_STATE_CHANGED,
53 idle::OnStateChanged::kEventName,
54 args.Pass()));
55 event->restrict_to_browser_context = context_;
56 EventRouter::Get(context_)
57 ->DispatchEventToExtension(extension_id, event.Pass());
60 void DefaultEventDelegate::RegisterObserver(EventRouter::Observer* observer) {
61 EventRouter::Get(context_)
62 ->RegisterObserver(observer, idle::OnStateChanged::kEventName);
65 void DefaultEventDelegate::UnregisterObserver(EventRouter::Observer* observer) {
66 EventRouter::Get(context_)->UnregisterObserver(observer);
69 class DefaultIdleProvider : public IdleManager::IdleTimeProvider {
70 public:
71 DefaultIdleProvider();
72 ~DefaultIdleProvider() override;
74 void CalculateIdleState(int idle_threshold, ui::IdleCallback notify) override;
75 void CalculateIdleTime(ui::IdleTimeCallback notify) override;
76 bool CheckIdleStateIsLocked() override;
79 DefaultIdleProvider::DefaultIdleProvider() {
82 DefaultIdleProvider::~DefaultIdleProvider() {
85 void DefaultIdleProvider::CalculateIdleState(int idle_threshold,
86 ui::IdleCallback notify) {
87 ui::CalculateIdleState(idle_threshold, notify);
90 void DefaultIdleProvider::CalculateIdleTime(ui::IdleTimeCallback notify) {
91 ui::CalculateIdleTime(notify);
94 bool DefaultIdleProvider::CheckIdleStateIsLocked() {
95 return ui::CheckIdleStateIsLocked();
98 ui::IdleState IdleTimeToIdleState(bool locked,
99 int idle_time,
100 int idle_threshold) {
101 ui::IdleState state;
103 if (locked) {
104 state = ui::IDLE_STATE_LOCKED;
105 } else if (idle_time >= idle_threshold) {
106 state = ui::IDLE_STATE_IDLE;
107 } else {
108 state = ui::IDLE_STATE_ACTIVE;
110 return state;
113 } // namespace
115 IdleMonitor::IdleMonitor(ui::IdleState initial_state)
116 : last_state(initial_state),
117 listeners(0),
118 threshold(kDefaultIdleThreshold) {
121 IdleManager::IdleManager(content::BrowserContext* context)
122 : context_(context),
123 last_state_(ui::IDLE_STATE_ACTIVE),
124 idle_time_provider_(new DefaultIdleProvider()),
125 event_delegate_(new DefaultEventDelegate(context)),
126 extension_registry_observer_(this),
127 weak_factory_(this) {
130 IdleManager::~IdleManager() {
133 void IdleManager::Init() {
134 extension_registry_observer_.Add(ExtensionRegistry::Get(context_));
135 event_delegate_->RegisterObserver(this);
138 void IdleManager::Shutdown() {
139 DCHECK(thread_checker_.CalledOnValidThread());
140 event_delegate_->UnregisterObserver(this);
143 void IdleManager::OnExtensionUnloaded(content::BrowserContext* browser_context,
144 const Extension* extension,
145 UnloadedExtensionInfo::Reason reason) {
146 DCHECK(thread_checker_.CalledOnValidThread());
147 monitors_.erase(extension->id());
150 void IdleManager::OnListenerAdded(const EventListenerInfo& details) {
151 DCHECK(thread_checker_.CalledOnValidThread());
153 ++GetMonitor(details.extension_id)->listeners;
154 StartPolling();
157 void IdleManager::OnListenerRemoved(const EventListenerInfo& details) {
158 DCHECK(thread_checker_.CalledOnValidThread());
160 // During unload the monitor could already have been deleted. No need to do
161 // anything in that case.
162 MonitorMap::iterator it = monitors_.find(details.extension_id);
163 if (it != monitors_.end()) {
164 DCHECK_GT(it->second.listeners, 0);
165 // Note: Deliberately leave the listener count as 0 rather than erase()ing
166 // this record so that the threshold doesn't get reset when all listeners
167 // are removed.
168 --it->second.listeners;
172 void IdleManager::QueryState(int threshold, QueryStateCallback notify) {
173 DCHECK(thread_checker_.CalledOnValidThread());
174 idle_time_provider_->CalculateIdleState(threshold, notify);
177 void IdleManager::SetThreshold(const std::string& extension_id, int threshold) {
178 DCHECK(thread_checker_.CalledOnValidThread());
179 GetMonitor(extension_id)->threshold = threshold;
182 // static
183 base::StringValue* IdleManager::CreateIdleValue(ui::IdleState idle_state) {
184 const char* description;
186 if (idle_state == ui::IDLE_STATE_ACTIVE) {
187 description = keys::kStateActive;
188 } else if (idle_state == ui::IDLE_STATE_IDLE) {
189 description = keys::kStateIdle;
190 } else {
191 description = keys::kStateLocked;
194 return new base::StringValue(description);
197 void IdleManager::SetEventDelegateForTest(
198 scoped_ptr<EventDelegate> event_delegate) {
199 DCHECK(thread_checker_.CalledOnValidThread());
200 event_delegate_ = event_delegate.Pass();
203 void IdleManager::SetIdleTimeProviderForTest(
204 scoped_ptr<IdleTimeProvider> idle_time_provider) {
205 DCHECK(thread_checker_.CalledOnValidThread());
206 idle_time_provider_ = idle_time_provider.Pass();
209 IdleMonitor* IdleManager::GetMonitor(const std::string& extension_id) {
210 DCHECK(thread_checker_.CalledOnValidThread());
211 MonitorMap::iterator it = monitors_.find(extension_id);
213 if (it == monitors_.end()) {
214 it = monitors_.insert(std::make_pair(extension_id,
215 IdleMonitor(last_state_))).first;
217 return &it->second;
220 void IdleManager::StartPolling() {
221 DCHECK(thread_checker_.CalledOnValidThread());
222 if (!poll_timer_.IsRunning()) {
223 poll_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kPollInterval),
224 this, &IdleManager::UpdateIdleState);
228 void IdleManager::StopPolling() {
229 DCHECK(thread_checker_.CalledOnValidThread());
230 poll_timer_.Stop();
233 void IdleManager::UpdateIdleState() {
234 DCHECK(thread_checker_.CalledOnValidThread());
235 idle_time_provider_->CalculateIdleTime(base::Bind(
236 &IdleManager::UpdateIdleStateCallback, weak_factory_.GetWeakPtr()));
239 void IdleManager::UpdateIdleStateCallback(int idle_time) {
240 DCHECK(thread_checker_.CalledOnValidThread());
241 bool locked = idle_time_provider_->CheckIdleStateIsLocked();
242 int listener_count = 0;
244 // Remember this state for initializing new event listeners.
245 last_state_ = IdleTimeToIdleState(locked, idle_time, kDefaultIdleThreshold);
247 for (MonitorMap::iterator it = monitors_.begin(); it != monitors_.end();
248 ++it) {
249 IdleMonitor& monitor = it->second;
250 ui::IdleState new_state =
251 IdleTimeToIdleState(locked, idle_time, monitor.threshold);
252 // TODO(kalman): Use EventRouter::HasListeners for these sorts of checks.
253 if (monitor.listeners > 0 && monitor.last_state != new_state)
254 event_delegate_->OnStateChanged(it->first, new_state);
255 monitor.last_state = new_state;
256 listener_count += monitor.listeners;
259 if (listener_count == 0)
260 StopPolling();
263 } // namespace extensions