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