desktop_notification_service.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 "chrome/browser/notifications/desktop_notification_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_details.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_provider.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_profile_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification_object_proxy.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification_ui_manager.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/desktop_notification_delegate.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/browser/render_frame_host.h"
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/browser/render_process_host.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/show_desktop_notification_params.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/webui/web_ui_util.h"
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/notifier_settings.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(ENABLE_EXTENSIONS)
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/extensions/api/notifications/notifications_api.h"
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/extensions/extension_service.h"
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/browser/event_router.h"
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/extension_registry.h"
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/browser/extension_system.h"
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_util.h"
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/browser/info_map.h"
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/constants.h"
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/extension.h"
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/extension_set.h"
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochusing blink::WebTextDirection;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing message_center::NotifierId;
640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid CancelNotification(const std::string& id) {
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  g_browser_process->notification_ui_manager()->CancelById(id);
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopNotificationService -------------------------------------------------
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DesktopNotificationService::RegisterProfilePrefs(
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterListPref(
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kMessageCenterDisabledExtensionIds,
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterListPref(
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kMessageCenterDisabledSystemComponentIds,
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionWelcomeNotification::RegisterProfilePrefs(registry);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DesktopNotificationService::CreateDataUrl(
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& icon_url,
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& body,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebTextDirection dir) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> subst;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_url.is_valid()) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_ICON_HTML;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(icon_url.spec());
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title)));
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body)));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // icon float position
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    subst.push_back(dir == blink::WebTextDirectionRightToLeft ?
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "right" : "left");
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (title.empty() || body.empty()) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_1LINE_HTML;
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 line = title.empty() ? body : title;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings are div names in the template file.
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 line_name =
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        title.empty() ? base::ASCIIToUTF16("description")
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      : base::ASCIIToUTF16("title");
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line_name)));
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line)));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_2LINE_HTML;
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title)));
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body)));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // body text direction
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  subst.push_back(dir == blink::WebTextDirectionRightToLeft ?
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "rtl" : "ltr");
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateDataUrl(resource, subst);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DesktopNotificationService::CreateDataUrl(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int resource, const std::vector<std::string>& subst) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece template_html(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResourceBundle::GetSharedInstance().GetRawDataResource(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          resource));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (template_html.empty()) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "unable to load template. ID: " << resource;
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = ReplaceStringPlaceholders(template_html, subst, NULL);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16("data:text/html;charset=utf-8," +
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               net::EscapeQueryParamValue(data, false));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DesktopNotificationService::AddIconNotification(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin_url,
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& message,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Image& icon,
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& replace_id,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationDelegate* delegate,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  Notification notification(origin_url, icon, title, message,
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            blink::WebTextDirectionDefault,
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            base::string16(), replace_id, delegate);
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  g_browser_process->notification_ui_manager()->Add(notification, profile);
1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return notification.delegate_id();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DesktopNotificationService::DesktopNotificationService(
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationUIManager* ui_manager)
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : PermissionContextBase(profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS),
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      profile_(profile),
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ui_manager_(ui_manager),
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_observer_(this),
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      weak_factory_(this) {
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStringListPrefChanged(
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      prefs::kMessageCenterDisabledExtensionIds, &disabled_extension_ids_);
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStringListPrefChanged(
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      prefs::kMessageCenterDisabledSystemComponentIds,
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &disabled_system_component_ids_);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  disabled_extension_id_pref_.Init(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prefs::kMessageCenterDisabledExtensionIds,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_->GetPrefs(),
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &DesktopNotificationService::OnStringListPrefChanged,
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(this),
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(prefs::kMessageCenterDisabledExtensionIds),
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(&disabled_extension_ids_)));
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  disabled_system_component_id_pref_.Init(
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kMessageCenterDisabledSystemComponentIds,
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_->GetPrefs(),
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &DesktopNotificationService::OnStringListPrefChanged,
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(this),
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds),
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(&disabled_system_component_ids_)));
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  extension_registry_observer_.Add(
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extensions::ExtensionRegistry::Get(profile_));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopNotificationService::~DesktopNotificationService() {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DesktopNotificationService::RequestNotificationPermission(
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    content::WebContents* web_contents,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const PermissionRequestID& request_id,
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& requesting_frame,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool user_gesture,
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const NotificationPermissionCallback& callback) {
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RequestPermission(
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      web_contents,
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      request_id,
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      requesting_frame,
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      user_gesture,
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&DesktopNotificationService::OnNotificationPermissionRequested,
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 callback));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid DesktopNotificationService::ShowDesktopNotification(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::ShowDesktopNotificationHostMsgParams& params,
2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::RenderFrameHost* render_frame_host,
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<content::DesktopNotificationDelegate> delegate,
2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::Closure* cancel_callback) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& origin = params.origin;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationObjectProxy* proxy =
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new NotificationObjectProxy(render_frame_host, delegate.Pass());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::string16 display_source = DisplayNameForOriginInProcessId(
2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      origin, render_frame_host->GetProcess()->GetID());
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Notification notification(origin, params.icon_url, params.title,
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      params.body, params.direction, display_source, params.replace_id,
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      proxy);
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The webkit notification doesn't timeout.
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  notification.set_never_timeout(true);
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GetUIManager()->Add(notification, profile_);
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (cancel_callback)
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *cancel_callback = base::Bind(&CancelNotification, proxy->id());
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DesktopNotificationProfileUtil::UsePermission(profile_, origin);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DesktopNotificationService::DisplayNameForOriginInProcessId(
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& origin, int process_id) {
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(ENABLE_EXTENSIONS)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the source is an extension, lookup the display name.
243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (origin.SchemeIs(extensions::kExtensionScheme)) {
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extensions::InfoMap* extension_info_map =
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extensions::ExtensionSystem::Get(profile_)->info_map();
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (extension_info_map) {
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::ExtensionSet extensions;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin(
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          origin,
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          process_id,
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extensions::APIPermission::kNotifications,
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &extensions);
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           iter != extensions.end(); ++iter) {
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id());
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (IsNotifierEnabled(notifier_id))
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return base::UTF8ToUTF16((*iter)->name());
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16(origin.host());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationUIManager* DesktopNotificationService::GetUIManager() {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We defer setting ui_manager_ to the global singleton until we need it
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in order to avoid UI dependent construction during startup.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ui_manager_)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_manager_ = g_browser_process->notification_ui_manager();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui_manager_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool DesktopNotificationService::IsNotifierEnabled(
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const NotifierId& notifier_id) {
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (notifier_id.type) {
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::APPLICATION:
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return disabled_extension_ids_.find(notifier_id.id) ==
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          disabled_extension_ids_.end();
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::WEB_PAGE:
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return DesktopNotificationProfileUtil::GetContentSetting(
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          profile_, notifier_id.url) == CONTENT_SETTING_ALLOW;
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::SYSTEM_COMPONENT:
284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_CHROMEOS)
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return disabled_system_component_ids_.find(notifier_id.id) ==
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          disabled_system_component_ids_.end();
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#else
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // We do not disable system component notifications.
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return true;
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NOTREACHED();
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DesktopNotificationService::SetNotifierEnabled(
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const NotifierId& notifier_id,
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bool enabled) {
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK_NE(NotifierId::WEB_PAGE, notifier_id.type);
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool add_new_item = false;
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* pref_name = NULL;
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::StringValue> id;
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (notifier_id.type) {
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::APPLICATION:
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pref_name = prefs::kMessageCenterDisabledExtensionIds;
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      add_new_item = !enabled;
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      id.reset(new base::StringValue(notifier_id.id));
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      FirePermissionLevelChangedEvent(notifier_id, enabled);
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::SYSTEM_COMPONENT:
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_CHROMEOS)
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pref_name = prefs::kMessageCenterDisabledSystemComponentIds;
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      add_new_item = !enabled;
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      id.reset(new base::StringValue(notifier_id.id));
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#else
318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return;
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(pref_name != NULL);
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ListPrefUpdate update(profile_->GetPrefs(), pref_name);
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::ListValue* const list = update.Get();
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (add_new_item) {
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // AppendIfNotPresent will delete |adding_value| when the same value
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // already exists.
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    list->AppendIfNotPresent(id.release());
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    list->Remove(*id, NULL);
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DesktopNotificationService::ShowWelcomeNotificationIfNecessary(
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const Notification& notification) {
339a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!chrome_now_welcome_notification_) {
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_now_welcome_notification_ =
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ExtensionWelcomeNotification::Create(kChromeNowExtensionID, profile_);
3428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (chrome_now_welcome_notification_) {
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_now_welcome_notification_->ShowWelcomeNotificationIfNecessary(
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        notification);
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DesktopNotificationService::OnStringListPrefChanged(
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* pref_name, std::set<std::string>* ids_field) {
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ids_field->clear();
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const PrefService* pref_service = profile_->GetPrefs();
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(pref_service);
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* pref_list = pref_service->GetList(pref_name);
357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < pref_list->GetSize(); ++i) {
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string element;
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (pref_list->GetString(i, &element) && !element.empty())
360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ids_field->insert(element);
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    else
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(WARNING) << i << "-th element is not a string for " << pref_name;
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DesktopNotificationService::OnExtensionUninstalled(
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    content::BrowserContext* browser_context,
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const extensions::Extension* extension,
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extensions::UninstallReason reason) {
3705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(ENABLE_EXTENSIONS)
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (IsNotifierEnabled(notifier_id))
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The settings for ephemeral apps will be persisted across cache evictions.
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extensions::util::IsEphemeralApp(extension->id(), profile_))
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SetNotifierEnabled(notifier_id, true);
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DesktopNotificationService::OnNotificationPermissionRequested(
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const NotificationPermissionCallback& callback, bool allowed) {
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  blink::WebNotificationPermission permission = allowed ?
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      blink::WebNotificationPermissionAllowed :
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      blink::WebNotificationPermissionDenied;
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  callback.Run(permission);
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DesktopNotificationService::FirePermissionLevelChangedEvent(
3931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const NotifierId& notifier_id, bool enabled) {
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(ENABLE_EXTENSIONS)
3951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_EQ(NotifierId::APPLICATION, notifier_id.type);
3961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extensions::api::notifications::PermissionLevel permission =
3971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      enabled ? extensions::api::notifications::PERMISSION_LEVEL_GRANTED
3981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              : extensions::api::notifications::PERMISSION_LEVEL_DENIED;
3991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<base::ListValue> args(new base::ListValue());
4001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  args->Append(new base::StringValue(
4011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::api::notifications::ToString(permission)));
4021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<extensions::Event> event(new extensions::Event(
4031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::api::notifications::OnPermissionLevelChanged::kEventName,
4041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      args.Pass()));
4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  extensions::EventRouter::Get(profile_)
4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ->DispatchEventToExtension(notifier_id.id, event.Pass());
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Tell the IO thread that this extension's permission for notifications
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // has changed.
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::InfoMap* extension_info_map =
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile_)->info_map();
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserThread::PostTask(
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&extensions::InfoMap::SetNotificationsDisabled,
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 extension_info_map, notifier_id.id, !enabled));
4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
4171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
418