[Cronet] Handle redirects in CronetHttpURLConnection
[chromium-blink-merge.git] / ui / message_center / message_center_impl.cc
blob7f4f568ba629e8884832d1a2ea29d7e873f4b2c8
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();
182 scoped_ptr<Change> change(
183 new Change(CHANGE_TYPE_ADD, id, notification.Pass()));
184 Replace(id, change.Pass());
187 void ChangeQueue::UpdateNotification(const std::string& old_id,
188 scoped_ptr<Notification> notification) {
189 std::string new_id = notification->id();
190 scoped_ptr<Change> change(
191 new Change(CHANGE_TYPE_UPDATE, new_id, notification.Pass()));
192 Replace(old_id, change.Pass());
195 void ChangeQueue::EraseNotification(const std::string& id, bool by_user) {
196 scoped_ptr<Change> change(
197 new Change(CHANGE_TYPE_DELETE, id, scoped_ptr<Notification>()));
198 change->set_by_user(by_user);
199 Replace(id, change.Pass());
202 bool ChangeQueue::Has(const std::string& id) const {
203 ScopedVector<Change>::const_iterator iter =
204 std::find_if(changes_.begin(), changes_.end(), ChangeFinder(id));
205 return iter != changes_.end();
208 Notification* ChangeQueue::GetLatestNotification(const std::string& id) const {
209 ScopedVector<Change>::const_iterator iter =
210 std::find_if(changes_.begin(), changes_.end(), ChangeFinder(id));
211 if (iter == changes_.end())
212 return NULL;
214 return (*iter)->notification();
217 void ChangeQueue::Replace(const std::string& changed_id,
218 scoped_ptr<Change> new_change) {
219 ScopedVector<Change>::iterator iter =
220 std::find_if(changes_.begin(), changes_.end(), ChangeFinder(changed_id));
221 if (iter != changes_.end()) {
222 Change* old_change = *iter;
223 new_change->set_notification_list_id(old_change->notification_list_id());
224 changes_.erase(iter);
225 } else {
226 new_change->set_notification_list_id(changed_id);
229 changes_.push_back(new_change.release());
232 ////////////////////////////////////////////////////////////////////////////////
233 // PopupTimer
235 PopupTimer::PopupTimer(const std::string& id,
236 base::TimeDelta timeout,
237 base::WeakPtr<PopupTimersController> controller)
238 : id_(id),
239 timeout_(timeout),
240 timer_controller_(controller),
241 timer_(new base::OneShotTimer<PopupTimersController>) {}
243 PopupTimer::~PopupTimer() {
244 if (!timer_)
245 return;
247 if (timer_->IsRunning())
248 timer_->Stop();
251 void PopupTimer::Start() {
252 if (timer_->IsRunning())
253 return;
254 base::TimeDelta timeout_to_close =
255 timeout_ <= passed_ ? base::TimeDelta() : timeout_ - passed_;
256 start_time_ = base::Time::Now();
257 timer_->Start(
258 FROM_HERE,
259 timeout_to_close,
260 base::Bind(
261 &PopupTimersController::TimerFinished, timer_controller_, id_));
264 void PopupTimer::Pause() {
265 if (!timer_.get() || !timer_->IsRunning())
266 return;
268 timer_->Stop();
269 passed_ += base::Time::Now() - start_time_;
272 void PopupTimer::Reset() {
273 if (timer_)
274 timer_->Stop();
275 passed_ = base::TimeDelta();
278 ////////////////////////////////////////////////////////////////////////////////
279 // PopupTimersController
281 PopupTimersController::PopupTimersController(MessageCenter* message_center)
282 : message_center_(message_center), popup_deleter_(&popup_timers_) {
283 message_center_->AddObserver(this);
286 PopupTimersController::~PopupTimersController() {
287 message_center_->RemoveObserver(this);
290 void PopupTimersController::StartTimer(const std::string& id,
291 const base::TimeDelta& timeout) {
292 PopupTimerCollection::iterator iter = popup_timers_.find(id);
293 if (iter != popup_timers_.end()) {
294 DCHECK(iter->second);
295 iter->second->Start();
296 return;
299 PopupTimer* timer = new PopupTimer(id, timeout, AsWeakPtr());
301 timer->Start();
302 popup_timers_[id] = timer;
305 void PopupTimersController::StartAll() {
306 std::map<std::string, PopupTimer*>::iterator iter;
307 for (iter = popup_timers_.begin(); iter != popup_timers_.end(); iter++) {
308 iter->second->Start();
312 void PopupTimersController::ResetTimer(const std::string& id,
313 const base::TimeDelta& timeout) {
314 CancelTimer(id);
315 StartTimer(id, timeout);
318 void PopupTimersController::PauseTimer(const std::string& id) {
319 PopupTimerCollection::iterator iter = popup_timers_.find(id);
320 if (iter == popup_timers_.end())
321 return;
322 iter->second->Pause();
325 void PopupTimersController::PauseAll() {
326 std::map<std::string, PopupTimer*>::iterator iter;
327 for (iter = popup_timers_.begin(); iter != popup_timers_.end(); iter++) {
328 iter->second->Pause();
332 void PopupTimersController::CancelTimer(const std::string& id) {
333 PopupTimerCollection::iterator iter = popup_timers_.find(id);
334 if (iter == popup_timers_.end())
335 return;
337 PopupTimer* timer = iter->second;
338 delete timer;
340 popup_timers_.erase(iter);
343 void PopupTimersController::CancelAll() {
344 STLDeleteValues(&popup_timers_);
345 popup_timers_.clear();
348 void PopupTimersController::TimerFinished(const std::string& id) {
349 PopupTimerCollection::iterator iter = popup_timers_.find(id);
350 if (iter == popup_timers_.end())
351 return;
353 CancelTimer(id);
354 message_center_->MarkSinglePopupAsShown(id, false);
357 void PopupTimersController::OnNotificationDisplayed(
358 const std::string& id,
359 const DisplaySource source) {
360 OnNotificationUpdated(id);
363 void PopupTimersController::OnNotificationUpdated(const std::string& id) {
364 NotificationList::PopupNotifications popup_notifications =
365 message_center_->GetPopupNotifications();
367 if (!popup_notifications.size()) {
368 CancelAll();
369 return;
372 NotificationList::PopupNotifications::const_iterator iter =
373 popup_notifications.begin();
374 for (; iter != popup_notifications.end(); iter++) {
375 if ((*iter)->id() == id)
376 break;
379 if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
380 CancelTimer(id);
381 return;
384 // Start the timer if not yet.
385 if (popup_timers_.find(id) == popup_timers_.end())
386 StartTimer(id, GetTimeoutForPriority((*iter)->priority()));
389 void PopupTimersController::OnNotificationRemoved(const std::string& id,
390 bool by_user) {
391 CancelTimer(id);
394 } // namespace internal
396 ////////////////////////////////////////////////////////////////////////////////
397 // MessageCenterImpl::NotificationCache
399 MessageCenterImpl::NotificationCache::NotificationCache()
400 : unread_count(0) {}
402 MessageCenterImpl::NotificationCache::~NotificationCache() {}
404 void MessageCenterImpl::NotificationCache::Rebuild(
405 const NotificationList::Notifications& notifications) {
406 visible_notifications = notifications;
407 RecountUnread();
410 void MessageCenterImpl::NotificationCache::RecountUnread() {
411 unread_count = 0;
412 for (NotificationList::Notifications::const_iterator iter =
413 visible_notifications.begin();
414 iter != visible_notifications.end(); ++iter) {
415 if (!(*iter)->IsRead())
416 ++unread_count;
420 ////////////////////////////////////////////////////////////////////////////////
421 // MessageCenterImpl
423 MessageCenterImpl::MessageCenterImpl()
424 : MessageCenter(),
425 popup_timers_controller_(new internal::PopupTimersController(this)),
426 settings_provider_(NULL) {
427 notification_list_.reset(new NotificationList());
428 notification_queue_.reset(new internal::ChangeQueue());
431 MessageCenterImpl::~MessageCenterImpl() {
432 SetNotifierSettingsProvider(NULL);
435 void MessageCenterImpl::AddObserver(MessageCenterObserver* observer) {
436 observer_list_.AddObserver(observer);
439 void MessageCenterImpl::RemoveObserver(MessageCenterObserver* observer) {
440 observer_list_.RemoveObserver(observer);
443 void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) {
444 if (std::find(blockers_.begin(), blockers_.end(), blocker) !=
445 blockers_.end()) {
446 return;
448 blocker->AddObserver(this);
449 blockers_.push_back(blocker);
452 void MessageCenterImpl::RemoveNotificationBlocker(
453 NotificationBlocker* blocker) {
454 std::vector<NotificationBlocker*>::iterator iter =
455 std::find(blockers_.begin(), blockers_.end(), blocker);
456 if (iter == blockers_.end())
457 return;
458 blocker->RemoveObserver(this);
459 blockers_.erase(iter);
462 void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker* blocker) {
463 std::list<std::string> blocked_ids;
464 NotificationList::PopupNotifications popups =
465 notification_list_->GetPopupNotifications(blockers_, &blocked_ids);
467 for (std::list<std::string>::const_iterator iter = blocked_ids.begin();
468 iter != blocked_ids.end(); ++iter) {
469 // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
470 // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
471 // calls NotificationList::MarkSinglePopupAsShown() and then updates the
472 // unread count, but the whole cache will be recreated below.
473 notification_list_->MarkSinglePopupAsShown((*iter), true);
474 FOR_EACH_OBSERVER(MessageCenterObserver,
475 observer_list_,
476 OnNotificationUpdated(*iter));
478 notification_cache_.Rebuild(
479 notification_list_->GetVisibleNotifications(blockers_));
480 FOR_EACH_OBSERVER(MessageCenterObserver,
481 observer_list_,
482 OnBlockingStateChanged(blocker));
485 void MessageCenterImpl::UpdateIconImage(
486 const NotifierId& notifier_id,const gfx::Image& icon) {}
488 void MessageCenterImpl::NotifierGroupChanged() {}
490 void MessageCenterImpl::NotifierEnabledChanged(
491 const NotifierId& notifier_id, bool enabled) {
492 if (!enabled) {
493 RemoveNotificationsForNotifierId(notifier_id);
497 void MessageCenterImpl::SetVisibility(Visibility visibility) {
498 std::set<std::string> updated_ids;
499 notification_list_->SetMessageCenterVisible(
500 (visibility == VISIBILITY_MESSAGE_CENTER), &updated_ids);
501 notification_cache_.RecountUnread();
503 for (std::set<std::string>::const_iterator iter = updated_ids.begin();
504 iter != updated_ids.end();
505 ++iter) {
506 FOR_EACH_OBSERVER(
507 MessageCenterObserver, observer_list_, OnNotificationUpdated(*iter));
510 if (visibility == VISIBILITY_TRANSIENT)
511 notification_queue_->ApplyChanges(this);
513 FOR_EACH_OBSERVER(MessageCenterObserver,
514 observer_list_,
515 OnCenterVisibilityChanged(visibility));
518 bool MessageCenterImpl::IsMessageCenterVisible() const {
519 return notification_list_->is_message_center_visible();
522 size_t MessageCenterImpl::NotificationCount() const {
523 return notification_cache_.visible_notifications.size();
526 size_t MessageCenterImpl::UnreadNotificationCount() const {
527 return notification_cache_.unread_count;
530 bool MessageCenterImpl::HasPopupNotifications() const {
531 return !IsMessageCenterVisible() &&
532 notification_list_->HasPopupNotifications(blockers_);
535 bool MessageCenterImpl::IsQuietMode() const {
536 return notification_list_->quiet_mode();
539 bool MessageCenterImpl::HasClickedListener(const std::string& id) {
540 scoped_refptr<NotificationDelegate> delegate =
541 notification_list_->GetNotificationDelegate(id);
542 return delegate.get() && delegate->HasClickedListener();
545 message_center::Notification* MessageCenterImpl::FindVisibleNotificationById(
546 const std::string& id) {
547 return notification_list_->GetNotificationById(id);
550 const NotificationList::Notifications&
551 MessageCenterImpl::GetVisibleNotifications() {
552 return notification_cache_.visible_notifications;
555 NotificationList::PopupNotifications
556 MessageCenterImpl::GetPopupNotifications() {
557 return notification_list_->GetPopupNotifications(blockers_, NULL);
560 //------------------------------------------------------------------------------
561 // Client code interface.
562 void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) {
563 DCHECK(notification.get());
564 const std::string id = notification->id();
565 for (size_t i = 0; i < blockers_.size(); ++i)
566 blockers_[i]->CheckState();
568 if (notification_list_->is_message_center_visible()) {
569 notification_queue_->AddNotification(notification.Pass());
570 return;
573 // Sometimes the notification can be added with the same id and the
574 // |notification_list| will replace the notification instead of adding new.
575 // This is essentially an update rather than addition.
576 bool already_exists = (notification_list_->GetNotificationById(id) != NULL);
577 notification_list_->AddNotification(notification.Pass());
578 notification_cache_.Rebuild(
579 notification_list_->GetVisibleNotifications(blockers_));
581 if (already_exists) {
582 FOR_EACH_OBSERVER(
583 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
584 } else {
585 FOR_EACH_OBSERVER(
586 MessageCenterObserver, observer_list_, OnNotificationAdded(id));
590 void MessageCenterImpl::UpdateNotification(
591 const std::string& old_id,
592 scoped_ptr<Notification> new_notification) {
593 for (size_t i = 0; i < blockers_.size(); ++i)
594 blockers_[i]->CheckState();
596 if (notification_list_->is_message_center_visible()) {
597 // We will allow notifications that are progress types (and stay progress
598 // types) to be updated even if the message center is open. There are 3
599 // requirements here:
600 // * Notification of type PROGRESS exists with same ID in the center
601 // * There are no queued updates for this notification (they imply a change
602 // that violates the PROGRESS invariant
603 // * The new notification is type PROGRESS.
604 // TODO(dewittj): Ensure this works when the ID is changed by the caller.
605 // This shouldn't be an issue in practice since only W3C notifications
606 // change the ID on update, and they don't have progress type notifications.
607 bool update_keeps_progress_type =
608 new_notification->type() == NOTIFICATION_TYPE_PROGRESS &&
609 !notification_queue_->Has(old_id) &&
610 notification_list_->HasNotificationOfType(old_id,
611 NOTIFICATION_TYPE_PROGRESS);
612 if (!update_keeps_progress_type) {
613 // Updates are allowed only for progress notifications.
614 notification_queue_->UpdateNotification(old_id, new_notification.Pass());
615 return;
619 std::string new_id = new_notification->id();
620 notification_list_->UpdateNotificationMessage(old_id,
621 new_notification.Pass());
622 notification_cache_.Rebuild(
623 notification_list_->GetVisibleNotifications(blockers_));
624 if (old_id == new_id) {
625 FOR_EACH_OBSERVER(
626 MessageCenterObserver, observer_list_, OnNotificationUpdated(new_id));
627 } else {
628 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
629 OnNotificationRemoved(old_id, false));
630 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
631 OnNotificationAdded(new_id));
635 void MessageCenterImpl::RemoveNotification(const std::string& id,
636 bool by_user) {
637 if (!by_user && notification_list_->is_message_center_visible()) {
638 notification_queue_->EraseNotification(id, by_user);
639 return;
642 if (FindVisibleNotificationById(id) == NULL)
643 return;
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);
650 scoped_refptr<NotificationDelegate> delegate =
651 notification_list_->GetNotificationDelegate(copied_id);
652 if (delegate.get())
653 delegate->Close(by_user);
655 notification_list_->RemoveNotification(copied_id);
656 notification_cache_.Rebuild(
657 notification_list_->GetVisibleNotifications(blockers_));
658 FOR_EACH_OBSERVER(MessageCenterObserver,
659 observer_list_,
660 OnNotificationRemoved(copied_id, by_user));
663 void MessageCenterImpl::RemoveNotificationsForNotifierId(
664 const NotifierId& notifier_id) {
665 NotificationList::Notifications notifications =
666 notification_list_->GetNotificationsByNotifierId(notifier_id);
667 for (NotificationList::Notifications::const_iterator iter =
668 notifications.begin(); iter != notifications.end(); ++iter) {
669 RemoveNotification((*iter)->id(), false);
671 if (!notifications.empty()) {
672 notification_cache_.Rebuild(
673 notification_list_->GetVisibleNotifications(blockers_));
677 void MessageCenterImpl::RemoveAllNotifications(bool by_user) {
678 // Using not |blockers_| but an empty list since it wants to remove literally
679 // all notifications.
680 RemoveNotifications(by_user, NotificationBlockers());
683 void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user) {
684 RemoveNotifications(by_user, blockers_);
687 void MessageCenterImpl::RemoveNotifications(
688 bool by_user,
689 const NotificationBlockers& blockers) {
690 const NotificationList::Notifications notifications =
691 notification_list_->GetVisibleNotifications(blockers);
692 std::set<std::string> ids;
693 for (NotificationList::Notifications::const_iterator iter =
694 notifications.begin(); iter != notifications.end(); ++iter) {
695 ids.insert((*iter)->id());
696 scoped_refptr<NotificationDelegate> delegate = (*iter)->delegate();
697 if (delegate.get())
698 delegate->Close(by_user);
699 notification_list_->RemoveNotification((*iter)->id());
702 if (!ids.empty()) {
703 notification_cache_.Rebuild(
704 notification_list_->GetVisibleNotifications(blockers_));
706 for (std::set<std::string>::const_iterator iter = ids.begin();
707 iter != ids.end(); ++iter) {
708 FOR_EACH_OBSERVER(MessageCenterObserver,
709 observer_list_,
710 OnNotificationRemoved(*iter, by_user));
714 void MessageCenterImpl::SetNotificationIcon(const std::string& notification_id,
715 const gfx::Image& image) {
716 bool updated = false;
717 Notification* queue_notification = notification_queue_->GetLatestNotification(
718 notification_id);
720 if (queue_notification) {
721 queue_notification->set_icon(image);
722 updated = true;
723 } else {
724 updated = notification_list_->SetNotificationIcon(notification_id, image);
727 if (updated) {
728 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
729 OnNotificationUpdated(notification_id));
733 void MessageCenterImpl::SetNotificationImage(const std::string& notification_id,
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->set_image(image);
741 updated = true;
742 } else {
743 updated = notification_list_->SetNotificationImage(notification_id, image);
746 if (updated) {
747 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
748 OnNotificationUpdated(notification_id));
752 void MessageCenterImpl::SetNotificationButtonIcon(
753 const std::string& notification_id, int button_index,
754 const gfx::Image& image) {
755 bool updated = false;
756 Notification* queue_notification = notification_queue_->GetLatestNotification(
757 notification_id);
759 if (queue_notification) {
760 queue_notification->SetButtonIcon(button_index, image);
761 updated = true;
762 } else {
763 updated = notification_list_->SetNotificationButtonIcon(
764 notification_id, button_index, image);
767 if (updated) {
768 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
769 OnNotificationUpdated(notification_id));
773 void MessageCenterImpl::DisableNotificationsByNotifier(
774 const NotifierId& notifier_id) {
775 if (settings_provider_) {
776 // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
777 Notifier notifier(notifier_id, base::string16(), true);
778 settings_provider_->SetNotifierEnabled(notifier, false);
779 // The settings provider will call back to remove the notifications
780 // belonging to the notifier id.
781 } else {
782 RemoveNotificationsForNotifierId(notifier_id);
786 void MessageCenterImpl::ClickOnNotification(const std::string& id) {
787 if (FindVisibleNotificationById(id) == NULL)
788 return;
789 if (HasPopupNotifications())
790 MarkSinglePopupAsShown(id, true);
791 scoped_refptr<NotificationDelegate> delegate =
792 notification_list_->GetNotificationDelegate(id);
793 if (delegate.get())
794 delegate->Click();
795 FOR_EACH_OBSERVER(
796 MessageCenterObserver, observer_list_, OnNotificationClicked(id));
799 void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
800 int button_index) {
801 if (FindVisibleNotificationById(id) == NULL)
802 return;
803 if (HasPopupNotifications())
804 MarkSinglePopupAsShown(id, true);
805 scoped_refptr<NotificationDelegate> delegate =
806 notification_list_->GetNotificationDelegate(id);
807 if (delegate.get())
808 delegate->ButtonClick(button_index);
809 FOR_EACH_OBSERVER(
810 MessageCenterObserver, observer_list_, OnNotificationButtonClicked(
811 id, button_index));
814 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id,
815 bool mark_notification_as_read) {
816 if (FindVisibleNotificationById(id) == NULL)
817 return;
818 notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read);
819 notification_cache_.RecountUnread();
820 FOR_EACH_OBSERVER(
821 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
824 void MessageCenterImpl::DisplayedNotification(
825 const std::string& id,
826 const DisplaySource source) {
827 if (FindVisibleNotificationById(id) == NULL)
828 return;
830 if (HasPopupNotifications())
831 notification_list_->MarkSinglePopupAsDisplayed(id);
832 notification_cache_.RecountUnread();
833 scoped_refptr<NotificationDelegate> delegate =
834 notification_list_->GetNotificationDelegate(id);
835 if (delegate.get())
836 delegate->Display();
837 FOR_EACH_OBSERVER(
838 MessageCenterObserver,
839 observer_list_,
840 OnNotificationDisplayed(id, source));
843 void MessageCenterImpl::SetNotifierSettingsProvider(
844 NotifierSettingsProvider* provider) {
845 if (settings_provider_) {
846 settings_provider_->RemoveObserver(this);
847 settings_provider_ = NULL;
849 settings_provider_ = provider;
850 if (settings_provider_)
851 settings_provider_->AddObserver(this);
854 NotifierSettingsProvider* MessageCenterImpl::GetNotifierSettingsProvider() {
855 return settings_provider_;
858 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) {
859 if (in_quiet_mode != notification_list_->quiet_mode()) {
860 notification_list_->SetQuietMode(in_quiet_mode);
861 FOR_EACH_OBSERVER(MessageCenterObserver,
862 observer_list_,
863 OnQuietModeChanged(in_quiet_mode));
865 quiet_mode_timer_.reset();
868 void MessageCenterImpl::EnterQuietModeWithExpire(
869 const base::TimeDelta& expires_in) {
870 if (quiet_mode_timer_.get()) {
871 // Note that the capital Reset() is the method to restart the timer, not
872 // scoped_ptr::reset().
873 quiet_mode_timer_->Reset();
874 } else {
875 notification_list_->SetQuietMode(true);
876 FOR_EACH_OBSERVER(
877 MessageCenterObserver, observer_list_, OnQuietModeChanged(true));
879 quiet_mode_timer_.reset(new base::OneShotTimer<MessageCenterImpl>);
880 quiet_mode_timer_->Start(
881 FROM_HERE,
882 expires_in,
883 base::Bind(
884 &MessageCenterImpl::SetQuietMode, base::Unretained(this), false));
888 void MessageCenterImpl::RestartPopupTimers() {
889 if (popup_timers_controller_.get())
890 popup_timers_controller_->StartAll();
893 void MessageCenterImpl::PausePopupTimers() {
894 if (popup_timers_controller_.get())
895 popup_timers_controller_->PauseAll();
898 void MessageCenterImpl::DisableTimersForTest() {
899 popup_timers_controller_.reset();
902 } // namespace message_center