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