notification_list_unittest.cc 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  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. #include "ui/message_center/notification_list.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/i18n/time_formatting.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/strings/stringprintf.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "base/values.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. #include "ui/message_center/fake_message_center.h"
  15. #include "ui/message_center/notification_blocker.h"
  16. #include "ui/message_center/public/cpp/message_center_constants.h"
  17. #include "ui/message_center/public/cpp/notification_types.h"
  18. #include "ui/message_center/public/cpp/notifier_id.h"
  19. #if BUILDFLAG(IS_CHROMEOS_ASH)
  20. #include "ash/constants/notifier_catalogs.h"
  21. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  22. namespace message_center {
  23. using NotificationState = NotificationList::NotificationState;
  24. // A trivial blocker that allows all popups.
  25. class NopNotificationBlocker : public NotificationBlocker {
  26. public:
  27. NopNotificationBlocker() : NotificationBlocker(/*message_center=*/nullptr) {}
  28. NopNotificationBlocker(const NopNotificationBlocker&) = delete;
  29. NopNotificationBlocker& operator=(const NopNotificationBlocker&) = delete;
  30. ~NopNotificationBlocker() override = default;
  31. bool ShouldShowNotificationAsPopup(
  32. const Notification& notification) const override {
  33. return true;
  34. }
  35. };
  36. class NotificationListTest : public testing::Test {
  37. public:
  38. NotificationListTest() {}
  39. NotificationListTest(const NotificationListTest&) = delete;
  40. NotificationListTest& operator=(const NotificationListTest&) = delete;
  41. ~NotificationListTest() override {}
  42. void SetUp() override {
  43. message_center_ = std::make_unique<FakeMessageCenter>();
  44. notification_list_ =
  45. std::make_unique<NotificationList>(message_center_.get());
  46. counter_ = 0;
  47. }
  48. protected:
  49. // Currently NotificationListTest doesn't care about some fields like title or
  50. // message, so put a simple template on it. Returns the id of the new
  51. // notification.
  52. std::string AddNotification(const RichNotificationData& optional_fields) {
  53. std::string new_id;
  54. std::unique_ptr<Notification> notification(
  55. MakeNotification(optional_fields, &new_id));
  56. notification_list_->AddNotification(std::move(notification));
  57. counter_++;
  58. return new_id;
  59. }
  60. std::string AddNotification() {
  61. return AddNotification(RichNotificationData());
  62. }
  63. // Construct a new notification for testing, but don't add it to the list yet.
  64. std::unique_ptr<Notification> MakeNotification(
  65. const RichNotificationData& optional_fields,
  66. std::string* id_out) {
  67. *id_out = base::StringPrintf(kIdFormat, counter_);
  68. std::unique_ptr<Notification> notification(
  69. new Notification(NOTIFICATION_TYPE_SIMPLE, *id_out,
  70. u"id" + base::NumberToString16(counter_),
  71. u"message" + base::NumberToString16(counter_),
  72. ui::ImageModel(), kDisplaySource, GURL(),
  73. NotifierId(NotifierType::APPLICATION, kExtensionId),
  74. optional_fields, nullptr));
  75. return notification;
  76. }
  77. std::unique_ptr<Notification> MakeNotification(std::string* id_out) {
  78. return MakeNotification(RichNotificationData(), id_out);
  79. }
  80. // Utility methods of AddNotification.
  81. std::string AddPriorityNotification(NotificationPriority priority) {
  82. RichNotificationData optional;
  83. optional.priority = priority;
  84. return AddNotification(optional);
  85. }
  86. NotificationList::PopupNotifications GetPopups() {
  87. return notification_list_->GetPopupNotifications(blockers_, nullptr);
  88. }
  89. size_t GetPopupCounts() {
  90. return GetPopups().size();
  91. }
  92. size_t GetPopupForBlockersCounts() {
  93. return notification_list_
  94. ->GetPopupNotificationsWithoutBlocker(blockers_,
  95. NopNotificationBlocker())
  96. .size();
  97. }
  98. Notification* GetNotification(const std::string& id) {
  99. auto iter = notification_list_->GetNotification(id);
  100. if (iter == notification_list_->notifications_.end())
  101. return nullptr;
  102. return iter->first.get();
  103. }
  104. NotificationState GetNotificationState(const std::string& id) {
  105. auto iter = notification_list_->GetNotification(id);
  106. EXPECT_FALSE(iter == notification_list_->notifications_.end());
  107. return iter->second;
  108. }
  109. static const char kIdFormat[];
  110. static const char16_t kDisplaySource[];
  111. static const char kExtensionId[];
  112. std::unique_ptr<FakeMessageCenter> message_center_;
  113. std::unique_ptr<NotificationList> notification_list_;
  114. NotificationBlockers blockers_;
  115. size_t counter_;
  116. };
  117. bool IsInNotifications(const NotificationList::Notifications& notifications,
  118. const std::string& id) {
  119. for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
  120. if ((*iter)->id() == id)
  121. return true;
  122. }
  123. return false;
  124. }
  125. const char NotificationListTest::kIdFormat[] = "id%ld";
  126. const char16_t NotificationListTest::kDisplaySource[] = u"source";
  127. const char NotificationListTest::kExtensionId[] = "ext";
  128. TEST_F(NotificationListTest, Basic) {
  129. ASSERT_EQ(0u, notification_list_->NotificationCount(blockers_));
  130. std::string id0 = AddNotification();
  131. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  132. std::string id1 = AddNotification();
  133. EXPECT_EQ(2u, notification_list_->NotificationCount(blockers_));
  134. EXPECT_TRUE(notification_list_->HasPopupNotifications(blockers_));
  135. EXPECT_TRUE(notification_list_->GetNotificationById(id0));
  136. EXPECT_TRUE(notification_list_->GetNotificationById(id1));
  137. EXPECT_FALSE(notification_list_->GetNotificationById(id1 + "foo"));
  138. EXPECT_EQ(2u, GetPopupCounts());
  139. notification_list_->MarkSinglePopupAsShown(id0, true);
  140. notification_list_->MarkSinglePopupAsShown(id1, true);
  141. EXPECT_EQ(2u, notification_list_->NotificationCount(blockers_));
  142. EXPECT_EQ(0u, GetPopupCounts());
  143. notification_list_->RemoveNotification(id0);
  144. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  145. AddNotification();
  146. EXPECT_EQ(2u, notification_list_->NotificationCount(blockers_));
  147. }
  148. TEST_F(NotificationListTest, MessageCenterVisible) {
  149. AddNotification();
  150. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  151. ASSERT_EQ(1u, GetPopupCounts());
  152. // Resets the unread count and popup counts.
  153. notification_list_->SetNotificationsShown(blockers_, nullptr);
  154. ASSERT_EQ(0u, GetPopupCounts());
  155. }
  156. TEST_F(NotificationListTest, UpdateNotification) {
  157. std::string id0 = AddNotification();
  158. std::string replaced = id0 + "_replaced";
  159. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  160. std::unique_ptr<Notification> notification(
  161. new Notification(NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle",
  162. u"newbody", ui::ImageModel(), kDisplaySource, GURL(),
  163. NotifierId(NotifierType::APPLICATION, kExtensionId),
  164. RichNotificationData(), nullptr));
  165. notification_list_->UpdateNotificationMessage(id0, std::move(notification));
  166. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  167. const NotificationList::Notifications notifications =
  168. notification_list_->GetVisibleNotifications(blockers_);
  169. EXPECT_EQ(replaced, (*notifications.begin())->id());
  170. EXPECT_EQ(u"newtitle", (*notifications.begin())->title());
  171. EXPECT_EQ(u"newbody", (*notifications.begin())->message());
  172. }
  173. TEST_F(NotificationListTest, UpdateNotificationWithRenotifyAndQuietMode) {
  174. for (size_t quiet_mode = 0u; quiet_mode < 2u; ++quiet_mode) {
  175. // Set Do Not Disturb mode.
  176. notification_list_->SetQuietMode(static_cast<bool>(quiet_mode));
  177. // Create notification.
  178. std::string old_id;
  179. auto old_notification = MakeNotification(&old_id);
  180. notification_list_->AddNotification(std::move(old_notification));
  181. notification_list_->MarkSinglePopupAsShown(old_id, true);
  182. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  183. std::string new_id;
  184. auto new_notification = MakeNotification(&new_id);
  185. // Set the renotify flag and update.
  186. new_notification->set_renotify(true);
  187. notification_list_->UpdateNotificationMessage(old_id,
  188. std::move(new_notification));
  189. const NotificationList::Notifications notifications =
  190. notification_list_->GetVisibleNotifications(blockers_);
  191. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  192. EXPECT_EQ(new_id, (*notifications.begin())->id());
  193. // Normally, |shown_as_popup| should be reset in order to show the popup
  194. // again.
  195. // In quiet mode, |shown_as_popup| should not be reset, as popup should not
  196. // be shown even though renotify was set.
  197. const NotificationList::PopupNotifications popup_notifications =
  198. notification_list_->GetPopupNotifications(blockers_, nullptr);
  199. if (quiet_mode) {
  200. ASSERT_EQ(0U, popup_notifications.size());
  201. } else {
  202. ASSERT_EQ(1U, popup_notifications.size());
  203. EXPECT_EQ(new_id, (*popup_notifications.begin())->id());
  204. }
  205. }
  206. }
  207. TEST_F(NotificationListTest, ResetPopupInQuietMode) {
  208. for (size_t quiet_mode = 0u; quiet_mode < 2u; ++quiet_mode) {
  209. // Set Do Not Disturb mode.
  210. notification_list_->SetQuietMode(static_cast<bool>(quiet_mode));
  211. // Create notification.
  212. std::string id;
  213. auto old_notification = MakeNotification(&id);
  214. notification_list_->AddNotification(std::move(old_notification));
  215. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  216. // Reset single popup and make sure that the behavior is correct
  217. // within/outside of quiet mode.
  218. notification_list_->ResetSinglePopup(id);
  219. // Normally, `shown_as_popup` should be reset in order to show the popup
  220. // again. However, in quiet mode, `shown_as_popup` should not be reset since
  221. // we don't want the popup to be shown.
  222. const NotificationList::PopupNotifications popup_notifications =
  223. notification_list_->GetPopupNotifications(blockers_, nullptr);
  224. if (quiet_mode) {
  225. ASSERT_EQ(0U, popup_notifications.size());
  226. } else {
  227. ASSERT_EQ(1U, popup_notifications.size());
  228. EXPECT_EQ(id, (*popup_notifications.begin())->id());
  229. }
  230. }
  231. }
  232. TEST_F(NotificationListTest, GetNotificationsByNotifierId) {
  233. NotifierId id0(NotifierType::APPLICATION, "ext0");
  234. NotifierId id1(NotifierType::APPLICATION, "ext1");
  235. NotifierId id2(GURL("http://example.com"));
  236. #if BUILDFLAG(IS_CHROMEOS_ASH)
  237. NotifierId id3(NotifierType::SYSTEM_COMPONENT, "system-notifier",
  238. ash::NotificationCatalogName::kTestCatalogName);
  239. #else
  240. NotifierId id3(NotifierType::SYSTEM_COMPONENT, "system-notifier");
  241. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  242. std::unique_ptr<Notification> notification(new Notification(
  243. NOTIFICATION_TYPE_SIMPLE, "id0", u"title0", u"message0", ui::ImageModel(),
  244. u"source0", GURL(), id0, RichNotificationData(), nullptr));
  245. notification_list_->AddNotification(std::move(notification));
  246. notification = std::make_unique<Notification>(
  247. NOTIFICATION_TYPE_SIMPLE, "id1", u"title1", u"message1", ui::ImageModel(),
  248. u"source0", GURL(), id0, RichNotificationData(), nullptr);
  249. notification_list_->AddNotification(std::move(notification));
  250. notification = std::make_unique<Notification>(
  251. NOTIFICATION_TYPE_SIMPLE, "id2", u"title1", u"message1", ui::ImageModel(),
  252. u"source1", GURL(), id0, RichNotificationData(), nullptr);
  253. notification_list_->AddNotification(std::move(notification));
  254. notification = std::make_unique<Notification>(
  255. NOTIFICATION_TYPE_SIMPLE, "id3", u"title1", u"message1", ui::ImageModel(),
  256. u"source2", GURL(), id1, RichNotificationData(), nullptr);
  257. notification_list_->AddNotification(std::move(notification));
  258. notification = std::make_unique<Notification>(
  259. NOTIFICATION_TYPE_SIMPLE, "id4", u"title1", u"message1", ui::ImageModel(),
  260. u"source2", GURL(), id2, RichNotificationData(), nullptr);
  261. notification_list_->AddNotification(std::move(notification));
  262. notification = std::make_unique<Notification>(
  263. NOTIFICATION_TYPE_SIMPLE, "id5", u"title1", u"message1", ui::ImageModel(),
  264. u"source2", GURL(), id3, RichNotificationData(), nullptr);
  265. notification_list_->AddNotification(std::move(notification));
  266. NotificationList::Notifications by_notifier_id =
  267. notification_list_->GetNotificationsByNotifierId(id0);
  268. EXPECT_TRUE(IsInNotifications(by_notifier_id, "id0"));
  269. EXPECT_TRUE(IsInNotifications(by_notifier_id, "id1"));
  270. EXPECT_TRUE(IsInNotifications(by_notifier_id, "id2"));
  271. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
  272. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
  273. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
  274. by_notifier_id = notification_list_->GetNotificationsByNotifierId(id1);
  275. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
  276. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
  277. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
  278. EXPECT_TRUE(IsInNotifications(by_notifier_id, "id3"));
  279. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
  280. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
  281. by_notifier_id = notification_list_->GetNotificationsByNotifierId(id2);
  282. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
  283. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
  284. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
  285. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
  286. EXPECT_TRUE(IsInNotifications(by_notifier_id, "id4"));
  287. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id5"));
  288. by_notifier_id = notification_list_->GetNotificationsByNotifierId(id3);
  289. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id0"));
  290. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id1"));
  291. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id2"));
  292. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id3"));
  293. EXPECT_FALSE(IsInNotifications(by_notifier_id, "id4"));
  294. EXPECT_TRUE(IsInNotifications(by_notifier_id, "id5"));
  295. }
  296. TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) {
  297. std::vector<std::string> ids;
  298. for (size_t i = 0; i <= kMaxVisiblePopupNotifications; i++)
  299. ids.push_back(AddNotification());
  300. NotificationList::PopupNotifications popups = GetPopups();
  301. // The popup should contain the oldest kMaxVisiblePopupNotifications. Newer
  302. // one should come earlier in the popup list. It means, the last element
  303. // of |popups| should be the firstly added one, and so on.
  304. EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
  305. auto iter = popups.rbegin();
  306. for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i, ++iter) {
  307. EXPECT_EQ(ids[i], (*iter)->id()) << i;
  308. }
  309. for (auto* popup : popups) {
  310. notification_list_->MarkSinglePopupAsShown(popup->id(), false);
  311. }
  312. popups.clear();
  313. popups = GetPopups();
  314. ASSERT_EQ(1u, popups.size());
  315. EXPECT_EQ(ids.back(), (*popups.begin())->id());
  316. }
  317. TEST_F(NotificationListTest, Priority) {
  318. ASSERT_EQ(0u, notification_list_->NotificationCount(blockers_));
  319. // Default priority has the limit on the number of the popups.
  320. for (size_t i = 0; i <= kMaxVisiblePopupNotifications; ++i)
  321. AddNotification();
  322. EXPECT_EQ(kMaxVisiblePopupNotifications + 1,
  323. notification_list_->NotificationCount(blockers_));
  324. EXPECT_EQ(kMaxVisiblePopupNotifications, GetPopupCounts());
  325. // Low priority: not visible to popups.
  326. notification_list_->SetNotificationsShown(blockers_, nullptr);
  327. AddPriorityNotification(LOW_PRIORITY);
  328. EXPECT_EQ(kMaxVisiblePopupNotifications + 2,
  329. notification_list_->NotificationCount(blockers_));
  330. EXPECT_EQ(0u, GetPopupCounts());
  331. // Minimum priority: doesn't update the unread count.
  332. AddPriorityNotification(MIN_PRIORITY);
  333. EXPECT_EQ(kMaxVisiblePopupNotifications + 3,
  334. notification_list_->NotificationCount(blockers_));
  335. EXPECT_EQ(0u, GetPopupCounts());
  336. NotificationList::Notifications notifications =
  337. notification_list_->GetVisibleNotifications(blockers_);
  338. for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
  339. notification_list_->RemoveNotification((*iter)->id());
  340. }
  341. // Higher priority: no limits to the number of popups.
  342. for (size_t i = 0; i < kMaxVisiblePopupNotifications * 2; ++i)
  343. AddPriorityNotification(HIGH_PRIORITY);
  344. for (size_t i = 0; i < kMaxVisiblePopupNotifications * 2; ++i)
  345. AddPriorityNotification(MAX_PRIORITY);
  346. EXPECT_EQ(kMaxVisiblePopupNotifications * 4,
  347. notification_list_->NotificationCount(blockers_));
  348. EXPECT_EQ(kMaxVisiblePopupNotifications * 4, GetPopupCounts());
  349. }
  350. TEST_F(NotificationListTest, WithoutOneBlocker) {
  351. ASSERT_EQ(0u, notification_list_->NotificationCount(blockers_));
  352. // Limit is not considered, even for default priority popups.
  353. for (size_t i = 0; i <= kMaxVisiblePopupNotifications; ++i)
  354. AddNotification();
  355. EXPECT_EQ(kMaxVisiblePopupNotifications + 1,
  356. notification_list_->NotificationCount(blockers_));
  357. EXPECT_EQ(kMaxVisiblePopupNotifications + 1, GetPopupForBlockersCounts());
  358. // Popups aren't marked as shown.
  359. EXPECT_EQ(kMaxVisiblePopupNotifications + 1, GetPopupForBlockersCounts());
  360. }
  361. // Tests that GetNotificationsByAppId returns notifications regardless of their
  362. // visibility.
  363. TEST_F(NotificationListTest, GetNotificationsByAppId) {
  364. const std::string app_id1("app_id1");
  365. const std::string app_id2("app_id2");
  366. {
  367. // Add a notification for |app_id1|.
  368. const std::string id1("id1");
  369. std::unique_ptr<Notification> notification(
  370. new Notification(NOTIFICATION_TYPE_PROGRESS, id1, u"updated",
  371. u"updated", ui::ImageModel(), std::u16string(), GURL(),
  372. NotifierId(NotifierType::APPLICATION, app_id1),
  373. RichNotificationData(), nullptr));
  374. notification_list_->AddNotification(std::move(notification));
  375. EXPECT_EQ(1u, notification_list_->GetNotificationsByAppId(app_id1).size());
  376. // Mark the popup as shown but not read.
  377. notification_list_->MarkSinglePopupAsShown(id1, false);
  378. EXPECT_EQ(1u, notification_list_->GetNotificationsByAppId(app_id1).size());
  379. // Mark the popup as shown and read.
  380. notification_list_->MarkSinglePopupAsShown(id1, true);
  381. EXPECT_EQ(1u, notification_list_->GetNotificationsByAppId(app_id1).size());
  382. // Remove the notification.
  383. notification_list_->RemoveNotification(id1);
  384. EXPECT_EQ(0u, notification_list_->GetNotificationsByAppId(app_id1).size());
  385. // Add two notifications for |app_id1| and one for |app_id2|.
  386. notification = std::make_unique<Notification>(
  387. NOTIFICATION_TYPE_PROGRESS, id1, u"updated", u"updated",
  388. ui::ImageModel(), std::u16string(), GURL(),
  389. NotifierId(NotifierType::APPLICATION, app_id1), RichNotificationData(),
  390. nullptr);
  391. notification_list_->AddNotification(std::move(notification));
  392. const std::string id2("id2");
  393. notification = std::make_unique<Notification>(
  394. NOTIFICATION_TYPE_PROGRESS, id2, u"updated", u"updated",
  395. ui::ImageModel(), std::u16string(), GURL(),
  396. NotifierId(NotifierType::APPLICATION, app_id1), RichNotificationData(),
  397. nullptr);
  398. notification_list_->AddNotification(std::move(notification));
  399. EXPECT_EQ(2u, notification_list_->GetNotificationsByAppId(app_id1).size());
  400. const std::string id3("id3");
  401. notification = std::make_unique<Notification>(
  402. NOTIFICATION_TYPE_PROGRESS, id3, u"updated", u"updated",
  403. ui::ImageModel(), std::u16string(), GURL(),
  404. NotifierId(NotifierType::APPLICATION, app_id2), RichNotificationData(),
  405. nullptr);
  406. notification_list_->AddNotification(std::move(notification));
  407. EXPECT_EQ(2u, notification_list_->GetNotificationsByAppId(app_id1).size());
  408. EXPECT_EQ(1u, notification_list_->GetNotificationsByAppId(app_id2).size());
  409. }
  410. for (std::string app_id : {app_id1, app_id2}) {
  411. for (auto* notification :
  412. notification_list_->GetNotificationsByAppId(app_id)) {
  413. EXPECT_EQ(app_id, notification->notifier_id().id);
  414. }
  415. }
  416. }
  417. // Tests that GetNotificationsByOriginUrl returns notifications regardless of
  418. // their visibility.
  419. TEST_F(NotificationListTest, GetNotificationsByOriginUrl) {
  420. const GURL kUrl1(u"http://www.kurl1.com");
  421. const GURL kUrl2(u"http://www.kUrl2.com");
  422. {
  423. // Add a notification for `kurl1`.
  424. const std::string id1("id1");
  425. std::unique_ptr<Notification> notification(
  426. new Notification(NOTIFICATION_TYPE_PROGRESS, id1, u"updated",
  427. u"updated", ui::ImageModel(), std::u16string(), kUrl1,
  428. NotifierId(), RichNotificationData(), nullptr));
  429. notification_list_->AddNotification(std::move(notification));
  430. EXPECT_EQ(1u,
  431. notification_list_->GetNotificationsByOriginUrl(kUrl1).size());
  432. // Mark the popup as shown but not read.
  433. notification_list_->MarkSinglePopupAsShown(id1, false);
  434. EXPECT_EQ(1u,
  435. notification_list_->GetNotificationsByOriginUrl(kUrl1).size());
  436. // Mark the popup as shown and read.
  437. notification_list_->MarkSinglePopupAsShown(id1, true);
  438. EXPECT_EQ(1u,
  439. notification_list_->GetNotificationsByOriginUrl(kUrl1).size());
  440. // Remove the notification.
  441. notification_list_->RemoveNotification(id1);
  442. EXPECT_EQ(0u,
  443. notification_list_->GetNotificationsByOriginUrl(kUrl1).size());
  444. // Add two notifications for `kurl1` and one for `kUrl2`.
  445. notification = std::make_unique<Notification>(
  446. NOTIFICATION_TYPE_PROGRESS, id1, u"updated", u"updated",
  447. ui::ImageModel(), std::u16string(), kUrl1, NotifierId(),
  448. RichNotificationData(), nullptr);
  449. notification_list_->AddNotification(std::move(notification));
  450. const std::string id2("id2");
  451. notification = std::make_unique<Notification>(
  452. NOTIFICATION_TYPE_PROGRESS, id2, u"updated", u"updated",
  453. ui::ImageModel(), std::u16string(), kUrl1, NotifierId(),
  454. RichNotificationData(), nullptr);
  455. notification_list_->AddNotification(std::move(notification));
  456. EXPECT_EQ(2u,
  457. notification_list_->GetNotificationsByOriginUrl(kUrl1).size());
  458. const std::string id3("id3");
  459. notification = std::make_unique<Notification>(
  460. NOTIFICATION_TYPE_PROGRESS, id3, u"updated", u"updated",
  461. ui::ImageModel(), std::u16string(), kUrl2, NotifierId(),
  462. RichNotificationData(), nullptr);
  463. notification_list_->AddNotification(std::move(notification));
  464. EXPECT_EQ(2u,
  465. notification_list_->GetNotificationsByOriginUrl(kUrl1).size());
  466. EXPECT_EQ(1u,
  467. notification_list_->GetNotificationsByOriginUrl(kUrl2).size());
  468. }
  469. for (GURL url : {kUrl1, kUrl2}) {
  470. for (auto* notification :
  471. notification_list_->GetNotificationsByOriginUrl(url)) {
  472. EXPECT_EQ(url, notification->origin_url());
  473. }
  474. }
  475. }
  476. TEST_F(NotificationListTest, HasPopupsWithPriority) {
  477. ASSERT_EQ(0u, notification_list_->NotificationCount(blockers_));
  478. AddPriorityNotification(MIN_PRIORITY);
  479. AddPriorityNotification(MAX_PRIORITY);
  480. EXPECT_EQ(1u, GetPopupCounts());
  481. }
  482. TEST_F(NotificationListTest, HasPopupsWithSystemPriority) {
  483. ASSERT_EQ(0u, notification_list_->NotificationCount(blockers_));
  484. std::string normal_id = AddPriorityNotification(DEFAULT_PRIORITY);
  485. std::string system_id = AddNotification();
  486. GetNotification(system_id)->SetSystemPriority();
  487. EXPECT_EQ(2u, GetPopupCounts());
  488. notification_list_->MarkSinglePopupAsDisplayed(normal_id);
  489. notification_list_->MarkSinglePopupAsDisplayed(system_id);
  490. notification_list_->MarkSinglePopupAsShown(normal_id, false);
  491. notification_list_->MarkSinglePopupAsShown(system_id, false);
  492. EXPECT_EQ(1u, GetPopupCounts());
  493. // Mark as read -- emulation of mouse click.
  494. notification_list_->MarkSinglePopupAsShown(system_id, true);
  495. EXPECT_EQ(0u, GetPopupCounts());
  496. }
  497. TEST_F(NotificationListTest, GetNotifications) {
  498. ASSERT_EQ(0u, notification_list_->NotificationCount(blockers_));
  499. EXPECT_EQ(0u, notification_list_->GetNotifications().size());
  500. AddPriorityNotification(MIN_PRIORITY);
  501. AddPriorityNotification(MAX_PRIORITY);
  502. EXPECT_EQ(1u, GetPopupCounts());
  503. EXPECT_EQ(2u, notification_list_->GetNotifications().size());
  504. }
  505. // Verifies that notification updates will re-show the toast when there is no
  506. // message center view (i.e. the bubble anchored to the status bar).
  507. TEST_F(NotificationListTest, UpdateWithoutMessageCenterView) {
  508. auto run_test = [this](bool has_message_center_view) {
  509. message_center_->SetHasMessageCenterView(has_message_center_view);
  510. std::string id0 = AddNotification();
  511. std::string replaced = id0 + "_replaced";
  512. notification_list_->MarkSinglePopupAsShown(id0, false);
  513. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  514. EXPECT_EQ(0u, GetPopupCounts());
  515. RichNotificationData optional;
  516. std::unique_ptr<Notification> notification(
  517. new Notification(NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle",
  518. u"newbody", ui::ImageModel(), kDisplaySource, GURL(),
  519. NotifierId(NotifierType::APPLICATION, kExtensionId),
  520. optional, nullptr));
  521. notification_list_->UpdateNotificationMessage(id0, std::move(notification));
  522. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  523. EXPECT_EQ(has_message_center_view ? 0U : 1U, GetPopupCounts());
  524. const NotificationList::Notifications notifications =
  525. notification_list_->GetVisibleNotifications(blockers_);
  526. EXPECT_EQ(replaced, (*notifications.begin())->id());
  527. EXPECT_EQ(u"newtitle", (*notifications.begin())->title());
  528. EXPECT_EQ(u"newbody", (*notifications.begin())->message());
  529. notification_list_->RemoveNotification(replaced);
  530. EXPECT_EQ(0U,
  531. notification_list_->GetVisibleNotifications(blockers_).size());
  532. };
  533. run_test(false);
  534. run_test(true);
  535. }
  536. TEST_F(NotificationListTest, Renotify) {
  537. std::string id0 = AddNotification();
  538. std::string replaced = id0 + "_replaced";
  539. notification_list_->MarkSinglePopupAsShown(id0, false);
  540. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  541. EXPECT_EQ(0u, GetPopupCounts());
  542. RichNotificationData optional;
  543. optional.renotify = true;
  544. std::unique_ptr<Notification> notification(new Notification(
  545. NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody",
  546. ui::ImageModel(), kDisplaySource, GURL(),
  547. NotifierId(NotifierType::APPLICATION, kExtensionId), optional, nullptr));
  548. notification_list_->UpdateNotificationMessage(id0, std::move(notification));
  549. EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_));
  550. EXPECT_EQ(1u, GetPopupCounts());
  551. const NotificationList::Notifications notifications =
  552. notification_list_->GetVisibleNotifications(blockers_);
  553. EXPECT_EQ(replaced, (*notifications.begin())->id());
  554. EXPECT_EQ(u"newtitle", (*notifications.begin())->title());
  555. EXPECT_EQ(u"newbody", (*notifications.begin())->message());
  556. }
  557. TEST_F(NotificationListTest, PriorityAndRenotify) {
  558. std::string id0 = AddPriorityNotification(LOW_PRIORITY);
  559. std::string id1 = AddPriorityNotification(DEFAULT_PRIORITY);
  560. EXPECT_EQ(1u, GetPopupCounts());
  561. notification_list_->MarkSinglePopupAsShown(id1, true);
  562. EXPECT_EQ(0u, GetPopupCounts());
  563. // id0 promoted to LOW->DEFAULT, it'll appear as toast (popup).
  564. RichNotificationData priority;
  565. priority.priority = DEFAULT_PRIORITY;
  566. std::unique_ptr<Notification> notification(new Notification(
  567. NOTIFICATION_TYPE_SIMPLE, id0, u"newtitle", u"newbody", ui::ImageModel(),
  568. kDisplaySource, GURL(),
  569. NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr));
  570. notification_list_->UpdateNotificationMessage(id0, std::move(notification));
  571. EXPECT_EQ(1u, GetPopupCounts());
  572. notification_list_->MarkSinglePopupAsShown(id0, true);
  573. EXPECT_EQ(0u, GetPopupCounts());
  574. // update with no promotion change for id0, it won't appear as a toast.
  575. notification = std::make_unique<Notification>(
  576. NOTIFICATION_TYPE_SIMPLE, id0, u"newtitle2", u"newbody2",
  577. ui::ImageModel(), kDisplaySource, GURL(),
  578. NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr);
  579. notification_list_->UpdateNotificationMessage(id0, std::move(notification));
  580. EXPECT_EQ(0u, GetPopupCounts());
  581. // id1 promoted to DEFAULT->HIGH, it won't reappear as a toast (popup).
  582. priority.priority = HIGH_PRIORITY;
  583. notification = std::make_unique<Notification>(
  584. NOTIFICATION_TYPE_SIMPLE, id1, u"newtitle", u"newbody", ui::ImageModel(),
  585. kDisplaySource, GURL(),
  586. NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr);
  587. notification_list_->UpdateNotificationMessage(id1, std::move(notification));
  588. EXPECT_EQ(0u, GetPopupCounts());
  589. // |renotify| will make it reappear as a toast (popup).
  590. priority.renotify = true;
  591. notification = std::make_unique<Notification>(
  592. NOTIFICATION_TYPE_SIMPLE, id1, u"newtitle", u"newbody", ui::ImageModel(),
  593. kDisplaySource, GURL(),
  594. NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr);
  595. notification_list_->UpdateNotificationMessage(id1, std::move(notification));
  596. EXPECT_EQ(1u, GetPopupCounts());
  597. notification_list_->MarkSinglePopupAsShown(id1, true);
  598. EXPECT_EQ(0u, GetPopupCounts());
  599. }
  600. TEST_F(NotificationListTest, NotificationOrderAndPriority) {
  601. base::Time now = base::Time::Now();
  602. RichNotificationData optional;
  603. optional.timestamp = now;
  604. optional.priority = 2;
  605. std::string max_id = AddNotification(optional);
  606. now += base::Seconds(1);
  607. optional.timestamp = now;
  608. optional.priority = 1;
  609. std::string high_id = AddNotification(optional);
  610. now += base::Seconds(1);
  611. optional.timestamp = now;
  612. optional.priority = 0;
  613. std::string default_id = AddNotification(optional);
  614. {
  615. // Popups: latest comes first.
  616. NotificationList::PopupNotifications popups = GetPopups();
  617. EXPECT_EQ(3u, popups.size());
  618. auto iter = popups.begin();
  619. EXPECT_EQ(default_id, (*iter)->id());
  620. iter++;
  621. EXPECT_EQ(high_id, (*iter)->id());
  622. iter++;
  623. EXPECT_EQ(max_id, (*iter)->id());
  624. }
  625. {
  626. // Notifications: high priority comes earlier.
  627. const NotificationList::Notifications notifications =
  628. notification_list_->GetVisibleNotifications(blockers_);
  629. EXPECT_EQ(3u, notifications.size());
  630. auto iter = notifications.begin();
  631. EXPECT_EQ(max_id, (*iter)->id());
  632. iter++;
  633. EXPECT_EQ(high_id, (*iter)->id());
  634. iter++;
  635. EXPECT_EQ(default_id, (*iter)->id());
  636. }
  637. }
  638. TEST_F(NotificationListTest, MarkSinglePopupAsShown) {
  639. std::string id1 = AddNotification();
  640. std::string id2 = AddNotification();
  641. std::string id3 = AddNotification();
  642. ASSERT_EQ(3u, notification_list_->NotificationCount(blockers_));
  643. ASSERT_EQ(std::min(static_cast<size_t>(3u), kMaxVisiblePopupNotifications),
  644. GetPopupCounts());
  645. notification_list_->MarkSinglePopupAsDisplayed(id1);
  646. notification_list_->MarkSinglePopupAsDisplayed(id2);
  647. notification_list_->MarkSinglePopupAsDisplayed(id3);
  648. notification_list_->MarkSinglePopupAsShown(id2, true);
  649. notification_list_->MarkSinglePopupAsShown(id3, false);
  650. EXPECT_EQ(3u, notification_list_->NotificationCount(blockers_));
  651. EXPECT_EQ(1u, GetPopupCounts());
  652. NotificationList::PopupNotifications popups = GetPopups();
  653. EXPECT_EQ(id1, (*popups.begin())->id());
  654. // The notifications in the NotificationCenter are unaffected by popups shown.
  655. NotificationList::Notifications notifications =
  656. notification_list_->GetVisibleNotifications(blockers_);
  657. auto iter = notifications.begin();
  658. EXPECT_EQ(id3, (*iter)->id());
  659. iter++;
  660. EXPECT_EQ(id2, (*iter)->id());
  661. iter++;
  662. EXPECT_EQ(id1, (*iter)->id());
  663. }
  664. TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) {
  665. std::string id1 = AddNotification();
  666. std::string id2 = AddNotification();
  667. notification_list_->MarkSinglePopupAsDisplayed(id1);
  668. notification_list_->MarkSinglePopupAsDisplayed(id2);
  669. EXPECT_EQ(2u, GetPopupCounts());
  670. NotificationState n1_state = GetNotificationState(id1);
  671. EXPECT_FALSE(n1_state.shown_as_popup);
  672. EXPECT_TRUE(n1_state.is_read);
  673. notification_list_->MarkSinglePopupAsShown(id1, true);
  674. n1_state = GetNotificationState(id1);
  675. EXPECT_TRUE(n1_state.shown_as_popup);
  676. EXPECT_TRUE(n1_state.is_read);
  677. const std::string replaced("test-replaced-id");
  678. std::unique_ptr<Notification> notification(
  679. new Notification(NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle",
  680. u"newbody", ui::ImageModel(), kDisplaySource, GURL(),
  681. NotifierId(NotifierType::APPLICATION, kExtensionId),
  682. RichNotificationData(), nullptr));
  683. notification_list_->UpdateNotificationMessage(id1, std::move(notification));
  684. Notification* n1 = GetNotification(id1);
  685. EXPECT_TRUE(n1 == nullptr);
  686. const NotificationState nr_state = GetNotificationState(replaced);
  687. EXPECT_TRUE(nr_state.shown_as_popup);
  688. EXPECT_TRUE(nr_state.is_read);
  689. }
  690. TEST_F(NotificationListTest, QuietMode) {
  691. notification_list_->SetQuietMode(true);
  692. AddNotification();
  693. AddPriorityNotification(HIGH_PRIORITY);
  694. AddPriorityNotification(MAX_PRIORITY);
  695. EXPECT_EQ(3u, notification_list_->NotificationCount(blockers_));
  696. EXPECT_EQ(0u, GetPopupCounts());
  697. notification_list_->SetQuietMode(false);
  698. AddNotification();
  699. EXPECT_EQ(4u, notification_list_->NotificationCount(blockers_));
  700. EXPECT_EQ(1u, GetPopupCounts());
  701. // TODO(mukai): Add test of quiet mode with expiration.
  702. }
  703. TEST_F(NotificationListTest, TestHasNotificationOfType) {
  704. std::string id = AddNotification();
  705. EXPECT_TRUE(
  706. notification_list_->HasNotificationOfType(id, NOTIFICATION_TYPE_SIMPLE));
  707. EXPECT_FALSE(notification_list_->HasNotificationOfType(
  708. id, NOTIFICATION_TYPE_PROGRESS));
  709. std::unique_ptr<Notification> updated_notification(new Notification(
  710. NOTIFICATION_TYPE_PROGRESS, id, u"updated", u"updated", ui::ImageModel(),
  711. std::u16string(), GURL(), NotifierId(), RichNotificationData(), nullptr));
  712. notification_list_->AddNotification(std::move(updated_notification));
  713. EXPECT_FALSE(
  714. notification_list_->HasNotificationOfType(id, NOTIFICATION_TYPE_SIMPLE));
  715. EXPECT_TRUE(notification_list_->HasNotificationOfType(
  716. id, NOTIFICATION_TYPE_PROGRESS));
  717. }
  718. } // namespace message_center