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"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/image/image.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/message_center/notification_blocker.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_types.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace message_center {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ShouldShowNotificationAsPopup(
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Notification& notification,
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const NotificationBlockers& blockers) {
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < blockers.size(); ++i) {
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!blockers[i]->ShouldShowNotificationAsPopup(notification.notifier_id()))
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return false;
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return true;
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ComparePriorityTimestampSerial::operator()(Notification* n1,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                Notification* n2) {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->priority() > n2->priority())  // Higher pri go first.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->priority() < n2->priority())
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return CompareTimestampSerial()(n1, n2);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->timestamp() > n2->timestamp())  // Newer come first.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->timestamp() < n2->timestamp())
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->serial_number() > n2->serial_number())  // Newer come first.
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (n1->serial_number() < n2->serial_number())
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NotificationList::NotificationList()
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : message_center_visible_(false),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      quiet_mode_(false) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationList::~NotificationList() {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPointers(notifications_.begin(), notifications_.end());
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotificationList::SetMessageCenterVisible(
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool visible,
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::set<std::string>* updated_ids) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_center_visible_ == visible)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_center_visible_ = visible;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!visible)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Notification* notification = *iter;
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool was_popup = notification->shown_as_popup();
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool was_read = notification->IsRead();
807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (notification->priority() < SYSTEM_PRIORITY)
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      notification->set_shown_as_popup(true);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    notification->set_is_read(true);
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (updated_ids && !(was_popup && was_read))
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      updated_ids->insert(notification->id());
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NotificationList::AddNotification(scoped_ptr<Notification> notification) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PushNotification(notification.Pass());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::UpdateNotificationMessage(
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& old_id,
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<Notification> new_notification) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notifications::iterator iter = GetNotification(old_id);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == notifications_.end())
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  new_notification->CopyState(*iter);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Handles priority promotion. If the notification is already dismissed but
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the updated notification has higher priority, it should re-appear as a
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // toast. Notifications coming from websites through the Web Notification API
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // will always re-appear on update.
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if ((*iter)->priority() < new_notification->priority() ||
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new_notification->notifier_id().type == NotifierId::WEB_PAGE) {
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    new_notification->set_is_read(false);
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    new_notification->set_shown_as_popup(false);
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Do not use EraseNotification and PushNotification, since we don't want to
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // change unread counts nor to update is_read/shown_as_popup states.
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Notification* old = *iter;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  notifications_.erase(iter);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delete old;
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // We really don't want duplicate IDs.
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(GetNotification(new_notification->id()) == notifications_.end());
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  notifications_.insert(new_notification.release());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::RemoveNotification(const std::string& id) {
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EraseNotification(GetNotification(id));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)NotificationList::Notifications NotificationList::GetNotificationsByNotifierId(
127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        const NotifierId& notifier_id) {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Notifications notifications;
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if ((*iter)->notifier_id() == notifier_id)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      notifications.insert(*iter);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return notifications;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationList::SetNotificationIcon(const std::string& notification_id,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const gfx::Image& image) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification_id);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == notifications_.end())
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (*iter)->set_icon(image);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationList::SetNotificationImage(const std::string& notification_id,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const gfx::Image& image) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification_id);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == notifications_.end())
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (*iter)->set_image(image);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool NotificationList::SetNotificationButtonIcon(
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& notification_id, int button_index,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Image& image) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification_id);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == notifications_.end())
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  (*iter)->SetButtonIcon(button_index, image);
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool NotificationList::HasNotificationOfType(const std::string& id,
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                             const NotificationType type) {
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (iter == notifications_.end())
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return false;
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return (*iter)->type() == type;
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool NotificationList::HasPopupNotifications(
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const NotificationBlockers& blockers) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != notifications_.end(); ++iter) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() < DEFAULT_PRIORITY)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!ShouldShowNotificationAsPopup(**iter, blockers))
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!(*iter)->shown_as_popup())
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NotificationList::PopupNotifications NotificationList::GetPopupNotifications(
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const NotificationBlockers& blockers,
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::list<std::string>* blocked_ids) {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PopupNotifications result;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t default_priority_popup_count = 0;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Collect notifications that should be shown as popups. Start from oldest.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Notifications::const_reverse_iterator iter = notifications_.rbegin();
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != notifications_.rend(); iter++) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->shown_as_popup())
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No popups for LOW/MIN priority.
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() < DEFAULT_PRIORITY)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!ShouldShowNotificationAsPopup(**iter, blockers)) {
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (blocked_ids)
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        blocked_ids->push_back((*iter)->id());
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // will return at most kMaxVisiblePopupNotifications entries. If the
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // popup entries are more, older entries are used. see crbug.com/165768
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->priority() == DEFAULT_PRIORITY &&
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        default_priority_popup_count++ >= kMaxVisiblePopupNotifications) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result.insert(*iter);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::MarkSinglePopupAsShown(
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& id, bool mark_notification_as_read) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(iter != notifications_.end());
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((*iter)->shown_as_popup())
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // System notification is marked as shown only when marked as read.
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if ((*iter)->priority() != SYSTEM_PRIORITY || mark_notification_as_read)
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (*iter)->set_shown_as_popup(true);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The popup notification is already marked as read when it's displayed.
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set the is_read() back to false if necessary.
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!mark_notification_as_read)
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    (*iter)->set_is_read(false);
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotificationList::MarkSinglePopupAsDisplayed(const std::string& id) {
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (iter == notifications_.end())
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if ((*iter)->shown_as_popup())
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!(*iter)->IsRead())
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*iter)->set_is_read(true);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NotificationDelegate* NotificationList::GetNotificationDelegate(
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& id) {
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (iter == notifications_.end())
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (*iter)->delegate();
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::SetQuietMode(bool quiet_mode) {
262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  quiet_mode_ = quiet_mode;
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (quiet_mode_) {
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    for (Notifications::iterator iter = notifications_.begin();
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)         iter != notifications_.end();
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)         ++iter) {
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      (*iter)->set_shown_as_popup(true);
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Notification* NotificationList::GetNotificationById(const std::string& id) {
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Notifications::iterator iter = GetNotification(id);
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (iter != notifications_.end())
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return *iter;
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return NULL;
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)NotificationList::Notifications NotificationList::GetVisibleNotifications(
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const NotificationBlockers& blockers) const {
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Notifications result;
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (Notifications::const_iterator iter = notifications_.begin();
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != notifications_.end(); ++iter) {
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool should_show = true;
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (size_t i = 0; i < blockers.size(); ++i) {
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (!blockers[i]->ShouldShowNotification((*iter)->notifier_id())) {
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        should_show = false;
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (should_show)
292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      result.insert(*iter);
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return result;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)size_t NotificationList::NotificationCount(
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const NotificationBlockers& blockers) const {
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return GetVisibleNotifications(blockers).size();
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)size_t NotificationList::UnreadCount(
304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const NotificationBlockers& blockers) const {
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Notifications notifications = GetVisibleNotifications(blockers);
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  size_t unread_count = 0;
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (Notifications::const_iterator iter = notifications.begin();
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       iter != notifications.end(); ++iter) {
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!(*iter)->IsRead())
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ++unread_count;
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return unread_count;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)NotificationList::Notifications::iterator NotificationList::GetNotification(
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& id) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Notifications::iterator iter = notifications_.begin();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != notifications_.end(); ++iter) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->id() == id)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return iter;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notifications_.end();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NotificationList::EraseNotification(Notifications::iterator iter) {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete *iter;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_.erase(iter);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationList::PushNotification(scoped_ptr<Notification> notification) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that notification.id is unique by erasing any existing
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notification with the same id (shouldn't normally happen).
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Notifications::iterator iter = GetNotification(notification->id());
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool state_inherited = false;
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (iter != notifications_.end()) {
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    notification->CopyState(*iter);
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state_inherited = true;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EraseNotification(iter);
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add the notification to the the list and mark it unread and unshown.
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!state_inherited) {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(mukai): needs to distinguish if a notification is dismissed by
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the quiet mode or user operation.
344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    notification->set_is_read(false);
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    notification->set_shown_as_popup(message_center_visible_
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     || quiet_mode_
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     || notification->shown_as_popup());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Take ownership. The notification can only be removed from the list
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in EraseNotification(), which will delete it.
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  notifications_.insert(notification.release());
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace message_center
355