desktop_notification_service.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/api/notifications/notifications_api.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/infobars/confirm_infobar_delegate.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service_factory.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification_object_proxy.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification_ui_manager.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings_pattern.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/infobars/core/infobar.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/browser/render_frame_host.h"
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/browser/render_process_host.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/show_desktop_notification_params.h"
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/info_map.h"
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h"
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension.h"
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/webui/web_ui_util.h"
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "ui/message_center/message_center_util.h"
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/message_center/notifier_settings.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochusing blink::WebTextDirection;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing message_center::NotifierId;
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kChromeNowExtensionID[] = "pafkbggdmjlpgkdkcbjmhmfcdpncadgh";
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// NotificationPermissionRequest ---------------------------------------
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NotificationPermissionRequest : public PermissionBubbleRequest {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotificationPermissionRequest(
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DesktopNotificationService* notification_service,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const GURL& origin,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::string16 display_name,
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const base::Closure& callback);
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~NotificationPermissionRequest();
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PermissionBubbleDelegate:
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual int GetIconID() const OVERRIDE;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual base::string16 GetMessageText() const OVERRIDE;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual base::string16 GetMessageTextFragment() const OVERRIDE;
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool HasUserGesture() const OVERRIDE;
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual GURL GetRequestingHostname() const OVERRIDE;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void PermissionGranted() OVERRIDE;
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void PermissionDenied() OVERRIDE;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Cancelled() OVERRIDE;
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RequestFinished() OVERRIDE;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The notification service to be used.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DesktopNotificationService* notification_service_;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The origin we are asking for permissions on.
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL origin_;
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The display name for the origin to be displayed.  Will be different from
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // origin_ for extensions.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 display_name_;
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // The callback information that tells us how to respond to javascript.
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::Closure callback_;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Whether the user clicked one of the buttons.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool action_taken_;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionRequest);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationPermissionRequest::NotificationPermissionRequest(
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DesktopNotificationService* notification_service,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const GURL& origin,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 display_name,
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::Closure& callback)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : notification_service_(notification_service),
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      origin_(origin),
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      display_name_(display_name),
1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      callback_(callback),
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      action_taken_(false) {}
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationPermissionRequest::~NotificationPermissionRequest() {}
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int NotificationPermissionRequest::GetIconID() const {
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return IDR_INFOBAR_DESKTOP_NOTIFICATIONS;
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 NotificationPermissionRequest::GetMessageText() const {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    display_name_);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NotificationPermissionRequest::GetMessageTextFragment() const {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return l10n_util::GetStringUTF16(IDS_NOTIFICATION_PERMISSIONS_FRAGMENT);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool NotificationPermissionRequest::HasUserGesture() const {
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Currently notification permission requests are only issued on
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // user gesture.
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GURL NotificationPermissionRequest::GetRequestingHostname() const {
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return origin_;
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationPermissionRequest::PermissionGranted() {
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_taken_ = true;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  notification_service_->GrantPermission(origin_);
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationPermissionRequest::PermissionDenied() {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  action_taken_ = true;
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  notification_service_->DenyPermission(origin_);
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationPermissionRequest::Cancelled() {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotificationPermissionRequest::RequestFinished() {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!action_taken_)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  callback_.Run();
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete this;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NotificationPermissionInfoBarDelegate --------------------------------------
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The delegate for the infobar shown when an origin requests notification
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// permissions.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Creates a notification permission infobar and delegate and adds the infobar
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // to |infobar_service|.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void Create(InfoBarService* infobar_service,
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     DesktopNotificationService* notification_service,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const GURL& origin,
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const base::string16& display_name,
1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                     const base::Closure& callback);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationPermissionInfoBarDelegate(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DesktopNotificationService* notification_service,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& origin,
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16& display_name,
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const base::Closure& callback);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~NotificationPermissionInfoBarDelegate();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ConfirmInfoBarDelegate:
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual int GetIconID() const OVERRIDE;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Type GetInfoBarType() const OVERRIDE;
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetMessageText() const OVERRIDE;
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Accept() OVERRIDE;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Cancel() OVERRIDE;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The origin we are asking for permissions on.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL origin_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The display name for the origin to be displayed.  Will be different from
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // origin_ for extensions.
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 display_name_;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The notification service to be used.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DesktopNotificationService* notification_service_;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // The callback information that tells us how to respond to javascript.
2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::Closure callback_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the user clicked one of the buttons.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool action_taken_;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotificationPermissionInfoBarDelegate::Create(
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DesktopNotificationService* notification_service,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& display_name,
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::Closure& callback) {
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_ptr<ConfirmInfoBarDelegate>(
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          new NotificationPermissionInfoBarDelegate(
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              notification_service, origin, display_name, callback))));
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DesktopNotificationService* notification_service,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& display_name,
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::Closure& callback)
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : ConfirmInfoBarDelegate(),
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin_(origin),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_name_(display_name),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notification_service_(notification_service),
2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      callback_(callback),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      action_taken_(false) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationPermissionInfoBarDelegate::
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~NotificationPermissionInfoBarDelegate() {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!action_taken_)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  callback_.Run();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int NotificationPermissionInfoBarDelegate::GetIconID() const {
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return IDR_INFOBAR_DESKTOP_NOTIFICATIONS;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochinfobars::InfoBarDelegate::Type
2630529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochNotificationPermissionInfoBarDelegate::GetInfoBarType() const {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PAGE_ACTION_TYPE;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 NotificationPermissionInfoBarDelegate::GetMessageText() const {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    display_name_);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 NotificationPermissionInfoBarDelegate::GetButtonLabel(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoBarButton button) const {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_NOTIFICATION_PERMISSION_YES : IDS_NOTIFICATION_PERMISSION_NO);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPermissionInfoBarDelegate::Accept() {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_service_->GrantPermission(origin_);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action_taken_ = true;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPermissionInfoBarDelegate::Cancel() {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_service_->DenyPermission(origin_);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action_taken_ = true;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid CancelNotification(const std::string& id) {
2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  g_browser_process->notification_ui_manager()->CancelById(id);
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace
2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopNotificationService -------------------------------------------------
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DesktopNotificationService::RegisterProfilePrefs(
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterListPref(
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kMessageCenterDisabledExtensionIds,
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterListPref(
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kMessageCenterDisabledSystemComponentIds,
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registry->RegisterListPref(
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      prefs::kMessageCenterEnabledSyncNotifierIds,
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionWelcomeNotification::RegisterProfilePrefs(registry);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DesktopNotificationService::CreateDataUrl(
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL& icon_url,
319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& body,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebTextDirection dir) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> subst;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_url.is_valid()) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_ICON_HTML;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(icon_url.spec());
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title)));
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body)));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // icon float position
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    subst.push_back(dir == blink::WebTextDirectionRightToLeft ?
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "right" : "left");
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (title.empty() || body.empty()) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_1LINE_HTML;
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 line = title.empty() ? body : title;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings are div names in the template file.
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 line_name =
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        title.empty() ? base::ASCIIToUTF16("description")
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      : base::ASCIIToUTF16("title");
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line_name)));
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(line)));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_2LINE_HTML;
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(title)));
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(base::UTF16ToUTF8(body)));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // body text direction
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  subst.push_back(dir == blink::WebTextDirectionRightToLeft ?
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "rtl" : "ltr");
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateDataUrl(resource, subst);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DesktopNotificationService::CreateDataUrl(
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int resource, const std::vector<std::string>& subst) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece template_html(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResourceBundle::GetSharedInstance().GetRawDataResource(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          resource));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (template_html.empty()) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "unable to load template. ID: " << resource;
362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = ReplaceStringPlaceholders(template_html, subst, NULL);
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16("data:text/html;charset=utf-8," +
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               net::EscapeQueryParamValue(data, false));
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DesktopNotificationService::AddIconNotification(
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin_url,
373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& message,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Image& icon,
376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& replace_id,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationDelegate* delegate,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
379a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  Notification notification(origin_url, icon, title, message,
380a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            blink::WebTextDirectionDefault,
381a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            base::string16(), replace_id, delegate);
382a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  g_browser_process->notification_ui_manager()->Add(notification, profile);
383a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return notification.notification_id();
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DesktopNotificationService::DesktopNotificationService(
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationUIManager* ui_manager)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui_manager_(ui_manager) {
391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStringListPrefChanged(
392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      prefs::kMessageCenterDisabledExtensionIds, &disabled_extension_ids_);
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStringListPrefChanged(
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      prefs::kMessageCenterDisabledSystemComponentIds,
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &disabled_system_component_ids_);
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStringListPrefChanged(
397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      prefs::kMessageCenterEnabledSyncNotifierIds, &enabled_sync_notifier_ids_);
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  disabled_extension_id_pref_.Init(
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prefs::kMessageCenterDisabledExtensionIds,
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_->GetPrefs(),
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(
402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &DesktopNotificationService::OnStringListPrefChanged,
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(this),
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(prefs::kMessageCenterDisabledExtensionIds),
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(&disabled_extension_ids_)));
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  disabled_system_component_id_pref_.Init(
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kMessageCenterDisabledSystemComponentIds,
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_->GetPrefs(),
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &DesktopNotificationService::OnStringListPrefChanged,
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(this),
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(prefs::kMessageCenterDisabledSystemComponentIds),
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(&disabled_system_component_ids_)));
414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  enabled_sync_notifier_id_pref_.Init(
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      prefs::kMessageCenterEnabledSyncNotifierIds,
416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      profile_->GetPrefs(),
417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(
418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &DesktopNotificationService::OnStringListPrefChanged,
419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(this),
420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(prefs::kMessageCenterEnabledSyncNotifierIds),
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Unretained(&enabled_sync_notifier_ids_)));
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 content::Source<Profile>(profile_));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopNotificationService::~DesktopNotificationService() {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::GrantPermission(const GURL& origin) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSettingsPattern primary_pattern =
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(origin);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_pattern,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTING_ALLOW);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::DenyPermission(const GURL& origin) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSettingsPattern primary_pattern =
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(origin);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_pattern,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTING_BLOCK);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSetting DesktopNotificationService::GetDefaultContentSetting(
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* provider_id) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, provider_id);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::SetDefaultContentSetting(
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContentSetting setting) {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ResetToDefaultContentSetting() {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_DEFAULT);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::GetNotificationsSettings(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContentSettingsForOneType* settings) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->GetSettingsForOneType(
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ClearSetting(
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ContentSettingsPattern& pattern) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pattern,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTING_DEFAULT);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ResetAllOrigins() {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->ClearSettingsForOneType(
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSetting DesktopNotificationService::GetContentSetting(
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_->GetHostContentSettingsMap()->GetContentSetting(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::RequestPermission(
5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const GURL& origin,
5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::RenderFrameHost* render_frame_host,
5030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::Closure& callback) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |origin| hasn't been seen before and the default content setting for
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifications is "ask", show an infobar.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The cache can only answer queries on the IO thread once it's initialized,
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so don't ask the cache.
5080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  WebContents* web_contents = WebContents::FromRenderFrameHost(
5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      render_frame_host);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSetting setting = GetContentSetting(origin);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (setting == CONTENT_SETTING_ASK) {
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (PermissionBubbleManager::Enabled()) {
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PermissionBubbleManager* bubble_manager =
5140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          PermissionBubbleManager::FromWebContents(web_contents);
5150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      bubble_manager->AddRequest(new NotificationPermissionRequest(
5160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          this,
5170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          origin,
5180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          DisplayNameForOriginInProcessId(
5190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              origin, render_frame_host->GetProcess()->GetID()),
5200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          callback));
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Show an info bar requesting permission.
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InfoBarService* infobar_service =
5260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        InfoBarService::FromWebContents(web_contents);
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |infobar_service| may be NULL, e.g., if this request originated in a
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // browser action popup, extension background page, or any HTML that runs
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // outside of a tab.
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (infobar_service) {
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NotificationPermissionInfoBarDelegate::Create(
5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          infobar_service, this, origin,
5330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          DisplayNameForOriginInProcessId(
5340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              origin, render_frame_host->GetProcess()->GetID()),
5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          callback);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify renderer immediately.
5410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  callback.Run();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid DesktopNotificationService::ShowDesktopNotification(
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::ShowDesktopNotificationHostMsgParams& params,
5460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::RenderFrameHost* render_frame_host,
5470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::DesktopNotificationDelegate* delegate,
5480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::Closure* cancel_callback) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& origin = params.origin;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationObjectProxy* proxy =
5520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      new NotificationObjectProxy(render_frame_host, delegate);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::string16 display_source = DisplayNameForOriginInProcessId(
5550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      origin, render_frame_host->GetProcess()->GetID());
556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Notification notification(origin, params.icon_url, params.title,
557a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      params.body, params.direction, display_source, params.replace_id,
558a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      proxy);
559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The webkit notification doesn't timeout.
561a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  notification.set_never_timeout(true);
562a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GetUIManager()->Add(notification, profile_);
5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (cancel_callback)
5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *cancel_callback = base::Bind(&CancelNotification, proxy->id());
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 DesktopNotificationService::DisplayNameForOriginInProcessId(
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& origin, int process_id) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the source is an extension, lookup the display name.
571a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (origin.SchemeIs(extensions::kExtensionScheme)) {
572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extensions::InfoMap* extension_info_map =
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extensions::ExtensionSystem::Get(profile_)->info_map();
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (extension_info_map) {
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::ExtensionSet extensions;
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin(
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          origin, process_id, extensions::APIPermission::kNotification,
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &extensions);
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           iter != extensions.end(); ++iter) {
581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id());
582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (IsNotifierEnabled(notifier_id))
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return base::UTF8ToUTF16((*iter)->name());
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16(origin.host());
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::NotifySettingsChange() {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<DesktopNotificationService>(this),
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::NoDetails());
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationUIManager* DesktopNotificationService::GetUIManager() {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We defer setting ui_manager_ to the global singleton until we need it
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in order to avoid UI dependent construction during startup.
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ui_manager_)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_manager_ = g_browser_process->notification_ui_manager();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui_manager_;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool DesktopNotificationService::IsNotifierEnabled(
606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const NotifierId& notifier_id) {
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (notifier_id.type) {
608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::APPLICATION:
609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return disabled_extension_ids_.find(notifier_id.id) ==
610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          disabled_extension_ids_.end();
611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::WEB_PAGE:
612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return GetContentSetting(notifier_id.url) == CONTENT_SETTING_ALLOW;
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::SYSTEM_COMPONENT:
614424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_CHROMEOS)
615a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return disabled_system_component_ids_.find(notifier_id.id) ==
616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          disabled_system_component_ids_.end();
617424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#else
618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // We do not disable system component notifications.
619a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return true;
620424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::SYNCED_NOTIFICATION_SERVICE:
622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return enabled_sync_notifier_ids_.find(notifier_id.id) !=
623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          enabled_sync_notifier_ids_.end();
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NOTREACHED();
627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DesktopNotificationService::SetNotifierEnabled(
631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const NotifierId& notifier_id,
632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bool enabled) {
633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK_NE(NotifierId::WEB_PAGE, notifier_id.type);
634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool add_new_item = false;
636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* pref_name = NULL;
637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::StringValue> id;
638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (notifier_id.type) {
639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::APPLICATION:
640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pref_name = prefs::kMessageCenterDisabledExtensionIds;
641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      add_new_item = !enabled;
642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      id.reset(new base::StringValue(notifier_id.id));
6431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      FirePermissionLevelChangedEvent(notifier_id, enabled);
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::SYSTEM_COMPONENT:
646424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_CHROMEOS)
647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pref_name = prefs::kMessageCenterDisabledSystemComponentIds;
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      add_new_item = !enabled;
649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      id.reset(new base::StringValue(notifier_id.id));
650424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#else
651424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return;
652424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case NotifierId::SYNCED_NOTIFICATION_SERVICE:
655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pref_name = prefs::kMessageCenterEnabledSyncNotifierIds;
656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Adding a new item if |enabled| == true, since synced notification
657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // services are opt-in.
658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      add_new_item = enabled;
659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      id.reset(new base::StringValue(notifier_id.id));
660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(pref_name != NULL);
665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ListPrefUpdate update(profile_->GetPrefs(), pref_name);
6677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::ListValue* const list = update.Get();
6687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (add_new_item) {
6697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // AppendIfNotPresent will delete |adding_value| when the same value
6707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // already exists.
6717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    list->AppendIfNotPresent(id.release());
6727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
6737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    list->Remove(*id, NULL);
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DesktopNotificationService::ShowWelcomeNotificationIfNecessary(
6788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const Notification& notification) {
679a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!chrome_now_welcome_notification_) {
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_now_welcome_notification_ =
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ExtensionWelcomeNotification::Create(kChromeNowExtensionID, profile_);
6828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
6838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (chrome_now_welcome_notification_) {
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_now_welcome_notification_->ShowWelcomeNotificationIfNecessary(
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        notification);
6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DesktopNotificationService::OnStringListPrefChanged(
691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* pref_name, std::set<std::string>* ids_field) {
692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ids_field->clear();
6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Separate GetPrefs()->GetList() to analyze the crash. See crbug.com/322320
6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const PrefService* pref_service = profile_->GetPrefs();
6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(pref_service);
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::ListValue* pref_list = pref_service->GetList(pref_name);
697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < pref_list->GetSize(); ++i) {
698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string element;
699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (pref_list->GetString(i, &element) && !element.empty())
700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ids_field->insert(element);
701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    else
702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(WARNING) << i << "-th element is not a string for " << pref_name;
703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DesktopNotificationService::Observe(
70790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int type,
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const content::NotificationSource& source,
70990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const content::NotificationDetails& details) {
71090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_UNINSTALLED, type);
71190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
71290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  extensions::Extension* extension =
71390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::Details<extensions::Extension>(details).ptr();
714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (IsNotifierEnabled(notifier_id))
71690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
71790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The settings for ephemeral apps will be persisted across cache evictions.
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (extension->is_ephemeral())
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SetNotifierEnabled(notifier_id, true);
72390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DesktopNotificationService::FirePermissionLevelChangedEvent(
7261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const NotifierId& notifier_id, bool enabled) {
7271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_EQ(NotifierId::APPLICATION, notifier_id.type);
7281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extensions::api::notifications::PermissionLevel permission =
7291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      enabled ? extensions::api::notifications::PERMISSION_LEVEL_GRANTED
7301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)              : extensions::api::notifications::PERMISSION_LEVEL_DENIED;
7311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<base::ListValue> args(new base::ListValue());
7321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  args->Append(new base::StringValue(
7331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::api::notifications::ToString(permission)));
7341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<extensions::Event> event(new extensions::Event(
7351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::api::notifications::OnPermissionLevelChanged::kEventName,
7361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      args.Pass()));
7370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  extensions::EventRouter::Get(profile_)
7380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ->DispatchEventToExtension(notifier_id.id, event.Pass());
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Tell the IO thread that this extension's permission for notifications
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // has changed.
742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::InfoMap* extension_info_map =
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile_)->info_map();
744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserThread::PostTask(
745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
746f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&extensions::InfoMap::SetNotificationsDisabled,
747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 extension_info_map, notifier_id.id, !enabled));
748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
750