Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: chrome/browser/extensions/extension_idle_api.cc

Issue 10750016: Moved c/b/e/*idle* to c/b/e/api/idle/ (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Sync with trunk Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/extension_idle_api.h"
6
7 #include <algorithm>
8 #include <map>
9 #include <string>
10
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/json/json_writer.h"
14 #include "base/message_loop.h"
15 #include "base/stl_util.h"
16 #include "base/time.h"
17 #include "chrome/browser/extensions/event_router.h"
18 #include "chrome/browser/extensions/extension_host.h"
19 #include "chrome/browser/extensions/extension_idle_api_constants.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/common/extensions/extension.h"
23 #include "content/public/browser/render_view_host.h"
24
25 namespace keys = extension_idle_api_constants;
26
27 namespace {
28
29 const int kIdlePollInterval = 1; // Number of seconds between status checks
30 // when polling for active.
31 const int kThrottleInterval = 1; // Number of seconds to throttle idle checks
32 // for. Return the previously checked idle
33 // state if the next check is faster than this
34 const int kMinThreshold = 15; // In seconds. Set >1 sec for security concerns.
35 const int kMaxThreshold = 4*60*60; // Four hours, in seconds. Not set
36 // arbitrarily high for security concerns.
37 const unsigned int kMaxCacheSize = 100; // Number of state queries to cache.
38
39 // Calculates the error query interval has in respect to idle interval.
40 // The error is defined as amount of the query interval that is not part of the
41 // idle interval.
42 double QueryErrorFromIdle(double idle_start,
43 double idle_end,
44 double query_start,
45 double query_end) {
46 return query_end - idle_end + std::max(0., idle_start - query_start);
47 }
48
49 // Internal class which is used to poll for changes in the system idle state.
50 class ExtensionIdlePollingTask {
51 public:
52 explicit ExtensionIdlePollingTask(int threshold, IdleState last_state,
53 Profile* profile) : threshold_(threshold), last_state_(last_state),
54 profile_(profile) {}
55
56 // Check if we're active; then restart the polling task. Do this till we are
57 // are in active state.
58 void CheckIdleState();
59 void IdleStateCallback(IdleState state);
60
61 // Create a poll task to check for Idle state
62 static void CreateNewPollTask(int threshold, IdleState state,
63 Profile* profile);
64
65 private:
66 int threshold_;
67 IdleState last_state_;
68 Profile* profile_;
69
70 static bool poll_task_running_;
71
72 DISALLOW_COPY_AND_ASSIGN(ExtensionIdlePollingTask);
73 };
74
75 // Implementation of ExtensionIdlePollingTask.
76 bool ExtensionIdlePollingTask::poll_task_running_ = false;
77
78 void ExtensionIdlePollingTask::IdleStateCallback(IdleState current_state) {
79 // If we just came into an active state, notify the extension.
80 if (IDLE_STATE_ACTIVE == current_state && last_state_ != current_state)
81 ExtensionIdleEventRouter::OnIdleStateChange(profile_, current_state);
82
83 ExtensionIdlePollingTask::poll_task_running_ = false;
84
85 ExtensionIdleCache::UpdateCache(threshold_, current_state);
86
87 // Startup another polling task as we exit.
88 if (current_state != IDLE_STATE_ACTIVE)
89 ExtensionIdlePollingTask::CreateNewPollTask(threshold_, current_state,
90 profile_);
91
92 // This instance won't be needed anymore.
93 delete this;
94 }
95
96 void ExtensionIdlePollingTask::CheckIdleState() {
97 CalculateIdleState(threshold_,
98 base::Bind(&ExtensionIdlePollingTask::IdleStateCallback,
99 base::Unretained(this)));
100 }
101
102 // static
103 void ExtensionIdlePollingTask::CreateNewPollTask(int threshold, IdleState state,
104 Profile* profile) {
105 if (ExtensionIdlePollingTask::poll_task_running_) return;
106
107 ExtensionIdlePollingTask::poll_task_running_ = true;
108 MessageLoop::current()->PostDelayedTask(
109 FROM_HERE,
110 base::Bind(&ExtensionIdlePollingTask::CheckIdleState, base::Unretained(
111 new ExtensionIdlePollingTask(threshold, state, profile))),
112 base::TimeDelta::FromSeconds(kIdlePollInterval));
113 }
114
115
116 const char* IdleStateToDescription(IdleState state) {
117 if (IDLE_STATE_ACTIVE == state)
118 return keys::kStateActive;
119 if (IDLE_STATE_IDLE == state)
120 return keys::kStateIdle;
121 return keys::kStateLocked;
122 };
123
124 // Helper function for reporting the idle state. The lifetime of the object
125 // returned is controlled by the caller.
126 StringValue* CreateIdleValue(IdleState idle_state) {
127 StringValue* result = new StringValue(IdleStateToDescription(idle_state));
128 return result;
129 }
130
131 int CheckThresholdBounds(int timeout) {
132 if (timeout < kMinThreshold) return kMinThreshold;
133 if (timeout > kMaxThreshold) return kMaxThreshold;
134 return timeout;
135 }
136
137 }; // namespace
138
139 void ExtensionIdleEventRouter::OnIdleStateChange(Profile* profile,
140 IdleState state) {
141 // Prepare the single argument of the current state.
142 ListValue args;
143 args.Append(CreateIdleValue(state));
144 std::string json_args;
145 base::JSONWriter::Write(&args, &json_args);
146
147 profile->GetExtensionEventRouter()->DispatchEventToRenderers(
148 keys::kOnStateChanged, json_args, profile,
149 GURL(), extensions::EventFilteringInfo());
150 }
151
152 bool ExtensionIdleQueryStateFunction::RunImpl() {
153 int threshold;
154 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &threshold));
155 threshold = CheckThresholdBounds(threshold);
156
157 IdleState state = ExtensionIdleCache::CalculateIdleState(threshold);
158 if (state != IDLE_STATE_UNKNOWN) {
159 SetResult(CreateIdleValue(state));
160 SendResponse(true);
161 return true;
162 }
163
164 CalculateIdleState(threshold,
165 base::Bind(&ExtensionIdleQueryStateFunction::IdleStateCallback,
166 this, threshold));
167 // Don't send the response, it'll be sent by our callback
168 return true;
169 }
170
171 void ExtensionIdleQueryStateFunction::IdleStateCallback(int threshold,
172 IdleState state) {
173 // If our state is not active, make sure we're running a polling task to check
174 // for active state and report it when it changes to active.
175 if (state != IDLE_STATE_ACTIVE) {
176 ExtensionIdlePollingTask::CreateNewPollTask(threshold, state, profile_);
177 }
178
179 SetResult(CreateIdleValue(state));
180
181 ExtensionIdleCache::UpdateCache(threshold, state);
182
183 SendResponse(true);
184 }
185
186 ExtensionIdleCache::CacheData ExtensionIdleCache::cached_data =
187 {-1, -1, -1, -1};
188
189 IdleState ExtensionIdleCache::CalculateIdleState(int threshold) {
190 return CalculateState(threshold, base::Time::Now().ToDoubleT());
191 }
192
193 void ExtensionIdleCache::UpdateCache(int threshold, IdleState state) {
194 Update(threshold, state, base::Time::Now().ToDoubleT());
195 }
196
197 IdleState ExtensionIdleCache::CalculateState(int threshold, double now) {
198 if (threshold < kMinThreshold)
199 return IDLE_STATE_UNKNOWN;
200 double threshold_moment = now - static_cast<double>(threshold);
201 double throttle_interval = static_cast<double>(kThrottleInterval);
202
203 // We test for IDEL_STATE_LOCKED first, because the result should be
204 // independent of the data for idle and active state. If last state was
205 // LOCKED and test for LOCKED is satisfied we should always return LOCKED.
206 if (cached_data.latest_locked > 0 &&
207 now - cached_data.latest_locked < throttle_interval)
208 return IDLE_STATE_LOCKED;
209
210 // If thershold moment is beyond the moment after whih we are certain we have
211 // been active, return active state. We allow kThrottleInterval error.
212 if (cached_data.latest_known_active > 0 &&
213 threshold_moment - cached_data.latest_known_active < throttle_interval)
214 return IDLE_STATE_ACTIVE;
215
216 // If total error that query interval has in respect to last recorded idle
217 // interval is less than kThrottleInterval, return IDLE state.
218 // query interval is the interval [now, now - threshold] and the error is
219 // defined as amount of query interval that is outside of idle interval.
220 double error_from_idle =
221 QueryErrorFromIdle(cached_data.idle_interval_start,
222 cached_data.idle_interval_end, threshold_moment, now);
223 if (cached_data.idle_interval_end > 0 &&
224 error_from_idle < throttle_interval)
225 return IDLE_STATE_IDLE;
226
227 return IDLE_STATE_UNKNOWN;
228 }
229
230 void ExtensionIdleCache::Update(int threshold, IdleState state, double now) {
231 if (threshold < kMinThreshold)
232 return;
233 double threshold_moment = now - static_cast<double>(threshold);
234 switch (state) {
235 case IDLE_STATE_IDLE:
236 if (threshold_moment > cached_data.idle_interval_end) {
237 // Cached and new interval don't overlap. We disregard the cached one.
238 cached_data.idle_interval_start = threshold_moment;
239 } else {
240 // Cached and new interval overlap, so we can combine them. We set
241 // the cached interval begining to less recent one.
242 cached_data.idle_interval_start =
243 std::min(cached_data.idle_interval_start, threshold_moment);
244 }
245 cached_data.idle_interval_end = now;
246 // Reset data for LOCKED state, since the last query result is not
247 // LOCKED.
248 cached_data.latest_locked = -1;
249 break;
250 case IDLE_STATE_ACTIVE:
251 if (threshold_moment > cached_data.latest_known_active)
252 cached_data.latest_known_active = threshold_moment;
253 // Reset data for LOCKED state, since the last query result is not
254 // LOCKED.
255 cached_data.latest_locked = -1;
256 break;
257 case IDLE_STATE_LOCKED:
258 if (threshold_moment > cached_data.latest_locked)
259 cached_data.latest_locked = now;
260 break;
261 default:
262 return;
263 }
264 }
265
266 int ExtensionIdleCache::get_min_threshold() {
267 return kMinThreshold;
268 }
269
270 double ExtensionIdleCache::get_throttle_interval() {
271 return static_cast<double>(kThrottleInterval);
272 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_idle_api.h ('k') | chrome/browser/extensions/extension_idle_api_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698