OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |