desktop_notification_service.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_details.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_provider.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/infobars/infobar_tab_helper.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification_object_proxy.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/notifications/notification_ui_manager.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/pref_service.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/tab_contents.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/web_ui_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings_pattern.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/show_desktop_notification_params.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebNotificationPresenter;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebTextDirection;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebSecurityOrigin;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ContentSetting kDefaultSetting = CONTENT_SETTING_ASK;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NotificationPermissionInfoBarDelegate --------------------------------------
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The delegate for the infobar shown when an origin requests notification
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// permissions.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationPermissionInfoBarDelegate(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InfoBarTabHelper* infobar_helper,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DesktopNotificationService* notification_service,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& origin,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const string16& display_name,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int process_id,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int route_id,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int callback_context);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~NotificationPermissionInfoBarDelegate();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ConfirmInfoBarDelegate:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual gfx::Image* GetIcon() const OVERRIDE;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Type GetInfoBarType() const OVERRIDE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual string16 GetMessageText() const OVERRIDE;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Accept() OVERRIDE;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Cancel() OVERRIDE;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The origin we are asking for permissions on.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL origin_;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The display name for the origin to be displayed.  Will be different from
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // origin_ for extensions.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 display_name_;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The notification service to be used.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DesktopNotificationService* notification_service_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback information that tells us how to respond to javascript via
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the correct RenderView.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int process_id_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int route_id_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int callback_context_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the user clicked one of the buttons.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool action_taken_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationPermissionInfoBarDelegate::NotificationPermissionInfoBarDelegate(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoBarTabHelper* infobar_helper,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DesktopNotificationService* notification_service,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& display_name,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int process_id,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int callback_context)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ConfirmInfoBarDelegate(infobar_helper),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin_(origin),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_name_(display_name),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notification_service_(notification_service),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process_id_(process_id),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_(route_id),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_context_(callback_context),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      action_taken_(false) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationPermissionInfoBarDelegate::
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~NotificationPermissionInfoBarDelegate() {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!action_taken_)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->DesktopNotificationPermissionRequestDone(callback_context_);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image* NotificationPermissionInfoBarDelegate::GetIcon() const {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &ResourceBundle::GetSharedInstance().GetNativeImageNamed(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDR_INFOBAR_DESKTOP_NOTIFICATIONS);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InfoBarDelegate::Type
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationPermissionInfoBarDelegate::GetInfoBarType() const {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PAGE_ACTION_TYPE;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 NotificationPermissionInfoBarDelegate::GetMessageText() const {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l10n_util::GetStringFUTF16(IDS_NOTIFICATION_PERMISSIONS,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    display_name_);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 NotificationPermissionInfoBarDelegate::GetButtonLabel(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoBarButton button) const {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_NOTIFICATION_PERMISSION_YES : IDS_NOTIFICATION_PERMISSION_NO);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPermissionInfoBarDelegate::Accept() {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_service_->GrantPermission(origin_);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action_taken_ = true;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NotificationPermissionInfoBarDelegate::Cancel() {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_service_->DenyPermission(origin_);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action_taken_ = true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopNotificationService -------------------------------------------------
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 DesktopNotificationService::CreateDataUrl(
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& icon_url, const string16& title, const string16& body,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebTextDirection dir) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> subst;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (icon_url.is_valid()) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_ICON_HTML;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(icon_url.spec());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(UTF16ToUTF8(title)));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(UTF16ToUTF8(body)));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // icon float position
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ?
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "right" : "left");
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (title.empty() || body.empty()) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_1LINE_HTML;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 line = title.empty() ? body : title;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings are div names in the template file.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 line_name = title.empty() ? ASCIIToUTF16("description")
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       : ASCIIToUTF16("title");
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(UTF16ToUTF8(line_name)));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(UTF16ToUTF8(line)));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resource = IDR_NOTIFICATION_2LINE_HTML;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(UTF16ToUTF8(title)));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subst.push_back(net::EscapeForHTML(UTF16ToUTF8(body)));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // body text direction
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subst.push_back(dir == WebKit::WebTextDirectionRightToLeft ?
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "rtl" : "ltr");
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateDataUrl(resource, subst);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 DesktopNotificationService::CreateDataUrl(
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int resource, const std::vector<std::string>& subst) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::StringPiece template_html(
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResourceBundle::GetSharedInstance().GetRawDataResource(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          resource));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (template_html.empty()) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "unable to load template. ID: " << resource;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return string16();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = ReplaceStringPlaceholders(template_html, subst, NULL);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UTF8ToUTF16("data:text/html;charset=utf-8," +
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      net::EscapeQueryParamValue(data, false));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DesktopNotificationService::AddNotification(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin_url,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& title,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& message,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& icon_url,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& replace_id,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationDelegate* delegate,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_ASH)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For Ash create a non-HTML notification with |icon_url|.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notification notification(GURL(), icon_url, title, message,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            WebKit::WebTextDirectionDefault,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            string16(), replace_id, delegate);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_browser_process->notification_ui_manager()->Add(notification, profile);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notification.notification_id();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate a data URL embedding the icon URL, title, and message.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL content_url(CreateDataUrl(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_url, title, message, WebKit::WebTextDirectionDefault));
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notification notification(
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL(), content_url, string16(), replace_id, delegate);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_browser_process->notification_ui_manager()->Add(notification, profile);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notification.notification_id();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DesktopNotificationService::AddIconNotification(
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin_url,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& title,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& message,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::ImageSkia& icon,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& replace_id,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationDelegate* delegate,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_ASH)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For Ash create a non-HTML notification with |icon|.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Notification notification(GURL(), icon, title, message,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            WebKit::WebTextDirectionDefault,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            string16(), replace_id, delegate);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_browser_process->notification_ui_manager()->Add(notification, profile);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notification.notification_id();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL icon_url;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!icon.isNull())
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_url = GURL(web_ui_util::GetBitmapDataUrl(*icon.bitmap()));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddNotification(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin_url, title, message, icon_url, replace_id, delegate, profile);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::RemoveNotification(
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& notification_id) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_browser_process->notification_ui_manager()->CancelById(notification_id);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopNotificationService::DesktopNotificationService(Profile* profile,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotificationUIManager* ui_manager)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui_manager_(ui_manager) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartObserving();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopNotificationService::~DesktopNotificationService() {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopObserving();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::StartObserving() {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile_->IsOffTheRecord()) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                content::Source<Profile>(profile_));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              content::Source<Profile>(profile_));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::StopObserving() {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.RemoveAll();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::GrantPermission(const GURL& origin) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSettingsPattern primary_pattern =
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(origin);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_pattern,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTING_ALLOW);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::DenyPermission(const GURL& origin) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSettingsPattern primary_pattern =
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::FromURLNoWildcard(origin);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      primary_pattern,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTING_BLOCK);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::Observe(
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove all notifications currently shown or queued by the extension
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which was unloaded. Don't use GetUIManager() here, because this may
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // get called during shutdown.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const extensions::Extension* extension =
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Details<extensions::UnloadedExtensionInfo>(details)->extension;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension &&
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_browser_process && g_browser_process->notification_ui_manager()) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_browser_process->notification_ui_manager()->
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CancelAllBySourceOrigin(extension->url());
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == chrome::NOTIFICATION_PROFILE_DESTROYED) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopObserving();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSetting DesktopNotificationService::GetDefaultContentSetting(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* provider_id) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, provider_id);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::SetDefaultContentSetting(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContentSetting setting) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ResetToDefaultContentSetting() {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetDefaultContentSetting(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_DEFAULT);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::GetNotificationsSettings(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContentSettingsForOneType* settings) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->GetSettingsForOneType(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ClearSetting(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ContentSettingsPattern& pattern) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->SetContentSetting(
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pattern,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ContentSettingsPattern::Wildcard(),
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTING_DEFAULT);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ResetAllOrigins() {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->GetHostContentSettingsMap()->ClearSettingsForOneType(
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContentSetting DesktopNotificationService::GetContentSetting(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_->GetHostContentSettingsMap()->GetContentSetting(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::RequestPermission(
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin, int process_id, int route_id, int callback_context,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* contents) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |origin| hasn't been seen before and the default content setting for
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifications is "ask", show an infobar.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The cache can only answer queries on the IO thread once it's initialized,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so don't ask the cache.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSetting setting = GetContentSetting(origin);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (setting == CONTENT_SETTING_ASK) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Show an info bar requesting permission.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoBarTabHelper* infobar_tab_helper =
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        InfoBarTabHelper::FromWebContents(contents);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |infobar_tab_helper| may be NULL, e.g., if this request originated in a
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // browser action popup, extension background page, or any HTML that runs
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // outside of a tab.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (infobar_tab_helper) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      infobar_tab_helper->AddInfoBar(new NotificationPermissionInfoBarDelegate(
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          infobar_tab_helper,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DesktopNotificationServiceFactory::GetForProfile(
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Profile::FromBrowserContext(contents->GetBrowserContext())),
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          origin,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DisplayNameForOrigin(origin),
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          process_id,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          route_id,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          callback_context));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify renderer immediately.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewHost* host = RenderViewHost::FromID(process_id, route_id);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->DesktopNotificationPermissionRequestDone(callback_context);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_WIN)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::ShowNotification(
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Notification& notification) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetUIManager()->Add(notification, profile_);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DesktopNotificationService::CancelDesktopNotification(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int process_id, int route_id, int notification_id) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<NotificationObjectProxy> proxy(
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new NotificationObjectProxy(process_id, route_id, notification_id,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  false));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetUIManager()->CancelById(proxy->id());
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_WIN
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DesktopNotificationService::ShowDesktopNotification(
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::ShowDesktopNotificationHostMsgParams& params,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int process_id, int route_id, DesktopNotificationSource source) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& origin = params.origin;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotificationObjectProxy* proxy =
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new NotificationObjectProxy(process_id, route_id,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  params.notification_id,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  source == WorkerNotification);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 display_source = DisplayNameForOrigin(origin);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params.is_html) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowNotification(Notification(origin, params.contents_url, display_source,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params.replace_id, proxy));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ShowNotification(Notification(origin, params.icon_url, params.title,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params.body, params.direction, display_source, params.replace_id,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 DesktopNotificationService::DisplayNameForOrigin(
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the source is an extension, lookup the display name.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (origin.SchemeIs(chrome::kExtensionScheme)) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionService* extension_service = profile_->GetExtensionService();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension_service) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const extensions::Extension* extension =
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_service->extensions()->GetExtensionOrAppByURL(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ExtensionURLInfo(
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  WebSecurityOrigin::createFromString(
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      UTF8ToUTF16(origin.spec())),
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  origin));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (extension)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return UTF8ToUTF16(extension->name());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UTF8ToUTF16(origin.host());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DesktopNotificationService::NotifySettingsChange() {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<DesktopNotificationService>(this),
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::NoDetails());
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NotificationUIManager* DesktopNotificationService::GetUIManager() {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We defer setting ui_manager_ to the global singleton until we need it
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in order to avoid UI dependent construction during startup.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ui_manager_)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_manager_ = g_browser_process->notification_ui_manager();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui_manager_;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebKit::WebNotificationPresenter::Permission
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DesktopNotificationService::HasPermission(const GURL& origin) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostContentSettingsMap* host_content_settings_map =
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->GetHostContentSettingsMap();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContentSetting setting = host_content_settings_map->GetContentSetting(
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin,
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_RESOURCE_IDENTIFIER);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (setting == CONTENT_SETTING_ALLOW)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebKit::WebNotificationPresenter::PermissionAllowed;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (setting == CONTENT_SETTING_BLOCK)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebKit::WebNotificationPresenter::PermissionDenied;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (setting == CONTENT_SETTING_ASK)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebKit::WebNotificationPresenter::PermissionNotAllowed;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Invalid notifications settings value: " << setting;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WebKit::WebNotificationPresenter::PermissionNotAllowed;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
519