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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/stl_util.h" |
9 #include "base/time.h" | 10 #include "base/time.h" |
10 #include "base/values.h" | 11 #include "base/values.h" |
11 #include "ui/message_center/notification.h" | 12 #include "ui/message_center/notification.h" |
| 13 #include "ui/message_center/notification_types.h" |
12 | 14 |
13 namespace message_center { | 15 namespace message_center { |
14 | 16 |
| 17 bool ComparePriorityTimestampSerial::operator()(Notification* n1, |
| 18 Notification* n2) { |
| 19 if (n1->priority() > n2->priority()) // Higher pri go first. |
| 20 return true; |
| 21 if (n1->priority() < n2->priority()) |
| 22 return false; |
| 23 return CompareTimestampSerial()(n1, n2); |
| 24 } |
| 25 |
| 26 bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) { |
| 27 if (n1->timestamp() > n2->timestamp()) // Newer come first. |
| 28 return true; |
| 29 if (n1->timestamp() < n2->timestamp()) |
| 30 return false; |
| 31 if (n1->serial_number() > n2->serial_number()) // Newer come first. |
| 32 return true; |
| 33 if (n1->serial_number() < n2->serial_number()) |
| 34 return false; |
| 35 return false; |
| 36 } |
| 37 |
15 const size_t NotificationList::kMaxVisibleMessageCenterNotifications = 100; | 38 const size_t NotificationList::kMaxVisibleMessageCenterNotifications = 100; |
16 const size_t NotificationList::kMaxVisiblePopupNotifications = 2; | 39 const size_t NotificationList::kMaxVisiblePopupNotifications = 2; |
17 | 40 |
18 NotificationList::NotificationList(Delegate* delegate) | 41 NotificationList::NotificationList(Delegate* delegate) |
19 : delegate_(delegate), | 42 : delegate_(delegate), |
20 message_center_visible_(false), | 43 message_center_visible_(false), |
21 unread_count_(0), | 44 unread_count_(0), |
22 quiet_mode_(false) { | 45 quiet_mode_(false) { |
23 } | 46 } |
24 | 47 |
25 NotificationList::~NotificationList() { | 48 NotificationList::~NotificationList() { |
| 49 STLDeleteContainerPointers(notifications_.begin(), notifications_.end()); |
26 } | 50 } |
27 | 51 |
28 void NotificationList::SetMessageCenterVisible(bool visible) { | 52 void NotificationList::SetMessageCenterVisible(bool visible) { |
29 if (message_center_visible_ == visible) | 53 if (message_center_visible_ == visible) |
30 return; | 54 return; |
31 message_center_visible_ = visible; | 55 message_center_visible_ = visible; |
32 // When the center appears, mark all notifications as shown, and | 56 // When the center appears, mark all notifications as shown, and |
33 // when the center is hidden, clear the unread count, and mark all | 57 // when the center is hidden, clear the unread count, and mark all |
34 // notifications as read. | 58 // notifications as read. |
35 if (!visible) | 59 if (!visible) |
36 unread_count_ = 0; | 60 unread_count_ = 0; |
37 | 61 |
38 for (NotificationMap::iterator mapiter = notifications_.begin(); | 62 for (Notifications::iterator iter = notifications_.begin(); |
39 mapiter != notifications_.end(); ++mapiter) { | 63 iter != notifications_.end(); ++iter) { |
40 for (Notifications::iterator iter = mapiter->second.begin(); | 64 if (visible) |
41 iter != mapiter->second.end(); ++iter) { | 65 (*iter)->set_shown_as_popup(true); |
42 if (visible) | 66 else |
43 iter->shown_as_popup = true; | 67 (*iter)->set_is_read(true); |
44 else | |
45 iter->is_read = true; | |
46 } | |
47 } | 68 } |
48 } | 69 } |
49 | 70 |
50 void NotificationList::AddNotification( | 71 void NotificationList::AddNotification( |
51 ui::notifications::NotificationType type, | 72 NotificationType type, |
52 const std::string& id, | 73 const std::string& id, |
53 const string16& title, | 74 const string16& title, |
54 const string16& message, | 75 const string16& message, |
55 const string16& display_source, | 76 const string16& display_source, |
56 const std::string& extension_id, | 77 const std::string& extension_id, |
57 const DictionaryValue* optional_fields) { | 78 const DictionaryValue* optional_fields) { |
58 Notification notification; | 79 scoped_ptr<Notification> notification( |
59 notification.type = type; | 80 new Notification(type, id, title, message, display_source, extension_id, |
60 notification.id = id; | 81 optional_fields)); |
61 notification.title = title; | 82 PushNotification(notification.Pass()); |
62 notification.message = message; | |
63 notification.display_source = display_source; | |
64 notification.extension_id = extension_id; | |
65 | |
66 // Initialize primitive fields before unpacking optional fields. | |
67 notification.priority = ui::notifications::DEFAULT_PRIORITY; | |
68 | |
69 UnpackOptionalFields(optional_fields, ¬ification); | |
70 | |
71 PushNotification(notification); | |
72 } | |
73 | |
74 void NotificationList::UnpackOptionalFields(const DictionaryValue* fields, | |
75 Notification* notification) { | |
76 if (!fields) | |
77 return; | |
78 | |
79 fields->GetInteger(ui::notifications::kPriorityKey, ¬ification->priority); | |
80 if (fields->HasKey(ui::notifications::kTimestampKey)) { | |
81 double time_double; | |
82 fields->GetDouble(ui::notifications::kTimestampKey, &time_double); | |
83 notification->timestamp = base::Time::FromJsTime(time_double); | |
84 } | |
85 if (fields->HasKey(ui::notifications::kButtonOneTitleKey) || | |
86 fields->HasKey(ui::notifications::kButtonOneIconUrlKey)) { | |
87 string16 title; | |
88 string16 icon; | |
89 if (fields->GetString(ui::notifications::kButtonOneTitleKey, &title) || | |
90 fields->GetString(ui::notifications::kButtonOneIconUrlKey, &icon)) { | |
91 notification->button_titles.push_back(title); | |
92 notification->button_icons.push_back(gfx::ImageSkia()); | |
93 if (fields->GetString(ui::notifications::kButtonTwoTitleKey, &title) || | |
94 fields->GetString(ui::notifications::kButtonTwoIconUrlKey, &icon)) { | |
95 notification->button_titles.push_back(title); | |
96 notification->button_icons.push_back(gfx::ImageSkia()); | |
97 } | |
98 } | |
99 } | |
100 fields->GetString(ui::notifications::kExpandedMessageKey, | |
101 ¬ification->expanded_message); | |
102 if (fields->HasKey(ui::notifications::kItemsKey)) { | |
103 const ListValue* items; | |
104 CHECK(fields->GetList(ui::notifications::kItemsKey, &items)); | |
105 for (size_t i = 0; i < items->GetSize(); ++i) { | |
106 string16 title; | |
107 string16 message; | |
108 const base::DictionaryValue* item; | |
109 items->GetDictionary(i, &item); | |
110 item->GetString(ui::notifications::kItemTitleKey, &title); | |
111 item->GetString(ui::notifications::kItemMessageKey, &message); | |
112 notification->items.push_back(NotificationItem(title, message)); | |
113 } | |
114 } | |
115 } | 83 } |
116 | 84 |
117 void NotificationList::UpdateNotificationMessage( | 85 void NotificationList::UpdateNotificationMessage( |
118 const std::string& old_id, | 86 const std::string& old_id, |
119 const std::string& new_id, | 87 const std::string& new_id, |
120 const string16& title, | 88 const string16& title, |
121 const string16& message, | 89 const string16& message, |
122 const base::DictionaryValue* optional_fields) { | 90 const base::DictionaryValue* optional_fields) { |
123 Notifications::iterator iter; | 91 Notifications::iterator iter = GetNotification(old_id); |
124 if (!GetNotification(old_id, &iter)) | 92 if (iter == notifications_.end()) |
125 return; | 93 return; |
126 // Copy and update notification, then move it to the front of the list. | 94 |
127 Notification notification(*iter); | 95 // Copy and update a notification. It has an effect of setting a new timestamp |
128 notification.id = new_id; | 96 // if not overridden by optional_fields |
129 notification.title = title; | 97 scoped_ptr<Notification> notification( |
130 notification.message = message; | 98 new Notification((*iter)->type(), |
131 UnpackOptionalFields(optional_fields, ¬ification); | 99 new_id, |
| 100 title, |
| 101 message, |
| 102 (*iter)->display_source(), |
| 103 (*iter)->extension_id(), |
| 104 optional_fields)); |
132 EraseNotification(iter); | 105 EraseNotification(iter); |
133 PushNotification(notification); | 106 PushNotification(notification.Pass()); |
134 } | 107 } |
135 | 108 |
136 bool NotificationList::RemoveNotification(const std::string& id) { | 109 void NotificationList::RemoveNotification(const std::string& id) { |
137 Notifications::iterator iter; | 110 EraseNotification(GetNotification(id)); |
138 if (!GetNotification(id, &iter)) | |
139 return false; | |
140 EraseNotification(iter); | |
141 return true; | |
142 } | 111 } |
143 | 112 |
144 void NotificationList::RemoveAllNotifications() { | 113 void NotificationList::RemoveAllNotifications() { |
145 notifications_.clear(); | 114 for (Notifications::iterator loopiter = notifications_.begin(); |
| 115 loopiter != notifications_.end(); ) { |
| 116 Notifications::iterator curiter = loopiter++; |
| 117 EraseNotification(curiter); |
| 118 } |
146 unread_count_ = 0; | 119 unread_count_ = 0; |
147 } | 120 } |
148 | 121 |
149 void NotificationList::SendRemoveNotificationsBySource( | 122 void NotificationList::SendRemoveNotificationsBySource( |
150 const std::string& id) { | 123 const std::string& id) { |
151 Notifications::iterator source_iter; | 124 Notifications::iterator source_iter = GetNotification(id); |
152 if (!GetNotification(id, &source_iter)) | 125 if (source_iter == notifications_.end()) |
153 return; | 126 return; |
154 string16 display_source = source_iter->display_source; | 127 string16 display_source = (*source_iter)->display_source(); |
155 for (NotificationMap::iterator mapiter = notifications_.begin(); | 128 |
156 mapiter != notifications_.end(); ++mapiter) { | 129 for (Notifications::iterator loopiter = notifications_.begin(); |
157 for (Notifications::iterator loopiter = mapiter->second.begin(); | 130 loopiter != notifications_.end(); ) { |
158 loopiter != mapiter->second.end(); ) { | 131 Notifications::iterator curiter = loopiter++; |
159 Notifications::iterator curiter = loopiter++; | 132 if ((*curiter)->display_source() == display_source) |
160 if (curiter->display_source == display_source) | 133 delegate_->SendRemoveNotification((*curiter)->id()); |
161 delegate_->SendRemoveNotification(curiter->id); | |
162 } | |
163 } | 134 } |
164 } | 135 } |
165 | 136 |
166 void NotificationList::SendRemoveNotificationsByExtension( | 137 void NotificationList::SendRemoveNotificationsByExtension( |
167 const std::string& id) { | 138 const std::string& id) { |
168 Notifications::iterator source_iter; | 139 Notifications::iterator source_iter = GetNotification(id); |
169 if (!GetNotification(id, &source_iter)) | 140 if (source_iter == notifications_.end()) |
170 return; | 141 return; |
171 std::string extension_id = source_iter->extension_id; | 142 std::string extension_id = (*source_iter)->extension_id(); |
172 for (NotificationMap::iterator mapiter = notifications_.begin(); | 143 for (Notifications::iterator loopiter = notifications_.begin(); |
173 mapiter != notifications_.end(); ++mapiter) { | 144 loopiter != notifications_.end(); ) { |
174 for (Notifications::iterator loopiter = mapiter->second.begin(); | 145 Notifications::iterator curiter = loopiter++; |
175 loopiter != mapiter->second.end(); ) { | 146 if ((*curiter)->extension_id() == extension_id) |
176 Notifications::iterator curiter = loopiter++; | 147 delegate_->SendRemoveNotification((*curiter)->id()); |
177 if (curiter->extension_id == extension_id) | |
178 delegate_->SendRemoveNotification(curiter->id); | |
179 } | |
180 } | 148 } |
181 } | 149 } |
182 | 150 |
183 bool NotificationList::SetNotificationIcon(const std::string& notification_id, | 151 bool NotificationList::SetNotificationIcon(const std::string& notification_id, |
184 const gfx::ImageSkia& image) { | 152 const gfx::ImageSkia& image) { |
185 Notifications::iterator iter; | 153 Notifications::iterator iter = GetNotification(notification_id); |
186 if (!GetNotification(notification_id, &iter)) | 154 if (iter == notifications_.end()) |
187 return false; | 155 return false; |
188 iter->primary_icon = image; | 156 (*iter)->set_primary_icon(image); |
189 return true; | 157 return true; |
190 } | 158 } |
191 | 159 |
192 bool NotificationList::SetNotificationImage(const std::string& notification_id, | 160 bool NotificationList::SetNotificationImage(const std::string& notification_id, |
193 const gfx::ImageSkia& image) { | 161 const gfx::ImageSkia& image) { |
194 Notifications::iterator iter; | 162 Notifications::iterator iter = GetNotification(notification_id); |
195 if (!GetNotification(notification_id, &iter)) | 163 if (iter == notifications_.end()) |
196 return false; | 164 return false; |
197 iter->image = image; | 165 (*iter)->set_image(image); |
198 return true; | 166 return true; |
199 } | 167 } |
200 | 168 |
201 bool NotificationList::SetNotificationButtonIcon( | 169 bool NotificationList::SetNotificationButtonIcon( |
202 const std::string& notification_id, int button_index, | 170 const std::string& notification_id, int button_index, |
203 const gfx::ImageSkia& image) { | 171 const gfx::ImageSkia& image) { |
204 Notifications::iterator iter; | 172 Notifications::iterator iter = GetNotification(notification_id); |
205 if (!GetNotification(notification_id, &iter) || | 173 if (iter == notifications_.end()) |
206 static_cast<size_t>(button_index) >= iter->button_icons.size()) | |
207 return false; | 174 return false; |
208 iter->button_icons[button_index] = image; | 175 return (*iter)->SetButtonIcon(button_index, image); |
209 return true; | |
210 } | 176 } |
211 | 177 |
212 bool NotificationList::HasNotification(const std::string& id) { | 178 bool NotificationList::HasNotification(const std::string& id) { |
213 Notifications::iterator dummy; | 179 return GetNotification(id) != notifications_.end(); |
214 return GetNotification(id, &dummy); | |
215 } | 180 } |
216 | 181 |
217 bool NotificationList::HasPopupNotifications() { | 182 bool NotificationList::HasPopupNotifications() { |
218 for (int i = ui::notifications::DEFAULT_PRIORITY; | 183 for (Notifications::iterator iter = notifications_.begin(); |
219 i <= ui::notifications::MAX_PRIORITY; ++i) { | 184 iter != notifications_.end(); ++iter) { |
220 Notifications notifications = notifications_[i]; | 185 if ((*iter)->priority() < DEFAULT_PRIORITY) |
221 if (!notifications.empty() && !notifications.front().shown_as_popup) | 186 break; |
| 187 if (!(*iter)->shown_as_popup()) |
222 return true; | 188 return true; |
223 } | 189 } |
224 return false; | 190 return false; |
225 } | 191 } |
226 | 192 |
227 void NotificationList::GetPopupNotifications( | 193 NotificationList::PopupNotifications NotificationList::GetPopupNotifications() { |
228 NotificationList::Notifications* notifications) { | 194 PopupNotifications result; |
229 typedef std::pair<Notifications::iterator, Notifications::iterator> | 195 size_t default_priority_popup_count = 0; |
230 NotificationRange; | 196 |
231 // In the popup, latest should come earlier. | 197 // Collect notifications that should be shown as popups. Start from oldest. |
232 std::list<NotificationRange> iters; | 198 for (Notifications::const_reverse_iterator iter = notifications_.rbegin(); |
233 for (int i = ui::notifications::DEFAULT_PRIORITY; | 199 iter != notifications_.rend(); iter++) { |
234 i <= ui::notifications::MAX_PRIORITY; ++i) { | 200 |
235 Notifications::iterator first, last; | 201 if ((*iter)->shown_as_popup()) |
236 GetPopupIterators(i, &first, &last); | 202 continue; |
237 if (first != last) | 203 |
238 iters.push_back(make_pair(first, last)); | 204 // No popups for LOW/MIN priority. |
| 205 if ((*iter)->priority() < DEFAULT_PRIORITY) |
| 206 break; |
| 207 |
| 208 // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority |
| 209 // will return at most kMaxVisiblePopupNotifications entries. If the |
| 210 // popup entries are more, older entries are used. see crbug.com/165768 |
| 211 if ((*iter)->priority() == DEFAULT_PRIORITY && |
| 212 default_priority_popup_count++ >= kMaxVisiblePopupNotifications) { |
| 213 continue; |
| 214 } |
| 215 |
| 216 result.insert(*iter); |
239 } | 217 } |
240 notifications->clear(); | 218 return result; |
241 while (!iters.empty()) { | |
242 std::list<NotificationRange>::iterator max_iter = iters.begin(); | |
243 std::list<NotificationRange>::iterator iter = max_iter; | |
244 iter++; | |
245 for (; iter != iters.end(); ++iter) { | |
246 if (max_iter->first->timestamp < iter->first->timestamp) | |
247 max_iter = iter; | |
248 } | |
249 notifications->push_back(*(max_iter->first)); | |
250 ++(max_iter->first); | |
251 if (max_iter->first == max_iter->second) | |
252 iters.erase(max_iter); | |
253 } | |
254 } | 219 } |
255 | 220 |
256 void NotificationList::MarkPopupsAsShown(int priority) { | 221 void NotificationList::MarkPopupsAsShown(int priority) { |
257 Notifications::iterator first, last; | 222 PopupNotifications popups = GetPopupNotifications(); |
258 GetPopupIterators(priority, &first, &last); | 223 for (PopupNotifications::iterator iter = popups.begin(); |
259 for (Notifications::iterator iter = first; iter != last; ++iter) | 224 iter != popups.end(); ++iter) { |
260 iter->shown_as_popup = true; | 225 if ((*iter)->priority() == priority) |
| 226 (*iter)->set_shown_as_popup(true); |
| 227 } |
261 } | 228 } |
262 | 229 |
263 void NotificationList::MarkSinglePopupAsShown( | 230 void NotificationList::MarkSinglePopupAsShown( |
264 const std::string& id, bool mark_notification_as_read) { | 231 const std::string& id, bool mark_notification_as_read) { |
265 Notifications::iterator iter; | 232 Notifications::iterator iter = GetNotification(id); |
266 if (!GetNotification(id, &iter)) | 233 DCHECK(iter != notifications_.end()); |
| 234 |
| 235 if ((*iter)->shown_as_popup()) |
267 return; | 236 return; |
268 | 237 |
269 if (iter->shown_as_popup) | 238 (*iter)->set_shown_as_popup(true); |
270 return; | |
271 | 239 |
272 // Moves the item to the beginning of the already-shown items. | |
273 Notification notification = *iter; | |
274 notification.shown_as_popup = true; | |
275 if (mark_notification_as_read) { | 240 if (mark_notification_as_read) { |
276 --unread_count_; | 241 --unread_count_; |
277 notification.is_read = true; | 242 (*iter)->set_is_read(true); |
278 } | 243 } |
279 | |
280 notifications_[notification.priority].erase(iter); | |
281 for (Notifications::iterator iter2 = | |
282 notifications_[notification.priority].begin(); | |
283 iter2 != notifications_[notification.priority].end(); iter2++) { | |
284 if (iter2->shown_as_popup) { | |
285 notifications_[notification.priority].insert(iter2, notification); | |
286 return; | |
287 } | |
288 } | |
289 | |
290 // No notifications are already shown as popup, so just re-adding at the end | |
291 // of the list. | |
292 notifications_[notification.priority].push_back(notification); | |
293 } | 244 } |
294 | 245 |
295 void NotificationList::SetQuietMode(bool quiet_mode) { | 246 void NotificationList::SetQuietMode(bool quiet_mode) { |
296 SetQuietModeInternal(quiet_mode); | 247 SetQuietModeInternal(quiet_mode); |
297 quiet_mode_timer_.reset(); | 248 quiet_mode_timer_.reset(); |
298 } | 249 } |
299 | 250 |
300 void NotificationList::EnterQuietModeWithExpire( | 251 void NotificationList::EnterQuietModeWithExpire( |
301 const base::TimeDelta& expires_in) { | 252 const base::TimeDelta& expires_in) { |
302 if (quiet_mode_timer_.get()) { | 253 if (quiet_mode_timer_.get()) { |
303 // Note that the capital Reset() is the method to restart the timer, not | 254 // Note that the capital Reset() is the method to restart the timer, not |
304 // scoped_ptr::reset(). | 255 // scoped_ptr::reset(). |
305 quiet_mode_timer_->Reset(); | 256 quiet_mode_timer_->Reset(); |
306 } else { | 257 } else { |
307 SetQuietModeInternal(true); | 258 SetQuietModeInternal(true); |
308 quiet_mode_timer_.reset(new base::OneShotTimer<NotificationList>); | 259 quiet_mode_timer_.reset(new base::OneShotTimer<NotificationList>); |
309 quiet_mode_timer_->Start(FROM_HERE, expires_in, base::Bind( | 260 quiet_mode_timer_->Start(FROM_HERE, expires_in, base::Bind( |
310 &NotificationList::SetQuietMode, base::Unretained(this), false)); | 261 &NotificationList::SetQuietMode, base::Unretained(this), false)); |
311 } | 262 } |
312 } | 263 } |
313 | 264 |
314 void NotificationList::GetNotifications( | 265 const NotificationList::Notifications& NotificationList::GetNotifications() { |
315 NotificationList::Notifications* notifications) const { | 266 return notifications_; |
316 DCHECK(notifications); | |
317 // Higher priority should come earlier. | |
318 for (NotificationMap::const_reverse_iterator mapiter = | |
319 notifications_.rbegin(); | |
320 mapiter != notifications_.rend(); ++mapiter) { | |
321 for (Notifications::const_iterator iter = mapiter->second.begin(); | |
322 iter != mapiter->second.end(); ++iter) { | |
323 notifications->push_back(*iter); | |
324 } | |
325 } | |
326 } | 267 } |
327 | 268 |
328 size_t NotificationList::NotificationCount() const { | 269 size_t NotificationList::NotificationCount() const { |
329 size_t result = 0; | 270 return notifications_.size(); |
330 for (NotificationMap::const_iterator mapiter = notifications_.begin(); | |
331 mapiter != notifications_.end(); ++mapiter) { | |
332 result += mapiter->second.size(); | |
333 } | |
334 return result; | |
335 } | 271 } |
336 | 272 |
337 void NotificationList::SetQuietModeInternal(bool quiet_mode) { | 273 void NotificationList::SetQuietModeInternal(bool quiet_mode) { |
338 quiet_mode_ = quiet_mode; | 274 quiet_mode_ = quiet_mode; |
339 if (quiet_mode_) { | 275 if (quiet_mode_) { |
340 for (NotificationMap::iterator mapiter = notifications_.begin(); | 276 for (Notifications::iterator iter = notifications_.begin(); |
341 mapiter != notifications_.end(); ++mapiter) { | 277 iter != notifications_.end(); ++iter) { |
342 for (Notifications::iterator iter = mapiter->second.begin(); | 278 (*iter)->set_is_read(true); |
343 iter != mapiter->second.end(); ++iter) { | 279 (*iter)->set_shown_as_popup(true); |
344 iter->is_read = true; | |
345 iter->shown_as_popup = true; | |
346 } | |
347 } | 280 } |
348 unread_count_ = 0; | 281 unread_count_ = 0; |
349 } | 282 } |
350 delegate_->OnQuietModeChanged(quiet_mode); | 283 delegate_->OnQuietModeChanged(quiet_mode); |
351 } | 284 } |
352 | 285 |
353 bool NotificationList::GetNotification( | 286 NotificationList::Notifications::iterator |
354 const std::string& id, Notifications::iterator* iter) { | 287 NotificationList::GetNotification(const std::string& id) { |
355 for (NotificationMap::iterator mapiter = notifications_.begin(); | 288 for (Notifications::iterator iter = notifications_.begin(); |
356 mapiter != notifications_.end(); ++mapiter) { | 289 iter != notifications_.end(); ++iter) { |
357 for (Notifications::iterator curiter = mapiter->second.begin(); | 290 if ((*iter)->id() == id) |
358 curiter != mapiter->second.end(); ++curiter) { | 291 return iter; |
359 if (curiter->id == id) { | |
360 *iter = curiter; | |
361 return true; | |
362 } | |
363 } | |
364 } | 292 } |
365 return false; | 293 return notifications_.end(); |
366 } | 294 } |
367 | 295 |
368 void NotificationList::EraseNotification(Notifications::iterator iter) { | 296 void NotificationList::EraseNotification(Notifications::iterator iter) { |
369 if (!message_center_visible_ && !iter->is_read && | 297 if (!message_center_visible_ && !(*iter)->is_read() && |
370 iter->priority > ui::notifications::MIN_PRIORITY) { | 298 (*iter)->priority() > MIN_PRIORITY) { |
371 --unread_count_; | 299 --unread_count_; |
372 } | 300 } |
373 notifications_[iter->priority].erase(iter); | 301 delete *iter; |
| 302 notifications_.erase(iter); |
374 } | 303 } |
375 | 304 |
376 void NotificationList::PushNotification(Notification& notification) { | 305 void NotificationList::PushNotification(scoped_ptr<Notification> notification) { |
377 // Ensure that notification.id is unique by erasing any existing | 306 // Ensure that notification.id is unique by erasing any existing |
378 // notification with the same id (shouldn't normally happen). | 307 // notification with the same id (shouldn't normally happen). |
379 Notifications::iterator iter; | 308 Notifications::iterator iter = GetNotification(notification->id()); |
380 if (GetNotification(notification.id, &iter)) | 309 if (iter != notifications_.end()) |
381 EraseNotification(iter); | 310 EraseNotification(iter); |
382 // Add the notification to the front (top) of the list and mark it | 311 // Add the notification to the the list and mark it unread and unshown. |
383 // unread and unshown. | |
384 if (!message_center_visible_) { | 312 if (!message_center_visible_) { |
385 if (quiet_mode_) { | 313 // TODO(mukai): needs to distinguish if a notification is dismissed by |
386 // TODO(mukai): needs to distinguish if a notification is dismissed by | 314 // the quiet mode or user operation. |
387 // the quiet mode or user operation. | 315 notification->set_is_read(quiet_mode_); |
388 notification.is_read = true; | 316 notification->set_shown_as_popup(quiet_mode_); |
389 notification.shown_as_popup = true; | 317 if (!quiet_mode_ && notification->priority() > MIN_PRIORITY) |
390 } else { | |
391 if (notification.priority > ui::notifications::MIN_PRIORITY) | |
392 ++unread_count_; | 318 ++unread_count_; |
393 notification.is_read = false; | |
394 notification.shown_as_popup = false; | |
395 } | |
396 } | 319 } |
397 notifications_[notification.priority].push_front(notification); | 320 // Take ownership. The notification can only be removed from the list |
398 } | 321 // in EraseNotification(), which will delete it. |
399 | 322 notifications_.insert(notification.release()); |
400 void NotificationList::GetPopupIterators(int priority, | |
401 Notifications::iterator* first, | |
402 Notifications::iterator* last) { | |
403 Notifications& notifications = notifications_[priority]; | |
404 // No popups for LOW/MIN priority. | |
405 if (priority < ui::notifications::DEFAULT_PRIORITY) { | |
406 *first = notifications.end(); | |
407 *last = notifications.end(); | |
408 return; | |
409 } | |
410 | |
411 size_t popup_count = 0; | |
412 *first = notifications.begin(); | |
413 *last = *first; | |
414 while (*last != notifications.end()) { | |
415 if ((*last)->shown_as_popup) | |
416 break; | |
417 ++(*last); | |
418 | |
419 // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority | |
420 // will return at most kMaxVisiblePopupNotifications entries. If the | |
421 // popup entries are more, older entries are used. see crbug.com/165768 | |
422 if (priority == ui::notifications::DEFAULT_PRIORITY && | |
423 popup_count >= kMaxVisiblePopupNotifications) { | |
424 ++(*first); | |
425 } else { | |
426 ++popup_count; | |
427 } | |
428 } | |
429 } | 323 } |
430 | 324 |
431 } // namespace message_center | 325 } // namespace message_center |
OLD | NEW |