Android: remove ContentView/ContentViewCore NeedsReload().
[chromium-blink-merge.git] / ui / message_center / notification_list.cc
blob73ea08b26277d7cb7ab33f555deb861654aa7f59
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
3 // found in the LICENSE file.
5 #include "ui/message_center/notification_list.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/stl_util.h"
10 #include "base/time/time.h"
11 #include "base/values.h"
12 #include "ui/message_center/message_center_style.h"
13 #include "ui/message_center/notification.h"
14 #include "ui/message_center/notification_blocker.h"
15 #include "ui/message_center/notification_types.h"
17 namespace message_center {
19 namespace {
21 bool ShouldShowNotificationAsPopup(
22 const NotifierId& notifier_id,
23 const std::vector<NotificationBlocker*>& blockers) {
24 for (size_t i = 0; i < blockers.size(); ++i) {
25 if (!blockers[i]->ShouldShowNotificationAsPopup(notifier_id))
26 return false;
28 return true;
31 } // namespace
33 bool ComparePriorityTimestampSerial::operator()(Notification* n1,
34 Notification* n2) {
35 if (n1->priority() > n2->priority()) // Higher pri go first.
36 return true;
37 if (n1->priority() < n2->priority())
38 return false;
39 return CompareTimestampSerial()(n1, n2);
42 bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) {
43 if (n1->timestamp() > n2->timestamp()) // Newer come first.
44 return true;
45 if (n1->timestamp() < n2->timestamp())
46 return false;
47 if (n1->serial_number() > n2->serial_number()) // Newer come first.
48 return true;
49 if (n1->serial_number() < n2->serial_number())
50 return false;
51 return false;
54 NotificationList::NotificationList()
55 : message_center_visible_(false),
56 unread_count_(0),
57 quiet_mode_(false) {
60 NotificationList::~NotificationList() {
61 STLDeleteContainerPointers(notifications_.begin(), notifications_.end());
64 void NotificationList::SetMessageCenterVisible(
65 bool visible,
66 std::set<std::string>* updated_ids) {
67 if (message_center_visible_ == visible)
68 return;
70 message_center_visible_ = visible;
72 if (!visible)
73 return;
75 unread_count_ = 0;
77 for (Notifications::iterator iter = notifications_.begin();
78 iter != notifications_.end(); ++iter) {
79 Notification* notification = *iter;
80 if (notification->priority() < SYSTEM_PRIORITY)
81 notification->set_shown_as_popup(true);
82 notification->set_is_read(true);
83 if (updated_ids &&
84 !(notification->shown_as_popup() && notification->is_read())) {
85 updated_ids->insert(notification->id());
90 void NotificationList::AddNotification(scoped_ptr<Notification> notification) {
91 PushNotification(notification.Pass());
94 void NotificationList::UpdateNotificationMessage(
95 const std::string& old_id,
96 scoped_ptr<Notification> new_notification) {
97 Notifications::iterator iter = GetNotification(old_id);
98 if (iter == notifications_.end())
99 return;
101 new_notification->CopyState(*iter);
103 // Handles priority promotion. If the notification is already dismissed but
104 // the updated notification has higher priority, it should re-appear as a
105 // toast.
106 if ((*iter)->priority() < new_notification->priority()) {
107 new_notification->set_is_read(false);
108 new_notification->set_shown_as_popup(false);
111 // Do not use EraseNotification and PushNotification, since we don't want to
112 // change unread counts nor to update is_read/shown_as_popup states.
113 Notification* old = *iter;
114 notifications_.erase(iter);
115 delete old;
117 // We really don't want duplicate IDs.
118 DCHECK(GetNotification(new_notification->id()) == notifications_.end());
119 notifications_.insert(new_notification.release());
122 void NotificationList::RemoveNotification(const std::string& id) {
123 EraseNotification(GetNotification(id));
126 void NotificationList::RemoveAllNotifications() {
127 for (Notifications::iterator loopiter = notifications_.begin();
128 loopiter != notifications_.end(); ) {
129 Notifications::iterator curiter = loopiter++;
130 EraseNotification(curiter);
132 unread_count_ = 0;
135 NotificationList::Notifications NotificationList::GetNotificationsByNotifierId(
136 const NotifierId& notifier_id) {
137 Notifications notifications;
138 for (Notifications::iterator iter = notifications_.begin();
139 iter != notifications_.end(); ++iter) {
140 if ((*iter)->notifier_id() == notifier_id)
141 notifications.insert(*iter);
143 return notifications;
146 bool NotificationList::SetNotificationIcon(const std::string& notification_id,
147 const gfx::Image& image) {
148 Notifications::iterator iter = GetNotification(notification_id);
149 if (iter == notifications_.end())
150 return false;
151 (*iter)->set_icon(image);
152 return true;
155 bool NotificationList::SetNotificationImage(const std::string& notification_id,
156 const gfx::Image& image) {
157 Notifications::iterator iter = GetNotification(notification_id);
158 if (iter == notifications_.end())
159 return false;
160 (*iter)->set_image(image);
161 return true;
164 bool NotificationList::SetNotificationButtonIcon(
165 const std::string& notification_id, int button_index,
166 const gfx::Image& image) {
167 Notifications::iterator iter = GetNotification(notification_id);
168 if (iter == notifications_.end())
169 return false;
170 (*iter)->SetButtonIcon(button_index, image);
171 return true;
174 bool NotificationList::HasNotification(const std::string& id) {
175 return GetNotification(id) != notifications_.end();
178 bool NotificationList::HasNotificationOfType(const std::string& id,
179 const NotificationType type) {
180 Notifications::iterator iter = GetNotification(id);
181 if (iter == notifications_.end())
182 return false;
184 return (*iter)->type() == type;
187 bool NotificationList::HasPopupNotifications(
188 const std::vector<NotificationBlocker*>& blockers) {
189 for (Notifications::iterator iter = notifications_.begin();
190 iter != notifications_.end(); ++iter) {
191 if ((*iter)->priority() < DEFAULT_PRIORITY)
192 break;
193 if (!ShouldShowNotificationAsPopup((*iter)->notifier_id(), blockers))
194 continue;
195 if (!(*iter)->shown_as_popup())
196 return true;
198 return false;
201 NotificationList::PopupNotifications NotificationList::GetPopupNotifications(
202 const std::vector<NotificationBlocker*>& blockers,
203 std::list<std::string>* blocked_ids) {
204 PopupNotifications result;
205 size_t default_priority_popup_count = 0;
207 // Collect notifications that should be shown as popups. Start from oldest.
208 for (Notifications::const_reverse_iterator iter = notifications_.rbegin();
209 iter != notifications_.rend(); iter++) {
210 if ((*iter)->shown_as_popup())
211 continue;
213 // No popups for LOW/MIN priority.
214 if ((*iter)->priority() < DEFAULT_PRIORITY)
215 continue;
217 if (!ShouldShowNotificationAsPopup((*iter)->notifier_id(), blockers)) {
218 if (blocked_ids)
219 blocked_ids->push_back((*iter)->id());
220 continue;
223 // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority
224 // will return at most kMaxVisiblePopupNotifications entries. If the
225 // popup entries are more, older entries are used. see crbug.com/165768
226 if ((*iter)->priority() == DEFAULT_PRIORITY &&
227 default_priority_popup_count++ >= kMaxVisiblePopupNotifications) {
228 continue;
231 result.insert(*iter);
233 return result;
236 void NotificationList::MarkSinglePopupAsShown(
237 const std::string& id, bool mark_notification_as_read) {
238 Notifications::iterator iter = GetNotification(id);
239 DCHECK(iter != notifications_.end());
241 if ((*iter)->shown_as_popup())
242 return;
244 // System notification is marked as shown only when marked as read.
245 if ((*iter)->priority() != SYSTEM_PRIORITY || mark_notification_as_read)
246 (*iter)->set_shown_as_popup(true);
248 // The popup notification is already marked as read when it's displayed.
249 // Set the is_read() back to false if necessary.
250 if (!mark_notification_as_read) {
251 (*iter)->set_is_read(false);
252 ++unread_count_;
256 void NotificationList::MarkSinglePopupAsDisplayed(const std::string& id) {
257 Notifications::iterator iter = GetNotification(id);
258 if (iter == notifications_.end())
259 return;
261 if ((*iter)->shown_as_popup())
262 return;
264 if (!(*iter)->is_read()) {
265 (*iter)->set_is_read(true);
266 --unread_count_;
270 void NotificationList::MarkNotificationAsExpanded(const std::string& id) {
271 Notifications::iterator iter = GetNotification(id);
272 if (iter != notifications_.end())
273 (*iter)->set_is_expanded(true);
276 NotificationDelegate* NotificationList::GetNotificationDelegate(
277 const std::string& id) {
278 Notifications::iterator iter = GetNotification(id);
279 if (iter == notifications_.end())
280 return NULL;
281 return (*iter)->delegate();
284 void NotificationList::SetQuietMode(bool quiet_mode) {
285 quiet_mode_ = quiet_mode;
286 if (quiet_mode_) {
287 for (Notifications::iterator iter = notifications_.begin();
288 iter != notifications_.end();
289 ++iter) {
290 (*iter)->set_shown_as_popup(true);
295 const NotificationList::Notifications& NotificationList::GetNotifications() {
296 return notifications_;
299 size_t NotificationList::NotificationCount() const {
300 return notifications_.size();
303 NotificationList::Notifications::iterator NotificationList::GetNotification(
304 const std::string& id) {
305 for (Notifications::iterator iter = notifications_.begin();
306 iter != notifications_.end(); ++iter) {
307 if ((*iter)->id() == id)
308 return iter;
310 return notifications_.end();
313 void NotificationList::EraseNotification(Notifications::iterator iter) {
314 if (!(*iter)->is_read() && (*iter)->priority() > MIN_PRIORITY)
315 --unread_count_;
316 delete *iter;
317 notifications_.erase(iter);
320 void NotificationList::PushNotification(scoped_ptr<Notification> notification) {
321 // Ensure that notification.id is unique by erasing any existing
322 // notification with the same id (shouldn't normally happen).
323 Notifications::iterator iter = GetNotification(notification->id());
324 bool state_inherited = false;
325 if (iter != notifications_.end()) {
326 notification->CopyState(*iter);
327 state_inherited = true;
328 EraseNotification(iter);
329 // if |iter| is unread, EraseNotification decrements |unread_count_| but
330 // actually the count is unchanged since |notification| will be added.
331 if (!notification->is_read())
332 ++unread_count_;
334 // Add the notification to the the list and mark it unread and unshown.
335 if (!state_inherited) {
336 // TODO(mukai): needs to distinguish if a notification is dismissed by
337 // the quiet mode or user operation.
338 notification->set_is_read(false);
339 notification->set_shown_as_popup(message_center_visible_ || quiet_mode_);
340 if (notification->priority() > MIN_PRIORITY)
341 ++unread_count_;
343 // Take ownership. The notification can only be removed from the list
344 // in EraseNotification(), which will delete it.
345 notifications_.insert(notification.release());
348 } // namespace message_center