Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / message_center / message_center_impl_unittest.cc
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   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   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   ~ToggledNotificationBlocker() override {}
111
112   void SetNotificationsEnabled(bool enabled) {
113     if (notifications_enabled_ != enabled) {
114       notifications_enabled_ = enabled;
115       NotifyBlockingStateChanged();
116     }
117   }
118
119   // NotificationBlocker overrides:
120   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   ~PopupNotificationBlocker() override {}
138
139   // NotificationBlocker overrides:
140   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   ~TotalNotificationBlocker() override {}
158
159   // NotificationBlocker overrides:
160   bool ShouldShowNotification(const NotifierId& notifier_id) const override {
161     return ShouldShowNotificationAsPopup(notifier_id);
162   }
163
164  private:
165   DISALLOW_COPY_AND_ASSIGN(TotalNotificationBlocker);
166 };
167
168 bool PopupNotificationsContain(
169     const NotificationList::PopupNotifications& popups,
170     const std::string& id) {
171   for (NotificationList::PopupNotifications::const_iterator iter =
172            popups.begin(); iter != popups.end(); ++iter) {
173     if ((*iter)->id() == id)
174       return true;
175   }
176   return false;
177 }
178
179 // Right now, MessageCenter::HasNotification() returns regardless of blockers.
180 bool NotificationsContain(
181     const NotificationList::Notifications& notifications,
182     const std::string& id) {
183   for (NotificationList::Notifications::const_iterator iter =
184            notifications.begin(); iter != notifications.end(); ++iter) {
185     if ((*iter)->id() == id)
186       return true;
187   }
188   return false;
189 }
190
191 }  // namespace
192
193 namespace internal {
194
195 class MockPopupTimersController : public PopupTimersController {
196  public:
197   MockPopupTimersController(MessageCenter* message_center,
198                             base::Closure quit_closure)
199       : PopupTimersController(message_center),
200         timer_finished_(false),
201         quit_closure_(quit_closure) {}
202   ~MockPopupTimersController() override {}
203
204   void TimerFinished(const std::string& id) override {
205     base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
206     timer_finished_ = true;
207     last_id_ = id;
208   }
209
210   bool timer_finished() const { return timer_finished_; }
211   const std::string& last_id() const { return last_id_; }
212
213  private:
214   bool timer_finished_;
215   std::string last_id_;
216   base::Closure quit_closure_;
217 };
218
219 TEST_F(MessageCenterImplTest, PopupTimersEmptyController) {
220   scoped_ptr<PopupTimersController> popup_timers_controller =
221       make_scoped_ptr(new PopupTimersController(message_center()));
222
223   // Test that all functions succed without any timers created.
224   popup_timers_controller->PauseAll();
225   popup_timers_controller->StartAll();
226   popup_timers_controller->CancelAll();
227   popup_timers_controller->TimerFinished("unknown");
228   popup_timers_controller->PauseTimer("unknown");
229   popup_timers_controller->CancelTimer("unknown");
230 }
231
232 TEST_F(MessageCenterImplTest, PopupTimersControllerStartTimer) {
233   scoped_ptr<MockPopupTimersController> popup_timers_controller =
234       make_scoped_ptr(
235           new MockPopupTimersController(message_center(), closure()));
236   popup_timers_controller->StartTimer("test",
237                                       base::TimeDelta::FromMilliseconds(1));
238   run_loop()->Run();
239   EXPECT_TRUE(popup_timers_controller->timer_finished());
240 }
241
242 TEST_F(MessageCenterImplTest, PopupTimersControllerPauseTimer) {
243   scoped_ptr<MockPopupTimersController> popup_timers_controller =
244       make_scoped_ptr(
245           new MockPopupTimersController(message_center(), closure()));
246   popup_timers_controller->StartTimer("test",
247                                       base::TimeDelta::FromMilliseconds(1));
248   popup_timers_controller->PauseTimer("test");
249   run_loop()->RunUntilIdle();
250
251   EXPECT_FALSE(popup_timers_controller->timer_finished());
252 }
253
254 TEST_F(MessageCenterImplTest, PopupTimersControllerCancelTimer) {
255   scoped_ptr<MockPopupTimersController> popup_timers_controller =
256       make_scoped_ptr(
257           new MockPopupTimersController(message_center(), closure()));
258   popup_timers_controller->StartTimer("test",
259                                       base::TimeDelta::FromMilliseconds(1));
260   popup_timers_controller->CancelTimer("test");
261   run_loop()->RunUntilIdle();
262
263   EXPECT_FALSE(popup_timers_controller->timer_finished());
264 }
265
266 TEST_F(MessageCenterImplTest, PopupTimersControllerPauseAllTimers) {
267   scoped_ptr<MockPopupTimersController> popup_timers_controller =
268       make_scoped_ptr(
269           new MockPopupTimersController(message_center(), closure()));
270   popup_timers_controller->StartTimer("test",
271                                       base::TimeDelta::FromMilliseconds(1));
272   popup_timers_controller->PauseAll();
273   run_loop()->RunUntilIdle();
274
275   EXPECT_FALSE(popup_timers_controller->timer_finished());
276 }
277
278 TEST_F(MessageCenterImplTest, PopupTimersControllerStartAllTimers) {
279   scoped_ptr<MockPopupTimersController> popup_timers_controller =
280       make_scoped_ptr(
281           new MockPopupTimersController(message_center(), closure()));
282   popup_timers_controller->StartTimer("test",
283                                       base::TimeDelta::FromMilliseconds(1));
284   popup_timers_controller->PauseAll();
285   popup_timers_controller->StartAll();
286   run_loop()->Run();
287
288   EXPECT_TRUE(popup_timers_controller->timer_finished());
289 }
290
291 TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimers) {
292   scoped_ptr<MockPopupTimersController> popup_timers_controller =
293       make_scoped_ptr(
294           new MockPopupTimersController(message_center(), closure()));
295   popup_timers_controller->StartTimer("test",
296                                       base::TimeDelta::FromMilliseconds(5));
297   popup_timers_controller->StartTimer("test2",
298                                       base::TimeDelta::FromMilliseconds(1));
299   popup_timers_controller->StartTimer("test3",
300                                       base::TimeDelta::FromMilliseconds(3));
301   popup_timers_controller->PauseAll();
302   popup_timers_controller->StartAll();
303   run_loop()->Run();
304
305   EXPECT_EQ(popup_timers_controller->last_id(), "test2");
306   EXPECT_TRUE(popup_timers_controller->timer_finished());
307 }
308
309 TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimersPause) {
310   scoped_ptr<MockPopupTimersController> popup_timers_controller =
311       make_scoped_ptr(
312           new MockPopupTimersController(message_center(), closure()));
313   popup_timers_controller->StartTimer("test",
314                                       base::TimeDelta::FromMilliseconds(5));
315   popup_timers_controller->StartTimer("test2",
316                                       base::TimeDelta::FromMilliseconds(1));
317   popup_timers_controller->StartTimer("test3",
318                                       base::TimeDelta::FromMilliseconds(3));
319   popup_timers_controller->PauseTimer("test2");
320
321   run_loop()->Run();
322
323   EXPECT_EQ(popup_timers_controller->last_id(), "test3");
324   EXPECT_TRUE(popup_timers_controller->timer_finished());
325 }
326
327 TEST_F(MessageCenterImplTest, PopupTimersControllerResetTimer) {
328   scoped_ptr<MockPopupTimersController> popup_timers_controller =
329       make_scoped_ptr(
330           new MockPopupTimersController(message_center(), closure()));
331   popup_timers_controller->StartTimer("test",
332                                       base::TimeDelta::FromMilliseconds(5));
333   popup_timers_controller->StartTimer("test2",
334                                       base::TimeDelta::FromMilliseconds(1));
335   popup_timers_controller->StartTimer("test3",
336                                       base::TimeDelta::FromMilliseconds(3));
337   popup_timers_controller->PauseTimer("test2");
338   popup_timers_controller->ResetTimer("test",
339                                       base::TimeDelta::FromMilliseconds(2));
340
341   run_loop()->Run();
342
343   EXPECT_EQ(popup_timers_controller->last_id(), "test");
344   EXPECT_TRUE(popup_timers_controller->timer_finished());
345 }
346
347 TEST_F(MessageCenterImplTest, NotificationBlocker) {
348   NotifierId notifier_id(NotifierId::APPLICATION, "app1");
349   // Multiple blockers to verify the case that one blocker blocks but another
350   // doesn't.
351   ToggledNotificationBlocker blocker1(message_center());
352   ToggledNotificationBlocker blocker2(message_center());
353
354   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
355       NOTIFICATION_TYPE_SIMPLE,
356       "id1",
357       UTF8ToUTF16("title"),
358       UTF8ToUTF16("message"),
359       gfx::Image() /* icon */,
360       base::string16() /* display_source */,
361       notifier_id,
362       RichNotificationData(),
363       NULL)));
364   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
365       NOTIFICATION_TYPE_SIMPLE,
366       "id2",
367       UTF8ToUTF16("title"),
368       UTF8ToUTF16("message"),
369       gfx::Image() /* icon */,
370       base::string16() /* display_source */,
371       notifier_id,
372       RichNotificationData(),
373       NULL)));
374   EXPECT_EQ(2u, message_center()->GetPopupNotifications().size());
375   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
376
377   // Block all notifications. All popups are gone and message center should be
378   // hidden.
379   blocker1.SetNotificationsEnabled(false);
380   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
381   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
382
383   // Updates |blocker2| state, which doesn't affect the global state.
384   blocker2.SetNotificationsEnabled(false);
385   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
386   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
387
388   blocker2.SetNotificationsEnabled(true);
389   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
390   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
391
392   // If |blocker2| blocks, then unblocking blocker1 doesn't change the global
393   // state.
394   blocker2.SetNotificationsEnabled(false);
395   blocker1.SetNotificationsEnabled(true);
396   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
397   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
398
399   // Unblock both blockers, which recovers the global state, but the popups
400   // aren't shown.
401   blocker2.SetNotificationsEnabled(true);
402   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
403   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
404 }
405
406 TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) {
407   NotifierId notifier_id(NotifierId::APPLICATION, "app1");
408   ToggledNotificationBlocker blocker(message_center());
409
410   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
411       NOTIFICATION_TYPE_SIMPLE,
412       "id1",
413       UTF8ToUTF16("title"),
414       UTF8ToUTF16("message"),
415       gfx::Image() /* icon */,
416       base::string16() /* display_source */,
417       notifier_id,
418       RichNotificationData(),
419       NULL)));
420   EXPECT_EQ(1u, message_center()->GetPopupNotifications().size());
421   EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
422
423   // Create a notification during blocked. Still no popups.
424   blocker.SetNotificationsEnabled(false);
425   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
426       NOTIFICATION_TYPE_SIMPLE,
427       "id2",
428       UTF8ToUTF16("title"),
429       UTF8ToUTF16("message"),
430       gfx::Image() /* icon */,
431       base::string16() /* display_source */,
432       notifier_id,
433       RichNotificationData(),
434       NULL)));
435   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
436   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
437
438   // Unblock notifications, the id1 should appear as a popup.
439   blocker.SetNotificationsEnabled(true);
440   NotificationList::PopupNotifications popups =
441       message_center()->GetPopupNotifications();
442   EXPECT_EQ(1u, popups.size());
443   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
444   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
445 }
446
447 // Similar to other blocker cases but this test case allows |notifier_id2| even
448 // in blocked.
449 TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) {
450   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
451   NotifierId notifier_id2(NotifierId::APPLICATION, "app2");
452   PopupNotificationBlocker blocker(message_center(), notifier_id2);
453
454   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
455       NOTIFICATION_TYPE_SIMPLE,
456       "id1",
457       UTF8ToUTF16("title"),
458       UTF8ToUTF16("message"),
459       gfx::Image() /* icon */,
460       base::string16() /* display_source */,
461       notifier_id1,
462       RichNotificationData(),
463       NULL)));
464   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
465       NOTIFICATION_TYPE_SIMPLE,
466       "id2",
467       UTF8ToUTF16("title"),
468       UTF8ToUTF16("message"),
469       gfx::Image() /* icon */,
470       base::string16() /* display_source */,
471       notifier_id2,
472       RichNotificationData(),
473       NULL)));
474
475   // "id1" is closed but "id2" is still visible as a popup.
476   blocker.SetNotificationsEnabled(false);
477   NotificationList::PopupNotifications popups =
478       message_center()->GetPopupNotifications();
479   EXPECT_EQ(1u, popups.size());
480   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
481   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
482
483   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
484       NOTIFICATION_TYPE_SIMPLE,
485       "id3",
486       UTF8ToUTF16("title"),
487       UTF8ToUTF16("message"),
488       gfx::Image() /* icon */,
489       base::string16() /* display_source */,
490       notifier_id1,
491       RichNotificationData(),
492       NULL)));
493   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
494       NOTIFICATION_TYPE_SIMPLE,
495       "id4",
496       UTF8ToUTF16("title"),
497       UTF8ToUTF16("message"),
498       gfx::Image() /* icon */,
499       base::string16() /* display_source */,
500       notifier_id2,
501       RichNotificationData(),
502       NULL)));
503   popups = message_center()->GetPopupNotifications();
504   EXPECT_EQ(2u, popups.size());
505   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
506   EXPECT_TRUE(PopupNotificationsContain(popups, "id4"));
507   EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size());
508
509   blocker.SetNotificationsEnabled(true);
510   popups = message_center()->GetPopupNotifications();
511   EXPECT_EQ(3u, popups.size());
512   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
513   EXPECT_TRUE(PopupNotificationsContain(popups, "id3"));
514   EXPECT_TRUE(PopupNotificationsContain(popups, "id4"));
515   EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size());
516 }
517
518 // TotalNotificationBlocker suppresses showing notifications even from the list.
519 // This would provide the feature to 'separated' message centers per-profile for
520 // ChromeOS multi-login.
521 TEST_F(MessageCenterImplTest, TotalNotificationBlocker) {
522   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
523   NotifierId notifier_id2(NotifierId::APPLICATION, "app2");
524   TotalNotificationBlocker blocker(message_center(), notifier_id2);
525
526   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
527       NOTIFICATION_TYPE_SIMPLE,
528       "id1",
529       UTF8ToUTF16("title"),
530       UTF8ToUTF16("message"),
531       gfx::Image() /* icon */,
532       base::string16() /* display_source */,
533       notifier_id1,
534       RichNotificationData(),
535       NULL)));
536   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
537       NOTIFICATION_TYPE_SIMPLE,
538       "id2",
539       UTF8ToUTF16("title"),
540       UTF8ToUTF16("message"),
541       gfx::Image() /* icon */,
542       base::string16() /* display_source */,
543       notifier_id2,
544       RichNotificationData(),
545       NULL)));
546
547   // "id1" becomes invisible while "id2" is still visible.
548   blocker.SetNotificationsEnabled(false);
549   EXPECT_EQ(1u, message_center()->NotificationCount());
550   NotificationList::Notifications notifications =
551       message_center()->GetVisibleNotifications();
552   EXPECT_FALSE(NotificationsContain(notifications, "id1"));
553   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
554
555   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
556       NOTIFICATION_TYPE_SIMPLE,
557       "id3",
558       UTF8ToUTF16("title"),
559       UTF8ToUTF16("message"),
560       gfx::Image() /* icon */,
561       base::string16() /* display_source */,
562       notifier_id1,
563       RichNotificationData(),
564       NULL)));
565   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
566       NOTIFICATION_TYPE_SIMPLE,
567       "id4",
568       UTF8ToUTF16("title"),
569       UTF8ToUTF16("message"),
570       gfx::Image() /* icon */,
571       base::string16() /* display_source */,
572       notifier_id2,
573       RichNotificationData(),
574       NULL)));
575   EXPECT_EQ(2u, message_center()->NotificationCount());
576   notifications = message_center()->GetVisibleNotifications();
577   EXPECT_FALSE(NotificationsContain(notifications, "id1"));
578   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
579   EXPECT_FALSE(NotificationsContain(notifications, "id3"));
580   EXPECT_TRUE(NotificationsContain(notifications, "id4"));
581
582   blocker.SetNotificationsEnabled(true);
583   EXPECT_EQ(4u, message_center()->NotificationCount());
584   notifications = message_center()->GetVisibleNotifications();
585   EXPECT_TRUE(NotificationsContain(notifications, "id1"));
586   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
587   EXPECT_TRUE(NotificationsContain(notifications, "id3"));
588   EXPECT_TRUE(NotificationsContain(notifications, "id4"));
589
590   // RemoveAllVisibleNotifications should remove just visible notifications.
591   blocker.SetNotificationsEnabled(false);
592   message_center()->RemoveAllVisibleNotifications(false /* by_user */);
593   EXPECT_EQ(0u, message_center()->NotificationCount());
594   blocker.SetNotificationsEnabled(true);
595   EXPECT_EQ(2u, message_center()->NotificationCount());
596   notifications = message_center()->GetVisibleNotifications();
597   EXPECT_TRUE(NotificationsContain(notifications, "id1"));
598   EXPECT_FALSE(NotificationsContain(notifications, "id2"));
599   EXPECT_TRUE(NotificationsContain(notifications, "id3"));
600   EXPECT_FALSE(NotificationsContain(notifications, "id4"));
601
602   // And RemoveAllNotifications should remove all.
603   blocker.SetNotificationsEnabled(false);
604   message_center()->RemoveAllNotifications(false /* by_user */);
605   EXPECT_EQ(0u, message_center()->NotificationCount());
606 }
607
608 TEST_F(MessageCenterImplTest, QueueUpdatesWithCenterVisible) {
609   std::string id("id1");
610   std::string id2("id2");
611   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
612
613   // First, add and update a notification to ensure updates happen
614   // normally.
615   scoped_ptr<Notification> notification(CreateSimpleNotification(id));
616   message_center()->AddNotification(notification.Pass());
617   notification.reset(CreateSimpleNotification(id2));
618   message_center()->UpdateNotification(id, notification.Pass());
619   EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2));
620   EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
621
622   // Then open the message center.
623   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
624
625   // Then update a notification; nothing should have happened.
626   notification.reset(CreateSimpleNotification(id));
627   message_center()->UpdateNotification(id2, notification.Pass());
628   EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2));
629   EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
630
631   // Close the message center; then the update should have propagated.
632   message_center()->SetVisibility(VISIBILITY_TRANSIENT);
633   EXPECT_FALSE(message_center()->FindVisibleNotificationById(id2));
634   EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
635 }
636
637 TEST_F(MessageCenterImplTest, ComplexQueueing) {
638   std::string ids[5] = {"0", "1", "2", "3", "4p"};
639   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
640
641   scoped_ptr<Notification> notification;
642   // Add some notifications
643   int i = 0;
644   for (; i < 3; i++) {
645     notification.reset(CreateSimpleNotification(ids[i]));
646     message_center()->AddNotification(notification.Pass());
647   }
648   for (i = 0; i < 3; i++) {
649     EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[i]));
650   }
651   for (; i < 5; i++) {
652     EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[i]));
653   }
654
655   notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS));
656   message_center()->AddNotification(notification.Pass());
657
658   // Now start queueing.
659   // NL: ["0", "1", "2", "4p"]
660   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
661
662   // This should update notification "1" to have id "3".
663   notification.reset(CreateSimpleNotification(ids[3]));
664   message_center()->UpdateNotification(ids[1], notification.Pass());
665
666   notification.reset(CreateSimpleNotification(ids[4]));
667   message_center()->UpdateNotification(ids[4], notification.Pass());
668
669   notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS));
670   message_center()->UpdateNotification(ids[4], notification.Pass());
671
672   // This should update notification "3" to a new ID after we go TRANSIENT.
673   notification.reset(CreateSimpleNotification("New id"));
674   message_center()->UpdateNotification(ids[3], notification.Pass());
675
676   // This should create a new "3", that doesn't overwrite the update to 3
677   // before.
678   notification.reset(CreateSimpleNotification(ids[3]));
679   message_center()->AddNotification(notification.Pass());
680
681   // The NL should still be the same: ["0", "1", "2", "4p"]
682   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[0]));
683   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[1]));
684   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2]));
685   EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[3]));
686   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4]));
687   EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 4u);
688   message_center()->SetVisibility(VISIBILITY_TRANSIENT);
689
690   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[0]));
691   EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[1]));
692   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2]));
693   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[3]));
694   EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4]));
695   EXPECT_TRUE(message_center()->FindVisibleNotificationById("New id"));
696   EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 5u);
697 }
698
699 TEST_F(MessageCenterImplTest, QueuedDirectUpdates) {
700   std::string id("id1");
701   std::string id2("id2");
702   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
703
704   gfx::Size original_size(0, 0);
705   // Open the message center to prevent adding notifications
706   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
707
708   // Create new notification to be added to the queue; images all have the same
709   // original size.
710   scoped_ptr<Notification> notification(CreateSimpleNotification(id));
711
712   // Double-check that sizes all match.
713   const std::vector<ButtonInfo>& original_buttons = notification->buttons();
714   ASSERT_EQ(2u, original_buttons.size());
715
716   EXPECT_EQ(original_size, notification->icon().Size());
717   EXPECT_EQ(original_size, notification->image().Size());
718   EXPECT_EQ(original_size, original_buttons[0].icon.Size());
719   EXPECT_EQ(original_size, original_buttons[1].icon.Size());
720
721   message_center()->AddNotification(notification.Pass());
722
723   // The notification should be in the queue.
724   EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
725
726   // Now try setting the icon to a different size.
727   gfx::Size new_size(16, 16);
728   EXPECT_NE(original_size, new_size);
729
730   gfx::Canvas canvas(new_size, 1.0f, true);
731   canvas.DrawColor(SK_ColorBLUE);
732   gfx::Image testImage(gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep())));
733   message_center()->SetNotificationIcon(id, testImage);
734   message_center()->SetNotificationImage(id, testImage);
735   message_center()->SetNotificationButtonIcon(id, 0, testImage);
736   message_center()->SetNotificationButtonIcon(id, 1, testImage);
737
738   // The notification should be in the queue.
739   EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
740
741   // Close the message center; then the update should have propagated.
742   message_center()->SetVisibility(VISIBILITY_TRANSIENT);
743   // The notification should no longer be in the queue.
744   EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
745
746   Notification* mc_notification =
747       *(message_center()->GetVisibleNotifications().begin());
748   const std::vector<ButtonInfo>& buttons = mc_notification->buttons();
749   ASSERT_EQ(2u, buttons.size());
750
751   EXPECT_EQ(new_size, mc_notification->icon().Size());
752   EXPECT_EQ(new_size, mc_notification->image().Size());
753   EXPECT_EQ(new_size, buttons[0].icon.Size());
754   EXPECT_EQ(new_size, buttons[1].icon.Size());
755 }
756
757 TEST_F(MessageCenterImplTest, CachedUnreadCount) {
758   message_center()->AddNotification(
759       scoped_ptr<Notification>(CreateSimpleNotification("id1")));
760   message_center()->AddNotification(
761       scoped_ptr<Notification>(CreateSimpleNotification("id2")));
762   message_center()->AddNotification(
763       scoped_ptr<Notification>(CreateSimpleNotification("id3")));
764   ASSERT_EQ(3u, message_center()->UnreadNotificationCount());
765
766   // Mark 'displayed' on all notifications by using for-loop. This shouldn't
767   // recreate |notifications| inside of the loop.
768   const NotificationList::Notifications& notifications =
769       message_center()->GetVisibleNotifications();
770   for (NotificationList::Notifications::const_iterator iter =
771            notifications.begin(); iter != notifications.end(); ++iter) {
772     message_center()->DisplayedNotification(
773         (*iter)->id(), message_center::DISPLAY_SOURCE_MESSAGE_CENTER);
774   }
775   EXPECT_EQ(0u, message_center()->UnreadNotificationCount());
776
777   // Imitate the timeout, which recovers the unread count. Again, this shouldn't
778   // recreate |notifications| inside of the loop.
779   for (NotificationList::Notifications::const_iterator iter =
780            notifications.begin(); iter != notifications.end(); ++iter) {
781     message_center()->MarkSinglePopupAsShown((*iter)->id(), false);
782   }
783   EXPECT_EQ(3u, message_center()->UnreadNotificationCount());
784
785   // Opening the message center will reset the unread count.
786   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
787   EXPECT_EQ(0u, message_center()->UnreadNotificationCount());
788 }
789
790 TEST_F(MessageCenterImplTest, DisableNotificationsByNotifier) {
791   ASSERT_EQ(0u, message_center()->NotificationCount());
792   message_center()->AddNotification(
793       scoped_ptr<Notification>(
794           CreateSimpleNotificationWithNotifierId("id1-1", "app1")));
795   message_center()->AddNotification(
796       scoped_ptr<Notification>(
797           CreateSimpleNotificationWithNotifierId("id1-2", "app1")));
798   message_center()->AddNotification(
799       scoped_ptr<Notification>(
800           CreateSimpleNotificationWithNotifierId("id2-1", "app2")));
801   message_center()->AddNotification(
802       scoped_ptr<Notification>(
803           CreateSimpleNotificationWithNotifierId("id2-2", "app2")));
804   message_center()->AddNotification(
805       scoped_ptr<Notification>(
806           CreateSimpleNotificationWithNotifierId("id2-3", "app2")));
807   ASSERT_EQ(5u, message_center()->NotificationCount());
808
809   // Removing all of app1's notifications should only leave app2's.
810   message_center()->DisableNotificationsByNotifier(
811       NotifierId(NotifierId::APPLICATION, "app1"));
812   ASSERT_EQ(3u, message_center()->NotificationCount());
813
814   // Now we remove the remaining notifications.
815   message_center()->DisableNotificationsByNotifier(
816       NotifierId(NotifierId::APPLICATION, "app2"));
817   ASSERT_EQ(0u, message_center()->NotificationCount());
818 }
819
820 TEST_F(MessageCenterImplTest, NotifierEnabledChanged) {
821   ASSERT_EQ(0u, message_center()->NotificationCount());
822   message_center()->AddNotification(
823       scoped_ptr<Notification>(
824           CreateSimpleNotificationWithNotifierId("id1-1", "app1")));
825   message_center()->AddNotification(
826       scoped_ptr<Notification>(
827           CreateSimpleNotificationWithNotifierId("id1-2", "app1")));
828   message_center()->AddNotification(
829       scoped_ptr<Notification>(
830           CreateSimpleNotificationWithNotifierId("id1-3", "app1")));
831   message_center()->AddNotification(
832       scoped_ptr<Notification>(
833           CreateSimpleNotificationWithNotifierId("id2-1", "app2")));
834   message_center()->AddNotification(
835       scoped_ptr<Notification>(
836           CreateSimpleNotificationWithNotifierId("id2-2", "app2")));
837   message_center()->AddNotification(
838       scoped_ptr<Notification>(
839           CreateSimpleNotificationWithNotifierId("id2-3", "app2")));
840   message_center()->AddNotification(
841       scoped_ptr<Notification>(
842           CreateSimpleNotificationWithNotifierId("id2-4", "app2")));
843   message_center()->AddNotification(
844       scoped_ptr<Notification>(
845           CreateSimpleNotificationWithNotifierId("id2-5", "app2")));
846   ASSERT_EQ(8u, message_center()->NotificationCount());
847
848   // Enabling an extension should have no effect on the count.
849   notifier_settings_observer()->NotifierEnabledChanged(
850       NotifierId(NotifierId::APPLICATION, "app1"), true);
851   ASSERT_EQ(8u, message_center()->NotificationCount());
852
853   // Removing all of app2's notifications should only leave app1's.
854   notifier_settings_observer()->NotifierEnabledChanged(
855       NotifierId(NotifierId::APPLICATION, "app2"), false);
856   ASSERT_EQ(3u, message_center()->NotificationCount());
857
858   // Removal operations should be idempotent.
859   notifier_settings_observer()->NotifierEnabledChanged(
860       NotifierId(NotifierId::APPLICATION, "app2"), false);
861   ASSERT_EQ(3u, message_center()->NotificationCount());
862
863   // Now we remove the remaining notifications.
864   notifier_settings_observer()->NotifierEnabledChanged(
865       NotifierId(NotifierId::APPLICATION, "app1"), false);
866   ASSERT_EQ(0u, message_center()->NotificationCount());
867 }
868
869 }  // namespace internal
870 }  // namespace message_center