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

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
« no previous file with comments | « content/renderer/notification_provider.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Icon downloaders must not be re-used for multiple notifications or icons.
39 class NotificationProvider::IconDownloader : public blink::WebURLLoaderClient {
40 typedef base::Callback<void(const WebNotification&,
41 const SkBitmap&)> DownloadCompletedCallback;
42
43 public:
44 IconDownloader(const WebNotification& notification,
45 const DownloadCompletedCallback& callback);
46
47 virtual ~IconDownloader();
48
49 // Downloads the notification's image and invokes the callback with the
50 // decoded SkBitmap when the download has succeeded, or with an empty SkBitmap
51 // in case the download has failed.
52 void Start();
53
54 // Cancels the current image download. The callback will not be invoked.
55 void Cancel();
56
57 // blink::WebURLLoaderClient implementation.
58 virtual void didReceiveData(WebURLLoader* loader,
59 const char* data,
60 int data_length,
61 int encoded_data_length) OVERRIDE;
jamesr 2014/09/24 04:39:54 not lgtm. You shouldn't use OVERRIDE on cross-rep
Peter Beverloo 2014/10/01 19:34:08 Erps, that's an oversight indeed. Fixed.
62 virtual void didFinishLoading(WebURLLoader* loader,
63 double finish_time,
64 int64_t total_encoded_data_length) OVERRIDE;
65 virtual void didFail(WebURLLoader* loader, const WebURLError& error) OVERRIDE;
66
67 const WebNotification& notification() const {
68 return notification_;
69 }
70
71 private:
72 WebNotification notification_;
73 DownloadCompletedCallback callback_;
74
75 scoped_ptr<WebURLLoader> loader_;
76 bool completed_;
77
78 std::string buffer_;
jamesr 2014/09/24 04:39:54 std::string should only be for utf8 string data, n
Peter Beverloo 2014/10/01 19:34:08 There's quite some precedence for using an std::st
79
80 DISALLOW_COPY_AND_ASSIGN(IconDownloader);
81 };
82
83 NotificationProvider::IconDownloader::IconDownloader(
84 const WebNotification& notification,
85 const DownloadCompletedCallback& callback)
86 : notification_(notification),
87 callback_(callback),
88 completed_(false) {}
89
90 NotificationProvider::IconDownloader::~IconDownloader() {}
91
92 void NotificationProvider::IconDownloader::Start() {
93 DCHECK(!loader_);
94
95 WebURLRequest request(notification_.iconURL());
96 request.setRequestContext(WebURLRequest::RequestContextImage);
97
98 loader_.reset(blink::Platform::current()->createURLLoader());
99 loader_->loadAsynchronously(request, this);
28 } 100 }
29 101
30 NotificationProvider::~NotificationProvider() { 102 void NotificationProvider::IconDownloader::Cancel() {
103 DCHECK(loader_);
104
105 completed_ = true;
106 loader_->cancel();
31 } 107 }
32 108
109 void NotificationProvider::IconDownloader::didReceiveData(
110 WebURLLoader* loader,
111 const char* data,
112 int data_length,
113 int encoded_data_length) {
114 DCHECK(!completed_);
115 DCHECK(data_length > 0);
jamesr 2014/09/24 04:39:54 DCHECK_GT is slightly better
Peter Beverloo 2014/10/01 19:34:08 Done.
116
117 buffer_.append(data, data_length);
118 }
119
120 void NotificationProvider::IconDownloader::didFinishLoading(
121 WebURLLoader* loader,
122 double finish_time,
123 int64_t total_encoded_data_length) {
124 DCHECK(!completed_);
125
126 ImageDecoder decoder;
127 SkBitmap icon = decoder.Decode(
128 reinterpret_cast<const unsigned char*>(buffer_.data()), buffer_.size());
129
130 callback_.Run(notification_, icon);
131 completed_ = true;
132 }
133
134 void NotificationProvider::IconDownloader::didFail(
135 WebURLLoader* loader, const WebURLError& error) {
136 if (completed_)
137 return;
138
139 callback_.Run(notification_, SkBitmap());
140 completed_ = true;
141 }
142
143 // NotificationProvider --------------------------------------------------------
144
145 NotificationProvider::NotificationProvider(RenderFrame* render_frame)
146 : RenderFrameObserver(render_frame) {}
147
148 NotificationProvider::~NotificationProvider() {}
149
33 bool NotificationProvider::show(const WebNotification& notification) { 150 bool NotificationProvider::show(const WebNotification& notification) {
151 if (notification.iconURL().isEmpty()) {
152 DisplayNotification(notification, SkBitmap());
153 return true;
154 }
155
156 scoped_ptr<IconDownloader> downloader(
157 new IconDownloader(notification,
158 base::Bind(&NotificationProvider::DisplayNotification,
159 base::Unretained(this))));
jamesr 2014/09/24 04:39:54 what makes the base::Unretained() here safe?
Peter Beverloo 2014/10/01 19:34:08 The icon downloaders are owned in the |pending_not
160
161 downloader->Start();
162
163 pending_notifications_.push_back(downloader.release());
164 return true;
165 }
166
167 void NotificationProvider::DisplayNotification(
168 const WebNotification& notification, const SkBitmap& icon) {
34 WebDocument document = render_frame()->GetWebFrame()->document(); 169 WebDocument document = render_frame()->GetWebFrame()->document();
35 int notification_id = manager_.RegisterNotification(notification); 170 int notification_id = manager_.RegisterNotification(notification);
36 171
172 RemovePendingNotification(notification);
173
174 PendingNotifications::iterator iter = pending_notifications_.begin();
175 for (; iter != pending_notifications_.end(); ++iter) {
176 if ((*iter)->notification() != notification)
177 continue;
178
179 pending_notifications_.erase(iter);
180 break;
181 }
182
37 ShowDesktopNotificationHostMsgParams params; 183 ShowDesktopNotificationHostMsgParams params;
38 params.origin = GURL(document.securityOrigin().toString()); 184 params.origin = GURL(document.securityOrigin().toString());
39 params.icon_url = notification.iconURL(); 185 params.icon = icon;
40 params.title = notification.title(); 186 params.title = notification.title();
41 params.body = notification.body(); 187 params.body = notification.body();
42 params.direction = notification.direction(); 188 params.direction = notification.direction();
43 params.replace_id = notification.replaceId(); 189 params.replace_id = notification.replaceId();
44 return Send(new DesktopNotificationHostMsg_Show( 190
45 routing_id(), notification_id, params)); 191 Send(new DesktopNotificationHostMsg_Show(routing_id(),
192 notification_id,
193 params));
194 }
195
196 // Removes the IconDownload object from the list of pending notifications for
197 // |notification|. If the download is still in process, it will be cancelled
198 // by the blink::WebURLLoaderClient destructor.
199 void NotificationProvider::RemovePendingNotification(
200 const WebNotification& notification) {
201 PendingNotifications::iterator iter = pending_notifications_.begin();
202 for (; iter != pending_notifications_.end(); ++iter) {
203 if ((*iter)->notification() != notification)
204 continue;
205
206 pending_notifications_.erase(iter);
207 break;
208 }
46 } 209 }
47 210
48 void NotificationProvider::cancel(const WebNotification& notification) { 211 void NotificationProvider::cancel(const WebNotification& notification) {
49 int id; 212 int id;
50 bool id_found = manager_.GetId(notification, id); 213 bool id_found = manager_.GetId(notification, id);
51 // Won't be found if the notification has already been closed by the user. 214 // Won't be found if the notification has already been closed by the user,
215 // or if the notification's icon is still being requested.
52 if (id_found) 216 if (id_found)
53 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id)); 217 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
218 else
219 RemovePendingNotification(notification);
54 } 220 }
55 221
56 void NotificationProvider::objectDestroyed( 222 void NotificationProvider::objectDestroyed(
57 const WebNotification& notification) { 223 const WebNotification& notification) {
58 int id; 224 int id;
59 bool id_found = manager_.GetId(notification, id); 225 bool id_found = manager_.GetId(notification, id);
60 // Won't be found if the notification has already been closed by the user. 226 // Won't be found if the notification has already been closed by the user.
61 if (id_found) 227 if (id_found)
62 manager_.UnregisterNotification(id); 228 manager_.UnregisterNotification(id);
229 else
230 RemovePendingNotification(notification);
63 } 231 }
64 232
65 WebNotificationPresenter::Permission NotificationProvider::checkPermission( 233 WebNotificationPresenter::Permission NotificationProvider::checkPermission(
66 const WebSecurityOrigin& origin) { 234 const WebSecurityOrigin& origin) {
67 int permission = WebNotificationPresenter::PermissionNotAllowed; 235 int permission = WebNotificationPresenter::PermissionNotAllowed;
68 Send(new DesktopNotificationHostMsg_CheckPermission( 236 Send(new DesktopNotificationHostMsg_CheckPermission(
69 routing_id(), 237 routing_id(),
70 GURL(origin.toString()), 238 GURL(origin.toString()),
71 &permission)); 239 &permission));
72 return static_cast<WebNotificationPresenter::Permission>(permission); 240 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. 292 // the page before the associated toast was clicked on.
125 if (found) 293 if (found)
126 notification.dispatchClickEvent(); 294 notification.dispatchClickEvent();
127 } 295 }
128 296
129 void NotificationProvider::OnNavigate() { 297 void NotificationProvider::OnNavigate() {
130 manager_.Clear(); 298 manager_.Clear();
131 } 299 }
132 300
133 } // namespace content 301 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/notification_provider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698