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 #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