172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/desktop_notification_service.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/content_settings/content_settings_provider.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/notifications/desktop_notification_service_factory.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/notification.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/notification_object_proxy.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/notification_ui_manager.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/notifications/notifications_prefs_cache.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h"
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_child_process_host.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h"
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/site_instance.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/worker_host/worker_process_host.h"
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/desktop_notification_messages.h"
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/browser_resources.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/escape.h"
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebNotificationPresenter;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebTextDirection;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst ContentSetting kDefaultSetting = CONTENT_SETTING_ASK;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace {
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef content_settings::ProviderInterface::Rules Rules;
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid GetOriginsWithSettingFromContentSettingsRules(
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Rules& content_setting_rules,
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ContentSetting setting,
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<GURL>* origins) {
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  origins->clear();
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (Rules::const_iterator rule = content_setting_rules.begin();
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       rule != content_setting_rules.end();
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       ++rule) {
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (setting == rule->content_setting) {
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::string url_str = rule->requesting_url_pattern.AsString();
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!rule->requesting_url_pattern.IsValid()) {
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // TODO(markusheintz): This will be removed in one of the next
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // refactoring steps as this entire function will disapear.
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        LOG(DFATAL) << "Ignoring invalid content settings pattern: "
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    << url_str;
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      } else if (url_str.find(ContentSettingsPattern::kDomainWildcard) == 0) {
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // TODO(markusheintz): This must be changed once the UI code is
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // refactored and content_settings patterns are fully supported for
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // notifications settings.
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        LOG(DFATAL) << "Ignoring unsupported content settings pattern: "
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    << url_str << ". Content settings patterns other than "
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    << "hostnames (e.g. wildcard patterns) are not supported "
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    << "for notification content settings yet.";
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      } else {
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        origins->push_back(
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            content_settings::NotificationProvider::ToGURL(
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                rule->requesting_url_pattern));
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NotificationPermissionInfoBarDelegate --------------------------------------
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The delegate for the infobar shown when an origin requests notification
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// permissions.
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public:
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  NotificationPermissionInfoBarDelegate(TabContents* contents,
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                        const GURL& origin,
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                        const string16& display_name,
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                        int process_id,
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                        int route_id,
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                        int callback_context);
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ~NotificationPermissionInfoBarDelegate();
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ConfirmInfoBarDelegate:
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void InfoBarClosed();
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual SkBitmap* GetIcon() const;
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual Type GetInfoBarType() const;
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual string16 GetMessageText() const;
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual string16 GetButtonLabel(InfoBarButton button) const;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual bool Accept();
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual bool Cancel();
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The origin we are asking for permissions on.
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  GURL origin_;
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The display name for the origin to be displayed.  Will be different from
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // origin_ for extensions.
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 display_name_;
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The Profile that we restore sessions from.
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Profile* profile_;
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The callback information that tells us how to respond to javascript via
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // the correct RenderView.
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int process_id_;
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int route_id_;
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int callback_context_;
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Whether the user clicked one of the buttons.
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool action_taken_;
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenNotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate(
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    TabContents* contents,
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const GURL& origin,
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& display_name,
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int process_id,
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int route_id,
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int callback_context)
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : ConfirmInfoBarDelegate(contents),
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      origin_(origin),
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      display_name_(display_name),
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      profile_(contents->profile()),
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      process_id_(process_id),
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      route_id_(route_id),
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      callback_context_(callback_context),
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      action_taken_(false) {
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenNotificationPermissionInfoBarDelegate::
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ~NotificationPermissionInfoBarDelegate() {
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid NotificationPermissionInfoBarDelegate::InfoBarClosed() {
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!action_taken_)
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (host) {
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    host->Send(new DesktopNotificationMsg_PermissionRequestDone(
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        route_id_, callback_context_));
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  delete this;
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSkBitmap* NotificationPermissionInfoBarDelegate::GetIcon() const {
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen     IDR_PRODUCT_ICON_32);
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenInfoBarDelegate::Type
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NotificationPermissionInfoBarDelegate::GetInfoBarType() const {
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return PAGE_ACTION_TYPE;
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 NotificationPermissionInfoBarDelegate::GetMessageText() const {
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    display_name_);
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 NotificationPermissionInfoBarDelegate::GetButtonLabel(
18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InfoBarButton button) const {
18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      IDS_NOTIFICATION_PERMISSION_YES : IDS_NOTIFICATION_PERMISSION_NO);
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool NotificationPermissionInfoBarDelegate::Accept() {
19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DesktopNotificationServiceFactory::GetForProfile(profile_)->
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GrantPermission(origin_);
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  action_taken_ = true;
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool NotificationPermissionInfoBarDelegate::Cancel() {
19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DesktopNotificationServiceFactory::GetForProfile(profile_)->
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DenyPermission(origin_);
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  action_taken_ = true;
20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// DesktopNotificationService -------------------------------------------------
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 DesktopNotificationService::CreateDataUrl(
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& icon_url, const string16& title, const string16& body,
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WebTextDirection dir) {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int resource;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> subst;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (icon_url.is_valid()) {
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resource = IDR_NOTIFICATION_ICON_HTML;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(icon_url.spec());
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(EscapeForHTML(UTF16ToUTF8(title)));
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(EscapeForHTML(UTF16ToUTF8(body)));
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // icon float position
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ?
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    "right" : "left");
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (title.empty() || body.empty()) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resource = IDR_NOTIFICATION_1LINE_HTML;
224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    string16 line = title.empty() ? body : title;
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Strings are div names in the template file.
226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    string16 line_name = title.empty() ? ASCIIToUTF16("description")
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                       : ASCIIToUTF16("title");
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(EscapeForHTML(UTF16ToUTF8(line_name)));
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(EscapeForHTML(UTF16ToUTF8(line)));
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resource = IDR_NOTIFICATION_2LINE_HTML;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(EscapeForHTML(UTF16ToUTF8(title)));
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subst.push_back(EscapeForHTML(UTF16ToUTF8(body)));
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // body text direction
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ?
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  "rtl" : "ltr");
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return CreateDataUrl(resource, subst);
240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
241731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstring16 DesktopNotificationService::CreateDataUrl(
244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int resource, const std::vector<std::string>& subst) {
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const base::StringPiece template_html(
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ResourceBundle::GetSharedInstance().GetRawDataResource(
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          resource));
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (template_html.empty()) {
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "unable to load template. ID: " << resource;
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return string16();
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string data = ReplaceStringPlaceholders(template_html, subst, NULL);
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF8ToUTF16("data:text/html;charset=utf-8," +
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      EscapeQueryParamValue(data, false));
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDesktopNotificationService::DesktopNotificationService(Profile* profile,
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotificationUIManager* ui_manager)
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : profile_(profile),
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ui_manager_(ui_manager) {
263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  prefs_registrar_.Init(profile_->GetPrefs());
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitPrefs();
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StartObserving();
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDesktopNotificationService::~DesktopNotificationService() {
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StopObserving();
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::RegisterUserPrefs(PrefService* user_prefs) {
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  content_settings::NotificationProvider::RegisterUserPrefs(user_prefs);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Initialize the cache with the allowed and denied origins, or
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// create the preferences if they don't exist yet.
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::InitPrefs() {
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_.reset(new content_settings::NotificationProvider(profile_));
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<GURL> allowed_origins;
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<GURL> denied_origins;
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContentSetting default_content_setting = CONTENT_SETTING_DEFAULT;
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!profile_->IsOffTheRecord()) {
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default_content_setting =
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    allowed_origins = GetAllowedOrigins();
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    denied_origins = GetBlockedOrigins();
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs_cache_ = new NotificationsPrefsCache();
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs_cache_->SetCacheDefaultContentSetting(default_content_setting);
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs_cache_->SetCacheAllowedOrigins(allowed_origins);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs_cache_->SetCacheDeniedOrigins(denied_origins);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs_cache_->set_is_initialized(true);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::StartObserving() {
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!profile_->IsOffTheRecord()) {
302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    prefs_registrar_.Add(prefs::kDesktopNotificationAllowedOrigins, this);
303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    prefs_registrar_.Add(prefs::kDesktopNotificationDeniedOrigins, this);
304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    notification_registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                NotificationService::AllSources());
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    notification_registrar_.Add(
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this,
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NotificationType::CONTENT_SETTINGS_CHANGED,
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // TODO(markusheintz): Remember to change to HostContentSettingsMap.
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NotificationService::AllSources());
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
312201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
313201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                              Source<Profile>(profile_));
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::StopObserving() {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!profile_->IsOffTheRecord()) {
318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    prefs_registrar_.RemoveAll();
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  notification_registrar_.RemoveAll();
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::GrantPermission(const GURL& origin) {
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ContentSettingsPattern pattern =
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      content_settings::NotificationProvider::ToContentSettingsPattern(origin);
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->SetContentSetting(
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER,
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTING_ALLOW);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Schedule a cache update on the IO thread.
334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO, FROM_HERE,
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          prefs_cache_.get(),
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &NotificationsPrefsCache::CacheAllowedOrigin,
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          origin));
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::DenyPermission(const GURL& origin) {
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Update content settings
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ContentSettingsPattern pattern =
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      content_settings::NotificationProvider::ToContentSettingsPattern(origin);
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->SetContentSetting(
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER,
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTING_BLOCK);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Schedule a cache update on the IO thread.
354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO, FROM_HERE,
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          prefs_cache_.get(),
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &NotificationsPrefsCache::CacheDeniedOrigin,
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          origin));
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::Observe(NotificationType type,
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         const NotificationSource& source,
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         const NotificationDetails& details) {
365201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (NotificationType::PREF_CHANGED == type) {
366201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const std::string& name = *Details<std::string>(details).ptr();
367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    OnPrefsChanged(name);
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (NotificationType::CONTENT_SETTINGS_CHANGED == type) {
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(markusheintz): Check if content settings type default was changed;
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ContentSetting default_content_setting =
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Schedule a cache update on the IO thread.
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::IO, FROM_HERE,
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(
377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            prefs_cache_.get(),
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &NotificationsPrefsCache::SetCacheDefaultContentSetting,
379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            default_content_setting));
380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else if (NotificationType::EXTENSION_UNLOADED == type) {
381201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Remove all notifications currently shown or queued by the extension
382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // which was unloaded.
38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const Extension* extension =
38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        Details<UnloadedExtensionInfo>(details)->extension;
385201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (extension)
386201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ui_manager_->CancelAllBySourceOrigin(extension->url());
387201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else if (NotificationType::PROFILE_DESTROYED == type) {
388201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    StopObserving();
389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
390201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
391201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
392201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DesktopNotificationService::OnPrefsChanged(const std::string& pref_name) {
393201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (pref_name == prefs::kDesktopNotificationAllowedOrigins) {
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Schedule a cache update on the IO thread.
395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<GURL> allowed_origins(GetAllowedOrigins());
396731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::IO, FROM_HERE,
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            prefs_cache_.get(),
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &NotificationsPrefsCache::SetCacheAllowedOrigins,
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            allowed_origins));
402201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else if (pref_name == prefs::kDesktopNotificationDeniedOrigins) {
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Schedule a cache update on the IO thread.
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<GURL> denied_origins(GetBlockedOrigins());
405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::IO, FROM_HERE,
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            prefs_cache_.get(),
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &NotificationsPrefsCache::SetCacheDeniedOrigins,
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            denied_origins));
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochContentSetting DesktopNotificationService::GetDefaultContentSetting() {
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::SetDefaultContentSetting(
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ContentSetting setting) {
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool DesktopNotificationService::IsDefaultContentSettingManaged() const {
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return profile_->GetHostContentSettingsMap()->IsDefaultContentSettingManaged(
429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
43121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DesktopNotificationService::ResetToDefaultContentSetting() {
433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_DEFAULT);
4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<GURL> DesktopNotificationService::GetAllowedOrigins() {
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  content_settings::ProviderInterface::Rules content_setting_rules;
439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->GetAllContentSettingsRules(
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER,
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      &content_setting_rules);
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<GURL> allowed_origins;
444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GetOriginsWithSettingFromContentSettingsRules(
446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      content_setting_rules, CONTENT_SETTING_ALLOW, &allowed_origins);
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return allowed_origins;
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<GURL> DesktopNotificationService::GetBlockedOrigins() {
452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  content_settings::ProviderInterface::Rules content_settings_rules;
453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->GetAllContentSettingsRules(
454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER,
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      &content_settings_rules);
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<GURL> denied_origins;
458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GetOriginsWithSettingFromContentSettingsRules(
460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      content_settings_rules, CONTENT_SETTING_BLOCK, &denied_origins);
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return denied_origins;
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::ResetAllowedOrigin(const GURL& origin) {
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ContentSettingsPattern pattern =
467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ContentSettingsPattern::FromURLNoWildcard(origin);
468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->SetContentSetting(
469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER,
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTING_DEFAULT);
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::ResetBlockedOrigin(const GURL& origin) {
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ContentSettingsPattern pattern =
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ContentSettingsPattern::FromURLNoWildcard(origin);
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->SetContentSetting(
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pattern,
482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER,
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTING_DEFAULT);
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::ResetAllOrigins() {
488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  provider_->ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochContentSetting DesktopNotificationService::GetContentSetting(
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& origin) {
493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ContentSetting provided_setting = provider_->GetContentSetting(
494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      origin,
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      origin,
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NO_RESOURCE_IDENTIFIER);
498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (CONTENT_SETTING_DEFAULT == provided_setting)
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return GetDefaultContentSetting();
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return provided_setting;
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::RequestPermission(
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& origin, int process_id, int route_id, int callback_context,
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabContents* tab) {
506731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!tab) {
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Browser* browser = BrowserList::GetLastActive();
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (browser)
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      tab = browser->GetSelectedTabContents();
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tab)
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If |origin| hasn't been seen before and the default content setting for
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // notifications is "ask", show an infobar.
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The cache can only answer queries on the IO thread once it's initialized,
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so don't ask the cache.
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContentSetting setting = GetContentSetting(origin);
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (setting == CONTENT_SETTING_ASK) {
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Show an info bar requesting permission.
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tab->AddInfoBar(new NotificationPermissionInfoBarDelegate(
5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        tab, origin, DisplayNameForOrigin(origin), process_id,
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        route_id, callback_context));
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Notify renderer immediately.
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    RenderViewHost* host = RenderViewHost::FromID(process_id, route_id);
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (host) {
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      host->Send(new DesktopNotificationMsg_PermissionRequestDone(
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          route_id, callback_context));
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DesktopNotificationService::ShowNotification(
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const Notification& notification) {
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ui_manager_->Add(notification, profile_);
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DesktopNotificationService::CancelDesktopNotification(
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int process_id, int route_id, int notification_id) {
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<NotificationObjectProxy> proxy(
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new NotificationObjectProxy(process_id, route_id, notification_id,
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  false));
546201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return ui_manager_->CancelById(proxy->id());
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DesktopNotificationService::ShowDesktopNotification(
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const DesktopNotificationHostMsg_Show_Params& params,
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int process_id, int route_id, DesktopNotificationSource source) {
553731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GURL& origin = params.origin;
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationObjectProxy* proxy =
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new NotificationObjectProxy(process_id, route_id,
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  params.notification_id,
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  source == WorkerNotification);
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL contents;
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (params.is_html) {
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    contents = params.contents_url;
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // "upconvert" the string parameters to a data: URL.
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    contents = GURL(
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CreateDataUrl(params.icon_url, params.title, params.body,
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      params.direction));
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
5683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Notification notification(
5693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      origin, contents, DisplayNameForOrigin(origin),
5703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      params.replace_id, proxy);
5713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ShowNotification(notification);
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 DesktopNotificationService::DisplayNameForOrigin(
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& origin) {
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the source is an extension, lookup the display name.
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (origin.SchemeIs(chrome::kExtensionScheme)) {
57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    ExtensionService* ext_service = profile_->GetExtensionService();
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ext_service) {
581513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      const Extension* extension = ext_service->GetExtensionByURL(origin);
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (extension)
5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return UTF8ToUTF16(extension->name());
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
5863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return UTF8ToUTF16(origin.host());
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
588201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DesktopNotificationService::NotifySettingsChange() {
590201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NotificationService::current()->Notify(
591201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
592201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      Source<DesktopNotificationService>(this),
593201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NotificationService::NoDetails());
594201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
595