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.
5 #include "content/renderer/notification_provider.h"
9 #include "base/strings/string_util.h"
10 #include "content/common/desktop_notification_messages.h"
11 #include "content/common/frame_messages.h"
12 #include "content/renderer/notification_icon_loader.h"
13 #include "content/renderer/render_frame_impl.h"
14 #include "third_party/WebKit/public/web/WebDocument.h"
15 #include "third_party/WebKit/public/web/WebLocalFrame.h"
17 using blink::WebDocument
;
18 using blink::WebNotification
;
19 using blink::WebNotificationPresenter
;
20 using blink::WebSecurityOrigin
;
21 using blink::WebString
;
25 NotificationProvider::NotificationProvider(RenderFrame
* render_frame
)
26 : RenderFrameObserver(render_frame
) {}
28 NotificationProvider::~NotificationProvider() {}
30 bool NotificationProvider::show(const WebNotification
& notification
) {
31 int notification_id
= manager_
.RegisterNotification(notification
);
32 if (notification
.iconURL().isEmpty()) {
33 DisplayNotification(notification_id
, SkBitmap());
37 scoped_ptr
<NotificationIconLoader
> loader(
38 new NotificationIconLoader(
40 base::Bind(&NotificationProvider::DisplayNotification
,
41 base::Unretained(this))));
43 loader
->Start(notification
.iconURL());
45 pending_notifications_
.push_back(loader
.release());
49 void NotificationProvider::DisplayNotification(int notification_id
,
50 const SkBitmap
& icon
) {
51 WebDocument document
= render_frame()->GetWebFrame()->document();
52 WebNotification notification
;
54 if (!manager_
.GetNotification(notification_id
, ¬ification
)) {
59 RemovePendingNotification(notification_id
);
61 ShowDesktopNotificationHostMsgParams params
;
62 params
.origin
= GURL(document
.securityOrigin().toString());
64 params
.title
= notification
.title();
65 params
.body
= notification
.body();
66 params
.direction
= notification
.direction();
67 params
.replace_id
= notification
.replaceId();
69 Send(new DesktopNotificationHostMsg_Show(routing_id(),
74 bool NotificationProvider::RemovePendingNotification(int notification_id
) {
75 PendingNotifications::iterator iter
= pending_notifications_
.begin();
76 for (; iter
!= pending_notifications_
.end(); ++iter
) {
77 if ((*iter
)->notification_id() != notification_id
)
80 pending_notifications_
.erase(iter
);
87 void NotificationProvider::cancel(const WebNotification
& notification
) {
89 bool id_found
= manager_
.GetId(notification
, id
);
90 // Won't be found if the notification has already been closed by the user,
91 // or if the notification's icon is still being requested.
92 if (id_found
&& !RemovePendingNotification(id
))
93 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id
));
96 void NotificationProvider::objectDestroyed(
97 const WebNotification
& notification
) {
99 bool id_found
= manager_
.GetId(notification
, id
);
100 // Won't be found if the notification has already been closed by the user.
102 RemovePendingNotification(id
);
103 manager_
.UnregisterNotification(id
);
107 WebNotificationPresenter::Permission
NotificationProvider::checkPermission(
108 const WebSecurityOrigin
& origin
) {
109 int permission
= WebNotificationPresenter::PermissionNotAllowed
;
110 Send(new DesktopNotificationHostMsg_CheckPermission(
112 GURL(origin
.toString()),
114 return static_cast<WebNotificationPresenter::Permission
>(permission
);
117 bool NotificationProvider::OnMessageReceived(const IPC::Message
& message
) {
119 IPC_BEGIN_MESSAGE_MAP(NotificationProvider
, message
)
120 IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostDisplay
, OnDisplay
);
121 IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostError
, OnError
);
122 IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClose
, OnClose
);
123 IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClick
, OnClick
);
124 IPC_MESSAGE_UNHANDLED(handled
= false)
125 IPC_END_MESSAGE_MAP()
127 if (message
.type() == FrameMsg_Navigate::ID
)
128 OnNavigate(); // Don't want to swallow the message.
133 void NotificationProvider::OnDisplay(int id
) {
134 WebNotification notification
;
135 bool found
= manager_
.GetNotification(id
, ¬ification
);
136 // |found| may be false if the WebNotification went out of scope in
137 // the page before it was actually displayed to the user.
139 notification
.dispatchDisplayEvent();
142 void NotificationProvider::OnError(int id
) {
143 WebNotification notification
;
144 bool found
= manager_
.GetNotification(id
, ¬ification
);
145 // |found| may be false if the WebNotification went out of scope in
146 // the page before the error occurred.
148 notification
.dispatchErrorEvent(WebString());
151 void NotificationProvider::OnClose(int id
, bool by_user
) {
152 WebNotification notification
;
153 bool found
= manager_
.GetNotification(id
, ¬ification
);
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.
157 notification
.dispatchCloseEvent(by_user
);
158 manager_
.UnregisterNotification(id
);
162 void NotificationProvider::OnClick(int id
) {
163 WebNotification notification
;
164 bool found
= manager_
.GetNotification(id
, ¬ification
);
165 // |found| may be false if the WebNotification went out of scope in
166 // the page before the associated toast was clicked on.
168 notification
.dispatchClickEvent();
171 void NotificationProvider::OnNavigate() {
175 } // namespace content