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 blink::WebDocument;
     19 using blink::WebNotification;
     20 using blink::WebNotificationPresenter;
     21 using blink::WebNotificationPermissionCallback;
     22 using blink::WebSecurityOrigin;
     23 using blink::WebString;
     24 using blink::WebURL;
     25 using blink::WebUserGestureIndicator;
     26 
     27 namespace content {
     28 
     29 
     30 NotificationProvider::NotificationProvider(RenderViewImpl* render_view)
     31     : RenderViewObserver(render_view) {
     32 }
     33 
     34 NotificationProvider::~NotificationProvider() {
     35 }
     36 
     37 bool NotificationProvider::show(const WebNotification& notification) {
     38   WebDocument document = render_view()->GetWebView()->mainFrame()->document();
     39   int notification_id = manager_.RegisterNotification(notification);
     40 
     41   ShowDesktopNotificationHostMsgParams params;
     42   params.origin = GURL(document.securityOrigin().toString());
     43   params.icon_url = notification.iconURL();
     44   params.title = notification.title();
     45   params.body = notification.body();
     46   params.direction = notification.direction();
     47   params.notification_id = notification_id;
     48   params.replace_id = notification.replaceId();
     49   return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
     50 }
     51 
     52 void NotificationProvider::cancel(const WebNotification& notification) {
     53   int id;
     54   bool id_found = manager_.GetId(notification, id);
     55   // Won't be found if the notification has already been closed by the user.
     56   if (id_found)
     57     Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
     58 }
     59 
     60 void NotificationProvider::objectDestroyed(
     61     const WebNotification& notification) {
     62   int id;
     63   bool id_found = manager_.GetId(notification, id);
     64   // Won't be found if the notification has already been closed by the user.
     65   if (id_found)
     66     manager_.UnregisterNotification(id);
     67 }
     68 
     69 WebNotificationPresenter::Permission NotificationProvider::checkPermission(
     70     const WebSecurityOrigin& origin) {
     71   int permission;
     72   Send(new DesktopNotificationHostMsg_CheckPermission(
     73           routing_id(),
     74           GURL(origin.toString()),
     75           &permission));
     76   return static_cast<WebNotificationPresenter::Permission>(permission);
     77 }
     78 
     79 void NotificationProvider::requestPermission(
     80     const WebSecurityOrigin& origin,
     81     WebNotificationPermissionCallback* callback) {
     82   // We only request permission in response to a user gesture.
     83   if (!WebUserGestureIndicator::isProcessingUserGesture())
     84     return;
     85 
     86   int id = manager_.RegisterPermissionRequest(callback);
     87 
     88   Send(new DesktopNotificationHostMsg_RequestPermission(
     89       routing_id(), GURL(origin.toString()), id));
     90 }
     91 
     92 bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
     93   bool handled = true;
     94   IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
     95     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostDisplay, OnDisplay);
     96     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostError, OnError);
     97     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClose, OnClose);
     98     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClick, OnClick);
     99     IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PermissionRequestDone,
    100                         OnPermissionRequestComplete);
    101     IPC_MESSAGE_UNHANDLED(handled = false)
    102   IPC_END_MESSAGE_MAP()
    103 
    104   if (message.type() == ViewMsg_Navigate::ID)
    105     OnNavigate();  // Don't want to swallow the message.
    106 
    107   return handled;
    108 }
    109 
    110 void NotificationProvider::OnDisplay(int id) {
    111   WebNotification notification;
    112   bool found = manager_.GetNotification(id, &notification);
    113   // |found| may be false if the WebNotification went out of scope in
    114   // the page before it was actually displayed to the user.
    115   if (found)
    116     notification.dispatchDisplayEvent();
    117 }
    118 
    119 void NotificationProvider::OnError(int id, const WebString& message) {
    120   WebNotification notification;
    121   bool found = manager_.GetNotification(id, &notification);
    122   // |found| may be false if the WebNotification went out of scope in
    123   // the page before the error occurred.
    124   if (found)
    125     notification.dispatchErrorEvent(message);
    126 }
    127 
    128 void NotificationProvider::OnClose(int id, bool by_user) {
    129   WebNotification notification;
    130   bool found = manager_.GetNotification(id, &notification);
    131   // |found| may be false if the WebNotification went out of scope in
    132   // the page before the associated toast was closed by the user.
    133   if (found) {
    134     notification.dispatchCloseEvent(by_user);
    135     manager_.UnregisterNotification(id);
    136   }
    137 }
    138 
    139 void NotificationProvider::OnClick(int id) {
    140   WebNotification notification;
    141   bool found = manager_.GetNotification(id, &notification);
    142   // |found| may be false if the WebNotification went out of scope in
    143   // the page before the associated toast was clicked on.
    144   if (found)
    145     notification.dispatchClickEvent();
    146 }
    147 
    148 void NotificationProvider::OnPermissionRequestComplete(int id) {
    149   WebNotificationPermissionCallback* callback = manager_.GetCallback(id);
    150   DCHECK(callback);
    151   callback->permissionRequestComplete();
    152   manager_.OnPermissionRequestComplete(id);
    153 }
    154 
    155 void NotificationProvider::OnNavigate() {
    156   manager_.Clear();
    157 }
    158 
    159 }  // namespace content
    160