1 // Copyright 2013 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 "ui/message_center/message_center_impl.h" 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/run_loop.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "ui/gfx/canvas.h" 13 #include "ui/gfx/size.h" 14 #include "ui/message_center/message_center.h" 15 #include "ui/message_center/message_center_types.h" 16 #include "ui/message_center/notification_blocker.h" 17 #include "ui/message_center/notification_types.h" 18 #include "ui/message_center/notifier_settings.h" 19 20 using base::UTF8ToUTF16; 21 22 namespace message_center { 23 namespace { 24 25 class MessageCenterImplTest : public testing::Test, 26 public MessageCenterObserver { 27 public: 28 MessageCenterImplTest() {} 29 30 virtual void SetUp() OVERRIDE { 31 MessageCenter::Initialize(); 32 message_center_ = MessageCenter::Get(); 33 loop_.reset(new base::MessageLoop); 34 run_loop_.reset(new base::RunLoop()); 35 closure_ = run_loop_->QuitClosure(); 36 } 37 38 virtual void TearDown() OVERRIDE { 39 run_loop_.reset(); 40 loop_.reset(); 41 message_center_ = NULL; 42 MessageCenter::Shutdown(); 43 } 44 45 MessageCenter* message_center() const { return message_center_; } 46 NotifierSettingsObserver* notifier_settings_observer() const { 47 return static_cast<NotifierSettingsObserver*>(message_center_impl()); 48 } 49 MessageCenterImpl* message_center_impl() const { 50 return reinterpret_cast<MessageCenterImpl*>(message_center_); 51 } 52 53 base::RunLoop* run_loop() const { return run_loop_.get(); } 54 base::Closure closure() const { return closure_; } 55 56 protected: 57 Notification* CreateSimpleNotification(const std::string& id) { 58 return CreateNotificationWithNotifierId( 59 id, 60 "app1", 61 NOTIFICATION_TYPE_SIMPLE); 62 } 63 64 Notification* CreateSimpleNotificationWithNotifierId( 65 const std::string& id, const std::string& notifier_id) { 66 return CreateNotificationWithNotifierId( 67 id, 68 notifier_id, 69 NOTIFICATION_TYPE_SIMPLE); 70 } 71 72 Notification* CreateNotification(const std::string& id, 73 message_center::NotificationType type) { 74 return CreateNotificationWithNotifierId(id, "app1", type); 75 } 76 77 Notification* CreateNotificationWithNotifierId( 78 const std::string& id, 79 const std::string& notifier_id, 80 message_center::NotificationType type) { 81 RichNotificationData optional_fields; 82 optional_fields.buttons.push_back(ButtonInfo(UTF8ToUTF16("foo"))); 83 optional_fields.buttons.push_back(ButtonInfo(UTF8ToUTF16("foo"))); 84 return new Notification(type, 85 id, 86 UTF8ToUTF16("title"), 87 UTF8ToUTF16(id), 88 gfx::Image() /* icon */, 89 base::string16() /* display_source */, 90 NotifierId(NotifierId::APPLICATION, notifier_id), 91 optional_fields, 92 NULL); 93 } 94 95 96 private: 97 MessageCenter* message_center_; 98 scoped_ptr<base::MessageLoop> loop_; 99 scoped_ptr<base::RunLoop> run_loop_; 100 base::Closure closure_; 101 102 DISALLOW_COPY_AND_ASSIGN(MessageCenterImplTest); 103 }; 104 105 class ToggledNotificationBlocker : public NotificationBlocker { 106 public: 107 explicit ToggledNotificationBlocker(MessageCenter* message_center) 108 : NotificationBlocker(message_center), 109 notifications_enabled_(true) {} 110 virtual ~ToggledNotificationBlocker() {} 111 112 void SetNotificationsEnabled(bool enabled) { 113 if (notifications_enabled_ != enabled) { 114 notifications_enabled_ = enabled; 115 NotifyBlockingStateChanged(); 116 } 117 } 118 119 // NotificationBlocker overrides: 120 virtual bool ShouldShowNotificationAsPopup( 121 const message_center::NotifierId& notifier_id) const OVERRIDE { 122 return notifications_enabled_; 123 } 124 125 private: 126 bool notifications_enabled_; 127 128 DISALLOW_COPY_AND_ASSIGN(ToggledNotificationBlocker); 129 }; 130 131 class PopupNotificationBlocker : public ToggledNotificationBlocker { 132 public: 133 PopupNotificationBlocker(MessageCenter* message_center, 134 const NotifierId& allowed_notifier) 135 : ToggledNotificationBlocker(message_center), 136 allowed_notifier_(allowed_notifier) {} 137 virtual ~PopupNotificationBlocker() {} 138 139 // NotificationBlocker overrides: 140 virtual bool ShouldShowNotificationAsPopup( 141 const NotifierId& notifier_id) const OVERRIDE { 142 return (notifier_id == allowed_notifier_) || 143 ToggledNotificationBlocker::ShouldShowNotificationAsPopup(notifier_id); 144 } 145 146 private: 147 NotifierId allowed_notifier_; 148 149 DISALLOW_COPY_AND_ASSIGN(PopupNotificationBlocker); 150 }; 151 152 class TotalNotificationBlocker : public PopupNotificationBlocker { 153 public: 154 TotalNotificationBlocker(MessageCenter* message_center, 155 const NotifierId& allowed_notifier) 156 : PopupNotificationBlocker(message_center, allowed_notifier) {} 157 virtual ~TotalNotificationBlocker() {} 158 159 // NotificationBlocker overrides: 160 virtual bool ShouldShowNotification( 161 const NotifierId& notifier_id) const OVERRIDE { 162 return ShouldShowNotificationAsPopup(notifier_id); 163 } 164 165 private: 166 DISALLOW_COPY_AND_ASSIGN(TotalNotificationBlocker); 167 }; 168 169 bool PopupNotificationsContain( 170 const NotificationList::PopupNotifications& popups, 171 const std::string& id) { 172 for (NotificationList::PopupNotifications::const_iterator iter = 173 popups.begin(); iter != popups.end(); ++iter) { 174 if ((*iter)->id() == id) 175 return true; 176 } 177 return false; 178 } 179 180 // Right now, MessageCenter::HasNotification() returns regardless of blockers. 181 bool NotificationsContain( 182 const NotificationList::Notifications& notifications, 183 const std::string& id) { 184 for (NotificationList::Notifications::const_iterator iter = 185 notifications.begin(); iter != notifications.end(); ++iter) { 186 if ((*iter)->id() == id) 187 return true; 188 } 189 return false; 190 } 191 192 } // namespace 193 194 namespace internal { 195 196 class MockPopupTimersController : public PopupTimersController { 197 public: 198 MockPopupTimersController(MessageCenter* message_center, 199 base::Closure quit_closure) 200 : PopupTimersController(message_center), 201 timer_finished_(false), 202 quit_closure_(quit_closure) {} 203 virtual ~MockPopupTimersController() {} 204 205 virtual void TimerFinished(const std::string& id) OVERRIDE { 206 base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_); 207 timer_finished_ = true; 208 last_id_ = id; 209 } 210 211 bool timer_finished() const { return timer_finished_; } 212 const std::string& last_id() const { return last_id_; } 213 214 private: 215 bool timer_finished_; 216 std::string last_id_; 217 base::Closure quit_closure_; 218 }; 219 220 TEST_F(MessageCenterImplTest, PopupTimersEmptyController) { 221 scoped_ptr<PopupTimersController> popup_timers_controller = 222 make_scoped_ptr(new PopupTimersController(message_center())); 223 224 // Test that all functions succed without any timers created. 225 popup_timers_controller->PauseAll(); 226 popup_timers_controller->StartAll(); 227 popup_timers_controller->CancelAll(); 228 popup_timers_controller->TimerFinished("unknown"); 229 popup_timers_controller->PauseTimer("unknown"); 230 popup_timers_controller->CancelTimer("unknown"); 231 } 232 233 TEST_F(MessageCenterImplTest, PopupTimersControllerStartTimer) { 234 scoped_ptr<MockPopupTimersController> popup_timers_controller = 235 make_scoped_ptr( 236 new MockPopupTimersController(message_center(), closure())); 237 popup_timers_controller->StartTimer("test", 238 base::TimeDelta::FromMilliseconds(1)); 239 run_loop()->Run(); 240 EXPECT_TRUE(popup_timers_controller->timer_finished()); 241 } 242 243 TEST_F(MessageCenterImplTest, PopupTimersControllerPauseTimer) { 244 scoped_ptr<MockPopupTimersController> popup_timers_controller = 245 make_scoped_ptr( 246 new MockPopupTimersController(message_center(), closure())); 247 popup_timers_controller->StartTimer("test", 248 base::TimeDelta::FromMilliseconds(1)); 249 popup_timers_controller->PauseTimer("test"); 250 run_loop()->RunUntilIdle(); 251 252 EXPECT_FALSE(popup_timers_controller->timer_finished()); 253 } 254 255 TEST_F(MessageCenterImplTest, PopupTimersControllerCancelTimer) { 256 scoped_ptr<MockPopupTimersController> popup_timers_controller = 257 make_scoped_ptr( 258 new MockPopupTimersController(message_center(), closure())); 259 popup_timers_controller->StartTimer("test", 260 base::TimeDelta::FromMilliseconds(1)); 261 popup_timers_controller->CancelTimer("test"); 262 run_loop()->RunUntilIdle(); 263 264 EXPECT_FALSE(popup_timers_controller->timer_finished()); 265 } 266 267 TEST_F(MessageCenterImplTest, PopupTimersControllerPauseAllTimers) { 268 scoped_ptr<MockPopupTimersController> popup_timers_controller = 269 make_scoped_ptr( 270 new MockPopupTimersController(message_center(), closure())); 271 popup_timers_controller->StartTimer("test", 272 base::TimeDelta::FromMilliseconds(1)); 273 popup_timers_controller->PauseAll(); 274 run_loop()->RunUntilIdle(); 275 276 EXPECT_FALSE(popup_timers_controller->timer_finished()); 277 } 278 279 TEST_F(MessageCenterImplTest, PopupTimersControllerStartAllTimers) { 280 scoped_ptr<MockPopupTimersController> popup_timers_controller = 281 make_scoped_ptr( 282 new MockPopupTimersController(message_center(), closure())); 283 popup_timers_controller->StartTimer("test", 284 base::TimeDelta::FromMilliseconds(1)); 285 popup_timers_controller->PauseAll(); 286 popup_timers_controller->StartAll(); 287 run_loop()->Run(); 288 289 EXPECT_TRUE(popup_timers_controller->timer_finished()); 290 } 291 292 TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimers) { 293 scoped_ptr<MockPopupTimersController> popup_timers_controller = 294 make_scoped_ptr( 295 new MockPopupTimersController(message_center(), closure())); 296 popup_timers_controller->StartTimer("test", 297 base::TimeDelta::FromMilliseconds(5)); 298 popup_timers_controller->StartTimer("test2", 299 base::TimeDelta::FromMilliseconds(1)); 300 popup_timers_controller->StartTimer("test3", 301 base::TimeDelta::FromMilliseconds(3)); 302 popup_timers_controller->PauseAll(); 303 popup_timers_controller->StartAll(); 304 run_loop()->Run(); 305 306 EXPECT_EQ(popup_timers_controller->last_id(), "test2"); 307 EXPECT_TRUE(popup_timers_controller->timer_finished()); 308 } 309 310 TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimersPause) { 311 scoped_ptr<MockPopupTimersController> popup_timers_controller = 312 make_scoped_ptr( 313 new MockPopupTimersController(message_center(), closure())); 314 popup_timers_controller->StartTimer("test", 315 base::TimeDelta::FromMilliseconds(5)); 316 popup_timers_controller->StartTimer("test2", 317 base::TimeDelta::FromMilliseconds(1)); 318 popup_timers_controller->StartTimer("test3", 319 base::TimeDelta::FromMilliseconds(3)); 320 popup_timers_controller->PauseTimer("test2"); 321 322 run_loop()->Run(); 323 324 EXPECT_EQ(popup_timers_controller->last_id(), "test3"); 325 EXPECT_TRUE(popup_timers_controller->timer_finished()); 326 } 327 328 TEST_F(MessageCenterImplTest, PopupTimersControllerResetTimer) { 329 scoped_ptr<MockPopupTimersController> popup_timers_controller = 330 make_scoped_ptr( 331 new MockPopupTimersController(message_center(), closure())); 332 popup_timers_controller->StartTimer("test", 333 base::TimeDelta::FromMilliseconds(5)); 334 popup_timers_controller->StartTimer("test2", 335 base::TimeDelta::FromMilliseconds(1)); 336 popup_timers_controller->StartTimer("test3", 337 base::TimeDelta::FromMilliseconds(3)); 338 popup_timers_controller->PauseTimer("test2"); 339 popup_timers_controller->ResetTimer("test", 340 base::TimeDelta::FromMilliseconds(2)); 341 342 run_loop()->Run(); 343 344 EXPECT_EQ(popup_timers_controller->last_id(), "test"); 345 EXPECT_TRUE(popup_timers_controller->timer_finished()); 346 } 347 348 TEST_F(MessageCenterImplTest, NotificationBlocker) { 349 NotifierId notifier_id(NotifierId::APPLICATION, "app1"); 350 // Multiple blockers to verify the case that one blocker blocks but another 351 // doesn't. 352 ToggledNotificationBlocker blocker1(message_center()); 353 ToggledNotificationBlocker blocker2(message_center()); 354 355 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 356 NOTIFICATION_TYPE_SIMPLE, 357 "id1", 358 UTF8ToUTF16("title"), 359 UTF8ToUTF16("message"), 360 gfx::Image() /* icon */, 361 base::string16() /* display_source */, 362 notifier_id, 363 RichNotificationData(), 364 NULL))); 365 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 366 NOTIFICATION_TYPE_SIMPLE, 367 "id2", 368 UTF8ToUTF16("title"), 369 UTF8ToUTF16("message"), 370 gfx::Image() /* icon */, 371 base::string16() /* display_source */, 372 notifier_id, 373 RichNotificationData(), 374 NULL))); 375 EXPECT_EQ(2u, message_center()->GetPopupNotifications().size()); 376 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 377 378 // Block all notifications. All popups are gone and message center should be 379 // hidden. 380 blocker1.SetNotificationsEnabled(false); 381 EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); 382 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 383 384 // Updates |blocker2| state, which doesn't affect the global state. 385 blocker2.SetNotificationsEnabled(false); 386 EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); 387 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 388 389 blocker2.SetNotificationsEnabled(true); 390 EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); 391 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 392 393 // If |blocker2| blocks, then unblocking blocker1 doesn't change the global 394 // state. 395 blocker2.SetNotificationsEnabled(false); 396 blocker1.SetNotificationsEnabled(true); 397 EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); 398 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 399 400 // Unblock both blockers, which recovers the global state, but the popups 401 // aren't shown. 402 blocker2.SetNotificationsEnabled(true); 403 EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); 404 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 405 } 406 407 TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) { 408 NotifierId notifier_id(NotifierId::APPLICATION, "app1"); 409 ToggledNotificationBlocker blocker(message_center()); 410 411 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 412 NOTIFICATION_TYPE_SIMPLE, 413 "id1", 414 UTF8ToUTF16("title"), 415 UTF8ToUTF16("message"), 416 gfx::Image() /* icon */, 417 base::string16() /* display_source */, 418 notifier_id, 419 RichNotificationData(), 420 NULL))); 421 EXPECT_EQ(1u, message_center()->GetPopupNotifications().size()); 422 EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size()); 423 424 // Create a notification during blocked. Still no popups. 425 blocker.SetNotificationsEnabled(false); 426 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 427 NOTIFICATION_TYPE_SIMPLE, 428 "id2", 429 UTF8ToUTF16("title"), 430 UTF8ToUTF16("message"), 431 gfx::Image() /* icon */, 432 base::string16() /* display_source */, 433 notifier_id, 434 RichNotificationData(), 435 NULL))); 436 EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); 437 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 438 439 // Unblock notifications, the id1 should appear as a popup. 440 blocker.SetNotificationsEnabled(true); 441 NotificationList::PopupNotifications popups = 442 message_center()->GetPopupNotifications(); 443 EXPECT_EQ(1u, popups.size()); 444 EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); 445 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 446 } 447 448 // Similar to other blocker cases but this test case allows |notifier_id2| even 449 // in blocked. 450 TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) { 451 NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); 452 NotifierId notifier_id2(NotifierId::APPLICATION, "app2"); 453 PopupNotificationBlocker blocker(message_center(), notifier_id2); 454 455 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 456 NOTIFICATION_TYPE_SIMPLE, 457 "id1", 458 UTF8ToUTF16("title"), 459 UTF8ToUTF16("message"), 460 gfx::Image() /* icon */, 461 base::string16() /* display_source */, 462 notifier_id1, 463 RichNotificationData(), 464 NULL))); 465 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 466 NOTIFICATION_TYPE_SIMPLE, 467 "id2", 468 UTF8ToUTF16("title"), 469 UTF8ToUTF16("message"), 470 gfx::Image() /* icon */, 471 base::string16() /* display_source */, 472 notifier_id2, 473 RichNotificationData(), 474 NULL))); 475 476 // "id1" is closed but "id2" is still visible as a popup. 477 blocker.SetNotificationsEnabled(false); 478 NotificationList::PopupNotifications popups = 479 message_center()->GetPopupNotifications(); 480 EXPECT_EQ(1u, popups.size()); 481 EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); 482 EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); 483 484 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 485 NOTIFICATION_TYPE_SIMPLE, 486 "id3", 487 UTF8ToUTF16("title"), 488 UTF8ToUTF16("message"), 489 gfx::Image() /* icon */, 490 base::string16() /* display_source */, 491 notifier_id1, 492 RichNotificationData(), 493 NULL))); 494 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 495 NOTIFICATION_TYPE_SIMPLE, 496 "id4", 497 UTF8ToUTF16("title"), 498 UTF8ToUTF16("message"), 499 gfx::Image() /* icon */, 500 base::string16() /* display_source */, 501 notifier_id2, 502 RichNotificationData(), 503 NULL))); 504 popups = message_center()->GetPopupNotifications(); 505 EXPECT_EQ(2u, popups.size()); 506 EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); 507 EXPECT_TRUE(PopupNotificationsContain(popups, "id4")); 508 EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size()); 509 510 blocker.SetNotificationsEnabled(true); 511 popups = message_center()->GetPopupNotifications(); 512 EXPECT_EQ(3u, popups.size()); 513 EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); 514 EXPECT_TRUE(PopupNotificationsContain(popups, "id3")); 515 EXPECT_TRUE(PopupNotificationsContain(popups, "id4")); 516 EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size()); 517 } 518 519 // TotalNotificationBlocker suppresses showing notifications even from the list. 520 // This would provide the feature to 'separated' message centers per-profile for 521 // ChromeOS multi-login. 522 TEST_F(MessageCenterImplTest, TotalNotificationBlocker) { 523 NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); 524 NotifierId notifier_id2(NotifierId::APPLICATION, "app2"); 525 TotalNotificationBlocker blocker(message_center(), notifier_id2); 526 527 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 528 NOTIFICATION_TYPE_SIMPLE, 529 "id1", 530 UTF8ToUTF16("title"), 531 UTF8ToUTF16("message"), 532 gfx::Image() /* icon */, 533 base::string16() /* display_source */, 534 notifier_id1, 535 RichNotificationData(), 536 NULL))); 537 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 538 NOTIFICATION_TYPE_SIMPLE, 539 "id2", 540 UTF8ToUTF16("title"), 541 UTF8ToUTF16("message"), 542 gfx::Image() /* icon */, 543 base::string16() /* display_source */, 544 notifier_id2, 545 RichNotificationData(), 546 NULL))); 547 548 // "id1" becomes invisible while "id2" is still visible. 549 blocker.SetNotificationsEnabled(false); 550 EXPECT_EQ(1u, message_center()->NotificationCount()); 551 NotificationList::Notifications notifications = 552 message_center()->GetVisibleNotifications(); 553 EXPECT_FALSE(NotificationsContain(notifications, "id1")); 554 EXPECT_TRUE(NotificationsContain(notifications, "id2")); 555 556 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 557 NOTIFICATION_TYPE_SIMPLE, 558 "id3", 559 UTF8ToUTF16("title"), 560 UTF8ToUTF16("message"), 561 gfx::Image() /* icon */, 562 base::string16() /* display_source */, 563 notifier_id1, 564 RichNotificationData(), 565 NULL))); 566 message_center()->AddNotification(scoped_ptr<Notification>(new Notification( 567 NOTIFICATION_TYPE_SIMPLE, 568 "id4", 569 UTF8ToUTF16("title"), 570 UTF8ToUTF16("message"), 571 gfx::Image() /* icon */, 572 base::string16() /* display_source */, 573 notifier_id2, 574 RichNotificationData(), 575 NULL))); 576 EXPECT_EQ(2u, message_center()->NotificationCount()); 577 notifications = message_center()->GetVisibleNotifications(); 578 EXPECT_FALSE(NotificationsContain(notifications, "id1")); 579 EXPECT_TRUE(NotificationsContain(notifications, "id2")); 580 EXPECT_FALSE(NotificationsContain(notifications, "id3")); 581 EXPECT_TRUE(NotificationsContain(notifications, "id4")); 582 583 blocker.SetNotificationsEnabled(true); 584 EXPECT_EQ(4u, message_center()->NotificationCount()); 585 notifications = message_center()->GetVisibleNotifications(); 586 EXPECT_TRUE(NotificationsContain(notifications, "id1")); 587 EXPECT_TRUE(NotificationsContain(notifications, "id2")); 588 EXPECT_TRUE(NotificationsContain(notifications, "id3")); 589 EXPECT_TRUE(NotificationsContain(notifications, "id4")); 590 591 // RemoveAllVisibleNotifications should remove just visible notifications. 592 blocker.SetNotificationsEnabled(false); 593 message_center()->RemoveAllVisibleNotifications(false /* by_user */); 594 EXPECT_EQ(0u, message_center()->NotificationCount()); 595 blocker.SetNotificationsEnabled(true); 596 EXPECT_EQ(2u, message_center()->NotificationCount()); 597 notifications = message_center()->GetVisibleNotifications(); 598 EXPECT_TRUE(NotificationsContain(notifications, "id1")); 599 EXPECT_FALSE(NotificationsContain(notifications, "id2")); 600 EXPECT_TRUE(NotificationsContain(notifications, "id3")); 601 EXPECT_FALSE(NotificationsContain(notifications, "id4")); 602 603 // And RemoveAllNotifications should remove all. 604 blocker.SetNotificationsEnabled(false); 605 message_center()->RemoveAllNotifications(false /* by_user */); 606 EXPECT_EQ(0u, message_center()->NotificationCount()); 607 } 608 609 TEST_F(MessageCenterImplTest, QueueUpdatesWithCenterVisible) { 610 std::string id("id1"); 611 std::string id2("id2"); 612 NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); 613 614 // First, add and update a notification to ensure updates happen 615 // normally. 616 scoped_ptr<Notification> notification(CreateSimpleNotification(id)); 617 message_center()->AddNotification(notification.Pass()); 618 notification.reset(CreateSimpleNotification(id2)); 619 message_center()->UpdateNotification(id, notification.Pass()); 620 EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2)); 621 EXPECT_FALSE(message_center()->FindVisibleNotificationById(id)); 622 623 // Then open the message center. 624 message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); 625 626 // Then update a notification; nothing should have happened. 627 notification.reset(CreateSimpleNotification(id)); 628 message_center()->UpdateNotification(id2, notification.Pass()); 629 EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2)); 630 EXPECT_FALSE(message_center()->FindVisibleNotificationById(id)); 631 632 // Close the message center; then the update should have propagated. 633 message_center()->SetVisibility(VISIBILITY_TRANSIENT); 634 EXPECT_FALSE(message_center()->FindVisibleNotificationById(id2)); 635 EXPECT_TRUE(message_center()->FindVisibleNotificationById(id)); 636 } 637 638 TEST_F(MessageCenterImplTest, ComplexQueueing) { 639 std::string ids[5] = {"0", "1", "2", "3", "4p"}; 640 NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); 641 642 scoped_ptr<Notification> notification; 643 // Add some notifications 644 int i = 0; 645 for (; i < 3; i++) { 646 notification.reset(CreateSimpleNotification(ids[i])); 647 message_center()->AddNotification(notification.Pass()); 648 } 649 for (i = 0; i < 3; i++) { 650 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[i])); 651 } 652 for (; i < 5; i++) { 653 EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[i])); 654 } 655 656 notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS)); 657 message_center()->AddNotification(notification.Pass()); 658 659 // Now start queueing. 660 // NL: ["0", "1", "2", "4p"] 661 message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); 662 663 // This should update notification "1" to have id "3". 664 notification.reset(CreateSimpleNotification(ids[3])); 665 message_center()->UpdateNotification(ids[1], notification.Pass()); 666 667 notification.reset(CreateSimpleNotification(ids[4])); 668 message_center()->UpdateNotification(ids[4], notification.Pass()); 669 670 notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS)); 671 message_center()->UpdateNotification(ids[4], notification.Pass()); 672 673 // This should update notification "3" to a new ID after we go TRANSIENT. 674 notification.reset(CreateSimpleNotification("New id")); 675 message_center()->UpdateNotification(ids[3], notification.Pass()); 676 677 // This should create a new "3", that doesn't overwrite the update to 3 678 // before. 679 notification.reset(CreateSimpleNotification(ids[3])); 680 message_center()->AddNotification(notification.Pass()); 681 682 // The NL should still be the same: ["0", "1", "2", "4p"] 683 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[0])); 684 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[1])); 685 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2])); 686 EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[3])); 687 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4])); 688 EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 4u); 689 message_center()->SetVisibility(VISIBILITY_TRANSIENT); 690 691 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[0])); 692 EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[1])); 693 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2])); 694 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[3])); 695 EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4])); 696 EXPECT_TRUE(message_center()->FindVisibleNotificationById("New id")); 697 EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 5u); 698 } 699 700 TEST_F(MessageCenterImplTest, QueuedDirectUpdates) { 701 std::string id("id1"); 702 std::string id2("id2"); 703 NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); 704 705 gfx::Size original_size(0, 0); 706 // Open the message center to prevent adding notifications 707 message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); 708 709 // Create new notification to be added to the queue; images all have the same 710 // original size. 711 scoped_ptr<Notification> notification(CreateSimpleNotification(id)); 712 713 // Double-check that sizes all match. 714 const std::vector<ButtonInfo>& original_buttons = notification->buttons(); 715 ASSERT_EQ(2u, original_buttons.size()); 716 717 EXPECT_EQ(original_size, notification->icon().Size()); 718 EXPECT_EQ(original_size, notification->image().Size()); 719 EXPECT_EQ(original_size, original_buttons[0].icon.Size()); 720 EXPECT_EQ(original_size, original_buttons[1].icon.Size()); 721 722 message_center()->AddNotification(notification.Pass()); 723 724 // The notification should be in the queue. 725 EXPECT_FALSE(message_center()->FindVisibleNotificationById(id)); 726 727 // Now try setting the icon to a different size. 728 gfx::Size new_size(16, 16); 729 EXPECT_NE(original_size, new_size); 730 731 gfx::Canvas canvas(new_size, 1.0f, true); 732 canvas.DrawColor(SK_ColorBLUE); 733 gfx::Image testImage(gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep()))); 734 message_center()->SetNotificationIcon(id, testImage); 735 message_center()->SetNotificationImage(id, testImage); 736 message_center()->SetNotificationButtonIcon(id, 0, testImage); 737 message_center()->SetNotificationButtonIcon(id, 1, testImage); 738 739 // The notification should be in the queue. 740 EXPECT_FALSE(message_center()->FindVisibleNotificationById(id)); 741 742 // Close the message center; then the update should have propagated. 743 message_center()->SetVisibility(VISIBILITY_TRANSIENT); 744 // The notification should no longer be in the queue. 745 EXPECT_TRUE(message_center()->FindVisibleNotificationById(id)); 746 747 Notification* mc_notification = 748 *(message_center()->GetVisibleNotifications().begin()); 749 const std::vector<ButtonInfo>& buttons = mc_notification->buttons(); 750 ASSERT_EQ(2u, buttons.size()); 751 752 EXPECT_EQ(new_size, mc_notification->icon().Size()); 753 EXPECT_EQ(new_size, mc_notification->image().Size()); 754 EXPECT_EQ(new_size, buttons[0].icon.Size()); 755 EXPECT_EQ(new_size, buttons[1].icon.Size()); 756 } 757 758 TEST_F(MessageCenterImplTest, CachedUnreadCount) { 759 message_center()->AddNotification( 760 scoped_ptr<Notification>(CreateSimpleNotification("id1"))); 761 message_center()->AddNotification( 762 scoped_ptr<Notification>(CreateSimpleNotification("id2"))); 763 message_center()->AddNotification( 764 scoped_ptr<Notification>(CreateSimpleNotification("id3"))); 765 ASSERT_EQ(3u, message_center()->UnreadNotificationCount()); 766 767 // Mark 'displayed' on all notifications by using for-loop. This shouldn't 768 // recreate |notifications| inside of the loop. 769 const NotificationList::Notifications& notifications = 770 message_center()->GetVisibleNotifications(); 771 for (NotificationList::Notifications::const_iterator iter = 772 notifications.begin(); iter != notifications.end(); ++iter) { 773 message_center()->DisplayedNotification( 774 (*iter)->id(), message_center::DISPLAY_SOURCE_MESSAGE_CENTER); 775 } 776 EXPECT_EQ(0u, message_center()->UnreadNotificationCount()); 777 778 // Imitate the timeout, which recovers the unread count. Again, this shouldn't 779 // recreate |notifications| inside of the loop. 780 for (NotificationList::Notifications::const_iterator iter = 781 notifications.begin(); iter != notifications.end(); ++iter) { 782 message_center()->MarkSinglePopupAsShown((*iter)->id(), false); 783 } 784 EXPECT_EQ(3u, message_center()->UnreadNotificationCount()); 785 786 // Opening the message center will reset the unread count. 787 message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); 788 EXPECT_EQ(0u, message_center()->UnreadNotificationCount()); 789 } 790 791 TEST_F(MessageCenterImplTest, DisableNotificationsByNotifier) { 792 ASSERT_EQ(0u, message_center()->NotificationCount()); 793 message_center()->AddNotification( 794 scoped_ptr<Notification>( 795 CreateSimpleNotificationWithNotifierId("id1-1", "app1"))); 796 message_center()->AddNotification( 797 scoped_ptr<Notification>( 798 CreateSimpleNotificationWithNotifierId("id1-2", "app1"))); 799 message_center()->AddNotification( 800 scoped_ptr<Notification>( 801 CreateSimpleNotificationWithNotifierId("id2-1", "app2"))); 802 message_center()->AddNotification( 803 scoped_ptr<Notification>( 804 CreateSimpleNotificationWithNotifierId("id2-2", "app2"))); 805 message_center()->AddNotification( 806 scoped_ptr<Notification>( 807 CreateSimpleNotificationWithNotifierId("id2-3", "app2"))); 808 ASSERT_EQ(5u, message_center()->NotificationCount()); 809 810 // Removing all of app1's notifications should only leave app2's. 811 message_center()->DisableNotificationsByNotifier( 812 NotifierId(NotifierId::APPLICATION, "app1")); 813 ASSERT_EQ(3u, message_center()->NotificationCount()); 814 815 // Now we remove the remaining notifications. 816 message_center()->DisableNotificationsByNotifier( 817 NotifierId(NotifierId::APPLICATION, "app2")); 818 ASSERT_EQ(0u, message_center()->NotificationCount()); 819 } 820 821 TEST_F(MessageCenterImplTest, NotifierEnabledChanged) { 822 ASSERT_EQ(0u, message_center()->NotificationCount()); 823 message_center()->AddNotification( 824 scoped_ptr<Notification>( 825 CreateSimpleNotificationWithNotifierId("id1-1", "app1"))); 826 message_center()->AddNotification( 827 scoped_ptr<Notification>( 828 CreateSimpleNotificationWithNotifierId("id1-2", "app1"))); 829 message_center()->AddNotification( 830 scoped_ptr<Notification>( 831 CreateSimpleNotificationWithNotifierId("id1-3", "app1"))); 832 message_center()->AddNotification( 833 scoped_ptr<Notification>( 834 CreateSimpleNotificationWithNotifierId("id2-1", "app2"))); 835 message_center()->AddNotification( 836 scoped_ptr<Notification>( 837 CreateSimpleNotificationWithNotifierId("id2-2", "app2"))); 838 message_center()->AddNotification( 839 scoped_ptr<Notification>( 840 CreateSimpleNotificationWithNotifierId("id2-3", "app2"))); 841 message_center()->AddNotification( 842 scoped_ptr<Notification>( 843 CreateSimpleNotificationWithNotifierId("id2-4", "app2"))); 844 message_center()->AddNotification( 845 scoped_ptr<Notification>( 846 CreateSimpleNotificationWithNotifierId("id2-5", "app2"))); 847 ASSERT_EQ(8u, message_center()->NotificationCount()); 848 849 // Enabling an extension should have no effect on the count. 850 notifier_settings_observer()->NotifierEnabledChanged( 851 NotifierId(NotifierId::APPLICATION, "app1"), true); 852 ASSERT_EQ(8u, message_center()->NotificationCount()); 853 854 // Removing all of app2's notifications should only leave app1's. 855 notifier_settings_observer()->NotifierEnabledChanged( 856 NotifierId(NotifierId::APPLICATION, "app2"), false); 857 ASSERT_EQ(3u, message_center()->NotificationCount()); 858 859 // Removal operations should be idempotent. 860 notifier_settings_observer()->NotifierEnabledChanged( 861 NotifierId(NotifierId::APPLICATION, "app2"), false); 862 ASSERT_EQ(3u, message_center()->NotificationCount()); 863 864 // Now we remove the remaining notifications. 865 notifier_settings_observer()->NotifierEnabledChanged( 866 NotifierId(NotifierId::APPLICATION, "app1"), false); 867 ASSERT_EQ(0u, message_center()->NotificationCount()); 868 } 869 870 } // namespace internal 871 } // namespace message_center 872