OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/child/push_messaging/push_provider.h" | 5 #include "content/child/push_messaging/push_provider.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
| 10 #include "base/bind_helpers.h" |
10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
11 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
12 #include "base/stl_util.h" | |
13 #include "base/threading/thread_local.h" | 13 #include "base/threading/thread_local.h" |
14 #include "content/child/push_messaging/push_dispatcher.h" | 14 #include "content/child/child_thread_impl.h" |
15 #include "content/child/service_worker/web_service_worker_registration_impl.h" | 15 #include "content/child/service_worker/web_service_worker_registration_impl.h" |
16 #include "content/child/thread_safe_sender.h" | |
17 #include "content/common/push_messaging_messages.h" | |
18 #include "content/public/common/child_process_host.h" | 16 #include "content/public/common/child_process_host.h" |
19 #include "content/public/common/push_subscription_options.h" | 17 #include "content/public/common/push_subscription_options.h" |
| 18 #include "services/service_manager/public/cpp/interface_provider.h" |
20 #include "third_party/WebKit/public/platform/WebString.h" | 19 #include "third_party/WebKit/public/platform/WebString.h" |
21 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
ription.h" | 20 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
ription.h" |
22 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
riptionOptions.h" | 21 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushSubsc
riptionOptions.h" |
23 | 22 |
24 namespace content { | 23 namespace content { |
25 namespace { | 24 namespace { |
26 | 25 |
27 int CurrentWorkerId() { | 26 int CurrentWorkerId() { |
28 return WorkerThread::GetCurrentId(); | 27 return WorkerThread::GetCurrentId(); |
29 } | 28 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 break; | 65 break; |
67 } | 66 } |
68 return blink::WebPushError( | 67 return blink::WebPushError( |
69 error_type, | 68 error_type, |
70 blink::WebString::fromUTF8(PushRegistrationStatusToString(status))); | 69 blink::WebString::fromUTF8(PushRegistrationStatusToString(status))); |
71 } | 70 } |
72 | 71 |
73 static base::LazyInstance<base::ThreadLocalPointer<PushProvider>>::Leaky | 72 static base::LazyInstance<base::ThreadLocalPointer<PushProvider>>::Leaky |
74 g_push_provider_tls = LAZY_INSTANCE_INITIALIZER; | 73 g_push_provider_tls = LAZY_INSTANCE_INITIALIZER; |
75 | 74 |
76 PushProvider::PushProvider(ThreadSafeSender* thread_safe_sender, | 75 PushProvider::PushProvider(const scoped_refptr<base::SingleThreadTaskRunner>& |
77 PushDispatcher* push_dispatcher) | 76 main_thread_task_runner) { |
78 : thread_safe_sender_(thread_safe_sender), | 77 DCHECK(main_thread_task_runner); |
79 push_dispatcher_(push_dispatcher) { | 78 |
| 79 auto request = mojo::MakeRequest(&push_messaging_manager_); |
| 80 if (!main_thread_task_runner->BelongsToCurrentThread()) { |
| 81 main_thread_task_runner->PostTask( |
| 82 FROM_HERE, |
| 83 base::Bind(&PushProvider::GetInterface, base::Passed(&request))); |
| 84 } else { |
| 85 GetInterface(std::move(request)); |
| 86 } |
80 g_push_provider_tls.Pointer()->Set(this); | 87 g_push_provider_tls.Pointer()->Set(this); |
81 } | 88 } |
82 | 89 |
83 PushProvider::~PushProvider() { | 90 PushProvider::~PushProvider() { |
84 g_push_provider_tls.Pointer()->Set(nullptr); | 91 g_push_provider_tls.Pointer()->Set(nullptr); |
85 } | 92 } |
86 | 93 |
87 PushProvider* PushProvider::ThreadSpecificInstance( | 94 PushProvider* PushProvider::ThreadSpecificInstance( |
88 ThreadSafeSender* thread_safe_sender, | 95 const scoped_refptr<base::SingleThreadTaskRunner>& |
89 PushDispatcher* push_dispatcher) { | 96 main_thread_task_runner) { |
90 if (g_push_provider_tls.Pointer()->Get()) | 97 if (g_push_provider_tls.Pointer()->Get()) |
91 return g_push_provider_tls.Pointer()->Get(); | 98 return g_push_provider_tls.Pointer()->Get(); |
92 | 99 |
93 PushProvider* provider = | 100 PushProvider* provider = new PushProvider(main_thread_task_runner); |
94 new PushProvider(thread_safe_sender, push_dispatcher); | |
95 if (CurrentWorkerId()) | 101 if (CurrentWorkerId()) |
96 WorkerThread::AddObserver(provider); | 102 WorkerThread::AddObserver(provider); |
97 return provider; | 103 return provider; |
98 } | 104 } |
99 | 105 |
| 106 // static |
| 107 void PushProvider::GetInterface(mojom::PushMessagingRequest request) { |
| 108 if (ChildThreadImpl::current()) { |
| 109 ChildThreadImpl::current()->GetRemoteInterfaces()->GetInterface( |
| 110 std::move(request)); |
| 111 } |
| 112 } |
| 113 |
100 void PushProvider::WillStopCurrentWorkerThread() { | 114 void PushProvider::WillStopCurrentWorkerThread() { |
101 delete this; | 115 delete this; |
102 } | 116 } |
103 | 117 |
104 void PushProvider::subscribe( | 118 void PushProvider::subscribe( |
105 blink::WebServiceWorkerRegistration* service_worker_registration, | 119 blink::WebServiceWorkerRegistration* service_worker_registration, |
106 const blink::WebPushSubscriptionOptions& options, | 120 const blink::WebPushSubscriptionOptions& options, |
107 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { | 121 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { |
108 DCHECK(service_worker_registration); | 122 DCHECK(service_worker_registration); |
109 DCHECK(callbacks); | 123 DCHECK(callbacks); |
110 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | 124 |
111 subscription_callbacks_.AddWithID(std::move(callbacks), request_id); | |
112 int64_t service_worker_registration_id = | 125 int64_t service_worker_registration_id = |
113 GetServiceWorkerRegistrationId(service_worker_registration); | 126 GetServiceWorkerRegistrationId(service_worker_registration); |
114 PushSubscriptionOptions content_options; | 127 PushSubscriptionOptions content_options; |
115 content_options.user_visible_only = options.userVisibleOnly; | 128 content_options.user_visible_only = options.userVisibleOnly; |
116 | 129 |
117 // Just treat the server key as a string of bytes and pass it to the push | 130 // Just treat the server key as a string of bytes and pass it to the push |
118 // service. | 131 // service. |
119 content_options.sender_info = options.applicationServerKey.latin1(); | 132 content_options.sender_info = options.applicationServerKey.latin1(); |
120 thread_safe_sender_->Send(new PushMessagingHostMsg_Subscribe( | 133 |
121 ChildProcessHost::kInvalidUniqueID, request_id, | 134 push_messaging_manager_->Subscribe( |
122 service_worker_registration_id, content_options)); | 135 ChildProcessHost::kInvalidUniqueID, service_worker_registration_id, |
| 136 content_options, |
| 137 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 138 // by |this|. |
| 139 base::Bind(&PushProvider::SubscribeCallback, base::Unretained(this), |
| 140 base::Passed(&callbacks))); |
| 141 } |
| 142 |
| 143 void PushProvider::SubscribeCallback( |
| 144 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks, |
| 145 content::PushRegistrationStatus status, |
| 146 const base::Optional<GURL>& endpoint, |
| 147 const base::Optional<content::PushSubscriptionOptions>& options, |
| 148 const base::Optional<std::vector<uint8_t>>& p256dh, |
| 149 const base::Optional<std::vector<uint8_t>>& auth) { |
| 150 if (!callbacks) { |
| 151 return; |
| 152 } |
| 153 |
| 154 if (status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE || |
| 155 status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE) { |
| 156 DCHECK(endpoint); |
| 157 DCHECK(options); |
| 158 DCHECK(p256dh); |
| 159 DCHECK(auth); |
| 160 |
| 161 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( |
| 162 endpoint.value(), options.value().user_visible_only, |
| 163 blink::WebString::fromLatin1(options.value().sender_info), |
| 164 p256dh.value(), auth.value())); |
| 165 } else { |
| 166 callbacks->onError(PushRegistrationStatusToWebPushError(status)); |
| 167 } |
123 } | 168 } |
124 | 169 |
125 void PushProvider::unsubscribe( | 170 void PushProvider::unsubscribe( |
126 blink::WebServiceWorkerRegistration* service_worker_registration, | 171 blink::WebServiceWorkerRegistration* service_worker_registration, |
127 std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) { | 172 std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) { |
128 DCHECK(service_worker_registration); | 173 DCHECK(service_worker_registration); |
129 DCHECK(callbacks); | 174 DCHECK(callbacks); |
130 | 175 |
131 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | |
132 unsubscribe_callbacks_.AddWithID(std::move(callbacks), request_id); | |
133 int64_t service_worker_registration_id = | 176 int64_t service_worker_registration_id = |
134 GetServiceWorkerRegistrationId(service_worker_registration); | 177 GetServiceWorkerRegistrationId(service_worker_registration); |
135 thread_safe_sender_->Send(new PushMessagingHostMsg_Unsubscribe( | 178 |
136 request_id, service_worker_registration_id)); | 179 push_messaging_manager_->Unsubscribe( |
| 180 service_worker_registration_id, |
| 181 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 182 // by |this|. |
| 183 base::Bind(&PushProvider::UnsubscribeCallback, base::Unretained(this), |
| 184 base::Passed(&callbacks))); |
| 185 } |
| 186 |
| 187 void PushProvider::UnsubscribeCallback( |
| 188 std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks, |
| 189 bool is_success, |
| 190 bool did_unsubscribe, |
| 191 blink::WebPushError::ErrorType error_type, |
| 192 const base::Optional<std::string>& error_message) { |
| 193 if (!callbacks) { |
| 194 return; |
| 195 } |
| 196 |
| 197 if (is_success) { |
| 198 callbacks->onSuccess(did_unsubscribe); |
| 199 } else { |
| 200 callbacks->onError(blink::WebPushError( |
| 201 error_type, blink::WebString::fromUTF8(error_message->c_str()))); |
| 202 } |
137 } | 203 } |
138 | 204 |
139 void PushProvider::getSubscription( | 205 void PushProvider::getSubscription( |
140 blink::WebServiceWorkerRegistration* service_worker_registration, | 206 blink::WebServiceWorkerRegistration* service_worker_registration, |
141 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { | 207 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { |
142 DCHECK(service_worker_registration); | 208 DCHECK(service_worker_registration); |
143 DCHECK(callbacks); | 209 DCHECK(callbacks); |
144 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | 210 |
145 subscription_callbacks_.AddWithID(std::move(callbacks), request_id); | |
146 int64_t service_worker_registration_id = | 211 int64_t service_worker_registration_id = |
147 GetServiceWorkerRegistrationId(service_worker_registration); | 212 GetServiceWorkerRegistrationId(service_worker_registration); |
148 thread_safe_sender_->Send(new PushMessagingHostMsg_GetSubscription( | 213 |
149 request_id, service_worker_registration_id)); | 214 push_messaging_manager_->GetSubscription( |
| 215 service_worker_registration_id, |
| 216 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 217 // by |this|. |
| 218 base::Bind(&PushProvider::GetSubscriptionCallback, base::Unretained(this), |
| 219 base::Passed(&callbacks))); |
| 220 } |
| 221 |
| 222 void PushProvider::GetSubscriptionCallback( |
| 223 std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks, |
| 224 content::PushGetRegistrationStatus status, |
| 225 const base::Optional<GURL>& endpoint, |
| 226 const base::Optional<content::PushSubscriptionOptions>& options, |
| 227 const base::Optional<std::vector<uint8_t>>& p256dh, |
| 228 const base::Optional<std::vector<uint8_t>>& auth) { |
| 229 if (!callbacks) |
| 230 return; |
| 231 |
| 232 if (status == PUSH_GETREGISTRATION_STATUS_SUCCESS) { |
| 233 DCHECK(endpoint); |
| 234 DCHECK(options); |
| 235 DCHECK(p256dh); |
| 236 DCHECK(auth); |
| 237 |
| 238 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( |
| 239 endpoint.value(), options.value().user_visible_only, |
| 240 blink::WebString::fromLatin1(options.value().sender_info), |
| 241 p256dh.value(), auth.value())); |
| 242 } else { |
| 243 // We are only expecting an error if we can't find a registration. |
| 244 callbacks->onSuccess(nullptr); |
| 245 } |
150 } | 246 } |
151 | 247 |
152 void PushProvider::getPermissionStatus( | 248 void PushProvider::getPermissionStatus( |
153 blink::WebServiceWorkerRegistration* service_worker_registration, | 249 blink::WebServiceWorkerRegistration* service_worker_registration, |
154 const blink::WebPushSubscriptionOptions& options, | 250 const blink::WebPushSubscriptionOptions& options, |
155 std::unique_ptr<blink::WebPushPermissionStatusCallbacks> callbacks) { | 251 std::unique_ptr<blink::WebPushPermissionStatusCallbacks> callbacks) { |
156 DCHECK(service_worker_registration); | 252 DCHECK(service_worker_registration); |
157 DCHECK(callbacks); | 253 DCHECK(callbacks); |
158 int request_id = push_dispatcher_->GenerateRequestId(CurrentWorkerId()); | 254 |
159 permission_status_callbacks_.AddWithID(std::move(callbacks), request_id); | |
160 int64_t service_worker_registration_id = | 255 int64_t service_worker_registration_id = |
161 GetServiceWorkerRegistrationId(service_worker_registration); | 256 GetServiceWorkerRegistrationId(service_worker_registration); |
162 thread_safe_sender_->Send(new PushMessagingHostMsg_GetPermissionStatus( | 257 |
163 request_id, service_worker_registration_id, options.userVisibleOnly)); | 258 push_messaging_manager_->GetPermissionStatus( |
| 259 service_worker_registration_id, options.userVisibleOnly, |
| 260 // Safe to use base::Unretained because |push_messaging_manager_ |is owned |
| 261 // by |this|. |
| 262 base::Bind(&PushProvider::GetPermissionStatusCallback, |
| 263 base::Unretained(this), base::Passed(&callbacks))); |
164 } | 264 } |
165 | 265 |
166 bool PushProvider::OnMessageReceived(const IPC::Message& message) { | 266 void PushProvider::GetPermissionStatusCallback( |
167 bool handled = true; | 267 std::unique_ptr<blink::WebPushPermissionStatusCallbacks> callbacks, |
168 IPC_BEGIN_MESSAGE_MAP(PushProvider, message) | 268 bool is_success, |
169 IPC_MESSAGE_HANDLER(PushMessagingMsg_SubscribeFromWorkerSuccess, | 269 blink::WebPushPermissionStatus status, |
170 OnSubscribeFromWorkerSuccess); | 270 blink::WebPushError::ErrorType error) { |
171 IPC_MESSAGE_HANDLER(PushMessagingMsg_SubscribeFromWorkerError, | |
172 OnSubscribeFromWorkerError); | |
173 IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeSuccess, | |
174 OnUnsubscribeSuccess); | |
175 IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeError, OnUnsubscribeError); | |
176 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetSubscriptionSuccess, | |
177 OnGetSubscriptionSuccess); | |
178 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetSubscriptionError, | |
179 OnGetSubscriptionError); | |
180 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusSuccess, | |
181 OnGetPermissionStatusSuccess); | |
182 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusError, | |
183 OnGetPermissionStatusError); | |
184 IPC_MESSAGE_UNHANDLED(handled = false) | |
185 IPC_END_MESSAGE_MAP() | |
186 | |
187 return handled; | |
188 } | |
189 | |
190 void PushProvider::OnSubscribeFromWorkerSuccess( | |
191 int request_id, | |
192 const GURL& endpoint, | |
193 const PushSubscriptionOptions& options, | |
194 const std::vector<uint8_t>& p256dh, | |
195 const std::vector<uint8_t>& auth) { | |
196 blink::WebPushSubscriptionCallbacks* callbacks = | |
197 subscription_callbacks_.Lookup(request_id); | |
198 if (!callbacks) | 271 if (!callbacks) |
199 return; | 272 return; |
200 | 273 |
201 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( | 274 if (is_success) { |
202 endpoint, options.user_visible_only, | 275 callbacks->onSuccess(status); |
203 blink::WebString::fromLatin1(options.sender_info), p256dh, auth)); | 276 } else { |
204 | 277 std::string error_message; |
205 subscription_callbacks_.Remove(request_id); | 278 if (error == blink::WebPushError::ErrorTypeNotSupported) { |
206 } | 279 error_message = |
207 | 280 "Push subscriptions that don't enable userVisibleOnly are not " |
208 void PushProvider::OnSubscribeFromWorkerError(int request_id, | 281 "supported."; |
209 PushRegistrationStatus status) { | 282 } |
210 blink::WebPushSubscriptionCallbacks* callbacks = | 283 callbacks->onError( |
211 subscription_callbacks_.Lookup(request_id); | 284 blink::WebPushError(error, blink::WebString::fromUTF8(error_message))); |
212 if (!callbacks) | |
213 return; | |
214 | |
215 callbacks->onError(PushRegistrationStatusToWebPushError(status)); | |
216 | |
217 subscription_callbacks_.Remove(request_id); | |
218 } | |
219 | |
220 void PushProvider::OnUnsubscribeSuccess(int request_id, bool did_unsubscribe) { | |
221 blink::WebPushUnsubscribeCallbacks* callbacks = | |
222 unsubscribe_callbacks_.Lookup(request_id); | |
223 if (!callbacks) | |
224 return; | |
225 | |
226 callbacks->onSuccess(did_unsubscribe); | |
227 | |
228 unsubscribe_callbacks_.Remove(request_id); | |
229 } | |
230 | |
231 void PushProvider::OnUnsubscribeError(int request_id, | |
232 blink::WebPushError::ErrorType error_type, | |
233 const std::string& error_message) { | |
234 blink::WebPushUnsubscribeCallbacks* callbacks = | |
235 unsubscribe_callbacks_.Lookup(request_id); | |
236 if (!callbacks) | |
237 return; | |
238 | |
239 callbacks->onError(blink::WebPushError( | |
240 error_type, blink::WebString::fromUTF8(error_message))); | |
241 | |
242 unsubscribe_callbacks_.Remove(request_id); | |
243 } | |
244 | |
245 void PushProvider::OnGetSubscriptionSuccess( | |
246 int request_id, | |
247 const GURL& endpoint, | |
248 const PushSubscriptionOptions& options, | |
249 const std::vector<uint8_t>& p256dh, | |
250 const std::vector<uint8_t>& auth) { | |
251 blink::WebPushSubscriptionCallbacks* callbacks = | |
252 subscription_callbacks_.Lookup(request_id); | |
253 if (!callbacks) | |
254 return; | |
255 | |
256 callbacks->onSuccess(base::MakeUnique<blink::WebPushSubscription>( | |
257 endpoint, options.user_visible_only, | |
258 blink::WebString::fromLatin1(options.sender_info), p256dh, auth)); | |
259 | |
260 subscription_callbacks_.Remove(request_id); | |
261 } | |
262 | |
263 void PushProvider::OnGetSubscriptionError(int request_id, | |
264 PushGetRegistrationStatus status) { | |
265 blink::WebPushSubscriptionCallbacks* callbacks = | |
266 subscription_callbacks_.Lookup(request_id); | |
267 if (!callbacks) | |
268 return; | |
269 | |
270 // We are only expecting an error if we can't find a registration. | |
271 callbacks->onSuccess(nullptr); | |
272 | |
273 subscription_callbacks_.Remove(request_id); | |
274 } | |
275 | |
276 void PushProvider::OnGetPermissionStatusSuccess( | |
277 int request_id, | |
278 blink::WebPushPermissionStatus status) { | |
279 blink::WebPushPermissionStatusCallbacks* callbacks = | |
280 permission_status_callbacks_.Lookup(request_id); | |
281 if (!callbacks) | |
282 return; | |
283 | |
284 callbacks->onSuccess(status); | |
285 | |
286 permission_status_callbacks_.Remove(request_id); | |
287 } | |
288 | |
289 void PushProvider::OnGetPermissionStatusError( | |
290 int request_id, | |
291 blink::WebPushError::ErrorType error) { | |
292 blink::WebPushPermissionStatusCallbacks* callbacks = | |
293 permission_status_callbacks_.Lookup(request_id); | |
294 if (!callbacks) | |
295 return; | |
296 | |
297 std::string error_message; | |
298 if (error == blink::WebPushError::ErrorTypeNotSupported) { | |
299 error_message = | |
300 "Push subscriptions that don't enable userVisibleOnly are not " | |
301 "supported."; | |
302 } | 285 } |
303 | |
304 callbacks->onError( | |
305 blink::WebPushError(error, blink::WebString::fromUTF8(error_message))); | |
306 | |
307 permission_status_callbacks_.Remove(request_id); | |
308 } | 286 } |
309 | 287 |
310 } // namespace content | 288 } // namespace content |
OLD | NEW |