OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/message_center_impl.h" | 5 #include "ui/message_center/message_center_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
| 9 #include <utility> |
9 | 10 |
10 #include "base/command_line.h" | 11 #include "base/command_line.h" |
11 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
12 #include "base/observer_list.h" | 13 #include "base/observer_list.h" |
13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
14 #include "ui/message_center/message_center_style.h" | 15 #include "ui/message_center/message_center_style.h" |
15 #include "ui/message_center/message_center_switches.h" | 16 #include "ui/message_center/message_center_switches.h" |
16 #include "ui/message_center/message_center_types.h" | 17 #include "ui/message_center/message_center_types.h" |
17 #include "ui/message_center/notification.h" | 18 #include "ui/message_center/notification.h" |
18 #include "ui/message_center/notification_blocker.h" | 19 #include "ui/message_center/notification_blocker.h" |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 132 |
132 //////////////////////////////////////////////////////////////////////////////// | 133 //////////////////////////////////////////////////////////////////////////////// |
133 // ChangeQueue::Change | 134 // ChangeQueue::Change |
134 | 135 |
135 ChangeQueue::Change::Change(ChangeType type, | 136 ChangeQueue::Change::Change(ChangeType type, |
136 const std::string& id, | 137 const std::string& id, |
137 scoped_ptr<Notification> notification) | 138 scoped_ptr<Notification> notification) |
138 : type_(type), | 139 : type_(type), |
139 notification_list_id_(id), | 140 notification_list_id_(id), |
140 by_user_(false), | 141 by_user_(false), |
141 notification_(notification.Pass()) { | 142 notification_(std::move(notification)) { |
142 DCHECK(!id.empty()); | 143 DCHECK(!id.empty()); |
143 DCHECK(type != CHANGE_TYPE_DELETE || notification_.get() == NULL); | 144 DCHECK(type != CHANGE_TYPE_DELETE || notification_.get() == NULL); |
144 | 145 |
145 id_ = notification_ ? notification_->id() : notification_list_id_; | 146 id_ = notification_ ? notification_->id() : notification_list_id_; |
146 } | 147 } |
147 | 148 |
148 ChangeQueue::Change::~Change() {} | 149 ChangeQueue::Change::~Change() {} |
149 | 150 |
150 scoped_ptr<Notification> ChangeQueue::Change::PassNotification() { | 151 scoped_ptr<Notification> ChangeQueue::Change::PassNotification() { |
151 return notification_.Pass(); | 152 return std::move(notification_); |
152 } | 153 } |
153 | 154 |
154 void ChangeQueue::Change::ReplaceNotification( | 155 void ChangeQueue::Change::ReplaceNotification( |
155 scoped_ptr<Notification> new_notification) { | 156 scoped_ptr<Notification> new_notification) { |
156 id_ = new_notification ? new_notification->id() : notification_list_id_; | 157 id_ = new_notification ? new_notification->id() : notification_list_id_; |
157 notification_.swap(new_notification); | 158 notification_.swap(new_notification); |
158 } | 159 } |
159 | 160 |
160 //////////////////////////////////////////////////////////////////////////////// | 161 //////////////////////////////////////////////////////////////////////////////// |
161 // ChangeQueue | 162 // ChangeQueue |
162 | 163 |
163 ChangeQueue::ChangeQueue() {} | 164 ChangeQueue::ChangeQueue() {} |
164 | 165 |
165 ChangeQueue::~ChangeQueue() {} | 166 ChangeQueue::~ChangeQueue() {} |
166 | 167 |
167 void ChangeQueue::ApplyChanges(MessageCenterImpl* message_center) { | 168 void ChangeQueue::ApplyChanges(MessageCenterImpl* message_center) { |
168 // This method is re-entrant. | 169 // This method is re-entrant. |
169 while (!changes_.empty()) { | 170 while (!changes_.empty()) { |
170 ScopedVector<Change>::iterator iter = changes_.begin(); | 171 ScopedVector<Change>::iterator iter = changes_.begin(); |
171 scoped_ptr<Change> change(*iter); | 172 scoped_ptr<Change> change(*iter); |
172 // TODO(dewittj): Replace changes_ with a deque. | 173 // TODO(dewittj): Replace changes_ with a deque. |
173 changes_.weak_erase(iter); | 174 changes_.weak_erase(iter); |
174 ApplyChangeInternal(message_center, change.Pass()); | 175 ApplyChangeInternal(message_center, std::move(change)); |
175 } | 176 } |
176 } | 177 } |
177 | 178 |
178 void ChangeQueue::ApplyChangesForId(MessageCenterImpl* message_center, | 179 void ChangeQueue::ApplyChangesForId(MessageCenterImpl* message_center, |
179 const std::string& id) { | 180 const std::string& id) { |
180 std::deque<Change*> changes_for_id; | 181 std::deque<Change*> changes_for_id; |
181 std::string interesting_id = id; | 182 std::string interesting_id = id; |
182 | 183 |
183 // Traverses the queue in reverse so shat we can track changes which change | 184 // Traverses the queue in reverse so shat we can track changes which change |
184 // the notification's ID. | 185 // the notification's ID. |
(...skipping 12 matching lines...) Expand all Loading... |
197 | 198 |
198 while (!changes_for_id.empty()) { | 199 while (!changes_for_id.empty()) { |
199 ApplyChangeInternal( | 200 ApplyChangeInternal( |
200 message_center, scoped_ptr<Change>(changes_for_id.back())); | 201 message_center, scoped_ptr<Change>(changes_for_id.back())); |
201 changes_for_id.pop_back(); | 202 changes_for_id.pop_back(); |
202 } | 203 } |
203 } | 204 } |
204 | 205 |
205 void ChangeQueue::AddNotification(scoped_ptr<Notification> notification) { | 206 void ChangeQueue::AddNotification(scoped_ptr<Notification> notification) { |
206 std::string id = notification->id(); | 207 std::string id = notification->id(); |
207 changes_.push_back( | 208 changes_.push_back(new Change(CHANGE_TYPE_ADD, id, std::move(notification))); |
208 new Change(CHANGE_TYPE_ADD, id, notification.Pass())); | |
209 } | 209 } |
210 | 210 |
211 void ChangeQueue::UpdateNotification(const std::string& old_id, | 211 void ChangeQueue::UpdateNotification(const std::string& old_id, |
212 scoped_ptr<Notification> notification) { | 212 scoped_ptr<Notification> notification) { |
213 ScopedVector<Change>::reverse_iterator iter = | 213 ScopedVector<Change>::reverse_iterator iter = |
214 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(old_id)); | 214 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(old_id)); |
215 if (iter == changes_.rend()) { | 215 if (iter == changes_.rend()) { |
216 changes_.push_back( | 216 changes_.push_back( |
217 new Change(CHANGE_TYPE_UPDATE, old_id, notification.Pass())); | 217 new Change(CHANGE_TYPE_UPDATE, old_id, std::move(notification))); |
218 return; | 218 return; |
219 } | 219 } |
220 | 220 |
221 Change* change = *iter; | 221 Change* change = *iter; |
222 switch (change->type()) { | 222 switch (change->type()) { |
223 case CHANGE_TYPE_ADD: { | 223 case CHANGE_TYPE_ADD: { |
224 std::string id = notification->id(); | 224 std::string id = notification->id(); |
225 // Needs to add the change at the last, because if this change updates | 225 // Needs to add the change at the last, because if this change updates |
226 // its ID, some previous changes may affect new ID. | 226 // its ID, some previous changes may affect new ID. |
227 // (eg. Add A, Update B->C, and This update A->B). | 227 // (eg. Add A, Update B->C, and This update A->B). |
228 changes_.erase(--(iter.base())); | 228 changes_.erase(--(iter.base())); |
229 changes_.push_back( | 229 changes_.push_back( |
230 new Change(CHANGE_TYPE_ADD, id, notification.Pass())); | 230 new Change(CHANGE_TYPE_ADD, id, std::move(notification))); |
231 break; | 231 break; |
232 } | 232 } |
233 case CHANGE_TYPE_UPDATE: | 233 case CHANGE_TYPE_UPDATE: |
234 if (notification->id() == old_id) { | 234 if (notification->id() == old_id) { |
235 // Safe to place the change at the previous place. | 235 // Safe to place the change at the previous place. |
236 change->ReplaceNotification(notification.Pass()); | 236 change->ReplaceNotification(std::move(notification)); |
237 } else if (change->id() == change->notification_list_id()) { | 237 } else if (change->id() == change->notification_list_id()) { |
238 std::string id = notification->id(); | 238 std::string id = notification->id(); |
239 // Safe to place the change at the last. | 239 // Safe to place the change at the last. |
240 changes_.erase(--(iter.base())); | 240 changes_.erase(--(iter.base())); |
241 changes_.push_back(new Change( | 241 changes_.push_back( |
242 CHANGE_TYPE_ADD, id, notification.Pass())); | 242 new Change(CHANGE_TYPE_ADD, id, std::move(notification))); |
243 } else { | 243 } else { |
244 // Complex case: gives up to optimize. | 244 // Complex case: gives up to optimize. |
245 changes_.push_back( | 245 changes_.push_back( |
246 new Change(CHANGE_TYPE_UPDATE, old_id, notification.Pass())); | 246 new Change(CHANGE_TYPE_UPDATE, old_id, std::move(notification))); |
247 } | 247 } |
248 break; | 248 break; |
249 case CHANGE_TYPE_DELETE: | 249 case CHANGE_TYPE_DELETE: |
250 // DELETE -> UPDATE. Something is wrong. Treats the UPDATE as ADD. | 250 // DELETE -> UPDATE. Something is wrong. Treats the UPDATE as ADD. |
251 changes_.push_back( | 251 changes_.push_back( |
252 new Change(CHANGE_TYPE_ADD, old_id, notification.Pass())); | 252 new Change(CHANGE_TYPE_ADD, old_id, std::move(notification))); |
253 break; | 253 break; |
254 default: | 254 default: |
255 NOTREACHED(); | 255 NOTREACHED(); |
256 } | 256 } |
257 } | 257 } |
258 | 258 |
259 void ChangeQueue::EraseNotification(const std::string& id, bool by_user) { | 259 void ChangeQueue::EraseNotification(const std::string& id, bool by_user) { |
260 ScopedVector<Change>::reverse_iterator iter = | 260 ScopedVector<Change>::reverse_iterator iter = |
261 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(id)); | 261 std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(id)); |
262 if (iter == changes_.rend()) { | 262 if (iter == changes_.rend()) { |
263 scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr)); | 263 scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr)); |
264 change->set_by_user(by_user); | 264 change->set_by_user(by_user); |
265 changes_.push_back(change.Pass()); | 265 changes_.push_back(std::move(change)); |
266 return; | 266 return; |
267 } | 267 } |
268 | 268 |
269 Change* change = *iter; | 269 Change* change = *iter; |
270 switch (change->type()) { | 270 switch (change->type()) { |
271 case CHANGE_TYPE_ADD: | 271 case CHANGE_TYPE_ADD: |
272 // ADD -> DELETE. Just removes both. | 272 // ADD -> DELETE. Just removes both. |
273 changes_.erase(--(iter.base())); | 273 changes_.erase(--(iter.base())); |
274 break; | 274 break; |
275 case CHANGE_TYPE_UPDATE: | 275 case CHANGE_TYPE_UPDATE: |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 //------------------------------------------------------------------------------ | 507 //------------------------------------------------------------------------------ |
508 // Client code interface. | 508 // Client code interface. |
509 void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) { | 509 void MessageCenterImpl::AddNotification(scoped_ptr<Notification> notification) { |
510 DCHECK(notification); | 510 DCHECK(notification); |
511 const std::string id = notification->id(); | 511 const std::string id = notification->id(); |
512 for (size_t i = 0; i < blockers_.size(); ++i) | 512 for (size_t i = 0; i < blockers_.size(); ++i) |
513 blockers_[i]->CheckState(); | 513 blockers_[i]->CheckState(); |
514 | 514 |
515 if (notification_queue_ && | 515 if (notification_queue_ && |
516 notification_list_->is_message_center_visible()) { | 516 notification_list_->is_message_center_visible()) { |
517 notification_queue_->AddNotification(notification.Pass()); | 517 notification_queue_->AddNotification(std::move(notification)); |
518 return; | 518 return; |
519 } | 519 } |
520 | 520 |
521 AddNotificationImmediately(notification.Pass()); | 521 AddNotificationImmediately(std::move(notification)); |
522 } | 522 } |
523 | 523 |
524 void MessageCenterImpl::AddNotificationImmediately( | 524 void MessageCenterImpl::AddNotificationImmediately( |
525 scoped_ptr<Notification> notification) { | 525 scoped_ptr<Notification> notification) { |
526 const std::string id = notification->id(); | 526 const std::string id = notification->id(); |
527 | 527 |
528 // Sometimes the notification can be added with the same id and the | 528 // Sometimes the notification can be added with the same id and the |
529 // |notification_list| will replace the notification instead of adding new. | 529 // |notification_list| will replace the notification instead of adding new. |
530 // This is essentially an update rather than addition. | 530 // This is essentially an update rather than addition. |
531 bool already_exists = (notification_list_->GetNotificationById(id) != NULL); | 531 bool already_exists = (notification_list_->GetNotificationById(id) != NULL); |
532 notification_list_->AddNotification(notification.Pass()); | 532 notification_list_->AddNotification(std::move(notification)); |
533 notification_cache_.Rebuild( | 533 notification_cache_.Rebuild( |
534 notification_list_->GetVisibleNotifications(blockers_)); | 534 notification_list_->GetVisibleNotifications(blockers_)); |
535 | 535 |
536 if (already_exists) { | 536 if (already_exists) { |
537 FOR_EACH_OBSERVER( | 537 FOR_EACH_OBSERVER( |
538 MessageCenterObserver, observer_list_, OnNotificationUpdated(id)); | 538 MessageCenterObserver, observer_list_, OnNotificationUpdated(id)); |
539 } else { | 539 } else { |
540 FOR_EACH_OBSERVER( | 540 FOR_EACH_OBSERVER( |
541 MessageCenterObserver, observer_list_, OnNotificationAdded(id)); | 541 MessageCenterObserver, observer_list_, OnNotificationAdded(id)); |
542 } | 542 } |
(...skipping 17 matching lines...) Expand all Loading... |
560 // TODO(dewittj): Ensure this works when the ID is changed by the caller. | 560 // TODO(dewittj): Ensure this works when the ID is changed by the caller. |
561 // This shouldn't be an issue in practice since only W3C notifications | 561 // This shouldn't be an issue in practice since only W3C notifications |
562 // change the ID on update, and they don't have progress type notifications. | 562 // change the ID on update, and they don't have progress type notifications. |
563 bool update_keeps_progress_type = | 563 bool update_keeps_progress_type = |
564 new_notification->type() == NOTIFICATION_TYPE_PROGRESS && | 564 new_notification->type() == NOTIFICATION_TYPE_PROGRESS && |
565 !notification_queue_->Has(old_id) && | 565 !notification_queue_->Has(old_id) && |
566 notification_list_->HasNotificationOfType(old_id, | 566 notification_list_->HasNotificationOfType(old_id, |
567 NOTIFICATION_TYPE_PROGRESS); | 567 NOTIFICATION_TYPE_PROGRESS); |
568 if (!update_keeps_progress_type) { | 568 if (!update_keeps_progress_type) { |
569 // Updates are allowed only for progress notifications. | 569 // Updates are allowed only for progress notifications. |
570 notification_queue_->UpdateNotification(old_id, new_notification.Pass()); | 570 notification_queue_->UpdateNotification(old_id, |
| 571 std::move(new_notification)); |
571 return; | 572 return; |
572 } | 573 } |
573 } | 574 } |
574 | 575 |
575 UpdateNotificationImmediately(old_id, new_notification.Pass()); | 576 UpdateNotificationImmediately(old_id, std::move(new_notification)); |
576 } | 577 } |
577 | 578 |
578 void MessageCenterImpl::UpdateNotificationImmediately( | 579 void MessageCenterImpl::UpdateNotificationImmediately( |
579 const std::string& old_id, | 580 const std::string& old_id, |
580 scoped_ptr<Notification> new_notification) { | 581 scoped_ptr<Notification> new_notification) { |
581 std::string new_id = new_notification->id(); | 582 std::string new_id = new_notification->id(); |
582 notification_list_->UpdateNotificationMessage(old_id, | 583 notification_list_->UpdateNotificationMessage(old_id, |
583 new_notification.Pass()); | 584 std::move(new_notification)); |
584 notification_cache_.Rebuild( | 585 notification_cache_.Rebuild( |
585 notification_list_->GetVisibleNotifications(blockers_)); | 586 notification_list_->GetVisibleNotifications(blockers_)); |
586 if (old_id == new_id) { | 587 if (old_id == new_id) { |
587 FOR_EACH_OBSERVER( | 588 FOR_EACH_OBSERVER( |
588 MessageCenterObserver, observer_list_, OnNotificationUpdated(new_id)); | 589 MessageCenterObserver, observer_list_, OnNotificationUpdated(new_id)); |
589 } else { | 590 } else { |
590 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, | 591 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, |
591 OnNotificationRemoved(old_id, false)); | 592 OnNotificationRemoved(old_id, false)); |
592 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, | 593 FOR_EACH_OBSERVER(MessageCenterObserver, observer_list_, |
593 OnNotificationAdded(new_id)); | 594 OnNotificationAdded(new_id)); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 } | 888 } |
888 | 889 |
889 void MessageCenterImpl::EnableChangeQueueForTest(bool enable) { | 890 void MessageCenterImpl::EnableChangeQueueForTest(bool enable) { |
890 if (enable) | 891 if (enable) |
891 notification_queue_.reset(new internal::ChangeQueue()); | 892 notification_queue_.reset(new internal::ChangeQueue()); |
892 else | 893 else |
893 notification_queue_.reset(); | 894 notification_queue_.reset(); |
894 } | 895 } |
895 | 896 |
896 } // namespace message_center | 897 } // namespace message_center |
OLD | NEW |