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