OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/message_center/notification_list.h" | 5 #include "ui/message_center/notification_list.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/stl_util.h" | |
12 #include "base/time/time.h" | 11 #include "base/time/time.h" |
13 #include "base/values.h" | 12 #include "base/values.h" |
14 #include "ui/gfx/image/image.h" | 13 #include "ui/gfx/image/image.h" |
15 #include "ui/message_center/message_center.h" | 14 #include "ui/message_center/message_center.h" |
16 #include "ui/message_center/message_center_style.h" | 15 #include "ui/message_center/message_center_style.h" |
17 #include "ui/message_center/notification.h" | 16 #include "ui/message_center/notification.h" |
18 #include "ui/message_center/notification_blocker.h" | 17 #include "ui/message_center/notification_blocker.h" |
19 #include "ui/message_center/notification_types.h" | 18 #include "ui/message_center/notification_types.h" |
20 | 19 |
21 namespace message_center { | 20 namespace message_center { |
22 | 21 |
23 namespace { | 22 namespace { |
24 | 23 |
25 bool ShouldShowNotificationAsPopup( | 24 bool ShouldShowNotificationAsPopup( |
26 const Notification& notification, | 25 const Notification& notification, |
27 const NotificationBlockers& blockers) { | 26 const NotificationBlockers& blockers) { |
28 for (size_t i = 0; i < blockers.size(); ++i) { | 27 for (const auto& blocker : blockers) { |
29 if (!blockers[i]->ShouldShowNotificationAsPopup(notification)) | 28 if (!blocker->ShouldShowNotificationAsPopup(notification)) |
30 return false; | 29 return false; |
31 } | 30 } |
32 return true; | 31 return true; |
33 } | 32 } |
34 | 33 |
35 } // namespace | 34 } // namespace |
36 | 35 |
37 bool ComparePriorityTimestampSerial::operator()(Notification* n1, | |
38 Notification* n2) { | |
39 if (n1->priority() > n2->priority()) // Higher pri go first. | |
40 return true; | |
41 if (n1->priority() < n2->priority()) | |
42 return false; | |
43 return CompareTimestampSerial()(n1, n2); | |
44 } | |
45 | |
46 bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) { | |
47 if (n1->timestamp() > n2->timestamp()) // Newer come first. | |
48 return true; | |
49 if (n1->timestamp() < n2->timestamp()) | |
50 return false; | |
51 if (n1->serial_number() > n2->serial_number()) // Newer come first. | |
52 return true; | |
53 if (n1->serial_number() < n2->serial_number()) | |
54 return false; | |
55 return false; | |
56 } | |
57 | |
58 NotificationList::NotificationList(MessageCenter* message_center) | 36 NotificationList::NotificationList(MessageCenter* message_center) |
59 : message_center_(message_center), | 37 : message_center_(message_center), |
60 quiet_mode_(false) { | 38 quiet_mode_(false) { |
61 } | 39 } |
62 | 40 |
63 NotificationList::~NotificationList() { | 41 NotificationList::~NotificationList() { |
64 base::STLDeleteContainerPointers(notifications_.begin(), | |
65 notifications_.end()); | |
66 } | 42 } |
67 | 43 |
68 void NotificationList::SetNotificationsShown( | 44 void NotificationList::SetNotificationsShown( |
69 const NotificationBlockers& blockers, | 45 const NotificationBlockers& blockers, |
70 std::set<std::string>* updated_ids) { | 46 std::set<std::string>* updated_ids) { |
71 Notifications notifications = GetVisibleNotifications(blockers); | 47 Notifications notifications = GetVisibleNotifications(blockers); |
72 | 48 |
73 for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) { | 49 for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) { |
74 Notification* notification = *iter; | 50 Notification* notification = *iter; |
75 bool was_popup = notification->shown_as_popup(); | 51 bool was_popup = notification->shown_as_popup(); |
76 bool was_read = notification->IsRead(); | 52 bool was_read = notification->IsRead(); |
77 if (notification->priority() < SYSTEM_PRIORITY) | 53 if (notification->priority() < SYSTEM_PRIORITY) |
78 notification->set_shown_as_popup(true); | 54 notification->set_shown_as_popup(true); |
79 notification->set_is_read(true); | 55 notification->set_is_read(true); |
80 if (updated_ids && !(was_popup && was_read)) | 56 if (updated_ids && !(was_popup && was_read)) |
81 updated_ids->insert(notification->id()); | 57 updated_ids->insert(notification->id()); |
82 } | 58 } |
83 } | 59 } |
84 | 60 |
85 void NotificationList::AddNotification( | 61 void NotificationList::AddNotification( |
86 std::unique_ptr<Notification> notification) { | 62 std::unique_ptr<Notification> notification) { |
87 PushNotification(std::move(notification)); | 63 PushNotification(std::move(notification)); |
88 } | 64 } |
89 | 65 |
90 void NotificationList::UpdateNotificationMessage( | 66 void NotificationList::UpdateNotificationMessage( |
91 const std::string& old_id, | 67 const std::string& old_id, |
92 std::unique_ptr<Notification> new_notification) { | 68 std::unique_ptr<Notification> new_notification) { |
93 Notifications::iterator iter = GetNotification(old_id); | 69 auto iter = GetNotification(old_id); |
94 if (iter == notifications_.end()) | 70 if (iter == notifications_.end()) |
95 return; | 71 return; |
96 | 72 |
97 new_notification->CopyState(*iter); | 73 new_notification->CopyState(iter->get()); |
98 | 74 |
99 // Handles priority promotion. If the notification is already dismissed but | 75 // Handles priority promotion. If the notification is already dismissed but |
100 // the updated notification has higher priority, it should re-appear as a | 76 // the updated notification has higher priority, it should re-appear as a |
101 // toast. Notifications coming from websites through the Web Notification API | 77 // toast. Notifications coming from websites through the Web Notification API |
102 // will always re-appear on update. | 78 // will always re-appear on update. |
103 if ((*iter)->priority() < new_notification->priority() || | 79 if ((*iter)->priority() < new_notification->priority() || |
104 new_notification->notifier_id().type == NotifierId::WEB_PAGE) { | 80 new_notification->notifier_id().type == NotifierId::WEB_PAGE) { |
105 new_notification->set_is_read(false); | 81 new_notification->set_is_read(false); |
106 new_notification->set_shown_as_popup(false); | 82 new_notification->set_shown_as_popup(false); |
107 } | 83 } |
108 | 84 |
109 // Do not use EraseNotification and PushNotification, since we don't want to | 85 // Do not use EraseNotification and PushNotification, since we don't want to |
110 // change unread counts nor to update is_read/shown_as_popup states. | 86 // change unread counts nor to update is_read/shown_as_popup states. |
111 Notification* old = *iter; | |
112 notifications_.erase(iter); | 87 notifications_.erase(iter); |
113 delete old; | |
114 | 88 |
115 // We really don't want duplicate IDs. | 89 // We really don't want duplicate IDs. |
116 DCHECK(GetNotification(new_notification->id()) == notifications_.end()); | 90 DCHECK(GetNotification(new_notification->id()) == notifications_.end()); |
117 notifications_.insert(new_notification.release()); | 91 notifications_.insert(std::move(new_notification)); |
118 } | 92 } |
119 | 93 |
120 void NotificationList::RemoveNotification(const std::string& id) { | 94 void NotificationList::RemoveNotification(const std::string& id) { |
121 EraseNotification(GetNotification(id)); | 95 EraseNotification(GetNotification(id)); |
122 } | 96 } |
123 | 97 |
124 NotificationList::Notifications NotificationList::GetNotificationsByNotifierId( | 98 NotificationList::Notifications NotificationList::GetNotificationsByNotifierId( |
125 const NotifierId& notifier_id) { | 99 const NotifierId& notifier_id) { |
126 Notifications notifications; | 100 Notifications notifications; |
127 for (Notifications::iterator iter = notifications_.begin(); | 101 for (const auto& notification : notifications_) { |
128 iter != notifications_.end(); ++iter) { | 102 if (notification->notifier_id() == notifier_id) |
129 if ((*iter)->notifier_id() == notifier_id) | 103 notifications.insert(notification.get()); |
130 notifications.insert(*iter); | |
131 } | 104 } |
132 return notifications; | 105 return notifications; |
133 } | 106 } |
134 | 107 |
135 bool NotificationList::SetNotificationIcon(const std::string& notification_id, | 108 bool NotificationList::SetNotificationIcon(const std::string& notification_id, |
136 const gfx::Image& image) { | 109 const gfx::Image& image) { |
137 Notifications::iterator iter = GetNotification(notification_id); | 110 auto iter = GetNotification(notification_id); |
138 if (iter == notifications_.end()) | 111 if (iter == notifications_.end()) |
139 return false; | 112 return false; |
140 (*iter)->set_icon(image); | 113 (*iter)->set_icon(image); |
141 return true; | 114 return true; |
142 } | 115 } |
143 | 116 |
144 bool NotificationList::SetNotificationImage(const std::string& notification_id, | 117 bool NotificationList::SetNotificationImage(const std::string& notification_id, |
145 const gfx::Image& image) { | 118 const gfx::Image& image) { |
146 Notifications::iterator iter = GetNotification(notification_id); | 119 auto iter = GetNotification(notification_id); |
147 if (iter == notifications_.end()) | 120 if (iter == notifications_.end()) |
148 return false; | 121 return false; |
149 (*iter)->set_image(image); | 122 (*iter)->set_image(image); |
150 return true; | 123 return true; |
151 } | 124 } |
152 | 125 |
153 bool NotificationList::SetNotificationButtonIcon( | 126 bool NotificationList::SetNotificationButtonIcon( |
154 const std::string& notification_id, int button_index, | 127 const std::string& notification_id, int button_index, |
155 const gfx::Image& image) { | 128 const gfx::Image& image) { |
156 Notifications::iterator iter = GetNotification(notification_id); | 129 auto iter = GetNotification(notification_id); |
157 if (iter == notifications_.end()) | 130 if (iter == notifications_.end()) |
158 return false; | 131 return false; |
159 (*iter)->SetButtonIcon(button_index, image); | 132 (*iter)->SetButtonIcon(button_index, image); |
160 return true; | 133 return true; |
161 } | 134 } |
162 | 135 |
163 bool NotificationList::HasNotificationOfType(const std::string& id, | 136 bool NotificationList::HasNotificationOfType(const std::string& id, |
164 const NotificationType type) { | 137 const NotificationType type) { |
165 Notifications::iterator iter = GetNotification(id); | 138 auto iter = GetNotification(id); |
166 if (iter == notifications_.end()) | 139 if (iter == notifications_.end()) |
167 return false; | 140 return false; |
168 | 141 |
169 return (*iter)->type() == type; | 142 return (*iter)->type() == type; |
170 } | 143 } |
171 | 144 |
172 bool NotificationList::HasPopupNotifications( | 145 bool NotificationList::HasPopupNotifications( |
173 const NotificationBlockers& blockers) { | 146 const NotificationBlockers& blockers) { |
174 for (Notifications::iterator iter = notifications_.begin(); | 147 for (const auto& notification : notifications_) { |
175 iter != notifications_.end(); ++iter) { | 148 if (notification->priority() < DEFAULT_PRIORITY) |
176 if ((*iter)->priority() < DEFAULT_PRIORITY) | |
177 break; | 149 break; |
178 if (!ShouldShowNotificationAsPopup(**iter, blockers)) | 150 if (!ShouldShowNotificationAsPopup(*notification.get(), blockers)) |
179 continue; | 151 continue; |
180 if (!(*iter)->shown_as_popup()) | 152 if (!notification->shown_as_popup()) |
181 return true; | 153 return true; |
182 } | 154 } |
183 return false; | 155 return false; |
184 } | 156 } |
185 | 157 |
186 NotificationList::PopupNotifications NotificationList::GetPopupNotifications( | 158 NotificationList::PopupNotifications NotificationList::GetPopupNotifications( |
187 const NotificationBlockers& blockers, | 159 const NotificationBlockers& blockers, |
188 std::list<std::string>* blocked_ids) { | 160 std::list<std::string>* blocked_ids) { |
189 PopupNotifications result; | 161 PopupNotifications result; |
190 size_t default_priority_popup_count = 0; | 162 size_t default_priority_popup_count = 0; |
191 | 163 |
192 // Collect notifications that should be shown as popups. Start from oldest. | 164 // Collect notifications that should be shown as popups. Start from oldest. |
193 for (Notifications::const_reverse_iterator iter = notifications_.rbegin(); | 165 for (auto iter = notifications_.rbegin(); iter != notifications_.rend(); |
194 iter != notifications_.rend(); iter++) { | 166 iter++) { |
195 if ((*iter)->shown_as_popup()) | 167 Notification* notification = iter->get(); |
| 168 if (notification->shown_as_popup()) |
196 continue; | 169 continue; |
197 | 170 |
198 // No popups for LOW/MIN priority. | 171 // No popups for LOW/MIN priority. |
199 if ((*iter)->priority() < DEFAULT_PRIORITY) | 172 if (notification->priority() < DEFAULT_PRIORITY) |
200 continue; | 173 continue; |
201 | 174 |
202 if (!ShouldShowNotificationAsPopup(**iter, blockers)) { | 175 if (!ShouldShowNotificationAsPopup(*notification, blockers)) { |
203 if (blocked_ids) | 176 if (blocked_ids) |
204 blocked_ids->push_back((*iter)->id()); | 177 blocked_ids->push_back(notification->id()); |
205 continue; | 178 continue; |
206 } | 179 } |
207 | 180 |
208 // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority | 181 // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority |
209 // will return at most kMaxVisiblePopupNotifications entries. If the | 182 // will return at most kMaxVisiblePopupNotifications entries. If the |
210 // popup entries are more, older entries are used. see crbug.com/165768 | 183 // popup entries are more, older entries are used. see crbug.com/165768 |
211 if ((*iter)->priority() == DEFAULT_PRIORITY && | 184 if (notification->priority() == DEFAULT_PRIORITY && |
212 default_priority_popup_count++ >= kMaxVisiblePopupNotifications) { | 185 default_priority_popup_count++ >= kMaxVisiblePopupNotifications) { |
213 continue; | 186 continue; |
214 } | 187 } |
215 | 188 |
216 result.insert(*iter); | 189 result.insert(notification); |
217 } | 190 } |
218 return result; | 191 return result; |
219 } | 192 } |
220 | 193 |
221 void NotificationList::MarkSinglePopupAsShown( | 194 void NotificationList::MarkSinglePopupAsShown( |
222 const std::string& id, bool mark_notification_as_read) { | 195 const std::string& id, bool mark_notification_as_read) { |
223 Notifications::iterator iter = GetNotification(id); | 196 auto iter = GetNotification(id); |
224 DCHECK(iter != notifications_.end()); | 197 DCHECK(iter != notifications_.end()); |
225 | 198 |
226 if ((*iter)->shown_as_popup()) | 199 if ((*iter)->shown_as_popup()) |
227 return; | 200 return; |
228 | 201 |
229 // System notification is marked as shown only when marked as read. | 202 // System notification is marked as shown only when marked as read. |
230 if ((*iter)->priority() != SYSTEM_PRIORITY || mark_notification_as_read) | 203 if ((*iter)->priority() != SYSTEM_PRIORITY || mark_notification_as_read) |
231 (*iter)->set_shown_as_popup(true); | 204 (*iter)->set_shown_as_popup(true); |
232 | 205 |
233 // The popup notification is already marked as read when it's displayed. | 206 // The popup notification is already marked as read when it's displayed. |
234 // Set the is_read() back to false if necessary. | 207 // Set the is_read() back to false if necessary. |
235 if (!mark_notification_as_read) | 208 if (!mark_notification_as_read) |
236 (*iter)->set_is_read(false); | 209 (*iter)->set_is_read(false); |
237 } | 210 } |
238 | 211 |
239 void NotificationList::MarkSinglePopupAsDisplayed(const std::string& id) { | 212 void NotificationList::MarkSinglePopupAsDisplayed(const std::string& id) { |
240 Notifications::iterator iter = GetNotification(id); | 213 auto iter = GetNotification(id); |
241 if (iter == notifications_.end()) | 214 if (iter == notifications_.end()) |
242 return; | 215 return; |
243 | 216 |
244 if ((*iter)->shown_as_popup()) | 217 if ((*iter)->shown_as_popup()) |
245 return; | 218 return; |
246 | 219 |
247 if (!(*iter)->IsRead()) | 220 if (!(*iter)->IsRead()) |
248 (*iter)->set_is_read(true); | 221 (*iter)->set_is_read(true); |
249 } | 222 } |
250 | 223 |
251 NotificationDelegate* NotificationList::GetNotificationDelegate( | 224 NotificationDelegate* NotificationList::GetNotificationDelegate( |
252 const std::string& id) { | 225 const std::string& id) { |
253 Notifications::iterator iter = GetNotification(id); | 226 auto iter = GetNotification(id); |
254 if (iter == notifications_.end()) | 227 if (iter == notifications_.end()) |
255 return NULL; | 228 return nullptr; |
256 return (*iter)->delegate(); | 229 return (*iter)->delegate(); |
257 } | 230 } |
258 | 231 |
259 void NotificationList::SetQuietMode(bool quiet_mode) { | 232 void NotificationList::SetQuietMode(bool quiet_mode) { |
260 quiet_mode_ = quiet_mode; | 233 quiet_mode_ = quiet_mode; |
261 if (quiet_mode_) { | 234 if (quiet_mode_) { |
262 for (Notifications::iterator iter = notifications_.begin(); | 235 for (auto& notification : notifications_) |
263 iter != notifications_.end(); | 236 notification->set_shown_as_popup(true); |
264 ++iter) { | |
265 (*iter)->set_shown_as_popup(true); | |
266 } | |
267 } | 237 } |
268 } | 238 } |
269 | 239 |
270 Notification* NotificationList::GetNotificationById(const std::string& id) { | 240 Notification* NotificationList::GetNotificationById(const std::string& id) { |
271 Notifications::iterator iter = GetNotification(id); | 241 auto iter = GetNotification(id); |
272 if (iter != notifications_.end()) | 242 if (iter != notifications_.end()) |
273 return *iter; | 243 return iter->get(); |
274 return NULL; | 244 return nullptr; |
275 } | 245 } |
276 | 246 |
277 NotificationList::Notifications NotificationList::GetVisibleNotifications( | 247 NotificationList::Notifications NotificationList::GetVisibleNotifications( |
278 const NotificationBlockers& blockers) const { | 248 const NotificationBlockers& blockers) const { |
279 Notifications result; | 249 Notifications result; |
280 for (Notifications::const_iterator iter = notifications_.begin(); | 250 for (const auto& notification : notifications_) { |
281 iter != notifications_.end(); ++iter) { | |
282 bool should_show = true; | 251 bool should_show = true; |
283 for (size_t i = 0; i < blockers.size(); ++i) { | 252 for (size_t i = 0; i < blockers.size(); ++i) { |
284 if (!blockers[i]->ShouldShowNotification(**iter)) { | 253 if (!blockers[i]->ShouldShowNotification(*notification.get())) { |
285 should_show = false; | 254 should_show = false; |
286 break; | 255 break; |
287 } | 256 } |
288 } | 257 } |
289 if (should_show) | 258 if (should_show) |
290 result.insert(*iter); | 259 result.insert(notification.get()); |
291 } | 260 } |
292 | 261 |
293 return result; | 262 return result; |
294 } | 263 } |
295 | 264 |
296 size_t NotificationList::NotificationCount( | 265 size_t NotificationList::NotificationCount( |
297 const NotificationBlockers& blockers) const { | 266 const NotificationBlockers& blockers) const { |
298 return GetVisibleNotifications(blockers).size(); | 267 return GetVisibleNotifications(blockers).size(); |
299 } | 268 } |
300 | 269 |
301 size_t NotificationList::UnreadCount( | 270 size_t NotificationList::UnreadCount( |
302 const NotificationBlockers& blockers) const { | 271 const NotificationBlockers& blockers) const { |
303 Notifications notifications = GetVisibleNotifications(blockers); | 272 Notifications notifications = GetVisibleNotifications(blockers); |
304 size_t unread_count = 0; | 273 size_t unread_count = 0; |
305 for (Notifications::const_iterator iter = notifications.begin(); | 274 for (Notifications::const_iterator iter = notifications.begin(); |
306 iter != notifications.end(); ++iter) { | 275 iter != notifications.end(); ++iter) { |
307 if (!(*iter)->IsRead()) | 276 if (!(*iter)->IsRead()) |
308 ++unread_count; | 277 ++unread_count; |
309 } | 278 } |
310 return unread_count; | 279 return unread_count; |
311 } | 280 } |
312 | 281 |
313 NotificationList::Notifications::iterator NotificationList::GetNotification( | 282 NotificationList::OwnedNotifications::iterator |
314 const std::string& id) { | 283 NotificationList::GetNotification(const std::string& id) { |
315 for (Notifications::iterator iter = notifications_.begin(); | 284 for (auto iter = notifications_.begin(); iter != notifications_.end(); |
316 iter != notifications_.end(); ++iter) { | 285 ++iter) { |
317 if ((*iter)->id() == id) | 286 if ((*iter)->id() == id) |
318 return iter; | 287 return iter; |
319 } | 288 } |
320 return notifications_.end(); | 289 return notifications_.end(); |
321 } | 290 } |
322 | 291 |
323 void NotificationList::EraseNotification(Notifications::iterator iter) { | 292 void NotificationList::EraseNotification(OwnedNotifications::iterator iter) { |
324 delete *iter; | |
325 notifications_.erase(iter); | 293 notifications_.erase(iter); |
326 } | 294 } |
327 | 295 |
328 void NotificationList::PushNotification( | 296 void NotificationList::PushNotification( |
329 std::unique_ptr<Notification> notification) { | 297 std::unique_ptr<Notification> notification) { |
330 // Ensure that notification.id is unique by erasing any existing | 298 // Ensure that notification.id is unique by erasing any existing |
331 // notification with the same id (shouldn't normally happen). | 299 // notification with the same id (shouldn't normally happen). |
332 Notifications::iterator iter = GetNotification(notification->id()); | 300 auto iter = GetNotification(notification->id()); |
333 bool state_inherited = false; | 301 bool state_inherited = false; |
334 if (iter != notifications_.end()) { | 302 if (iter != notifications_.end()) { |
335 notification->CopyState(*iter); | 303 notification->CopyState(iter->get()); |
336 state_inherited = true; | 304 state_inherited = true; |
337 EraseNotification(iter); | 305 EraseNotification(iter); |
338 } | 306 } |
339 // Add the notification to the the list and mark it unread and unshown. | 307 // Add the notification to the the list and mark it unread and unshown. |
340 if (!state_inherited) { | 308 if (!state_inherited) { |
341 // TODO(mukai): needs to distinguish if a notification is dismissed by | 309 // TODO(mukai): needs to distinguish if a notification is dismissed by |
342 // the quiet mode or user operation. | 310 // the quiet mode or user operation. |
343 notification->set_is_read(false); | 311 notification->set_is_read(false); |
344 notification->set_shown_as_popup(message_center_->IsMessageCenterVisible() | 312 notification->set_shown_as_popup(message_center_->IsMessageCenterVisible() |
345 || quiet_mode_ | 313 || quiet_mode_ |
346 || notification->shown_as_popup()); | 314 || notification->shown_as_popup()); |
347 } | 315 } |
348 // Take ownership. The notification can only be removed from the list | 316 // Take ownership. The notification can only be removed from the list |
349 // in EraseNotification(), which will delete it. | 317 // in EraseNotification(), which will delete it. |
350 notifications_.insert(notification.release()); | 318 notifications_.insert(std::move(notification)); |
351 } | 319 } |
352 | 320 |
353 } // namespace message_center | 321 } // namespace message_center |
OLD | NEW |