Add the host toolset to base:sanitizer_options. Fix a typo in nacl.gyp
[chromium-blink-merge.git] / ui / message_center / message_center_impl.cc
blobb56e76e71061c0bc4bf17d23259d61a550e54c6d
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/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"
19 namespace {
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);
30 } // namespace
32 namespace message_center {
33 namespace internal {
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.
37 class ChangeQueue {
38 public:
39 enum ChangeType {
40 CHANGE_TYPE_ADD = 0,
41 CHANGE_TYPE_UPDATE,
42 CHANGE_TYPE_DELETE
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.
51 class Change {
52 public:
53 Change(ChangeType type,
54 const std::string& id,
55 scoped_ptr<Notification> notification);
56 ~Change();
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;
73 private:
74 const ChangeType type_;
75 const std::string id_;
76 std::string notification_list_id_;
77 bool by_user_;
78 scoped_ptr<Notification> notification_;
80 DISALLOW_COPY_AND_ASSIGN(Change);
83 ChangeQueue();
84 ~ChangeQueue();
86 // Called when the message center has appropriate visibility. Modifies
87 // |message_center| but does not retain it. This also causes the queue to
88 // empty itself.
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;
110 private:
111 void Replace(const std::string& id, scoped_ptr<Change> change);
113 ScopedVector<Change> changes_;
116 ////////////////////////////////////////////////////////////////////////////////
117 // ChangeFinder
119 struct ChangeFinder {
120 explicit ChangeFinder(const std::string& id) : id(id) {}
121 bool operator()(ChangeQueue::Change* change) { return change->id() == id; }
123 std::string id;
126 ////////////////////////////////////////////////////////////////////////////////
127 // ChangeQueue::Change
129 ChangeQueue::Change::Change(ChangeType type,
130 const std::string& id,
131 scoped_ptr<Notification> notification)
132 : type_(type),
133 id_(id),
134 notification_list_id_(id),
135 by_user_(false),
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 ////////////////////////////////////////////////////////////////////////////////
148 // ChangeQueue
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());
165 break;
166 case CHANGE_TYPE_UPDATE:
167 message_center->UpdateNotification(change->notification_list_id(),
168 change->PassNotification());
169 break;
170 case CHANGE_TYPE_DELETE:
171 message_center->RemoveNotification(change->notification_list_id(),
172 change->by_user());
173 break;
174 default:
175 NOTREACHED();
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())
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_.get() || !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 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) {
315 CancelTimer(id);
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())
322 return;
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())
336 return;
338 PopupTimer* timer = iter->second;
339 delete timer;
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())
352 return;
354 CancelTimer(id);
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()) {
367 CancelAll();
368 return;
371 NotificationList::PopupNotifications::const_iterator iter =
372 popup_notifications.begin();
373 for (; iter != popup_notifications.end(); iter++) {
374 if ((*iter)->id() == id)
375 break;
378 if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
379 CancelTimer(id);
380 return;
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,
389 bool by_user) {
390 CancelTimer(id);
393 } // namespace internal
395 ////////////////////////////////////////////////////////////////////////////////
396 // MessageCenterImpl::NotificationCache
398 MessageCenterImpl::NotificationCache::NotificationCache()
399 : unread_count(0) {}
401 MessageCenterImpl::NotificationCache::~NotificationCache() {}
403 void MessageCenterImpl::NotificationCache::Rebuild(
404 const NotificationList::Notifications& notifications) {
405 visible_notifications = notifications;
406 RecountUnread();
409 void MessageCenterImpl::NotificationCache::RecountUnread() {
410 unread_count = 0;
411 for (NotificationList::Notifications::const_iterator iter =
412 visible_notifications.begin();
413 iter != visible_notifications.end(); ++iter) {
414 if (!(*iter)->IsRead())
415 ++unread_count;
419 ////////////////////////////////////////////////////////////////////////////////
420 // MessageCenterImpl
422 MessageCenterImpl::MessageCenterImpl()
423 : MessageCenter(),
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) !=
442 blockers_.end()) {
443 return;
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())
454 return;
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,
472 observer_list_,
473 OnNotificationUpdated(*iter));
475 notification_cache_.Rebuild(
476 notification_list_->GetVisibleNotifications(blockers_));
477 FOR_EACH_OBSERVER(MessageCenterObserver,
478 observer_list_,
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();
490 ++iter) {
491 FOR_EACH_OBSERVER(
492 MessageCenterObserver, observer_list_, OnNotificationUpdated(*iter));
495 if (visibility == VISIBILITY_TRANSIENT)
496 notification_queue_->ApplyChanges(this);
498 FOR_EACH_OBSERVER(MessageCenterObserver,
499 observer_list_,
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
524 // arrive here.
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());
564 return;
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) {
577 FOR_EACH_OBSERVER(
578 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
579 } else {
580 FOR_EACH_OBSERVER(
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());
610 return;
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) {
620 FOR_EACH_OBSERVER(
621 MessageCenterObserver, observer_list_, OnNotificationUpdated(new_id));
622 } else {
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,
631 bool by_user) {
632 if (!by_user && notification_list_->is_message_center_visible()) {
633 notification_queue_->EraseNotification(id, by_user);
634 return;
637 if (!HasNotification(id))
638 return;
640 scoped_refptr<NotificationDelegate> delegate =
641 notification_list_->GetNotificationDelegate(id);
642 if (delegate.get())
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,
653 observer_list_,
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(
668 bool by_user,
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();
677 if (delegate.get())
678 delegate->Close(by_user);
679 notification_list_->RemoveNotification((*iter)->id());
682 if (!ids.empty()) {
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,
689 observer_list_,
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(
698 notification_id);
700 if (queue_notification) {
701 queue_notification->set_icon(image);
702 updated = true;
703 } else {
704 updated = notification_list_->SetNotificationIcon(notification_id, image);
707 if (updated) {
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(
717 notification_id);
719 if (queue_notification) {
720 queue_notification->set_image(image);
721 updated = true;
722 } else {
723 updated = notification_list_->SetNotificationImage(notification_id, image);
726 if (updated) {
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(
737 notification_id);
739 if (queue_notification) {
740 queue_notification->SetButtonIcon(button_index, image);
741 updated = true;
742 } else {
743 updated = notification_list_->SetNotificationButtonIcon(
744 notification_id, button_index, image);
747 if (updated) {
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();
766 iter++;
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))
777 return;
778 if (HasPopupNotifications())
779 MarkSinglePopupAsShown(id, true);
780 scoped_refptr<NotificationDelegate> delegate =
781 notification_list_->GetNotificationDelegate(id);
782 if (delegate.get())
783 delegate->Click();
784 FOR_EACH_OBSERVER(
785 MessageCenterObserver, observer_list_, OnNotificationClicked(id));
788 void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
789 int button_index) {
790 if (!HasNotification(id))
791 return;
792 if (HasPopupNotifications())
793 MarkSinglePopupAsShown(id, true);
794 scoped_refptr<NotificationDelegate> delegate =
795 notification_list_->GetNotificationDelegate(id);
796 if (delegate.get())
797 delegate->ButtonClick(button_index);
798 FOR_EACH_OBSERVER(
799 MessageCenterObserver, observer_list_, OnNotificationButtonClicked(
800 id, button_index));
803 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id,
804 bool mark_notification_as_read) {
805 if (!HasNotification(id))
806 return;
807 notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read);
808 notification_cache_.RecountUnread();
809 FOR_EACH_OBSERVER(
810 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
813 void MessageCenterImpl::DisplayedNotification(const std::string& id) {
814 if (!HasNotification(id))
815 return;
817 if (HasPopupNotifications())
818 notification_list_->MarkSinglePopupAsDisplayed(id);
819 notification_cache_.RecountUnread();
820 scoped_refptr<NotificationDelegate> delegate =
821 notification_list_->GetNotificationDelegate(id);
822 if (delegate.get())
823 delegate->Display();
824 FOR_EACH_OBSERVER(
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,
841 observer_list_,
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();
853 } else {
854 notification_list_->SetQuietMode(true);
855 FOR_EACH_OBSERVER(
856 MessageCenterObserver, observer_list_, OnQuietModeChanged(true));
858 quiet_mode_timer_.reset(new base::OneShotTimer<MessageCenterImpl>);
859 quiet_mode_timer_->Start(
860 FROM_HERE,
861 expires_in,
862 base::Bind(
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