Chromium Code Reviews| 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; | |
|
stevenjb
2013/02/25 18:11:08
Instead of adding a serial number, maybe just comp
Dmitry Titov
2013/02/25 23:21:15
See the previous comment. I think we might want to
| |
| 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 // 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 } | 83 } |
| 120 | 84 |
| 121 void NotificationList::UpdateNotificationMessage( | 85 void NotificationList::UpdateNotificationMessage( |
| 122 const std::string& old_id, | 86 const std::string& old_id, |
| 123 const std::string& new_id, | 87 const std::string& new_id, |
| 124 const string16& title, | 88 const string16& title, |
| 125 const string16& message, | 89 const string16& message, |
| 126 const base::DictionaryValue* optional_fields) { | 90 const base::DictionaryValue* optional_fields) { |
| 127 Notifications::iterator iter; | 91 Notifications::iterator iter = GetNotification(old_id); |
| 128 if (!GetNotification(old_id, &iter)) | 92 if (iter == notifications_.end()) |
| 129 return; | 93 return; |
| 130 // Copy and update notification, then move it to the front of the list. | 94 |
| 131 Notification notification(*iter); | 95 // Copy and update a notification. It has an effect of setting a new timestamp |
| 132 notification.id = new_id; | 96 // if not overridden by optional_fields |
| 133 notification.title = title; | 97 scoped_ptr<Notification> notification( |
| 134 notification.message = message; | 98 new Notification((*iter)->type(), |
| 135 UnpackOptionalFields(optional_fields, ¬ification); | 99 new_id, |
| 100 title, | |
| 101 message, | |
| 102 (*iter)->display_source(), | |
| 103 (*iter)->extension_id(), | |
| 104 optional_fields)); | |
| 136 EraseNotification(iter); | 105 EraseNotification(iter); |
| 137 PushNotification(notification); | 106 PushNotification(notification.Pass()); |
| 138 } | 107 } |
| 139 | 108 |
| 140 bool NotificationList::RemoveNotification(const std::string& id) { | 109 void NotificationList::RemoveNotification(const std::string& id) { |
| 141 Notifications::iterator iter; | 110 EraseNotification(GetNotification(id)); |
| 142 if (!GetNotification(id, &iter)) | |
| 143 return false; | |
| 144 EraseNotification(iter); | |
| 145 return true; | |
| 146 } | 111 } |
| 147 | 112 |
| 148 void NotificationList::RemoveAllNotifications() { | 113 void NotificationList::RemoveAllNotifications() { |
| 149 notifications_.clear(); | 114 for (Notifications::iterator loopiter = notifications_.begin(); |
| 115 loopiter != notifications_.end(); ) { | |
| 116 Notifications::iterator curiter = loopiter++; | |
| 117 EraseNotification(curiter); | |
| 118 } | |
| 150 unread_count_ = 0; | 119 unread_count_ = 0; |
| 151 } | 120 } |
| 152 | 121 |
| 153 void NotificationList::SendRemoveNotificationsBySource( | 122 void NotificationList::SendRemoveNotificationsBySource( |
| 154 const std::string& id) { | 123 const std::string& id) { |
| 155 Notifications::iterator source_iter; | 124 Notifications::iterator source_iter = GetNotification(id); |
| 156 if (!GetNotification(id, &source_iter)) | 125 if (source_iter == notifications_.end()) |
| 157 return; | 126 return; |
| 158 string16 display_source = source_iter->display_source; | 127 string16 display_source = (*source_iter)->display_source(); |
| 159 for (NotificationMap::iterator mapiter = notifications_.begin(); | 128 |
| 160 mapiter != notifications_.end(); ++mapiter) { | 129 for (Notifications::iterator loopiter = notifications_.begin(); |
| 161 for (Notifications::iterator loopiter = mapiter->second.begin(); | 130 loopiter != notifications_.end(); ) { |
| 162 loopiter != mapiter->second.end(); ) { | 131 Notifications::iterator curiter = loopiter++; |
| 163 Notifications::iterator curiter = loopiter++; | 132 if ((*curiter)->display_source() == display_source) |
| 164 if (curiter->display_source == display_source) | 133 delegate_->SendRemoveNotification((*curiter)->id()); |
| 165 delegate_->SendRemoveNotification(curiter->id); | |
| 166 } | |
| 167 } | 134 } |
| 168 } | 135 } |
| 169 | 136 |
| 170 void NotificationList::SendRemoveNotificationsByExtension( | 137 void NotificationList::SendRemoveNotificationsByExtension( |
| 171 const std::string& id) { | 138 const std::string& id) { |
| 172 Notifications::iterator source_iter; | 139 Notifications::iterator source_iter = GetNotification(id); |
| 173 if (!GetNotification(id, &source_iter)) | 140 if (source_iter == notifications_.end()) |
| 174 return; | 141 return; |
| 175 std::string extension_id = source_iter->extension_id; | 142 std::string extension_id = (*source_iter)->extension_id(); |
| 176 for (NotificationMap::iterator mapiter = notifications_.begin(); | 143 for (Notifications::iterator loopiter = notifications_.begin(); |
| 177 mapiter != notifications_.end(); ++mapiter) { | 144 loopiter != notifications_.end(); ) { |
| 178 for (Notifications::iterator loopiter = mapiter->second.begin(); | 145 Notifications::iterator curiter = loopiter++; |
| 179 loopiter != mapiter->second.end(); ) { | 146 if ((*curiter)->extension_id() == extension_id) |
| 180 Notifications::iterator curiter = loopiter++; | 147 delegate_->SendRemoveNotification((*curiter)->id()); |
| 181 if (curiter->extension_id == extension_id) | |
| 182 delegate_->SendRemoveNotification(curiter->id); | |
| 183 } | |
| 184 } | 148 } |
| 185 } | 149 } |
| 186 | 150 |
| 187 bool NotificationList::SetNotificationIcon(const std::string& notification_id, | 151 bool NotificationList::SetNotificationIcon(const std::string& notification_id, |
| 188 const gfx::ImageSkia& image) { | 152 const gfx::ImageSkia& image) { |
| 189 Notifications::iterator iter; | 153 Notifications::iterator iter = GetNotification(notification_id); |
| 190 if (!GetNotification(notification_id, &iter)) | 154 if (iter == notifications_.end()) |
| 191 return false; | 155 return false; |
| 192 iter->primary_icon = image; | 156 (*iter)->set_primary_icon(image); |
| 193 return true; | 157 return true; |
| 194 } | 158 } |
| 195 | 159 |
| 196 bool NotificationList::SetNotificationImage(const std::string& notification_id, | 160 bool NotificationList::SetNotificationImage(const std::string& notification_id, |
| 197 const gfx::ImageSkia& image) { | 161 const gfx::ImageSkia& image) { |
| 198 Notifications::iterator iter; | 162 Notifications::iterator iter = GetNotification(notification_id); |
| 199 if (!GetNotification(notification_id, &iter)) | 163 if (iter == notifications_.end()) |
| 200 return false; | 164 return false; |
| 201 iter->image = image; | 165 (*iter)->set_image(image); |
| 202 return true; | 166 return true; |
| 203 } | 167 } |
| 204 | 168 |
| 205 bool NotificationList::SetNotificationButtonIcon( | 169 bool NotificationList::SetNotificationButtonIcon( |
| 206 const std::string& notification_id, int button_index, | 170 const std::string& notification_id, int button_index, |
| 207 const gfx::ImageSkia& image) { | 171 const gfx::ImageSkia& image) { |
| 208 Notifications::iterator iter; | 172 Notifications::iterator iter = GetNotification(notification_id); |
| 209 if (!GetNotification(notification_id, &iter) || | 173 if (iter == notifications_.end()) |
| 210 static_cast<size_t>(button_index) >= iter->button_icons.size()) | |
| 211 return false; | 174 return false; |
| 212 iter->button_icons[button_index] = image; | 175 return (*iter)->SetButtonIcon(button_index, image); |
| 213 return true; | |
| 214 } | 176 } |
| 215 | 177 |
| 216 bool NotificationList::HasNotification(const std::string& id) { | 178 bool NotificationList::HasNotification(const std::string& id) { |
| 217 Notifications::iterator dummy; | 179 return GetNotification(id) != notifications_.end(); |
| 218 return GetNotification(id, &dummy); | |
| 219 } | 180 } |
| 220 | 181 |
| 221 bool NotificationList::HasPopupNotifications() { | 182 bool NotificationList::HasPopupNotifications() { |
| 222 for (int i = ui::notifications::DEFAULT_PRIORITY; | 183 for (Notifications::iterator iter = notifications_.begin(); |
| 223 i <= ui::notifications::MAX_PRIORITY; ++i) { | 184 iter != notifications_.end(); ++iter) { |
|
stevenjb
2013/02/25 18:11:08
Aren't these stored in priority order, so couldn't
Dmitry Titov
2013/02/25 23:21:15
The notifications are stored in priority/timestamp
stevenjb
2013/02/25 23:55:56
Ah, yes, I didn't think that through. Might be cle
Dmitry Titov
2013/02/26 01:01:51
Done.
| |
| 224 Notifications notifications = notifications_[i]; | 185 if (!(*iter)->shown_as_popup() && (*iter)->priority() >= DEFAULT_PRIORITY) |
| 225 if (!notifications.empty() && !notifications.front().shown_as_popup) | |
| 226 return true; | 186 return true; |
| 227 } | 187 } |
| 228 return false; | 188 return false; |
| 229 } | 189 } |
| 230 | 190 |
| 231 void NotificationList::GetPopupNotifications( | 191 NotificationList::PopupNotifications NotificationList::GetPopupNotifications() { |
| 232 NotificationList::Notifications* notifications) { | 192 PopupNotifications result; |
| 233 typedef std::pair<Notifications::iterator, Notifications::iterator> | 193 size_t default_priority_popup_count = 0; |
| 234 NotificationRange; | 194 |
| 235 // In the popup, latest should come earlier. | 195 // Collect notifications that should be shown as popups. Start from oldest. |
| 236 std::list<NotificationRange> iters; | 196 for (Notifications::const_reverse_iterator iter = notifications_.rbegin(); |
| 237 for (int i = ui::notifications::DEFAULT_PRIORITY; | 197 iter != notifications_.rend(); iter++) { |
| 238 i <= ui::notifications::MAX_PRIORITY; ++i) { | 198 |
| 239 Notifications::iterator first, last; | 199 if ((*iter)->shown_as_popup()) |
| 240 GetPopupIterators(i, &first, &last); | 200 continue; |
| 241 if (first != last) | 201 |
| 242 iters.push_back(make_pair(first, last)); | 202 // No popups for LOW/MIN priority. |
| 203 if ((*iter)->priority() < DEFAULT_PRIORITY) | |
| 204 continue; | |
|
stevenjb
2013/02/25 18:11:08
Can we break here?
Dmitry Titov
2013/02/25 23:21:15
Good catch, done.
| |
| 205 | |
| 206 // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority | |
| 207 // will return at most kMaxVisiblePopupNotifications entries. If the | |
| 208 // popup entries are more, older entries are used. see crbug.com/165768 | |
| 209 if ((*iter)->priority() == DEFAULT_PRIORITY && | |
| 210 default_priority_popup_count ++ >= kMaxVisiblePopupNotifications) { | |
|
stevenjb
2013/02/25 18:11:08
no ' ' before ++
Dmitry Titov
2013/02/25 23:21:15
Done.
| |
| 211 continue; | |
| 212 } | |
| 213 | |
| 214 result.insert(*iter); | |
| 243 } | 215 } |
| 244 notifications->clear(); | 216 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 } | 217 } |
| 259 | 218 |
| 260 void NotificationList::MarkPopupsAsShown(int priority) { | 219 void NotificationList::MarkPopupsAsShown(int priority) { |
| 261 Notifications::iterator first, last; | 220 PopupNotifications popups = GetPopupNotifications(); |
| 262 GetPopupIterators(priority, &first, &last); | 221 for (PopupNotifications::iterator iter = popups.begin(); |
| 263 for (Notifications::iterator iter = first; iter != last; ++iter) | 222 iter != popups.end(); ++iter) { |
| 264 iter->shown_as_popup = true; | 223 if ((*iter)->priority() == priority) |
| 224 (*iter)->set_shown_as_popup(true); | |
| 225 } | |
| 265 } | 226 } |
| 266 | 227 |
| 267 void NotificationList::MarkSinglePopupAsShown( | 228 void NotificationList::MarkSinglePopupAsShown( |
| 268 const std::string& id, bool mark_notification_as_read) { | 229 const std::string& id, bool mark_notification_as_read) { |
| 269 Notifications::iterator iter; | 230 Notifications::iterator iter = GetNotification(id); |
| 270 if (!GetNotification(id, &iter)) | 231 DCHECK(iter != notifications_.end()); |
| 232 | |
| 233 if ((*iter)->shown_as_popup()) | |
| 271 return; | 234 return; |
| 272 | 235 |
| 273 if (iter->shown_as_popup) | 236 (*iter)->set_shown_as_popup(true); |
| 274 return; | |
| 275 | 237 |
| 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) { | 238 if (mark_notification_as_read) { |
| 280 --unread_count_; | 239 --unread_count_; |
| 281 notification.is_read = true; | 240 (*iter)->set_is_read(true); |
| 282 } | 241 } |
| 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 } | 242 } |
| 298 | 243 |
| 299 void NotificationList::SetQuietMode(bool quiet_mode) { | 244 void NotificationList::SetQuietMode(bool quiet_mode) { |
| 300 SetQuietModeInternal(quiet_mode); | 245 SetQuietModeInternal(quiet_mode); |
| 301 quiet_mode_timer_.reset(); | 246 quiet_mode_timer_.reset(); |
| 302 } | 247 } |
| 303 | 248 |
| 304 void NotificationList::EnterQuietModeWithExpire( | 249 void NotificationList::EnterQuietModeWithExpire( |
| 305 const base::TimeDelta& expires_in) { | 250 const base::TimeDelta& expires_in) { |
| 306 if (quiet_mode_timer_.get()) { | 251 if (quiet_mode_timer_.get()) { |
| 307 // Note that the capital Reset() is the method to restart the timer, not | 252 // Note that the capital Reset() is the method to restart the timer, not |
| 308 // scoped_ptr::reset(). | 253 // scoped_ptr::reset(). |
| 309 quiet_mode_timer_->Reset(); | 254 quiet_mode_timer_->Reset(); |
| 310 } else { | 255 } else { |
| 311 SetQuietModeInternal(true); | 256 SetQuietModeInternal(true); |
| 312 quiet_mode_timer_.reset(new base::OneShotTimer<NotificationList>); | 257 quiet_mode_timer_.reset(new base::OneShotTimer<NotificationList>); |
| 313 quiet_mode_timer_->Start(FROM_HERE, expires_in, base::Bind( | 258 quiet_mode_timer_->Start(FROM_HERE, expires_in, base::Bind( |
| 314 &NotificationList::SetQuietMode, base::Unretained(this), false)); | 259 &NotificationList::SetQuietMode, base::Unretained(this), false)); |
| 315 } | 260 } |
| 316 } | 261 } |
| 317 | 262 |
| 318 void NotificationList::GetNotifications( | 263 const NotificationList::Notifications& NotificationList::GetNotifications() { |
| 319 NotificationList::Notifications* notifications) const { | 264 return notifications_; |
| 320 DCHECK(notifications); | |
| 321 // Higher priority should come earlier. | |
| 322 for (NotificationMap::const_reverse_iterator mapiter = | |
| 323 notifications_.rbegin(); | |
| 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 } | 265 } |
| 331 | 266 |
| 332 size_t NotificationList::NotificationCount() const { | 267 size_t NotificationList::NotificationCount() const { |
| 333 size_t result = 0; | 268 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 } | 269 } |
| 340 | 270 |
| 341 void NotificationList::SetQuietModeInternal(bool quiet_mode) { | 271 void NotificationList::SetQuietModeInternal(bool quiet_mode) { |
| 342 quiet_mode_ = quiet_mode; | 272 quiet_mode_ = quiet_mode; |
| 343 if (quiet_mode_) { | 273 if (quiet_mode_) { |
| 344 for (NotificationMap::iterator mapiter = notifications_.begin(); | 274 for (Notifications::iterator iter = notifications_.begin(); |
| 345 mapiter != notifications_.end(); ++mapiter) { | 275 iter != notifications_.end(); ++iter) { |
| 346 for (Notifications::iterator iter = mapiter->second.begin(); | 276 (*iter)->set_is_read(true); |
| 347 iter != mapiter->second.end(); ++iter) { | 277 (*iter)->set_shown_as_popup(true); |
| 348 iter->is_read = true; | |
| 349 iter->shown_as_popup = true; | |
| 350 } | |
| 351 } | 278 } |
| 352 unread_count_ = 0; | 279 unread_count_ = 0; |
| 353 } | 280 } |
| 354 delegate_->OnQuietModeChanged(quiet_mode); | 281 delegate_->OnQuietModeChanged(quiet_mode); |
| 355 } | 282 } |
| 356 | 283 |
| 357 bool NotificationList::GetNotification( | 284 NotificationList::Notifications::iterator |
| 358 const std::string& id, Notifications::iterator* iter) { | 285 NotificationList::GetNotification(const std::string& id) { |
| 359 for (NotificationMap::iterator mapiter = notifications_.begin(); | 286 for (Notifications::iterator iter = notifications_.begin(); |
| 360 mapiter != notifications_.end(); ++mapiter) { | 287 iter != notifications_.end(); ++iter) { |
| 361 for (Notifications::iterator curiter = mapiter->second.begin(); | 288 if ((*iter)->id() == id) |
| 362 curiter != mapiter->second.end(); ++curiter) { | 289 return iter; |
| 363 if (curiter->id == id) { | |
| 364 *iter = curiter; | |
| 365 return true; | |
| 366 } | |
| 367 } | |
| 368 } | 290 } |
| 369 return false; | 291 return notifications_.end(); |
| 370 } | 292 } |
| 371 | 293 |
| 372 void NotificationList::EraseNotification(Notifications::iterator iter) { | 294 void NotificationList::EraseNotification(Notifications::iterator iter) { |
| 373 if (!message_center_visible_ && !iter->is_read && | 295 if (!message_center_visible_ && !(*iter)->is_read() && |
| 374 iter->priority > ui::notifications::MIN_PRIORITY) { | 296 (*iter)->priority() > MIN_PRIORITY) { |
| 375 --unread_count_; | 297 --unread_count_; |
| 376 } | 298 } |
| 377 notifications_[iter->priority].erase(iter); | 299 delete *iter; |
| 300 notifications_.erase(iter); | |
| 378 } | 301 } |
| 379 | 302 |
| 380 void NotificationList::PushNotification(Notification& notification) { | 303 void NotificationList::PushNotification(scoped_ptr<Notification> notification) { |
| 381 // Ensure that notification.id is unique by erasing any existing | 304 // Ensure that notification.id is unique by erasing any existing |
| 382 // notification with the same id (shouldn't normally happen). | 305 // notification with the same id (shouldn't normally happen). |
| 383 Notifications::iterator iter; | 306 Notifications::iterator iter = GetNotification(notification->id()); |
| 384 if (GetNotification(notification.id, &iter)) | 307 if (iter != notifications_.end()) |
| 385 EraseNotification(iter); | 308 EraseNotification(iter); |
| 386 // Add the notification to the front (top) of the list and mark it | 309 // Add the notification to the the list and mark it unread and unshown. |
| 387 // unread and unshown. | |
| 388 if (!message_center_visible_) { | 310 if (!message_center_visible_) { |
| 389 if (quiet_mode_) { | 311 // TODO(mukai): needs to distinguish if a notification is dismissed by |
| 390 // TODO(mukai): needs to distinguish if a notification is dismissed by | 312 // the quiet mode or user operation. |
| 391 // the quiet mode or user operation. | 313 notification->set_is_read(quiet_mode_); |
| 392 notification.is_read = true; | 314 notification->set_shown_as_popup(quiet_mode_); |
| 393 notification.shown_as_popup = true; | 315 if (!quiet_mode_ && notification->priority() > MIN_PRIORITY) |
| 394 } else { | |
| 395 if (notification.priority > ui::notifications::MIN_PRIORITY) | |
| 396 ++unread_count_; | 316 ++unread_count_; |
| 397 notification.is_read = false; | |
| 398 notification.shown_as_popup = false; | |
| 399 } | |
| 400 } | 317 } |
| 401 notifications_[notification.priority].push_front(notification); | 318 // Take ownership. The notification can only be removed form the list |
| 402 } | 319 // in EraseNotification(), which will delete it. |
| 403 | 320 notifications_.insert(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 } | 321 } |
| 434 | 322 |
| 435 } // namespace message_center | 323 } // namespace message_center |
| OLD | NEW |