Home | History | Annotate | Download | only in message_center
      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