Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: ui/message_center/notification_list.cc

Issue 12277024: Notificaitons refactor step 2 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix the remaining test Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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, &notification);
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, &notification->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(), &notification->timestamp);
86 }
87 fields->GetInteger(ui::notifications::kUnreadCountKey,
88 &notification->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 &notification->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, &notification); 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698