message_center_notification_manager.cc revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/message_center_notification_manager.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/chrome_notification_types.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/extension_info_map.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service_factory.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/message_center_settings_controller.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/notifications/notification.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/chrome_pages.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension_set.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "content/public/browser/notification_service.h"
242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "content/public/browser/user_metrics.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/common/url_constants.h"
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/message_center/message_center_style.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/message_center_tray.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/notifier_settings.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The first-run balloon will be shown |kFirstRunIdleDelaySeconds| after all
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// popups go away and the user has notifications in the message center.
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kFirstRunIdleDelaySeconds = 1;
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::MessageCenterNotificationManager(
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    message_center::MessageCenter* message_center,
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PrefService* local_state)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : message_center_(message_center),
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_WIN)
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      first_run_idle_timeout_(
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::TimeDelta::FromSeconds(kFirstRunIdleDelaySeconds)),
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      weak_factory_(this),
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      settings_controller_(new MessageCenterSettingsController) {
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_WIN)
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  first_run_pref_.Init(prefs::kMessageCenterShowedFirstRunBalloon, local_state);
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_center_->SetDelegate(this);
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  message_center_->AddObserver(this);
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message_center_->SetNotifierSettingsProvider(settings_controller_.get());
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX) \
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  || (defined(USE_AURA) && !defined(USE_ASH))
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // On Windows, Linux and Mac, the notification manager owns the tray icon and
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // views.Other platforms have global ownership and Create will return NULL.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tray_.reset(message_center::CreateMessageCenterTray());
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  registrar_.Add(this,
622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                 content::NotificationService::AllSources());
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::~MessageCenterNotificationManager() {
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  message_center_->RemoveObserver(this);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationUIManager
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst Notification* MessageCenterNotificationManager::FindById(
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const std::string& id) const {
75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const Notification* notification = NotificationUIManagerImpl::FindById(id);
76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (notification)
77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return notification;
78558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  NotificationMap::const_iterator iter = profile_notifications_.find(id);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == profile_notifications_.end())
80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return NULL;
81558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return &(iter->second->notification());
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessageCenterNotificationManager::CancelById(const std::string& id) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See if this ID hasn't been shown yet.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NotificationUIManagerImpl::CancelById(id))
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it has been shown, remove it.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotificationMap::iterator iter = profile_notifications_.find(id);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == profile_notifications_.end())
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  message_center_->RemoveNotification(id, /* by_user */ false);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::set<std::string>
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)MessageCenterNotificationManager::GetAllIdsByProfileAndSourceOrigin(
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Profile* profile,
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const GURL& source) {
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::set<std::string> notification_ids =
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      NotificationUIManagerImpl::GetAllIdsByProfileAndSourceOrigin(profile,
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                                   source);
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (NotificationMap::iterator iter = profile_notifications_.begin();
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       iter != profile_notifications_.end(); iter++) {
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if ((*iter).second->notification().origin_url() == source &&
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        profile == (*iter).second->profile()) {
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      notification_ids.insert(iter->first);
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return notification_ids;
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessageCenterNotificationManager::CancelAllBySourceOrigin(
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& source) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Same pattern as CancelById, but more complicated than the above
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // because there may be multiple notifications from the same source.
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool removed = NotificationUIManagerImpl::CancelAllBySourceOrigin(source);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (NotificationMap::iterator loopiter = profile_notifications_.begin();
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       loopiter != profile_notifications_.end(); ) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotificationMap::iterator curiter = loopiter++;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*curiter).second->notification().origin_url() == source) {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      message_center_->RemoveNotification(curiter->first, /* by_user */ false);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      removed = true;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return removed;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessageCenterNotificationManager::CancelAllByProfile(Profile* profile) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Same pattern as CancelAllBySourceOrigin.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool removed = NotificationUIManagerImpl::CancelAllByProfile(profile);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (NotificationMap::iterator loopiter = profile_notifications_.begin();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       loopiter != profile_notifications_.end(); ) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotificationMap::iterator curiter = loopiter++;
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (profile == (*curiter).second->profile()) {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      message_center_->RemoveNotification(curiter->first, /* by_user */ false);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      removed = true;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return removed;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::CancelAll() {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotificationUIManagerImpl::CancelAll();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  message_center_->RemoveAllNotifications(/* by_user */ false);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NotificationUIManagerImpl
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessageCenterNotificationManager::ShowNotification(
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Notification& notification, Profile* profile) {
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (message_center_->IsMessageCenterVisible())
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (UpdateNotification(notification, profile))
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddProfileNotification(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ProfileNotification(profile, notification, message_center_));
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessageCenterNotificationManager::UpdateNotification(
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Notification& notification, Profile* profile) {
173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Only progress notification update can be reflected immediately in the
174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // message center.
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool update_progress_notification =
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS;
177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool is_message_center_visible = message_center_->IsMessageCenterVisible();
178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!update_progress_notification && is_message_center_visible)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const string16& replace_id = notification.replace_id();
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (replace_id.empty())
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL origin_url = notification.origin_url();
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(origin_url.is_valid());
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since replace_id is provided by arbitrary JS, we need to use origin_url
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (which is an app url in case of app/extension) to scope the replace ids
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in the given profile.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (NotificationMap::iterator iter = profile_notifications_.begin();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != profile_notifications_.end(); ++iter) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProfileNotification* old_notification = (*iter).second;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (old_notification->notification().replace_id() == replace_id &&
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        old_notification->notification().origin_url() == origin_url &&
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        old_notification->profile() == profile) {
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // Changing the type from non-progress to progress does not count towards
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      // the immediate update allowed in the message center.
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (update_progress_notification && is_message_center_visible &&
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          old_notification->notification().type() !=
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              message_center::NOTIFICATION_TYPE_PROGRESS) {
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string old_id =
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          old_notification->notification().notification_id();
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DCHECK(message_center_->HasNotification(old_id));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Add/remove notification in the local list but just update the same
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // one in MessageCenter.
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delete old_notification;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_notifications_.erase(old_id);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProfileNotification* new_notification =
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new ProfileNotification(profile, notification, message_center_);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_notifications_[notification.notification_id()] = new_notification;
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Now pass a copy to message center.
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      scoped_ptr<message_center::Notification> message_center_notification(
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          make_scoped_ptr(new message_center::Notification(notification)));
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      message_center_notification->set_extension_id(
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          new_notification->GetExtensionId());
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message_center_->UpdateNotification(old_id,
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          message_center_notification.Pass());
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_notification->StartDownloads();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MessageCenter::Delegate
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::DisableExtension(
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& notification_id) {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileNotification* profile_notification =
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FindProfileNotification(notification_id);
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile_notification)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string extension_id = profile_notification->GetExtensionId();
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!extension_id.empty());  // or UI should not have enabled the command.
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DesktopNotificationService* service =
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DesktopNotificationServiceFactory::GetForProfile(
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          profile_notification->profile());
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message_center::NotifierId notifier_id(
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      message_center::NotifierId::APPLICATION, extension_id);
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  service->SetNotifierEnabled(notifier_id, false);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::DisableNotificationsFromSource(
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& notification_id) {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileNotification* profile_notification =
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FindProfileNotification(notification_id);
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile_notification)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // UI should not have enabled the command if there is no valid source.
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(profile_notification->notification().origin_url().is_valid());
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DesktopNotificationService* service =
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DesktopNotificationServiceFactory::GetForProfile(
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          profile_notification->profile());
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile_notification->notification().origin_url().scheme() ==
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome::kChromeUIScheme) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string name =
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        profile_notification->notification().origin_url().host();
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    message_center::NotifierId notifier_id(
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        message_center::ParseSystemComponentName(name));
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    service->SetNotifierEnabled(notifier_id, false);
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    service->DenyPermission(profile_notification->notification().origin_url());
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::ShowSettings(
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& notification_id) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The per-message-center Settings button passes an empty string.
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (notification_id.empty()) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTIMPLEMENTED();
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProfileNotification* profile_notification =
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FindProfileNotification(notification_id);
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!profile_notification)
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* browser =
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::FindOrCreateTabbedBrowser(profile_notification->profile(),
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        chrome::HOST_DESKTOP_TYPE_NATIVE);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (profile_notification->GetExtensionId().empty())
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::ShowContentSettings(browser, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chrome::ShowExtensions(browser, std::string());
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// MessageCenter::Observer
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MessageCenterNotificationManager::OnNotificationRemoved(
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& notification_id,
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool by_user) {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Do not call FindProfileNotification(). Some tests create notifications
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // directly to MessageCenter, but this method will be called for the removals
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // of such notifications.
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NotificationMap::const_iterator iter =
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_notifications_.find(notification_id);
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (iter != profile_notifications_.end())
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RemoveProfileNotification(iter->second, by_user);
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_WIN)
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CheckFirstRunTimer();
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MessageCenterNotificationManager::OnNotificationCenterClosed() {
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // When the center is open it halts all notifications, so we need to listen
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // for events indicating it's been closed.
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CheckAndShowNotifications();
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_WIN)
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CheckFirstRunTimer();
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MessageCenterNotificationManager::OnNotificationUpdated(
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& notification_id) {
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_WIN)
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CheckFirstRunTimer();
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MessageCenterNotificationManager::SetMessageCenterTrayDelegateForTest(
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    message_center::MessageCenterTrayDelegate* delegate) {
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  tray_.reset(delegate);
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid MessageCenterNotificationManager::Observe(
3382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    int type,
3392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::NotificationSource& source,
3402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const content::NotificationDetails& details) {
3412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (type == chrome::NOTIFICATION_FULLSCREEN_CHANGED) {
3422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const bool is_fullscreen = *content::Details<bool>(details).ptr();
3432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (is_fullscreen && tray_.get() && tray_->GetMessageCenterTray())
3452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      tray_->GetMessageCenterTray()->HidePopupBubble();
3462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  } else {
3472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    NotificationUIManagerImpl::Observe(type, source, details);
3482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
3492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ImageDownloads
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::ImageDownloads::ImageDownloads(
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    message_center::MessageCenter* message_center,
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ImageDownloadsObserver* observer)
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : message_center_(message_center),
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pending_downloads_(0),
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      observer_(observer) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::ImageDownloads::~ImageDownloads() { }
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::ImageDownloads::StartDownloads(
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Notification& notification) {
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // In case all downloads are synchronous, assume a pending download.
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AddPendingDownload();
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notification primary icon.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartDownloadWithImage(
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      notification,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &notification.icon(),
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      notification.icon_url(),
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message_center::kNotificationIconSize,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&message_center::MessageCenter::SetNotificationIcon,
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(message_center_),
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 notification.notification_id()));
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notification image.
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StartDownloadWithImage(
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      notification,
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      NULL,
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      notification.image_url(),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message_center::kNotificationPreferredImageSize,
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&message_center::MessageCenter::SetNotificationImage,
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(message_center_),
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 notification.notification_id()));
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notification button icons.
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StartDownloadWithImage(
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      notification,
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      NULL,
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      notification.button_one_icon_url(),
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message_center::kNotificationButtonIconSize,
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon,
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(message_center_),
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 notification.notification_id(),
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 0));
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StartDownloadWithImage(
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      notification,
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      NULL,
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      notification.button_two_icon_url(),
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message_center::kNotificationButtonIconSize,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(message_center_),
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 notification.notification_id(),
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 1));
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This should tell the observer we're done if everything was synchronous.
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PendingDownloadCompleted();
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::ImageDownloads::StartDownloadWithImage(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Notification& notification,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Image* image,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& url,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int size,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SetImageCallback& callback) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set the image directly if we have it.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (image && !image->IsEmpty()) {
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(*image);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Leave the image null if there's no URL.
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url.is_empty())
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::RenderViewHost* host = notification.GetRenderViewHost();
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!host) {
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Notification needs an image but has no RenderViewHost";
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* contents =
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::WebContents::FromRenderViewHost(host);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!contents) {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Notification needs an image but has no WebContents";
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AddPendingDownload();
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  contents->DownloadImage(
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url,
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      false,  // Not a favicon
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      size,  // Preferred size
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      0,  // No maximum size
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &MessageCenterNotificationManager::ImageDownloads::DownloadComplete,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          AsWeakPtr(),
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          callback));
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::ImageDownloads::DownloadComplete(
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SetImageCallback& callback,
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int download_id,
45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int http_status_code,
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& image_url,
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int requested_size,
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<SkBitmap>& bitmaps) {
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PendingDownloadCompleted();
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bitmaps.empty())
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmaps[0]);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(image);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Private methods.
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MessageCenterNotificationManager::ImageDownloads::AddPendingDownload() {
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ++pending_downloads_;
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MessageCenterNotificationManager::ImageDownloads::PendingDownloadCompleted() {
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(pending_downloads_ > 0);
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--pending_downloads_ == 0 && observer_)
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    observer_->OnDownloadsCompleted();
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ProfileNotification
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::ProfileNotification::ProfileNotification(
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile,
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Notification& notification,
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    message_center::MessageCenter* message_center)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile),
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      notification_(notification),
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      downloads_(new ImageDownloads(message_center, this)) {
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(profile);
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::ProfileNotification::~ProfileNotification() {
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::ProfileNotification::StartDownloads() {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  downloads_->StartDownloads(notification_);
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)MessageCenterNotificationManager::ProfileNotification::OnDownloadsCompleted() {
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  notification_.DoneRendering();
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageCenterNotificationManager::ProfileNotification::GetExtensionId() {
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExtensionInfoMap* extension_info_map =
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile())->info_map();
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExtensionSet extensions;
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin(
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      notification().origin_url(), notification().process_id(),
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::APIPermission::kNotification, &extensions);
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DesktopNotificationService* desktop_service =
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DesktopNotificationServiceFactory::GetForProfile(profile());
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (ExtensionSet::const_iterator iter = extensions.begin();
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != extensions.end(); ++iter) {
521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (desktop_service->IsNotifierEnabled(message_center::NotifierId(
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            message_center::NotifierId::APPLICATION, (*iter)->id()))) {
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return (*iter)->id();
524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// private
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::AddProfileNotification(
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProfileNotification* profile_notification) {
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Notification& notification = profile_notification->notification();
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string id = notification.notification_id();
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notification ids should be unique.
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(profile_notifications_.find(id) == profile_notifications_.end());
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_notifications_[id] = profile_notification;
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Create the copy for message center, and ensure the extension ID is correct.
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<message_center::Notification> message_center_notification(
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new message_center::Notification(notification));
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  message_center_notification->set_extension_id(
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile_notification->GetExtensionId());
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  message_center_->AddNotification(message_center_notification.Pass());
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_notification->StartDownloads();
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessageCenterNotificationManager::RemoveProfileNotification(
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProfileNotification* profile_notification,
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool by_user) {
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_notification->notification().Close(by_user);
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string id = profile_notification->notification().notification_id();
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  profile_notifications_.erase(id);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete profile_notification;
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessageCenterNotificationManager::ProfileNotification*
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageCenterNotificationManager::FindProfileNotification(
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const std::string& id) const {
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotificationMap::const_iterator iter = profile_notifications_.find(id);
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (iter == profile_notifications_.end())
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (*iter).second;
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
568