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/notification.h"
14 #include "ui/message_center/notification_blocker.h"
15 #include "ui/message_center/notification_list.h"
16 #include "ui/message_center/notification_types.h"
20 base::TimeDelta
GetTimeoutForPriority(int priority
) {
21 if (priority
> message_center::DEFAULT_PRIORITY
) {
22 return base::TimeDelta::FromSeconds(
23 message_center::kAutocloseHighPriorityDelaySeconds
);
25 return base::TimeDelta::FromSeconds(
26 message_center::kAutocloseDefaultDelaySeconds
);
31 namespace message_center
{
34 // ChangeQueue keeps track of all the changes that we need to make to the
35 // notification list once the visibility is set to VISIBILITY_TRANSIENT.
44 // Change represents an operation made on a notification. Since it contains
45 // the final state of the notification, we only keep the last change for a
46 // particular notification that is in the notification list around. There are
47 // two ids; |id_| is the newest notification id that has been assigned by an
48 // update, and |notification_list_id_| is the id of the notification it should
49 // be updating as it exists in the notification list.
52 Change(ChangeType type
,
53 const std::string
& id
,
54 scoped_ptr
<Notification
> notification
);
57 // Used to transfer ownership of the contained notification.
58 scoped_ptr
<Notification
> PassNotification();
60 Notification
* notification() const { return notification_
.get(); }
61 const std::string
& id() const { return id_
; }
62 ChangeType
type() const { return type_
; }
63 bool by_user() const { return by_user_
; }
64 void set_by_user(bool by_user
) { by_user_
= by_user
; }
65 const std::string
& notification_list_id() const {
66 return notification_list_id_
;
68 void set_notification_list_id(const std::string
& id
) {
69 notification_list_id_
= id
;
73 const ChangeType type_
;
74 const std::string id_
;
75 std::string notification_list_id_
;
77 scoped_ptr
<Notification
> notification_
;
79 DISALLOW_COPY_AND_ASSIGN(Change
);
85 // Called when the message center has appropriate visibility. Modifies
86 // |message_center| but does not retain it. This also causes the queue to
88 void ApplyChanges(MessageCenter
* message_center
);
90 // Causes a TYPE_ADD change to be added to the queue.
91 void AddNotification(scoped_ptr
<Notification
> notification
);
93 // Causes a TYPE_UPDATE change to be added to the queue.
94 void UpdateNotification(const std::string
& old_id
,
95 scoped_ptr
<Notification
> notification
);
97 // Causes a TYPE_DELETE change to be added to the queue.
98 void EraseNotification(const std::string
& id
, bool by_user
);
100 // Returns whether the queue matches an id. The id given will be matched
101 // against the ID of all changes post-update, not the id of the notification
102 // as it stands in the notification list.
103 bool Has(const std::string
& id
) const;
105 // Returns a Change that can be modified by the caller. ChangeQueue retains
106 // ownership of the Change; pointers should not be retained.
107 Notification
* GetLatestNotification(const std::string
& id
) const;
110 void Replace(const std::string
& id
, scoped_ptr
<Change
> change
);
112 ScopedVector
<Change
> changes_
;
115 ////////////////////////////////////////////////////////////////////////////////
118 struct ChangeFinder
{
119 explicit ChangeFinder(const std::string
& id
) : id(id
) {}
120 bool operator()(ChangeQueue::Change
* change
) { return change
->id() == id
; }
125 ////////////////////////////////////////////////////////////////////////////////
126 // ChangeQueue::Change
128 ChangeQueue::Change::Change(ChangeType type
,
129 const std::string
& id
,
130 scoped_ptr
<Notification
> notification
)
133 notification_list_id_(id
),
135 notification_(notification
.Pass()) {
136 DCHECK(!id
.empty() &&
137 (type
!= CHANGE_TYPE_DELETE
|| notification_
.get() == NULL
));
140 ChangeQueue::Change::~Change() {}
142 scoped_ptr
<Notification
> ChangeQueue::Change::PassNotification() {
143 return notification_
.Pass();
146 ////////////////////////////////////////////////////////////////////////////////
149 ChangeQueue::ChangeQueue() {}
151 ChangeQueue::~ChangeQueue() {}
153 void ChangeQueue::ApplyChanges(MessageCenter
* message_center
) {
154 // This method is re-entrant.
155 while (!changes_
.empty()) {
156 ScopedVector
<Change
>::iterator iter
= changes_
.begin();
157 scoped_ptr
<Change
> change(*iter
);
158 // TODO(dewittj): Replace changes_ with a deque.
159 changes_
.weak_erase(iter
);
160 // |message_center| is taking ownership of each element here.
161 switch (change
->type()) {
162 case CHANGE_TYPE_ADD
:
163 message_center
->AddNotification(change
->PassNotification());
165 case CHANGE_TYPE_UPDATE
:
166 message_center
->UpdateNotification(change
->notification_list_id(),
167 change
->PassNotification());
169 case CHANGE_TYPE_DELETE
:
170 message_center
->RemoveNotification(change
->notification_list_id(),
179 void ChangeQueue::AddNotification(scoped_ptr
<Notification
> notification
) {
180 std::string id
= notification
->id();
181 scoped_ptr
<Change
> change(
182 new Change(CHANGE_TYPE_ADD
, id
, notification
.Pass()));
183 Replace(id
, change
.Pass());
186 void ChangeQueue::UpdateNotification(const std::string
& old_id
,
187 scoped_ptr
<Notification
> notification
) {
188 std::string new_id
= notification
->id();
189 scoped_ptr
<Change
> change(
190 new Change(CHANGE_TYPE_UPDATE
, new_id
, notification
.Pass()));
191 Replace(old_id
, change
.Pass());
194 void ChangeQueue::EraseNotification(const std::string
& id
, bool by_user
) {
195 scoped_ptr
<Change
> change(
196 new Change(CHANGE_TYPE_DELETE
, id
, scoped_ptr
<Notification
>()));
197 change
->set_by_user(by_user
);
198 Replace(id
, change
.Pass());
201 bool ChangeQueue::Has(const std::string
& id
) const {
202 ScopedVector
<Change
>::const_iterator iter
=
203 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(id
));
204 return iter
!= changes_
.end();
207 Notification
* ChangeQueue::GetLatestNotification(const std::string
& id
) const {
208 ScopedVector
<Change
>::const_iterator iter
=
209 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(id
));
210 if (iter
== changes_
.end())
213 return (*iter
)->notification();
216 void ChangeQueue::Replace(const std::string
& changed_id
,
217 scoped_ptr
<Change
> new_change
) {
218 ScopedVector
<Change
>::iterator iter
=
219 std::find_if(changes_
.begin(), changes_
.end(), ChangeFinder(changed_id
));
220 if (iter
!= changes_
.end()) {
221 Change
* old_change
= *iter
;
222 new_change
->set_notification_list_id(old_change
->notification_list_id());
223 changes_
.erase(iter
);
225 new_change
->set_notification_list_id(changed_id
);
228 changes_
.push_back(new_change
.release());
231 ////////////////////////////////////////////////////////////////////////////////
234 PopupTimer::PopupTimer(const std::string
& id
,
235 base::TimeDelta timeout
,
236 base::WeakPtr
<PopupTimersController
> controller
)
239 timer_controller_(controller
),
240 timer_(new base::OneShotTimer
<PopupTimersController
>) {}
242 PopupTimer::~PopupTimer() {
246 if (timer_
->IsRunning())
250 void PopupTimer::Start() {
251 if (timer_
->IsRunning())
253 base::TimeDelta timeout_to_close
=
254 timeout_
<= passed_
? base::TimeDelta() : timeout_
- passed_
;
255 start_time_
= base::Time::Now();
260 &PopupTimersController::TimerFinished
, timer_controller_
, id_
));
263 void PopupTimer::Pause() {
264 if (!timer_
.get() || !timer_
->IsRunning())
268 passed_
+= base::Time::Now() - start_time_
;
271 void PopupTimer::Reset() {
274 passed_
= base::TimeDelta();
277 ////////////////////////////////////////////////////////////////////////////////
278 // PopupTimersController
280 PopupTimersController::PopupTimersController(MessageCenter
* message_center
)
281 : message_center_(message_center
), popup_deleter_(&popup_timers_
) {
282 message_center_
->AddObserver(this);
285 PopupTimersController::~PopupTimersController() {
286 message_center_
->RemoveObserver(this);
289 void PopupTimersController::StartTimer(const std::string
& id
,
290 const base::TimeDelta
& timeout
) {
291 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
292 if (iter
!= popup_timers_
.end()) {
293 DCHECK(iter
->second
);
294 iter
->second
->Start();
298 PopupTimer
* timer
= new PopupTimer(id
, timeout
, AsWeakPtr());
301 popup_timers_
[id
] = timer
;
304 void PopupTimersController::StartAll() {
305 std::map
<std::string
, PopupTimer
*>::iterator iter
;
306 for (iter
= popup_timers_
.begin(); iter
!= popup_timers_
.end(); iter
++) {
307 iter
->second
->Start();
311 void PopupTimersController::ResetTimer(const std::string
& id
,
312 const base::TimeDelta
& timeout
) {
314 StartTimer(id
, timeout
);
317 void PopupTimersController::PauseTimer(const std::string
& id
) {
318 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
319 if (iter
== popup_timers_
.end())
321 iter
->second
->Pause();
324 void PopupTimersController::PauseAll() {
325 std::map
<std::string
, PopupTimer
*>::iterator iter
;
326 for (iter
= popup_timers_
.begin(); iter
!= popup_timers_
.end(); iter
++) {
327 iter
->second
->Pause();
331 void PopupTimersController::CancelTimer(const std::string
& id
) {
332 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
333 if (iter
== popup_timers_
.end())
336 PopupTimer
* timer
= iter
->second
;
339 popup_timers_
.erase(iter
);
342 void PopupTimersController::CancelAll() {
343 STLDeleteValues(&popup_timers_
);
344 popup_timers_
.clear();
347 void PopupTimersController::TimerFinished(const std::string
& id
) {
348 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
349 if (iter
== popup_timers_
.end())
353 message_center_
->MarkSinglePopupAsShown(id
, false);
356 void PopupTimersController::OnNotificationDisplayed(const std::string
& id
) {
357 OnNotificationUpdated(id
);
360 void PopupTimersController::OnNotificationUpdated(const std::string
& id
) {
361 NotificationList::PopupNotifications popup_notifications
=
362 message_center_
->GetPopupNotifications();
364 if (!popup_notifications
.size()) {
369 NotificationList::PopupNotifications::const_iterator iter
=
370 popup_notifications
.begin();
371 for (; iter
!= popup_notifications
.end(); iter
++) {
372 if ((*iter
)->id() == id
)
376 if (iter
== popup_notifications
.end() || (*iter
)->never_timeout()) {
381 // Start the timer if not yet.
382 if (popup_timers_
.find(id
) == popup_timers_
.end())
383 StartTimer(id
, GetTimeoutForPriority((*iter
)->priority()));
386 void PopupTimersController::OnNotificationRemoved(const std::string
& id
,
391 } // namespace internal
393 ////////////////////////////////////////////////////////////////////////////////
394 // MessageCenterImpl::NotificationCache
396 MessageCenterImpl::NotificationCache::NotificationCache()
399 MessageCenterImpl::NotificationCache::~NotificationCache() {}
401 void MessageCenterImpl::NotificationCache::Rebuild(
402 const NotificationList::Notifications
& notifications
) {
403 visible_notifications
= notifications
;
407 void MessageCenterImpl::NotificationCache::RecountUnread() {
409 for (NotificationList::Notifications::const_iterator iter
=
410 visible_notifications
.begin();
411 iter
!= visible_notifications
.end(); ++iter
) {
412 if (!(*iter
)->IsRead())
417 ////////////////////////////////////////////////////////////////////////////////
420 MessageCenterImpl::MessageCenterImpl()
422 popup_timers_controller_(new internal::PopupTimersController(this)),
423 settings_provider_(NULL
) {
424 notification_list_
.reset(new NotificationList());
425 notification_queue_
.reset(new internal::ChangeQueue());
428 MessageCenterImpl::~MessageCenterImpl() {}
430 void MessageCenterImpl::AddObserver(MessageCenterObserver
* observer
) {
431 observer_list_
.AddObserver(observer
);
434 void MessageCenterImpl::RemoveObserver(MessageCenterObserver
* observer
) {
435 observer_list_
.RemoveObserver(observer
);
438 void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker
* blocker
) {
439 if (std::find(blockers_
.begin(), blockers_
.end(), blocker
) !=
443 blocker
->AddObserver(this);
444 blockers_
.push_back(blocker
);
447 void MessageCenterImpl::RemoveNotificationBlocker(
448 NotificationBlocker
* blocker
) {
449 std::vector
<NotificationBlocker
*>::iterator iter
=
450 std::find(blockers_
.begin(), blockers_
.end(), blocker
);
451 if (iter
== blockers_
.end())
453 blocker
->RemoveObserver(this);
454 blockers_
.erase(iter
);
457 void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker
* blocker
) {
458 std::list
<std::string
> blocked_ids
;
459 NotificationList::PopupNotifications popups
=
460 notification_list_
->GetPopupNotifications(blockers_
, &blocked_ids
);
462 for (std::list
<std::string
>::const_iterator iter
= blocked_ids
.begin();
463 iter
!= blocked_ids
.end(); ++iter
) {
464 // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
465 // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
466 // calls NotificationList::MarkSinglePopupAsShown() and then updates the
467 // unread count, but the whole cache will be recreated below.
468 notification_list_
->MarkSinglePopupAsShown((*iter
), true);
469 FOR_EACH_OBSERVER(MessageCenterObserver
,
471 OnNotificationUpdated(*iter
));
473 notification_cache_
.Rebuild(
474 notification_list_
->GetVisibleNotifications(blockers_
));
475 FOR_EACH_OBSERVER(MessageCenterObserver
,
477 OnBlockingStateChanged(blocker
));
480 void MessageCenterImpl::SetVisibility(Visibility visibility
) {
481 std::set
<std::string
> updated_ids
;
482 notification_list_
->SetMessageCenterVisible(
483 (visibility
== VISIBILITY_MESSAGE_CENTER
), &updated_ids
);
484 notification_cache_
.RecountUnread();
486 for (std::set
<std::string
>::const_iterator iter
= updated_ids
.begin();
487 iter
!= updated_ids
.end();
490 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(*iter
));
493 if (visibility
== VISIBILITY_TRANSIENT
)
494 notification_queue_
->ApplyChanges(this);
496 FOR_EACH_OBSERVER(MessageCenterObserver
,
498 OnCenterVisibilityChanged(visibility
));
501 bool MessageCenterImpl::IsMessageCenterVisible() const {
502 return notification_list_
->is_message_center_visible();
505 size_t MessageCenterImpl::NotificationCount() const {
506 return notification_cache_
.visible_notifications
.size();
509 size_t MessageCenterImpl::UnreadNotificationCount() const {
510 return notification_cache_
.unread_count
;
513 bool MessageCenterImpl::HasPopupNotifications() const {
514 return !IsMessageCenterVisible() &&
515 notification_list_
->HasPopupNotifications(blockers_
);
518 bool MessageCenterImpl::HasNotification(const std::string
& id
) {
519 // This will return true if the notification with |id| is hidden by the
520 // ChromeOS multi-profile feature. This would be harmless for now because
521 // this check will be used from the UI, so the |id| for hidden profile won't
523 // TODO(mukai): fix this if necessary.
524 return notification_list_
->HasNotification(id
);
527 bool MessageCenterImpl::IsQuietMode() const {
528 return notification_list_
->quiet_mode();
531 bool MessageCenterImpl::HasClickedListener(const std::string
& id
) {
532 NotificationDelegate
* delegate
=
533 notification_list_
->GetNotificationDelegate(id
);
534 return delegate
&& delegate
->HasClickedListener();
537 const NotificationList::Notifications
&
538 MessageCenterImpl::GetVisibleNotifications() {
539 return notification_cache_
.visible_notifications
;
542 NotificationList::PopupNotifications
543 MessageCenterImpl::GetPopupNotifications() {
544 return notification_list_
->GetPopupNotifications(blockers_
, NULL
);
547 //------------------------------------------------------------------------------
548 // Client code interface.
549 void MessageCenterImpl::AddNotification(scoped_ptr
<Notification
> notification
) {
550 DCHECK(notification
.get());
552 for (size_t i
= 0; i
< blockers_
.size(); ++i
)
553 blockers_
[i
]->CheckState();
555 if (notification_list_
->is_message_center_visible()) {
556 notification_queue_
->AddNotification(notification
.Pass());
560 // Sometimes the notification can be added with the same id and the
561 // |notification_list| will replace the notification instead of adding new.
562 // This is essentially an update rather than addition.
563 const std::string
& id
= notification
->id();
564 bool already_exists
= notification_list_
->HasNotification(id
);
565 notification_list_
->AddNotification(notification
.Pass());
566 notification_cache_
.Rebuild(
567 notification_list_
->GetVisibleNotifications(blockers_
));
569 if (already_exists
) {
571 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
574 MessageCenterObserver
, observer_list_
, OnNotificationAdded(id
));
578 void MessageCenterImpl::UpdateNotification(
579 const std::string
& old_id
,
580 scoped_ptr
<Notification
> new_notification
) {
581 for (size_t i
= 0; i
< blockers_
.size(); ++i
)
582 blockers_
[i
]->CheckState();
584 if (notification_list_
->is_message_center_visible()) {
585 // We will allow notifications that are progress types (and stay progress
586 // types) to be updated even if the message center is open. There are 3
587 // requirements here:
588 // * Notification of type PROGRESS exists with same ID in the center
589 // * There are no queued updates for this notification (they imply a change
590 // that violates the PROGRESS invariant
591 // * The new notification is type PROGRESS.
592 // TODO(dewittj): Ensure this works when the ID is changed by the caller.
593 // This shouldn't be an issue in practice since only W3C notifications
594 // change the ID on update, and they don't have progress type notifications.
595 bool update_keeps_progress_type
=
596 new_notification
->type() == NOTIFICATION_TYPE_PROGRESS
&&
597 !notification_queue_
->Has(old_id
) &&
598 notification_list_
->HasNotificationOfType(old_id
,
599 NOTIFICATION_TYPE_PROGRESS
);
600 if (!update_keeps_progress_type
) {
601 // Updates are allowed only for progress notifications.
602 notification_queue_
->UpdateNotification(old_id
, new_notification
.Pass());
607 std::string new_id
= new_notification
->id();
608 notification_list_
->UpdateNotificationMessage(old_id
,
609 new_notification
.Pass());
610 notification_cache_
.Rebuild(
611 notification_list_
->GetVisibleNotifications(blockers_
));
612 if (old_id
== new_id
) {
614 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(new_id
));
616 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
617 OnNotificationRemoved(old_id
, false));
618 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
619 OnNotificationAdded(new_id
));
623 void MessageCenterImpl::RemoveNotification(const std::string
& id
,
625 if (!by_user
&& notification_list_
->is_message_center_visible()) {
626 notification_queue_
->EraseNotification(id
, by_user
);
630 if (!HasNotification(id
))
633 NotificationDelegate
* delegate
=
634 notification_list_
->GetNotificationDelegate(id
);
636 delegate
->Close(by_user
);
638 // In many cases |id| is a reference to an existing notification instance
639 // but the instance can be destructed in RemoveNotification(). Hence
640 // copies the id explicitly here.
641 std::string
copied_id(id
);
642 notification_list_
->RemoveNotification(copied_id
);
643 notification_cache_
.Rebuild(
644 notification_list_
->GetVisibleNotifications(blockers_
));
645 FOR_EACH_OBSERVER(MessageCenterObserver
,
647 OnNotificationRemoved(copied_id
, by_user
));
650 void MessageCenterImpl::RemoveAllNotifications(bool by_user
) {
651 // Using not |blockers_| but an empty list since it wants to remove literally
652 // all notifications.
653 RemoveNotifications(by_user
, NotificationBlockers());
656 void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user
) {
657 RemoveNotifications(by_user
, blockers_
);
660 void MessageCenterImpl::RemoveNotifications(
662 const NotificationBlockers
& blockers
) {
663 const NotificationList::Notifications notifications
=
664 notification_list_
->GetVisibleNotifications(blockers
);
665 std::set
<std::string
> ids
;
666 for (NotificationList::Notifications::const_iterator iter
=
667 notifications
.begin(); iter
!= notifications
.end(); ++iter
) {
668 ids
.insert((*iter
)->id());
669 NotificationDelegate
* delegate
= (*iter
)->delegate();
671 delegate
->Close(by_user
);
672 notification_list_
->RemoveNotification((*iter
)->id());
676 notification_cache_
.Rebuild(
677 notification_list_
->GetVisibleNotifications(blockers_
));
679 for (std::set
<std::string
>::const_iterator iter
= ids
.begin();
680 iter
!= ids
.end(); ++iter
) {
681 FOR_EACH_OBSERVER(MessageCenterObserver
,
683 OnNotificationRemoved(*iter
, by_user
));
687 void MessageCenterImpl::SetNotificationIcon(const std::string
& notification_id
,
688 const gfx::Image
& image
) {
689 bool updated
= false;
690 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
693 if (queue_notification
) {
694 queue_notification
->set_icon(image
);
697 updated
= notification_list_
->SetNotificationIcon(notification_id
, image
);
701 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
702 OnNotificationUpdated(notification_id
));
706 void MessageCenterImpl::SetNotificationImage(const std::string
& notification_id
,
707 const gfx::Image
& image
) {
708 bool updated
= false;
709 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
712 if (queue_notification
) {
713 queue_notification
->set_image(image
);
716 updated
= notification_list_
->SetNotificationImage(notification_id
, image
);
720 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
721 OnNotificationUpdated(notification_id
));
725 void MessageCenterImpl::SetNotificationButtonIcon(
726 const std::string
& notification_id
, int button_index
,
727 const gfx::Image
& image
) {
728 bool updated
= false;
729 Notification
* queue_notification
= notification_queue_
->GetLatestNotification(
732 if (queue_notification
) {
733 queue_notification
->SetButtonIcon(button_index
, image
);
736 updated
= notification_list_
->SetNotificationButtonIcon(
737 notification_id
, button_index
, image
);
741 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
742 OnNotificationUpdated(notification_id
));
746 void MessageCenterImpl::DisableNotificationsByNotifier(
747 const NotifierId
& notifier_id
) {
748 if (settings_provider_
) {
749 // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
750 Notifier
notifier(notifier_id
, base::string16(), true);
751 settings_provider_
->SetNotifierEnabled(notifier
, false);
754 NotificationList::Notifications notifications
=
755 notification_list_
->GetNotificationsByNotifierId(notifier_id
);
756 for (NotificationList::Notifications::const_iterator iter
=
757 notifications
.begin(); iter
!= notifications
.end();) {
758 std::string id
= (*iter
)->id();
760 RemoveNotification(id
, false);
762 if (!notifications
.empty()) {
763 notification_cache_
.Rebuild(
764 notification_list_
->GetVisibleNotifications(blockers_
));
768 void MessageCenterImpl::ExpandNotification(const std::string
& id
) {
769 if (!HasNotification(id
))
771 notification_list_
->MarkNotificationAsExpanded(id
);
772 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
773 OnNotificationUpdated(id
));
776 void MessageCenterImpl::ClickOnNotification(const std::string
& id
) {
777 if (!HasNotification(id
))
779 if (HasPopupNotifications())
780 MarkSinglePopupAsShown(id
, true);
781 NotificationDelegate
* delegate
=
782 notification_list_
->GetNotificationDelegate(id
);
786 MessageCenterObserver
, observer_list_
, OnNotificationClicked(id
));
789 void MessageCenterImpl::ClickOnNotificationButton(const std::string
& id
,
791 if (!HasNotification(id
))
793 if (HasPopupNotifications())
794 MarkSinglePopupAsShown(id
, true);
795 NotificationDelegate
* delegate
=
796 notification_list_
->GetNotificationDelegate(id
);
798 delegate
->ButtonClick(button_index
);
800 MessageCenterObserver
, observer_list_
, OnNotificationButtonClicked(
804 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string
& id
,
805 bool mark_notification_as_read
) {
806 if (!HasNotification(id
))
808 notification_list_
->MarkSinglePopupAsShown(id
, mark_notification_as_read
);
809 notification_cache_
.RecountUnread();
811 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
814 void MessageCenterImpl::DisplayedNotification(const std::string
& id
) {
815 if (!HasNotification(id
))
818 if (HasPopupNotifications())
819 notification_list_
->MarkSinglePopupAsDisplayed(id
);
820 notification_cache_
.RecountUnread();
821 NotificationDelegate
* delegate
=
822 notification_list_
->GetNotificationDelegate(id
);
826 MessageCenterObserver
, observer_list_
, OnNotificationDisplayed(id
));
829 void MessageCenterImpl::SetNotifierSettingsProvider(
830 NotifierSettingsProvider
* provider
) {
831 settings_provider_
= provider
;
834 NotifierSettingsProvider
* MessageCenterImpl::GetNotifierSettingsProvider() {
835 return settings_provider_
;
838 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode
) {
839 if (in_quiet_mode
!= notification_list_
->quiet_mode()) {
840 notification_list_
->SetQuietMode(in_quiet_mode
);
841 FOR_EACH_OBSERVER(MessageCenterObserver
,
843 OnQuietModeChanged(in_quiet_mode
));
845 quiet_mode_timer_
.reset();
848 void MessageCenterImpl::EnterQuietModeWithExpire(
849 const base::TimeDelta
& expires_in
) {
850 if (quiet_mode_timer_
.get()) {
851 // Note that the capital Reset() is the method to restart the timer, not
852 // scoped_ptr::reset().
853 quiet_mode_timer_
->Reset();
855 notification_list_
->SetQuietMode(true);
857 MessageCenterObserver
, observer_list_
, OnQuietModeChanged(true));
859 quiet_mode_timer_
.reset(new base::OneShotTimer
<MessageCenterImpl
>);
860 quiet_mode_timer_
->Start(
864 &MessageCenterImpl::SetQuietMode
, base::Unretained(this), false));
868 void MessageCenterImpl::RestartPopupTimers() {
869 if (popup_timers_controller_
.get())
870 popup_timers_controller_
->StartAll();
873 void MessageCenterImpl::PausePopupTimers() {
874 if (popup_timers_controller_
.get())
875 popup_timers_controller_
->PauseAll();
878 void MessageCenterImpl::DisableTimersForTest() {
879 popup_timers_controller_
.reset();
882 } // namespace message_center