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