1 // Copyright (c) 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.
5 #include "ui/message_center/message_center_impl.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/observer_list.h"
12 #include "ui/message_center/message_center_style.h"
13 #include "ui/message_center/message_center_types.h"
14 #include "ui/message_center/notification.h"
15 #include "ui/message_center/notification_blocker.h"
16 #include "ui/message_center/notification_list.h"
17 #include "ui/message_center/notification_types.h"
21 base::TimeDelta
GetTimeoutForPriority(int priority
) {
22 if (priority
> message_center::DEFAULT_PRIORITY
) {
23 return base::TimeDelta::FromSeconds(
24 message_center::kAutocloseHighPriorityDelaySeconds
);
26 return base::TimeDelta::FromSeconds(
27 message_center::kAutocloseDefaultDelaySeconds
);
32 namespace message_center
{
35 // ChangeQueue keeps track of all the changes that we need to make to the
36 // notification list once the visibility is set to VISIBILITY_TRANSIENT.
45 // Change represents an operation made on a notification. Since it contains
46 // the final state of the notification, we only keep the last change for a
47 // particular notification that is in the notification list around. There are
48 // two ids; |id_| is the newest notification id that has been assigned by an
49 // update, and |notification_list_id_| is the id of the notification it should
50 // be updating as it exists in the notification list.
53 Change(ChangeType type
,
54 const std::string
& id
,
55 scoped_ptr
<Notification
> notification
);
58 // Used to transfer ownership of the contained notification.
59 scoped_ptr
<Notification
> PassNotification();
61 Notification
* notification() const { return notification_
.get(); }
62 // Returns the post-update ID. It means:
63 // - ADD event: ID of the notification to be added.
64 // - UPDATE event: ID of the notification after the change. If the change
65 // doesn't update its ID, this value is same as |notification_list_id|.
66 // - DELETE event: ID of the notification to be deleted.
67 const std::string
& id() const { return id_
; }
68 ChangeType
type() const { return type_
; }
69 bool by_user() const { return by_user_
; }
70 void set_by_user(bool by_user
) { by_user_
= by_user
; }
71 // Returns the ID which is used in the notification list. In other word, it
72 // means the ID before the change.
73 const std::string
& notification_list_id() const {
74 return notification_list_id_
;
76 void set_type(const ChangeType new_type
) {
79 void ReplaceNotification(scoped_ptr
<Notification
> new_notification
);
84 std::string notification_list_id_
;
86 scoped_ptr
<Notification
> notification_
;
88 DISALLOW_COPY_AND_ASSIGN(Change
);
94 // Called when the message center has appropriate visibility. Modifies
95 // |message_center| but does not retain it. This also causes the queue to
97 void ApplyChanges(MessageCenterImpl
* message_center
);
99 // Applies only the changes of the given ID.
100 void ApplyChangesForId(MessageCenterImpl
* message_center
,
101 const std::string
& id
);
103 // Causes a TYPE_ADD change to be added to the queue.
104 void AddNotification(scoped_ptr
<Notification
> notification
);
106 // Causes a TYPE_UPDATE change to be added to the queue.
107 void UpdateNotification(const std::string
& old_id
,
108 scoped_ptr
<Notification
> notification
);
110 // Causes a TYPE_DELETE change to be added to the queue.
111 void EraseNotification(const std::string
& id
, bool by_user
);
113 // Returns whether the queue matches an id. The id given will be matched
114 // against the ID of all changes post-update, not the id of the notification
115 // as it stands in the notification list.
116 bool Has(const std::string
& id
) const;
118 // Returns a Change that can be modified by the caller. ChangeQueue retains
119 // ownership of the Change; pointers should not be retained.
120 Notification
* GetLatestNotification(const std::string
& id
) const;
123 void ApplyChangeInternal(MessageCenterImpl
* message_center
,
124 scoped_ptr
<Change
> change
);
126 ScopedVector
<Change
> changes_
;
128 DISALLOW_COPY_AND_ASSIGN(ChangeQueue
);
131 ////////////////////////////////////////////////////////////////////////////////
134 struct ChangeFinder
{
135 explicit ChangeFinder(const std::string
& id
) : id(id
) {}
136 bool operator()(ChangeQueue::Change
* change
) { return change
->id() == id
; }
141 ////////////////////////////////////////////////////////////////////////////////
142 // ChangeQueue::Change
144 ChangeQueue::Change::Change(ChangeType type
,
145 const std::string
& id
,
146 scoped_ptr
<Notification
> notification
)
148 notification_list_id_(id
),
150 notification_(notification
.Pass()) {
152 DCHECK(type
!= CHANGE_TYPE_DELETE
|| notification_
.get() == NULL
);
154 id_
= notification_
? notification_
->id() : notification_list_id_
;
157 ChangeQueue::Change::~Change() {}
159 scoped_ptr
<Notification
> ChangeQueue::Change::PassNotification() {
160 return notification_
.Pass();
163 void ChangeQueue::Change::ReplaceNotification(
164 scoped_ptr
<Notification
> new_notification
) {
165 id_
= new_notification
? new_notification
->id() : notification_list_id_
;
166 notification_
.swap(new_notification
);
169 ////////////////////////////////////////////////////////////////////////////////
172 ChangeQueue::ChangeQueue() {}
174 ChangeQueue::~ChangeQueue() {}
176 void ChangeQueue::ApplyChanges(MessageCenterImpl
* message_center
) {
177 // This method is re-entrant.
178 while (!changes_
.empty()) {
179 ScopedVector
<Change
>::iterator iter
= changes_
.begin();
180 scoped_ptr
<Change
> change(*iter
);
181 // TODO(dewittj): Replace changes_ with a deque.
182 changes_
.weak_erase(iter
);
183 ApplyChangeInternal(message_center
, change
.Pass());
187 void ChangeQueue::ApplyChangesForId(MessageCenterImpl
* message_center
,
188 const std::string
& id
) {
189 std::deque
<Change
*> changes_for_id
;
190 std::string interesting_id
= id
;
192 // Traverses the queue in reverse so shat we can track changes which change
193 // the notification's ID.
194 ScopedVector
<Change
>::iterator iter
= changes_
.end();
195 while (iter
!= changes_
.begin()) {
197 if (interesting_id
!= (*iter
)->id())
199 scoped_ptr
<Change
> change(*iter
);
201 interesting_id
= change
->notification_list_id();
203 iter
= changes_
.weak_erase(iter
);
204 changes_for_id
.push_back(change
.release());
207 while (!changes_for_id
.empty()) {
209 message_center
, scoped_ptr
<Change
>(changes_for_id
.back()));
210 changes_for_id
.pop_back();
214 void ChangeQueue::AddNotification(scoped_ptr
<Notification
> notification
) {
215 std::string id
= notification
->id();
217 new Change(CHANGE_TYPE_ADD
, id
, notification
.Pass()));
220 void ChangeQueue::UpdateNotification(const std::string
& old_id
,
221 scoped_ptr
<Notification
> notification
) {
222 ScopedVector
<Change
>::reverse_iterator iter
=
223 std::find_if(changes_
.rbegin(), changes_
.rend(), ChangeFinder(old_id
));
224 if (iter
== changes_
.rend()) {
226 new Change(CHANGE_TYPE_UPDATE
, old_id
, notification
.Pass()));
230 Change
* change
= *iter
;
231 switch (change
->type()) {
232 case CHANGE_TYPE_ADD
: {
233 std::string id
= notification
->id();
234 // Needs to add the change at the last, because if this change updates
235 // its ID, some previous changes may affect new ID.
236 // (eg. Add A, Update B->C, and This update A->B).
237 changes_
.erase(--(iter
.base()));
239 new Change(CHANGE_TYPE_ADD
, id
, notification
.Pass()));
242 case CHANGE_TYPE_UPDATE
:
243 if (notification
->id() == old_id
) {
244 // Safe to place the change at the previous place.
245 change
->ReplaceNotification(notification
.Pass());
246 } else if (change
->id() == change
->notification_list_id()) {
247 std::string id
= notification
->id();
248 // Safe to place the change at the last.
249 changes_
.erase(--(iter
.base()));
250 changes_
.push_back(new Change(
251 CHANGE_TYPE_ADD
, id
, notification
.Pass()));
253 // Complex case: gives up to optimize.
255 new Change(CHANGE_TYPE_UPDATE
, old_id
, notification
.Pass()));
258 case CHANGE_TYPE_DELETE
:
259 // DELETE -> UPDATE. Something is wrong. Treats the UPDATE as ADD.
261 new Change(CHANGE_TYPE_ADD
, old_id
, notification
.Pass()));
268 void ChangeQueue::EraseNotification(const std::string
& id
, bool by_user
) {
269 ScopedVector
<Change
>::reverse_iterator iter
=
270 std::find_if(changes_
.rbegin(), changes_
.rend(), ChangeFinder(id
));
271 if (iter
== changes_
.rend()) {
272 scoped_ptr
<Change
> change(new Change(CHANGE_TYPE_DELETE
, id
, nullptr));
273 change
->set_by_user(by_user
);
274 changes_
.push_back(change
.Pass());
278 Change
* change
= *iter
;
279 switch (change
->type()) {
280 case CHANGE_TYPE_ADD
:
281 // ADD -> DELETE. Just removes both.
282 changes_
.erase(--(iter
.base()));
284 case CHANGE_TYPE_UPDATE
:
285 // UPDATE -> DELETE. Changes the previous UPDATE to DELETE.
286 change
->set_type(CHANGE_TYPE_DELETE
);
287 change
->set_by_user(by_user
);
288 change
->ReplaceNotification(nullptr);
290 case CHANGE_TYPE_DELETE
:
291 // DELETE -> DELETE. Something is wrong. Combines them with overriding
292 // the |by_user| flag.
293 change
->set_by_user(!change
->by_user() && by_user
);
300 bool ChangeQueue::Has(const std::string
& id
) const {
301 ScopedVector
<Change
>::const_iterator iter
=
302 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(id
));
303 return iter
!= changes_
.end();
306 Notification
* ChangeQueue::GetLatestNotification(const std::string
& id
) const {
307 ScopedVector
<Change
>::const_iterator iter
=
308 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(id
));
309 if (iter
== changes_
.end())
312 return (*iter
)->notification();
315 void ChangeQueue::ApplyChangeInternal(MessageCenterImpl
* message_center
,
316 scoped_ptr
<Change
> change
) {
317 switch (change
->type()) {
318 case CHANGE_TYPE_ADD
:
319 message_center
->AddNotificationImmediately(change
->PassNotification());
321 case CHANGE_TYPE_UPDATE
:
322 message_center
->UpdateNotificationImmediately(
323 change
->notification_list_id(), change
->PassNotification());
325 case CHANGE_TYPE_DELETE
:
326 message_center
->RemoveNotificationImmediately(
327 change
->notification_list_id(), change
->by_user());
334 ////////////////////////////////////////////////////////////////////////////////
337 PopupTimer::PopupTimer(const std::string
& id
,
338 base::TimeDelta timeout
,
339 base::WeakPtr
<PopupTimersController
> controller
)
342 timer_controller_(controller
),
343 timer_(new base::OneShotTimer
<PopupTimersController
>) {}
345 PopupTimer::~PopupTimer() {
349 if (timer_
->IsRunning())
353 void PopupTimer::Start() {
354 if (timer_
->IsRunning())
356 base::TimeDelta timeout_to_close
=
357 timeout_
<= passed_
? base::TimeDelta() : timeout_
- passed_
;
358 start_time_
= base::Time::Now();
363 &PopupTimersController::TimerFinished
, timer_controller_
, id_
));
366 void PopupTimer::Pause() {
367 if (!timer_
|| !timer_
->IsRunning())
371 passed_
+= base::Time::Now() - start_time_
;
374 void PopupTimer::Reset() {
377 passed_
= base::TimeDelta();
380 ////////////////////////////////////////////////////////////////////////////////
381 // PopupTimersController
383 PopupTimersController::PopupTimersController(MessageCenter
* message_center
)
384 : message_center_(message_center
) {
385 message_center_
->AddObserver(this);
388 PopupTimersController::~PopupTimersController() {
389 message_center_
->RemoveObserver(this);
392 void PopupTimersController::StartTimer(const std::string
& id
,
393 const base::TimeDelta
& timeout
) {
394 PopupTimerCollection::const_iterator iter
= popup_timers_
.find(id
);
395 if (iter
!= popup_timers_
.end()) {
396 DCHECK(iter
->second
);
397 iter
->second
->Start();
401 scoped_ptr
<PopupTimer
> timer(new PopupTimer(id
, timeout
, AsWeakPtr()));
404 popup_timers_
.insert(id
, timer
.Pass());
407 void PopupTimersController::StartAll() {
408 for (auto& iter
: popup_timers_
)
409 iter
.second
->Start();
412 void PopupTimersController::ResetTimer(const std::string
& id
,
413 const base::TimeDelta
& timeout
) {
415 StartTimer(id
, timeout
);
418 void PopupTimersController::PauseTimer(const std::string
& id
) {
419 PopupTimerCollection::const_iterator iter
= popup_timers_
.find(id
);
420 if (iter
== popup_timers_
.end())
422 iter
->second
->Pause();
425 void PopupTimersController::PauseAll() {
426 for (auto& iter
: popup_timers_
)
427 iter
.second
->Pause();
430 void PopupTimersController::CancelTimer(const std::string
& id
) {
431 popup_timers_
.erase(id
);
434 void PopupTimersController::CancelAll() {
435 popup_timers_
.clear();
438 void PopupTimersController::TimerFinished(const std::string
& id
) {
439 if (!ContainsKey(popup_timers_
, id
))
443 message_center_
->MarkSinglePopupAsShown(id
, false);
446 void PopupTimersController::OnNotificationDisplayed(
447 const std::string
& id
,
448 const DisplaySource source
) {
449 OnNotificationUpdated(id
);
452 void PopupTimersController::OnNotificationUpdated(const std::string
& id
) {
453 NotificationList::PopupNotifications popup_notifications
=
454 message_center_
->GetPopupNotifications();
456 if (!popup_notifications
.size()) {
461 NotificationList::PopupNotifications::const_iterator iter
=
462 popup_notifications
.begin();
463 for (; iter
!= popup_notifications
.end(); ++iter
) {
464 if ((*iter
)->id() == id
)
468 if (iter
== popup_notifications
.end() || (*iter
)->never_timeout()) {
473 // Start the timer if not yet.
474 if (popup_timers_
.find(id
) == popup_timers_
.end())
475 StartTimer(id
, GetTimeoutForPriority((*iter
)->priority()));
478 void PopupTimersController::OnNotificationRemoved(const std::string
& id
,
483 } // namespace internal
485 ////////////////////////////////////////////////////////////////////////////////
486 // MessageCenterImpl::NotificationCache
488 MessageCenterImpl::NotificationCache::NotificationCache()
491 MessageCenterImpl::NotificationCache::~NotificationCache() {}
493 void MessageCenterImpl::NotificationCache::Rebuild(
494 const NotificationList::Notifications
& notifications
) {
495 visible_notifications
= notifications
;
499 void MessageCenterImpl::NotificationCache::RecountUnread() {
501 for (const auto& notification
: visible_notifications
) {
502 if (!notification
->IsRead())
507 ////////////////////////////////////////////////////////////////////////////////
510 MessageCenterImpl::MessageCenterImpl()
512 popup_timers_controller_(new internal::PopupTimersController(this)),
513 settings_provider_(NULL
) {
514 notification_list_
.reset(new NotificationList());
515 notification_queue_
.reset(new internal::ChangeQueue());
518 MessageCenterImpl::~MessageCenterImpl() {
519 SetNotifierSettingsProvider(NULL
);
522 void MessageCenterImpl::AddObserver(MessageCenterObserver
* observer
) {
523 observer_list_
.AddObserver(observer
);
526 void MessageCenterImpl::RemoveObserver(MessageCenterObserver
* observer
) {
527 observer_list_
.RemoveObserver(observer
);
530 void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker
* blocker
) {
531 if (std::find(blockers_
.begin(), blockers_
.end(), blocker
) !=
535 blocker
->AddObserver(this);
536 blockers_
.push_back(blocker
);
539 void MessageCenterImpl::RemoveNotificationBlocker(
540 NotificationBlocker
* blocker
) {
541 std::vector
<NotificationBlocker
*>::iterator iter
=
542 std::find(blockers_
.begin(), blockers_
.end(), blocker
);
543 if (iter
== blockers_
.end())
545 blocker
->RemoveObserver(this);
546 blockers_
.erase(iter
);
549 void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker
* blocker
) {
550 std::list
<std::string
> blocked_ids
;
551 NotificationList::PopupNotifications popups
=
552 notification_list_
->GetPopupNotifications(blockers_
, &blocked_ids
);
554 for (const auto& id
: blocked_ids
) {
555 // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
556 // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
557 // calls NotificationList::MarkSinglePopupAsShown() and then updates the
558 // unread count, but the whole cache will be recreated below.
559 notification_list_
->MarkSinglePopupAsShown(id
, true);
560 FOR_EACH_OBSERVER(MessageCenterObserver
,
562 OnNotificationUpdated(id
));
564 notification_cache_
.Rebuild(
565 notification_list_
->GetVisibleNotifications(blockers_
));
566 FOR_EACH_OBSERVER(MessageCenterObserver
,
568 OnBlockingStateChanged(blocker
));
571 void MessageCenterImpl::UpdateIconImage(
572 const NotifierId
& notifier_id
, const gfx::Image
& icon
) {}
574 void MessageCenterImpl::NotifierGroupChanged() {}
576 void MessageCenterImpl::NotifierEnabledChanged(
577 const NotifierId
& notifier_id
, bool enabled
) {
579 RemoveNotificationsForNotifierId(notifier_id
);
583 void MessageCenterImpl::SetVisibility(Visibility visibility
) {
584 std::set
<std::string
> updated_ids
;
585 notification_list_
->SetMessageCenterVisible(
586 (visibility
== VISIBILITY_MESSAGE_CENTER
), &updated_ids
);
587 notification_cache_
.RecountUnread();
589 for (const auto& id
: updated_ids
) {
591 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
594 if (visibility
== VISIBILITY_TRANSIENT
)
595 notification_queue_
->ApplyChanges(this);
597 FOR_EACH_OBSERVER(MessageCenterObserver
,
599 OnCenterVisibilityChanged(visibility
));
602 bool MessageCenterImpl::IsMessageCenterVisible() const {
603 return notification_list_
->is_message_center_visible();
606 size_t MessageCenterImpl::NotificationCount() const {
607 return notification_cache_
.visible_notifications
.size();
610 size_t MessageCenterImpl::UnreadNotificationCount() const {
611 return notification_cache_
.unread_count
;
614 bool MessageCenterImpl::HasPopupNotifications() const {
615 return !IsMessageCenterVisible() &&
616 notification_list_
->HasPopupNotifications(blockers_
);
619 bool MessageCenterImpl::IsQuietMode() const {
620 return notification_list_
->quiet_mode();
623 bool MessageCenterImpl::HasClickedListener(const std::string
& id
) {
624 scoped_refptr
<NotificationDelegate
> delegate
=
625 notification_list_
->GetNotificationDelegate(id
);
626 return delegate
.get() && delegate
->HasClickedListener();
629 message_center::Notification
* MessageCenterImpl::FindVisibleNotificationById(
630 const std::string
& id
) {
631 return notification_list_
->GetNotificationById(id
);
634 const NotificationList::Notifications
&
635 MessageCenterImpl::GetVisibleNotifications() {
636 return notification_cache_
.visible_notifications
;
639 NotificationList::PopupNotifications
640 MessageCenterImpl::GetPopupNotifications() {
641 return notification_list_
->GetPopupNotifications(blockers_
, NULL
);
644 void MessageCenterImpl::ForceNotificationFlush(const std::string
& id
) {
645 notification_queue_
->ApplyChangesForId(this, id
);
648 //------------------------------------------------------------------------------
649 // Client code interface.
650 void MessageCenterImpl::AddNotification(scoped_ptr
<Notification
> notification
) {
651 DCHECK(notification
);
652 const std::string id
= notification
->id();
653 for (size_t i
= 0; i
< blockers_
.size(); ++i
)
654 blockers_
[i
]->CheckState();
656 if (notification_list_
->is_message_center_visible()) {
657 notification_queue_
->AddNotification(notification
.Pass());
661 AddNotificationImmediately(notification
.Pass());
664 void MessageCenterImpl::AddNotificationImmediately(
665 scoped_ptr
<Notification
> notification
) {
666 const std::string id
= notification
->id();
668 // Sometimes the notification can be added with the same id and the
669 // |notification_list| will replace the notification instead of adding new.
670 // This is essentially an update rather than addition.
671 bool already_exists
= (notification_list_
->GetNotificationById(id
) != NULL
);
672 notification_list_
->AddNotification(notification
.Pass());
673 notification_cache_
.Rebuild(
674 notification_list_
->GetVisibleNotifications(blockers_
));
676 if (already_exists
) {
678 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
681 MessageCenterObserver
, observer_list_
, OnNotificationAdded(id
));
685 void MessageCenterImpl::UpdateNotification(
686 const std::string
& old_id
,
687 scoped_ptr
<Notification
> new_notification
) {
688 for (size_t i
= 0; i
< blockers_
.size(); ++i
)
689 blockers_
[i
]->CheckState();
691 if (notification_list_
->is_message_center_visible()) {
692 // We will allow notifications that are progress types (and stay progress
693 // types) to be updated even if the message center is open. There are 3
694 // requirements here:
695 // * Notification of type PROGRESS exists with same ID in the center
696 // * There are no queued updates for this notification (they imply a change
697 // that violates the PROGRESS invariant
698 // * The new notification is type PROGRESS.
699 // TODO(dewittj): Ensure this works when the ID is changed by the caller.
700 // This shouldn't be an issue in practice since only W3C notifications
701 // change the ID on update, and they don't have progress type notifications.
702 bool update_keeps_progress_type
=
703 new_notification
->type() == NOTIFICATION_TYPE_PROGRESS
&&
704 !notification_queue_
->Has(old_id
) &&
705 notification_list_
->HasNotificationOfType(old_id
,
706 NOTIFICATION_TYPE_PROGRESS
);
707 if (!update_keeps_progress_type
) {
708 // Updates are allowed only for progress notifications.
709 notification_queue_
->UpdateNotification(old_id
, new_notification
.Pass());
714 UpdateNotificationImmediately(old_id
, new_notification
.Pass());
717 void MessageCenterImpl::UpdateNotificationImmediately(
718 const std::string
& old_id
,
719 scoped_ptr
<Notification
> new_notification
) {
720 std::string new_id
= new_notification
->id();
721 notification_list_
->UpdateNotificationMessage(old_id
,
722 new_notification
.Pass());
723 notification_cache_
.Rebuild(
724 notification_list_
->GetVisibleNotifications(blockers_
));
725 if (old_id
== new_id
) {
727 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(new_id
));
729 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
730 OnNotificationRemoved(old_id
, false));
731 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
732 OnNotificationAdded(new_id
));
736 void MessageCenterImpl::RemoveNotification(const std::string
& id
,
738 if (!by_user
&& notification_list_
->is_message_center_visible()) {
739 notification_queue_
->EraseNotification(id
, by_user
);
743 RemoveNotificationImmediately(id
, by_user
);
746 void MessageCenterImpl::RemoveNotificationImmediately(
747 const std::string
& id
, bool by_user
) {
748 if (FindVisibleNotificationById(id
) == NULL
)
751 // In many cases |id| is a reference to an existing notification instance
752 // but the instance can be destructed in this method. Hence copies the id
754 std::string
copied_id(id
);
756 scoped_refptr
<NotificationDelegate
> delegate
=
757 notification_list_
->GetNotificationDelegate(copied_id
);
759 delegate
->Close(by_user
);
761 notification_list_
->RemoveNotification(copied_id
);
762 notification_cache_
.Rebuild(
763 notification_list_
->GetVisibleNotifications(blockers_
));
764 FOR_EACH_OBSERVER(MessageCenterObserver
,
766 OnNotificationRemoved(copied_id
, by_user
));
769 void MessageCenterImpl::RemoveNotificationsForNotifierId(
770 const NotifierId
& notifier_id
) {
771 NotificationList::Notifications notifications
=
772 notification_list_
->GetNotificationsByNotifierId(notifier_id
);
773 for (const auto& notification
: notifications
)
774 RemoveNotification(notification
->id(), false);
775 if (!notifications
.empty()) {
776 notification_cache_
.Rebuild(
777 notification_list_
->GetVisibleNotifications(blockers_
));
781 void MessageCenterImpl::RemoveAllNotifications(bool by_user
) {
782 // Using not |blockers_| but an empty list since it wants to remove literally
783 // all notifications.
784 RemoveNotifications(by_user
, NotificationBlockers());
787 void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user
) {
788 RemoveNotifications(by_user
, blockers_
);
791 void MessageCenterImpl::RemoveNotifications(
793 const NotificationBlockers
& blockers
) {
794 const NotificationList::Notifications notifications
=
795 notification_list_
->GetVisibleNotifications(blockers
);
796 std::set
<std::string
> ids
;
797 for (const auto& notification
: notifications
) {
798 ids
.insert(notification
->id());
799 scoped_refptr
<NotificationDelegate
> delegate
= notification
->delegate();
801 delegate
->Close(by_user
);
802 notification_list_
->RemoveNotification(notification
->id());
806 notification_cache_
.Rebuild(
807 notification_list_
->GetVisibleNotifications(blockers_
));
809 for (const auto& id
: ids
) {
810 FOR_EACH_OBSERVER(MessageCenterObserver
,
812 OnNotificationRemoved(id
, by_user
));
816 void MessageCenterImpl::SetNotificationIcon(const std::string
& notification_id
,
817 const gfx::Image
& image
) {
818 bool updated
= false;
819 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
822 if (queue_notification
) {
823 queue_notification
->set_icon(image
);
826 updated
= notification_list_
->SetNotificationIcon(notification_id
, image
);
830 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
831 OnNotificationUpdated(notification_id
));
835 void MessageCenterImpl::SetNotificationImage(const std::string
& notification_id
,
836 const gfx::Image
& image
) {
837 bool updated
= false;
838 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
841 if (queue_notification
) {
842 queue_notification
->set_image(image
);
845 updated
= notification_list_
->SetNotificationImage(notification_id
, image
);
849 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
850 OnNotificationUpdated(notification_id
));
854 void MessageCenterImpl::SetNotificationButtonIcon(
855 const std::string
& notification_id
, int button_index
,
856 const gfx::Image
& image
) {
857 bool updated
= false;
858 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
861 if (queue_notification
) {
862 queue_notification
->SetButtonIcon(button_index
, image
);
865 updated
= notification_list_
->SetNotificationButtonIcon(
866 notification_id
, button_index
, image
);
870 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
871 OnNotificationUpdated(notification_id
));
875 void MessageCenterImpl::DisableNotificationsByNotifier(
876 const NotifierId
& notifier_id
) {
877 if (settings_provider_
) {
878 // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
879 Notifier
notifier(notifier_id
, base::string16(), true);
880 settings_provider_
->SetNotifierEnabled(notifier
, false);
881 // The settings provider will call back to remove the notifications
882 // belonging to the notifier id.
884 RemoveNotificationsForNotifierId(notifier_id
);
888 void MessageCenterImpl::ClickOnNotification(const std::string
& id
) {
889 if (FindVisibleNotificationById(id
) == NULL
)
891 if (HasPopupNotifications())
892 MarkSinglePopupAsShown(id
, true);
893 scoped_refptr
<NotificationDelegate
> delegate
=
894 notification_list_
->GetNotificationDelegate(id
);
898 MessageCenterObserver
, observer_list_
, OnNotificationClicked(id
));
901 void MessageCenterImpl::ClickOnNotificationButton(const std::string
& id
,
903 if (FindVisibleNotificationById(id
) == NULL
)
905 if (HasPopupNotifications())
906 MarkSinglePopupAsShown(id
, true);
907 scoped_refptr
<NotificationDelegate
> delegate
=
908 notification_list_
->GetNotificationDelegate(id
);
910 delegate
->ButtonClick(button_index
);
912 MessageCenterObserver
, observer_list_
, OnNotificationButtonClicked(
916 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string
& id
,
917 bool mark_notification_as_read
) {
918 if (FindVisibleNotificationById(id
) == NULL
)
920 notification_list_
->MarkSinglePopupAsShown(id
, mark_notification_as_read
);
921 notification_cache_
.RecountUnread();
923 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
926 void MessageCenterImpl::DisplayedNotification(
927 const std::string
& id
,
928 const DisplaySource source
) {
929 if (FindVisibleNotificationById(id
) == NULL
)
932 if (HasPopupNotifications())
933 notification_list_
->MarkSinglePopupAsDisplayed(id
);
934 notification_cache_
.RecountUnread();
935 scoped_refptr
<NotificationDelegate
> delegate
=
936 notification_list_
->GetNotificationDelegate(id
);
940 MessageCenterObserver
,
942 OnNotificationDisplayed(id
, source
));
945 void MessageCenterImpl::SetNotifierSettingsProvider(
946 NotifierSettingsProvider
* provider
) {
947 if (settings_provider_
) {
948 settings_provider_
->RemoveObserver(this);
949 settings_provider_
= NULL
;
951 settings_provider_
= provider
;
952 if (settings_provider_
)
953 settings_provider_
->AddObserver(this);
956 NotifierSettingsProvider
* MessageCenterImpl::GetNotifierSettingsProvider() {
957 return settings_provider_
;
960 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode
) {
961 if (in_quiet_mode
!= notification_list_
->quiet_mode()) {
962 notification_list_
->SetQuietMode(in_quiet_mode
);
963 FOR_EACH_OBSERVER(MessageCenterObserver
,
965 OnQuietModeChanged(in_quiet_mode
));
967 quiet_mode_timer_
.reset();
970 void MessageCenterImpl::EnterQuietModeWithExpire(
971 const base::TimeDelta
& expires_in
) {
972 if (quiet_mode_timer_
) {
973 // Note that the capital Reset() is the method to restart the timer, not
974 // scoped_ptr::reset().
975 quiet_mode_timer_
->Reset();
977 notification_list_
->SetQuietMode(true);
979 MessageCenterObserver
, observer_list_
, OnQuietModeChanged(true));
981 quiet_mode_timer_
.reset(new base::OneShotTimer
<MessageCenterImpl
>);
982 quiet_mode_timer_
->Start(
986 &MessageCenterImpl::SetQuietMode
, base::Unretained(this), false));
990 void MessageCenterImpl::RestartPopupTimers() {
991 if (popup_timers_controller_
)
992 popup_timers_controller_
->StartAll();
995 void MessageCenterImpl::PausePopupTimers() {
996 if (popup_timers_controller_
)
997 popup_timers_controller_
->PauseAll();
1000 void MessageCenterImpl::DisableTimersForTest() {
1001 popup_timers_controller_
.reset();
1004 } // namespace message_center