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/frame_messages.h"
10#include "content/renderer/render_frame_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/WebLocalFrame.h"
14#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
15
16using blink::WebDocument;
17using blink::WebNotification;
18using blink::WebNotificationPresenter;
19using blink::WebSecurityOrigin;
20using blink::WebString;
21using blink::WebURL;
22using blink::WebUserGestureIndicator;
23
24namespace content {
25
26NotificationProvider::NotificationProvider(RenderFrame* render_frame)
27    : RenderFrameObserver(render_frame) {
28}
29
30NotificationProvider::~NotificationProvider() {
31}
32
33bool NotificationProvider::show(const WebNotification& notification) {
34  WebDocument document = render_frame()->GetWebFrame()->document();
35  int notification_id = manager_.RegisterNotification(notification);
36
37  ShowDesktopNotificationHostMsgParams params;
38  params.origin = GURL(document.securityOrigin().toString());
39  params.icon_url = notification.iconURL();
40  params.title = notification.title();
41  params.body = notification.body();
42  params.direction = notification.direction();
43  params.replace_id = notification.replaceId();
44  return Send(new DesktopNotificationHostMsg_Show(
45      routing_id(), notification_id, params));
46}
47
48void NotificationProvider::cancel(const WebNotification& notification) {
49  int id;
50  bool id_found = manager_.GetId(notification, id);
51  // Won't be found if the notification has already been closed by the user.
52  if (id_found)
53    Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
54}
55
56void NotificationProvider::objectDestroyed(
57    const WebNotification& notification) {
58  int id;
59  bool id_found = manager_.GetId(notification, id);
60  // Won't be found if the notification has already been closed by the user.
61  if (id_found)
62    manager_.UnregisterNotification(id);
63}
64
65WebNotificationPresenter::Permission NotificationProvider::checkPermission(
66    const WebSecurityOrigin& origin) {
67  int permission = WebNotificationPresenter::PermissionNotAllowed;
68  Send(new DesktopNotificationHostMsg_CheckPermission(
69          routing_id(),
70          GURL(origin.toString()),
71          &permission));
72  return static_cast<WebNotificationPresenter::Permission>(permission);
73}
74
75bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
76  bool handled = true;
77  IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
78    IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostDisplay, OnDisplay);
79    IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostError, OnError);
80    IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClose, OnClose);
81    IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClick, OnClick);
82    IPC_MESSAGE_UNHANDLED(handled = false)
83  IPC_END_MESSAGE_MAP()
84
85  if (message.type() == FrameMsg_Navigate::ID)
86    OnNavigate();  // Don't want to swallow the message.
87
88  return handled;
89}
90
91void NotificationProvider::OnDisplay(int id) {
92  WebNotification notification;
93  bool found = manager_.GetNotification(id, &notification);
94  // |found| may be false if the WebNotification went out of scope in
95  // the page before it was actually displayed to the user.
96  if (found)
97    notification.dispatchDisplayEvent();
98}
99
100void NotificationProvider::OnError(int id) {
101  WebNotification notification;
102  bool found = manager_.GetNotification(id, &notification);
103  // |found| may be false if the WebNotification went out of scope in
104  // the page before the error occurred.
105  if (found)
106    notification.dispatchErrorEvent(WebString());
107}
108
109void NotificationProvider::OnClose(int id, bool by_user) {
110  WebNotification notification;
111  bool found = manager_.GetNotification(id, &notification);
112  // |found| may be false if the WebNotification went out of scope in
113  // the page before the associated toast was closed by the user.
114  if (found) {
115    notification.dispatchCloseEvent(by_user);
116    manager_.UnregisterNotification(id);
117  }
118}
119
120void NotificationProvider::OnClick(int id) {
121  WebNotification notification;
122  bool found = manager_.GetNotification(id, &notification);
123  // |found| may be false if the WebNotification went out of scope in
124  // the page before the associated toast was clicked on.
125  if (found)
126    notification.dispatchClickEvent();
127}
128
129void NotificationProvider::OnNavigate() {
130  manager_.Clear();
131}
132
133}  // namespace content
134