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