Home | History | Annotate | Download | only in renderer
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/notification_provider.h"
      6 
      7 #include "base/strings/string_util.h"
      8 #include "content/common/desktop_notification_messages.h"
      9 #include "content/common/view_messages.h"
     10 #include "content/renderer/render_view_impl.h"
     11 #include "third_party/WebKit/public/platform/WebURL.h"
     12 #include "third_party/WebKit/public/web/WebDocument.h"
     13 #include "third_party/WebKit/public/web/WebFrame.h"
     14 #include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
     15 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
     16 #include "third_party/WebKit/public/web/WebView.h"
     17 
     18 using WebKit::WebDocument;
     19 using WebKit::WebNotification;
     20 using WebKit::WebNotificationPresenter;
     21 using WebKit::WebNotificationPermissionCallback;
     22 using WebKit::WebSecurityOrigin;
     23 using WebKit::WebString;
     24 using WebKit::WebURL;
     25 using WebKit::WebUserGestureIndicator;
     26 
     27 namespace content {
     28 
     29 
     30 NotificationProvider::NotificationProvider(RenderViewImpl* render_view)
     31     : RenderViewObserver(render_view) {
     32 }
     33 
     34 NotificationProvider::~NotificationProvider() {
     35   manager_.DetachAll();
     36 }
     37 
     38 bool NotificationProvider::show(const WebNotification& notification) {
     39   int notification_id = manager_.RegisterNotification(notification);
     40   if (notification.isHTML())
     41     return ShowHTML(notification, notification_id);
     42   else
     43     return ShowText(notification, notification_id);
     44 }
     45 
     46 void NotificationProvider::cancel(const WebNotification& notification) {
     47   int id;
     48   bool id_found = manager_.GetId(notification, id);
     49   // Won't be found if the notification has already been closed by the user.
     50   if (id_found)
     51     Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
     52 }
     53 
     54 void NotificationProvider::objectDestroyed(
     55     const WebNotification& notification) {
     56   int id;
     57   bool id_found = manager_.GetId(notification, id);
     58   // Won't be found if the notification has already been closed by the user.
     59   if (id_found)
     60     manager_.UnregisterNotification(id);
     61 }
     62 
     63 WebNotificationPresenter::Permission NotificationProvider::checkPermission(
     64     const WebSecurityOrigin& origin) {
     65   int permission;
     66   Send(new DesktopNotificationHostMsg_CheckPermission(
     67           routing_id(),
     68           GURL(origin.toString()),
     69           &permission));
     70   return static_cast<WebNotificationPresenter::Permission>(permission);
     71 }
     72 
     73 void NotificationProvider::requestPermission(
     74     const WebSecurityOrigin& origin,
     75     WebNotificationPermissionCallback* callback) {
     76   // We only request permission in response to a user gesture.
     77   if (!WebUserGestureIndicator::isProcessingUserGesture())
     78     return;
     79 
     80   int id = manager_.RegisterPermissionRequest(callback);
     81 
     82   Send(new DesktopNotificationHostMsg_RequestPermission(
     83       routing_id(), GURL(origin.toString()), id));
     84 }
     85 
     86 bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
     87   bool handled = true;
     88   IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
     89     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostDisplay, OnDisplay);
     90     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostError, OnError);
     91     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClose, OnClose);
     92     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClick, OnClick);
     93     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PermissionRequestDone,
     94                         OnPermissionRequestComplete);
     95     IPC_MESSAGE_UNHANDLED(handled = false)
     96   IPC_END_MESSAGE_MAP()
     97 
     98   if (message.type() == ViewMsg_Navigate::ID)
     99     OnNavigate();  // Don't want to swallow the message.
    100 
    101   return handled;
    102 }
    103 
    104 bool NotificationProvider::ShowHTML(const WebNotification& notification,
    105                                     int id) {
    106   DCHECK(notification.isHTML());
    107   ShowDesktopNotificationHostMsgParams params;
    108   WebDocument document = render_view()->GetWebView()->mainFrame()->document();
    109   params.origin = GURL(document.securityOrigin().toString());
    110   params.is_html = true;
    111   params.contents_url = notification.url();
    112   params.notification_id = id;
    113   params.replace_id = notification.replaceId();
    114   return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
    115 }
    116 
    117 bool NotificationProvider::ShowText(const WebNotification& notification,
    118                                     int id) {
    119   DCHECK(!notification.isHTML());
    120   ShowDesktopNotificationHostMsgParams params;
    121   params.is_html = false;
    122   WebDocument document = render_view()->GetWebView()->mainFrame()->document();
    123   params.origin = GURL(document.securityOrigin().toString());
    124   params.icon_url = notification.iconURL();
    125   params.title = notification.title();
    126   params.body = notification.body();
    127   params.direction = notification.direction();
    128   params.notification_id = id;
    129   params.replace_id = notification.replaceId();
    130   return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
    131 }
    132 
    133 void NotificationProvider::OnDisplay(int id) {
    134   WebNotification notification;
    135   bool found = manager_.GetNotification(id, &notification);
    136   // |found| may be false if the WebNotification went out of scope in
    137   // the page before it was actually displayed to the user.
    138   if (found)
    139     notification.dispatchDisplayEvent();
    140 }
    141 
    142 void NotificationProvider::OnError(int id, const WebString& message) {
    143   WebNotification notification;
    144   bool found = manager_.GetNotification(id, &notification);
    145   // |found| may be false if the WebNotification went out of scope in
    146   // the page before the error occurred.
    147   if (found)
    148     notification.dispatchErrorEvent(message);
    149 }
    150 
    151 void NotificationProvider::OnClose(int id, bool by_user) {
    152   WebNotification notification;
    153   bool found = manager_.GetNotification(id, &notification);
    154   // |found| may be false if the WebNotification went out of scope in
    155   // the page before the associated toast was closed by the user.
    156   if (found) {
    157     notification.dispatchCloseEvent(by_user);
    158     manager_.UnregisterNotification(id);
    159   }
    160 }
    161 
    162 void NotificationProvider::OnClick(int id) {
    163   WebNotification notification;
    164   bool found = manager_.GetNotification(id, &notification);
    165   // |found| may be false if the WebNotification went out of scope in
    166   // the page before the associated toast was clicked on.
    167   if (found)
    168     notification.dispatchClickEvent();
    169 }
    170 
    171 void NotificationProvider::OnPermissionRequestComplete(int id) {
    172   WebNotificationPermissionCallback* callback = manager_.GetCallback(id);
    173   DCHECK(callback);
    174   callback->permissionRequestComplete();
    175   manager_.OnPermissionRequestComplete(id);
    176 }
    177 
    178 void NotificationProvider::OnNavigate() {
    179   manager_.Clear();
    180 }
    181 
    182 }  // namespace content
    183