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

Side by Side Diff: chrome/browser/chromeos/power/session_length_limiter_unittest.cc

Issue 11499012: Add policy for limiting the session length (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix include order. Created 8 years 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 | Annotate | Revision Log
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/chromeos/power/session_length_limiter.h"
6
7 #include <deque>
8 #include <utility>
9
10 #include "base/basictypes.h"
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/string_number_conversions.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "base/time.h"
21 #include "base/values.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/common/chrome_notification_types.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/testing_browser_process.h"
26 #include "chrome/test/base/testing_pref_service.h"
27 #include "content/public/browser/notification_details.h"
28 #include "content/public/browser/notification_observer.h"
29 #include "content/public/browser/notification_registrar.h"
30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34
35 using ::testing::_;
36 using ::testing::Invoke;
37 using ::testing::Mock;
38 using ::testing::NiceMock;
39
40 namespace chromeos {
41
42 namespace {
43
44 // The interval at which the SessionLengthLimiter sends periodic notifications.
45 const base::TimeDelta kSessionLengthLimitTimerInterval(
46 base::TimeDelta::FromSeconds(1));
47
48 const base::TimeDelta kZeroTimeDelta;
49 const base::TimeDelta kTenSeconds(base::TimeDelta::FromSeconds(10));
50
51 class MockNotificationObserver : public content::NotificationObserver {
52 public:
53 MockNotificationObserver() {
54 }
55
56 virtual void Observe(int type,
57 const content::NotificationSource& source,
58 const content::NotificationDetails& details) OVERRIDE {
59 switch (type) {
60 case chrome::NOTIFICATION_SESSION_LENGTH_UNLIMITED:
61 ObservedSessionLengthUnlimited();
62 break;
63 case chrome::NOTIFICATION_REMAINING_SESSION_TIME_CHANGED:
64 ObservedRemainingSessionTimeChanged(
65 *content::Details<const base::TimeDelta>(details).ptr());
66 break;
67 default:
68 ADD_FAILURE() << "Unexpected notification type: " << type;
69 }
70 }
71
72 void Register() {
73 registrar_.Add(this,
74 chrome::NOTIFICATION_SESSION_LENGTH_UNLIMITED,
75 content::NotificationService::AllSources());
76 registrar_.Add(this,
77 chrome::NOTIFICATION_REMAINING_SESSION_TIME_CHANGED,
78 content::NotificationService::AllSources());
79 }
80
81 MOCK_CONST_METHOD0(ObservedSessionLengthUnlimited, void(void));
82 MOCK_CONST_METHOD1(ObservedRemainingSessionTimeChanged,
83 void(const base::TimeDelta&));
84
85 private:
86 content::NotificationRegistrar registrar_;
87
88 DISALLOW_COPY_AND_ASSIGN(MockNotificationObserver);
89 };
90
91 class MockSessionLengthLimiterDelegate : public SessionLengthLimiter::Delegate {
92 public:
93 MOCK_CONST_METHOD0(GetCurrentTime, const base::Time(void));
94 MOCK_METHOD0(StopSession, void(void));
95 };
96
97 // A SingleThreadTaskRunner that allows the task queue to be inspected and
98 // delayed tasks to be run without waiting for the actual delays to expire.
99 class ImmediateSingleThreadTaskRunner : public base::SingleThreadTaskRunner {
100 public:
101 virtual bool RunsTasksOnCurrentThread() const OVERRIDE {
102 return true;
103 }
104
105 virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
106 const base::Closure& task,
107 base::TimeDelta delay) OVERRIDE {
108 tasks_.push_back(std::pair<base::TimeDelta, base::Closure>(delay, task));
109 return true;
110 }
111
112 virtual bool PostNonNestableDelayedTask(
113 const tracked_objects::Location& from_here,
114 const base::Closure& task,
115 base::TimeDelta delay) OVERRIDE {
116 NOTREACHED();
117 return false;
118 }
119
120 void RunTasks() {
121 std::deque<std::pair<base::TimeDelta, base::Closure> > tasks;
122 tasks.swap(tasks_);
123 for (std::deque<std::pair<base::TimeDelta, base::Closure> >::iterator
124 it = tasks.begin(); it != tasks.end(); ++it) {
125 it->second.Run();
126 }
127 }
128
129 const std::deque<std::pair<base::TimeDelta, base::Closure> >& tasks() const {
130 return tasks_;
131 }
132
133 private:
134 std::deque<std::pair<base::TimeDelta, base::Closure> > tasks_;
135
136 virtual ~ImmediateSingleThreadTaskRunner() {}
137 };
138
139 } // namespace
140
141 class SessionLengthLimiterTest : public testing::Test {
142 protected:
143 SessionLengthLimiterTest() : delegate_(NULL) {
144 }
145
146 virtual void SetUp() {
147 static_cast<TestingBrowserProcess*>(g_browser_process)->
148 SetLocalState(&local_state_);
149 SessionLengthLimiter::RegisterPrefs(&local_state_);
150
151 observer_.Register();
152 delegate_ = new NiceMock<MockSessionLengthLimiterDelegate>;
153 ON_CALL(*delegate_, GetCurrentTime())
154 .WillByDefault(Invoke(this, &SessionLengthLimiterTest::GetCurrentTime));
155 EXPECT_CALL(*delegate_, StopSession()).Times(0);
156 runner_ = new ImmediateSingleThreadTaskRunner;
157
158 // Initialize the mock clock to a fixed value, ensuring that timezone
159 // differences or DST changes do not affect the test.
160 now_ = base::Time::UnixEpoch() + base::TimeDelta::FromDays(40 * 365);
161 session_start_time_ = now_;
162 }
163
164 virtual void TearDown() {
165 static_cast<TestingBrowserProcess*>(g_browser_process)->SetLocalState(NULL);
166 }
167
168 void SetSessionStartTimePref(int64 session_start_time) {
169 local_state_.SetUserPref(prefs::kSessionStartTime,
170 base::Value::CreateStringValue(
171 base::Int64ToString(session_start_time)));
172 }
173
174 void VerifySessionStartTimePref() {
175 base::Time session_start_time(base::Time::FromInternalValue(
176 local_state_.GetInt64(prefs::kSessionStartTime)));
177 EXPECT_EQ(session_start_time_, session_start_time);
178 }
179
180 void SetSessionLengthLimitPref(int64 session_length_limit) {
181 local_state_.SetUserPref(prefs::kSessionLengthLimit,
182 base::Value::CreateIntegerValue(
183 session_length_limit));
184 base::TimeDelta remaining(
185 base::TimeDelta::FromMilliseconds(session_length_limit) -
186 (now_ - session_start_time_));
187 if (remaining < kZeroTimeDelta)
188 remaining = kZeroTimeDelta;
189 remaining_.reset(new base::TimeDelta(remaining));
190 }
191
192 void ExpectNoNotifications() {
193 EXPECT_CALL(observer_, ObservedSessionLengthUnlimited()).Times(0);
194 EXPECT_CALL(observer_, ObservedRemainingSessionTimeChanged(_)).Times(0);
195 }
196
197 void ExpectSessionLengthUnlimitedNotification() {
198 EXPECT_CALL(observer_, ObservedSessionLengthUnlimited()).Times(1);
199 EXPECT_CALL(observer_, ObservedRemainingSessionTimeChanged(_)).Times(0);
200 }
201
202 void ExpectRemainingSessionTimeChangedNotification() {
203 EXPECT_CALL(observer_, ObservedSessionLengthUnlimited()).Times(0);
204 EXPECT_CALL(observer_, ObservedRemainingSessionTimeChanged(_)).Times(0);
205 EXPECT_CALL(observer_, ObservedRemainingSessionTimeChanged(*remaining_))
206 .Times(1);
207 }
208
209 void ExpectStopSession() {
210 Mock::VerifyAndClearExpectations(delegate_);
211 EXPECT_CALL(*delegate_, StopSession()).Times(1);
212 }
213
214 void CreateSessionLengthLimiter(bool browser_restarted) {
215 ExpectNoNotifications();
216 session_length_limiter_.reset(
217 new SessionLengthLimiter(delegate_, browser_restarted));
218 Mock::VerifyAndClearExpectations(&observer_);
219 }
220
221 void VerifyNoTimerTickIsEnqueued() {
222 EXPECT_TRUE(runner_->tasks().empty());
223 }
224
225 void VerifyTimerTickIsEnqueued() {
226 ASSERT_EQ(1U, runner_->tasks().size());
227 EXPECT_EQ(kSessionLengthLimitTimerInterval,
228 runner_->tasks().front().first);
229 }
230
231 void VerifyTimerTick() {
232 VerifyTimerTickIsEnqueued();
233 ExpectRemainingSessionTimeChangedNotification();
234 runner_->RunTasks();
235 Mock::VerifyAndClearExpectations(&observer_);
236
237 now_ += kSessionLengthLimitTimerInterval;
238 *remaining_ -= kSessionLengthLimitTimerInterval;
239 if (*remaining_ < kZeroTimeDelta)
240 remaining_.reset(new base::TimeDelta(kZeroTimeDelta));
241 }
242
243 base::Time GetCurrentTime() const {
244 return now_;
245 }
246
247 TestingPrefService local_state_;
248 MockNotificationObserver observer_;
249 MockSessionLengthLimiterDelegate* delegate_; // Owned by
250 // session_length_limiter_.
251 scoped_refptr<ImmediateSingleThreadTaskRunner> runner_;
252
253 base::Time session_start_time_;
254 base::Time now_;
255 scoped_ptr<base::TimeDelta> remaining_;
256
257 scoped_ptr<SessionLengthLimiter> session_length_limiter_;
258 };
259
260 // Verifies that the session start time in local state is updated during login
261 // if no session start time has been stored before.
262 TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeUnset) {
263 CreateSessionLengthLimiter(false);
264 VerifySessionStartTimePref();
265 }
266
267 // Verifies that the session start time in local state is updated during login
268 // if an invalid session start time has been stored before.
269 TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeInvalid) {
270 SetSessionStartTimePref(0);
271 CreateSessionLengthLimiter(false);
272 VerifySessionStartTimePref();
273 }
274
275 // Verifies that the session start time in local state is updated during login
276 // if a session start time lying in the future has been stored before.
277 TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeFuture) {
278 SetSessionStartTimePref(
279 (now_ + base::TimeDelta::FromHours(2)).ToInternalValue());
280 CreateSessionLengthLimiter(false);
281 VerifySessionStartTimePref();
282 }
283
284 // Verifies that the session start time in local state is updated during login
285 // if a valid session start time has been stored before.
286 TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeValid) {
287 const base::Time previous_start_time = now_ - base::TimeDelta::FromHours(2);
288 SetSessionStartTimePref(previous_start_time.ToInternalValue());
289 CreateSessionLengthLimiter(false);
290 VerifySessionStartTimePref();
291 }
292
293 // Verifies that the session start time in local state is updated during restart
294 // after a crash if no session start time has been stored before.
295 TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeUnset) {
296 CreateSessionLengthLimiter(true);
297 VerifySessionStartTimePref();
298 }
299
300 // Verifies that the session start time in local state is updated during restart
301 // after a crash if an invalid session start time has been stored before.
302 TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeInvalid) {
303 SetSessionStartTimePref(0);
304 CreateSessionLengthLimiter(true);
305 VerifySessionStartTimePref();
306 }
307
308 // Verifies that the session start time in local state is updated during restart
309 // after a crash if a session start time lying in the future has been stored
310 // before.
311 TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeFuture) {
312 SetSessionStartTimePref(
313 (now_ + base::TimeDelta::FromHours(2)).ToInternalValue());
314 CreateSessionLengthLimiter(true);
315 VerifySessionStartTimePref();
316 }
317
318 // Verifies that the session start time in local state is *not* updated during
319 // restart after a crash if a valid session start time has been stored before.
320 TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeValid) {
321 session_start_time_ -= base::TimeDelta::FromHours(2);
322 SetSessionStartTimePref(session_start_time_.ToInternalValue());
323 CreateSessionLengthLimiter(true);
324 VerifySessionStartTimePref();
325 }
326
327 // Creates a SessionLengthLimiter without setting a limit. Verifies that the
328 // limiter does not start a timer.
329 TEST_F(SessionLengthLimiterTest, RunWithoutSessionLengthLimit) {
330 base::ThreadTaskRunnerHandle runner_handler(runner_);
331
332 // Create a SessionLengthLimiter.
333 CreateSessionLengthLimiter(false);
334
335 // Verify that no timer tick has been enqueued.
336 VerifyNoTimerTickIsEnqueued();
337 }
338
339 // Creates a SessionLengthLimiter after setting a limit. Verifies that the
340 // limiter starts a timer and sends notifications as the time passes. Verifies
341 // that when the session length reaches the limit, the session is terminated.
342 TEST_F(SessionLengthLimiterTest, RunWithSessionLengthLimit) {
343 base::ThreadTaskRunnerHandle runner_handler(runner_);
344
345 // Set a 60 second session time limit.
346 SetSessionLengthLimitPref(60 * 1000); // 60 seconds.
347
348 // Create a SessionLengthLimiter.
349 CreateSessionLengthLimiter(false);
350
351 // Check timer ticks until the remaining session time reaches zero.
352 while (*remaining_ > kZeroTimeDelta)
353 VerifyTimerTick();
354
355 // Check that the next timer tick leads to the session being terminated.
356 ExpectStopSession();
357 VerifyTimerTick();
358 }
359
360 // Creates a SessionLengthLimiter after setting a 60 second limit, allows 50
361 // seconds of session time to pass, then increases the limit to 90 seconds.
362 // Verifies that the limiter starts a timer and sends notifications as time
363 // passes. Verifies that when the session length reaches the 90 second limit,
364 // the session is terminated.
365 TEST_F(SessionLengthLimiterTest, RunAndIncreaseSessionLengthLimit) {
366 base::ThreadTaskRunnerHandle runner_handler(runner_);
367
368 // Set a 60 second session time limit.
369 SetSessionLengthLimitPref(60 * 1000); // 60 seconds.
370
371 // Create a SessionLengthLimiter.
372 CreateSessionLengthLimiter(false);
373
374 // Check timer ticks for 50 seconds of session time.
375 while (*remaining_ > kTenSeconds)
376 VerifyTimerTick();
377
378 // Increase the session length limit to 90 seconds.
379 SetSessionLengthLimitPref(90 * 1000); // 90 seconds.
380
381 // Check timer ticks until the remaining session time reaches zero.
382 while (*remaining_ > kZeroTimeDelta)
383 VerifyTimerTick();
384
385 // Check that the next timer tick leads to the session being terminated.
386 ExpectStopSession();
387 VerifyTimerTick();
388 }
389
390 // Creates a SessionLengthLimiter after setting a 60 second limit, allows 50
391 // seconds of session time to pass, then decreases the limit to 40 seconds.
392 // Verifies that the limiter starts a timer and sends notifications as time
393 // passes. Verifies that when the limit is decreased to 40 seconds after 50
394 // seconds of session time have passed, the next timer tick causes the session
395 // to be terminated.
396 TEST_F(SessionLengthLimiterTest, RunAndDecreaseSessionLengthLimit) {
397 base::ThreadTaskRunnerHandle runner_handler(runner_);
398
399 // Set a 60 second session time limit.
400 SetSessionLengthLimitPref(60 * 1000); // 60 seconds.
401
402 // Create a SessionLengthLimiter.
403 CreateSessionLengthLimiter(false);
404
405 // Check timer ticks for 50 seconds of session time.
406 while (*remaining_ > kTenSeconds)
407 VerifyTimerTick();
408
409 // Reduce the session length limit below the 50 seconds that have already
410 // elapsed.
411 SetSessionLengthLimitPref(40 * 1000); // 40 seconds.
412
413 // Check that the next timer tick causes the session to be terminated.
414 ExpectStopSession();
415 VerifyTimerTick();
416 }
417
418 // Creates a SessionLengthLimiter after setting a 60 second limit, allows 50
419 // seconds of session time to pass, then removes the limit. Verifies that the
420 // limiter starts a timer and sends notifications as time passes. Verifies that
421 // when the limit is removed, a final notification is sent that there no longer
422 // is a limit and no further notifications or session termination occur.
423 TEST_F(SessionLengthLimiterTest, RunAndRemoveSessionLengthLimit) {
424 base::ThreadTaskRunnerHandle runner_handler(runner_);
425
426 // Set a 60 second session time limit.
427 SetSessionLengthLimitPref(60 * 1000); // 60 seconds.
428
429 // Create a SessionLengthLimiter.
430 CreateSessionLengthLimiter(false);
431
432 // Check timer ticks for 50 seconds of session time.
433 while (*remaining_ > kTenSeconds)
434 VerifyTimerTick();
435
436 // Check that removing the session length limit leads to an immediate
437 // notification.
438 ExpectSessionLengthUnlimitedNotification();
439 local_state_.RemoveUserPref(prefs::kSessionLengthLimit);
440 Mock::VerifyAndClearExpectations(&observer_);
441
442 // Check that the next timer tick does not lead to any notification or to the
443 // session being terminated.
444 ExpectNoNotifications();
445 now_ += kSessionLengthLimitTimerInterval;
446 runner_->RunTasks();
447 }
448
449 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698