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