Fix search results being clipped in app list.
[chromium-blink-merge.git] / ui / message_center / message_center_impl.cc
blobcb2f812367f9bf3443f7b37b561cf18ea19bcb02
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_;
114 DISALLOW_COPY_AND_ASSIGN(ChangeQueue);
117 ////////////////////////////////////////////////////////////////////////////////
118 // ChangeFinder
120 struct ChangeFinder {
121 explicit ChangeFinder(const std::string& id) : id(id) {}
122 bool operator()(ChangeQueue::Change* change) { return change->id() == id; }
124 std::string id;
127 ////////////////////////////////////////////////////////////////////////////////
128 // ChangeQueue::Change
130 ChangeQueue::Change::Change(ChangeType type,
131 const std::string& id,
132 scoped_ptr<Notification> notification)
133 : type_(type),
134 id_(id),
135 notification_list_id_(id),
136 by_user_(false),
137 notification_(notification.Pass()) {
138 DCHECK(!id.empty());
139 DCHECK(type != CHANGE_TYPE_DELETE || notification_.get() == NULL);
142 ChangeQueue::Change::~Change() {}
144 scoped_ptr<Notification> ChangeQueue::Change::PassNotification() {
145 return notification_.Pass();
148 ////////////////////////////////////////////////////////////////////////////////
149 // ChangeQueue
151 ChangeQueue::ChangeQueue() {}
153 ChangeQueue::~ChangeQueue() {}
155 void ChangeQueue::ApplyChanges(MessageCenter* message_center) {
156 // This method is re-entrant.
157 while (!changes_.empty()) {
158 ScopedVector<Change>::iterator iter = changes_.begin();
159 scoped_ptr<Change> change(*iter);
160 // TODO(dewittj): Replace changes_ with a deque.
161 changes_.weak_erase(iter);
162 // |message_center| is taking ownership of each element here.
163 switch (change->type()) {
164 case CHANGE_TYPE_ADD:
165 message_center->AddNotification(change->PassNotification());
166 break;
167 case CHANGE_TYPE_UPDATE:
168 message_center->UpdateNotification(change->notification_list_id(),
169 change->PassNotification());
170 break;
171 case CHANGE_TYPE_DELETE:
172 message_center->RemoveNotification(change->notification_list_id(),
173 change->by_user());
174 break;
175 default:
176 NOTREACHED();
181 void ChangeQueue::AddNotification(scoped_ptr<Notification> notification) {
182 std::string id = notification->id();
184 scoped_ptr<Change> change(
185 new Change(CHANGE_TYPE_ADD, id, notification.Pass()));
186 Replace(id, change.Pass());
189 void ChangeQueue::UpdateNotification(const std::string& old_id,
190 scoped_ptr<Notification> notification) {
191 std::string new_id = notification->id();
192 scoped_ptr<Change> change(
193 new Change(CHANGE_TYPE_UPDATE, new_id, notification.Pass()));
194 Replace(old_id, change.Pass());
197 void ChangeQueue::EraseNotification(const std::string& id, bool by_user) {
198 scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr));
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())
213 return NULL;
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);
226 } else {
227 new_change->set_notification_list_id(changed_id);
230 changes_.push_back(new_change.release());
233 ////////////////////////////////////////////////////////////////////////////////
234 // PopupTimer
236 PopupTimer::PopupTimer(const std::string& id,
237 base::TimeDelta timeout,
238 base::WeakPtr<PopupTimersController> controller)
239 : id_(id),
240 timeout_(timeout),
241 timer_controller_(controller),
242 timer_(new base::OneShotTimer<PopupTimersController>) {}
244 PopupTimer::~PopupTimer() {
245 if (!timer_)
246 return;
248 if (timer_->IsRunning())
249 timer_->Stop();
252 void PopupTimer::Start() {
253 if (timer_->IsRunning())
254 return;
255 base::TimeDelta timeout_to_close =
256 timeout_ <= passed_ ? base::TimeDelta() : timeout_ - passed_;
257 start_time_ = base::Time::Now();
258 timer_->Start(
259 FROM_HERE,
260 timeout_to_close,
261 base::Bind(
262 &PopupTimersController::TimerFinished, timer_controller_, id_));
265 void PopupTimer::Pause() {
266 if (!timer_ || !timer_->IsRunning())
267 return;
269 timer_->Stop();
270 passed_ += base::Time::Now() - start_time_;
273 void PopupTimer::Reset() {
274 if (timer_)
275 timer_->Stop();
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();
297 return;
300 PopupTimer* timer = new PopupTimer(id, timeout, AsWeakPtr());
302 timer->Start();
303 popup_timers_[id] = timer;
306 void PopupTimersController::StartAll() {
307 for (auto& iter : popup_timers_)
308 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 for (auto& iter : popup_timers_)
326 iter.second->Pause();
329 void PopupTimersController::CancelTimer(const std::string& id) {
330 PopupTimerCollection::iterator iter = popup_timers_.find(id);
331 if (iter == popup_timers_.end())
332 return;
334 delete iter->second;
335 popup_timers_.erase(iter);
338 void PopupTimersController::CancelAll() {
339 STLDeleteValues(&popup_timers_);
342 void PopupTimersController::TimerFinished(const std::string& id) {
343 if (!ContainsKey(popup_timers_, id))
344 return;
346 CancelTimer(id);
347 message_center_->MarkSinglePopupAsShown(id, false);
350 void PopupTimersController::OnNotificationDisplayed(
351 const std::string& id,
352 const DisplaySource source) {
353 OnNotificationUpdated(id);
356 void PopupTimersController::OnNotificationUpdated(const std::string& id) {
357 NotificationList::PopupNotifications popup_notifications =
358 message_center_->GetPopupNotifications();
360 if (!popup_notifications.size()) {
361 CancelAll();
362 return;
365 NotificationList::PopupNotifications::const_iterator iter =
366 popup_notifications.begin();
367 for (; iter != popup_notifications.end(); ++iter) {
368 if ((*iter)->id() == id)
369 break;
372 if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
373 CancelTimer(id);
374 return;
377 // Start the timer if not yet.
378 if (popup_timers_.find(id) == popup_timers_.end())
379 StartTimer(id, GetTimeoutForPriority((*iter)->priority()));
382 void PopupTimersController::OnNotificationRemoved(const std::string& id,
383 bool by_user) {
384 CancelTimer(id);
387 } // namespace internal
389 ////////////////////////////////////////////////////////////////////////////////
390 // MessageCenterImpl::NotificationCache
392 MessageCenterImpl::NotificationCache::NotificationCache()
393 : unread_count(0) {}
395 MessageCenterImpl::NotificationCache::~NotificationCache() {}
397 void MessageCenterImpl::NotificationCache::Rebuild(
398 const NotificationList::Notifications& notifications) {
399 visible_notifications = notifications;
400 RecountUnread();
403 void MessageCenterImpl::NotificationCache::RecountUnread() {
404 unread_count = 0;
405 for (const auto& notification : visible_notifications) {
406 if (!notification->IsRead())
407 ++unread_count;
411 ////////////////////////////////////////////////////////////////////////////////
412 // MessageCenterImpl
414 MessageCenterImpl::MessageCenterImpl()
415 : MessageCenter(),
416 popup_timers_controller_(new internal::PopupTimersController(this)),
417 settings_provider_(NULL) {
418 notification_list_.reset(new NotificationList());
419 notification_queue_.reset(new internal::ChangeQueue());
422 MessageCenterImpl::~MessageCenterImpl() {
423 SetNotifierSettingsProvider(NULL);
426 void MessageCenterImpl::AddObserver(MessageCenterObserver* observer) {
427 observer_list_.AddObserver(observer);
430 void MessageCenterImpl::RemoveObserver(MessageCenterObserver* observer) {
431 observer_list_.RemoveObserver(observer);
434 void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) {
435 if (std::find(blockers_.begin(), blockers_.end(), blocker) !=
436 blockers_.end()) {
437 return;
439 blocker->AddObserver(this);
440 blockers_.push_back(blocker);
443 void MessageCenterImpl::RemoveNotificationBlocker(
444 NotificationBlocker* blocker) {
445 std::vector<NotificationBlocker*>::iterator iter =
446 std::find(blockers_.begin(), blockers_.end(), blocker);
447 if (iter == blockers_.end())
448 return;
449 blocker->RemoveObserver(this);
450 blockers_.erase(iter);
453 void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker* blocker) {
454 std::list<std::string> blocked_ids;
455 NotificationList::PopupNotifications popups =
456 notification_list_->GetPopupNotifications(blockers_, &blocked_ids);
458 for (const auto& id : blocked_ids) {
459 // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
460 // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
461 // calls NotificationList::MarkSinglePopupAsShown() and then updates the
462 // unread count, but the whole cache will be recreated below.
463 notification_list_->MarkSinglePopupAsShown(id, true);
464 FOR_EACH_OBSERVER(MessageCenterObserver,
465 observer_list_,
466 OnNotificationUpdated(id));
468 notification_cache_.Rebuild(
469 notification_list_->GetVisibleNotifications(blockers_));
470 FOR_EACH_OBSERVER(MessageCenterObserver,
471 observer_list_,
472 OnBlockingStateChanged(blocker));
475 void MessageCenterImpl::UpdateIconImage(
476 const NotifierId& notifier_id, const gfx::Image& icon) {}
478 void MessageCenterImpl::NotifierGroupChanged() {}
480 void MessageCenterImpl::NotifierEnabledChanged(
481 const NotifierId& notifier_id, bool enabled) {
482 if (!enabled) {
483 RemoveNotificationsForNotifierId(notifier_id);
487 void MessageCenterImpl::SetVisibility(Visibility visibility) {
488 std::set<std::string> updated_ids;
489 notification_list_->SetMessageCenterVisible(
490 (visibility == VISIBILITY_MESSAGE_CENTER), &updated_ids);
491 notification_cache_.RecountUnread();
493 for (const auto& id : updated_ids) {
494 FOR_EACH_OBSERVER(
495 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
498 if (visibility == VISIBILITY_TRANSIENT)
499 notification_queue_->ApplyChanges(this);
501 FOR_EACH_OBSERVER(MessageCenterObserver,
502 observer_list_,
503 OnCenterVisibilityChanged(visibility));
506 bool MessageCenterImpl::IsMessageCenterVisible() const {
507 return notification_list_->is_message_center_visible();
510 size_t MessageCenterImpl::NotificationCount() const {
511 return notification_cache_.visible_notifications.size();
514 size_t MessageCenterImpl::UnreadNotificationCount() const {
515 return notification_cache_.unread_count;
518 bool MessageCenterImpl::HasPopupNotifications() const {
519 return !IsMessageCenterVisible() &&
520 notification_list_->HasPopupNotifications(blockers_);
523 bool MessageCenterImpl::IsQuietMode() const {
524 return notification_list_->quiet_mode();
527 bool MessageCenterImpl::HasClickedListener(const std::string& id) {
528 scoped_refptr<NotificationDelegate> delegate =
529 notification_list_->GetNotificationDelegate(id);
530 return delegate.get() && delegate->HasClickedListener();
533 message_center::Notification* MessageCenterImpl::FindVisibleNotificationById(
534 const std::string& id) {
535 return notification_list_->GetNotificationById(id);
538 const NotificationList::Notifications&
539 MessageCenterImpl::GetVisibleNotifications() {
540 return notification_cache_.visible_notifications;
543 NotificationList::PopupNotifications
544 MessageCenterImpl::GetPopupNotifications() {
545 return notification_list_->GetPopupNotifications(blockers_, NULL);
548 //------------------------------------------------------------------------------
549 // Client code interface.
550 void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) {
551 DCHECK(notification);
552 const std::string id = notification->id();
553 for (size_t i = 0; i < blockers_.size(); ++i)
554 blockers_[i]->CheckState();
556 if (notification_list_->is_message_center_visible()) {
557 notification_queue_->AddNotification(notification.Pass());
558 return;
561 // Sometimes the notification can be added with the same id and the
562 // |notification_list| will replace the notification instead of adding new.
563 // This is essentially an update rather than addition.
564 bool already_exists = (notification_list_->GetNotificationById(id) != NULL);
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 (FindVisibleNotificationById(id) == NULL)
631 return;
633 // In many cases |id| is a reference to an existing notification instance
634 // but the instance can be destructed in RemoveNotification(). Hence
635 // copies the id explicitly here.
636 std::string copied_id(id);
638 scoped_refptr<NotificationDelegate> delegate =
639 notification_list_->GetNotificationDelegate(copied_id);
640 if (delegate.get())
641 delegate->Close(by_user);
643 notification_list_->RemoveNotification(copied_id);
644 notification_cache_.Rebuild(
645 notification_list_->GetVisibleNotifications(blockers_));
646 FOR_EACH_OBSERVER(MessageCenterObserver,
647 observer_list_,
648 OnNotificationRemoved(copied_id, by_user));
651 void MessageCenterImpl::RemoveNotificationsForNotifierId(
652 const NotifierId& notifier_id) {
653 NotificationList::Notifications notifications =
654 notification_list_->GetNotificationsByNotifierId(notifier_id);
655 for (const auto& notification : notifications)
656 RemoveNotification(notification->id(), false);
657 if (!notifications.empty()) {
658 notification_cache_.Rebuild(
659 notification_list_->GetVisibleNotifications(blockers_));
663 void MessageCenterImpl::RemoveAllNotifications(bool by_user) {
664 // Using not |blockers_| but an empty list since it wants to remove literally
665 // all notifications.
666 RemoveNotifications(by_user, NotificationBlockers());
669 void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user) {
670 RemoveNotifications(by_user, blockers_);
673 void MessageCenterImpl::RemoveNotifications(
674 bool by_user,
675 const NotificationBlockers& blockers) {
676 const NotificationList::Notifications notifications =
677 notification_list_->GetVisibleNotifications(blockers);
678 std::set<std::string> ids;
679 for (const auto& notification : notifications) {
680 ids.insert(notification->id());
681 scoped_refptr<NotificationDelegate> delegate = notification->delegate();
682 if (delegate.get())
683 delegate->Close(by_user);
684 notification_list_->RemoveNotification(notification->id());
687 if (!ids.empty()) {
688 notification_cache_.Rebuild(
689 notification_list_->GetVisibleNotifications(blockers_));
691 for (const auto& id : ids) {
692 FOR_EACH_OBSERVER(MessageCenterObserver,
693 observer_list_,
694 OnNotificationRemoved(id, by_user));
698 void MessageCenterImpl::SetNotificationIcon(const std::string& notification_id,
699 const gfx::Image& image) {
700 bool updated = false;
701 Notification* queue_notification = notification_queue_->GetLatestNotification(
702 notification_id);
704 if (queue_notification) {
705 queue_notification->set_icon(image);
706 updated = true;
707 } else {
708 updated = notification_list_->SetNotificationIcon(notification_id, image);
711 if (updated) {
712 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
713 OnNotificationUpdated(notification_id));
717 void MessageCenterImpl::SetNotificationImage(const std::string& notification_id,
718 const gfx::Image& image) {
719 bool updated = false;
720 Notification* queue_notification = notification_queue_->GetLatestNotification(
721 notification_id);
723 if (queue_notification) {
724 queue_notification->set_image(image);
725 updated = true;
726 } else {
727 updated = notification_list_->SetNotificationImage(notification_id, image);
730 if (updated) {
731 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
732 OnNotificationUpdated(notification_id));
736 void MessageCenterImpl::SetNotificationButtonIcon(
737 const std::string& notification_id, int button_index,
738 const gfx::Image& image) {
739 bool updated = false;
740 Notification* queue_notification = notification_queue_->GetLatestNotification(
741 notification_id);
743 if (queue_notification) {
744 queue_notification->SetButtonIcon(button_index, image);
745 updated = true;
746 } else {
747 updated = notification_list_->SetNotificationButtonIcon(
748 notification_id, button_index, image);
751 if (updated) {
752 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
753 OnNotificationUpdated(notification_id));
757 void MessageCenterImpl::DisableNotificationsByNotifier(
758 const NotifierId& notifier_id) {
759 if (settings_provider_) {
760 // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
761 Notifier notifier(notifier_id, base::string16(), true);
762 settings_provider_->SetNotifierEnabled(notifier, false);
763 // The settings provider will call back to remove the notifications
764 // belonging to the notifier id.
765 } else {
766 RemoveNotificationsForNotifierId(notifier_id);
770 void MessageCenterImpl::ClickOnNotification(const std::string& id) {
771 if (FindVisibleNotificationById(id) == NULL)
772 return;
773 if (HasPopupNotifications())
774 MarkSinglePopupAsShown(id, true);
775 scoped_refptr<NotificationDelegate> delegate =
776 notification_list_->GetNotificationDelegate(id);
777 if (delegate.get())
778 delegate->Click();
779 FOR_EACH_OBSERVER(
780 MessageCenterObserver, observer_list_, OnNotificationClicked(id));
783 void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
784 int button_index) {
785 if (FindVisibleNotificationById(id) == NULL)
786 return;
787 if (HasPopupNotifications())
788 MarkSinglePopupAsShown(id, true);
789 scoped_refptr<NotificationDelegate> delegate =
790 notification_list_->GetNotificationDelegate(id);
791 if (delegate.get())
792 delegate->ButtonClick(button_index);
793 FOR_EACH_OBSERVER(
794 MessageCenterObserver, observer_list_, OnNotificationButtonClicked(
795 id, button_index));
798 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id,
799 bool mark_notification_as_read) {
800 if (FindVisibleNotificationById(id) == NULL)
801 return;
802 notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read);
803 notification_cache_.RecountUnread();
804 FOR_EACH_OBSERVER(
805 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
808 void MessageCenterImpl::DisplayedNotification(
809 const std::string& id,
810 const DisplaySource source) {
811 if (FindVisibleNotificationById(id) == NULL)
812 return;
814 if (HasPopupNotifications())
815 notification_list_->MarkSinglePopupAsDisplayed(id);
816 notification_cache_.RecountUnread();
817 scoped_refptr<NotificationDelegate> delegate =
818 notification_list_->GetNotificationDelegate(id);
819 if (delegate.get())
820 delegate->Display();
821 FOR_EACH_OBSERVER(
822 MessageCenterObserver,
823 observer_list_,
824 OnNotificationDisplayed(id, source));
827 void MessageCenterImpl::SetNotifierSettingsProvider(
828 NotifierSettingsProvider* provider) {
829 if (settings_provider_) {
830 settings_provider_->RemoveObserver(this);
831 settings_provider_ = NULL;
833 settings_provider_ = provider;
834 if (settings_provider_)
835 settings_provider_->AddObserver(this);
838 NotifierSettingsProvider* MessageCenterImpl::GetNotifierSettingsProvider() {
839 return settings_provider_;
842 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) {
843 if (in_quiet_mode != notification_list_->quiet_mode()) {
844 notification_list_->SetQuietMode(in_quiet_mode);
845 FOR_EACH_OBSERVER(MessageCenterObserver,
846 observer_list_,
847 OnQuietModeChanged(in_quiet_mode));
849 quiet_mode_timer_.reset();
852 void MessageCenterImpl::EnterQuietModeWithExpire(
853 const base::TimeDelta& expires_in) {
854 if (quiet_mode_timer_) {
855 // Note that the capital Reset() is the method to restart the timer, not
856 // scoped_ptr::reset().
857 quiet_mode_timer_->Reset();
858 } else {
859 notification_list_->SetQuietMode(true);
860 FOR_EACH_OBSERVER(
861 MessageCenterObserver, observer_list_, OnQuietModeChanged(true));
863 quiet_mode_timer_.reset(new base::OneShotTimer<MessageCenterImpl>);
864 quiet_mode_timer_->Start(
865 FROM_HERE,
866 expires_in,
867 base::Bind(
868 &MessageCenterImpl::SetQuietMode, base::Unretained(this), false));
872 void MessageCenterImpl::RestartPopupTimers() {
873 if (popup_timers_controller_)
874 popup_timers_controller_->StartAll();
877 void MessageCenterImpl::PausePopupTimers() {
878 if (popup_timers_controller_)
879 popup_timers_controller_->PauseAll();
882 void MessageCenterImpl::DisableTimersForTest() {
883 popup_timers_controller_.reset();
886 } // namespace message_center