• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/message_center/message_center_impl.h"
6 
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/size.h"
14 #include "ui/message_center/message_center.h"
15 #include "ui/message_center/message_center_types.h"
16 #include "ui/message_center/notification_blocker.h"
17 #include "ui/message_center/notification_types.h"
18 
19 namespace message_center {
20 namespace {
21 
22 class MessageCenterImplTest : public testing::Test,
23                               public MessageCenterObserver {
24  public:
MessageCenterImplTest()25   MessageCenterImplTest() {}
26 
SetUp()27   virtual void SetUp() OVERRIDE {
28     MessageCenter::Initialize();
29     message_center_ = MessageCenter::Get();
30     loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
31     run_loop_.reset(new base::RunLoop());
32     closure_ = run_loop_->QuitClosure();
33   }
34 
TearDown()35   virtual void TearDown() OVERRIDE {
36     run_loop_.reset();
37     loop_.reset();
38     message_center_ = NULL;
39     MessageCenter::Shutdown();
40   }
41 
message_center() const42   MessageCenter* message_center() const { return message_center_; }
run_loop() const43   base::RunLoop* run_loop() const { return run_loop_.get(); }
closure() const44   base::Closure closure() const { return closure_; }
45 
46  protected:
CreateSimpleNotification(const std::string & id)47   Notification* CreateSimpleNotification(const std::string& id) {
48     return CreateNotification(id, NOTIFICATION_TYPE_SIMPLE);
49   }
50 
CreateNotification(const std::string & id,message_center::NotificationType type)51   Notification* CreateNotification(const std::string& id,
52                                    message_center::NotificationType type) {
53     RichNotificationData optional_fields;
54     optional_fields.buttons.push_back(ButtonInfo(UTF8ToUTF16("foo")));
55     optional_fields.buttons.push_back(ButtonInfo(UTF8ToUTF16("foo")));
56     return new Notification(type,
57                             id,
58                             UTF8ToUTF16("title"),
59                             UTF8ToUTF16(id),
60                             gfx::Image() /* icon */,
61                             base::string16() /* display_source */,
62                             NotifierId(NotifierId::APPLICATION, "app1"),
63                             optional_fields,
64                             NULL);
65   }
66 
67  private:
68   MessageCenter* message_center_;
69   scoped_ptr<base::MessageLoop> loop_;
70   scoped_ptr<base::RunLoop> run_loop_;
71   base::Closure closure_;
72 
73   DISALLOW_COPY_AND_ASSIGN(MessageCenterImplTest);
74 };
75 
76 class ToggledNotificationBlocker : public NotificationBlocker {
77  public:
ToggledNotificationBlocker(MessageCenter * message_center)78   explicit ToggledNotificationBlocker(MessageCenter* message_center)
79       : NotificationBlocker(message_center),
80         notifications_enabled_(true) {}
~ToggledNotificationBlocker()81   virtual ~ToggledNotificationBlocker() {}
82 
SetNotificationsEnabled(bool enabled)83   void SetNotificationsEnabled(bool enabled) {
84     if (notifications_enabled_ != enabled) {
85       notifications_enabled_ = enabled;
86       NotifyBlockingStateChanged();
87     }
88   }
89 
90   // NotificationBlocker overrides:
ShouldShowNotificationAsPopup(const message_center::NotifierId & notifier_id) const91   virtual  bool ShouldShowNotificationAsPopup(
92       const message_center::NotifierId& notifier_id) const OVERRIDE {
93     return notifications_enabled_;
94   }
95 
96  private:
97   bool notifications_enabled_;
98 
99   DISALLOW_COPY_AND_ASSIGN(ToggledNotificationBlocker);
100 };
101 
102 class PopupNotificationBlocker : public ToggledNotificationBlocker {
103  public:
PopupNotificationBlocker(MessageCenter * message_center,const NotifierId & allowed_notifier)104   PopupNotificationBlocker(MessageCenter* message_center,
105                            const NotifierId& allowed_notifier)
106       : ToggledNotificationBlocker(message_center),
107         allowed_notifier_(allowed_notifier) {}
~PopupNotificationBlocker()108   virtual ~PopupNotificationBlocker() {}
109 
110   // NotificationBlocker overrides:
ShouldShowNotificationAsPopup(const NotifierId & notifier_id) const111   virtual bool ShouldShowNotificationAsPopup(
112       const NotifierId& notifier_id) const OVERRIDE {
113     return (notifier_id == allowed_notifier_) ||
114         ToggledNotificationBlocker::ShouldShowNotificationAsPopup(notifier_id);
115   }
116 
117  private:
118   NotifierId allowed_notifier_;
119 
120   DISALLOW_COPY_AND_ASSIGN(PopupNotificationBlocker);
121 };
122 
123 class TotalNotificationBlocker : public PopupNotificationBlocker {
124  public:
TotalNotificationBlocker(MessageCenter * message_center,const NotifierId & allowed_notifier)125   TotalNotificationBlocker(MessageCenter* message_center,
126                            const NotifierId& allowed_notifier)
127       : PopupNotificationBlocker(message_center, allowed_notifier) {}
~TotalNotificationBlocker()128   virtual ~TotalNotificationBlocker() {}
129 
130   // NotificationBlocker overrides:
ShouldShowNotification(const NotifierId & notifier_id) const131   virtual bool ShouldShowNotification(
132       const NotifierId& notifier_id) const OVERRIDE {
133     return ShouldShowNotificationAsPopup(notifier_id);
134   }
135 
136  private:
137   DISALLOW_COPY_AND_ASSIGN(TotalNotificationBlocker);
138 };
139 
PopupNotificationsContain(const NotificationList::PopupNotifications & popups,const std::string & id)140 bool PopupNotificationsContain(
141     const NotificationList::PopupNotifications& popups,
142     const std::string& id) {
143   for (NotificationList::PopupNotifications::const_iterator iter =
144            popups.begin(); iter != popups.end(); ++iter) {
145     if ((*iter)->id() == id)
146       return true;
147   }
148   return false;
149 }
150 
151 // Right now, MessageCenter::HasNotification() returns regardless of blockers.
NotificationsContain(const NotificationList::Notifications & notifications,const std::string & id)152 bool NotificationsContain(
153     const NotificationList::Notifications& notifications,
154     const std::string& id) {
155   for (NotificationList::Notifications::const_iterator iter =
156            notifications.begin(); iter != notifications.end(); ++iter) {
157     if ((*iter)->id() == id)
158       return true;
159   }
160   return false;
161 }
162 
163 }  // namespace
164 
165 namespace internal {
166 
167 class MockPopupTimersController : public PopupTimersController {
168  public:
MockPopupTimersController(MessageCenter * message_center,base::Closure quit_closure)169   MockPopupTimersController(MessageCenter* message_center,
170                             base::Closure quit_closure)
171       : PopupTimersController(message_center),
172         timer_finished_(false),
173         quit_closure_(quit_closure) {}
~MockPopupTimersController()174   virtual ~MockPopupTimersController() {}
175 
TimerFinished(const std::string & id)176   virtual void TimerFinished(const std::string& id) OVERRIDE {
177     base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
178     timer_finished_ = true;
179     last_id_ = id;
180   }
181 
timer_finished() const182   bool timer_finished() const { return timer_finished_; }
last_id() const183   const std::string& last_id() const { return last_id_; }
184 
185  private:
186   bool timer_finished_;
187   std::string last_id_;
188   base::Closure quit_closure_;
189 };
190 
TEST_F(MessageCenterImplTest,PopupTimersEmptyController)191 TEST_F(MessageCenterImplTest, PopupTimersEmptyController) {
192   scoped_ptr<PopupTimersController> popup_timers_controller =
193       make_scoped_ptr(new PopupTimersController(message_center()));
194 
195   // Test that all functions succed without any timers created.
196   popup_timers_controller->PauseAll();
197   popup_timers_controller->StartAll();
198   popup_timers_controller->CancelAll();
199   popup_timers_controller->TimerFinished("unknown");
200   popup_timers_controller->PauseTimer("unknown");
201   popup_timers_controller->CancelTimer("unknown");
202 }
203 
TEST_F(MessageCenterImplTest,PopupTimersControllerStartTimer)204 TEST_F(MessageCenterImplTest, PopupTimersControllerStartTimer) {
205   scoped_ptr<MockPopupTimersController> popup_timers_controller =
206       make_scoped_ptr(
207           new MockPopupTimersController(message_center(), closure()));
208   popup_timers_controller->StartTimer("test",
209                                       base::TimeDelta::FromMilliseconds(1));
210   run_loop()->Run();
211   EXPECT_TRUE(popup_timers_controller->timer_finished());
212 }
213 
TEST_F(MessageCenterImplTest,PopupTimersControllerPauseTimer)214 TEST_F(MessageCenterImplTest, PopupTimersControllerPauseTimer) {
215   scoped_ptr<MockPopupTimersController> popup_timers_controller =
216       make_scoped_ptr(
217           new MockPopupTimersController(message_center(), closure()));
218   popup_timers_controller->StartTimer("test",
219                                       base::TimeDelta::FromMilliseconds(1));
220   popup_timers_controller->PauseTimer("test");
221   run_loop()->RunUntilIdle();
222 
223   EXPECT_FALSE(popup_timers_controller->timer_finished());
224 }
225 
TEST_F(MessageCenterImplTest,PopupTimersControllerCancelTimer)226 TEST_F(MessageCenterImplTest, PopupTimersControllerCancelTimer) {
227   scoped_ptr<MockPopupTimersController> popup_timers_controller =
228       make_scoped_ptr(
229           new MockPopupTimersController(message_center(), closure()));
230   popup_timers_controller->StartTimer("test",
231                                       base::TimeDelta::FromMilliseconds(1));
232   popup_timers_controller->CancelTimer("test");
233   run_loop()->RunUntilIdle();
234 
235   EXPECT_FALSE(popup_timers_controller->timer_finished());
236 }
237 
TEST_F(MessageCenterImplTest,PopupTimersControllerPauseAllTimers)238 TEST_F(MessageCenterImplTest, PopupTimersControllerPauseAllTimers) {
239   scoped_ptr<MockPopupTimersController> popup_timers_controller =
240       make_scoped_ptr(
241           new MockPopupTimersController(message_center(), closure()));
242   popup_timers_controller->StartTimer("test",
243                                       base::TimeDelta::FromMilliseconds(1));
244   popup_timers_controller->PauseAll();
245   run_loop()->RunUntilIdle();
246 
247   EXPECT_FALSE(popup_timers_controller->timer_finished());
248 }
249 
TEST_F(MessageCenterImplTest,PopupTimersControllerStartAllTimers)250 TEST_F(MessageCenterImplTest, PopupTimersControllerStartAllTimers) {
251   scoped_ptr<MockPopupTimersController> popup_timers_controller =
252       make_scoped_ptr(
253           new MockPopupTimersController(message_center(), closure()));
254   popup_timers_controller->StartTimer("test",
255                                       base::TimeDelta::FromMilliseconds(1));
256   popup_timers_controller->PauseAll();
257   popup_timers_controller->StartAll();
258   run_loop()->Run();
259 
260   EXPECT_TRUE(popup_timers_controller->timer_finished());
261 }
262 
TEST_F(MessageCenterImplTest,PopupTimersControllerStartMultipleTimers)263 TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimers) {
264   scoped_ptr<MockPopupTimersController> popup_timers_controller =
265       make_scoped_ptr(
266           new MockPopupTimersController(message_center(), closure()));
267   popup_timers_controller->StartTimer("test",
268                                       base::TimeDelta::FromMilliseconds(5));
269   popup_timers_controller->StartTimer("test2",
270                                       base::TimeDelta::FromMilliseconds(1));
271   popup_timers_controller->StartTimer("test3",
272                                       base::TimeDelta::FromMilliseconds(3));
273   popup_timers_controller->PauseAll();
274   popup_timers_controller->StartAll();
275   run_loop()->Run();
276 
277   EXPECT_EQ(popup_timers_controller->last_id(), "test2");
278   EXPECT_TRUE(popup_timers_controller->timer_finished());
279 }
280 
TEST_F(MessageCenterImplTest,PopupTimersControllerStartMultipleTimersPause)281 TEST_F(MessageCenterImplTest, PopupTimersControllerStartMultipleTimersPause) {
282   scoped_ptr<MockPopupTimersController> popup_timers_controller =
283       make_scoped_ptr(
284           new MockPopupTimersController(message_center(), closure()));
285   popup_timers_controller->StartTimer("test",
286                                       base::TimeDelta::FromMilliseconds(5));
287   popup_timers_controller->StartTimer("test2",
288                                       base::TimeDelta::FromMilliseconds(1));
289   popup_timers_controller->StartTimer("test3",
290                                       base::TimeDelta::FromMilliseconds(3));
291   popup_timers_controller->PauseTimer("test2");
292 
293   run_loop()->Run();
294 
295   EXPECT_EQ(popup_timers_controller->last_id(), "test3");
296   EXPECT_TRUE(popup_timers_controller->timer_finished());
297 }
298 
TEST_F(MessageCenterImplTest,PopupTimersControllerResetTimer)299 TEST_F(MessageCenterImplTest, PopupTimersControllerResetTimer) {
300   scoped_ptr<MockPopupTimersController> popup_timers_controller =
301       make_scoped_ptr(
302           new MockPopupTimersController(message_center(), closure()));
303   popup_timers_controller->StartTimer("test",
304                                       base::TimeDelta::FromMilliseconds(5));
305   popup_timers_controller->StartTimer("test2",
306                                       base::TimeDelta::FromMilliseconds(1));
307   popup_timers_controller->StartTimer("test3",
308                                       base::TimeDelta::FromMilliseconds(3));
309   popup_timers_controller->PauseTimer("test2");
310   popup_timers_controller->ResetTimer("test",
311                                       base::TimeDelta::FromMilliseconds(2));
312 
313   run_loop()->Run();
314 
315   EXPECT_EQ(popup_timers_controller->last_id(), "test");
316   EXPECT_TRUE(popup_timers_controller->timer_finished());
317 }
318 
TEST_F(MessageCenterImplTest,NotificationBlocker)319 TEST_F(MessageCenterImplTest, NotificationBlocker) {
320   NotifierId notifier_id(NotifierId::APPLICATION, "app1");
321   // Multiple blockers to verify the case that one blocker blocks but another
322   // doesn't.
323   ToggledNotificationBlocker blocker1(message_center());
324   ToggledNotificationBlocker blocker2(message_center());
325 
326   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
327       NOTIFICATION_TYPE_SIMPLE,
328       "id1",
329       UTF8ToUTF16("title"),
330       UTF8ToUTF16("message"),
331       gfx::Image() /* icon */,
332       base::string16() /* display_source */,
333       notifier_id,
334       RichNotificationData(),
335       NULL)));
336   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
337       NOTIFICATION_TYPE_SIMPLE,
338       "id2",
339       UTF8ToUTF16("title"),
340       UTF8ToUTF16("message"),
341       gfx::Image() /* icon */,
342       base::string16() /* display_source */,
343       notifier_id,
344       RichNotificationData(),
345       NULL)));
346   EXPECT_EQ(2u, message_center()->GetPopupNotifications().size());
347   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
348 
349   // Block all notifications. All popups are gone and message center should be
350   // hidden.
351   blocker1.SetNotificationsEnabled(false);
352   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
353   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
354 
355   // Updates |blocker2| state, which doesn't affect the global state.
356   blocker2.SetNotificationsEnabled(false);
357   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
358   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
359 
360   blocker2.SetNotificationsEnabled(true);
361   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
362   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
363 
364   // If |blocker2| blocks, then unblocking blocker1 doesn't change the global
365   // state.
366   blocker2.SetNotificationsEnabled(false);
367   blocker1.SetNotificationsEnabled(true);
368   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
369   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
370 
371   // Unblock both blockers, which recovers the global state, but the popups
372   // aren't shown.
373   blocker2.SetNotificationsEnabled(true);
374   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
375   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
376 }
377 
TEST_F(MessageCenterImplTest,NotificationsDuringBlocked)378 TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) {
379   NotifierId notifier_id(NotifierId::APPLICATION, "app1");
380   ToggledNotificationBlocker blocker(message_center());
381 
382   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
383       NOTIFICATION_TYPE_SIMPLE,
384       "id1",
385       UTF8ToUTF16("title"),
386       UTF8ToUTF16("message"),
387       gfx::Image() /* icon */,
388       base::string16() /* display_source */,
389       notifier_id,
390       RichNotificationData(),
391       NULL)));
392   EXPECT_EQ(1u, message_center()->GetPopupNotifications().size());
393   EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
394 
395   // Create a notification during blocked. Still no popups.
396   blocker.SetNotificationsEnabled(false);
397   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
398       NOTIFICATION_TYPE_SIMPLE,
399       "id2",
400       UTF8ToUTF16("title"),
401       UTF8ToUTF16("message"),
402       gfx::Image() /* icon */,
403       base::string16() /* display_source */,
404       notifier_id,
405       RichNotificationData(),
406       NULL)));
407   EXPECT_TRUE(message_center()->GetPopupNotifications().empty());
408   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
409 
410   // Unblock notifications, the id1 should appear as a popup.
411   blocker.SetNotificationsEnabled(true);
412   NotificationList::PopupNotifications popups =
413       message_center()->GetPopupNotifications();
414   EXPECT_EQ(1u, popups.size());
415   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
416   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
417 }
418 
419 // Similar to other blocker cases but this test case allows |notifier_id2| even
420 // in blocked.
TEST_F(MessageCenterImplTest,NotificationBlockerAllowsPopups)421 TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) {
422   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
423   NotifierId notifier_id2(NotifierId::APPLICATION, "app2");
424   PopupNotificationBlocker blocker(message_center(), notifier_id2);
425 
426   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
427       NOTIFICATION_TYPE_SIMPLE,
428       "id1",
429       UTF8ToUTF16("title"),
430       UTF8ToUTF16("message"),
431       gfx::Image() /* icon */,
432       base::string16() /* display_source */,
433       notifier_id1,
434       RichNotificationData(),
435       NULL)));
436   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
437       NOTIFICATION_TYPE_SIMPLE,
438       "id2",
439       UTF8ToUTF16("title"),
440       UTF8ToUTF16("message"),
441       gfx::Image() /* icon */,
442       base::string16() /* display_source */,
443       notifier_id2,
444       RichNotificationData(),
445       NULL)));
446 
447   // "id1" is closed but "id2" is still visible as a popup.
448   blocker.SetNotificationsEnabled(false);
449   NotificationList::PopupNotifications popups =
450       message_center()->GetPopupNotifications();
451   EXPECT_EQ(1u, popups.size());
452   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
453   EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size());
454 
455   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
456       NOTIFICATION_TYPE_SIMPLE,
457       "id3",
458       UTF8ToUTF16("title"),
459       UTF8ToUTF16("message"),
460       gfx::Image() /* icon */,
461       base::string16() /* display_source */,
462       notifier_id1,
463       RichNotificationData(),
464       NULL)));
465   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
466       NOTIFICATION_TYPE_SIMPLE,
467       "id4",
468       UTF8ToUTF16("title"),
469       UTF8ToUTF16("message"),
470       gfx::Image() /* icon */,
471       base::string16() /* display_source */,
472       notifier_id2,
473       RichNotificationData(),
474       NULL)));
475   popups = message_center()->GetPopupNotifications();
476   EXPECT_EQ(2u, popups.size());
477   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
478   EXPECT_TRUE(PopupNotificationsContain(popups, "id4"));
479   EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size());
480 
481   blocker.SetNotificationsEnabled(true);
482   popups = message_center()->GetPopupNotifications();
483   EXPECT_EQ(3u, popups.size());
484   EXPECT_TRUE(PopupNotificationsContain(popups, "id2"));
485   EXPECT_TRUE(PopupNotificationsContain(popups, "id3"));
486   EXPECT_TRUE(PopupNotificationsContain(popups, "id4"));
487   EXPECT_EQ(4u, message_center()->GetVisibleNotifications().size());
488 }
489 
490 // TotalNotificationBlocker suppresses showing notifications even from the list.
491 // This would provide the feature to 'separated' message centers per-profile for
492 // ChromeOS multi-login.
TEST_F(MessageCenterImplTest,TotalNotificationBlocker)493 TEST_F(MessageCenterImplTest, TotalNotificationBlocker) {
494   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
495   NotifierId notifier_id2(NotifierId::APPLICATION, "app2");
496   TotalNotificationBlocker blocker(message_center(), notifier_id2);
497 
498   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
499       NOTIFICATION_TYPE_SIMPLE,
500       "id1",
501       UTF8ToUTF16("title"),
502       UTF8ToUTF16("message"),
503       gfx::Image() /* icon */,
504       base::string16() /* display_source */,
505       notifier_id1,
506       RichNotificationData(),
507       NULL)));
508   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
509       NOTIFICATION_TYPE_SIMPLE,
510       "id2",
511       UTF8ToUTF16("title"),
512       UTF8ToUTF16("message"),
513       gfx::Image() /* icon */,
514       base::string16() /* display_source */,
515       notifier_id2,
516       RichNotificationData(),
517       NULL)));
518 
519   // "id1" becomes invisible while "id2" is still visible.
520   blocker.SetNotificationsEnabled(false);
521   EXPECT_EQ(1u, message_center()->NotificationCount());
522   NotificationList::Notifications notifications =
523       message_center()->GetVisibleNotifications();
524   EXPECT_FALSE(NotificationsContain(notifications, "id1"));
525   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
526 
527   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
528       NOTIFICATION_TYPE_SIMPLE,
529       "id3",
530       UTF8ToUTF16("title"),
531       UTF8ToUTF16("message"),
532       gfx::Image() /* icon */,
533       base::string16() /* display_source */,
534       notifier_id1,
535       RichNotificationData(),
536       NULL)));
537   message_center()->AddNotification(scoped_ptr<Notification>(new Notification(
538       NOTIFICATION_TYPE_SIMPLE,
539       "id4",
540       UTF8ToUTF16("title"),
541       UTF8ToUTF16("message"),
542       gfx::Image() /* icon */,
543       base::string16() /* display_source */,
544       notifier_id2,
545       RichNotificationData(),
546       NULL)));
547   EXPECT_EQ(2u, message_center()->NotificationCount());
548   notifications = message_center()->GetVisibleNotifications();
549   EXPECT_FALSE(NotificationsContain(notifications, "id1"));
550   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
551   EXPECT_FALSE(NotificationsContain(notifications, "id3"));
552   EXPECT_TRUE(NotificationsContain(notifications, "id4"));
553 
554   blocker.SetNotificationsEnabled(true);
555   EXPECT_EQ(4u, message_center()->NotificationCount());
556   notifications = message_center()->GetVisibleNotifications();
557   EXPECT_TRUE(NotificationsContain(notifications, "id1"));
558   EXPECT_TRUE(NotificationsContain(notifications, "id2"));
559   EXPECT_TRUE(NotificationsContain(notifications, "id3"));
560   EXPECT_TRUE(NotificationsContain(notifications, "id4"));
561 
562   // RemoveAllVisibleNotifications should remove just visible notifications.
563   blocker.SetNotificationsEnabled(false);
564   message_center()->RemoveAllVisibleNotifications(false /* by_user */);
565   EXPECT_EQ(0u, message_center()->NotificationCount());
566   blocker.SetNotificationsEnabled(true);
567   EXPECT_EQ(2u, message_center()->NotificationCount());
568   notifications = message_center()->GetVisibleNotifications();
569   EXPECT_TRUE(NotificationsContain(notifications, "id1"));
570   EXPECT_FALSE(NotificationsContain(notifications, "id2"));
571   EXPECT_TRUE(NotificationsContain(notifications, "id3"));
572   EXPECT_FALSE(NotificationsContain(notifications, "id4"));
573 
574   // And RemoveAllNotifications should remove all.
575   blocker.SetNotificationsEnabled(false);
576   message_center()->RemoveAllNotifications(false /* by_user */);
577   EXPECT_EQ(0u, message_center()->NotificationCount());
578 }
579 
TEST_F(MessageCenterImplTest,QueueUpdatesWithCenterVisible)580 TEST_F(MessageCenterImplTest, QueueUpdatesWithCenterVisible) {
581   std::string id("id1");
582   std::string id2("id2");
583   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
584 
585   // First, add and update a notification to ensure updates happen
586   // normally.
587   scoped_ptr<Notification> notification(CreateSimpleNotification(id));
588   message_center()->AddNotification(notification.Pass());
589   notification.reset(CreateSimpleNotification(id2));
590   message_center()->UpdateNotification(id, notification.Pass());
591   EXPECT_TRUE(message_center()->HasNotification(id2));
592   EXPECT_FALSE(message_center()->HasNotification(id));
593 
594   // Then open the message center.
595   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
596 
597   // Then update a notification; nothing should have happened.
598   notification.reset(CreateSimpleNotification(id));
599   message_center()->UpdateNotification(id2, notification.Pass());
600   EXPECT_TRUE(message_center()->HasNotification(id2));
601   EXPECT_FALSE(message_center()->HasNotification(id));
602 
603   // Close the message center; then the update should have propagated.
604   message_center()->SetVisibility(VISIBILITY_TRANSIENT);
605   EXPECT_FALSE(message_center()->HasNotification(id2));
606   EXPECT_TRUE(message_center()->HasNotification(id));
607 }
608 
TEST_F(MessageCenterImplTest,ComplexQueueing)609 TEST_F(MessageCenterImplTest, ComplexQueueing) {
610   std::string ids[5] = {"0", "1", "2", "3", "4p"};
611   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
612 
613   scoped_ptr<Notification> notification;
614   // Add some notifications
615   int i = 0;
616   for (; i < 3; i++) {
617     notification.reset(CreateSimpleNotification(ids[i]));
618     message_center()->AddNotification(notification.Pass());
619   }
620   for (i = 0; i < 3; i++) {
621     EXPECT_TRUE(message_center()->HasNotification(ids[i]));
622   }
623   for (; i < 5; i++) {
624     EXPECT_FALSE(message_center()->HasNotification(ids[i]));
625   }
626 
627   notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS));
628   message_center()->AddNotification(notification.Pass());
629 
630   // Now start queueing.
631   // NL: ["0", "1", "2", "4p"]
632   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
633 
634   // This should update notification "1" to have id "3".
635   notification.reset(CreateSimpleNotification(ids[3]));
636   message_center()->UpdateNotification(ids[1], notification.Pass());
637 
638   notification.reset(CreateSimpleNotification(ids[4]));
639   message_center()->UpdateNotification(ids[4], notification.Pass());
640 
641   notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS));
642   message_center()->UpdateNotification(ids[4], notification.Pass());
643 
644   // This should update notification "3" to a new ID after we go TRANSIENT.
645   notification.reset(CreateSimpleNotification("New id"));
646   message_center()->UpdateNotification(ids[3], notification.Pass());
647 
648   // This should create a new "3", that doesn't overwrite the update to 3
649   // before.
650   notification.reset(CreateSimpleNotification(ids[3]));
651   message_center()->AddNotification(notification.Pass());
652 
653   // The NL should still be the same: ["0", "1", "2", "4p"]
654   EXPECT_TRUE(message_center()->HasNotification(ids[0]));
655   EXPECT_TRUE(message_center()->HasNotification(ids[1]));
656   EXPECT_TRUE(message_center()->HasNotification(ids[2]));
657   EXPECT_FALSE(message_center()->HasNotification(ids[3]));
658   EXPECT_TRUE(message_center()->HasNotification(ids[4]));
659   EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 4u);
660   message_center()->SetVisibility(VISIBILITY_TRANSIENT);
661 
662   EXPECT_TRUE(message_center()->HasNotification(ids[0]));
663   EXPECT_FALSE(message_center()->HasNotification(ids[1]));
664   EXPECT_TRUE(message_center()->HasNotification(ids[2]));
665   EXPECT_TRUE(message_center()->HasNotification(ids[3]));
666   EXPECT_TRUE(message_center()->HasNotification(ids[4]));
667   EXPECT_TRUE(message_center()->HasNotification("New id"));
668   EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 5u);
669 }
670 
TEST_F(MessageCenterImplTest,QueuedDirectUpdates)671 TEST_F(MessageCenterImplTest, QueuedDirectUpdates) {
672   std::string id("id1");
673   std::string id2("id2");
674   NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
675 
676   gfx::Size original_size(0, 0);
677   // Open the message center to prevent adding notifications
678   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
679 
680   // Create new notification to be added to the queue; images all have the same
681   // original size.
682   scoped_ptr<Notification> notification(CreateSimpleNotification(id));
683 
684   // Double-check that sizes all match.
685   const std::vector<ButtonInfo>& original_buttons = notification->buttons();
686   ASSERT_EQ(2u, original_buttons.size());
687 
688   EXPECT_EQ(original_size, notification->icon().Size());
689   EXPECT_EQ(original_size, notification->image().Size());
690   EXPECT_EQ(original_size, original_buttons[0].icon.Size());
691   EXPECT_EQ(original_size, original_buttons[1].icon.Size());
692 
693   message_center()->AddNotification(notification.Pass());
694 
695   // The notification should be in the queue.
696   EXPECT_FALSE(message_center()->HasNotification(id));
697 
698   // Now try setting the icon to a different size.
699   gfx::Size new_size(16, 16);
700   EXPECT_NE(original_size, new_size);
701 
702   gfx::Canvas canvas(new_size, 1.0f, true);
703   canvas.DrawColor(SK_ColorBLUE);
704   gfx::Image testImage(gfx::Image(gfx::ImageSkia(canvas.ExtractImageRep())));
705   message_center()->SetNotificationIcon(id, testImage);
706   message_center()->SetNotificationImage(id, testImage);
707   message_center()->SetNotificationButtonIcon(id, 0, testImage);
708   message_center()->SetNotificationButtonIcon(id, 1, testImage);
709 
710   // The notification should be in the queue.
711   EXPECT_FALSE(message_center()->HasNotification(id));
712 
713   // Close the message center; then the update should have propagated.
714   message_center()->SetVisibility(VISIBILITY_TRANSIENT);
715   // The notification should no longer be in the queue.
716   EXPECT_TRUE(message_center()->HasNotification(id));
717 
718   Notification* mc_notification =
719       *(message_center()->GetVisibleNotifications().begin());
720   const std::vector<ButtonInfo>& buttons = mc_notification->buttons();
721   ASSERT_EQ(2u, buttons.size());
722 
723   EXPECT_EQ(new_size, mc_notification->icon().Size());
724   EXPECT_EQ(new_size, mc_notification->image().Size());
725   EXPECT_EQ(new_size, buttons[0].icon.Size());
726   EXPECT_EQ(new_size, buttons[1].icon.Size());
727 }
728 
TEST_F(MessageCenterImplTest,CachedUnreadCount)729 TEST_F(MessageCenterImplTest, CachedUnreadCount) {
730   message_center()->AddNotification(
731       scoped_ptr<Notification>(CreateSimpleNotification("id1")));
732   message_center()->AddNotification(
733       scoped_ptr<Notification>(CreateSimpleNotification("id2")));
734   message_center()->AddNotification(
735       scoped_ptr<Notification>(CreateSimpleNotification("id3")));
736   ASSERT_EQ(3u, message_center()->UnreadNotificationCount());
737 
738   // Mark 'displayed' on all notifications by using for-loop. This shouldn't
739   // recreate |notifications| inside of the loop.
740   const NotificationList::Notifications& notifications =
741       message_center()->GetVisibleNotifications();
742   for (NotificationList::Notifications::const_iterator iter =
743            notifications.begin(); iter != notifications.end(); ++iter) {
744     message_center()->DisplayedNotification((*iter)->id());
745   }
746   EXPECT_EQ(0u, message_center()->UnreadNotificationCount());
747 
748   // Imitate the timeout, which recovers the unread count. Again, this shouldn't
749   // recreate |notifications| inside of the loop.
750   for (NotificationList::Notifications::const_iterator iter =
751            notifications.begin(); iter != notifications.end(); ++iter) {
752     message_center()->MarkSinglePopupAsShown((*iter)->id(), false);
753   }
754   EXPECT_EQ(3u, message_center()->UnreadNotificationCount());
755 
756   // Opening the message center will reset the unread count.
757   message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
758   EXPECT_EQ(0u, message_center()->UnreadNotificationCount());
759 }
760 
761 }  // namespace internal
762 }  // namespace message_center
763