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