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/extension_api_unittest.h"
16 #include "chrome/common/extensions/api/idle.h"
17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_source.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/extension.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
27 namespace idle
= extensions::api::idle
;
29 namespace extensions
{
33 class MockEventDelegate
: public IdleManager::EventDelegate
{
35 MockEventDelegate() {}
36 virtual ~MockEventDelegate() {}
37 MOCK_METHOD2(OnStateChanged
, void(const std::string
&, IdleState
));
38 virtual void RegisterObserver(EventRouter::Observer
* observer
) {}
39 virtual void UnregisterObserver(EventRouter::Observer
* observer
) {}
42 class TestIdleProvider
: public IdleManager::IdleTimeProvider
{
45 ~TestIdleProvider() override
;
46 void CalculateIdleState(int idle_threshold
, IdleCallback notify
) override
;
47 void CalculateIdleTime(IdleTimeCallback notify
) override
;
48 bool CheckIdleStateIsLocked() override
;
50 void set_idle_time(int idle_time
);
51 void set_locked(bool locked
);
58 TestIdleProvider::TestIdleProvider()
63 TestIdleProvider::~TestIdleProvider() {
66 void TestIdleProvider::CalculateIdleState(int idle_threshold
,
67 IdleCallback notify
) {
69 notify
.Run(IDLE_STATE_LOCKED
);
71 if (idle_time_
>= idle_threshold
) {
72 notify
.Run(IDLE_STATE_IDLE
);
74 notify
.Run(IDLE_STATE_ACTIVE
);
79 void TestIdleProvider::CalculateIdleTime(IdleTimeCallback notify
) {
80 notify
.Run(idle_time_
);
83 bool TestIdleProvider::CheckIdleStateIsLocked() {
87 void TestIdleProvider::set_idle_time(int idle_time
) {
88 idle_time_
= idle_time
;
91 void TestIdleProvider::set_locked(bool locked
) {
97 ScopedListen(IdleManager
* idle_manager
, const std::string
& extension_id
);
101 IdleManager
* idle_manager_
;
102 const std::string extension_id_
;
105 ScopedListen::ScopedListen(IdleManager
* idle_manager
,
106 const std::string
& extension_id
)
107 : idle_manager_(idle_manager
),
108 extension_id_(extension_id
) {
109 const EventListenerInfo
details(
110 idle::OnStateChanged::kEventName
, extension_id_
, GURL(), NULL
);
111 idle_manager_
->OnListenerAdded(details
);
114 ScopedListen::~ScopedListen() {
115 const EventListenerInfo
details(
116 idle::OnStateChanged::kEventName
, extension_id_
, GURL(), NULL
);
117 idle_manager_
->OnListenerRemoved(details
);
120 KeyedService
* IdleManagerTestFactory(content::BrowserContext
* context
) {
121 return new IdleManager(context
);
126 // TODO(derat): Make this instead derive from extensions::ApiUnitTest after
127 // moving it out of the unit_tests target. Its base class can't be changed
128 // before then since doing so results in crashes due to multiple
129 // content::NotificationService instances being created.
130 class IdleTest
: public ExtensionApiUnittest
{
132 void SetUp() override
;
135 IdleManager
* idle_manager_
;
136 TestIdleProvider
* idle_provider_
;
137 testing::StrictMock
<MockEventDelegate
>* event_delegate_
;
140 void IdleTest::SetUp() {
141 ExtensionApiUnittest::SetUp();
143 IdleManagerFactory::GetInstance()->SetTestingFactory(browser()->profile(),
144 &IdleManagerTestFactory
);
145 idle_manager_
= IdleManagerFactory::GetForBrowserContext(
146 browser()->profile());
148 idle_provider_
= new TestIdleProvider();
149 idle_manager_
->SetIdleTimeProviderForTest(
150 scoped_ptr
<IdleManager::IdleTimeProvider
>(idle_provider_
).Pass());
151 event_delegate_
= new testing::StrictMock
<MockEventDelegate
>();
152 idle_manager_
->SetEventDelegateForTest(
153 scoped_ptr
<IdleManager::EventDelegate
>(event_delegate_
).Pass());
154 idle_manager_
->Init();
157 // Verifies that "locked" takes priority over "active".
158 TEST_F(IdleTest
, QueryLockedActive
) {
159 idle_provider_
->set_locked(true);
160 idle_provider_
->set_idle_time(0);
162 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
163 new IdleQueryStateFunction(),
166 std::string idle_state
;
167 ASSERT_TRUE(result
->GetAsString(&idle_state
));
168 EXPECT_EQ("locked", idle_state
);
171 // Verifies that "locked" takes priority over "idle".
172 TEST_F(IdleTest
, QueryLockedIdle
) {
173 idle_provider_
->set_locked(true);
174 idle_provider_
->set_idle_time(INT_MAX
);
176 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
177 new IdleQueryStateFunction(),
180 std::string idle_state
;
181 ASSERT_TRUE(result
->GetAsString(&idle_state
));
182 EXPECT_EQ("locked", idle_state
);
185 // Verifies that any amount of idle time less than the detection interval
186 // translates to a state of "active".
187 TEST_F(IdleTest
, QueryActive
) {
188 idle_provider_
->set_locked(false);
190 for (int time
= 0; time
< 60; ++time
) {
192 idle_provider_
->set_idle_time(time
);
194 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
195 new IdleQueryStateFunction(),
198 std::string idle_state
;
199 ASSERT_TRUE(result
->GetAsString(&idle_state
));
200 EXPECT_EQ("active", idle_state
);
204 // Verifies that an idle time >= the detection interval returns the "idle"
206 TEST_F(IdleTest
, QueryIdle
) {
207 idle_provider_
->set_locked(false);
209 for (int time
= 80; time
>= 60; --time
) {
211 idle_provider_
->set_idle_time(time
);
213 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
214 new IdleQueryStateFunction(),
217 std::string idle_state
;
218 ASSERT_TRUE(result
->GetAsString(&idle_state
));
219 EXPECT_EQ("idle", idle_state
);
223 // Verifies that requesting a detection interval < 15 has the same effect as
225 TEST_F(IdleTest
, QueryMinThreshold
) {
226 idle_provider_
->set_locked(false);
228 for (int threshold
= 0; threshold
< 20; ++threshold
) {
229 for (int time
= 10; time
< 60; ++time
) {
230 SCOPED_TRACE(threshold
);
232 idle_provider_
->set_idle_time(time
);
234 std::string args
= "[" + base::IntToString(threshold
) + "]";
235 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
236 new IdleQueryStateFunction(), args
));
238 std::string idle_state
;
239 ASSERT_TRUE(result
->GetAsString(&idle_state
));
241 int real_threshold
= (threshold
< 15) ? 15 : threshold
;
242 const char* expected
= (time
< real_threshold
) ? "active" : "idle";
243 EXPECT_EQ(expected
, idle_state
);
248 // Verifies that passing in a detection interval > 4 hours has the same effect
249 // as passing in 4 hours.
250 TEST_F(IdleTest
, QueryMaxThreshold
) {
251 idle_provider_
->set_locked(false);
253 const int kFourHoursInSeconds
= 4*60*60;
255 for (int threshold
= kFourHoursInSeconds
- 20;
256 threshold
< (kFourHoursInSeconds
+ 20); ++threshold
) {
257 for (int time
= kFourHoursInSeconds
- 30; time
< kFourHoursInSeconds
+ 30;
259 SCOPED_TRACE(threshold
);
261 idle_provider_
->set_idle_time(time
);
263 std::string args
= "[" + base::IntToString(threshold
) + "]";
264 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
265 new IdleQueryStateFunction(), args
));
267 std::string idle_state
;
268 ASSERT_TRUE(result
->GetAsString(&idle_state
));
270 int real_threshold
= (threshold
> kFourHoursInSeconds
) ?
271 kFourHoursInSeconds
: threshold
;
272 const char* expected
= (time
< real_threshold
) ? "active" : "idle";
273 EXPECT_EQ(expected
, idle_state
);
278 // Verifies that transitioning from an active to idle state fires an "idle"
279 // OnStateChanged event.
280 TEST_F(IdleTest
, ActiveToIdle
) {
281 ScopedListen
listen_test(idle_manager_
, "test");
283 idle_provider_
->set_locked(false);
285 for (int time
= 0; time
< 60; ++time
) {
287 idle_provider_
->set_idle_time(time
);
289 idle_manager_
->UpdateIdleState();
292 idle_provider_
->set_idle_time(60);
294 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_IDLE
));
295 idle_manager_
->UpdateIdleState();
296 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
298 for (int time
= 61; time
< 75; ++time
) {
300 idle_provider_
->set_idle_time(time
);
301 idle_manager_
->UpdateIdleState();
305 // Verifies that locking an active system generates a "locked" event.
306 TEST_F(IdleTest
, ActiveToLocked
) {
307 ScopedListen
listen_test(idle_manager_
, "test");
309 idle_provider_
->set_locked(true);
310 idle_provider_
->set_idle_time(5);
312 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_LOCKED
));
313 idle_manager_
->UpdateIdleState();
316 // Verifies that transitioning from an idle to active state generates an
318 TEST_F(IdleTest
, IdleToActive
) {
319 ScopedListen
listen_test(idle_manager_
, "test");
321 idle_provider_
->set_locked(false);
322 idle_provider_
->set_idle_time(75);
323 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_IDLE
));
324 idle_manager_
->UpdateIdleState();
325 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
327 idle_provider_
->set_idle_time(0);
328 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_ACTIVE
));
329 idle_manager_
->UpdateIdleState();
332 // Verifies that locking an idle system generates a "locked" event.
333 TEST_F(IdleTest
, IdleToLocked
) {
334 ScopedListen
listen_test(idle_manager_
, "test");
336 idle_provider_
->set_locked(false);
337 idle_provider_
->set_idle_time(75);
339 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_IDLE
));
340 idle_manager_
->UpdateIdleState();
341 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
343 idle_provider_
->set_locked(true);
344 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_LOCKED
));
345 idle_manager_
->UpdateIdleState();
348 // Verifies that unlocking an active system generates an "active" event.
349 TEST_F(IdleTest
, LockedToActive
) {
350 ScopedListen
listen_test(idle_manager_
, "test");
352 idle_provider_
->set_locked(true);
353 idle_provider_
->set_idle_time(0);
355 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_LOCKED
));
356 idle_manager_
->UpdateIdleState();
358 idle_provider_
->set_locked(false);
359 idle_provider_
->set_idle_time(5);
360 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_ACTIVE
));
361 idle_manager_
->UpdateIdleState();
364 // Verifies that unlocking an inactive system generates an "idle" event.
365 TEST_F(IdleTest
, LockedToIdle
) {
366 ScopedListen
listen_test(idle_manager_
, "test");
368 idle_provider_
->set_locked(true);
369 idle_provider_
->set_idle_time(75);
370 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_LOCKED
));
371 idle_manager_
->UpdateIdleState();
372 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
374 idle_provider_
->set_locked(false);
375 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_IDLE
));
376 idle_manager_
->UpdateIdleState();
379 // Verifies that events are routed to extensions that have one or more listeners
381 TEST_F(IdleTest
, MultipleExtensions
) {
382 ScopedListen
listen_1(idle_manager_
, "1");
383 ScopedListen
listen_2(idle_manager_
, "2");
385 idle_provider_
->set_locked(true);
386 EXPECT_CALL(*event_delegate_
, OnStateChanged("1", IDLE_STATE_LOCKED
));
387 EXPECT_CALL(*event_delegate_
, OnStateChanged("2", IDLE_STATE_LOCKED
));
388 idle_manager_
->UpdateIdleState();
389 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
392 ScopedListen
listen_2prime(idle_manager_
, "2");
393 ScopedListen
listen_3(idle_manager_
, "3");
394 idle_provider_
->set_locked(false);
395 EXPECT_CALL(*event_delegate_
, OnStateChanged("1", IDLE_STATE_ACTIVE
));
396 EXPECT_CALL(*event_delegate_
, OnStateChanged("2", IDLE_STATE_ACTIVE
));
397 EXPECT_CALL(*event_delegate_
, OnStateChanged("3", IDLE_STATE_ACTIVE
));
398 idle_manager_
->UpdateIdleState();
399 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
402 idle_provider_
->set_locked(true);
403 EXPECT_CALL(*event_delegate_
, OnStateChanged("1", IDLE_STATE_LOCKED
));
404 EXPECT_CALL(*event_delegate_
, OnStateChanged("2", IDLE_STATE_LOCKED
));
405 idle_manager_
->UpdateIdleState();
408 // Verifies that setDetectionInterval changes the detection interval from the
409 // default of 60 seconds, and that the call only affects a single extension's
411 TEST_F(IdleTest
, SetDetectionInterval
) {
412 ScopedListen
listen_default(idle_manager_
, "default");
413 ScopedListen
listen_extension(idle_manager_
, extension()->id());
415 scoped_ptr
<base::Value
> result45(RunFunctionAndReturnValue(
416 new IdleSetDetectionIntervalFunction(),
419 idle_provider_
->set_locked(false);
420 idle_provider_
->set_idle_time(44);
421 idle_manager_
->UpdateIdleState();
423 idle_provider_
->set_idle_time(45);
424 EXPECT_CALL(*event_delegate_
,
425 OnStateChanged(extension()->id(), IDLE_STATE_IDLE
));
426 idle_manager_
->UpdateIdleState();
427 // Verify that the expectation has been fulfilled before incrementing the
429 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
431 idle_provider_
->set_idle_time(60);
432 EXPECT_CALL(*event_delegate_
, OnStateChanged("default", IDLE_STATE_IDLE
));
433 idle_manager_
->UpdateIdleState();
436 // Verifies that setting the detection interval before creating the listener
438 TEST_F(IdleTest
, SetDetectionIntervalBeforeListener
) {
439 scoped_ptr
<base::Value
> result45(RunFunctionAndReturnValue(
440 new IdleSetDetectionIntervalFunction(),
443 ScopedListen
listen_extension(idle_manager_
, extension()->id());
445 idle_provider_
->set_locked(false);
446 idle_provider_
->set_idle_time(44);
447 idle_manager_
->UpdateIdleState();
449 idle_provider_
->set_idle_time(45);
450 EXPECT_CALL(*event_delegate_
,
451 OnStateChanged(extension()->id(), IDLE_STATE_IDLE
));
452 idle_manager_
->UpdateIdleState();
455 // Verifies that setting a detection interval above the maximum value results
456 // in an interval of 4 hours.
457 TEST_F(IdleTest
, SetDetectionIntervalMaximum
) {
458 ScopedListen
listen_extension(idle_manager_
, extension()->id());
460 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
461 new IdleSetDetectionIntervalFunction(),
462 "[18000]")); // five hours in seconds
464 idle_provider_
->set_locked(false);
465 idle_provider_
->set_idle_time(4*60*60 - 1);
466 idle_manager_
->UpdateIdleState();
468 idle_provider_
->set_idle_time(4*60*60);
469 EXPECT_CALL(*event_delegate_
,
470 OnStateChanged(extension()->id(), IDLE_STATE_IDLE
));
471 idle_manager_
->UpdateIdleState();
474 // Verifies that setting a detection interval below the minimum value results
475 // in an interval of 15 seconds.
476 TEST_F(IdleTest
, SetDetectionIntervalMinimum
) {
477 ScopedListen
listen_extension(idle_manager_
, extension()->id());
479 scoped_ptr
<base::Value
> result(RunFunctionAndReturnValue(
480 new IdleSetDetectionIntervalFunction(),
483 idle_provider_
->set_locked(false);
484 idle_provider_
->set_idle_time(14);
485 idle_manager_
->UpdateIdleState();
487 idle_provider_
->set_idle_time(15);
488 EXPECT_CALL(*event_delegate_
,
489 OnStateChanged(extension()->id(), IDLE_STATE_IDLE
));
490 idle_manager_
->UpdateIdleState();
493 // Verifies that an extension's detection interval is discarded when it unloads.
494 TEST_F(IdleTest
, UnloadCleanup
) {
496 ScopedListen
listen(idle_manager_
, extension()->id());
498 scoped_ptr
<base::Value
> result45(RunFunctionAndReturnValue(
499 new IdleSetDetectionIntervalFunction(),
503 // Listener count dropping to zero does not reset threshold.
506 ScopedListen
listen(idle_manager_
, extension()->id());
507 idle_provider_
->set_idle_time(16);
508 EXPECT_CALL(*event_delegate_
,
509 OnStateChanged(extension()->id(), IDLE_STATE_IDLE
));
510 idle_manager_
->UpdateIdleState();
511 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
514 // Threshold will reset after unload (and listen count == 0)
515 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
516 registry
->TriggerOnUnloaded(extension(),
517 UnloadedExtensionInfo::REASON_UNINSTALL
);
520 ScopedListen
listen(idle_manager_
, extension()->id());
521 idle_manager_
->UpdateIdleState();
522 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
524 idle_provider_
->set_idle_time(61);
525 EXPECT_CALL(*event_delegate_
,
526 OnStateChanged(extension()->id(), IDLE_STATE_IDLE
));
527 idle_manager_
->UpdateIdleState();
531 // Verifies that unloading an extension with no listeners or threshold works.
532 TEST_F(IdleTest
, UnloadOnly
) {
533 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
534 registry
->TriggerOnUnloaded(extension(),
535 UnloadedExtensionInfo::REASON_UNINSTALL
);
538 // Verifies that its ok for the unload notification to happen before all the
539 // listener removals.
540 TEST_F(IdleTest
, UnloadWhileListening
) {
541 ScopedListen
listen(idle_manager_
, extension()->id());
542 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
543 registry
->TriggerOnUnloaded(extension(),
544 UnloadedExtensionInfo::REASON_UNINSTALL
);
547 // Verifies that re-adding a listener after a state change doesn't immediately
548 // fire a change event. Regression test for http://crbug.com/366580.
549 TEST_F(IdleTest
, ReAddListener
) {
550 idle_provider_
->set_locked(false);
554 ScopedListen
listen(idle_manager_
, "test");
555 idle_provider_
->set_idle_time(60);
556 EXPECT_CALL(*event_delegate_
, OnStateChanged("test", IDLE_STATE_IDLE
));
557 idle_manager_
->UpdateIdleState();
558 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
562 idle_provider_
->set_idle_time(0);
563 idle_manager_
->UpdateIdleState();
566 // Nothing should have fired, the listener wasn't added until afterward.
567 ScopedListen
listen(idle_manager_
, "test");
568 idle_manager_
->UpdateIdleState();
569 testing::Mock::VerifyAndClearExpectations(event_delegate_
);
573 } // namespace extensions