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