Remove old about scheme URL constants.
[chromium-blink-merge.git] / ui / message_center / message_center_impl.cc
blob22c473d39d556d17aa3b92958ce561f76e193e30
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"
7 #include <algorithm>
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"
18 namespace {
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);
29 } // namespace
31 namespace message_center {
32 namespace internal {
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.
36 class ChangeQueue {
37 public:
38 enum ChangeType {
39 CHANGE_TYPE_ADD = 0,
40 CHANGE_TYPE_UPDATE,
41 CHANGE_TYPE_DELETE
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.
50 class Change {
51 public:
52 Change(ChangeType type,
53 const std::string& id,
54 scoped_ptr<Notification> notification);
55 ~Change();
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;
72 private:
73 const ChangeType type_;
74 const std::string id_;
75 std::string notification_list_id_;
76 bool by_user_;
77 scoped_ptr<Notification> notification_;
79 DISALLOW_COPY_AND_ASSIGN(Change);
82 ChangeQueue();
83 ~ChangeQueue();
85 // Called when the message center has appropriate visibility. Modifies
86 // |message_center| but does not retain it. This also causes the queue to
87 // empty itself.
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;
109 private:
110 void Replace(const std::string& id, scoped_ptr<Change> change);
112 ScopedVector<Change> changes_;
115 ////////////////////////////////////////////////////////////////////////////////
116 // ChangeFinder
118 struct ChangeFinder {
119 explicit ChangeFinder(const std::string& id) : id(id) {}
120 bool operator()(ChangeQueue::Change* change) { return change->id() == id; }
122 std::string id;
125 ////////////////////////////////////////////////////////////////////////////////
126 // ChangeQueue::Change
128 ChangeQueue::Change::Change(ChangeType type,
129 const std::string& id,
130 scoped_ptr<Notification> notification)
131 : type_(type),
132 id_(id),
133 notification_list_id_(id),
134 by_user_(false),
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 ////////////////////////////////////////////////////////////////////////////////
147 // ChangeQueue
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());
164 break;
165 case CHANGE_TYPE_UPDATE:
166 message_center->UpdateNotification(change->notification_list_id(),
167 change->PassNotification());
168 break;
169 case CHANGE_TYPE_DELETE:
170 message_center->RemoveNotification(change->notification_list_id(),
171 change->by_user());
172 break;
173 default:
174 NOTREACHED();
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())
211 return NULL;
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);
224 } else {
225 new_change->set_notification_list_id(changed_id);
228 changes_.push_back(new_change.release());
231 ////////////////////////////////////////////////////////////////////////////////
232 // PopupTimer
234 PopupTimer::PopupTimer(const std::string& id,
235 base::TimeDelta timeout,
236 base::WeakPtr<PopupTimersController> controller)
237 : id_(id),
238 timeout_(timeout),
239 timer_controller_(controller),
240 timer_(new base::OneShotTimer<PopupTimersController>) {}
242 PopupTimer::~PopupTimer() {
243 if (!timer_)
244 return;
246 if (timer_->IsRunning())
247 timer_->Stop();
250 void PopupTimer::Start() {
251 if (timer_->IsRunning())
252 return;
253 base::TimeDelta timeout_to_close =
254 timeout_ <= passed_ ? base::TimeDelta() : timeout_ - passed_;
255 start_time_ = base::Time::Now();
256 timer_->Start(
257 FROM_HERE,
258 timeout_to_close,
259 base::Bind(
260 &PopupTimersController::TimerFinished, timer_controller_, id_));
263 void PopupTimer::Pause() {
264 if (!timer_.get() || !timer_->IsRunning())
265 return;
267 timer_->Stop();
268 passed_ += base::Time::Now() - start_time_;
271 void PopupTimer::Reset() {
272 if (timer_)
273 timer_->Stop();
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();
295 return;
298 PopupTimer* timer = new PopupTimer(id, timeout, AsWeakPtr());
300 timer->Start();
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) {
313 CancelTimer(id);
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())
320 return;
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())
334 return;
336 PopupTimer* timer = iter->second;
337 delete timer;
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())
350 return;
352 CancelTimer(id);
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()) {
365 CancelAll();
366 return;
369 NotificationList::PopupNotifications::const_iterator iter =
370 popup_notifications.begin();
371 for (; iter != popup_notifications.end(); iter++) {
372 if ((*iter)->id() == id)
373 break;
376 if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
377 CancelTimer(id);
378 return;
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,
387 bool by_user) {
388 CancelTimer(id);
391 } // namespace internal
393 ////////////////////////////////////////////////////////////////////////////////
394 // MessageCenterImpl::NotificationCache
396 MessageCenterImpl::NotificationCache::NotificationCache()
397 : unread_count(0) {}
399 MessageCenterImpl::NotificationCache::~NotificationCache() {}
401 void MessageCenterImpl::NotificationCache::Rebuild(
402 const NotificationList::Notifications& notifications) {
403 visible_notifications = notifications;
404 RecountUnread();
407 void MessageCenterImpl::NotificationCache::RecountUnread() {
408 unread_count = 0;
409 for (NotificationList::Notifications::const_iterator iter =
410 visible_notifications.begin();
411 iter != visible_notifications.end(); ++iter) {
412 if (!(*iter)->IsRead())
413 ++unread_count;
417 ////////////////////////////////////////////////////////////////////////////////
418 // MessageCenterImpl
420 MessageCenterImpl::MessageCenterImpl()
421 : MessageCenter(),
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) !=
440 blockers_.end()) {
441 return;
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())
452 return;
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,
470 observer_list_,
471 OnNotificationUpdated(*iter));
473 notification_cache_.Rebuild(
474 notification_list_->GetVisibleNotifications(blockers_));
475 FOR_EACH_OBSERVER(MessageCenterObserver,
476 observer_list_,
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();
488 ++iter) {
489 FOR_EACH_OBSERVER(
490 MessageCenterObserver, observer_list_, OnNotificationUpdated(*iter));
493 if (visibility == VISIBILITY_TRANSIENT)
494 notification_queue_->ApplyChanges(this);
496 FOR_EACH_OBSERVER(MessageCenterObserver,
497 observer_list_,
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
522 // arrive here.
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());
557 return;
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) {
570 FOR_EACH_OBSERVER(
571 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
572 } else {
573 FOR_EACH_OBSERVER(
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());
603 return;
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) {
613 FOR_EACH_OBSERVER(
614 MessageCenterObserver, observer_list_, OnNotificationUpdated(new_id));
615 } else {
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,
624 bool by_user) {
625 if (!by_user && notification_list_->is_message_center_visible()) {
626 notification_queue_->EraseNotification(id, by_user);
627 return;
630 if (!HasNotification(id))
631 return;
633 NotificationDelegate* delegate =
634 notification_list_->GetNotificationDelegate(id);
635 if (delegate)
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,
646 observer_list_,
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(
661 bool by_user,
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();
670 if (delegate)
671 delegate->Close(by_user);
672 notification_list_->RemoveNotification((*iter)->id());
675 if (!ids.empty()) {
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,
682 observer_list_,
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(
691 notification_id);
693 if (queue_notification) {
694 queue_notification->set_icon(image);
695 updated = true;
696 } else {
697 updated = notification_list_->SetNotificationIcon(notification_id, image);
700 if (updated) {
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(
710 notification_id);
712 if (queue_notification) {
713 queue_notification->set_image(image);
714 updated = true;
715 } else {
716 updated = notification_list_->SetNotificationImage(notification_id, image);
719 if (updated) {
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(
730 notification_id);
732 if (queue_notification) {
733 queue_notification->SetButtonIcon(button_index, image);
734 updated = true;
735 } else {
736 updated = notification_list_->SetNotificationButtonIcon(
737 notification_id, button_index, image);
740 if (updated) {
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();
759 iter++;
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))
770 return;
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))
778 return;
779 if (HasPopupNotifications())
780 MarkSinglePopupAsShown(id, true);
781 NotificationDelegate* delegate =
782 notification_list_->GetNotificationDelegate(id);
783 if (delegate)
784 delegate->Click();
785 FOR_EACH_OBSERVER(
786 MessageCenterObserver, observer_list_, OnNotificationClicked(id));
789 void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
790 int button_index) {
791 if (!HasNotification(id))
792 return;
793 if (HasPopupNotifications())
794 MarkSinglePopupAsShown(id, true);
795 NotificationDelegate* delegate =
796 notification_list_->GetNotificationDelegate(id);
797 if (delegate)
798 delegate->ButtonClick(button_index);
799 FOR_EACH_OBSERVER(
800 MessageCenterObserver, observer_list_, OnNotificationButtonClicked(
801 id, button_index));
804 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id,
805 bool mark_notification_as_read) {
806 if (!HasNotification(id))
807 return;
808 notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read);
809 notification_cache_.RecountUnread();
810 FOR_EACH_OBSERVER(
811 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
814 void MessageCenterImpl::DisplayedNotification(const std::string& id) {
815 if (!HasNotification(id))
816 return;
818 if (HasPopupNotifications())
819 notification_list_->MarkSinglePopupAsDisplayed(id);
820 notification_cache_.RecountUnread();
821 NotificationDelegate* delegate =
822 notification_list_->GetNotificationDelegate(id);
823 if (delegate)
824 delegate->Display();
825 FOR_EACH_OBSERVER(
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,
842 observer_list_,
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();
854 } else {
855 notification_list_->SetQuietMode(true);
856 FOR_EACH_OBSERVER(
857 MessageCenterObserver, observer_list_, OnQuietModeChanged(true));
859 quiet_mode_timer_.reset(new base::OneShotTimer<MessageCenterImpl>);
860 quiet_mode_timer_->Start(
861 FROM_HERE,
862 expires_in,
863 base::Bind(
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