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 "extensions/browser/api/idle/idle_api.h"
6 
7 #include <limits.h>
8 
9 #include <memory>
10 #include <string>
11 
12 #include "base/bind.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "extensions/browser/api/idle/idle_api_constants.h"
15 #include "extensions/browser/api/idle/idle_manager.h"
16 #include "extensions/browser/api/idle/idle_manager_factory.h"
17 #include "extensions/browser/api_unittest.h"
18 #include "extensions/browser/event_router.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/browser/unloaded_extension_reason.h"
21 #include "extensions/common/api/idle.h"
22 #include "extensions/common/extension.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 using ::testing::_;
27 
28 namespace idle = extensions::api::idle;
29 
30 namespace extensions {
31 
32 namespace {
33 
34 class MockEventDelegate : public IdleManager::EventDelegate {
35  public:
MockEventDelegate()36   MockEventDelegate() {}
~MockEventDelegate()37   ~MockEventDelegate() override {}
38   MOCK_METHOD2(OnStateChanged, void(const std::string&, ui::IdleState));
RegisterObserver(EventRouter::Observer * observer)39   void RegisterObserver(EventRouter::Observer* observer) override {}
UnregisterObserver(EventRouter::Observer * observer)40   void UnregisterObserver(EventRouter::Observer* observer) override {}
41 };
42 
43 class TestIdleProvider : public IdleManager::IdleTimeProvider {
44  public:
45   TestIdleProvider();
46   ~TestIdleProvider() override;
47   ui::IdleState CalculateIdleState(int idle_threshold) override;
48   int CalculateIdleTime() override;
49   bool CheckIdleStateIsLocked() override;
50 
51   void set_idle_time(int idle_time);
52   void set_locked(bool locked);
53 
54  private:
55   int idle_time_;
56   bool locked_;
57 };
58 
TestIdleProvider()59 TestIdleProvider::TestIdleProvider() : idle_time_(0), locked_(false) {
60 }
61 
~TestIdleProvider()62 TestIdleProvider::~TestIdleProvider() {
63 }
64 
CalculateIdleState(int idle_threshold)65 ui::IdleState TestIdleProvider::CalculateIdleState(int idle_threshold) {
66   if (locked_) {
67     return ui::IDLE_STATE_LOCKED;
68   } else if (idle_time_ >= idle_threshold) {
69     return ui::IDLE_STATE_IDLE;
70   } else {
71     return ui::IDLE_STATE_ACTIVE;
72   }
73 }
74 
CalculateIdleTime()75 int TestIdleProvider::CalculateIdleTime() {
76   return idle_time_;
77 }
78 
CheckIdleStateIsLocked()79 bool TestIdleProvider::CheckIdleStateIsLocked() {
80   return locked_;
81 }
82 
set_idle_time(int idle_time)83 void TestIdleProvider::set_idle_time(int idle_time) {
84   idle_time_ = idle_time;
85 }
86 
set_locked(bool locked)87 void TestIdleProvider::set_locked(bool locked) {
88   locked_ = locked;
89 }
90 
91 class ScopedListen {
92  public:
93   ScopedListen(IdleManager* idle_manager, const std::string& extension_id);
94   ~ScopedListen();
95 
96  private:
97   IdleManager* idle_manager_;
98   const std::string extension_id_;
99 };
100 
ScopedListen(IdleManager * idle_manager,const std::string & extension_id)101 ScopedListen::ScopedListen(IdleManager* idle_manager,
102                            const std::string& extension_id)
103     : idle_manager_(idle_manager), extension_id_(extension_id) {
104   const EventListenerInfo details(idle::OnStateChanged::kEventName,
105                                   extension_id_, GURL(), NULL);
106   idle_manager_->OnListenerAdded(details);
107 }
108 
~ScopedListen()109 ScopedListen::~ScopedListen() {
110   const EventListenerInfo details(idle::OnStateChanged::kEventName,
111                                   extension_id_, GURL(), NULL);
112   idle_manager_->OnListenerRemoved(details);
113 }
114 
IdleManagerTestFactory(content::BrowserContext * context)115 std::unique_ptr<KeyedService> IdleManagerTestFactory(
116     content::BrowserContext* context) {
117   return std::make_unique<IdleManager>(context);
118 }
119 
120 }  // namespace
121 
122 class IdleTest : public ApiUnitTest {
123  public:
124   void SetUp() override;
125 
126  protected:
127   IdleManager* idle_manager_;
128   TestIdleProvider* idle_provider_;
129   testing::StrictMock<MockEventDelegate>* event_delegate_;
130 };
131 
SetUp()132 void IdleTest::SetUp() {
133   ApiUnitTest::SetUp();
134 
135   IdleManagerFactory::GetInstance()->SetTestingFactory(
136       browser_context(), base::BindRepeating(&IdleManagerTestFactory));
137   idle_manager_ = IdleManagerFactory::GetForBrowserContext(browser_context());
138 
139   idle_provider_ = new TestIdleProvider();
140   idle_manager_->SetIdleTimeProviderForTest(
141       std::unique_ptr<IdleManager::IdleTimeProvider>(idle_provider_));
142   event_delegate_ = new testing::StrictMock<MockEventDelegate>();
143   idle_manager_->SetEventDelegateForTest(
144       std::unique_ptr<IdleManager::EventDelegate>(event_delegate_));
145   idle_manager_->Init();
146 }
147 
148 // Verifies that "locked" takes priority over "active".
TEST_F(IdleTest,QueryLockedActive)149 TEST_F(IdleTest, QueryLockedActive) {
150   idle_provider_->set_locked(true);
151   idle_provider_->set_idle_time(0);
152 
153   std::unique_ptr<base::Value> result(
154       RunFunctionAndReturnValue(new IdleQueryStateFunction(), "[60]"));
155 
156   std::string idle_state;
157   ASSERT_TRUE(result->GetAsString(&idle_state));
158   EXPECT_EQ("locked", idle_state);
159 }
160 
161 // Verifies that "locked" takes priority over "idle".
TEST_F(IdleTest,QueryLockedIdle)162 TEST_F(IdleTest, QueryLockedIdle) {
163   idle_provider_->set_locked(true);
164   idle_provider_->set_idle_time(INT_MAX);
165 
166   std::unique_ptr<base::Value> result(
167       RunFunctionAndReturnValue(new IdleQueryStateFunction(), "[60]"));
168 
169   std::string idle_state;
170   ASSERT_TRUE(result->GetAsString(&idle_state));
171   EXPECT_EQ("locked", idle_state);
172 }
173 
174 // Verifies that any amount of idle time less than the detection interval
175 // translates to a state of "active".
TEST_F(IdleTest,QueryActive)176 TEST_F(IdleTest, QueryActive) {
177   idle_provider_->set_locked(false);
178 
179   for (int time = 0; time < 60; ++time) {
180     SCOPED_TRACE(time);
181     idle_provider_->set_idle_time(time);
182 
183     std::unique_ptr<base::Value> result(
184         RunFunctionAndReturnValue(new IdleQueryStateFunction(), "[60]"));
185 
186     std::string idle_state;
187     ASSERT_TRUE(result->GetAsString(&idle_state));
188     EXPECT_EQ("active", idle_state);
189   }
190 }
191 
192 // Verifies that an idle time >= the detection interval returns the "idle"
193 // state.
TEST_F(IdleTest,QueryIdle)194 TEST_F(IdleTest, QueryIdle) {
195   idle_provider_->set_locked(false);
196 
197   for (int time = 80; time >= 60; --time) {
198     SCOPED_TRACE(time);
199     idle_provider_->set_idle_time(time);
200 
201     std::unique_ptr<base::Value> result(
202         RunFunctionAndReturnValue(new IdleQueryStateFunction(), "[60]"));
203 
204     std::string idle_state;
205     ASSERT_TRUE(result->GetAsString(&idle_state));
206     EXPECT_EQ("idle", idle_state);
207   }
208 }
209 
210 // Verifies that requesting a detection interval < 15 has the same effect as
211 // passing in 15.
TEST_F(IdleTest,QueryMinThreshold)212 TEST_F(IdleTest, QueryMinThreshold) {
213   idle_provider_->set_locked(false);
214 
215   for (int threshold = 0; threshold < 20; ++threshold) {
216     for (int time = 10; time < 60; ++time) {
217       SCOPED_TRACE(threshold);
218       SCOPED_TRACE(time);
219       idle_provider_->set_idle_time(time);
220 
221       std::string args = "[" + base::NumberToString(threshold) + "]";
222       std::unique_ptr<base::Value> result(
223           RunFunctionAndReturnValue(new IdleQueryStateFunction(), args));
224 
225       std::string idle_state;
226       ASSERT_TRUE(result->GetAsString(&idle_state));
227 
228       int real_threshold = (threshold < 15) ? 15 : threshold;
229       const char* expected = (time < real_threshold) ? "active" : "idle";
230       EXPECT_EQ(expected, idle_state);
231     }
232   }
233 }
234 
235 // Verifies that passing in a detection interval > 4 hours has the same effect
236 // as passing in 4 hours.
TEST_F(IdleTest,QueryMaxThreshold)237 TEST_F(IdleTest, QueryMaxThreshold) {
238   idle_provider_->set_locked(false);
239 
240   const int kFourHoursInSeconds = 4 * 60 * 60;
241 
242   for (int threshold = kFourHoursInSeconds - 20;
243        threshold < (kFourHoursInSeconds + 20); ++threshold) {
244     for (int time = kFourHoursInSeconds - 30; time < kFourHoursInSeconds + 30;
245          ++time) {
246       SCOPED_TRACE(threshold);
247       SCOPED_TRACE(time);
248       idle_provider_->set_idle_time(time);
249 
250       std::string args = "[" + base::NumberToString(threshold) + "]";
251       std::unique_ptr<base::Value> result(
252           RunFunctionAndReturnValue(new IdleQueryStateFunction(), args));
253 
254       std::string idle_state;
255       ASSERT_TRUE(result->GetAsString(&idle_state));
256 
257       int real_threshold =
258           (threshold > kFourHoursInSeconds) ? kFourHoursInSeconds : threshold;
259       const char* expected = (time < real_threshold) ? "active" : "idle";
260       EXPECT_EQ(expected, idle_state);
261     }
262   }
263 }
264 
265 // Verifies that transitioning from an active to idle state fires an "idle"
266 // OnStateChanged event.
TEST_F(IdleTest,ActiveToIdle)267 TEST_F(IdleTest, ActiveToIdle) {
268   ScopedListen listen_test(idle_manager_, "test");
269 
270   idle_provider_->set_locked(false);
271 
272   for (int time = 0; time < 60; ++time) {
273     SCOPED_TRACE(time);
274     idle_provider_->set_idle_time(time);
275 
276     idle_manager_->UpdateIdleState();
277   }
278 
279   idle_provider_->set_idle_time(60);
280 
281   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_IDLE));
282   idle_manager_->UpdateIdleState();
283   testing::Mock::VerifyAndClearExpectations(event_delegate_);
284 
285   for (int time = 61; time < 75; ++time) {
286     SCOPED_TRACE(time);
287     idle_provider_->set_idle_time(time);
288     idle_manager_->UpdateIdleState();
289   }
290 }
291 
292 // Verifies that locking an active system generates a "locked" event.
TEST_F(IdleTest,ActiveToLocked)293 TEST_F(IdleTest, ActiveToLocked) {
294   ScopedListen listen_test(idle_manager_, "test");
295 
296   idle_provider_->set_locked(true);
297   idle_provider_->set_idle_time(5);
298 
299   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_LOCKED));
300   idle_manager_->UpdateIdleState();
301 }
302 
303 // Verifies that transitioning from an idle to active state generates an
304 // "active" event.
TEST_F(IdleTest,IdleToActive)305 TEST_F(IdleTest, IdleToActive) {
306   ScopedListen listen_test(idle_manager_, "test");
307 
308   idle_provider_->set_locked(false);
309   idle_provider_->set_idle_time(75);
310   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_IDLE));
311   idle_manager_->UpdateIdleState();
312   testing::Mock::VerifyAndClearExpectations(event_delegate_);
313 
314   idle_provider_->set_idle_time(0);
315   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_ACTIVE));
316   idle_manager_->UpdateIdleState();
317 }
318 
319 // Verifies that locking an idle system generates a "locked" event.
TEST_F(IdleTest,IdleToLocked)320 TEST_F(IdleTest, IdleToLocked) {
321   ScopedListen listen_test(idle_manager_, "test");
322 
323   idle_provider_->set_locked(false);
324   idle_provider_->set_idle_time(75);
325 
326   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_IDLE));
327   idle_manager_->UpdateIdleState();
328   testing::Mock::VerifyAndClearExpectations(event_delegate_);
329 
330   idle_provider_->set_locked(true);
331   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_LOCKED));
332   idle_manager_->UpdateIdleState();
333 }
334 
335 // Verifies that unlocking an active system generates an "active" event.
TEST_F(IdleTest,LockedToActive)336 TEST_F(IdleTest, LockedToActive) {
337   ScopedListen listen_test(idle_manager_, "test");
338 
339   idle_provider_->set_locked(true);
340   idle_provider_->set_idle_time(0);
341 
342   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_LOCKED));
343   idle_manager_->UpdateIdleState();
344 
345   idle_provider_->set_locked(false);
346   idle_provider_->set_idle_time(5);
347   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_ACTIVE));
348   idle_manager_->UpdateIdleState();
349 }
350 
351 // Verifies that unlocking an inactive system generates an "idle" event.
TEST_F(IdleTest,LockedToIdle)352 TEST_F(IdleTest, LockedToIdle) {
353   ScopedListen listen_test(idle_manager_, "test");
354 
355   idle_provider_->set_locked(true);
356   idle_provider_->set_idle_time(75);
357   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_LOCKED));
358   idle_manager_->UpdateIdleState();
359   testing::Mock::VerifyAndClearExpectations(event_delegate_);
360 
361   idle_provider_->set_locked(false);
362   EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_IDLE));
363   idle_manager_->UpdateIdleState();
364 }
365 
366 // Verifies that events are routed to extensions that have one or more listeners
367 // in scope.
TEST_F(IdleTest,MultipleExtensions)368 TEST_F(IdleTest, MultipleExtensions) {
369   ScopedListen listen_1(idle_manager_, "1");
370   ScopedListen listen_2(idle_manager_, "2");
371 
372   idle_provider_->set_locked(true);
373   EXPECT_CALL(*event_delegate_, OnStateChanged("1", ui::IDLE_STATE_LOCKED));
374   EXPECT_CALL(*event_delegate_, OnStateChanged("2", ui::IDLE_STATE_LOCKED));
375   idle_manager_->UpdateIdleState();
376   testing::Mock::VerifyAndClearExpectations(event_delegate_);
377 
378   {
379     ScopedListen listen_2prime(idle_manager_, "2");
380     ScopedListen listen_3(idle_manager_, "3");
381     idle_provider_->set_locked(false);
382     EXPECT_CALL(*event_delegate_, OnStateChanged("1", ui::IDLE_STATE_ACTIVE));
383     EXPECT_CALL(*event_delegate_, OnStateChanged("2", ui::IDLE_STATE_ACTIVE));
384     EXPECT_CALL(*event_delegate_, OnStateChanged("3", ui::IDLE_STATE_ACTIVE));
385     idle_manager_->UpdateIdleState();
386     testing::Mock::VerifyAndClearExpectations(event_delegate_);
387   }
388 
389   idle_provider_->set_locked(true);
390   EXPECT_CALL(*event_delegate_, OnStateChanged("1", ui::IDLE_STATE_LOCKED));
391   EXPECT_CALL(*event_delegate_, OnStateChanged("2", ui::IDLE_STATE_LOCKED));
392   idle_manager_->UpdateIdleState();
393 }
394 
395 // Verifies that setDetectionInterval changes the detection interval from the
396 // default of 60 seconds, and that the call only affects a single extension's
397 // IdleMonitor.
TEST_F(IdleTest,SetDetectionInterval)398 TEST_F(IdleTest, SetDetectionInterval) {
399   ScopedListen listen_default(idle_manager_, "default");
400   ScopedListen listen_extension(idle_manager_, extension()->id());
401 
402   std::unique_ptr<base::Value> result45(RunFunctionAndReturnValue(
403       new IdleSetDetectionIntervalFunction(), "[45]"));
404 
405   idle_provider_->set_locked(false);
406   idle_provider_->set_idle_time(44);
407   idle_manager_->UpdateIdleState();
408 
409   idle_provider_->set_idle_time(45);
410   EXPECT_CALL(*event_delegate_,
411               OnStateChanged(extension()->id(), ui::IDLE_STATE_IDLE));
412   idle_manager_->UpdateIdleState();
413   // Verify that the expectation has been fulfilled before incrementing the
414   // time again.
415   testing::Mock::VerifyAndClearExpectations(event_delegate_);
416 
417   idle_provider_->set_idle_time(60);
418   EXPECT_CALL(*event_delegate_, OnStateChanged("default", ui::IDLE_STATE_IDLE));
419   idle_manager_->UpdateIdleState();
420 }
421 
422 // Verifies that setting the detection interval before creating the listener
423 // works correctly.
TEST_F(IdleTest,SetDetectionIntervalBeforeListener)424 TEST_F(IdleTest, SetDetectionIntervalBeforeListener) {
425   std::unique_ptr<base::Value> result45(RunFunctionAndReturnValue(
426       new IdleSetDetectionIntervalFunction(), "[45]"));
427 
428   ScopedListen listen_extension(idle_manager_, extension()->id());
429 
430   idle_provider_->set_locked(false);
431   idle_provider_->set_idle_time(44);
432   idle_manager_->UpdateIdleState();
433 
434   idle_provider_->set_idle_time(45);
435   EXPECT_CALL(*event_delegate_,
436               OnStateChanged(extension()->id(), ui::IDLE_STATE_IDLE));
437   idle_manager_->UpdateIdleState();
438 }
439 
440 // Verifies that setting a detection interval above the maximum value results
441 // in an interval of 4 hours.
TEST_F(IdleTest,SetDetectionIntervalMaximum)442 TEST_F(IdleTest, SetDetectionIntervalMaximum) {
443   ScopedListen listen_extension(idle_manager_, extension()->id());
444 
445   std::unique_ptr<base::Value> result(
446       RunFunctionAndReturnValue(new IdleSetDetectionIntervalFunction(),
447                                 "[18000]"));  // five hours in seconds
448 
449   idle_provider_->set_locked(false);
450   idle_provider_->set_idle_time(4 * 60 * 60 - 1);
451   idle_manager_->UpdateIdleState();
452 
453   idle_provider_->set_idle_time(4 * 60 * 60);
454   EXPECT_CALL(*event_delegate_,
455               OnStateChanged(extension()->id(), ui::IDLE_STATE_IDLE));
456   idle_manager_->UpdateIdleState();
457 }
458 
459 // Verifies that setting a detection interval below the minimum value results
460 // in an interval of 15 seconds.
TEST_F(IdleTest,SetDetectionIntervalMinimum)461 TEST_F(IdleTest, SetDetectionIntervalMinimum) {
462   ScopedListen listen_extension(idle_manager_, extension()->id());
463 
464   std::unique_ptr<base::Value> result(RunFunctionAndReturnValue(
465       new IdleSetDetectionIntervalFunction(), "[10]"));
466 
467   idle_provider_->set_locked(false);
468   idle_provider_->set_idle_time(14);
469   idle_manager_->UpdateIdleState();
470 
471   idle_provider_->set_idle_time(15);
472   EXPECT_CALL(*event_delegate_,
473               OnStateChanged(extension()->id(), ui::IDLE_STATE_IDLE));
474   idle_manager_->UpdateIdleState();
475 }
476 
477 // Verifies that an extension's detection interval is discarded when it unloads.
TEST_F(IdleTest,UnloadCleanup)478 TEST_F(IdleTest, UnloadCleanup) {
479   {
480     ScopedListen listen(idle_manager_, extension()->id());
481 
482     std::unique_ptr<base::Value> result45(RunFunctionAndReturnValue(
483         new IdleSetDetectionIntervalFunction(), "[15]"));
484   }
485 
486   // Listener count dropping to zero does not reset threshold.
487 
488   {
489     ScopedListen listen(idle_manager_, extension()->id());
490     idle_provider_->set_idle_time(16);
491     EXPECT_CALL(*event_delegate_,
492                 OnStateChanged(extension()->id(), ui::IDLE_STATE_IDLE));
493     idle_manager_->UpdateIdleState();
494     testing::Mock::VerifyAndClearExpectations(event_delegate_);
495   }
496 
497   // Threshold will reset after unload (and listen count == 0)
498   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
499   registry->TriggerOnUnloaded(extension(), UnloadedExtensionReason::UNINSTALL);
500 
501   {
502     ScopedListen listen(idle_manager_, extension()->id());
503     idle_manager_->UpdateIdleState();
504     testing::Mock::VerifyAndClearExpectations(event_delegate_);
505 
506     idle_provider_->set_idle_time(61);
507     EXPECT_CALL(*event_delegate_,
508                 OnStateChanged(extension()->id(), ui::IDLE_STATE_IDLE));
509     idle_manager_->UpdateIdleState();
510   }
511 }
512 
513 // Verifies that unloading an extension with no listeners or threshold works.
TEST_F(IdleTest,UnloadOnly)514 TEST_F(IdleTest, UnloadOnly) {
515   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
516   registry->TriggerOnUnloaded(extension(), UnloadedExtensionReason::UNINSTALL);
517 }
518 
519 // Verifies that its ok for the unload notification to happen before all the
520 // listener removals.
TEST_F(IdleTest,UnloadWhileListening)521 TEST_F(IdleTest, UnloadWhileListening) {
522   ScopedListen listen(idle_manager_, extension()->id());
523   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
524   registry->TriggerOnUnloaded(extension(), UnloadedExtensionReason::UNINSTALL);
525 }
526 
527 // Verifies that re-adding a listener after a state change doesn't immediately
528 // fire a change event. Regression test for http://crbug.com/366580.
TEST_F(IdleTest,ReAddListener)529 TEST_F(IdleTest, ReAddListener) {
530   idle_provider_->set_locked(false);
531 
532   {
533     // Fire idle event.
534     ScopedListen listen(idle_manager_, "test");
535     idle_provider_->set_idle_time(60);
536     EXPECT_CALL(*event_delegate_, OnStateChanged("test", ui::IDLE_STATE_IDLE));
537     idle_manager_->UpdateIdleState();
538     testing::Mock::VerifyAndClearExpectations(event_delegate_);
539   }
540 
541   // Trigger active.
542   idle_provider_->set_idle_time(0);
543   idle_manager_->UpdateIdleState();
544 
545   {
546     // Nothing should have fired, the listener wasn't added until afterward.
547     ScopedListen listen(idle_manager_, "test");
548     idle_manager_->UpdateIdleState();
549     testing::Mock::VerifyAndClearExpectations(event_delegate_);
550   }
551 }
552 
553 }  // namespace extensions
554