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

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: Fix the tests Created 6 years, 2 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 <vector>
8
7 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "content/child/image_decoder.h"
8 #include "content/common/desktop_notification_messages.h" 11 #include "content/common/desktop_notification_messages.h"
9 #include "content/common/frame_messages.h" 12 #include "content/common/frame_messages.h"
10 #include "content/renderer/render_frame_impl.h" 13 #include "content/renderer/render_frame_impl.h"
14 #include "third_party/WebKit/public/platform/Platform.h"
11 #include "third_party/WebKit/public/platform/WebURL.h" 15 #include "third_party/WebKit/public/platform/WebURL.h"
16 #include "third_party/WebKit/public/platform/WebURLLoader.h"
17 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
12 #include "third_party/WebKit/public/web/WebDocument.h" 18 #include "third_party/WebKit/public/web/WebDocument.h"
13 #include "third_party/WebKit/public/web/WebLocalFrame.h" 19 #include "third_party/WebKit/public/web/WebLocalFrame.h"
14 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 20 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
15 22
16 using blink::WebDocument; 23 using blink::WebDocument;
17 using blink::WebNotification; 24 using blink::WebNotification;
18 using blink::WebNotificationPresenter; 25 using blink::WebNotificationPresenter;
19 using blink::WebSecurityOrigin; 26 using blink::WebSecurityOrigin;
20 using blink::WebString; 27 using blink::WebString;
21 using blink::WebURL; 28 using blink::WebURL;
29 using blink::WebURLError;
30 using blink::WebURLLoader;
31 using blink::WebURLRequest;
22 using blink::WebUserGestureIndicator; 32 using blink::WebUserGestureIndicator;
23 33
24 namespace content { 34 namespace content {
25 35
26 NotificationProvider::NotificationProvider(RenderFrame* render_frame) 36 // NotificationProvider::IconDownloader ----------------------------------------
27 : RenderFrameObserver(render_frame) { 37
38 // Downloads the icon associated with a notification and decodes the received
39 // image. This must be completed before notifications are shown to the user.
40 // Icon downloaders must not be re-used for multiple notifications or icons.
41 class NotificationProvider::IconDownloader : public blink::WebURLLoaderClient {
jamesr 2014/10/06 22:56:24 put this in its own .h/.cc file. It's too much co
Peter Beverloo 2014/10/13 19:09:30 Moved to its own file. I've filed http://crbug.com
42 typedef base::Callback<void(int, const SkBitmap&)> DownloadCompletedCallback;
43
44 public:
45 IconDownloader(int notification_id,
46 const DownloadCompletedCallback& callback);
47
48 virtual ~IconDownloader();
49
50 // Downloads the notification's image and invokes the callback with the
51 // decoded SkBitmap when the download has succeeded, or with an empty SkBitmap
52 // in case the download has failed.
53 void Start(const WebURL& icon_url);
54
55 // Cancels the current image download. The callback will not be invoked.
56 void Cancel();
57
58 // blink::WebURLLoaderClient implementation.
59 virtual void didReceiveData(WebURLLoader* loader,
60 const char* data,
61 int data_length,
62 int encoded_data_length);
63 virtual void didFinishLoading(WebURLLoader* loader,
64 double finish_time,
65 int64_t total_encoded_data_length);
66 virtual void didFail(WebURLLoader* loader, const WebURLError& error);
67
68 int notification_id() const {
69 return notification_id_;
70 }
71
72 private:
73 int notification_id_;
74 DownloadCompletedCallback callback_;
75
76 scoped_ptr<WebURLLoader> loader_;
77 bool completed_;
78
79 std::vector<uint8_t> buffer_;
80
81 DISALLOW_COPY_AND_ASSIGN(IconDownloader);
82 };
83
84 NotificationProvider::IconDownloader::IconDownloader(
85 int notification_id,
86 const DownloadCompletedCallback& callback)
87 : notification_id_(notification_id),
88 callback_(callback),
89 completed_(false) {}
90
91 NotificationProvider::IconDownloader::~IconDownloader() {}
92
93 void NotificationProvider::IconDownloader::Start(const WebURL& icon_url) {
94 DCHECK(!loader_);
95
96 WebURLRequest request(icon_url);
97 request.setRequestContext(WebURLRequest::RequestContextImage);
98
99 loader_.reset(blink::Platform::current()->createURLLoader());
100 loader_->loadAsynchronously(request, this);
28 } 101 }
29 102
30 NotificationProvider::~NotificationProvider() { 103 void NotificationProvider::IconDownloader::Cancel() {
104 DCHECK(loader_);
105
106 completed_ = true;
107 loader_->cancel();
31 } 108 }
32 109
110 void NotificationProvider::IconDownloader::didReceiveData(
111 WebURLLoader* loader,
112 const char* data,
113 int data_length,
114 int encoded_data_length) {
115 DCHECK(!completed_);
116 DCHECK_GT(data_length, 0);
117
118 buffer_.insert(buffer_.end(), data, data + data_length);
119 }
120
121 void NotificationProvider::IconDownloader::didFinishLoading(
122 WebURLLoader* loader,
123 double finish_time,
124 int64_t total_encoded_data_length) {
125 DCHECK(!completed_);
126
127 SkBitmap icon;
128 if (!buffer_.empty()) {
129 ImageDecoder decoder;
130 icon = decoder.Decode(&buffer_[0], buffer_.size());
131 }
132
133 completed_ = true;
134 callback_.Run(notification_id_, icon);
135 }
136
137 void NotificationProvider::IconDownloader::didFail(
138 WebURLLoader* loader, const WebURLError& error) {
139 if (completed_)
140 return;
141
142 completed_ = true;
143 callback_.Run(notification_id_, SkBitmap());
144 }
145
146 // NotificationProvider --------------------------------------------------------
147
148 NotificationProvider::NotificationProvider(RenderFrame* render_frame)
149 : RenderFrameObserver(render_frame) {}
150
151 NotificationProvider::~NotificationProvider() {}
152
33 bool NotificationProvider::show(const WebNotification& notification) { 153 bool NotificationProvider::show(const WebNotification& notification) {
154 int notification_id = manager_.RegisterNotification(notification);
155 if (notification.iconURL().isEmpty()) {
156 DisplayNotification(notification_id, SkBitmap());
157 return true;
158 }
159
160 scoped_ptr<IconDownloader> downloader(
161 new IconDownloader(notification_id,
162 base::Bind(&NotificationProvider::DisplayNotification,
163 base::Unretained(this))));
164
165 downloader->Start(notification.iconURL());
166
167 pending_notifications_.push_back(downloader.release());
168 return true;
169 }
170
171 void NotificationProvider::DisplayNotification(int notification_id,
172 const SkBitmap& icon) {
34 WebDocument document = render_frame()->GetWebFrame()->document(); 173 WebDocument document = render_frame()->GetWebFrame()->document();
35 int notification_id = manager_.RegisterNotification(notification); 174 WebNotification notification;
175
176 bool found = manager_.GetNotification(notification_id, &notification);
177 CHECK(found);
jamesr 2014/10/06 22:56:24 what does failing this CHECK mean? is there a secu
Peter Beverloo 2014/10/13 19:09:30 It means that display is being requested for a non
178
179 RemovePendingNotification(notification_id);
36 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 bool NotificationProvider::RemovePendingNotification(int notification_id) {
195 PendingNotifications::iterator iter = pending_notifications_.begin();
196 for (; iter != pending_notifications_.end(); ++iter) {
jamesr 2014/10/06 22:56:24 should probably be a const_iterator since you aren
Peter Beverloo 2014/10/13 19:09:30 pending_notifications_ is a ScopedVector, so erase
197 if ((*iter)->notification_id() != notification_id)
198 continue;
199
200 pending_notifications_.erase(iter);
201 return true;
202 }
203
204 return false;
46 } 205 }
47 206
48 void NotificationProvider::cancel(const WebNotification& notification) { 207 void NotificationProvider::cancel(const WebNotification& notification) {
49 int id; 208 int id;
50 bool id_found = manager_.GetId(notification, id); 209 bool id_found = manager_.GetId(notification, id);
51 // Won't be found if the notification has already been closed by the user. 210 // Won't be found if the notification has already been closed by the user,
52 if (id_found) 211 // or if the notification's icon is still being requested.
212 if (id_found && !RemovePendingNotification(id))
53 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id)); 213 Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
54 } 214 }
55 215
56 void NotificationProvider::objectDestroyed( 216 void NotificationProvider::objectDestroyed(
57 const WebNotification& notification) { 217 const WebNotification& notification) {
58 int id; 218 int id;
59 bool id_found = manager_.GetId(notification, id); 219 bool id_found = manager_.GetId(notification, id);
60 // Won't be found if the notification has already been closed by the user. 220 // Won't be found if the notification has already been closed by the user.
61 if (id_found) 221 if (id_found) {
222 RemovePendingNotification(id);
62 manager_.UnregisterNotification(id); 223 manager_.UnregisterNotification(id);
224 }
63 } 225 }
64 226
65 WebNotificationPresenter::Permission NotificationProvider::checkPermission( 227 WebNotificationPresenter::Permission NotificationProvider::checkPermission(
66 const WebSecurityOrigin& origin) { 228 const WebSecurityOrigin& origin) {
67 int permission = WebNotificationPresenter::PermissionNotAllowed; 229 int permission = WebNotificationPresenter::PermissionNotAllowed;
68 Send(new DesktopNotificationHostMsg_CheckPermission( 230 Send(new DesktopNotificationHostMsg_CheckPermission(
69 routing_id(), 231 routing_id(),
70 GURL(origin.toString()), 232 GURL(origin.toString()),
71 &permission)); 233 &permission));
72 return static_cast<WebNotificationPresenter::Permission>(permission); 234 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. 286 // the page before the associated toast was clicked on.
125 if (found) 287 if (found)
126 notification.dispatchClickEvent(); 288 notification.dispatchClickEvent();
127 } 289 }
128 290
129 void NotificationProvider::OnNavigate() { 291 void NotificationProvider::OnNavigate() {
130 manager_.Clear(); 292 manager_.Clear();
131 } 293 }
132 294
133 } // namespace content 295 } // 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