notification_list.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/message_center/notification_list.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_types.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace message_center {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ComparePriorityTimestampSerial::operator()(Notification* n1,
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                Notification* n2) {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->priority() > n2->priority())  // Higher pri go first.
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->priority() < n2->priority())
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return CompareTimestampSerial()(n1, n2);
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->timestamp() > n2->timestamp())  // Newer come first.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->timestamp() < n2->timestamp())
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->serial_number() > n2->serial_number())  // Newer come first.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->serial_number() < n2->serial_number())
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NotificationList::NotificationList()
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : message_center_visible_(false),
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unread_count_(0),
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      quiet_mode_(false) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationList::~NotificationList() {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPointers(notifications_.begin(), notifications_.end());
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotificationList::SetMessageCenterVisible(
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool visible,
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::set<std::string>* updated_ids) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_center_visible_ == visible)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_center_visible_ = visible;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!visible)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unread_count_ = 0;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Notification* notification = *iter;
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (notification->priority() < SYSTEM_PRIORITY)
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      notification->set_shown_as_popup(true);
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    notification->set_is_read(true);
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (updated_ids &&
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !(notification->shown_as_popup() && notification->is_read())) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      updated_ids->insert(notification->id());
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NotificationList::AddNotification(scoped_ptr<Notification> notification) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PushNotification(notification.Pass());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::UpdateNotificationMessage(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& old_id,
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<Notification> new_notification) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notifications::iterator iter = GetNotification(old_id);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == notifications_.end())
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  new_notification->CopyState(*iter);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Handles priority promotion. If the notification is already dismissed but
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the updated notification has higher priority, it should re-appear as a
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // toast.
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if ((*iter)->priority() < new_notification->priority()) {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    new_notification->set_is_read(false);
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    new_notification->set_shown_as_popup(false);
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Do not use EraseNotification and PushNotification, since we don't want to
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // change unread counts nor to update is_read/shown_as_popup states.
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Notification* old = *iter;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  notifications_.erase(iter);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delete old;
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  notifications_.insert(new_notification.release());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::RemoveNotification(const std::string& id) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EraseNotification(GetNotification(id));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationList::RemoveAllNotifications() {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::iterator loopiter = notifications_.begin();
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       loopiter != notifications_.end(); ) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Notifications::iterator curiter = loopiter++;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EraseNotification(curiter);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unread_count_ = 0;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NotificationList::Notifications NotificationList::GetNotificationsBySource(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id) {
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Notifications notifications;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notifications::iterator source_iter = GetNotification(id);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source_iter == notifications_.end())
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return notifications;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string16 display_source = (*source_iter)->display_source();
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if ((*iter)->display_source() == display_source)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      notifications.insert(*iter);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return notifications;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NotificationList::Notifications NotificationList::GetNotificationsByExtension(
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const std::string& id) {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Notifications notifications;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notifications::iterator source_iter = GetNotification(id);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source_iter == notifications_.end())
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return notifications;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string extension_id = (*source_iter)->extension_id();
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if ((*iter)->extension_id() == extension_id)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      notifications.insert(*iter);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return notifications;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationList::SetNotificationIcon(const std::string& notification_id,
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const gfx::Image& image) {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification_id);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == notifications_.end())
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (*iter)->set_icon(image);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationList::SetNotificationImage(const std::string& notification_id,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const gfx::Image& image) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification_id);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == notifications_.end())
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (*iter)->set_image(image);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationList::SetNotificationButtonIcon(
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& notification_id, int button_index,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Image& image) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification_id);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == notifications_.end())
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  (*iter)->SetButtonIcon(button_index, image);
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationList::HasNotification(const std::string& id) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetNotification(id) != notifications_.end();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationList::HasPopupNotifications() {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() < DEFAULT_PRIORITY)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!(*iter)->shown_as_popup())
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationList::PopupNotifications NotificationList::GetPopupNotifications() {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PopupNotifications result;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t default_priority_popup_count = 0;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Collect notifications that should be shown as popups. Start from oldest.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::const_reverse_iterator iter = notifications_.rbegin();
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != notifications_.rend(); iter++) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->shown_as_popup())
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No popups for LOW/MIN priority.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() < DEFAULT_PRIORITY)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // will return at most kMaxVisiblePopupNotifications entries. If the
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // popup entries are more, older entries are used. see crbug.com/165768
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() == DEFAULT_PRIORITY &&
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        default_priority_popup_count++ >= kMaxVisiblePopupNotifications) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result.insert(*iter);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Notification* NotificationList::GetPopup(const std::string& id) {
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PopupNotifications popups = GetPopupNotifications();
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (PopupNotifications::iterator iter = popups.begin(); iter != popups.end();
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       ++iter) {
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if ((*iter)->id() == id)
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return *iter;
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return NULL;
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::MarkPopupsAsShown(int priority) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PopupNotifications popups = GetPopupNotifications();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (PopupNotifications::iterator iter = popups.begin();
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != popups.end(); ++iter) {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() == priority)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (*iter)->set_shown_as_popup(true);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::MarkSinglePopupAsShown(
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& id, bool mark_notification_as_read) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(iter != notifications_.end());
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((*iter)->shown_as_popup())
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // System notification is marked as shown only when marked as read.
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if ((*iter)->priority() != SYSTEM_PRIORITY || mark_notification_as_read)
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (*iter)->set_shown_as_popup(true);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The popup notification is already marked as read when it's displayed.
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set the is_read() back to false if necessary.
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!mark_notification_as_read) {
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    (*iter)->set_is_read(false);
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ++unread_count_;
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotificationList::MarkSinglePopupAsDisplayed(const std::string& id) {
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (iter == notifications_.end())
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if ((*iter)->shown_as_popup())
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!(*iter)->is_read()) {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*iter)->set_is_read(true);
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    --unread_count_;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::MarkNotificationAsExpanded(const std::string& id) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != notifications_.end())
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*iter)->set_is_expanded(true);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NotificationDelegate* NotificationList::GetNotificationDelegate(
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& id) {
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (iter == notifications_.end())
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (*iter)->delegate();
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::SetQuietMode(bool quiet_mode) {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetQuietModeInternal(quiet_mode);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  quiet_mode_timer_.reset();
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::EnterQuietModeWithExpire(
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::TimeDelta& expires_in) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (quiet_mode_timer_.get()) {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Note that the capital Reset() is the method to restart the timer, not
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // scoped_ptr::reset().
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    quiet_mode_timer_->Reset();
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetQuietModeInternal(true);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    quiet_mode_timer_.reset(new base::OneShotTimer<NotificationList>);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    quiet_mode_timer_->Start(FROM_HERE, expires_in, base::Bind(
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &NotificationList::SetQuietMode, base::Unretained(this), false));
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const NotificationList::Notifications& NotificationList::GetNotifications() {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return notifications_;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t NotificationList::NotificationCount() const {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return notifications_.size();
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::SetQuietModeInternal(bool quiet_mode) {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  quiet_mode_ = quiet_mode;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (quiet_mode_) {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (Notifications::iterator iter = notifications_.begin();
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)         iter != notifications_.end();
319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)         ++iter) {
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (*iter)->set_shown_as_popup(true);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NotificationList::Notifications::iterator
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotificationList::GetNotification(const std::string& id) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != notifications_.end(); ++iter) {
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->id() == id)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return iter;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notifications_.end();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationList::EraseNotification(Notifications::iterator iter) {
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!(*iter)->is_read() && (*iter)->priority() > MIN_PRIORITY)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --unread_count_;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete *iter;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_.erase(iter);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::PushNotification(scoped_ptr<Notification> notification) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that notification.id is unique by erasing any existing
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notification with the same id (shouldn't normally happen).
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification->id());
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool state_inherited = false;
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (iter != notifications_.end()) {
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    notification->CopyState(*iter);
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state_inherited = true;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EraseNotification(iter);
3513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // if |iter| is unread, EraseNotification decrements |unread_count_| but
3523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // actually the count is unchanged since |notification| will be added.
3533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!notification->is_read())
3543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      ++unread_count_;
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add the notification to the the list and mark it unread and unshown.
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!state_inherited) {
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(mukai): needs to distinguish if a notification is dismissed by
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the quiet mode or user operation.
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    notification->set_is_read(false);
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    notification->set_shown_as_popup(message_center_visible_ || quiet_mode_);
362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (notification->priority() > MIN_PRIORITY)
363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ++unread_count_;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Take ownership. The notification can only be removed from the list
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in EraseNotification(), which will delete it.
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  notifications_.insert(notification.release());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace message_center
371