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