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 "base/observer_list.h"
8 #include "ui/message_center/message_center_style.h"
9 #include "ui/message_center/notification.h"
10 #include "ui/message_center/notification_list.h"
11 #include "ui/message_center/notification_types.h"
15 base::TimeDelta
GetTimeoutForPriority(int priority
) {
16 if (priority
> message_center::DEFAULT_PRIORITY
) {
17 return base::TimeDelta::FromSeconds(
18 message_center::kAutocloseHighPriorityDelaySeconds
);
20 return base::TimeDelta::FromSeconds(
21 message_center::kAutocloseDefaultDelaySeconds
);
26 namespace message_center
{
29 ////////////////////////////////////////////////////////////////////////////////
32 PopupTimer::PopupTimer(const std::string
& id
,
33 base::TimeDelta timeout
,
34 base::WeakPtr
<PopupTimersController
> controller
)
37 timer_controller_(controller
),
38 timer_(new base::OneShotTimer
<PopupTimersController
>) {}
40 PopupTimer::~PopupTimer() {
44 if (timer_
->IsRunning())
48 void PopupTimer::Start() {
49 if (timer_
->IsRunning())
51 base::TimeDelta timeout_to_close
=
52 timeout_
<= passed_
? base::TimeDelta() : timeout_
- passed_
;
53 start_time_
= base::Time::Now();
58 &PopupTimersController::TimerFinished
, timer_controller_
, id_
));
61 void PopupTimer::Pause() {
62 if (!timer_
.get() || !timer_
->IsRunning())
66 passed_
+= base::Time::Now() - start_time_
;
69 void PopupTimer::Reset() {
72 passed_
= base::TimeDelta();
75 ////////////////////////////////////////////////////////////////////////////////
76 // PopupTimersController
78 PopupTimersController::PopupTimersController(MessageCenter
* message_center
)
79 : message_center_(message_center
), popup_deleter_(&popup_timers_
) {
80 message_center_
->AddObserver(this);
83 PopupTimersController::~PopupTimersController() {
84 message_center_
->RemoveObserver(this);
87 void PopupTimersController::StartTimer(const std::string
& id
,
88 const base::TimeDelta
& timeout
) {
89 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
90 if (iter
!= popup_timers_
.end()) {
92 iter
->second
->Start();
96 PopupTimer
* timer
= new PopupTimer(id
, timeout
, AsWeakPtr());
99 popup_timers_
[id
] = timer
;
102 void PopupTimersController::StartAll() {
103 std::map
<std::string
, PopupTimer
*>::iterator iter
;
104 for (iter
= popup_timers_
.begin(); iter
!= popup_timers_
.end(); iter
++) {
105 iter
->second
->Start();
109 void PopupTimersController::ResetTimer(const std::string
& id
,
110 const base::TimeDelta
& timeout
) {
112 StartTimer(id
, timeout
);
115 void PopupTimersController::PauseTimer(const std::string
& id
) {
116 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
117 if (iter
== popup_timers_
.end())
119 iter
->second
->Pause();
122 void PopupTimersController::PauseAll() {
123 std::map
<std::string
, PopupTimer
*>::iterator iter
;
124 for (iter
= popup_timers_
.begin(); iter
!= popup_timers_
.end(); iter
++) {
125 iter
->second
->Pause();
129 void PopupTimersController::CancelTimer(const std::string
& id
) {
130 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
131 if (iter
== popup_timers_
.end())
134 PopupTimer
* timer
= iter
->second
;
137 popup_timers_
.erase(iter
);
140 void PopupTimersController::CancelAll() {
141 STLDeleteValues(&popup_timers_
);
142 popup_timers_
.clear();
145 void PopupTimersController::TimerFinished(const std::string
& id
) {
146 PopupTimerCollection::iterator iter
= popup_timers_
.find(id
);
147 if (iter
== popup_timers_
.end())
151 message_center_
->MarkSinglePopupAsShown(id
, false);
154 void PopupTimersController::OnNotificationDisplayed(const std::string
& id
) {
155 OnNotificationUpdated(id
);
158 void PopupTimersController::OnNotificationUpdated(const std::string
& id
) {
159 NotificationList::PopupNotifications popup_notifications
=
160 message_center_
->GetPopupNotifications();
162 if (!popup_notifications
.size()) {
167 NotificationList::PopupNotifications::const_iterator iter
=
168 popup_notifications
.begin();
169 for (; iter
!= popup_notifications
.end(); iter
++) {
170 if ((*iter
)->id() == id
)
174 if (iter
== popup_notifications
.end() || (*iter
)->never_timeout()) {
179 // Start the timer if not yet.
180 if (popup_timers_
.find(id
) == popup_timers_
.end())
181 StartTimer(id
, GetTimeoutForPriority((*iter
)->priority()));
184 void PopupTimersController::OnNotificationRemoved(const std::string
& id
,
189 } // namespace internal
191 ////////////////////////////////////////////////////////////////////////////////
194 MessageCenterImpl::MessageCenterImpl()
196 popup_timers_controller_(new internal::PopupTimersController(this)),
198 settings_provider_(NULL
) {
199 notification_list_
.reset(new NotificationList());
202 MessageCenterImpl::~MessageCenterImpl() {
203 notification_list_
.reset();
206 void MessageCenterImpl::AddObserver(MessageCenterObserver
* observer
) {
207 observer_list_
.AddObserver(observer
);
210 void MessageCenterImpl::RemoveObserver(MessageCenterObserver
* observer
) {
211 observer_list_
.RemoveObserver(observer
);
214 void MessageCenterImpl::SetDelegate(Delegate
* delegate
) {
215 delegate_
= delegate
;
218 void MessageCenterImpl::SetMessageCenterVisible(bool visible
) {
219 std::set
<std::string
> updated_ids
;
220 notification_list_
->SetMessageCenterVisible(visible
, &updated_ids
);
221 for (std::set
<std::string
>::const_iterator iter
= updated_ids
.begin();
222 iter
!= updated_ids
.end();
225 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(*iter
));
230 MessageCenterObserver
, observer_list_
, OnNotificationCenterClosed());
234 bool MessageCenterImpl::IsMessageCenterVisible() {
235 return notification_list_
->is_message_center_visible();
238 size_t MessageCenterImpl::NotificationCount() const {
239 return notification_list_
->NotificationCount();
242 size_t MessageCenterImpl::UnreadNotificationCount() const {
243 return notification_list_
->unread_count();
246 bool MessageCenterImpl::HasPopupNotifications() const {
247 return notification_list_
->HasPopupNotifications();
250 bool MessageCenterImpl::HasNotification(const std::string
& id
) {
251 return notification_list_
->HasNotification(id
);
254 bool MessageCenterImpl::IsQuietMode() const {
255 return notification_list_
->quiet_mode();
258 bool MessageCenterImpl::HasClickedListener(const std::string
& id
) {
259 NotificationDelegate
* delegate
=
260 notification_list_
->GetNotificationDelegate(id
);
261 return delegate
&& delegate
->HasClickedListener();
264 const NotificationList::Notifications
& MessageCenterImpl::GetNotifications() {
265 return notification_list_
->GetNotifications();
268 NotificationList::PopupNotifications
269 MessageCenterImpl::GetPopupNotifications() {
270 return notification_list_
->GetPopupNotifications();
273 //------------------------------------------------------------------------------
274 // Client code interface.
275 void MessageCenterImpl::AddNotification(scoped_ptr
<Notification
> notification
) {
276 DCHECK(notification
.get());
278 // Sometimes the notification can be added with the same id and the
279 // |notification_list| will replace the notification instead of adding new.
280 // This is essentially an update rather than addition.
281 const std::string
& id
= notification
->id();
282 bool already_exists
= notification_list_
->HasNotification(id
);
283 notification_list_
->AddNotification(notification
.Pass());
285 if (already_exists
) {
287 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
290 MessageCenterObserver
, observer_list_
, OnNotificationAdded(id
));
294 void MessageCenterImpl::UpdateNotification(
295 const std::string
& old_id
,
296 scoped_ptr
<Notification
> new_notification
) {
297 std::string new_id
= new_notification
->id();
298 notification_list_
->UpdateNotificationMessage(old_id
,
299 new_notification
.Pass());
300 if (old_id
== new_id
) {
302 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(new_id
));
304 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
305 OnNotificationRemoved(old_id
, false));
306 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
307 OnNotificationAdded(new_id
));
311 void MessageCenterImpl::RemoveNotification(const std::string
& id
,
313 if (!HasNotification(id
))
316 NotificationDelegate
* delegate
=
317 notification_list_
->GetNotificationDelegate(id
);
319 delegate
->Close(by_user
);
321 // In many cases |id| is a reference to an existing notification instance
322 // but the instance can be destructed in RemoveNotification(). Hence
323 // copies the id explicitly here.
324 std::string
copied_id(id
);
325 notification_list_
->RemoveNotification(copied_id
);
326 FOR_EACH_OBSERVER(MessageCenterObserver
,
328 OnNotificationRemoved(copied_id
, by_user
));
331 void MessageCenterImpl::RemoveAllNotifications(bool by_user
) {
332 const NotificationList::Notifications
& notifications
=
333 notification_list_
->GetNotifications();
334 std::set
<std::string
> ids
;
335 for (NotificationList::Notifications::const_iterator iter
=
336 notifications
.begin(); iter
!= notifications
.end(); ++iter
) {
337 ids
.insert((*iter
)->id());
339 notification_list_
->RemoveAllNotifications();
341 for (std::set
<std::string
>::const_iterator iter
= ids
.begin();
342 iter
!= ids
.end(); ++iter
) {
343 FOR_EACH_OBSERVER(MessageCenterObserver
,
345 OnNotificationRemoved(*iter
, by_user
));
349 void MessageCenterImpl::SetNotificationIcon(const std::string
& notification_id
,
350 const gfx::Image
& image
) {
351 if (notification_list_
->SetNotificationIcon(notification_id
, image
)) {
352 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
353 OnNotificationUpdated(notification_id
));
357 void MessageCenterImpl::SetNotificationImage(const std::string
& notification_id
,
358 const gfx::Image
& image
) {
359 if (notification_list_
->SetNotificationImage(notification_id
, image
)) {
360 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
361 OnNotificationUpdated(notification_id
));
365 void MessageCenterImpl::SetNotificationButtonIcon(
366 const std::string
& notification_id
, int button_index
,
367 const gfx::Image
& image
) {
368 if (!HasNotification(notification_id
))
370 if (notification_list_
->SetNotificationButtonIcon(notification_id
,
371 button_index
, image
)) {
372 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
373 OnNotificationUpdated(notification_id
));
377 void MessageCenterImpl::DisableNotificationsByExtension(
378 const std::string
& id
) {
380 delegate_
->DisableExtension(id
);
382 NotificationList::Notifications notifications
=
383 notification_list_
->GetNotificationsByExtension(id
);
384 for (NotificationList::Notifications::const_iterator iter
=
385 notifications
.begin(); iter
!= notifications
.end();) {
386 std::string id
= (*iter
)->id();
388 RemoveNotification(id
, false);
392 void MessageCenterImpl::DisableNotificationsByUrl(const std::string
& id
) {
394 delegate_
->DisableNotificationsFromSource(id
);
396 NotificationList::Notifications notifications
=
397 notification_list_
->GetNotificationsBySource(id
);
398 for (NotificationList::Notifications::const_iterator iter
=
399 notifications
.begin(); iter
!= notifications
.end();) {
400 std::string id
= (*iter
)->id();
402 RemoveNotification(id
, false);
406 void MessageCenterImpl::ShowNotificationSettings(const std::string
& id
) {
408 delegate_
->ShowSettings(id
);
411 void MessageCenterImpl::ExpandNotification(const std::string
& id
) {
412 if (!HasNotification(id
))
414 notification_list_
->MarkNotificationAsExpanded(id
);
415 FOR_EACH_OBSERVER(MessageCenterObserver
, observer_list_
,
416 OnNotificationUpdated(id
));
419 void MessageCenterImpl::ClickOnNotification(const std::string
& id
) {
420 if (!HasNotification(id
))
422 if (HasPopupNotifications())
423 MarkSinglePopupAsShown(id
, true);
424 NotificationDelegate
* delegate
=
425 notification_list_
->GetNotificationDelegate(id
);
429 MessageCenterObserver
, observer_list_
, OnNotificationClicked(id
));
432 void MessageCenterImpl::ClickOnNotificationButton(const std::string
& id
,
434 if (!HasNotification(id
))
436 if (HasPopupNotifications())
437 MarkSinglePopupAsShown(id
, true);
438 NotificationDelegate
* delegate
=
439 notification_list_
->GetNotificationDelegate(id
);
441 delegate
->ButtonClick(button_index
);
443 MessageCenterObserver
, observer_list_
, OnNotificationButtonClicked(
447 void MessageCenterImpl::MarkSinglePopupAsShown(const std::string
& id
,
448 bool mark_notification_as_read
) {
449 if (!HasNotification(id
))
451 notification_list_
->MarkSinglePopupAsShown(id
, mark_notification_as_read
);
453 MessageCenterObserver
, observer_list_
, OnNotificationUpdated(id
));
456 void MessageCenterImpl::DisplayedNotification(const std::string
& id
) {
457 if (!HasNotification(id
))
460 if (HasPopupNotifications())
461 notification_list_
->MarkSinglePopupAsDisplayed(id
);
462 NotificationDelegate
* delegate
=
463 notification_list_
->GetNotificationDelegate(id
);
467 MessageCenterObserver
, observer_list_
, OnNotificationDisplayed(id
));
470 void MessageCenterImpl::SetNotifierSettingsProvider(
471 NotifierSettingsProvider
* provider
) {
472 settings_provider_
= provider
;
475 NotifierSettingsProvider
* MessageCenterImpl::GetNotifierSettingsProvider() {
476 return settings_provider_
;
479 void MessageCenterImpl::SetQuietMode(bool in_quiet_mode
) {
480 notification_list_
->SetQuietMode(in_quiet_mode
);
483 void MessageCenterImpl::EnterQuietModeWithExpire(
484 const base::TimeDelta
& expires_in
) {
485 notification_list_
->EnterQuietModeWithExpire(expires_in
);
488 void MessageCenterImpl::RestartPopupTimers() {
489 if (popup_timers_controller_
.get())
490 popup_timers_controller_
->StartAll();
493 void MessageCenterImpl::PausePopupTimers() {
494 if (popup_timers_controller_
.get())
495 popup_timers_controller_
->PauseAll();
498 void MessageCenterImpl::DisableTimersForTest() {
499 popup_timers_controller_
.reset();
502 } // namespace message_center