summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-12 05:44:26 +0000
committerjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-12 05:44:26 +0000
commit4bb33630869981809c47c36c3c18813d6b005d34 (patch)
tree505252dfeac2de2d02a89d1f7e69ffcdf4affcf5 /chrome
parenta93244407e205a8619d620ce91bafbdf88eab195 (diff)
downloadchromium_src-4bb33630869981809c47c36c3c18813d6b005d34.zip
chromium_src-4bb33630869981809c47c36c3c18813d6b005d34.tar.gz
chromium_src-4bb33630869981809c47c36c3c18813d6b005d34.tar.bz2
Browser side support (sans UI) for desktop notifications.
BUG=none TEST=none Review URL: http://codereview.chromium.org/194108 Review URL: http://codereview.chromium.org/271052 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28696 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/chromium_strings.grd3
-rw-r--r--chrome/app/generated_resources.grd14
-rw-r--r--chrome/browser/automation/automation_profile_impl.h3
-rw-r--r--chrome/browser/browser_resources.grd1
-rw-r--r--chrome/browser/notifications/balloons.h200
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc234
-rw-r--r--chrome/browser/notifications/desktop_notification_service.h78
-rw-r--r--chrome/browser/notifications/desktop_notification_service_linux.cc30
-rw-r--r--chrome/browser/notifications/desktop_notification_service_mac.mm30
-rw-r--r--chrome/browser/notifications/desktop_notification_service_win.cc97
-rw-r--r--chrome/browser/notifications/notification.h58
-rw-r--r--chrome/browser/notifications/notification_object_proxy.cc68
-rw-r--r--chrome/browser/notifications/notification_object_proxy.h51
-rw-r--r--chrome/browser/notifications/notifications_prefs_cache.cc67
-rw-r--r--chrome/browser/notifications/notifications_prefs_cache.h45
-rw-r--r--chrome/browser/profile.cc16
-rw-r--r--chrome/browser/profile.h6
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc33
-rw-r--r--chrome/browser/renderer_host/render_view_host.h8
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc11
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h8
-rw-r--r--chrome/browser/resources/notification.html36
-rwxr-xr-xchrome/chrome.gyp11
-rw-r--r--chrome/common/pref_names.cc6
-rw-r--r--chrome/common/pref_names.h2
-rw-r--r--chrome/common/render_messages_internal.h4
-rw-r--r--chrome/renderer/notification_provider.cc6
-rw-r--r--chrome/test/testing_profile.h3
28 files changed, 1124 insertions, 5 deletions
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 05cdf36..da38b89 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -362,6 +362,9 @@ be available for now. -->
<message name="IDS_DEFAULT_BROWSER_INFOBAR_SHORT_TEXT" desc="More compact text to show in the default browser query infobar.">
Chromium isn't your default browser.
</message>
+ <message name="IDS_NOTIFICATION_PERMISSIONS" desc="Text requesting permission for desktop notifications.">
+ Allow <ph name="site">$1<ex>mail.google.com</ex></ph> to show desktop notifications?
+ </message>
<if expr="os == 'darwin'">
<message name="IDS_SHORT_PRODUCT_NAME" desc="The application's short name, used for the Mac's application menu, activity monitor, etc. This should be less than 16 characters. Example: Chrome, not Google Chrome.">
Chromium
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 0ec8bbe..8015426 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5333,6 +5333,20 @@ Keep your key file in a safe place. You will need it to create new versions of y
Your login details are out of date. Click to re-enter your password.
</message>
+ <!-- Desktop notifications -->
+ <message name="IDS_NOTIFICATION_BALLOON_DISMISS_LABEL" desc="Text on the button which dismisses the balloon.">
+ Dismiss
+ </message>
+ <message name="IDS_NOTIFICATION_BALLOON_SOURCE_LABEL" desc="Text which labels the balloon with the source origin.">
+ from <ph name="SOURCE_ORIGIN">$1</ph>
+ </message>
+ <message name="IDS_NOTIFICATION_PERMISSION_YES" desc="The label of the 'allow' button on the notification permission infobar.">
+ Allow
+ </message>
+ <message name="IDS_NOTIFICATION_PERMISSION_NO" desc="The label of the 'deny' button on the notification permission infobar.">
+ Deny
+ </message>
+
<!-- Mac Menubar Menus -->
<if expr="os == 'darwin'">
<!-- Menubar Menu Titles -->
diff --git a/chrome/browser/automation/automation_profile_impl.h b/chrome/browser/automation/automation_profile_impl.h
index dc57f9b..c464f73 100644
--- a/chrome/browser/automation/automation_profile_impl.h
+++ b/chrome/browser/automation/automation_profile_impl.h
@@ -168,6 +168,9 @@ class AutomationProfileImpl : public Profile {
virtual BookmarkModel* GetBookmarkModel() {
return original_profile_->GetBookmarkModel();
}
+ virtual DesktopNotificationService* GetDesktopNotificationService() {
+ return original_profile_->GetDesktopNotificationService();
+ }
#ifdef CHROME_PERSONALIZATION
virtual ProfileSyncService* GetProfileSyncService() {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index fc6d70f..5fba870 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -52,6 +52,7 @@ without changes to the corresponding grd file. ek -->
<include name="IDR_BLACKLIST_HTML" file="resources\privacy_blacklist_block.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_BLACKLIST_IMAGE" file="resources\privacy_blacklist_block.png" type="BINDATA" />
<include name="IDR_DEFAULT_EXTENSION_ICON_128" file="resources\default_extension_icon_128.png" type="BINDATA" />
+ <include name="IDR_NOTIFICATION_HTML" file="resources\notification.html" type="BINDATA" />
</includes>
</release>
</grit>
diff --git a/chrome/browser/notifications/balloons.h b/chrome/browser/notifications/balloons.h
new file mode 100644
index 0000000..6191d53
--- /dev/null
+++ b/chrome/browser/notifications/balloons.h
@@ -0,0 +1,200 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Handles the visible notification (or balloons).
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_BALLOONS_H_
+#define CHROME_BROWSER_NOTIFICATIONS_BALLOONS_H_
+
+#include <deque>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gfx/point.h"
+#include "base/gfx/rect.h"
+#include "base/gfx/size.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/notifications/notification.h"
+
+class Balloon;
+class BalloonView;
+class Profile;
+class SiteInstance;
+
+class BalloonCloseListener {
+ public:
+ virtual ~BalloonCloseListener() { }
+
+ // Called when a balloon is closed.
+ virtual void OnBalloonClosed(Balloon* source) = 0;
+};
+
+class BalloonSpaceChangeListener {
+ public:
+ virtual ~BalloonSpaceChangeListener() { }
+
+ // Called when there is more or less space for balloons due to
+ // monitor size changes or balloons disappearing.
+ virtual void OnBalloonSpaceChanged() = 0;
+};
+
+class BalloonCollectionInterface {
+ public:
+ virtual ~BalloonCollectionInterface() {}
+
+ // Adds a new balloon for the specified notification.
+ virtual void Add(const Notification& notification,
+ Profile* profile,
+ SiteInstance* site_instance) = 0;
+
+ // Is there room to add another notification?
+ virtual bool HasSpace() const = 0;
+};
+
+typedef std::deque<Balloon*> Balloons;
+
+// Represents a Notification on the screen.
+class Balloon {
+ public:
+ Balloon(const Notification& notification,
+ Profile* profile,
+ SiteInstance* site_instance,
+ BalloonCloseListener* listener);
+ ~Balloon();
+
+ const Notification& notification() const {
+ return notification_;
+ }
+
+ Profile* profile() const {
+ return profile_;
+ }
+
+ SiteInstance* site_instance() const {
+ return site_instance_;
+ }
+
+ void SetPosition(const gfx::Point& upper_left, bool reposition);
+ void SetSize(const gfx::Size& size);
+ void Show();
+ void Close();
+
+ const gfx::Point& position() const;
+ const gfx::Size& size() const;
+
+ private:
+ Profile* profile_;
+ SiteInstance* site_instance_;
+ Notification notification_;
+ BalloonCloseListener* close_listener_;
+ scoped_ptr<BalloonView> balloon_view_;
+ gfx::Point position_;
+ gfx::Size size_;
+ DISALLOW_COPY_AND_ASSIGN(Balloon);
+};
+
+class BalloonCollection : public BalloonCollectionInterface,
+ public BalloonCloseListener {
+ public:
+ explicit BalloonCollection();
+
+ BalloonSpaceChangeListener* space_change_listener() { return listener_; }
+ void set_space_change_listener(BalloonSpaceChangeListener* listener) {
+ listener_ = listener;
+ }
+
+ // BalloonCollectionInterface overrides
+ virtual void Add(const Notification& notification,
+ Profile* profile,
+ SiteInstance* site_instance);
+ virtual void ShowAll();
+ virtual void HideAll();
+ virtual bool HasSpace() const;
+
+ // BalloonCloseListener interface
+ virtual void OnBalloonClosed(Balloon* source);
+
+ protected:
+ // Overridable by unit tests.
+ virtual Balloon* MakeBalloon(const Notification& notification,
+ Profile* profile,
+ SiteInstance* site_instance) {
+ return new Balloon(notification, profile, site_instance, this);
+ }
+
+ private:
+ // The number of balloons being displayed.
+ int count() const { return balloons_.size(); }
+
+ // Calculates layout values for the balloons including
+ // the scaling, the max/min sizes, and the upper left corner of each.
+ class Layout {
+ public:
+ Layout();
+
+ // Refresh the work area and balloon placement.
+ void OnDisplaySettingsChanged();
+
+ int min_balloon_width() const;
+ int max_balloon_width() const;
+ int min_balloon_height() const;
+ int max_balloon_height() const;
+
+ // Returns both the total length available and the maximum
+ // allowed per balloon.
+ //
+ // The length may be a height or length depending on the way that
+ // balloons are laid out.
+ const void GetMaxLengths(int* max_balloon_length, int* total_length) const;
+
+ // Scale the size to count in the system font factor.
+ int ScaleSize(int size) const;
+
+ // Refresh the cached values for work area and drawing metrics.
+ // This is done automatically first time and the application should
+ // call this method to re-acquire metrics after any
+ // resolution or settings change.
+ //
+ // Return true if and only if a metric changed.
+ bool RefreshSystemMetrics();
+
+ // Returns the starting value for NextUpperLeftPosition.
+ gfx::Point GetStartPosition() const;
+
+ // Compute the position for the next balloon.
+ // Modifies origin.
+ // Returns the position of the upper left coordinate for the given
+ // balloon.
+ gfx::Point NextPosition(const gfx::Size& balloon_size,
+ gfx::Point* origin) const;
+
+ private:
+ enum Placement {
+ HORIZONTALLY_FROM_BOTTOM_LEFT,
+ HORIZONTALLY_FROM_BOTTOM_RIGHT,
+ VERTICALLY_FROM_TOP_RIGHT,
+ VERTICALLY_FROM_BOTTOM_RIGHT
+ };
+
+ // Minimum and maximum size of balloon
+ static const int kBalloonMinWidth = 300;
+ static const int kBalloonMaxWidth = 300;
+ static const int kBalloonMinHeight = 90;
+ static const int kBalloonMaxHeight = 120;
+
+ static Placement placement_;
+ gfx::Rect work_area_;
+ double font_scale_factor_;
+ DISALLOW_COPY_AND_ASSIGN(Layout);
+ };
+
+ // Non-owned pointer to an object listening for space changes.
+ BalloonSpaceChangeListener* listener_;
+
+ Balloons balloons_;
+ Layout layout_;
+ DISALLOW_COPY_AND_ASSIGN(BalloonCollection);
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_BALLOONS_H_
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
new file mode 100644
index 0000000..0df73d7
--- /dev/null
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -0,0 +1,234 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/desktop_notification_service.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/thread.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_object_proxy.h"
+#include "chrome/browser/notifications/notifications_prefs_cache.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/worker_host/worker_process_host.h"
+#include "chrome/common/child_process_host.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/common/render_messages.h"
+#include "webkit/api/public/WebNotificationPresenter.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+
+using WebKit::WebNotificationPresenter;
+
+// A task object which calls the renderer to inform the web page that the
+// permission request has completed.
+class NotificationPermissionCallbackTask : public Task {
+ public:
+ NotificationPermissionCallbackTask(int process_id, int route_id,
+ int request_id)
+ : process_id_(process_id),
+ route_id_(route_id),
+ request_id_(request_id) {
+ }
+
+ virtual void Run() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
+ if (host)
+ host->Send(new ViewMsg_PermissionRequestDone(route_id_, request_id_));
+ }
+
+ private:
+ int process_id_;
+ int route_id_;
+ int request_id_;
+};
+
+// The delegate for the infobar shown when an origin requests notification
+// permissions.
+class NotificationPermissionInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+ NotificationPermissionInfoBarDelegate(TabContents* contents,
+ const GURL& origin,
+ int callback_context)
+ : ConfirmInfoBarDelegate(contents),
+ origin_(origin),
+ profile_(contents->profile()),
+ process_id_(contents->process()->id()),
+ route_id_(contents->render_view_host()->routing_id()),
+ callback_context_(callback_context),
+ action_taken_(false) {
+ }
+
+ // Overridden from ConfirmInfoBarDelegate:
+ virtual void InfoBarClosed() {
+ if (!action_taken_)
+ UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Ignored", 1);
+
+ base::Thread* io_thread = g_browser_process->io_thread();
+ if (io_thread && io_thread->message_loop()) {
+ io_thread->message_loop()->PostTask(FROM_HERE,
+ new NotificationPermissionCallbackTask(process_id_, route_id_,
+ callback_context_));
+ }
+
+ delete this;
+ }
+
+ virtual std::wstring GetMessageText() const {
+ return l10n_util::GetStringF(IDS_NOTIFICATION_PERMISSIONS,
+ UTF8ToWide(origin_.spec()));
+ }
+
+ virtual SkBitmap* GetIcon() const {
+ return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_PRODUCT_ICON_32);
+ }
+
+ virtual int GetButtons() const {
+ return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
+ }
+
+ virtual std::wstring GetButtonLabel(InfoBarButton button) const {
+ return button == BUTTON_OK ?
+ l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_YES) :
+ l10n_util::GetString(IDS_NOTIFICATION_PERMISSION_NO);
+ }
+
+ virtual bool Accept() {
+ UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Allowed", 1);
+ profile_->GetDesktopNotificationService()->GrantPermission(origin_);
+ action_taken_ = true;
+ return true;
+ }
+
+ virtual bool Cancel() {
+ UMA_HISTOGRAM_COUNTS("NotificationPermissionRequest.Denied", 1);
+ profile_->GetDesktopNotificationService()->DenyPermission(origin_);
+ action_taken_ = true;
+ return true;
+ }
+
+ private:
+ // The origin we are asking for permissions on.
+ GURL origin_;
+
+ // The Profile that we restore sessions from.
+ Profile* profile_;
+
+ // The callback information that tells us how to respond to javascript via
+ // the correct RenderView.
+ int process_id_;
+ int route_id_;
+ int callback_context_;
+
+ // Whether the user clicked one of the buttons.
+ bool action_taken_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationPermissionInfoBarDelegate);
+};
+
+DesktopNotificationService::DesktopNotificationService(Profile* profile,
+ NotificationUIManager* ui_manager)
+ : profile_(profile),
+ ui_manager_(ui_manager) {
+ InitPrefs();
+}
+
+DesktopNotificationService::~DesktopNotificationService() {
+}
+
+// Initialize the cache with the allowed and denied origins, or
+// create the preferences if they don't exist yet.
+void DesktopNotificationService::InitPrefs() {
+ PrefService* prefs = profile_->GetPrefs();
+ ListValue* allowed_sites = NULL;
+ ListValue* denied_sites = NULL;
+
+ if (prefs->FindPreference(prefs::kDesktopNotificationAllowedOrigins))
+ allowed_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
+ else
+ prefs->RegisterListPref(prefs::kDesktopNotificationAllowedOrigins);
+
+ if (prefs->FindPreference(prefs::kDesktopNotificationDeniedOrigins))
+ denied_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
+ else
+ prefs->RegisterListPref(prefs::kDesktopNotificationDeniedOrigins);
+
+ prefs_cache_ = new NotificationsPrefsCache(allowed_sites, denied_sites);
+}
+
+void DesktopNotificationService::GrantPermission(const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ PrefService* prefs = profile_->GetPrefs();
+ ListValue* allowed_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
+ ListValue* denied_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
+ // Remove from the black-list and add to the white-list.
+ StringValue* value = new StringValue(origin.spec());
+ denied_sites->Remove(*value);
+ allowed_sites->Append(value);
+ prefs->ScheduleSavePersistentPrefs();
+
+ // Schedule a cache update on the IO thread.
+ base::Thread* io_thread = g_browser_process->io_thread();
+ if (io_thread && io_thread->message_loop()) {
+ io_thread->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(prefs_cache_.get(),
+ &NotificationsPrefsCache::CacheAllowedOrigin,
+ origin));
+ }
+}
+
+void DesktopNotificationService::DenyPermission(const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ PrefService* prefs = profile_->GetPrefs();
+ ListValue* allowed_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
+ ListValue* denied_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
+ StringValue* value = new StringValue(origin.spec());
+ // Remove from the white-list and add to the black-list.
+ allowed_sites->Remove(*value);
+ denied_sites->Append(value);
+ prefs->ScheduleSavePersistentPrefs();
+
+ // Schedule a cache update on the IO thread.
+ base::Thread* io_thread = g_browser_process->io_thread();
+ if (io_thread && io_thread->message_loop()) {
+ io_thread->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(prefs_cache_.get(),
+ &NotificationsPrefsCache::CacheDeniedOrigin,
+ origin));
+ }
+}
+
+void DesktopNotificationService::RequestPermission(
+ const GURL& origin, int callback_context) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ // Show an info bar requesting permission.
+ Browser* browser = BrowserList::GetLastActive();
+ if (!browser) {
+ // Reached during ui tests.
+ return;
+ }
+ TabContents* tab = browser->GetSelectedTabContents();
+ if (!tab)
+ return;
+ tab->AddInfoBar(new NotificationPermissionInfoBarDelegate(tab, origin,
+ callback_context));
+}
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
new file mode 100644
index 0000000..38e0b27
--- /dev/null
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H
+#define CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "chrome/browser/notifications/notification.h"
+#include "googleurl/src/gurl.h"
+
+class NotificationUIManager;
+class NotificationsPrefsCache;
+class PrefService;
+class Profile;
+class Task;
+
+// The DesktopNotificationService is an object, owned by the Profile,
+// which provides the creation of desktop "toasts" to web pages and workers.
+class DesktopNotificationService {
+ public:
+ enum NotificationSource {
+ PageNotification,
+ WorkerNotification
+ };
+
+ DesktopNotificationService(Profile* profile,
+ NotificationUIManager* ui_manager);
+ ~DesktopNotificationService();
+
+ // Requests permission (using an info-bar) for a given origin.
+ // |callback_context| contains an opaque value to pass back to the
+ // requesting process when the info-bar finishes.
+ void RequestPermission(const GURL& origin, int callback_context);
+
+ // Takes a notification object and shows it in the UI.
+ void ShowNotification(const Notification& notification);
+
+ // Two ShowNotification methods: getting content either from remote
+ // URL or as local parameters. These are called on the UI thread
+ // in response to IPCs from a child process running script. |origin|
+ // is the origin of the script. |source| indicates whether the
+ // script is in a worker or page. |notification_id| is an opaque
+ // value to be passed back to the process when events occur on
+ // this notification.
+ bool ShowDesktopNotification(const GURL& origin, const GURL& url,
+ int process_id, int route_id, NotificationSource source,
+ int notification_id);
+ bool ShowDesktopNotificationText(const GURL& origin, const GURL& icon,
+ const string16& title, const string16& text, int process_id,
+ int route_id, NotificationSource source, int notification_id);
+
+ // Methods to setup and modify permission preferences.
+ void GrantPermission(const GURL& origin);
+ void DenyPermission(const GURL& origin);
+
+ NotificationsPrefsCache* prefs_cache() { return prefs_cache_; }
+
+ private:
+ void InitPrefs();
+
+ // The profile which owns this object.
+ Profile* profile_;
+
+ // A cache of preferences which is accessible only on the IO thread
+ // to service synchronous IPCs.
+ scoped_refptr<NotificationsPrefsCache> prefs_cache_;
+
+ // Non-owned pointer to the notification manager which manages the
+ // UI for desktop toasts.
+ NotificationUIManager* ui_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopNotificationService);
+};
+
+#endif // #ifndef CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H
diff --git a/chrome/browser/notifications/desktop_notification_service_linux.cc b/chrome/browser/notifications/desktop_notification_service_linux.cc
new file mode 100644
index 0000000..15148ce
--- /dev/null
+++ b/chrome/browser/notifications/desktop_notification_service_linux.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/desktop_notification_service.h"
+
+bool DesktopNotificationService::ShowDesktopNotification(
+ const GURL& url,
+ const GURL&,
+ int process_id,
+ int route_id,
+ NotificationSource source,
+ int notification_id) {
+ // TODO(johnnyg): http://crbug.com/23954 Linux support coming soon.
+ return false;
+}
+
+bool DesktopNotificationService::ShowDesktopNotificationText(
+ const GURL& origin,
+ const GURL& url,
+ const string16& title,
+ const string16& text,
+ int process_id,
+ int route_id,
+ NotificationSource source,
+ int notification_id) {
+ // TODO(johnnyg): http://crbug.com/23066 Linux support coming soon.
+ // Coming soon.
+ return false;
+}
diff --git a/chrome/browser/notifications/desktop_notification_service_mac.mm b/chrome/browser/notifications/desktop_notification_service_mac.mm
new file mode 100644
index 0000000..42473c4
--- /dev/null
+++ b/chrome/browser/notifications/desktop_notification_service_mac.mm
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/desktop_notification_service.h"
+
+bool DesktopNotificationService::ShowDesktopNotification(
+ const GURL& url,
+ const GURL&,
+ int process_id,
+ int route_id,
+ NotificationSource source,
+ int notification_id) {
+ // TODO(johnnyg): http://crbug.com/23066 Mac support coming soon.
+ return false;
+}
+
+bool DesktopNotificationService::ShowDesktopNotificationText(
+ const GURL& origin,
+ const GURL& url,
+ const string16& title,
+ const string16& text,
+ int process_id,
+ int route_id,
+ NotificationSource source,
+ int notification_id) {
+ // TODO(johnnyg): http://crbug.com/23066 Integration with Growl will go here
+ // Coming soon.
+ return false;
+}
diff --git a/chrome/browser/notifications/desktop_notification_service_win.cc b/chrome/browser/notifications/desktop_notification_service_win.cc
new file mode 100644
index 0000000..41e3e29
--- /dev/null
+++ b/chrome/browser/notifications/desktop_notification_service_win.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/desktop_notification_service.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_piece.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/notifications/notification_object_proxy.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/worker_host/worker_process_host.h"
+#include "chrome/common/child_process_host.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+
+// Creates a data:xxxx URL which contains the full HTML for a notification
+// using supplied icon, title, and text, run through a template which contains
+// the standard formatting for notifications.
+static string16 CreateDataUrl(const GURL& icon_url, const string16& title,
+ const string16& body) {
+ const base::StringPiece template_html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_NOTIFICATION_HTML));
+
+ if (template_html.empty()) {
+ NOTREACHED() << "unable to load template. ID: " << IDR_NOTIFICATION_HTML;
+ return EmptyString16();
+ }
+
+ std::vector<string16> subst;
+ if (icon_url.is_valid())
+ subst.push_back(UTF8ToUTF16(icon_url.spec()));
+ else
+ subst.push_back(EmptyString16());
+
+ subst.push_back(title);
+ subst.push_back(body);
+
+ if (icon_url.is_valid()) {
+ subst.push_back(ASCIIToUTF16("block"));
+ subst.push_back(ASCIIToUTF16("60"));
+ } else {
+ subst.push_back(ASCIIToUTF16("none"));
+ subst.push_back(ASCIIToUTF16("5"));
+ }
+
+ string16 format_string = ASCIIToUTF16("data:text/html;charset=utf-8,"
+ + template_html.as_string());
+ return ReplaceStringPlaceholders(format_string, subst, NULL);
+}
+
+// This will call the notification manager on the UI thread to actually
+// put the notification with the requested parameters on the desktop.
+void DesktopNotificationService::ShowNotification(
+ const Notification& notification) {
+ SiteInstance* site_instance = SiteInstance::CreateSiteInstance(profile_);
+ // TODO(johnnyg): When UI Manager is available, add from here.
+ // ui_manager_->Add(notification, profile_, site_instance);
+}
+
+// Shows a notification bubble which contains the contents of url.
+bool DesktopNotificationService::ShowDesktopNotification(
+ const GURL& origin, const GURL& url, int process_id, int route_id,
+ NotificationSource source, int notification_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ NotificationObjectProxy* proxy =
+ new NotificationObjectProxy(process_id, route_id,
+ notification_id,
+ source == WorkerNotification);
+ Notification notif(origin, url, proxy);
+ ShowNotification(notif);
+ return true;
+}
+
+// Shows a notification constructed from an icon, title, and text.
+bool DesktopNotificationService::ShowDesktopNotificationText(
+ const GURL& origin, const GURL& icon, const string16& title,
+ const string16& text, int process_id, int route_id,
+ NotificationSource source, int notification_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ NotificationObjectProxy* proxy =
+ new NotificationObjectProxy(process_id, route_id,
+ notification_id,
+ source == WorkerNotification);
+ // "upconvert" the string parameters to a data: URL.
+ string16 data_url = CreateDataUrl(icon, title, text);
+ Notification notif(origin, GURL(data_url), proxy);
+ ShowNotification(notif);
+ return true;
+}
+
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h
new file mode 100644
index 0000000..ed63e04
--- /dev/null
+++ b/chrome/browser/notifications/notification.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/notifications/notification_object_proxy.h"
+#include "googleurl/src/gurl.h"
+
+// Representation of an notification to be shown to the user. All
+// notifications at this level are HTML, although they may be
+// data: URLs representing simple text+icon notifications.
+class Notification {
+ public:
+ Notification(const GURL& origin_url, const GURL& content_url,
+ NotificationObjectProxy* proxy)
+ : origin_url_(origin_url),
+ content_url_(content_url),
+ proxy_(proxy) {
+ }
+
+ Notification(const Notification& notification)
+ : origin_url_(notification.origin_url()),
+ content_url_(notification.content_url()),
+ proxy_(notification.proxy()) {
+ }
+
+ // The URL (may be data:) containing the contents for the notification.
+ const GURL& content_url() const { return content_url_; }
+
+ // The origin URL of the script which requested the notification.
+ const GURL& origin_url() const { return origin_url_; }
+
+ void Display() const { proxy()->Display(); }
+ void Error() const { proxy()->Error(); }
+ void Close(bool by_user) const { proxy()->Close(by_user); }
+
+ private:
+ NotificationObjectProxy* proxy() const { return proxy_.get(); }
+
+ // The Origin of the page/worker which created this notification.
+ GURL origin_url_;
+
+ // The URL of the HTML content of the toast (may be a data: URL for simple
+ // string-based notifications).
+ GURL content_url_;
+
+ // A proxy object that allows access back to the JavaScript object that
+ // represents the notification, for firing events.
+ scoped_refptr<NotificationObjectProxy> proxy_;
+
+ // Disallow assign. Copy constructor written above.
+ void operator=(const Notification&);
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_H_
diff --git a/chrome/browser/notifications/notification_object_proxy.cc b/chrome/browser/notifications/notification_object_proxy.cc
new file mode 100644
index 0000000..f230d19
--- /dev/null
+++ b/chrome/browser/notifications/notification_object_proxy.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/notification_object_proxy.h"
+
+#include "base/message_loop.h"
+#include "base/string16.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/common/render_messages.h"
+
+NotificationObjectProxy::NotificationObjectProxy(int process_id, int route_id,
+ int notification_id, bool worker)
+ : process_id_(process_id),
+ route_id_(route_id),
+ notification_id_(notification_id),
+ worker_(worker) {
+}
+
+void NotificationObjectProxy::Display() {
+ if (worker_) {
+ // TODO(johnnyg): http://crbug.com/23065 Worker support coming soon.
+ NOTREACHED();
+ } else {
+ DeliverMessage(new ViewMsg_PostDisplayToNotificationObject(
+ route_id_, notification_id_));
+ }
+}
+
+void NotificationObjectProxy::Error() {
+ if (worker_) {
+ // TODO(johnnyg): http://crbug.com/23065 Worker support coming soon.
+ NOTREACHED();
+ } else {
+ DeliverMessage(new ViewMsg_PostErrorToNotificationObject(
+ route_id_, notification_id_, string16()));
+ }
+}
+
+void NotificationObjectProxy::Close(bool by_user) {
+ if (worker_) {
+ // TODO(johnnyg): http://crbug.com/23065 Worker support coming soon.
+ NOTREACHED();
+ } else {
+ DeliverMessage(new ViewMsg_PostCloseToNotificationObject(
+ route_id_, notification_id_, by_user));
+ }
+}
+
+void NotificationObjectProxy::DeliverMessage(IPC::Message* message) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ MessageLoop* io_loop = ChromeThread::GetMessageLoop(ChromeThread::IO);
+ if (io_loop) {
+ io_loop->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &NotificationObjectProxy::Send, message));
+ }
+}
+
+// Deferred method which runs on the IO thread and sends a message to the
+// proxied notification, routing it through the correct host in the browser.
+void NotificationObjectProxy::Send(IPC::Message* message) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ RenderViewHost* host = RenderViewHost::FromID(process_id_, route_id_);
+ if (host)
+ host->Send(message);
+}
diff --git a/chrome/browser/notifications/notification_object_proxy.h b/chrome/browser/notifications/notification_object_proxy.h
new file mode 100644
index 0000000..168bd8a
--- /dev/null
+++ b/chrome/browser/notifications/notification_object_proxy.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_OBJECT_PROXY_H_
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_OBJECT_PROXY_H_
+
+#include "base/ref_counted.h"
+
+class MessageLoop;
+namespace IPC {
+class Message;
+}
+
+// A NotificationObjectProxy stands in for the JavaScript Notification object
+// which corresponds to a notification toast on the desktop. It can be signaled
+// when various events occur regarding the desktop notification, and the
+// attached JS listeners will be invoked in the renderer or worker process.
+class NotificationObjectProxy :
+ public base::RefCountedThreadSafe<NotificationObjectProxy> {
+ public:
+ // Creates a Proxy object with the necessary callback information.
+ NotificationObjectProxy(int process_id, int route_id,
+ int notification_id, bool worker);
+
+ // To be called when the desktop notification is actually shown.
+ void Display();
+
+ // To be called when the desktop notification cannot be shown due to an
+ // error.
+ void Error();
+
+ // To be called when the desktop notification is closed. If closed by a
+ // user explicitly (as opposed to timeout), |by_user| should be true.
+ void Close(bool by_user);
+
+ private:
+ // Called on UI thread to schedule a message for sending.
+ void DeliverMessage(IPC::Message* message);
+
+ // Called via Task on IO thread to actually send a message to a notification.
+ void Send(IPC::Message* message);
+
+ // Callback information to find the JS Notification object where it lives.
+ int process_id_;
+ int route_id_;
+ int notification_id_;
+ bool worker_;
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_OBJECT_PROXY_H_
diff --git a/chrome/browser/notifications/notifications_prefs_cache.cc b/chrome/browser/notifications/notifications_prefs_cache.cc
new file mode 100644
index 0000000..c5663e4
--- /dev/null
+++ b/chrome/browser/notifications/notifications_prefs_cache.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/notifications_prefs_cache.h"
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/pref_service.h"
+#include "webkit/api/public/WebNotificationPresenter.h"
+
+NotificationsPrefsCache::NotificationsPrefsCache(
+ ListValue* allowed, ListValue* denied) {
+ ListValue::const_iterator i;
+ std::wstring origin;
+ if (allowed) {
+ for (i = allowed->begin(); i != allowed->end(); ++i) {
+ (*i)->GetAsString(&origin);
+ allowed_origins_.insert(GURL(WideToUTF8(origin)));
+ }
+ }
+ if (denied) {
+ for (i = denied->begin(); i != denied->end(); ++i) {
+ (*i)->GetAsString(&origin);
+ denied_origins_.insert(GURL(WideToUTF8(origin)));
+ }
+ }
+}
+
+void NotificationsPrefsCache::CacheAllowedOrigin(
+ const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ std::set<GURL>::iterator iter;
+ allowed_origins_.insert(origin);
+ if ((iter = denied_origins_.find(origin)) != denied_origins_.end())
+ denied_origins_.erase(iter);
+}
+
+void NotificationsPrefsCache::CacheDeniedOrigin(
+ const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ std::set<GURL>::iterator iter;
+ denied_origins_.insert(origin);
+ if ((iter = allowed_origins_.find(origin)) != allowed_origins_.end())
+ allowed_origins_.erase(iter);
+}
+
+int NotificationsPrefsCache::HasPermission(const GURL& origin) {
+ if (IsOriginAllowed(origin))
+ return WebKit::WebNotificationPresenter::PermissionAllowed;
+ if (IsOriginDenied(origin))
+ return WebKit::WebNotificationPresenter::PermissionDenied;
+ return WebKit::WebNotificationPresenter::PermissionNotAllowed;
+}
+
+bool NotificationsPrefsCache::IsOriginAllowed(
+ const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ return (allowed_origins_.find(origin) != allowed_origins_.end());
+}
+
+bool NotificationsPrefsCache::IsOriginDenied(
+ const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ return (denied_origins_.find(origin) != denied_origins_.end());
+}
diff --git a/chrome/browser/notifications/notifications_prefs_cache.h b/chrome/browser/notifications/notifications_prefs_cache.h
new file mode 100644
index 0000000..e873da7
--- /dev/null
+++ b/chrome/browser/notifications/notifications_prefs_cache.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATIONS_PREFS_CACHE_H
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATIONS_PREFS_CACHE_H
+
+#include <set>
+
+#include "base/ref_counted.h"
+#include "googleurl/src/gurl.h"
+
+class ListValue;
+
+// Class which caches notification preferences.
+// Construction occurs on the UI thread when the contents
+// of the profile preferences are initially cached. Once constructed
+// this class should only be accessed on the IO thread.
+class NotificationsPrefsCache :
+ public base::RefCountedThreadSafe<NotificationsPrefsCache> {
+ public:
+ NotificationsPrefsCache(ListValue* allowed, ListValue* denied);
+
+ // Checks to see if a given origin has permission to create desktop
+ // notifications. Returns a constant from WebNotificationPresenter
+ // class.
+ int HasPermission(const GURL& origin);
+
+ // Updates the cache with a new origin allowed or denied.
+ void CacheAllowedOrigin(const GURL& origin);
+ void CacheDeniedOrigin(const GURL& origin);
+
+ private:
+ // Helper functions which read preferences.
+ bool IsOriginAllowed(const GURL& origin);
+ bool IsOriginDenied(const GURL& origin);
+
+ // Storage of the actual preferences.
+ std::set<GURL> allowed_origins_;
+ std::set<GURL> denied_origins_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationsPrefsCache);
+};
+
+#endif // #ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATIONS_PREFS_CACHE_H
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 4508644..87c9713 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -27,6 +27,7 @@
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/ssl_config_service_manager.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/password_manager/password_store_default.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
#include "chrome/browser/profile_manager.h"
@@ -459,6 +460,10 @@ class OffTheRecordProfileImpl : public Profile,
return profile_->GetBookmarkModel();
}
+ virtual DesktopNotificationService* GetDesktopNotificationService() {
+ return profile_->GetDesktopNotificationService();
+ }
+
virtual ProfileSyncService* GetProfileSyncService() {
return NULL;
}
@@ -1344,6 +1349,17 @@ WebKitContext* ProfileImpl::GetWebKitContext() {
return webkit_context_.get();
}
+DesktopNotificationService* ProfileImpl::GetDesktopNotificationService() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ if (!desktop_notification_service_.get()) {
+ // TODO(johnnyg): hook this up with notification UI manager.
+ desktop_notification_service_.reset(new DesktopNotificationService(
+ this, NULL));
+ }
+
+ return desktop_notification_service_.get();
+}
+
void ProfileImpl::MarkAsCleanShutdown() {
if (prefs_.get()) {
// The session cleanly exited, set kSessionExitedCleanly appropriately.
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 07e5e34..a7107f4 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -30,6 +30,7 @@ class BookmarkModel;
class BrowserThemeProvider;
class ChromeAppCacheService;
class ChromeURLRequestContext;
+class DesktopNotificationService;
class DownloadManager;
class Extension;
class ExtensionDevToolsManager;
@@ -343,6 +344,9 @@ class Profile {
// Returns the WebKitContext assigned to this profile.
virtual WebKitContext* GetWebKitContext() = 0;
+ // Returns the provider of desktop notifications for this profile.
+ virtual DesktopNotificationService* GetDesktopNotificationService() = 0;
+
// Marks the profile as cleanly shutdown.
//
// NOTE: this is invoked internally on a normal shutdown, but is public so
@@ -439,6 +443,7 @@ class ProfileImpl : public Profile,
virtual SpellChecker* GetSpellChecker();
virtual void DeleteSpellChecker() { DeleteSpellCheckerImpl(true); }
virtual WebKitContext* GetWebKitContext();
+ virtual DesktopNotificationService* GetDesktopNotificationService();
virtual void MarkAsCleanShutdown();
virtual void InitExtensions();
virtual void InitWebResources();
@@ -520,6 +525,7 @@ class ProfileImpl : public Profile,
scoped_refptr<SessionService> session_service_;
scoped_ptr<BrowserThemeProvider> theme_provider_;
scoped_refptr<WebKitContext> webkit_context_;
+ scoped_ptr<DesktopNotificationService> desktop_notification_service_;
bool history_service_created_;
bool favicon_service_created_;
bool created_web_data_service_;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index af14f52..cd9eb26 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/dom_operation_notification_details.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
@@ -833,6 +834,12 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
OnQueryFormFieldAutofill)
IPC_MESSAGE_HANDLER(ViewHostMsg_RemoveAutofillEntry,
OnRemoveAutofillEntry)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDesktopNotification,
+ OnShowDesktopNotification)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDesktopNotificationText,
+ OnShowDesktopNotificationText)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RequestNotificationPermission,
+ OnRequestNotificationPermission)
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRequest, OnExtensionRequest)
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnMsgSelectionChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage,
@@ -1644,6 +1651,32 @@ void RenderViewHost::ForwardMessageFromExternalHost(const std::string& message,
target));
}
+void RenderViewHost::OnShowDesktopNotification(const GURL& source_origin,
+ const GURL& url, int notification_id) {
+ DesktopNotificationService* service =
+ process()->profile()->GetDesktopNotificationService();
+ service->ShowDesktopNotification(source_origin, url, process()->id(),
+ routing_id(), DesktopNotificationService::PageNotification,
+ notification_id);
+}
+
+void RenderViewHost::OnShowDesktopNotificationText(const GURL& source_origin,
+ const GURL& icon, const string16& title, const string16& text,
+ int notification_id) {
+ DesktopNotificationService* service =
+ process()->profile()->GetDesktopNotificationService();
+ service->ShowDesktopNotificationText(source_origin, icon, title, text,
+ process()->id(), routing_id(),
+ DesktopNotificationService::PageNotification, notification_id);
+}
+
+void RenderViewHost::OnRequestNotificationPermission(
+ const GURL& source_origin, int callback_context) {
+ DesktopNotificationService* service =
+ process()->profile()->GetDesktopNotificationService();
+ service->RequestPermission(source_origin, callback_context);
+}
+
void RenderViewHost::OnExtensionRequest(const std::string& name,
const ListValue& args_holder,
int request_id,
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 76b7460..7f24d97 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -577,6 +577,14 @@ class RenderViewHost : public RenderWidgetHost,
void OnRemoveAutofillEntry(const std::wstring& field_name,
const std::wstring& value);
+ void OnShowDesktopNotification(const GURL& source_origin,
+ const GURL& url, int notification_id);
+ void OnShowDesktopNotificationText(const GURL& origin, const GURL& icon,
+ const string16& title,
+ const string16& text,
+ int notification_id);
+ void OnRequestNotificationPermission(const GURL& origin, int callback_id);
+
void OnExtensionRequest(const std::string& name, const ListValue& args,
int request_id, bool has_callback);
void OnExtensionPostMessage(int port_id, const std::string& message);
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 5645ef6..8927ab0 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -19,6 +19,8 @@
#include "chrome/browser/nacl_process_host.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/dns_global.h"
+#include "chrome/browser/notifications/desktop_notification_service.h"
+#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/plugin_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
@@ -167,6 +169,8 @@ ResourceMessageFilter::ResourceMessageFilter(
resource_dispatcher_host->webkit_thread()))),
ALLOW_THIS_IN_INITIALIZER_LIST(db_dispatcher_host_(
new DatabaseDispatcherHost(profile->GetPath(), this))),
+ notification_prefs_(
+ profile->GetDesktopNotificationService()->prefs_cache()),
off_the_record_(profile->IsOffTheRecord()),
next_route_id_callback_(NewCallbackWithReturnValue(
render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)) {
@@ -335,6 +339,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardFindPboardWriteStringAsync,
OnClipboardFindPboardWriteString)
#endif
+ IPC_MESSAGE_HANDLER(ViewHostMsg_CheckNotificationPermission,
+ OnCheckNotificationPermission)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromExtension,
OnGetMimeTypeFromExtension)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromFile,
@@ -690,6 +696,11 @@ void ResourceMessageFilter::OnClipboardReadHTML(Clipboard::Buffer buffer,
#endif
+void ResourceMessageFilter::OnCheckNotificationPermission(
+ const GURL& source_origin, int* result) {
+ *result = notification_prefs_->HasPermission(source_origin);
+}
+
void ResourceMessageFilter::OnGetMimeTypeFromExtension(
const FilePath::StringType& ext, std::string* mime_type) {
net::GetMimeTypeFromExtension(ext, mime_type);
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 8084e72..bcb5ece5 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -36,6 +36,7 @@ class AudioRendererHost;
class DatabaseDispatcherHost;
class DOMStorageDispatcherHost;
class ExtensionMessageService;
+class NotificationsPrefsCache;
class Profile;
class RenderWidgetHelper;
class SpellChecker;
@@ -191,6 +192,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnClipboardFindPboardWriteString(const string16& text);
#endif
+ void OnCheckNotificationPermission(const GURL& origin,
+ int* permission_level);
+
#if !defined(OS_MACOSX)
// Not handled in the IO thread on Mac.
void OnGetWindowRect(gfx::NativeViewId window, IPC::Message* reply);
@@ -350,6 +354,10 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// Handles HTML5 DB related messages
scoped_ptr<DatabaseDispatcherHost> db_dispatcher_host_;
+ // A cache of notifications preferences which is used to handle
+ // Desktop Notifications permission messages.
+ scoped_refptr<NotificationsPrefsCache> notification_prefs_;
+
// Whether this process is used for off the record tabs.
bool off_the_record_;
diff --git a/chrome/browser/resources/notification.html b/chrome/browser/resources/notification.html
new file mode 100644
index 0000000..5e436e7
--- /dev/null
+++ b/chrome/browser/resources/notification.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+<title>$2</title>
+<style type="text/css"><!--
+#icon {
+height:48px;
+width:48px;
+position:absolute;
+top:2px;
+left:2px;
+display:$4;
+}
+#title {
+font-weight:bold;
+position:absolute;
+top:3px;
+left:$5px;
+font-family:sans-serif;
+font-size:11pt;
+}
+#body {
+position:absolute;
+left:$5px;
+top:20px;
+font-family:sans-serif;
+font-size:9pt;
+}
+//-->
+</style>
+</head>
+<body>
+<div id="icon"><img src="$1" /></div>
+<div id="title">$2</div>
+<div id="body">$3</div>
+</body>
+</html>
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index eac73f5..3708a3a 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1724,6 +1724,17 @@
'browser/net/url_request_slow_http_job.h',
'browser/net/url_request_tracking.cc',
'browser/net/url_request_tracking.h',
+ 'browser/notifications/balloons.h',
+ 'browser/notifications/desktop_notification_service.cc',
+ 'browser/notifications/desktop_notification_service.h',
+ 'browser/notifications/desktop_notification_service_linux.cc',
+ 'browser/notifications/desktop_notification_service_mac.mm',
+ 'browser/notifications/desktop_notification_service_win.cc',
+ 'browser/notifications/notification.h',
+ 'browser/notifications/notification_object_proxy.cc',
+ 'browser/notifications/notification_object_proxy.h',
+ 'browser/notifications/notifications_prefs_cache.cc',
+ 'browser/notifications/notifications_prefs_cache.h',
'browser/ntp_background_util.cc',
'browser/ntp_background_util.h',
'browser/omnibox_search_hint.cc',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index b1104da..ee03bc3 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -281,6 +281,12 @@ const wchar_t kShowOmniboxSearchHint[] = L"browser.show_omnibox_search_hint";
// in a session.
const wchar_t kNTPThemePromoRemaining[] = L"browser.ntp.theme_promo_remaining";
+// The list of origins which are allowed|denied to show desktop notifications.
+const wchar_t kDesktopNotificationAllowedOrigins[] =
+ L"profile.notification_allowed_sites";
+const wchar_t kDesktopNotificationDeniedOrigins[] =
+ L"profile.notification_denied_sites";
+
// *************** LOCAL STATE ***************
// These are attached to the machine/installation
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 01fb279..f6d62ea 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -112,6 +112,8 @@ extern const wchar_t kCheckDefaultBrowser[];
extern const wchar_t kUseCustomChromeFrame[];
extern const wchar_t kShowOmniboxSearchHint[];
extern const wchar_t kNTPThemePromoRemaining[];
+extern const wchar_t kDesktopNotificationAllowedOrigins[];
+extern const wchar_t kDesktopNotificationDeniedOrigins[];
// Local state
extern const wchar_t kMetricsClientID[];
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 2758c95..d29d41d 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1701,10 +1701,10 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_CancelDesktopNotification,
int /* notification_id */ )
IPC_MESSAGE_ROUTED2(ViewHostMsg_RequestNotificationPermission,
- string16 /* origin */,
+ GURL /* origin */,
int /* callback_context */)
IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_CheckNotificationPermission,
- string16 /* origin */,
+ GURL /* origin */,
int /* permission_result */)
// Sent if the worker object has sent a ViewHostMsg_CreateDedicatedWorker
diff --git a/chrome/renderer/notification_provider.cc b/chrome/renderer/notification_provider.cc
index f6baba8..505349d 100644
--- a/chrome/renderer/notification_provider.cc
+++ b/chrome/renderer/notification_provider.cc
@@ -47,8 +47,8 @@ void NotificationProvider::objectDestroyed(
WebNotificationPresenter::Permission NotificationProvider::checkPermission(
const WebString& origin) {
int permission;
- Send(new ViewHostMsg_CheckNotificationPermission(view_->routing_id(), origin,
- &permission));
+ Send(new ViewHostMsg_CheckNotificationPermission(view_->routing_id(),
+ GURL(origin), &permission));
return static_cast<WebNotificationPresenter::Permission>(permission);
}
@@ -57,7 +57,7 @@ void NotificationProvider::requestPermission(
int id = manager_.RegisterPermissionRequest(callback);
Send(new ViewHostMsg_RequestNotificationPermission(view_->routing_id(),
- origin, id));
+ GURL(origin), id));
}
bool NotificationProvider::ShowHTML(const WebNotification& notification,
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 8f49917..ca10ebd 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -173,6 +173,9 @@ class TestingProfile : public Profile {
virtual void MarkAsCleanShutdown() {}
virtual void InitExtensions() {}
virtual void InitWebResources() {}
+ virtual DesktopNotificationService* GetDesktopNotificationService() {
+ return NULL;
+ }
// Schedules a task on the history backend and runs a nested loop until the
// task is processed. This has the effect of blocking the caller until the