Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: content/renderer/notification_provider.cc

Issue 554213003: Request the icon of a Web Notification in the renderer process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/notification_provider.h" 5 #include "content/renderer/notification_provider.h"
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "content/child/image_decoder.h"
8 #include "content/common/desktop_notification_messages.h" 9 #include "content/common/desktop_notification_messages.h"
9 #include "content/common/frame_messages.h" 10 #include "content/common/frame_messages.h"
10 #include "content/renderer/render_frame_impl.h" 11 #include "content/renderer/render_frame_impl.h"
12 #include "third_party/WebKit/public/platform/Platform.h"
11 #include "third_party/WebKit/public/platform/WebURL.h" 13 #include "third_party/WebKit/public/platform/WebURL.h"
14 #include "third_party/WebKit/public/platform/WebURLLoader.h"
15 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
12 #include "third_party/WebKit/public/web/WebDocument.h" 16 #include "third_party/WebKit/public/web/WebDocument.h"
13 #include "third_party/WebKit/public/web/WebLocalFrame.h" 17 #include "third_party/WebKit/public/web/WebLocalFrame.h"
14 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 18 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
15 20
16 using blink::WebDocument; 21 using blink::WebDocument;
17 using blink::WebNotification; 22 using blink::WebNotification;
18 using blink::WebNotificationPresenter; 23 using blink::WebNotificationPresenter;
19 using blink::WebSecurityOrigin; 24 using blink::WebSecurityOrigin;
20 using blink::WebString; 25 using blink::WebString;
21 using blink::WebURL; 26 using blink::WebURL;
27 using blink::WebURLError;
28 using blink::WebURLLoader;
29 using blink::WebURLRequest;
22 using blink::WebUserGestureIndicator; 30 using blink::WebUserGestureIndicator;
23 31
24 namespace content { 32 namespace content {
25 33
26 NotificationProvider::NotificationProvider(RenderFrame* render_frame) 34 // NotificationProvider::IconDownloader ----------------------------------------
27 : RenderFrameObserver(render_frame) { 35
36 // Downloads the icon associated with a notification and decodes the received
37 // image. This must be completed before notifications are shown to the user.
38 class NotificationProvider::IconDownloader : public blink::WebURLLoaderClient {
39 typedef base::Callback<void(const WebNotification&,
40 const SkBitmap&)> DownloadCompletedCallback;
41
42 public:
43 IconDownloader(const WebNotification& notification,
44 const DownloadCompletedCallback& callback);
45
46 virtual ~IconDownloader();
47
48 // Downloads |image_url| and invokes |callback| with the decoded SkBitmap when
Mike West 2014/09/18 19:48:42 There's not an 'image_url' parameter anywhere. Per
Peter Beverloo 2014/09/19 14:15:48 Done.
49 // the download has succeeded, or invokes |callback| with an empty SkBitmap
50 // in case the download has failed.
51 void Start();
52
53 // Cancels the current image download. The callback will not be invoked.
54 void Cancel();
55
56 // blink::WebURLLoaderClient implementation.
57 virtual void didReceiveData(WebURLLoader* loader,
58 const char* data,
59 int data_length,
60 int encoded_data_length) OVERRIDE;
61 virtual void didFinishLoading(WebURLLoader* loader,
62 double finish_time,
63 int64_t total_encoded_data_length) OVERRIDE;
64 virtual void didFail(WebURLLoader* loader, const WebURLError& error) OVERRIDE;
65
66 const WebNotification& notification() const {
67 return notification_;
68 }
69
70 private:
71 WebNotification notification_;
72 DownloadCompletedCallback callback_;
73
74 scoped_ptr<WebURLLoader> loader_;
75 bool completed_;
76
77 std::string buffer_;
78
79 DISALLOW_COPY_AND_ASSIGN(IconDownloader);
80 };
81
82 NotificationProvider::IconDownloader::IconDownloader(
83 const WebNotification& notification,
84 const DownloadCompletedCallback& callback)
85 : notification_(notification),
86 callback_(callback),
87 completed_(false) {}
88
89 NotificationProvider::IconDownloader::~IconDownloader() {}
90
91 void NotificationProvider::IconDownloader::Start() {
92 DCHECK(!loader_);
93
94 WebURLRequest request(notification_.iconURL());
Mike West 2014/09/18 19:48:42 Please set the request's context. It looks like it
Peter Beverloo 2014/09/19 14:15:48 Done.
95
96 loader_.reset(blink::Platform::current()->createURLLoader());
Mike West 2014/09/18 19:48:42 Should this be an AssociatedURLLoader? I'd imagine
Peter Beverloo 2014/09/19 14:15:48 Notifications won't be associated with a RenderFra
Mike West 2014/09/19 15:00:28 Hrm. That's a bit surprising. I thought notificati
97 loader_->loadAsynchronously(request, this);
28 } 98 }
29 99
30 NotificationProvider::~NotificationProvider() { 100 void NotificationProvider::IconDownloader::Cancel() {
101 DCHECK(loader_);
102
103 completed_ = true;
104 loader_->cancel();
Mike West 2014/09/18 19:48:42 You don't do anything with the contents of |buffer
Peter Beverloo 2014/09/19 14:15:48 buffer_ is unlikely to contain sensitive data, and
Mike West 2014/09/19 15:00:28 My worry was that the load could cancel, get resta
31 } 105 }
32 106
107 void NotificationProvider::IconDownloader::didReceiveData(
108 WebURLLoader* loader,
109 const char* data,
110 int data_length,
111 int encoded_data_length) {
112 DCHECK(!completed_);
113 DCHECK(data_length > 0);
114
115 buffer_.append(data, data_length);
116 }
117
118 void NotificationProvider::IconDownloader::didFinishLoading(
119 WebURLLoader* loader,
120 double finish_time,
121 int64_t total_encoded_data_length) {
122 DCHECK(!completed_);
123
124 ImageDecoder decoder;
125 SkBitmap icon = decoder.Decode(
126 reinterpret_cast<const unsigned char*>(buffer_.data()), buffer_.size());
127
128 callback_.Run(notification_, icon);
129 completed_ = true;
130 }
131
132 void NotificationProvider::IconDownloader::didFail(
133 WebURLLoader* loader, const WebURLError& error) {
134 if (completed_)
dewittj 2014/09/18 17:46:49 Is this the correct failure behavior? In extensio
Peter Beverloo 2014/09/19 14:15:48 The Web Notification API doesn't imply restriction
135 return;
136
137 callback_.Run(notification_, SkBitmap());
138 completed_ = true;
Mike West 2014/09/18 19:48:42 Again, it seems like you should do something with
Peter Beverloo 2014/09/19 14:15:48 Done.
139 }
140
141 // NotificationProvider --------------------------------------------------------
142
143 NotificationProvider::NotificationProvider(RenderFrame* render_frame)
144 : RenderFrameObserver(render_frame) {}
145
146 NotificationProvider::~NotificationProvider() {}
147
33 bool NotificationProvider::show(const WebNotification& notification) { 148 bool NotificationProvider::show(const WebNotification& notification) {
149 if (notification.iconURL().isEmpty()) {
150 DisplayNotification(notification, SkBitmap());
151 return true;
152 }
153
154 scoped_ptr<IconDownloader> downloader(
155 new IconDownloader(notification,
156 base::Bind(&NotificationProvider::DisplayNotification,
157 base::Unretained(this))));
158
159 downloader->Start();
160
161 pending_notifications_.push_back(downloader.release());
162 return true;
163 }
164
165 void NotificationProvider::DisplayNotification(
166 const WebNotification& notification, const SkBitmap& icon) {
34 WebDocument document = render_frame()->GetWebFrame()->document(); 167 WebDocument document = render_frame()->GetWebFrame()->document();
35 int notification_id = manager_.RegisterNotification(notification); 168 int notification_id = manager_.RegisterNotification(notification);
36 169
170 RemovePendingNotification(notification);
171
172 PendingNotifications::iterator iter = pending_notifications_.begin();
173 for (; iter != pending_notifications_.end(); ++iter) {
174 if ((*iter)->notification() != notification)
175 continue;
176
177 pending_notifications_.erase(iter);
178 break;
179 }
180
37 ShowDesktopNotificationHostMsgParams params; 181 ShowDesktopNotificationHostMsgParams params;
38 params.origin = GURL(document.securityOrigin().toString()); 182 params.origin = GURL(document.securityOrigin().toString());
39 params.icon_url = notification.iconURL(); 183 params.icon = icon;
40 params.title = notification.title(); 184 params.title = notification.title();
41 params.body = notification.body(); 185 params.body = notification.body();
42 params.direction = notification.direction(); 186 params.direction = notification.direction();
43 params.replace_id = notification.replaceId(); 187 params.replace_id = notification.replaceId();
44 return Send(new DesktopNotificationHostMsg_Show( 188
45 routing_id(), notification_id, params)); 189 Send(new DesktopNotificationHostMsg_Show(routing_id(),
190 notification_id,
191 params));
192 }
193
194 // Removes the IconDownload object from the list of pending notifications for
195 // |notification|. If the download is still in process, it will be cancelled
196 // by the blink::WebURLLoaderClient destructor.
197 void NotificationProvider::RemovePendingNotification(
198 const WebNotification& notification) {
199 PendingNotifications::iterator iter = pending_notifications_.begin();
200 for (; iter != pending_notifications_.end(); ++iter) {
201 if ((*iter)->notification() != notification)
202 continue;
203
204 pending_notifications_.erase(iter);
205 break;
206 }
46 } 207 }
47 208
48 void NotificationProvider::cancel(const WebNotification& notification) { 209 void NotificationProvider::cancel(const WebNotification& notification) {
49 int id; 210 int id;
50 bool id_found = manager_.GetId(notification, id); 211 bool id_found = manager_.GetId(notification, id);
51 // Won't be found if the notification has already been closed by the user. 212 // Won't be found if the notification has already been closed by the user,
213 // or if the notification's icon is still being requested.
52 if (id_found) 214 if (id_found)
53 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id)); 215 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
216 else
217 RemovePendingNotification(notification);
54 } 218 }
55 219
56 void NotificationProvider::objectDestroyed( 220 void NotificationProvider::objectDestroyed(
57 const WebNotification& notification) { 221 const WebNotification& notification) {
58 int id; 222 int id;
59 bool id_found = manager_.GetId(notification, id); 223 bool id_found = manager_.GetId(notification, id);
60 // Won't be found if the notification has already been closed by the user. 224 // Won't be found if the notification has already been closed by the user.
61 if (id_found) 225 if (id_found)
62 manager_.UnregisterNotification(id); 226 manager_.UnregisterNotification(id);
227 else
228 RemovePendingNotification(notification);
dewittj 2014/09/18 17:46:49 Is this correct? (I'm unfamiliar with blink code)
Peter Beverloo 2014/09/19 14:15:48 We'd only cancel showing the notification if the i
63 } 229 }
64 230
65 WebNotificationPresenter::Permission NotificationProvider::checkPermission( 231 WebNotificationPresenter::Permission NotificationProvider::checkPermission(
66 const WebSecurityOrigin& origin) { 232 const WebSecurityOrigin& origin) {
67 int permission = WebNotificationPresenter::PermissionNotAllowed; 233 int permission = WebNotificationPresenter::PermissionNotAllowed;
68 Send(new DesktopNotificationHostMsg_CheckPermission( 234 Send(new DesktopNotificationHostMsg_CheckPermission(
69 routing_id(), 235 routing_id(),
70 GURL(origin.toString()), 236 GURL(origin.toString()),
71 &permission)); 237 &permission));
72 return static_cast<WebNotificationPresenter::Permission>(permission); 238 return static_cast<WebNotificationPresenter::Permission>(permission);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 // the page before the associated toast was clicked on. 290 // the page before the associated toast was clicked on.
125 if (found) 291 if (found)
126 notification.dispatchClickEvent(); 292 notification.dispatchClickEvent();
127 } 293 }
128 294
129 void NotificationProvider::OnNavigate() { 295 void NotificationProvider::OnNavigate() {
130 manager_.Clear(); 296 manager_.Clear();
131 } 297 }
132 298
133 } // namespace content 299 } // namespace content
OLDNEW
« content/renderer/notification_provider.h ('K') | « content/renderer/notification_provider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698