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, ¬ification); 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, ¬ification); 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, ¬ification); 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, ¬ification); 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