// Copyright (c) 2012 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 "content/renderer/notification_provider.h"
#include "base/strings/string_util.h"
#include "content/common/desktop_notification_messages.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
using blink::WebDocument;
using blink::WebNotification;
using blink::WebNotificationPresenter;
using blink::WebNotificationPermissionCallback;
using blink::WebSecurityOrigin;
using blink::WebString;
using blink::WebURL;
using blink::WebUserGestureIndicator;
namespace content {
NotificationProvider::NotificationProvider(RenderViewImpl* render_view)
: RenderViewObserver(render_view) {
}
NotificationProvider::~NotificationProvider() {
}
bool NotificationProvider::show(const WebNotification& notification) {
WebDocument document = render_view()->GetWebView()->mainFrame()->document();
int notification_id = manager_.RegisterNotification(notification);
ShowDesktopNotificationHostMsgParams params;
params.origin = GURL(document.securityOrigin().toString());
params.icon_url = notification.iconURL();
params.title = notification.title();
params.body = notification.body();
params.direction = notification.direction();
params.notification_id = notification_id;
params.replace_id = notification.replaceId();
return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
}
void NotificationProvider::cancel(const WebNotification& notification) {
int id;
bool id_found = manager_.GetId(notification, id);
// Won't be found if the notification has already been closed by the user.
if (id_found)
Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
}
void NotificationProvider::objectDestroyed(
const WebNotification& notification) {
int id;
bool id_found = manager_.GetId(notification, id);
// Won't be found if the notification has already been closed by the user.
if (id_found)
manager_.UnregisterNotification(id);
}
WebNotificationPresenter::Permission NotificationProvider::checkPermission(
const WebSecurityOrigin& origin) {
int permission;
Send(new DesktopNotificationHostMsg_CheckPermission(
routing_id(),
GURL(origin.toString()),
&permission));
return static_cast<WebNotificationPresenter::Permission>(permission);
}
void NotificationProvider::requestPermission(
const WebSecurityOrigin& origin,
WebNotificationPermissionCallback* callback) {
// We only request permission in response to a user gesture.
if (!WebUserGestureIndicator::isProcessingUserGesture())
return;
int id = manager_.RegisterPermissionRequest(callback);
Send(new DesktopNotificationHostMsg_RequestPermission(
routing_id(), GURL(origin.toString()), id));
}
bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostDisplay, OnDisplay);
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostError, OnError);
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClose, OnClose);
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClick, OnClick);
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PermissionRequestDone,
OnPermissionRequestComplete);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
if (message.type() == ViewMsg_Navigate::ID)
OnNavigate(); // Don't want to swallow the message.
return handled;
}
void NotificationProvider::OnDisplay(int id) {
WebNotification notification;
bool found = manager_.GetNotification(id, ¬ification);
// |found| may be false if the WebNotification went out of scope in
// the page before it was actually displayed to the user.
if (found)
notification.dispatchDisplayEvent();
}
void NotificationProvider::OnError(int id, const WebString& message) {
WebNotification notification;
bool found = manager_.GetNotification(id, ¬ification);
// |found| may be false if the WebNotification went out of scope in
// the page before the error occurred.
if (found)
notification.dispatchErrorEvent(message);
}
void NotificationProvider::OnClose(int id, bool by_user) {
WebNotification notification;
bool found = manager_.GetNotification(id, ¬ification);
// |found| may be false if the WebNotification went out of scope in
// the page before the associated toast was closed by the user.
if (found) {
notification.dispatchCloseEvent(by_user);
manager_.UnregisterNotification(id);
}
}
void NotificationProvider::OnClick(int id) {
WebNotification notification;
bool found = manager_.GetNotification(id, ¬ification);
// |found| may be false if the WebNotification went out of scope in
// the page before the associated toast was clicked on.
if (found)
notification.dispatchClickEvent();
}
void NotificationProvider::OnPermissionRequestComplete(int id) {
WebNotificationPermissionCallback* callback = manager_.GetCallback(id);
DCHECK(callback);
callback->permissionRequestComplete();
manager_.OnPermissionRequestComplete(id);
}
void NotificationProvider::OnNavigate() {
manager_.Clear();
}
} // namespace content