Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / ui / message_center / message_center_impl.cc
blobaf3d31405067bbc798ce48a0c4301e86062305b9
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 // Returns the post-update ID. It means:
62 // - ADD event: ID of the notification to be added.
63 // - UPDATE event: ID of the notification after the change. If the change
64 // doesn't update its ID, this value is same as |notification_list_id|.
65 // - DELETE event: ID of the notification to be deleted.
66 const std::string& id() const { return id_; }
67 ChangeType type() const { return type_; }
68 bool by_user() const { return by_user_; }
69 void set_by_user(bool by_user) { by_user_ = by_user; }
70 // Returns the ID which is used in the notification list. In other word, it
71 // means the ID before the change.
72 const std::string& notification_list_id() const {
73 return notification_list_id_;
75 void set_type(const ChangeType new_type) {
76 type_ = new_type;
78 void ReplaceNotification(scoped_ptr<Notification> new_notification);
80 private:
81 ChangeType type_;
82 std::string id_;
83 std::string notification_list_id_;
84 bool by_user_;
85 scoped_ptr<Notification> notification_;
87 DISALLOW_COPY_AND_ASSIGN(Change);
90 ChangeQueue();
91 ~ChangeQueue();
93 // Called when the message center has appropriate visibility. Modifies
94 // |message_center| but does not retain it. This also causes the queue to
95 // empty itself.
96 void ApplyChanges(MessageCenter* message_center);
98 // Causes a TYPE_ADD change to be added to the queue.
99 void AddNotification(scoped_ptr<Notification> notification);
101 // Causes a TYPE_UPDATE change to be added to the queue.
102 void UpdateNotification(const std::string& old_id,
103 scoped_ptr<Notification> notification);
105 // Causes a TYPE_DELETE change to be added to the queue.
106 void EraseNotification(const std::string& id, bool by_user);
108 // Returns whether the queue matches an id. The id given will be matched
109 // against the ID of all changes post-update, not the id of the notification
110 // as it stands in the notification list.
111 bool Has(const std::string& id) const;
113 // Returns a Change that can be modified by the caller. ChangeQueue retains
114 // ownership of the Change; pointers should not be retained.
115 Notification* GetLatestNotification(const std::string& id) const;
117 private:
118 ScopedVector<Change> changes_;
120 DISALLOW_COPY_AND_ASSIGN(ChangeQueue);
123 ////////////////////////////////////////////////////////////////////////////////
124 // ChangeFinder
126 struct ChangeFinder {
127 explicit ChangeFinder(const std::string& id) : id(id) {}
128 bool operator()(ChangeQueue::Change* change) { return change->id() == id; }
130 std::string id;
133 ////////////////////////////////////////////////////////////////////////////////
134 // ChangeQueue::Change
136 ChangeQueue::Change::Change(ChangeType type,
137 const std::string& id,
138 scoped_ptr<Notification> notification)
139 : type_(type),
140 notification_list_id_(id),
141 by_user_(false),
142 notification_(notification.Pass()) {
143 DCHECK(!id.empty());
144 DCHECK(type != CHANGE_TYPE_DELETE || notification_.get() == NULL);
146 id_ = notification_ ? notification_->id() : notification_list_id_;
149 ChangeQueue::Change::~Change() {}
151 scoped_ptr<Notification> ChangeQueue::Change::PassNotification() {
152 return notification_.Pass();
155 void ChangeQueue::Change::ReplaceNotification(
156 scoped_ptr<Notification> new_notification) {
157 id_ = new_notification ? new_notification->id() : notification_list_id_;
158 notification_.swap(new_notification);
161 ////////////////////////////////////////////////////////////////////////////////
162 // ChangeQueue
164 ChangeQueue::ChangeQueue() {}
166 ChangeQueue::~ChangeQueue() {}
168 void ChangeQueue::ApplyChanges(MessageCenter* message_center) {
169 // This method is re-entrant.
170 while (!changes_.empty()) {
171 ScopedVector<Change>::iterator iter = changes_.begin();
172 scoped_ptr<Change> change(*iter);
173 // TODO(dewittj): Replace changes_ with a deque.
174 changes_.weak_erase(iter);
175 // |message_center| is taking ownership of each element here.
176 switch (change->type()) {
177 case CHANGE_TYPE_ADD:
178 message_center->AddNotification(change->PassNotification());
179 break;
180 case CHANGE_TYPE_UPDATE:
181 message_center->UpdateNotification(change->notification_list_id(),
182 change->PassNotification());
183 break;
184 case CHANGE_TYPE_DELETE:
185 message_center->RemoveNotification(change->notification_list_id(),
186 change->by_user());
187 break;
188 default:
189 NOTREACHED();
194 void ChangeQueue::AddNotification(scoped_ptr<Notification> notification) {
195 std::string id = notification->id();
196 changes_.push_back(
197 new Change(CHANGE_TYPE_ADD, id, notification.Pass()));
200 void ChangeQueue::UpdateNotification(const std::string& old_id,
201 scoped_ptr<Notification> notification) {
202 ScopedVector<Change>::reverse_iterator iter =
203 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(old_id));
204 if (iter == changes_.rend()) {
205 changes_.push_back(
206 new Change(CHANGE_TYPE_UPDATE, old_id, notification.Pass()));
207 return;
210 Change* change = *iter;
211 switch (change->type()) {
212 case CHANGE_TYPE_ADD: {
213 std::string id = notification->id();
214 // Needs to add the change at the last, because if this change updates
215 // its ID, some previous changes may affect new ID.
216 // (eg. Add A, Update B->C, and This update A->B).
217 changes_.erase(--(iter.base()));
218 changes_.push_back(
219 new Change(CHANGE_TYPE_ADD, id, notification.Pass()));
220 break;
222 case CHANGE_TYPE_UPDATE:
223 if (notification->id() == old_id) {
224 // Safe to place the change at the previous place.
225 change->ReplaceNotification(notification.Pass());
226 } else if (change->id() == change->notification_list_id()) {
227 std::string id = notification->id();
228 // Safe to place the change at the last.
229 changes_.erase(--(iter.base()));
230 changes_.push_back(new Change(
231 CHANGE_TYPE_ADD, id, notification.Pass()));
232 } else {
233 // Complex case: gives up to optimize.
234 changes_.push_back(
235 new Change(CHANGE_TYPE_UPDATE, old_id, notification.Pass()));
237 break;
238 case CHANGE_TYPE_DELETE:
239 // DELETE -> UPDATE. Something is wrong. Treats the UPDATE as ADD.
240 changes_.push_back(
241 new Change(CHANGE_TYPE_ADD, old_id, notification.Pass()));
242 break;
243 default:
244 NOTREACHED();
248 void ChangeQueue::EraseNotification(const std::string& id, bool by_user) {
249 ScopedVector<Change>::reverse_iterator iter =
250 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(id));
251 if (iter == changes_.rend()) {
252 scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr));
253 change->set_by_user(by_user);
254 changes_.push_back(change.release());
255 return;
258 Change* change = *iter;
259 switch (change->type()) {
260 case CHANGE_TYPE_ADD:
261 // ADD -> DELETE. Just removes both.
262 changes_.erase(--(iter.base()));
263 break;
264 case CHANGE_TYPE_UPDATE:
265 // UPDATE -> DELETE. Changes the previous UPDATE to DELETE.
266 change->set_type(CHANGE_TYPE_DELETE);
267 change->set_by_user(by_user);
268 change->ReplaceNotification(nullptr);
269 break;
270 case CHANGE_TYPE_DELETE:
271 // DELETE -> DELETE. Something is wrong. Combines them with overriding
272 // the |by_user| flag.
273 change->set_by_user(!change->by_user() && by_user);
274 break;
275 default:
276 NOTREACHED();
280 bool ChangeQueue::Has(const std::string& id) const {
281 ScopedVector<Change>::const_iterator iter =
282 std::find_if(changes_.begin(), changes_.end(), ChangeFinder(id));
283 return iter != changes_.end();
286 Notification* ChangeQueue::GetLatestNotification(const std::string& id) const {
287 ScopedVector<Change>::const_iterator iter =
288 std::find_if(changes_.begin(), changes_.end(), ChangeFinder(id));
289 if (iter == changes_.end())
290 return NULL;
292 return (*iter)->notification();
295 ////////////////////////////////////////////////////////////////////////////////
296 // PopupTimer
298 PopupTimer::PopupTimer(const std::string& id,
299 base::TimeDelta timeout,
300 base::WeakPtr<PopupTimersController> controller)
301 : id_(id),
302 timeout_(timeout),
303 timer_controller_(controller),
304 timer_(new base::OneShotTimer<PopupTimersController>) {}
306 PopupTimer::~PopupTimer() {
307 if (!timer_)
308 return;
310 if (timer_->IsRunning())
311 timer_->Stop();
314 void PopupTimer::Start() {
315 if (timer_->IsRunning())
316 return;
317 base::TimeDelta timeout_to_close =
318 timeout_ <= passed_ ? base::TimeDelta() : timeout_ - passed_;
319 start_time_ = base::Time::Now();
320 timer_->Start(
321 FROM_HERE,
322 timeout_to_close,
323 base::Bind(
324 &PopupTimersController::TimerFinished, timer_controller_, id_));
327 void PopupTimer::Pause() {
328 if (!timer_ || !timer_->IsRunning())
329 return;
331 timer_->Stop();
332 passed_ += base::Time::Now() - start_time_;
335 void PopupTimer::Reset() {
336 if (timer_)
337 timer_->Stop();
338 passed_ = base::TimeDelta();
341 ////////////////////////////////////////////////////////////////////////////////
342 // PopupTimersController
344 PopupTimersController::PopupTimersController(MessageCenter* message_center)
345 : message_center_(message_center), popup_deleter_(&popup_timers_) {
346 message_center_->AddObserver(this);
349 PopupTimersController::~PopupTimersController() {
350 message_center_->RemoveObserver(this);
353 void PopupTimersController::StartTimer(const std::string& id,
354 const base::TimeDelta& timeout) {
355 PopupTimerCollection::iterator iter = popup_timers_.find(id);
356 if (iter != popup_timers_.end()) {
357 DCHECK(iter->second);
358 iter->second->Start();
359 return;
362 PopupTimer* timer = new PopupTimer(id, timeout, AsWeakPtr());
364 timer->Start();
365 popup_timers_[id] = timer;
368 void PopupTimersController::StartAll() {
369 for (auto& iter : popup_timers_)
370 iter.second->Start();
373 void PopupTimersController::ResetTimer(const std::string& id,
374 const base::TimeDelta& timeout) {
375 CancelTimer(id);
376 StartTimer(id, timeout);
379 void PopupTimersController::PauseTimer(const std::string& id) {
380 PopupTimerCollection::iterator iter = popup_timers_.find(id);
381 if (iter == popup_timers_.end())
382 return;
383 iter->second->Pause();
386 void PopupTimersController::PauseAll() {
387 for (auto& iter : popup_timers_)
388 iter.second->Pause();
391 void PopupTimersController::CancelTimer(const std::string& id) {
392 PopupTimerCollection::iterator iter = popup_timers_.find(id);
393 if (iter == popup_timers_.end())
394 return;
396 delete iter->second;
397 popup_timers_.erase(iter);
400 void PopupTimersController::CancelAll() {
401 STLDeleteValues(&popup_timers_);
404 void PopupTimersController::TimerFinished(const std::string& id) {
405 if (!ContainsKey(popup_timers_, id))
406 return;
408 CancelTimer(id);
409 message_center_->MarkSinglePopupAsShown(id, false);
412 void PopupTimersController::OnNotificationDisplayed(
413 const std::string& id,
414 const DisplaySource source) {
415 OnNotificationUpdated(id);
418 void PopupTimersController::OnNotificationUpdated(const std::string& id) {
419 NotificationList::PopupNotifications popup_notifications =
420 message_center_->GetPopupNotifications();
422 if (!popup_notifications.size()) {
423 CancelAll();
424 return;
427 NotificationList::PopupNotifications::const_iterator iter =
428 popup_notifications.begin();
429 for (; iter != popup_notifications.end(); ++iter) {
430 if ((*iter)->id() == id)
431 break;
434 if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
435 CancelTimer(id);
436 return;
439 // Start the timer if not yet.
440 if (popup_timers_.find(id) == popup_timers_.end())
441 StartTimer(id, GetTimeoutForPriority((*iter)->priority()));
444 void PopupTimersController::OnNotificationRemoved(const std::string& id,
445 bool by_user) {
446 CancelTimer(id);
449 } // namespace internal
451 ////////////////////////////////////////////////////////////////////////////////
452 // MessageCenterImpl::NotificationCache
454 MessageCenterImpl::NotificationCache::NotificationCache()
455 : unread_count(0) {}
457 MessageCenterImpl::NotificationCache::~NotificationCache() {}
459 void MessageCenterImpl::NotificationCache::Rebuild(
460 const NotificationList::Notifications& notifications) {
461 visible_notifications = notifications;
462 RecountUnread();
465 void MessageCenterImpl::NotificationCache::RecountUnread() {
466 unread_count = 0;
467 for (const auto& notification : visible_notifications) {
468 if (!notification->IsRead())
469 ++unread_count;
473 ////////////////////////////////////////////////////////////////////////////////
474 // MessageCenterImpl
476 MessageCenterImpl::MessageCenterImpl()
477 : MessageCenter(),
478 popup_timers_controller_(new internal::PopupTimersController(this)),
479 settings_provider_(NULL) {
480 notification_list_.reset(new NotificationList());
481 notification_queue_.reset(new internal::ChangeQueue());
484 MessageCenterImpl::~MessageCenterImpl() {
485 SetNotifierSettingsProvider(NULL);
488 void MessageCenterImpl::AddObserver(MessageCenterObserver* observer) {
489 observer_list_.AddObserver(observer);
492 void MessageCenterImpl::RemoveObserver(MessageCenterObserver* observer) {
493 observer_list_.RemoveObserver(observer);
496 void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) {
497 if (std::find(blockers_.begin(), blockers_.end(), blocker) !=
498 blockers_.end()) {
499 return;
501 blocker->AddObserver(this);
502 blockers_.push_back(blocker);
505 void MessageCenterImpl::RemoveNotificationBlocker(
506 NotificationBlocker* blocker) {
507 std::vector<NotificationBlocker*>::iterator iter =
508 std::find(blockers_.begin(), blockers_.end(), blocker);
509 if (iter == blockers_.end())
510 return;
511 blocker->RemoveObserver(this);
512 blockers_.erase(iter);
515 void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker* blocker) {
516 std::list<std::string> blocked_ids;
517 NotificationList::PopupNotifications popups =
518 notification_list_->GetPopupNotifications(blockers_, &blocked_ids);
520 for (const auto& id : blocked_ids) {
521 // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
522 // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
523 // calls NotificationList::MarkSinglePopupAsShown() and then updates the
524 // unread count, but the whole cache will be recreated below.
525 notification_list_->MarkSinglePopupAsShown(id, true);
526 FOR_EACH_OBSERVER(MessageCenterObserver,
527 observer_list_,
528 OnNotificationUpdated(id));
530 notification_cache_.Rebuild(
531 notification_list_->GetVisibleNotifications(blockers_));
532 FOR_EACH_OBSERVER(MessageCenterObserver,
533 observer_list_,
534 OnBlockingStateChanged(blocker));
537 void MessageCenterImpl::UpdateIconImage(
538 const NotifierId& notifier_id, const gfx::Image& icon) {}
540 void MessageCenterImpl::NotifierGroupChanged() {}
542 void MessageCenterImpl::NotifierEnabledChanged(
543 const NotifierId& notifier_id, bool enabled) {
544 if (!enabled) {
545 RemoveNotificationsForNotifierId(notifier_id);
549 void MessageCenterImpl::SetVisibility(Visibility visibility) {
550 std::set<std::string> updated_ids;
551 notification_list_->SetMessageCenterVisible(
552 (visibility == VISIBILITY_MESSAGE_CENTER), &updated_ids);
553 notification_cache_.RecountUnread();
555 for (const auto& id : updated_ids) {
556 FOR_EACH_OBSERVER(
557 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
560 if (visibility == VISIBILITY_TRANSIENT)
561 notification_queue_->ApplyChanges(this);
563 FOR_EACH_OBSERVER(MessageCenterObserver,
564 observer_list_,
565 OnCenterVisibilityChanged(visibility));
568 bool MessageCenterImpl::IsMessageCenterVisible() const {
569 return notification_list_->is_message_center_visible();
572 size_t MessageCenterImpl::NotificationCount() const {
573 return notification_cache_.visible_notifications.size();
576 size_t MessageCenterImpl::UnreadNotificationCount() const {
577 return notification_cache_.unread_count;
580 bool MessageCenterImpl::HasPopupNotifications() const {
581 return !IsMessageCenterVisible() &&
582 notification_list_->HasPopupNotifications(blockers_);
585 bool MessageCenterImpl::IsQuietMode() const {
586 return notification_list_->quiet_mode();
589 bool MessageCenterImpl::HasClickedListener(const std::string& id) {
590 scoped_refptr<NotificationDelegate> delegate =
591 notification_list_->GetNotificationDelegate(id);
592 return delegate.get() && delegate->HasClickedListener();
595 message_center::Notification* MessageCenterImpl::FindVisibleNotificationById(
596 const std::string& id) {
597 return notification_list_->GetNotificationById(id);
600 const NotificationList::Notifications&
601 MessageCenterImpl::GetVisibleNotifications() {
602 return notification_cache_.visible_notifications;
605 NotificationList::PopupNotifications
606 MessageCenterImpl::GetPopupNotifications() {
607 return notification_list_->GetPopupNotifications(blockers_, NULL);
610 //------------------------------------------------------------------------------
611 // Client code interface.
612 void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) {
613 DCHECK(notification);
614 const std::string id = notification->id();
615 for (size_t i = 0; i < blockers_.size(); ++i)
616 blockers_[i]->CheckState();
618 if (notification_list_->is_message_center_visible()) {
619 notification_queue_->AddNotification(notification.Pass());
620 return;
623 // Sometimes the notification can be added with the same id and the
624 // |notification_list| will replace the notification instead of adding new.
625 // This is essentially an update rather than addition.
626 bool already_exists = (notification_list_->GetNotificationById(id) != NULL);
627 notification_list_->AddNotification(notification.Pass());
628 notification_cache_.Rebuild(
629 notification_list_->GetVisibleNotifications(blockers_));
631 if (already_exists) {
632 FOR_EACH_OBSERVER(
633 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
634 } else {
635 FOR_EACH_OBSERVER(
636 MessageCenterObserver, observer_list_, OnNotificationAdded(id));
640 void MessageCenterImpl::UpdateNotification(
641 const std::string& old_id,
642 scoped_ptr<Notification> new_notification) {
643 for (size_t i = 0; i < blockers_.size(); ++i)
644 blockers_[i]->CheckState();
646 if (notification_list_->is_message_center_visible()) {
647 // We will allow notifications that are progress types (and stay progress
648 // types) to be updated even if the message center is open. There are 3
649 // requirements here:
650 // * Notification of type PROGRESS exists with same ID in the center
651 // * There are no queued updates for this notification (they imply a change
652 // that violates the PROGRESS invariant
653 // * The new notification is type PROGRESS.
654 // TODO(dewittj): Ensure this works when the ID is changed by the caller.
655 // This shouldn't be an issue in practice since only W3C notifications
656 // change the ID on update, and they don't have progress type notifications.
657 bool update_keeps_progress_type =
658 new_notification->type() == NOTIFICATION_TYPE_PROGRESS &&
659 !notification_queue_->Has(old_id) &&
660 notification_list_->HasNotificationOfType(old_id,
661 NOTIFICATION_TYPE_PROGRESS);
662 if (!update_keeps_progress_type) {
663 // Updates are allowed only for progress notifications.
664 notification_queue_->UpdateNotification(old_id, new_notification.Pass());
665 return;
669 std::string new_id = new_notification->id();
670 notification_list_->UpdateNotificationMessage(old_id,
671 new_notification.Pass());
672 notification_cache_.Rebuild(
673 notification_list_->GetVisibleNotifications(blockers_));
674 if (old_id == new_id) {
675 FOR_EACH_OBSERVER(
676 MessageCenterObserver, observer_list_, OnNotificationUpdated(new_id));
677 } else {
678 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
679 OnNotificationRemoved(old_id, false));
680 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
681 OnNotificationAdded(new_id));
685 void MessageCenterImpl::RemoveNotification(const std::string& id,
686 bool by_user) {
687 if (!by_user && notification_list_->is_message_center_visible()) {
688 notification_queue_->EraseNotification(id, by_user);
689 return;
692 if (FindVisibleNotificationById(id) == NULL)
693 return;
695 // In many cases |id| is a reference to an existing notification instance
696 // but the instance can be destructed in RemoveNotification(). Hence
697 // copies the id explicitly here.
698 std::string copied_id(id);
700 scoped_refptr<NotificationDelegate> delegate =
701 notification_list_->GetNotificationDelegate(copied_id);
702 if (delegate.get())
703 delegate->Close(by_user);
705 notification_list_->RemoveNotification(copied_id);
706 notification_cache_.Rebuild(
707 notification_list_->GetVisibleNotifications(blockers_));
708 FOR_EACH_OBSERVER(MessageCenterObserver,
709 observer_list_,
710 OnNotificationRemoved(copied_id, by_user));
713 void MessageCenterImpl::RemoveNotificationsForNotifierId(
714 const NotifierId& notifier_id) {
715 NotificationList::Notifications notifications =
716 notification_list_->GetNotificationsByNotifierId(notifier_id);
717 for (const auto& notification : notifications)
718 RemoveNotification(notification->id(), false);
719 if (!notifications.empty()) {
720 notification_cache_.Rebuild(
721 notification_list_->GetVisibleNotifications(blockers_));
725 void MessageCenterImpl::RemoveAllNotifications(bool by_user) {
726 // Using not |blockers_| but an empty list since it wants to remove literally
727 // all notifications.
728 RemoveNotifications(by_user, NotificationBlockers());
731 void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user) {
732 RemoveNotifications(by_user, blockers_);
735 void MessageCenterImpl::RemoveNotifications(
736 bool by_user,
737 const NotificationBlockers& blockers) {
738 const NotificationList::Notifications notifications =
739 notification_list_->GetVisibleNotifications(blockers);
740 std::set<std::string> ids;
741 for (const auto& notification : notifications) {
742 ids.insert(notification->id());
743 scoped_refptr<NotificationDelegate> delegate = notification->delegate();
744 if (delegate.get())
745 delegate->Close(by_user);
746 notification_list_->RemoveNotification(notification->id());
749 if (!ids.empty()) {
750 notification_cache_.Rebuild(
751 notification_list_->GetVisibleNotifications(blockers_));
753 for (const auto& id : ids) {
754 FOR_EACH_OBSERVER(MessageCenterObserver,
755 observer_list_,
756 OnNotificationRemoved(id, by_user));
760 void MessageCenterImpl::SetNotificationIcon(const std::string& notification_id,
761 const gfx::Image& image) {
762 bool updated = false;
763 Notification* queue_notification = notification_queue_->GetLatestNotification(
764 notification_id);
766 if (queue_notification) {
767 queue_notification->set_icon(image);
768 updated = true;
769 } else {
770 updated = notification_list_->SetNotificationIcon(notification_id, image);
773 if (updated) {
774 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
775 OnNotificationUpdated(notification_id));
779 void MessageCenterImpl::SetNotificationImage(const std::string& notification_id,
780 const gfx::Image& image) {
781 bool updated = false;
782 Notification* queue_notification = notification_queue_->GetLatestNotification(
783 notification_id);
785 if (queue_notification) {
786 queue_notification->set_image(image);
787 updated = true;
788 } else {
789 updated = notification_list_->SetNotificationImage(notification_id, image);
792 if (updated) {
793 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
794 OnNotificationUpdated(notification_id));
798 void MessageCenterImpl::SetNotificationButtonIcon(
799 const std::string& notification_id, int button_index,
800 const gfx::Image& image) {
801 bool updated = false;
802 Notification* queue_notification = notification_queue_->GetLatestNotification(
803 notification_id);
805 if (queue_notification) {
806 queue_notification->SetButtonIcon(button_index, image);
807 updated = true;
808 } else {
809 updated = notification_list_->SetNotificationButtonIcon(
810 notification_id, button_index, image);
813 if (updated) {
814 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_,
815 OnNotificationUpdated(notification_id));
819 void MessageCenterImpl::DisableNotificationsByNotifier(
820 const NotifierId& notifier_id) {
821 if (settings_provider_) {
822 // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
823 Notifier notifier(notifier_id, base::string16(), true);
824 settings_provider_->SetNotifierEnabled(notifier, false);
825 // The settings provider will call back to remove the notifications
826 // belonging to the notifier id.
827 } else {
828 RemoveNotificationsForNotifierId(notifier_id);
832 void MessageCenterImpl::ClickOnNotification(const std::string& id) {
833 if (FindVisibleNotificationById(id) == NULL)
834 return;
835 if (HasPopupNotifications())
836 MarkSinglePopupAsShown(id, true);
837 scoped_refptr<NotificationDelegate> delegate =
838 notification_list_->GetNotificationDelegate(id);
839 if (delegate.get())
840 delegate->Click();
841 FOR_EACH_OBSERVER(
842 MessageCenterObserver, observer_list_, OnNotificationClicked(id));
845 void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
846 int button_index) {
847 if (FindVisibleNotificationById(id) == NULL)
848 return;
849 if (HasPopupNotifications())
850 MarkSinglePopupAsShown(id, true);
851 scoped_refptr<NotificationDelegate> delegate =
852 notification_list_->GetNotificationDelegate(id);
853 if (delegate.get())
854 delegate->ButtonClick(button_index);
855 FOR_EACH_OBSERVER(
856 MessageCenterObserver, observer_list_, OnNotificationButtonClicked(
857 id, button_index));
860 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id,
861 bool mark_notification_as_read) {
862 if (FindVisibleNotificationById(id) == NULL)
863 return;
864 notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read);
865 notification_cache_.RecountUnread();
866 FOR_EACH_OBSERVER(
867 MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
870 void MessageCenterImpl::DisplayedNotification(
871 const std::string& id,
872 const DisplaySource source) {
873 if (FindVisibleNotificationById(id) == NULL)
874 return;
876 if (HasPopupNotifications())
877 notification_list_->MarkSinglePopupAsDisplayed(id);
878 notification_cache_.RecountUnread();
879 scoped_refptr<NotificationDelegate> delegate =
880 notification_list_->GetNotificationDelegate(id);
881 if (delegate.get())
882 delegate->Display();
883 FOR_EACH_OBSERVER(
884 MessageCenterObserver,
885 observer_list_,
886 OnNotificationDisplayed(id, source));
889 void MessageCenterImpl::SetNotifierSettingsProvider(
890 NotifierSettingsProvider* provider) {
891 if (settings_provider_) {
892 settings_provider_->RemoveObserver(this);
893 settings_provider_ = NULL;
895 settings_provider_ = provider;
896 if (settings_provider_)
897 settings_provider_->AddObserver(this);
900 NotifierSettingsProvider* MessageCenterImpl::GetNotifierSettingsProvider() {
901 return settings_provider_;
904 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) {
905 if (in_quiet_mode != notification_list_->quiet_mode()) {
906 notification_list_->SetQuietMode(in_quiet_mode);
907 FOR_EACH_OBSERVER(MessageCenterObserver,
908 observer_list_,
909 OnQuietModeChanged(in_quiet_mode));
911 quiet_mode_timer_.reset();
914 void MessageCenterImpl::EnterQuietModeWithExpire(
915 const base::TimeDelta& expires_in) {
916 if (quiet_mode_timer_) {
917 // Note that the capital Reset() is the method to restart the timer, not
918 // scoped_ptr::reset().
919 quiet_mode_timer_->Reset();
920 } else {
921 notification_list_->SetQuietMode(true);
922 FOR_EACH_OBSERVER(
923 MessageCenterObserver, observer_list_, OnQuietModeChanged(true));
925 quiet_mode_timer_.reset(new base::OneShotTimer<MessageCenterImpl>);
926 quiet_mode_timer_->Start(
927 FROM_HERE,
928 expires_in,
929 base::Bind(
930 &MessageCenterImpl::SetQuietMode, base::Unretained(this), false));
934 void MessageCenterImpl::RestartPopupTimers() {
935 if (popup_timers_controller_)
936 popup_timers_controller_->StartAll();
939 void MessageCenterImpl::PausePopupTimers() {
940 if (popup_timers_controller_)
941 popup_timers_controller_->PauseAll();
944 void MessageCenterImpl::DisableTimersForTest() {
945 popup_timers_controller_.reset();
948 } // namespace message_center