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_api.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/api/idle/idle_api_constants.h"
13 #include "chrome/browser/extensions/api/idle/idle_manager.h"
14 #include "chrome/browser/extensions/api/idle/idle_manager_factory.h"
15 #include "chrome/browser/extensions/event_router.h"
16 #include "chrome/browser/extensions/extension_function_test_utils.h"
17 #include "chrome/common/extensions/api/idle.h"
18 #include "chrome/common/extensions/extension.h"
19 #include "chrome/test/base/browser_with_test_window_test.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_source.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
27 namespace utils = extension_function_test_utils;
28 namespace idle = extensions::api::idle;
30 namespace extensions {
34 class MockEventDelegate : public IdleManager::EventDelegate {
36 MockEventDelegate() {}
37 virtual ~MockEventDelegate() {}
38 MOCK_METHOD2(OnStateChanged, void(const std::string&, IdleState));
39 virtual void RegisterObserver(EventRouter::Observer* observer) {}
40 virtual void UnregisterObserver(EventRouter::Observer* observer) {}
43 class TestIdleProvider : public IdleManager::IdleTimeProvider {
46 virtual ~TestIdleProvider();
47 virtual void CalculateIdleState(int idle_threshold,
48 IdleCallback notify) OVERRIDE;
49 virtual void CalculateIdleTime(IdleTimeCallback notify) OVERRIDE;
50 virtual bool CheckIdleStateIsLocked() OVERRIDE;
52 void set_idle_time(int idle_time);
53 void set_locked(bool locked);
60 TestIdleProvider::TestIdleProvider()
65 TestIdleProvider::~TestIdleProvider() {
68 void TestIdleProvider::CalculateIdleState(int idle_threshold,
69 IdleCallback notify) {
71 notify.Run(IDLE_STATE_LOCKED);
73 if (idle_time_ >= idle_threshold) {
74 notify.Run(IDLE_STATE_IDLE);
76 notify.Run(IDLE_STATE_ACTIVE);
81 void TestIdleProvider::CalculateIdleTime(IdleTimeCallback notify) {
82 notify.Run(idle_time_);
85 bool TestIdleProvider::CheckIdleStateIsLocked() {
89 void TestIdleProvider::set_idle_time(int idle_time) {
90 idle_time_ = idle_time;
93 void TestIdleProvider::set_locked(bool locked) {
99 ScopedListen(IdleManager* idle_manager, const std::string& extension_id);
103 IdleManager* idle_manager_;
104 const std::string extension_id_;
107 ScopedListen::ScopedListen(IdleManager* idle_manager,
108 const std::string& extension_id)
109 : idle_manager_(idle_manager),
110 extension_id_(extension_id) {
111 const EventListenerInfo details(idle::OnStateChanged::kEventName,
113 idle_manager_->OnListenerAdded(details);
116 ScopedListen::~ScopedListen() {
117 const EventListenerInfo details(idle::OnStateChanged::kEventName,
119 idle_manager_->OnListenerRemoved(details);
122 BrowserContextKeyedService* IdleManagerTestFactory(
123 content::BrowserContext* profile) {
124 return new IdleManager(static_cast<Profile*>(profile));
129 class IdleTest : public BrowserWithTestWindowTest {
131 virtual void SetUp() OVERRIDE;
134 base::Value* RunFunctionWithExtension(
135 UIThreadExtensionFunction* function, const std::string& args);
137 IdleManager* idle_manager_;
138 TestIdleProvider* idle_provider_;
139 testing::StrictMock<MockEventDelegate>* event_delegate_;
140 scoped_refptr<extensions::Extension> extension_;
143 void IdleTest::SetUp() {
144 BrowserWithTestWindowTest::SetUp();
146 IdleManagerFactory::GetInstance()->SetTestingFactory(browser()->profile(),
147 &IdleManagerTestFactory);
148 idle_manager_ = IdleManagerFactory::GetForProfile(browser()->profile());
150 extension_ = utils::CreateEmptyExtensionWithLocation(
151 extensions::Manifest::UNPACKED);
153 idle_provider_ = new TestIdleProvider();
154 idle_manager_->SetIdleTimeProviderForTest(
155 scoped_ptr<IdleManager::IdleTimeProvider>(idle_provider_).Pass());
156 event_delegate_ = new testing::StrictMock<MockEventDelegate>();
157 idle_manager_->SetEventDelegateForTest(
158 scoped_ptr<IdleManager::EventDelegate>(event_delegate_).Pass());
159 idle_manager_->Init();
162 base::Value* IdleTest::RunFunctionWithExtension(
163 UIThreadExtensionFunction* function, const std::string& args) {
164 function->set_extension(extension_.get());
165 return utils::RunFunctionAndReturnSingleResult(function, args, browser());
168 // Verifies that "locked" takes priority over "active".
169 TEST_F(IdleTest, QueryLockedActive) {
170 idle_provider_->set_locked(true);
171 idle_provider_->set_idle_time(0);
173 scoped_ptr<base::Value> result(RunFunctionWithExtension(
174 new IdleQueryStateFunction(),
177 std::string idle_state;
178 ASSERT_TRUE(result->GetAsString(&idle_state));
179 EXPECT_EQ("locked", idle_state);
182 // Verifies that "locked" takes priority over "idle".
183 TEST_F(IdleTest, QueryLockedIdle) {
184 idle_provider_->set_locked(true);
185 idle_provider_->set_idle_time(INT_MAX);
187 scoped_ptr<base::Value> result(RunFunctionWithExtension(
188 new IdleQueryStateFunction(),
191 std::string idle_state;
192 ASSERT_TRUE(result->GetAsString(&idle_state));
193 EXPECT_EQ("locked", idle_state);
196 // Verifies that any amount of idle time less than the detection interval
197 // translates to a state of "active".
198 TEST_F(IdleTest, QueryActive) {
199 idle_provider_->set_locked(false);
201 for (int time = 0; time < 60; ++time) {
203 idle_provider_->set_idle_time(time);
205 scoped_ptr<base::Value> result(RunFunctionWithExtension(
206 new IdleQueryStateFunction(),
209 std::string idle_state;
210 ASSERT_TRUE(result->GetAsString(&idle_state));
211 EXPECT_EQ("active", idle_state);
215 // Verifies that an idle time >= the detection interval returns the "idle"
217 TEST_F(IdleTest, QueryIdle) {
218 idle_provider_->set_locked(false);
220 for (int time = 80; time >= 60; --time) {
222 idle_provider_->set_idle_time(time);
224 scoped_ptr<base::Value> result(RunFunctionWithExtension(
225 new IdleQueryStateFunction(),
228 std::string idle_state;
229 ASSERT_TRUE(result->GetAsString(&idle_state));
230 EXPECT_EQ("idle", idle_state);
234 // Verifies that requesting a detection interval < 15 has the same effect as
236 TEST_F(IdleTest, QueryMinThreshold) {
237 idle_provider_->set_locked(false);
239 for (int threshold = 0; threshold < 20; ++threshold) {
240 for (int time = 10; time < 60; ++time) {
241 SCOPED_TRACE(threshold);
243 idle_provider_->set_idle_time(time);
245 std::string args = "[" + base::IntToString(threshold) + "]";
246 scoped_ptr<base::Value> result(RunFunctionWithExtension(
247 new IdleQueryStateFunction(), args));
249 std::string idle_state;
250 ASSERT_TRUE(result->GetAsString(&idle_state));
252 int real_threshold = (threshold < 15) ? 15 : threshold;
253 const char* expected = (time < real_threshold) ? "active" : "idle";
254 EXPECT_EQ(expected, idle_state);
259 // Verifies that passing in a detection interval > 4 hours has the same effect
260 // as passing in 4 hours.
261 TEST_F(IdleTest, QueryMaxThreshold) {
262 idle_provider_->set_locked(false);
264 const int kFourHoursInSeconds = 4*60*60;
266 for (int threshold = kFourHoursInSeconds - 20;
267 threshold < (kFourHoursInSeconds + 20); ++threshold) {
268 for (int time = kFourHoursInSeconds - 30; time < kFourHoursInSeconds + 30;
270 SCOPED_TRACE(threshold);
272 idle_provider_->set_idle_time(time);
274 std::string args = "[" + base::IntToString(threshold) + "]";
275 scoped_ptr<base::Value> result(RunFunctionWithExtension(
276 new IdleQueryStateFunction(), args));
278 std::string idle_state;
279 ASSERT_TRUE(result->GetAsString(&idle_state));
281 int real_threshold = (threshold > kFourHoursInSeconds) ?
282 kFourHoursInSeconds : threshold;
283 const char* expected = (time < real_threshold) ? "active" : "idle";
284 EXPECT_EQ(expected, idle_state);
289 // Verifies that transitioning from an active to idle state fires an "idle"
290 // OnStateChanged event.
291 TEST_F(IdleTest, ActiveToIdle) {
292 ScopedListen listen_test(idle_manager_, "test");
294 idle_provider_->set_locked(false);
296 for (int time = 0; time < 60; ++time) {
298 idle_provider_->set_idle_time(time);
300 idle_manager_->UpdateIdleState();
303 idle_provider_->set_idle_time(60);
305 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
306 idle_manager_->UpdateIdleState();
307 testing::Mock::VerifyAndClearExpectations(event_delegate_);
309 for (int time = 61; time < 75; ++time) {
311 idle_provider_->set_idle_time(time);
312 idle_manager_->UpdateIdleState();
316 // Verifies that locking an active system generates a "locked" event.
317 TEST_F(IdleTest, ActiveToLocked) {
318 ScopedListen listen_test(idle_manager_, "test");
320 idle_provider_->set_locked(true);
321 idle_provider_->set_idle_time(5);
323 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
324 idle_manager_->UpdateIdleState();
327 // Verifies that transitioning from an idle to active state generates an
329 TEST_F(IdleTest, IdleToActive) {
330 ScopedListen listen_test(idle_manager_, "test");
332 idle_provider_->set_locked(false);
333 idle_provider_->set_idle_time(75);
334 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
335 idle_manager_->UpdateIdleState();
336 testing::Mock::VerifyAndClearExpectations(event_delegate_);
338 idle_provider_->set_idle_time(0);
339 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_ACTIVE));
340 idle_manager_->UpdateIdleState();
343 // Verifies that locking an idle system generates a "locked" event.
344 TEST_F(IdleTest, IdleToLocked) {
345 ScopedListen listen_test(idle_manager_, "test");
347 idle_provider_->set_locked(false);
348 idle_provider_->set_idle_time(75);
350 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
351 idle_manager_->UpdateIdleState();
352 testing::Mock::VerifyAndClearExpectations(event_delegate_);
354 idle_provider_->set_locked(true);
355 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
356 idle_manager_->UpdateIdleState();
359 // Verifies that unlocking an active system generates an "active" event.
360 TEST_F(IdleTest, LockedToActive) {
361 ScopedListen listen_test(idle_manager_, "test");
363 idle_provider_->set_locked(true);
364 idle_provider_->set_idle_time(0);
366 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
367 idle_manager_->UpdateIdleState();
369 idle_provider_->set_locked(false);
370 idle_provider_->set_idle_time(5);
371 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_ACTIVE));
372 idle_manager_->UpdateIdleState();
375 // Verifies that unlocking an inactive system generates an "idle" event.
376 TEST_F(IdleTest, LockedToIdle) {
377 ScopedListen listen_test(idle_manager_, "test");
379 idle_provider_->set_locked(true);
380 idle_provider_->set_idle_time(75);
381 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
382 idle_manager_->UpdateIdleState();
383 testing::Mock::VerifyAndClearExpectations(event_delegate_);
385 idle_provider_->set_locked(false);
386 EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
387 idle_manager_->UpdateIdleState();
390 // Verifies that events are routed to extensions that have one or more listeners
392 TEST_F(IdleTest, MultipleExtensions) {
393 ScopedListen listen_1(idle_manager_, "1");
394 ScopedListen listen_2(idle_manager_, "2");
396 idle_provider_->set_locked(true);
397 EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_LOCKED));
398 EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_LOCKED));
399 idle_manager_->UpdateIdleState();
400 testing::Mock::VerifyAndClearExpectations(event_delegate_);
403 ScopedListen listen_2prime(idle_manager_, "2");
404 ScopedListen listen_3(idle_manager_, "3");
405 idle_provider_->set_locked(false);
406 EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_ACTIVE));
407 EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_ACTIVE));
408 EXPECT_CALL(*event_delegate_, OnStateChanged("3", IDLE_STATE_ACTIVE));
409 idle_manager_->UpdateIdleState();
410 testing::Mock::VerifyAndClearExpectations(event_delegate_);
413 idle_provider_->set_locked(true);
414 EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_LOCKED));
415 EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_LOCKED));
416 idle_manager_->UpdateIdleState();
419 // Verifies that setDetectionInterval changes the detection interval from the
420 // default of 60 seconds, and that the call only affects a single extension's
422 TEST_F(IdleTest, SetDetectionInterval) {
423 ScopedListen listen_default(idle_manager_, "default");
424 ScopedListen listen_extension(idle_manager_, extension_->id());
426 scoped_ptr<base::Value> result45(RunFunctionWithExtension(
427 new IdleSetDetectionIntervalFunction(),
430 idle_provider_->set_locked(false);
431 idle_provider_->set_idle_time(44);
432 idle_manager_->UpdateIdleState();
434 idle_provider_->set_idle_time(45);
435 EXPECT_CALL(*event_delegate_,
436 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
437 idle_manager_->UpdateIdleState();
438 // Verify that the expectation has been fulfilled before incrementing the
440 testing::Mock::VerifyAndClearExpectations(event_delegate_);
442 idle_provider_->set_idle_time(60);
443 EXPECT_CALL(*event_delegate_, OnStateChanged("default", IDLE_STATE_IDLE));
444 idle_manager_->UpdateIdleState();
447 // Verifies that setting the detection interval before creating the listener
449 TEST_F(IdleTest, SetDetectionIntervalBeforeListener) {
450 scoped_ptr<base::Value> result45(RunFunctionWithExtension(
451 new IdleSetDetectionIntervalFunction(),
454 ScopedListen listen_extension(idle_manager_, extension_->id());
456 idle_provider_->set_locked(false);
457 idle_provider_->set_idle_time(44);
458 idle_manager_->UpdateIdleState();
460 idle_provider_->set_idle_time(45);
461 EXPECT_CALL(*event_delegate_,
462 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
463 idle_manager_->UpdateIdleState();
466 // Verifies that setting a detection interval above the maximum value results
467 // in an interval of 4 hours.
468 TEST_F(IdleTest, SetDetectionIntervalMaximum) {
469 ScopedListen listen_extension(idle_manager_, extension_->id());
471 scoped_ptr<base::Value> result(RunFunctionWithExtension(
472 new IdleSetDetectionIntervalFunction(),
473 "[18000]")); // five hours in seconds
475 idle_provider_->set_locked(false);
476 idle_provider_->set_idle_time(4*60*60 - 1);
477 idle_manager_->UpdateIdleState();
479 idle_provider_->set_idle_time(4*60*60);
480 EXPECT_CALL(*event_delegate_,
481 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
482 idle_manager_->UpdateIdleState();
485 // Verifies that setting a detection interval below the minimum value results
486 // in an interval of 15 seconds.
487 TEST_F(IdleTest, SetDetectionIntervalMinimum) {
488 ScopedListen listen_extension(idle_manager_, extension_->id());
490 scoped_ptr<base::Value> result(RunFunctionWithExtension(
491 new IdleSetDetectionIntervalFunction(),
494 idle_provider_->set_locked(false);
495 idle_provider_->set_idle_time(14);
496 idle_manager_->UpdateIdleState();
498 idle_provider_->set_idle_time(15);
499 EXPECT_CALL(*event_delegate_,
500 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
501 idle_manager_->UpdateIdleState();
504 // Verifies that an extension's detection interval is discarded when it unloads.
505 TEST_F(IdleTest, UnloadCleanup) {
507 ScopedListen listen(idle_manager_, extension_->id());
509 scoped_ptr<base::Value> result45(RunFunctionWithExtension(
510 new IdleSetDetectionIntervalFunction(),
514 // Listener count dropping to zero does not reset threshold.
517 ScopedListen listen(idle_manager_, extension_->id());
518 idle_provider_->set_idle_time(16);
519 EXPECT_CALL(*event_delegate_,
520 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
521 idle_manager_->UpdateIdleState();
522 testing::Mock::VerifyAndClearExpectations(event_delegate_);
525 // Threshold will reset after unload (and listen count == 0)
526 UnloadedExtensionInfo details(extension_.get(),
527 UnloadedExtensionInfo::REASON_UNINSTALL);
528 idle_manager_->Observe(
529 chrome::NOTIFICATION_EXTENSION_UNLOADED,
530 content::Source<Profile>(browser()->profile()),
531 content::Details<UnloadedExtensionInfo>(&details));
534 ScopedListen listen(idle_manager_, extension_->id());
535 idle_manager_->UpdateIdleState();
536 testing::Mock::VerifyAndClearExpectations(event_delegate_);
538 idle_provider_->set_idle_time(61);
539 EXPECT_CALL(*event_delegate_,
540 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
541 idle_manager_->UpdateIdleState();
545 // Verifies that unloading an extension with no listeners or threshold works.
546 TEST_F(IdleTest, UnloadOnly) {
547 UnloadedExtensionInfo details(extension_.get(),
548 UnloadedExtensionInfo::REASON_UNINSTALL);
549 idle_manager_->Observe(
550 chrome::NOTIFICATION_EXTENSION_UNLOADED,
551 content::Source<Profile>(browser()->profile()),
552 content::Details<UnloadedExtensionInfo>(&details));
555 // Verifies that its ok for the unload notification to happen before all the
556 // listener removals.
557 TEST_F(IdleTest, UnloadWhileListening) {
558 ScopedListen listen(idle_manager_, extension_->id());
559 UnloadedExtensionInfo details(extension_.get(),
560 UnloadedExtensionInfo::REASON_UNINSTALL);
561 idle_manager_->Observe(
562 chrome::NOTIFICATION_EXTENSION_UNLOADED,
563 content::Source<Profile>(browser()->profile()),
564 content::Details<UnloadedExtensionInfo>(&details));
567 } // namespace extensions