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"
9 #include "base/memory/scoped_vector.h"
10 #include "base/observer_list.h"
11 #include "ui/message_center/message_center_style.h"
12 #include "ui/message_center/message_center_types.h"
13 #include "ui/message_center/message_center_util.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 const std::string
& id() const { return id_
; }
63 ChangeType
type() const { return type_
; }
64 bool by_user() const { return by_user_
; }
65 void set_by_user(bool by_user
) { by_user_
= by_user
; }
66 const std::string
& notification_list_id() const {
67 return notification_list_id_
;
69 void set_notification_list_id(const std::string
& id
) {
70 notification_list_id_
= id
;
74 const ChangeType type_
;
75 const std::string id_
;
76 std::string notification_list_id_
;
78 scoped_ptr
<Notification
> notification_
;
80 DISALLOW_COPY_AND_ASSIGN(Change
);
86 // Called when the message center has appropriate visibility. Modifies
87 // |message_center| but does not retain it. This also causes the queue to
89 void ApplyChanges(MessageCenter
* message_center
);
91 // Causes a TYPE_ADD change to be added to the queue.
92 void AddNotification(scoped_ptr
<Notification
> notification
);
94 // Causes a TYPE_UPDATE change to be added to the queue.
95 void UpdateNotification(const std::string
& old_id
,
96 scoped_ptr
<Notification
> notification
);
98 // Causes a TYPE_DELETE change to be added to the queue.
99 void EraseNotification(const std::string
& id
, bool by_user
);
101 // Returns whether the queue matches an id. The id given will be matched
102 // against the ID of all changes post-update, not the id of the notification
103 // as it stands in the notification list.
104 bool Has(const std::string
& id
) const;
106 // Returns a Change that can be modified by the caller. ChangeQueue retains
107 // ownership of the Change; pointers should not be retained.
108 Notification
* GetLatestNotification(const std::string
& id
) const;
111 void Replace(const std::string
& id
, scoped_ptr
<Change
> change
);
113 ScopedVector
<Change
> changes_
;
116 ////////////////////////////////////////////////////////////////////////////////
119 struct ChangeFinder
{
120 explicit ChangeFinder(const std::string
& id
) : id(id
) {}
121 bool operator()(ChangeQueue::Change
* change
) { return change
->id() == id
; }
126 ////////////////////////////////////////////////////////////////////////////////
127 // ChangeQueue::Change
129 ChangeQueue::Change::Change(ChangeType type
,
130 const std::string
& id
,
131 scoped_ptr
<Notification
> notification
)
134 notification_list_id_(id
),
136 notification_(notification
.Pass()) {
137 DCHECK(!id
.empty() &&
138 (type
!= CHANGE_TYPE_DELETE
|| notification_
.get() == NULL
));
141 ChangeQueue::Change::~Change() {}
143 scoped_ptr
<Notification
> ChangeQueue::Change::PassNotification() {
144 return notification_
.Pass();
147 ////////////////////////////////////////////////////////////////////////////////
150 ChangeQueue::ChangeQueue() {}
152 ChangeQueue::~ChangeQueue() {}
154 void ChangeQueue::ApplyChanges(MessageCenter
* message_center
) {
155 // This method is re-entrant.
156 while (!changes_
.empty()) {
157 ScopedVector
<Change
>::iterator iter
= changes_
.begin();
158 scoped_ptr
<Change
> change(*iter
);
159 // TODO(dewittj): Replace changes_ with a deque.
160 changes_
.weak_erase(iter
);
161 // |message_center| is taking ownership of each element here.
162 switch (change
->type()) {
163 case CHANGE_TYPE_ADD
:
164 message_center
->AddNotification(change
->PassNotification());
166 case CHANGE_TYPE_UPDATE
:
167 message_center
->UpdateNotification(change
->notification_list_id(),
168 change
->PassNotification());
170 case CHANGE_TYPE_DELETE
:
171 message_center
->RemoveNotification(change
->notification_list_id(),
180 void ChangeQueue::AddNotification(scoped_ptr
<Notification
> notification
) {
181 std::string id
= notification
->id();
183 scoped_ptr
<Change
> change(
184 new Change(CHANGE_TYPE_ADD
, id
, notification
.Pass()));
185 Replace(id
, change
.Pass());
188 void ChangeQueue::UpdateNotification(const std::string
& old_id
,
189 scoped_ptr
<Notification
> notification
) {
190 std::string new_id
= notification
->id();
191 scoped_ptr
<Change
> change(
192 new Change(CHANGE_TYPE_UPDATE
, new_id
, notification
.Pass()));
193 Replace(old_id
, change
.Pass());
196 void ChangeQueue::EraseNotification(const std::string
& id
, bool by_user
) {
197 scoped_ptr
<Change
> change(
198 new Change(CHANGE_TYPE_DELETE
, id
, scoped_ptr
<Notification
>()));
199 change
->set_by_user(by_user
);
200 Replace(id
, change
.Pass());
203 bool ChangeQueue::Has(const std::string
& id
) const {
204 ScopedVector
<Change
>::const_iterator iter
=
205 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(id
));
206 return iter
!= changes_
.end();
209 Notification
* ChangeQueue::GetLatestNotification(const std::string
& id
) const {
210 ScopedVector
<Change
>::const_iterator iter
=
211 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(id
));
212 if (iter
== changes_
.end())
215 return (*iter
)->notification();
218 void ChangeQueue::Replace(const std::string
& changed_id
,
219 scoped_ptr
<Change
> new_change
) {
220 ScopedVector
<Change
>::iterator iter
=
221 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(changed_id
));
222 if (iter
!= changes_
.end()) {
223 Change
* old_change
= *iter
;
224 new_change
->set_notification_list_id(old_change
->notification_list_id());
225 changes_
.erase(iter
);
227 new_change
->set_notification_list_id(changed_id
);
230 changes_
.push_back(new_change
.release());
233 ////////////////////////////////////////////////////////////////////////////////
236 PopupTimer::PopupTimer(const std::string
& id
,
237 base::TimeDelta timeout
,
238 base::WeakPtr
<PopupTimersController
> controller
)
241 timer_controller_(controller
),
242 timer_(new base::OneShotTimer
<PopupTimersController
>) {}
244 PopupTimer::~PopupTimer() {
248 if (timer_
->IsRunning())
252 void PopupTimer::Start() {
253 if (timer_
->IsRunning())
255 base::TimeDelta timeout_to_close
=
256 timeout_
<= passed_
? base::TimeDelta() : timeout_
- passed_
;
257 start_time_
= base::Time::Now();
262 &PopupTimersController::TimerFinished
, timer_controller_
, id_
));
265 void PopupTimer::Pause() {
266 if (!timer_
.get() || !timer_
->IsRunning())
270 passed_
+= base::Time::Now() - start_time_
;
273 void PopupTimer::Reset() {
276 passed_
= base::TimeDelta();
279 ////////////////////////////////////////////////////////////////////////////////
280 // PopupTimersController
282 PopupTimersController::PopupTimersController(MessageCenter
* message_center
)
283 : message_center_(message_center
), popup_deleter_(&popup_timers_
) {
284 message_center_
->AddObserver(this);
287 PopupTimersController::~PopupTimersController() {
288 message_center_
->RemoveObserver(this);
291 void PopupTimersController::StartTimer(const std::string
& id
,
292 const base::TimeDelta
& timeout
) {
293 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
294 if (iter
!= popup_timers_
.end()) {
295 DCHECK(iter
->second
);
296 iter
->second
->Start();
300 PopupTimer
* timer
= new PopupTimer(id
, timeout
, AsWeakPtr());
303 popup_timers_
[id
] = timer
;
306 void PopupTimersController::StartAll() {
307 std::map
<std::string
, PopupTimer
*>::iterator iter
;
308 for (iter
= popup_timers_
.begin(); iter
!= popup_timers_
.end(); iter
++) {
309 iter
->second
->Start();
313 void PopupTimersController::ResetTimer(const std::string
& id
,
314 const base::TimeDelta
& timeout
) {
316 StartTimer(id
, timeout
);
319 void PopupTimersController::PauseTimer(const std::string
& id
) {
320 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
321 if (iter
== popup_timers_
.end())
323 iter
->second
->Pause();
326 void PopupTimersController::PauseAll() {
327 std::map
<std::string
, PopupTimer
*>::iterator iter
;
328 for (iter
= popup_timers_
.begin(); iter
!= popup_timers_
.end(); iter
++) {
329 iter
->second
->Pause();
333 void PopupTimersController::CancelTimer(const std::string
& id
) {
334 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
335 if (iter
== popup_timers_
.end())
338 PopupTimer
* timer
= iter
->second
;
341 popup_timers_
.erase(iter
);
344 void PopupTimersController::CancelAll() {
345 STLDeleteValues(&popup_timers_
);
346 popup_timers_
.clear();
349 void PopupTimersController::TimerFinished(const std::string
& id
) {
350 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
351 if (iter
== popup_timers_
.end())
355 message_center_
->MarkSinglePopupAsShown(id
, false);
358 void PopupTimersController::OnNotificationDisplayed(const std::string
& id
) {
359 OnNotificationUpdated(id
);
362 void PopupTimersController::OnNotificationUpdated(const std::string
& id
) {
363 NotificationList::PopupNotifications popup_notifications
=
364 message_center_
->GetPopupNotifications();
366 if (!popup_notifications
.size()) {
371 NotificationList::PopupNotifications::const_iterator iter
=
372 popup_notifications
.begin();
373 for (; iter
!= popup_notifications
.end(); iter
++) {
374 if ((*iter
)->id() == id
)
378 if (iter
== popup_notifications
.end() || (*iter
)->never_timeout()) {
383 // Start the timer if not yet.
384 if (popup_timers_
.find(id
) == popup_timers_
.end())
385 StartTimer(id
, GetTimeoutForPriority((*iter
)->priority()));
388 void PopupTimersController::OnNotificationRemoved(const std::string
& id
,
393 } // namespace internal
395 ////////////////////////////////////////////////////////////////////////////////
396 // MessageCenterImpl::NotificationCache
398 MessageCenterImpl::NotificationCache::NotificationCache()
401 MessageCenterImpl::NotificationCache::~NotificationCache() {}
403 void MessageCenterImpl::NotificationCache::Rebuild(
404 const NotificationList::Notifications
& notifications
) {
405 visible_notifications
= notifications
;
409 void MessageCenterImpl::NotificationCache::RecountUnread() {
411 for (NotificationList::Notifications::const_iterator iter
=
412 visible_notifications
.begin();
413 iter
!= visible_notifications
.end(); ++iter
) {
414 if (!(*iter
)->IsRead())
419 ////////////////////////////////////////////////////////////////////////////////
422 MessageCenterImpl::MessageCenterImpl()
424 popup_timers_controller_(new internal::PopupTimersController(this)),
425 settings_provider_(NULL
) {
426 notification_list_
.reset(new NotificationList());
427 notification_queue_
.reset(new internal::ChangeQueue());
430 MessageCenterImpl::~MessageCenterImpl() {}
432 void MessageCenterImpl::AddObserver(MessageCenterObserver
* observer
) {
433 observer_list_
.AddObserver(observer
);
436 void MessageCenterImpl::RemoveObserver(MessageCenterObserver
* observer
) {
437 observer_list_
.RemoveObserver(observer
);
440 void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker
* blocker
) {
441 if (std::find(blockers_
.begin(), blockers_
.end(), blocker
) !=
445 blocker
->AddObserver(this);
446 blockers_
.push_back(blocker
);
449 void MessageCenterImpl::RemoveNotificationBlocker(
450 NotificationBlocker
* blocker
) {
451 std::vector
<NotificationBlocker
*>::iterator iter
=
452 std::find(blockers_
.begin(), blockers_
.end(), blocker
);
453 if (iter
== blockers_
.end())
455 blocker
->RemoveObserver(this);
456 blockers_
.erase(iter
);
459 void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker
* blocker
) {
460 std::list
<std::string
> blocked_ids
;
461 NotificationList::PopupNotifications popups
=
462 notification_list_
->GetPopupNotifications(blockers_
, &blocked_ids
);
464 for (std::list
<std::string
>::const_iterator iter
= blocked_ids
.begin();
465 iter
!= blocked_ids
.end(); ++iter
) {
466 // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
467 // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
468 // calls NotificationList::MarkSinglePopupAsShown() and then updates the
469 // unread count, but the whole cache will be recreated below.
470 notification_list_
->MarkSinglePopupAsShown((*iter
), true);
471 FOR_EACH_OBSERVER(MessageCenterObserver
,
473 OnNotificationUpdated(*iter
));
475 notification_cache_
.Rebuild(
476 notification_list_
->GetVisibleNotifications(blockers_
));
477 FOR_EACH_OBSERVER(MessageCenterObserver
,
479 OnBlockingStateChanged(blocker
));
482 void MessageCenterImpl::SetVisibility(Visibility visibility
) {
483 std::set
<std::string
> updated_ids
;
484 notification_list_
->SetMessageCenterVisible(
485 (visibility
== VISIBILITY_MESSAGE_CENTER
), &updated_ids
);
486 notification_cache_
.RecountUnread();
488 for (std::set
<std::string
>::const_iterator iter
= updated_ids
.begin();
489 iter
!= updated_ids
.end();
492 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(*iter
));
495 if (visibility
== VISIBILITY_TRANSIENT
)
496 notification_queue_
->ApplyChanges(this);
498 FOR_EACH_OBSERVER(MessageCenterObserver
,
500 OnCenterVisibilityChanged(visibility
));
503 bool MessageCenterImpl::IsMessageCenterVisible() const {
504 return notification_list_
->is_message_center_visible();
507 size_t MessageCenterImpl::NotificationCount() const {
508 return notification_cache_
.visible_notifications
.size();
511 size_t MessageCenterImpl::UnreadNotificationCount() const {
512 return notification_cache_
.unread_count
;
515 bool MessageCenterImpl::HasPopupNotifications() const {
516 return !IsMessageCenterVisible() &&
517 notification_list_
->HasPopupNotifications(blockers_
);
520 bool MessageCenterImpl::HasNotification(const std::string
& id
) {
521 // This will return true if the notification with |id| is hidden by the
522 // ChromeOS multi-profile feature. This would be harmless for now because
523 // this check will be used from the UI, so the |id| for hidden profile won't
525 // TODO(mukai): fix this if necessary.
526 return notification_list_
->HasNotification(id
);
529 bool MessageCenterImpl::IsQuietMode() const {
530 return notification_list_
->quiet_mode();
533 bool MessageCenterImpl::HasClickedListener(const std::string
& id
) {
534 scoped_refptr
<NotificationDelegate
> delegate
=
535 notification_list_
->GetNotificationDelegate(id
);
536 return delegate
.get() && delegate
->HasClickedListener();
539 const NotificationList::Notifications
&
540 MessageCenterImpl::GetVisibleNotifications() {
541 return notification_cache_
.visible_notifications
;
544 NotificationList::PopupNotifications
545 MessageCenterImpl::GetPopupNotifications() {
546 return notification_list_
->GetPopupNotifications(blockers_
, NULL
);
549 //------------------------------------------------------------------------------
550 // Client code interface.
551 void MessageCenterImpl::AddNotification(scoped_ptr
<Notification
> notification
) {
552 DCHECK(notification
.get());
553 if (GetMessageCenterShowState() == MESSAGE_CENTER_SHOW_NEVER
) {
554 notification
->set_shown_as_popup(false);
555 notification
->set_never_timeout(true);
556 notification
->set_priority(message_center::DEFAULT_PRIORITY
);
559 for (size_t i
= 0; i
< blockers_
.size(); ++i
)
560 blockers_
[i
]->CheckState();
562 if (notification_list_
->is_message_center_visible()) {
563 notification_queue_
->AddNotification(notification
.Pass());
567 // Sometimes the notification can be added with the same id and the
568 // |notification_list| will replace the notification instead of adding new.
569 // This is essentially an update rather than addition.
570 const std::string
& id
= notification
->id();
571 bool already_exists
= notification_list_
->HasNotification(id
);
572 notification_list_
->AddNotification(notification
.Pass());
573 notification_cache_
.Rebuild(
574 notification_list_
->GetVisibleNotifications(blockers_
));
576 if (already_exists
) {
578 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
581 MessageCenterObserver
, observer_list_
, OnNotificationAdded(id
));
585 void MessageCenterImpl::UpdateNotification(
586 const std::string
& old_id
,
587 scoped_ptr
<Notification
> new_notification
) {
588 for (size_t i
= 0; i
< blockers_
.size(); ++i
)
589 blockers_
[i
]->CheckState();
591 if (notification_list_
->is_message_center_visible()) {
592 // We will allow notifications that are progress types (and stay progress
593 // types) to be updated even if the message center is open. There are 3
594 // requirements here:
595 // * Notification of type PROGRESS exists with same ID in the center
596 // * There are no queued updates for this notification (they imply a change
597 // that violates the PROGRESS invariant
598 // * The new notification is type PROGRESS.
599 // TODO(dewittj): Ensure this works when the ID is changed by the caller.
600 // This shouldn't be an issue in practice since only W3C notifications
601 // change the ID on update, and they don't have progress type notifications.
602 bool update_keeps_progress_type
=
603 new_notification
->type() == NOTIFICATION_TYPE_PROGRESS
&&
604 !notification_queue_
->Has(old_id
) &&
605 notification_list_
->HasNotificationOfType(old_id
,
606 NOTIFICATION_TYPE_PROGRESS
);
607 if (!update_keeps_progress_type
) {
608 // Updates are allowed only for progress notifications.
609 notification_queue_
->UpdateNotification(old_id
, new_notification
.Pass());
614 std::string new_id
= new_notification
->id();
615 notification_list_
->UpdateNotificationMessage(old_id
,
616 new_notification
.Pass());
617 notification_cache_
.Rebuild(
618 notification_list_
->GetVisibleNotifications(blockers_
));
619 if (old_id
== new_id
) {
621 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(new_id
));
623 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
624 OnNotificationRemoved(old_id
, false));
625 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
626 OnNotificationAdded(new_id
));
630 void MessageCenterImpl::RemoveNotification(const std::string
& id
,
632 if (!by_user
&& notification_list_
->is_message_center_visible()) {
633 notification_queue_
->EraseNotification(id
, by_user
);
637 if (!HasNotification(id
))
640 scoped_refptr
<NotificationDelegate
> delegate
=
641 notification_list_
->GetNotificationDelegate(id
);
643 delegate
->Close(by_user
);
645 // In many cases |id| is a reference to an existing notification instance
646 // but the instance can be destructed in RemoveNotification(). Hence
647 // copies the id explicitly here.
648 std::string
copied_id(id
);
649 notification_list_
->RemoveNotification(copied_id
);
650 notification_cache_
.Rebuild(
651 notification_list_
->GetVisibleNotifications(blockers_
));
652 FOR_EACH_OBSERVER(MessageCenterObserver
,
654 OnNotificationRemoved(copied_id
, by_user
));
657 void MessageCenterImpl::RemoveAllNotifications(bool by_user
) {
658 // Using not |blockers_| but an empty list since it wants to remove literally
659 // all notifications.
660 RemoveNotifications(by_user
, NotificationBlockers());
663 void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user
) {
664 RemoveNotifications(by_user
, blockers_
);
667 void MessageCenterImpl::RemoveNotifications(
669 const NotificationBlockers
& blockers
) {
670 const NotificationList::Notifications notifications
=
671 notification_list_
->GetVisibleNotifications(blockers
);
672 std::set
<std::string
> ids
;
673 for (NotificationList::Notifications::const_iterator iter
=
674 notifications
.begin(); iter
!= notifications
.end(); ++iter
) {
675 ids
.insert((*iter
)->id());
676 scoped_refptr
<NotificationDelegate
> delegate
= (*iter
)->delegate();
678 delegate
->Close(by_user
);
679 notification_list_
->RemoveNotification((*iter
)->id());
683 notification_cache_
.Rebuild(
684 notification_list_
->GetVisibleNotifications(blockers_
));
686 for (std::set
<std::string
>::const_iterator iter
= ids
.begin();
687 iter
!= ids
.end(); ++iter
) {
688 FOR_EACH_OBSERVER(MessageCenterObserver
,
690 OnNotificationRemoved(*iter
, by_user
));
694 void MessageCenterImpl::SetNotificationIcon(const std::string
& notification_id
,
695 const gfx::Image
& image
) {
696 bool updated
= false;
697 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
700 if (queue_notification
) {
701 queue_notification
->set_icon(image
);
704 updated
= notification_list_
->SetNotificationIcon(notification_id
, image
);
708 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
709 OnNotificationUpdated(notification_id
));
713 void MessageCenterImpl::SetNotificationImage(const std::string
& notification_id
,
714 const gfx::Image
& image
) {
715 bool updated
= false;
716 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
719 if (queue_notification
) {
720 queue_notification
->set_image(image
);
723 updated
= notification_list_
->SetNotificationImage(notification_id
, image
);
727 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
728 OnNotificationUpdated(notification_id
));
732 void MessageCenterImpl::SetNotificationButtonIcon(
733 const std::string
& notification_id
, int button_index
,
734 const gfx::Image
& image
) {
735 bool updated
= false;
736 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
739 if (queue_notification
) {
740 queue_notification
->SetButtonIcon(button_index
, image
);
743 updated
= notification_list_
->SetNotificationButtonIcon(
744 notification_id
, button_index
, image
);
748 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
749 OnNotificationUpdated(notification_id
));
753 void MessageCenterImpl::DisableNotificationsByNotifier(
754 const NotifierId
& notifier_id
) {
755 if (settings_provider_
) {
756 // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
757 Notifier
notifier(notifier_id
, base::string16(), true);
758 settings_provider_
->SetNotifierEnabled(notifier
, false);
761 NotificationList::Notifications notifications
=
762 notification_list_
->GetNotificationsByNotifierId(notifier_id
);
763 for (NotificationList::Notifications::const_iterator iter
=
764 notifications
.begin(); iter
!= notifications
.end();) {
765 std::string id
= (*iter
)->id();
767 RemoveNotification(id
, false);
769 if (!notifications
.empty()) {
770 notification_cache_
.Rebuild(
771 notification_list_
->GetVisibleNotifications(blockers_
));
775 void MessageCenterImpl::ClickOnNotification(const std::string
& id
) {
776 if (!HasNotification(id
))
778 if (HasPopupNotifications())
779 MarkSinglePopupAsShown(id
, true);
780 scoped_refptr
<NotificationDelegate
> delegate
=
781 notification_list_
->GetNotificationDelegate(id
);
785 MessageCenterObserver
, observer_list_
, OnNotificationClicked(id
));
788 void MessageCenterImpl::ClickOnNotificationButton(const std::string
& id
,
790 if (!HasNotification(id
))
792 if (HasPopupNotifications())
793 MarkSinglePopupAsShown(id
, true);
794 scoped_refptr
<NotificationDelegate
> delegate
=
795 notification_list_
->GetNotificationDelegate(id
);
797 delegate
->ButtonClick(button_index
);
799 MessageCenterObserver
, observer_list_
, OnNotificationButtonClicked(
803 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string
& id
,
804 bool mark_notification_as_read
) {
805 if (!HasNotification(id
))
807 notification_list_
->MarkSinglePopupAsShown(id
, mark_notification_as_read
);
808 notification_cache_
.RecountUnread();
810 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
813 void MessageCenterImpl::DisplayedNotification(const std::string
& id
) {
814 if (!HasNotification(id
))
817 if (HasPopupNotifications())
818 notification_list_
->MarkSinglePopupAsDisplayed(id
);
819 notification_cache_
.RecountUnread();
820 scoped_refptr
<NotificationDelegate
> delegate
=
821 notification_list_
->GetNotificationDelegate(id
);
825 MessageCenterObserver
, observer_list_
, OnNotificationDisplayed(id
));
828 void MessageCenterImpl::SetNotifierSettingsProvider(
829 NotifierSettingsProvider
* provider
) {
830 settings_provider_
= provider
;
833 NotifierSettingsProvider
* MessageCenterImpl::GetNotifierSettingsProvider() {
834 return settings_provider_
;
837 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode
) {
838 if (in_quiet_mode
!= notification_list_
->quiet_mode()) {
839 notification_list_
->SetQuietMode(in_quiet_mode
);
840 FOR_EACH_OBSERVER(MessageCenterObserver
,
842 OnQuietModeChanged(in_quiet_mode
));
844 quiet_mode_timer_
.reset();
847 void MessageCenterImpl::EnterQuietModeWithExpire(
848 const base::TimeDelta
& expires_in
) {
849 if (quiet_mode_timer_
.get()) {
850 // Note that the capital Reset() is the method to restart the timer, not
851 // scoped_ptr::reset().
852 quiet_mode_timer_
->Reset();
854 notification_list_
->SetQuietMode(true);
856 MessageCenterObserver
, observer_list_
, OnQuietModeChanged(true));
858 quiet_mode_timer_
.reset(new base::OneShotTimer
<MessageCenterImpl
>);
859 quiet_mode_timer_
->Start(
863 &MessageCenterImpl::SetQuietMode
, base::Unretained(this), false));
867 void MessageCenterImpl::RestartPopupTimers() {
868 if (popup_timers_controller_
.get())
869 popup_timers_controller_
->StartAll();
872 void MessageCenterImpl::PausePopupTimers() {
873 if (popup_timers_controller_
.get())
874 popup_timers_controller_
->PauseAll();
877 void MessageCenterImpl::DisableTimersForTest() {
878 popup_timers_controller_
.reset();
881 } // namespace message_center