desktop_notification_service.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// Use of this source code is governed by a BSD-style license that can be
3d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// found in the LICENSE file.
4d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
5d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/desktop_notification_service.h"
6d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
7d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "base/bind.h"
8d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "base/metrics/histogram.h"
9d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "base/prefs/scoped_user_pref_update.h"
10d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "base/strings/utf_string_conversions.h"
11d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "base/threading/thread.h"
12d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/browser_process.h"
13d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/chrome_notification_types.h"
14d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/desktop_notification_profile_util.h"
15d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/desktop_notification_service_factory.h"
16d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/notification.h"
17d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/notification_object_proxy.h"
18d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/notification_ui_manager.h"
19d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
20d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
21d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/profiles/profile.h"
22d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/ui/browser.h"
23d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/common/pref_names.h"
24d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/common/url_constants.h"
25d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "components/pref_registry/pref_registry_syncable.h"
26d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/browser_thread.h"
27d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/desktop_notification_delegate.h"
28d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/notification_service.h"
29d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/render_frame_host.h"
30d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/render_process_host.h"
31d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/render_view_host.h"
32d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/browser/web_contents.h"
33d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "content/public/common/show_desktop_notification_params.h"
34d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "ui/base/webui/web_ui_util.h"
35d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "ui/message_center/notifier_settings.h"
36d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
37d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(ENABLE_EXTENSIONS)
38d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/extensions/api/notifications/notifications_api.h"
39d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "chrome/browser/extensions/extension_service.h"
40d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/browser/event_router.h"
41d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/browser/extension_registry.h"
42d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/browser/extension_system.h"
43d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/browser/extension_util.h"
44d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/browser/info_map.h"
45d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/common/constants.h"
46d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/common/extension.h"
47d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#include "extensions/common/extension_set.h"
48d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
49d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
50d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberusing blink::WebTextDirection;
51d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberusing content::BrowserThread;
52d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberusing content::RenderViewHost;
53d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberusing content::WebContents;
54d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberusing message_center::NotifierId;
55d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
56d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubernamespace {
57d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
58d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid CancelNotification(const std::string& id) {
59d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  g_browser_process->notification_ui_manager()->CancelById(id);
60d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
61d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
62d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}  // namespace
63d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
64d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// DesktopNotificationService -------------------------------------------------
65d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
66d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// static
67d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid DesktopNotificationService::RegisterProfilePrefs(
68d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    user_prefs::PrefRegistrySyncable* registry) {
69d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  registry->RegisterListPref(
70d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      prefs::kMessageCenterDisabledExtensionIds,
71d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
72d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  registry->RegisterListPref(
73d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      prefs::kMessageCenterDisabledSystemComponentIds,
74d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
75d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
76d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
77d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// static
78d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberstd::string DesktopNotificationService::AddIconNotification(
79d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const GURL& origin_url,
80d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const base::string16& title,
81d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const base::string16& message,
82d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const gfx::Image& icon,
83d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const base::string16& replace_id,
84d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    NotificationDelegate* delegate,
85d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    Profile* profile) {
86d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  Notification notification(message_center::NOTIFICATION_TYPE_SIMPLE,
87d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            origin_url,
88d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            title,
89d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            message,
90d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            icon,
91d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            blink::WebTextDirectionDefault,
92d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            message_center::NotifierId(origin_url),
93d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            base::string16(),
94d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            replace_id,
95d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            message_center::RichNotificationData(),
96d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                            delegate);
97d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  g_browser_process->notification_ui_manager()->Add(notification, profile);
98d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  return notification.delegate_id();
99d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
100d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
101d9618f23226f46c752e56f712bc4b505117d8b4bAndreas HuberDesktopNotificationService::DesktopNotificationService(Profile* profile)
102d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    : PermissionContextBase(profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS),
103d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      profile_(profile),
104d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(ENABLE_EXTENSIONS)
105d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      extension_registry_observer_(this),
106d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
107d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      weak_factory_(this) {
108d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  OnStringListPrefChanged(
109d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      prefs::kMessageCenterDisabledExtensionIds, &disabled_extension_ids_);
110d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  OnStringListPrefChanged(
111d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      prefs::kMessageCenterDisabledSystemComponentIds,
112d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      &disabled_system_component_ids_);
113d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  disabled_extension_id_pref_.Init(
114d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      prefs::kMessageCenterDisabledExtensionIds,
115d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      profile_->GetPrefs(),
116d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      base::Bind(
117d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          &DesktopNotificationService::OnStringListPrefChanged,
118d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          base::Unretained(this),
119d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          base::Unretained(prefs::kMessageCenterDisabledExtensionIds),
120d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          base::Unretained(&disabled_extension_ids_)));
121d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  disabled_system_component_id_pref_.Init(
122d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      prefs::kMessageCenterDisabledSystemComponentIds,
123d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      profile_->GetPrefs(),
124d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      base::Bind(
125d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          &DesktopNotificationService::OnStringListPrefChanged,
126d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          base::Unretained(this),
127d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds),
128d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          base::Unretained(&disabled_system_component_ids_)));
129d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(ENABLE_EXTENSIONS)
130d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  extension_registry_observer_.Add(
131d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      extensions::ExtensionRegistry::Get(profile_));
132d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
133d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
134d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
135d9618f23226f46c752e56f712bc4b505117d8b4bAndreas HuberDesktopNotificationService::~DesktopNotificationService() {
136d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
137d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
138d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid DesktopNotificationService::RequestNotificationPermission(
139d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    content::WebContents* web_contents,
140d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const PermissionRequestID& request_id,
141d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const GURL& requesting_frame,
142d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    bool user_gesture,
143d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const NotificationPermissionCallback& callback) {
144d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  RequestPermission(
146d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      web_contents,
147d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      request_id,
148d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      requesting_frame,
149d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      user_gesture,
150d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      base::Bind(&DesktopNotificationService::OnNotificationPermissionRequested,
151d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                 weak_factory_.GetWeakPtr(),
152d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber                 callback));
153d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
154d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
155d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid DesktopNotificationService::ShowDesktopNotification(
156d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const content::ShowDesktopNotificationHostMsgParams& params,
157d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    content::RenderFrameHost* render_frame_host,
158d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    scoped_ptr<content::DesktopNotificationDelegate> delegate,
159d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    base::Closure* cancel_callback) {
160d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  const GURL& origin = params.origin;
162d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  NotificationObjectProxy* proxy =
163d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      new NotificationObjectProxy(render_frame_host, delegate.Pass());
164d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
165d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  base::string16 display_source = DisplayNameForOriginInProcessId(
166d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      origin, render_frame_host->GetProcess()->GetID());
167d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  Notification notification(origin, params.icon_url, params.title,
168d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      params.body, params.direction, display_source, params.replace_id,
169d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      proxy);
170d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
171d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  // The webkit notification doesn't timeout.
172d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  notification.set_never_timeout(true);
173d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
174d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  g_browser_process->notification_ui_manager()->Add(notification, profile_);
175d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  if (cancel_callback)
176d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    *cancel_callback = base::Bind(&CancelNotification, proxy->id());
177d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
178d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  DesktopNotificationProfileUtil::UsePermission(profile_, origin);
179d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
180d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
181d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberbase::string16 DesktopNotificationService::DisplayNameForOriginInProcessId(
182d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const GURL& origin, int process_id) {
183d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(ENABLE_EXTENSIONS)
184d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  // If the source is an extension, lookup the display name.
185d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  if (origin.SchemeIs(extensions::kExtensionScheme)) {
186d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    extensions::InfoMap* extension_info_map =
187d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber        extensions::ExtensionSystem::Get(profile_)->info_map();
188d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    if (extension_info_map) {
189d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      extensions::ExtensionSet extensions;
190d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin(
191d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          origin,
192d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          process_id,
193d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          extensions::APIPermission::kNotifications,
194d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          &extensions);
195d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
196d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber           iter != extensions.end(); ++iter) {
197d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber        NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id());
198d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber        if (IsNotifierEnabled(notifier_id))
199d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          return base::UTF8ToUTF16((*iter)->name());
200d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      }
201d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    }
202d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  }
203d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
204d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
205d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  return base::UTF8ToUTF16(origin.host());
206d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
207d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
208d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huberbool DesktopNotificationService::IsNotifierEnabled(
209d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const NotifierId& notifier_id) {
210d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  switch (notifier_id.type) {
211d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    case NotifierId::APPLICATION:
212d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      return disabled_extension_ids_.find(notifier_id.id) ==
213d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          disabled_extension_ids_.end();
214d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    case NotifierId::WEB_PAGE:
215d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      return DesktopNotificationProfileUtil::GetContentSetting(
216d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          profile_, notifier_id.url) == CONTENT_SETTING_ALLOW;
217d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    case NotifierId::SYSTEM_COMPONENT:
218d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(OS_CHROMEOS)
219d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      return disabled_system_component_ids_.find(notifier_id.id) ==
220d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber          disabled_system_component_ids_.end();
221d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#else
222d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      // We do not disable system component notifications.
223d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      return true;
224d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
225d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  }
226d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
227d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  NOTREACHED();
228d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  return false;
229d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
230d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
231d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid DesktopNotificationService::SetNotifierEnabled(
232d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const NotifierId& notifier_id,
233d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    bool enabled) {
234d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  DCHECK_NE(NotifierId::WEB_PAGE, notifier_id.type);
235d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
236d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  bool add_new_item = false;
237d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  const char* pref_name = NULL;
238d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  scoped_ptr<base::StringValue> id;
239d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  switch (notifier_id.type) {
240d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    case NotifierId::APPLICATION:
241d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      pref_name = prefs::kMessageCenterDisabledExtensionIds;
242d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      add_new_item = !enabled;
243d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      id.reset(new base::StringValue(notifier_id.id));
244d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      FirePermissionLevelChangedEvent(notifier_id, enabled);
245d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      break;
246d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    case NotifierId::SYSTEM_COMPONENT:
247d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(OS_CHROMEOS)
248d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      pref_name = prefs::kMessageCenterDisabledSystemComponentIds;
249d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      add_new_item = !enabled;
250d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      id.reset(new base::StringValue(notifier_id.id));
251d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#else
252d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      return;
253d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
254d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      break;
255d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    default:
256d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      NOTREACHED();
257d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  }
258d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  DCHECK(pref_name != NULL);
259d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
260d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  ListPrefUpdate update(profile_->GetPrefs(), pref_name);
261d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  base::ListValue* const list = update.Get();
262d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  if (add_new_item) {
263d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    // AppendIfNotPresent will delete |adding_value| when the same value
264d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    // already exists.
265d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    list->AppendIfNotPresent(id.release());
266d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  } else {
267d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    list->Remove(*id, NULL);
268d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  }
269d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
270d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
271d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid DesktopNotificationService::OnStringListPrefChanged(
272d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const char* pref_name, std::set<std::string>* ids_field) {
273d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  ids_field->clear();
274d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
275d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  const PrefService* pref_service = profile_->GetPrefs();
276d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  CHECK(pref_service);
277d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  const base::ListValue* pref_list = pref_service->GetList(pref_name);
278d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  for (size_t i = 0; i < pref_list->GetSize(); ++i) {
279d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    std::string element;
280d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    if (pref_list->GetString(i, &element) && !element.empty())
281d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      ids_field->insert(element);
282d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    else
283d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber      LOG(WARNING) << i << "-th element is not a string for " << pref_name;
284d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  }
285d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
286d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
287d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#if defined(ENABLE_EXTENSIONS)
288d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Hubervoid DesktopNotificationService::OnExtensionUninstalled(
289d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    content::BrowserContext* browser_context,
290d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    const extensions::Extension* extension,
291d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    extensions::UninstallReason reason) {
292d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
293d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  if (IsNotifierEnabled(notifier_id))
294d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    return;
295d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
296d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  // The settings for ephemeral apps will be persisted across cache evictions.
297d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  if (extensions::util::IsEphemeralApp(extension->id(), profile_))
298d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber    return;
299d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
300d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber  SetNotifierEnabled(notifier_id, true);
301d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber}
302d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber#endif
303d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber
304d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// Unlike other permission types, granting a notification for a given origin
305d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// will not take into account the |embedder_origin|, it will only be based
306d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// on the requesting iframe origin.
307d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// TODO(mukai) Consider why notifications behave differently than
308d9618f23226f46c752e56f712bc4b505117d8b4bAndreas Huber// other permissions. crbug.com/416894
309void DesktopNotificationService::UpdateContentSetting(
310    const GURL& requesting_origin,
311    const GURL& embedder_origin,
312    bool allowed) {
313  if (allowed) {
314    DesktopNotificationProfileUtil::GrantPermission(
315        profile_, requesting_origin);
316  } else {
317    DesktopNotificationProfileUtil::DenyPermission(profile_, requesting_origin);
318  }
319}
320
321void DesktopNotificationService::OnNotificationPermissionRequested(
322    const NotificationPermissionCallback& callback, bool allowed) {
323  blink::WebNotificationPermission permission = allowed ?
324      blink::WebNotificationPermissionAllowed :
325      blink::WebNotificationPermissionDenied;
326
327  callback.Run(permission);
328}
329
330void DesktopNotificationService::FirePermissionLevelChangedEvent(
331    const NotifierId& notifier_id, bool enabled) {
332#if defined(ENABLE_EXTENSIONS)
333  DCHECK_EQ(NotifierId::APPLICATION, notifier_id.type);
334  extensions::api::notifications::PermissionLevel permission =
335      enabled ? extensions::api::notifications::PERMISSION_LEVEL_GRANTED
336              : extensions::api::notifications::PERMISSION_LEVEL_DENIED;
337  scoped_ptr<base::ListValue> args(new base::ListValue());
338  args->Append(new base::StringValue(
339      extensions::api::notifications::ToString(permission)));
340  scoped_ptr<extensions::Event> event(new extensions::Event(
341      extensions::api::notifications::OnPermissionLevelChanged::kEventName,
342      args.Pass()));
343  extensions::EventRouter::Get(profile_)
344      ->DispatchEventToExtension(notifier_id.id, event.Pass());
345
346  // Tell the IO thread that this extension's permission for notifications
347  // has changed.
348  extensions::InfoMap* extension_info_map =
349      extensions::ExtensionSystem::Get(profile_)->info_map();
350  BrowserThread::PostTask(
351      BrowserThread::IO, FROM_HERE,
352      base::Bind(&extensions::InfoMap::SetNotificationsDisabled,
353                 extension_info_map, notifier_id.id, !enabled));
354#endif
355}
356