1 // Copyright 2016 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.
4
5 #include "ui/message_center/popup_timers_controller.h"
6
7 #include <algorithm>
8
9 #include "base/stl_util.h"
10 #include "ui/message_center/public/cpp/message_center_constants.h"
11
12 namespace message_center {
13
14 namespace {
15
UseHighPriorityDelay(Notification * notification)16 bool UseHighPriorityDelay(Notification* notification) {
17 // Web Notifications are given a longer on-screen time on non-Chrome OS
18 // platforms as there is no notification center to dismiss them to.
19 #if defined(OS_CHROMEOS)
20 const bool use_high_priority_delay =
21 notification->priority() > DEFAULT_PRIORITY;
22 #else
23 const bool use_high_priority_delay =
24 notification->priority() > DEFAULT_PRIORITY ||
25 notification->notifier_id().type == NotifierType::WEB_PAGE;
26 #endif
27
28 return use_high_priority_delay;
29 }
30
31 } // namespace
32
33 // Timeout values used to dismiss notifications automatically after they are
34 // shown.
35 int notification_timeout_default_seconds_ = kAutocloseDefaultDelaySeconds;
36 int notification_timeout_high_priority_seconds_ =
37 kAutocloseHighPriorityDelaySeconds;
38
PopupTimersController(MessageCenter * message_center)39 PopupTimersController::PopupTimersController(MessageCenter* message_center)
40 : message_center_(message_center) {
41 message_center_->AddObserver(this);
42 }
43
~PopupTimersController()44 PopupTimersController::~PopupTimersController() {
45 message_center_->RemoveObserver(this);
46 }
47
StartTimer(const std::string & id,const base::TimeDelta & timeout)48 void PopupTimersController::StartTimer(const std::string& id,
49 const base::TimeDelta& timeout) {
50 PopupTimerCollection::const_iterator iter = popup_timers_.find(id);
51 if (iter != popup_timers_.end()) {
52 DCHECK(iter->second);
53 iter->second->Start();
54 return;
55 }
56
57 std::unique_ptr<PopupTimer> timer(new PopupTimer(id, timeout, AsWeakPtr()));
58
59 timer->Start();
60 popup_timers_.emplace(id, std::move(timer));
61 }
62
StartAll()63 void PopupTimersController::StartAll() {
64 for (const auto& iter : popup_timers_)
65 iter.second->Start();
66 }
67
PauseAll()68 void PopupTimersController::PauseAll() {
69 for (const auto& iter : popup_timers_)
70 iter.second->Pause();
71 }
72
CancelTimer(const std::string & id)73 void PopupTimersController::CancelTimer(const std::string& id) {
74 popup_timers_.erase(id);
75 }
76
SetNotificationTimeouts(int default_timeout,int high_priority_timeout)77 void PopupTimersController::SetNotificationTimeouts(int default_timeout,
78 int high_priority_timeout) {
79 notification_timeout_default_seconds_ = default_timeout;
80 notification_timeout_high_priority_seconds_ = high_priority_timeout;
81 }
82
CancelAll()83 void PopupTimersController::CancelAll() {
84 popup_timers_.clear();
85 }
86
TimerFinished(const std::string & id)87 void PopupTimersController::TimerFinished(const std::string& id) {
88 if (!base::Contains(popup_timers_, id))
89 return;
90
91 CancelTimer(id);
92 message_center_->MarkSinglePopupAsShown(id, false);
93 }
94
GetTimeoutForNotification(Notification * notification)95 base::TimeDelta PopupTimersController::GetTimeoutForNotification(
96 Notification* notification) {
97 return base::TimeDelta::FromSeconds(
98 UseHighPriorityDelay(notification)
99 ? notification_timeout_high_priority_seconds_
100 : notification_timeout_default_seconds_);
101 }
102
GetNotificationTimeoutDefault()103 int PopupTimersController::GetNotificationTimeoutDefault() {
104 return notification_timeout_default_seconds_;
105 }
106
OnNotificationDisplayed(const std::string & id,const DisplaySource source)107 void PopupTimersController::OnNotificationDisplayed(
108 const std::string& id,
109 const DisplaySource source) {
110 OnNotificationUpdated(id);
111 }
112
OnNotificationUpdated(const std::string & id)113 void PopupTimersController::OnNotificationUpdated(const std::string& id) {
114 NotificationList::PopupNotifications popup_notifications =
115 message_center_->GetPopupNotifications();
116
117 if (popup_notifications.empty()) {
118 CancelAll();
119 return;
120 }
121
122 auto iter = popup_notifications.begin();
123 for (; iter != popup_notifications.end(); ++iter) {
124 if ((*iter)->id() == id)
125 break;
126 }
127
128 if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
129 CancelTimer(id);
130 return;
131 }
132
133 auto timer = popup_timers_.find(id);
134 // The timer must already have been started and not be running. Relies on
135 // the invariant that |popup_timers_| only contains timers that have been
136 // started.
137 bool was_paused = timer != popup_timers_.end() && !timer->second->IsRunning();
138 CancelTimer(id);
139 StartTimer(id, GetTimeoutForNotification(*iter));
140
141 // If a timer was paused before, pause it afterwards as well.
142 // See crbug.com/710298
143 if (was_paused) {
144 auto timer = popup_timers_.find(id);
145 timer->second->Pause();
146 }
147 }
148
OnNotificationRemoved(const std::string & id,bool by_user)149 void PopupTimersController::OnNotificationRemoved(const std::string& id,
150 bool by_user) {
151 CancelTimer(id);
152 }
153
154 } // namespace message_center
155