Home | History | Annotate | Download | only in message_center
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/message_center/notification_list.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/i18n/time_formatting.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/values.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "ui/message_center/message_center_style.h"
     14 #include "ui/message_center/notification_blocker.h"
     15 #include "ui/message_center/notification_types.h"
     16 #include "ui/message_center/notifier_settings.h"
     17 
     18 using base::UTF8ToUTF16;
     19 
     20 namespace message_center {
     21 
     22 class NotificationListTest : public testing::Test {
     23  public:
     24   NotificationListTest() {}
     25   virtual ~NotificationListTest() {}
     26 
     27   virtual void SetUp() {
     28     notification_list_.reset(new NotificationList());
     29     counter_ = 0;
     30   }
     31 
     32  protected:
     33   // Currently NotificationListTest doesn't care about some fields like title or
     34   // message, so put a simple template on it. Returns the id of the new
     35   // notification.
     36   std::string AddNotification(
     37       const message_center::RichNotificationData& optional_fields) {
     38     std::string new_id;
     39     scoped_ptr<Notification> notification(
     40         MakeNotification(optional_fields, &new_id));
     41     notification_list_->AddNotification(notification.Pass());
     42     counter_++;
     43     return new_id;
     44   }
     45 
     46   std::string AddNotification() {
     47     return AddNotification(message_center::RichNotificationData());
     48   }
     49 
     50   // Construct a new notification for testing, but don't add it to the list yet.
     51   scoped_ptr<Notification> MakeNotification(
     52       const message_center::RichNotificationData& optional_fields,
     53       std::string* id_out) {
     54     *id_out = base::StringPrintf(kIdFormat, counter_);
     55     scoped_ptr<Notification> notification(new Notification(
     56         message_center::NOTIFICATION_TYPE_SIMPLE,
     57         *id_out,
     58         UTF8ToUTF16(base::StringPrintf(kTitleFormat, counter_)),
     59         UTF8ToUTF16(base::StringPrintf(kMessageFormat, counter_)),
     60         gfx::Image(),
     61         UTF8ToUTF16(kDisplaySource),
     62         NotifierId(NotifierId::APPLICATION, kExtensionId),
     63         optional_fields,
     64         NULL));
     65     return notification.Pass();
     66   }
     67 
     68   scoped_ptr<Notification> MakeNotification(std::string* id_out) {
     69     return MakeNotification(message_center::RichNotificationData(), id_out);
     70   }
     71 
     72   // Utility methods of AddNotification.
     73   std::string AddPriorityNotification(NotificationPriority priority) {
     74     message_center::RichNotificationData optional;
     75     optional.priority = priority;
     76     return AddNotification(optional);
     77   }
     78 
     79   NotificationList::PopupNotifications GetPopups() {
     80     return notification_list()->GetPopupNotifications(blockers_, NULL);
     81   }
     82 
     83   size_t GetPopupCounts() {
     84     return GetPopups().size();
     85   }
     86 
     87   Notification* GetNotification(const std::string& id) {
     88     NotificationList::Notifications::iterator iter =
     89         notification_list()->GetNotification(id);
     90     if (iter == notification_list()->notifications_.end())
     91       return NULL;
     92     return *iter;
     93   }
     94 
     95   NotificationList* notification_list() { return notification_list_.get(); }
     96   const NotificationBlockers& blockers() const { return blockers_; }
     97 
     98   static const char kIdFormat[];
     99   static const char kTitleFormat[];
    100   static const char kMessageFormat[];
    101   static const char kDisplaySource[];
    102   static const char kExtensionId[];
    103 
    104  private:
    105   scoped_ptr<NotificationList> notification_list_;
    106   NotificationBlockers blockers_;
    107   size_t counter_;
    108 
    109   DISALLOW_COPY_AND_ASSIGN(NotificationListTest);
    110 };
    111 
    112 bool IsInNotifications(const NotificationList::Notifications& notifications,
    113                        const std::string& id) {
    114   for (NotificationList::Notifications::const_iterator iter =
    115            notifications.begin(); iter != notifications.end(); ++iter) {
    116     if ((*iter)->id() == id)
    117       return true;
    118   }
    119   return false;
    120 }
    121 
    122 const char NotificationListTest::kIdFormat[] = "id%ld";
    123 const char NotificationListTest::kTitleFormat[] = "id%ld";
    124 const char NotificationListTest::kMessageFormat[] = "message%ld";
    125 const char NotificationListTest::kDisplaySource[] = "source";
    126 const char NotificationListTest::kExtensionId[] = "ext";
    127 
    128 TEST_F(NotificationListTest, Basic) {
    129   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    130   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    131 
    132   std::string id0 = AddNotification();
    133   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    134   std::string id1 = AddNotification();
    135   EXPECT_EQ(2u, notification_list()->NotificationCount(blockers()));
    136   EXPECT_EQ(2u, notification_list()->UnreadCount(blockers()));
    137 
    138   EXPECT_TRUE(notification_list()->HasPopupNotifications(blockers()));
    139   EXPECT_TRUE(notification_list()->GetNotificationById(id0));
    140   EXPECT_TRUE(notification_list()->GetNotificationById(id1));
    141   EXPECT_FALSE(notification_list()->GetNotificationById(id1 + "foo"));
    142 
    143   EXPECT_EQ(2u, GetPopupCounts());
    144 
    145   notification_list()->MarkSinglePopupAsShown(id0, true);
    146   notification_list()->MarkSinglePopupAsShown(id1, true);
    147   EXPECT_EQ(2u, notification_list()->NotificationCount(blockers()));
    148   EXPECT_EQ(0u, GetPopupCounts());
    149 
    150   notification_list()->RemoveNotification(id0);
    151   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    152   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    153 
    154   AddNotification();
    155   EXPECT_EQ(2u, notification_list()->NotificationCount(blockers()));
    156 }
    157 
    158 TEST_F(NotificationListTest, MessageCenterVisible) {
    159   AddNotification();
    160   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    161   ASSERT_EQ(1u, notification_list()->UnreadCount(blockers()));
    162   ASSERT_EQ(1u, GetPopupCounts());
    163 
    164   // Make the message center visible. It resets the unread count and popup
    165   // counts.
    166   notification_list()->SetMessageCenterVisible(true, NULL);
    167   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    168   ASSERT_EQ(0u, GetPopupCounts());
    169 }
    170 
    171 TEST_F(NotificationListTest, UnreadCount) {
    172   std::string id0 = AddNotification();
    173   std::string id1 = AddNotification();
    174   ASSERT_EQ(2u, notification_list()->UnreadCount(blockers()));
    175 
    176   notification_list()->MarkSinglePopupAsDisplayed(id0);
    177   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    178   notification_list()->MarkSinglePopupAsDisplayed(id0);
    179   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    180   notification_list()->MarkSinglePopupAsDisplayed(id1);
    181   EXPECT_EQ(0u, notification_list()->UnreadCount(blockers()));
    182 }
    183 
    184 TEST_F(NotificationListTest, UpdateNotification) {
    185   std::string id0 = AddNotification();
    186   std::string replaced = id0 + "_replaced";
    187   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    188   scoped_ptr<Notification> notification(
    189       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    190                        replaced,
    191                        UTF8ToUTF16("newtitle"),
    192                        UTF8ToUTF16("newbody"),
    193                        gfx::Image(),
    194                        UTF8ToUTF16(kDisplaySource),
    195                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    196                        message_center::RichNotificationData(),
    197                        NULL));
    198   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    199   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    200   const NotificationList::Notifications notifications =
    201       notification_list()->GetVisibleNotifications(blockers());
    202   EXPECT_EQ(replaced, (*notifications.begin())->id());
    203   EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title());
    204   EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message());
    205 }
    206 
    207 TEST_F(NotificationListTest, GetNotificationsByNotifierId) {
    208   NotifierId id0(NotifierId::APPLICATION, "ext0");
    209   NotifierId id1(NotifierId::APPLICATION, "ext1");
    210   NotifierId id2(GURL("http://example.com"));
    211   NotifierId id3(NotifierId::SYSTEM_COMPONENT, "system-notifier");
    212   scoped_ptr<Notification> notification(
    213       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    214                        "id0",
    215                        UTF8ToUTF16("title0"),
    216                        UTF8ToUTF16("message0"),
    217                        gfx::Image(),
    218                        UTF8ToUTF16("source0"),
    219                        id0,
    220                        message_center::RichNotificationData(),
    221                        NULL));
    222   notification_list()->AddNotification(notification.Pass());
    223   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    224                                       "id1",
    225                                       UTF8ToUTF16("title1"),
    226                                       UTF8ToUTF16("message1"),
    227                                       gfx::Image(),
    228                                       UTF8ToUTF16("source0"),
    229                                       id0,
    230                                       message_center::RichNotificationData(),
    231                                       NULL));
    232   notification_list()->AddNotification(notification.Pass());
    233   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    234                                       "id2",
    235                                       UTF8ToUTF16("title1"),
    236                                       UTF8ToUTF16("message1"),
    237                                       gfx::Image(),
    238                                       UTF8ToUTF16("source1"),
    239                                       id0,
    240                                       message_center::RichNotificationData(),
    241                                       NULL));
    242   notification_list()->AddNotification(notification.Pass());
    243   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    244                                       "id3",
    245                                       UTF8ToUTF16("title1"),
    246                                       UTF8ToUTF16("message1"),
    247                                       gfx::Image(),
    248                                       UTF8ToUTF16("source2"),
    249                                       id1,
    250                                       message_center::RichNotificationData(),
    251                                       NULL));
    252   notification_list()->AddNotification(notification.Pass());
    253   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    254                                       "id4",
    255                                       UTF8ToUTF16("title1"),
    256                                       UTF8ToUTF16("message1"),
    257                                       gfx::Image(),
    258                                       UTF8ToUTF16("source2"),
    259                                       id2,
    260                                       message_center::RichNotificationData(),
    261                                       NULL));
    262   notification_list()->AddNotification(notification.Pass());
    263   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    264                                       "id5",
    265                                       UTF8ToUTF16("title1"),
    266                                       UTF8ToUTF16("message1"),
    267                                       gfx::Image(),
    268                                       UTF8ToUTF16("source2"),
    269                                       id3,
    270                                       message_center::RichNotificationData(),
    271                                       NULL));
    272   notification_list()->AddNotification(notification.Pass());
    273 
    274   NotificationList::Notifications by_notifier_id =
    275       notification_list()->GetNotificationsByNotifierId(id0);
    276   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id0"));
    277   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id1"));
    278   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id2"));
    279   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
    280   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
    281   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
    282 
    283   by_notifier_id = notification_list()->GetNotificationsByNotifierId(id1);
    284   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
    285   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
    286   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
    287   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id3"));
    288   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
    289   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
    290 
    291   by_notifier_id = notification_list()->GetNotificationsByNotifierId(id2);
    292   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
    293   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
    294   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
    295   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
    296   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id4"));
    297   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
    298 
    299   by_notifier_id = notification_list()->GetNotificationsByNotifierId(id3);
    300   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
    301   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
    302   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
    303   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
    304   EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
    305   EXPECT_TRUE(IsInNotifications(by_notifier_id, "id5"));
    306 }
    307 
    308 TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) {
    309   std::vector<std::string> ids;
    310   for (size_t i = 0; i <= kMaxVisiblePopupNotifications; i++)
    311     ids.push_back(AddNotification());
    312 
    313   NotificationList::PopupNotifications popups = GetPopups();
    314   // The popup should contain the oldest kMaxVisiblePopupNotifications. Newer
    315   // one should come earlier in the popup list. It means, the last element
    316   // of |popups| should be the firstly added one, and so on.
    317   EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
    318   NotificationList::PopupNotifications::const_reverse_iterator iter =
    319       popups.rbegin();
    320   for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i, ++iter) {
    321     EXPECT_EQ(ids[i], (*iter)->id()) << i;
    322   }
    323 
    324   for (NotificationList::PopupNotifications::const_iterator iter =
    325            popups.begin(); iter != popups.end(); ++iter) {
    326     notification_list()->MarkSinglePopupAsShown((*iter)->id(), false);
    327   }
    328   popups.clear();
    329   popups = GetPopups();
    330   EXPECT_EQ(1u, popups.size());
    331   EXPECT_EQ(ids[ids.size() - 1], (*popups.begin())->id());
    332 }
    333 
    334 TEST_F(NotificationListTest, Priority) {
    335   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    336   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    337 
    338   // Default priority has the limit on the number of the popups.
    339   for (size_t i = 0; i <= kMaxVisiblePopupNotifications; ++i)
    340     AddNotification();
    341   EXPECT_EQ(kMaxVisiblePopupNotifications + 1,
    342             notification_list()->NotificationCount(blockers()));
    343   EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
    344 
    345   // Low priority: not visible to popups.
    346   notification_list()->SetMessageCenterVisible(true, NULL);
    347   notification_list()->SetMessageCenterVisible(false, NULL);
    348   EXPECT_EQ(0u, notification_list()->UnreadCount(blockers()));
    349   AddPriorityNotification(LOW_PRIORITY);
    350   EXPECT_EQ(kMaxVisiblePopupNotifications + 2,
    351             notification_list()->NotificationCount(blockers()));
    352   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    353   EXPECT_EQ(0u, GetPopupCounts());
    354 
    355   // Minimum priority: doesn't update the unread count.
    356   AddPriorityNotification(MIN_PRIORITY);
    357   EXPECT_EQ(kMaxVisiblePopupNotifications + 3,
    358             notification_list()->NotificationCount(blockers()));
    359   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    360   EXPECT_EQ(0u, GetPopupCounts());
    361 
    362   NotificationList::Notifications notifications =
    363       notification_list()->GetVisibleNotifications(blockers());
    364   for (NotificationList::Notifications::const_iterator iter =
    365            notifications.begin(); iter != notifications.end(); ++iter) {
    366     notification_list()->RemoveNotification((*iter)->id());
    367   }
    368 
    369   // Higher priority: no limits to the number of popups.
    370   for (size_t i = 0; i < kMaxVisiblePopupNotifications * 2; ++i)
    371     AddPriorityNotification(HIGH_PRIORITY);
    372   for (size_t i = 0; i < kMaxVisiblePopupNotifications * 2; ++i)
    373     AddPriorityNotification(MAX_PRIORITY);
    374   EXPECT_EQ(kMaxVisiblePopupNotifications * 4,
    375             notification_list()->NotificationCount(blockers()));
    376   EXPECT_EQ(kMaxVisiblePopupNotifications * 4, GetPopupCounts());
    377 }
    378 
    379 TEST_F(NotificationListTest, HasPopupsWithPriority) {
    380   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    381   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    382 
    383   AddPriorityNotification(MIN_PRIORITY);
    384   AddPriorityNotification(MAX_PRIORITY);
    385 
    386   EXPECT_EQ(1u, GetPopupCounts());
    387 }
    388 
    389 TEST_F(NotificationListTest, HasPopupsWithSystemPriority) {
    390   ASSERT_EQ(0u, notification_list()->NotificationCount(blockers()));
    391   ASSERT_EQ(0u, notification_list()->UnreadCount(blockers()));
    392 
    393   std::string normal_id = AddPriorityNotification(DEFAULT_PRIORITY);
    394   std::string system_id = AddNotification();
    395   GetNotification(system_id)->SetSystemPriority();
    396 
    397   EXPECT_EQ(2u, GetPopupCounts());
    398 
    399   notification_list()->MarkSinglePopupAsDisplayed(normal_id);
    400   notification_list()->MarkSinglePopupAsDisplayed(system_id);
    401 
    402   notification_list()->MarkSinglePopupAsShown(normal_id, false);
    403   notification_list()->MarkSinglePopupAsShown(system_id, false);
    404 
    405   notification_list()->SetMessageCenterVisible(true, NULL);
    406   notification_list()->SetMessageCenterVisible(false, NULL);
    407   EXPECT_EQ(1u, GetPopupCounts());
    408 
    409   // Mark as read -- emulation of mouse click.
    410   notification_list()->MarkSinglePopupAsShown(system_id, true);
    411   EXPECT_EQ(0u, GetPopupCounts());
    412 }
    413 
    414 TEST_F(NotificationListTest, PriorityPromotion) {
    415   std::string id0 = AddPriorityNotification(LOW_PRIORITY);
    416   std::string replaced = id0 + "_replaced";
    417   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    418   EXPECT_EQ(0u, GetPopupCounts());
    419   message_center::RichNotificationData optional;
    420   optional.priority = 1;
    421   scoped_ptr<Notification> notification(
    422       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    423                        replaced,
    424                        UTF8ToUTF16("newtitle"),
    425                        UTF8ToUTF16("newbody"),
    426                        gfx::Image(),
    427                        UTF8ToUTF16(kDisplaySource),
    428                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    429                        optional,
    430                        NULL));
    431   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    432   EXPECT_EQ(1u, notification_list()->NotificationCount(blockers()));
    433   EXPECT_EQ(1u, GetPopupCounts());
    434   const NotificationList::Notifications notifications =
    435       notification_list()->GetVisibleNotifications(blockers());
    436   EXPECT_EQ(replaced, (*notifications.begin())->id());
    437   EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title());
    438   EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message());
    439   EXPECT_EQ(1, (*notifications.begin())->priority());
    440 }
    441 
    442 TEST_F(NotificationListTest, PriorityPromotionWithPopups) {
    443   std::string id0 = AddPriorityNotification(LOW_PRIORITY);
    444   std::string id1 = AddPriorityNotification(DEFAULT_PRIORITY);
    445   EXPECT_EQ(1u, GetPopupCounts());
    446   notification_list()->MarkSinglePopupAsShown(id1, true);
    447   EXPECT_EQ(0u, GetPopupCounts());
    448 
    449   // id0 promoted to LOW->DEFAULT, it'll appear as toast (popup).
    450   message_center::RichNotificationData priority;
    451   priority.priority = DEFAULT_PRIORITY;
    452   scoped_ptr<Notification> notification(
    453       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    454                        id0,
    455                        UTF8ToUTF16("newtitle"),
    456                        UTF8ToUTF16("newbody"),
    457                        gfx::Image(),
    458                        UTF8ToUTF16(kDisplaySource),
    459                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    460                        priority,
    461                        NULL));
    462   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    463   EXPECT_EQ(1u, GetPopupCounts());
    464   notification_list()->MarkSinglePopupAsShown(id0, true);
    465   EXPECT_EQ(0u, GetPopupCounts());
    466 
    467   // update with no promotion change for id0, it won't appear as a toast.
    468   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    469                                       id0,
    470                                       UTF8ToUTF16("newtitle2"),
    471                                       UTF8ToUTF16("newbody2"),
    472                                       gfx::Image(),
    473                                       UTF8ToUTF16(kDisplaySource),
    474                                       NotifierId(NotifierId::APPLICATION,
    475                                                  kExtensionId),
    476                                       priority,
    477                                       NULL));
    478   notification_list()->UpdateNotificationMessage(id0, notification.Pass());
    479   EXPECT_EQ(0u, GetPopupCounts());
    480 
    481   // id1 promoted to DEFAULT->HIGH, it'll appear as toast (popup).
    482   priority.priority = HIGH_PRIORITY;
    483   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    484                                       id1,
    485                                       UTF8ToUTF16("newtitle"),
    486                                       UTF8ToUTF16("newbody"),
    487                                       gfx::Image(),
    488                                       UTF8ToUTF16(kDisplaySource),
    489                                       NotifierId(NotifierId::APPLICATION,
    490                                                  kExtensionId),
    491                                       priority,
    492                                       NULL));
    493   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    494   EXPECT_EQ(1u, GetPopupCounts());
    495   notification_list()->MarkSinglePopupAsShown(id1, true);
    496   EXPECT_EQ(0u, GetPopupCounts());
    497 
    498   // id1 promoted to HIGH->MAX, it'll appear as toast again.
    499   priority.priority = MAX_PRIORITY;
    500   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    501                                       id1,
    502                                       UTF8ToUTF16("newtitle2"),
    503                                       UTF8ToUTF16("newbody2"),
    504                                       gfx::Image(),
    505                                       UTF8ToUTF16(kDisplaySource),
    506                                       NotifierId(NotifierId::APPLICATION,
    507                                                  kExtensionId),
    508                                       priority,
    509                                       NULL));
    510   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    511   EXPECT_EQ(1u, GetPopupCounts());
    512   notification_list()->MarkSinglePopupAsShown(id1, true);
    513   EXPECT_EQ(0u, GetPopupCounts());
    514 
    515   // id1 demoted to MAX->DEFAULT, no appearing as toast.
    516   priority.priority = DEFAULT_PRIORITY;
    517   notification.reset(new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    518                                       id1,
    519                                       UTF8ToUTF16("newtitle3"),
    520                                       UTF8ToUTF16("newbody3"),
    521                                       gfx::Image(),
    522                                       UTF8ToUTF16(kDisplaySource),
    523                                       NotifierId(NotifierId::APPLICATION,
    524                                                  kExtensionId),
    525                                       priority,
    526                                       NULL));
    527   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    528   EXPECT_EQ(0u, GetPopupCounts());
    529 }
    530 
    531 TEST_F(NotificationListTest, WebNotificationUpdatePromotion) {
    532   std::string notification_id = "replaced-web-notification";
    533   scoped_ptr<Notification> original_notification(
    534       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    535                        notification_id,
    536                        UTF8ToUTF16("Web Notification"),
    537                        UTF8ToUTF16("Notification contents"),
    538                        gfx::Image(),
    539                        UTF8ToUTF16(kDisplaySource),
    540                        NotifierId(GURL("https://example.com/")),
    541                        message_center::RichNotificationData(),
    542                        NULL));
    543 
    544   EXPECT_EQ(0u, GetPopupCounts());
    545   notification_list()->AddNotification(original_notification.Pass());
    546   EXPECT_EQ(1u, GetPopupCounts());
    547 
    548   notification_list()->MarkSinglePopupAsShown(notification_id, true);
    549   EXPECT_EQ(0u, GetPopupCounts());
    550 
    551   scoped_ptr<Notification> replaced_notification(
    552       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    553                        notification_id,
    554                        UTF8ToUTF16("Web Notification Replacement"),
    555                        UTF8ToUTF16("New notification contents"),
    556                        gfx::Image(),
    557                        UTF8ToUTF16(kDisplaySource),
    558                        NotifierId(GURL("https://example.com/")),
    559                        message_center::RichNotificationData(),
    560                        NULL));
    561 
    562   // Web Notifications will be re-shown as popups even if their priority didn't
    563   // change, to match the behavior of the Web Notification API.
    564   notification_list()->UpdateNotificationMessage(notification_id,
    565                                                  replaced_notification.Pass());
    566   EXPECT_EQ(1u, GetPopupCounts());
    567 }
    568 
    569 TEST_F(NotificationListTest, NotificationOrderAndPriority) {
    570   base::Time now = base::Time::Now();
    571   message_center::RichNotificationData optional;
    572   optional.timestamp = now;
    573   optional.priority = 2;
    574   std::string max_id = AddNotification(optional);
    575 
    576   now += base::TimeDelta::FromSeconds(1);
    577   optional.timestamp = now;
    578   optional.priority = 1;
    579   std::string high_id = AddNotification(optional);
    580 
    581   now += base::TimeDelta::FromSeconds(1);
    582   optional.timestamp = now;
    583   optional.priority = 0;
    584   std::string default_id = AddNotification(optional);
    585 
    586   {
    587     // Popups: latest comes first.
    588     NotificationList::PopupNotifications popups = GetPopups();
    589     EXPECT_EQ(3u, popups.size());
    590     NotificationList::PopupNotifications::const_iterator iter = popups.begin();
    591     EXPECT_EQ(default_id, (*iter)->id());
    592     iter++;
    593     EXPECT_EQ(high_id, (*iter)->id());
    594     iter++;
    595     EXPECT_EQ(max_id, (*iter)->id());
    596   }
    597   {
    598     // Notifications: high priority comes ealier.
    599     const NotificationList::Notifications notifications =
    600         notification_list()->GetVisibleNotifications(blockers());
    601     EXPECT_EQ(3u, notifications.size());
    602     NotificationList::Notifications::const_iterator iter =
    603         notifications.begin();
    604     EXPECT_EQ(max_id, (*iter)->id());
    605     iter++;
    606     EXPECT_EQ(high_id, (*iter)->id());
    607     iter++;
    608     EXPECT_EQ(default_id, (*iter)->id());
    609   }
    610 }
    611 
    612 TEST_F(NotificationListTest, MarkSinglePopupAsShown) {
    613   std::string id1 = AddNotification();
    614   std::string id2 = AddNotification();
    615   std::string id3 = AddNotification();
    616   ASSERT_EQ(3u, notification_list()->NotificationCount(blockers()));
    617   ASSERT_EQ(std::min(static_cast<size_t>(3u), kMaxVisiblePopupNotifications),
    618             GetPopupCounts());
    619   notification_list()->MarkSinglePopupAsDisplayed(id1);
    620   notification_list()->MarkSinglePopupAsDisplayed(id2);
    621   notification_list()->MarkSinglePopupAsDisplayed(id3);
    622 
    623   notification_list()->MarkSinglePopupAsShown(id2, true);
    624   notification_list()->MarkSinglePopupAsShown(id3, false);
    625   EXPECT_EQ(3u, notification_list()->NotificationCount(blockers()));
    626   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    627   EXPECT_EQ(1u, GetPopupCounts());
    628   NotificationList::PopupNotifications popups = GetPopups();
    629   EXPECT_EQ(id1, (*popups.begin())->id());
    630 
    631   // The notifications in the NotificationCenter are unaffected by popups shown.
    632   NotificationList::Notifications notifications =
    633       notification_list()->GetVisibleNotifications(blockers());
    634   NotificationList::Notifications::const_iterator iter = notifications.begin();
    635   EXPECT_EQ(id3, (*iter)->id());
    636   iter++;
    637   EXPECT_EQ(id2, (*iter)->id());
    638   iter++;
    639   EXPECT_EQ(id1, (*iter)->id());
    640 }
    641 
    642 TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) {
    643   std::string id1 = AddNotification();
    644   std::string id2 = AddNotification();
    645   notification_list()->MarkSinglePopupAsDisplayed(id1);
    646   notification_list()->MarkSinglePopupAsDisplayed(id2);
    647 
    648   EXPECT_EQ(2u, GetPopupCounts());
    649 
    650   const Notification* n1 = GetNotification(id1);
    651   EXPECT_FALSE(n1->shown_as_popup());
    652   EXPECT_TRUE(n1->IsRead());
    653 
    654   notification_list()->MarkSinglePopupAsShown(id1, true);
    655 
    656   n1 = GetNotification(id1);
    657   EXPECT_TRUE(n1->shown_as_popup());
    658   EXPECT_TRUE(n1->IsRead());
    659 
    660   const std::string replaced("test-replaced-id");
    661   scoped_ptr<Notification> notification(
    662       new Notification(message_center::NOTIFICATION_TYPE_SIMPLE,
    663                        replaced,
    664                        UTF8ToUTF16("newtitle"),
    665                        UTF8ToUTF16("newbody"),
    666                        gfx::Image(),
    667                        UTF8ToUTF16(kDisplaySource),
    668                        NotifierId(NotifierId::APPLICATION, kExtensionId),
    669                        message_center::RichNotificationData(),
    670                        NULL));
    671   notification_list()->UpdateNotificationMessage(id1, notification.Pass());
    672   n1 = GetNotification(id1);
    673   EXPECT_TRUE(n1 == NULL);
    674   const Notification* nr = GetNotification(replaced);
    675   EXPECT_TRUE(nr->shown_as_popup());
    676   EXPECT_TRUE(nr->IsRead());
    677 }
    678 
    679 TEST_F(NotificationListTest, QuietMode) {
    680   notification_list()->SetQuietMode(true);
    681   AddNotification();
    682   AddPriorityNotification(HIGH_PRIORITY);
    683   AddPriorityNotification(MAX_PRIORITY);
    684   EXPECT_EQ(3u, notification_list()->NotificationCount(blockers()));
    685   EXPECT_EQ(0u, GetPopupCounts());
    686 
    687   notification_list()->SetQuietMode(false);
    688   AddNotification();
    689   EXPECT_EQ(4u, notification_list()->NotificationCount(blockers()));
    690   EXPECT_EQ(1u, GetPopupCounts());
    691 
    692   // TODO(mukai): Add test of quiet mode with expiration.
    693 }
    694 
    695 // Verifies that unread_count doesn't become negative.
    696 TEST_F(NotificationListTest, UnreadCountNoNegative) {
    697   std::string id = AddNotification();
    698   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    699 
    700   notification_list()->MarkSinglePopupAsDisplayed(id);
    701   EXPECT_EQ(0u, notification_list()->UnreadCount(blockers()));
    702   notification_list()->MarkSinglePopupAsShown(
    703       id, false /* mark_notification_as_read */);
    704   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    705 
    706   // Updates the notification  and verifies unread_count doesn't change.
    707   scoped_ptr<Notification> updated_notification(new Notification(
    708       message_center::NOTIFICATION_TYPE_SIMPLE,
    709       id,
    710       UTF8ToUTF16("updated"),
    711       UTF8ToUTF16("updated"),
    712       gfx::Image(),
    713       base::string16(),
    714       NotifierId(),
    715       RichNotificationData(),
    716       NULL));
    717   notification_list()->AddNotification(updated_notification.Pass());
    718   EXPECT_EQ(1u, notification_list()->UnreadCount(blockers()));
    719 }
    720 
    721 TEST_F(NotificationListTest, TestPushingShownNotification) {
    722   // Create a notification and mark it as shown.
    723   std::string id1;
    724   scoped_ptr<Notification> notification(MakeNotification(&id1));
    725   notification->set_shown_as_popup(true);
    726 
    727   // Call PushNotification on this notification.
    728   notification_list()->PushNotification(notification.Pass());
    729 
    730   // Ensure it is still marked as shown.
    731   EXPECT_TRUE(GetNotification(id1)->shown_as_popup());
    732 }
    733 
    734 TEST_F(NotificationListTest, TestHasNotificationOfType) {
    735   std::string id = AddNotification();
    736 
    737   EXPECT_TRUE(notification_list()->HasNotificationOfType(
    738       id, message_center::NOTIFICATION_TYPE_SIMPLE));
    739   EXPECT_FALSE(notification_list()->HasNotificationOfType(
    740       id, message_center::NOTIFICATION_TYPE_PROGRESS));
    741 
    742   scoped_ptr<Notification> updated_notification(new Notification(
    743       message_center::NOTIFICATION_TYPE_PROGRESS,
    744       id,
    745       UTF8ToUTF16("updated"),
    746       UTF8ToUTF16("updated"),
    747       gfx::Image(),
    748       base::string16(),
    749       NotifierId(),
    750       RichNotificationData(),
    751       NULL));
    752   notification_list()->AddNotification(updated_notification.Pass());
    753 
    754   EXPECT_FALSE(notification_list()->HasNotificationOfType(
    755       id, message_center::NOTIFICATION_TYPE_SIMPLE));
    756   EXPECT_TRUE(notification_list()->HasNotificationOfType(
    757       id, message_center::NOTIFICATION_TYPE_PROGRESS));
    758 }
    759 
    760 }  // namespace message_center
    761