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/browser/push_messaging/push_messaging_manager.h" | 5 #include "content/browser/push_messaging/push_messaging_manager.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 | 42 |
43 namespace { | 43 namespace { |
44 | 44 |
45 // Chrome currently does not support the Push API in incognito. | 45 // Chrome currently does not support the Push API in incognito. |
46 const char kIncognitoPushUnsupportedMessage[] = | 46 const char kIncognitoPushUnsupportedMessage[] = |
47 "Chrome currently does not support the Push API in incognito mode " | 47 "Chrome currently does not support the Push API in incognito mode " |
48 "(https://crbug.com/401439). There is deliberately no way to " | 48 "(https://crbug.com/401439). There is deliberately no way to " |
49 "feature-detect this, since incognito mode needs to be undetectable by " | 49 "feature-detect this, since incognito mode needs to be undetectable by " |
50 "websites."; | 50 "websites."; |
51 | 51 |
52 // These UMA methods are only called from IO thread, but it would be acceptable | 52 // These UMA methods are called from the IO and/or UI threads. Racey but ok, see |
53 // (even though slightly racy) to call them from UI thread as well, see | |
54 // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CW
AXJJ1kJ | 53 // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CW
AXJJ1kJ |
55 void RecordRegistrationStatus(PushRegistrationStatus status) { | 54 void RecordRegistrationStatus(PushRegistrationStatus status) { |
56 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || |
| 56 BrowserThread::CurrentlyOn(BrowserThread::UI)); |
57 UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status, | 57 UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status, |
58 PUSH_REGISTRATION_STATUS_LAST + 1); | 58 PUSH_REGISTRATION_STATUS_LAST + 1); |
59 } | 59 } |
60 | |
61 void RecordUnregistrationStatus(PushUnregistrationStatus status) { | 60 void RecordUnregistrationStatus(PushUnregistrationStatus status) { |
62 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 61 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
63 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status, | 62 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status, |
64 PUSH_UNREGISTRATION_STATUS_LAST + 1); | 63 PUSH_UNREGISTRATION_STATUS_LAST + 1); |
65 } | 64 } |
66 | |
67 void RecordGetRegistrationStatus(PushGetRegistrationStatus status) { | 65 void RecordGetRegistrationStatus(PushGetRegistrationStatus status) { |
68 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || |
| 67 BrowserThread::CurrentlyOn(BrowserThread::UI)); |
69 UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status, | 68 UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status, |
70 PUSH_GETREGISTRATION_STATUS_LAST + 1); | 69 PUSH_GETREGISTRATION_STATUS_LAST + 1); |
71 } | 70 } |
72 | 71 |
73 // Curries the |success| and |p256dh| parameters over to |callback| and | 72 void UnregisterCallbackToClosure(const base::Closure& closure, |
74 // posts a task to invoke |callback| on the IO thread. | 73 PushUnregistrationStatus status) { |
75 void ForwardEncryptionInfoToIOThreadProxy( | 74 DCHECK(!closure.is_null()); |
76 const PushMessagingService::EncryptionInfoCallback& callback, | 75 closure.Run(); |
77 bool success, | |
78 const std::vector<uint8_t>& p256dh, | |
79 const std::vector<uint8_t>& auth) { | |
80 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
81 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
82 base::Bind(callback, success, p256dh, auth)); | |
83 } | 76 } |
84 | 77 |
85 // Returns whether |sender_info| contains a valid application server key, that | 78 // Returns whether |sender_info| contains a valid application server key, that |
86 // is, a NIST P-256 public key in uncompressed format. | 79 // is, a NIST P-256 public key in uncompressed format. |
87 bool IsApplicationServerKey(const std::string& sender_info) { | 80 bool IsApplicationServerKey(const std::string& sender_info) { |
88 return sender_info.size() == 65 && sender_info[0] == 0x04; | 81 return sender_info.size() == 65 && sender_info[0] == 0x04; |
89 } | 82 } |
90 | 83 |
91 // Returns sender_info if non-empty, otherwise checks if stored_sender_id | 84 // Returns sender_info if non-empty, otherwise checks if stored_sender_id |
92 // may be used as a fallback and if so, returns stored_sender_id instead. | 85 // may be used as a fallback and if so, returns stored_sender_id instead. |
(...skipping 28 matching lines...) Expand all Loading... |
121 }; | 114 }; |
122 | 115 |
123 // Inner core of the PushMessagingManager which lives on the UI thread. | 116 // Inner core of the PushMessagingManager which lives on the UI thread. |
124 class PushMessagingManager::Core { | 117 class PushMessagingManager::Core { |
125 public: | 118 public: |
126 Core(const base::WeakPtr<PushMessagingManager>& io_parent, | 119 Core(const base::WeakPtr<PushMessagingManager>& io_parent, |
127 int render_process_id); | 120 int render_process_id); |
128 | 121 |
129 // Public Register methods on UI thread -------------------------------------- | 122 // Public Register methods on UI thread -------------------------------------- |
130 | 123 |
| 124 // Callback called on UI thread. |
| 125 void SubscribeDidGetInfoOnUI(const RegisterData& data, |
| 126 const std::string& push_subscription_id, |
| 127 const std::string& sender_id, |
| 128 bool is_valid, |
| 129 const std::vector<uint8_t>& p256dh, |
| 130 const std::vector<uint8_t>& auth); |
| 131 |
131 // Called via PostTask from IO thread. | 132 // Called via PostTask from IO thread. |
132 void RegisterOnUI(const RegisterData& data); | 133 void RegisterOnUI(const RegisterData& data); |
133 | 134 |
134 // Public Unregister methods on UI thread ------------------------------------ | 135 // Public Unregister methods on UI thread ------------------------------------ |
135 | 136 |
136 // Called via PostTask from IO thread. | 137 // Called via PostTask from IO thread. |
137 void UnregisterFromService(const UnsubscribeCallback& callback, | 138 void UnregisterFromService(const UnsubscribeCallback& callback, |
138 int64_t service_worker_registration_id, | 139 int64_t service_worker_registration_id, |
139 const GURL& requesting_origin, | 140 const GURL& requesting_origin, |
140 const std::string& sender_id); | 141 const std::string& sender_id); |
141 | 142 |
| 143 // Public GetSubscription methods on UI thread ------------------------------- |
| 144 |
| 145 // Callback called on UI thread. |
| 146 void GetSubscriptionDidGetInfoOnUI(const GetSubscriptionCallback& callback, |
| 147 const GURL& origin, |
| 148 int64_t service_worker_registration_id, |
| 149 const GURL& endpoint, |
| 150 const std::string& sender_info, |
| 151 bool is_valid, |
| 152 const std::vector<uint8_t>& p256dh, |
| 153 const std::vector<uint8_t>& auth); |
| 154 |
| 155 // Callback called on UI thread. |
| 156 void GetSubscriptionDidUnsubscribe( |
| 157 const GetSubscriptionCallback& callback, |
| 158 PushGetRegistrationStatus get_status, |
| 159 PushUnregistrationStatus unsubscribe_status); |
| 160 |
142 // Public GetPermission methods on UI thread --------------------------------- | 161 // Public GetPermission methods on UI thread --------------------------------- |
143 | 162 |
144 // Called via PostTask from IO thread. | 163 // Called via PostTask from IO thread. |
145 void GetPermissionStatusOnUI(const GetPermissionStatusCallback& callback, | 164 void GetPermissionStatusOnUI(const GetPermissionStatusCallback& callback, |
146 const GURL& requesting_origin, | 165 const GURL& requesting_origin, |
147 bool user_visible); | 166 bool user_visible); |
148 | 167 |
149 // Public helper methods on UI thread ---------------------------------------- | 168 // Public helper methods on UI thread ---------------------------------------- |
150 | 169 |
151 // Called via PostTask from IO thread. The |io_thread_callback| callback | 170 // Called via PostTask from IO thread. |callback| will be run on UI thread. |
152 // will be invoked on the IO thread. | 171 void GetSubscriptionInfoOnUI( |
153 void GetEncryptionInfoOnUI( | |
154 const GURL& origin, | 172 const GURL& origin, |
155 int64_t service_worker_registration_id, | 173 int64_t service_worker_registration_id, |
156 const std::string& sender_id, | 174 const std::string& sender_id, |
157 const PushMessagingService::EncryptionInfoCallback& io_thread_callback); | 175 const std::string& push_subscription_id, |
| 176 const PushMessagingService::SubscriptionInfoCallback& callback); |
158 | 177 |
159 // Called (directly) from both the UI and IO threads. | 178 // Called (directly) from both the UI and IO threads. |
160 bool is_incognito() const { return is_incognito_; } | 179 bool is_incognito() const { return is_incognito_; } |
161 | 180 |
162 // Returns a push messaging service. May return null. | 181 // Returns a push messaging service. May return null. |
163 PushMessagingService* service(); | 182 PushMessagingService* service(); |
164 | 183 |
| 184 // Returns a weak ptr. Must only be called on the UI thread (and hence can |
| 185 // only be called from the outer class's constructor). |
| 186 base::WeakPtr<Core> GetWeakPtrFromIOParentConstructor(); |
| 187 |
165 private: | 188 private: |
166 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 189 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
167 friend class base::DeleteHelper<Core>; | 190 friend class base::DeleteHelper<Core>; |
168 | 191 |
169 ~Core(); | 192 ~Core(); |
170 | 193 |
171 // Private Register methods on UI thread ------------------------------------- | 194 // Private Register methods on UI thread ------------------------------------- |
172 | 195 |
173 void DidRequestPermissionInIncognito(const RegisterData& data, | 196 void DidRequestPermissionInIncognito(const RegisterData& data, |
174 blink::mojom::PermissionStatus status); | 197 blink::mojom::PermissionStatus status); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 ServiceWorkerContextWrapper* service_worker_context) | 247 ServiceWorkerContextWrapper* service_worker_context) |
225 : service_worker_context_(service_worker_context), | 248 : service_worker_context_(service_worker_context), |
226 weak_factory_io_to_io_(this) { | 249 weak_factory_io_to_io_(this) { |
227 // Although this class is used only on the IO thread, it is constructed on UI. | 250 // Although this class is used only on the IO thread, it is constructed on UI. |
228 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 251 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
229 // Normally, it would be unsafe to obtain a weak pointer from the UI thread, | 252 // Normally, it would be unsafe to obtain a weak pointer from the UI thread, |
230 // but it's ok in the constructor since we can't be destroyed before our | 253 // but it's ok in the constructor since we can't be destroyed before our |
231 // constructor finishes. | 254 // constructor finishes. |
232 ui_core_.reset( | 255 ui_core_.reset( |
233 new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); | 256 new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); |
| 257 ui_core_weak_ptr_ = ui_core_->GetWeakPtrFromIOParentConstructor(); |
234 | 258 |
235 PushMessagingService* service = ui_core_->service(); | 259 PushMessagingService* service = ui_core_->service(); |
236 service_available_ = !!service; | 260 service_available_ = !!service; |
237 | 261 |
238 if (service_available_) { | 262 if (service_available_) { |
239 default_endpoint_ = service->GetEndpoint(false /* standard_protocol */); | 263 default_endpoint_ = service->GetEndpoint(false /* standard_protocol */); |
240 web_push_protocol_endpoint_ = | 264 web_push_protocol_endpoint_ = |
241 service->GetEndpoint(true /* standard_protocol */); | 265 service->GetEndpoint(true /* standard_protocol */); |
242 } | 266 } |
243 } | 267 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 weak_factory_io_to_io_.GetWeakPtr(), data)); | 310 weak_factory_io_to_io_.GetWeakPtr(), data)); |
287 } | 311 } |
288 | 312 |
289 void PushMessagingManager::DidCheckForExistingRegistration( | 313 void PushMessagingManager::DidCheckForExistingRegistration( |
290 const RegisterData& data, | 314 const RegisterData& data, |
291 const std::vector<std::string>& push_registration_id_and_sender_id, | 315 const std::vector<std::string>& push_registration_id_and_sender_id, |
292 ServiceWorkerStatusCode service_worker_status) { | 316 ServiceWorkerStatusCode service_worker_status) { |
293 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 317 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
294 if (service_worker_status == SERVICE_WORKER_OK) { | 318 if (service_worker_status == SERVICE_WORKER_OK) { |
295 DCHECK_EQ(2u, push_registration_id_and_sender_id.size()); | 319 DCHECK_EQ(2u, push_registration_id_and_sender_id.size()); |
296 const auto& push_registration_id = push_registration_id_and_sender_id[0]; | 320 const auto& push_subscription_id = push_registration_id_and_sender_id[0]; |
297 const auto& stored_sender_id = push_registration_id_and_sender_id[1]; | 321 const auto& stored_sender_id = push_registration_id_and_sender_id[1]; |
298 std::string fixed_sender_id = | 322 std::string fixed_sender_id = |
299 FixSenderInfo(data.options.sender_info, stored_sender_id); | 323 FixSenderInfo(data.options.sender_info, stored_sender_id); |
300 if (fixed_sender_id.empty()) { | 324 if (fixed_sender_id.empty()) { |
301 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 325 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); |
302 return; | 326 return; |
303 } | 327 } |
304 if (fixed_sender_id != stored_sender_id) { | 328 if (fixed_sender_id != stored_sender_id) { |
305 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SENDER_ID_MISMATCH); | 329 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SENDER_ID_MISMATCH); |
306 return; | 330 return; |
307 } | 331 } |
308 auto callback = base::Bind(&PushMessagingManager::DidGetEncryptionKeys, | |
309 weak_factory_io_to_io_.GetWeakPtr(), data, | |
310 push_registration_id); | |
311 BrowserThread::PostTask( | 332 BrowserThread::PostTask( |
312 BrowserThread::UI, FROM_HERE, | 333 BrowserThread::UI, FROM_HERE, |
313 base::Bind(&Core::GetEncryptionInfoOnUI, | 334 base::Bind(&Core::GetSubscriptionInfoOnUI, |
314 base::Unretained(ui_core_.get()), data.requesting_origin, | 335 base::Unretained(ui_core_.get()), data.requesting_origin, |
315 data.service_worker_registration_id, fixed_sender_id, | 336 data.service_worker_registration_id, fixed_sender_id, |
316 callback)); | 337 push_subscription_id, |
| 338 base::Bind(&Core::SubscribeDidGetInfoOnUI, ui_core_weak_ptr_, |
| 339 data, push_subscription_id, fixed_sender_id))); |
317 return; | 340 return; |
318 } | 341 } |
319 // TODO(johnme): The spec allows the register algorithm to reject with an | 342 // TODO(johnme): The spec allows the register algorithm to reject with an |
320 // AbortError when accessing storage fails. Perhaps we should do that if | 343 // AbortError when accessing storage fails. Perhaps we should do that if |
321 // service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND instead of | 344 // service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND instead of |
322 // attempting to do a fresh registration? | 345 // attempting to do a fresh registration? |
323 // https://w3c.github.io/push-api/#widl-PushRegistrationManager-register-Promi
se-PushRegistration | 346 // https://w3c.github.io/push-api/#widl-PushRegistrationManager-register-Promi
se-PushRegistration |
324 if (!data.options.sender_info.empty()) { | 347 if (!data.options.sender_info.empty()) { |
325 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 348 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
326 base::Bind(&Core::RegisterOnUI, | 349 base::Bind(&Core::RegisterOnUI, |
327 base::Unretained(ui_core_.get()), data)); | 350 base::Unretained(ui_core_.get()), data)); |
328 } else { | 351 } else { |
329 // There is no existing registration and the sender_info passed in was | 352 // There is no existing registration and the sender_info passed in was |
330 // empty, but perhaps there is a stored sender id we can use. | 353 // empty, but perhaps there is a stored sender id we can use. |
331 service_worker_context_->GetRegistrationUserData( | 354 service_worker_context_->GetRegistrationUserData( |
332 data.service_worker_registration_id, {kPushSenderIdServiceWorkerKey}, | 355 data.service_worker_registration_id, {kPushSenderIdServiceWorkerKey}, |
333 base::Bind(&PushMessagingManager::DidGetSenderIdFromStorage, | 356 base::Bind(&PushMessagingManager::DidGetSenderIdFromStorage, |
334 weak_factory_io_to_io_.GetWeakPtr(), data)); | 357 weak_factory_io_to_io_.GetWeakPtr(), data)); |
335 } | 358 } |
336 } | 359 } |
337 | 360 |
338 void PushMessagingManager::DidGetEncryptionKeys( | 361 void PushMessagingManager::Core::SubscribeDidGetInfoOnUI( |
339 const RegisterData& data, | 362 const RegisterData& data, |
340 const std::string& push_registration_id, | 363 const std::string& push_subscription_id, |
341 bool success, | 364 const std::string& sender_id, |
| 365 bool is_valid, |
342 const std::vector<uint8_t>& p256dh, | 366 const std::vector<uint8_t>& p256dh, |
343 const std::vector<uint8_t>& auth) { | 367 const std::vector<uint8_t>& auth) { |
344 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 368 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
345 if (!success) { | 369 if (is_valid) { |
346 SendSubscriptionError(data, | 370 BrowserThread::PostTask( |
347 PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE); | 371 BrowserThread::IO, FROM_HERE, |
348 return; | 372 base::Bind(&PushMessagingManager::SendSubscriptionSuccess, io_parent_, |
| 373 data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, |
| 374 push_subscription_id, p256dh, auth)); |
| 375 } else { |
| 376 PushMessagingService* push_service = service(); |
| 377 if (!push_service) { |
| 378 NOTREACHED() << "Shouldn't be possible to have a stored push " |
| 379 "subscription in a profile with no push service."; |
| 380 BrowserThread::PostTask( |
| 381 BrowserThread::IO, FROM_HERE, |
| 382 base::Bind(&PushMessagingManager::SendSubscriptionError, io_parent_, |
| 383 data, PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE)); |
| 384 return; |
| 385 } |
| 386 |
| 387 // Uh-oh! Although there was a cached subscription in the Service Worker |
| 388 // database, it did not have matching counterparts in the |
| 389 // PushMessagingAppIdentifier map and/or GCM Store. Unsubscribe and |
| 390 // re-subscribe to fix this inconsistency. |
| 391 |
| 392 // Consider this subscription attempt to have failed. The re-subscribe will |
| 393 // be logged to UMA as a separate subscription attempt. |
| 394 RecordRegistrationStatus(PUSH_REGISTRATION_STATUS_STORAGE_CORRUPT); |
| 395 |
| 396 auto try_again_on_io = base::Bind( |
| 397 &PushMessagingManager::DidCheckForExistingRegistration, io_parent_, |
| 398 data, |
| 399 std::vector<std::string>() /* push_registration_id_and_sender_id */, |
| 400 SERVICE_WORKER_ERROR_NOT_FOUND); |
| 401 push_service->Unsubscribe( |
| 402 PUSH_UNREGISTRATION_REASON_SUBSCRIBE_STORAGE_CORRUPT, |
| 403 data.requesting_origin, data.service_worker_registration_id, sender_id, |
| 404 base::Bind(&UnregisterCallbackToClosure, |
| 405 base::Bind(IgnoreResult(&BrowserThread::PostTask), |
| 406 BrowserThread::IO, FROM_HERE, try_again_on_io))); |
349 } | 407 } |
350 | |
351 SendSubscriptionSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, | |
352 push_registration_id, p256dh, auth); | |
353 } | 408 } |
354 | 409 |
355 void PushMessagingManager::DidGetSenderIdFromStorage( | 410 void PushMessagingManager::DidGetSenderIdFromStorage( |
356 const RegisterData& data, | 411 const RegisterData& data, |
357 const std::vector<std::string>& stored_sender_id, | 412 const std::vector<std::string>& stored_sender_id, |
358 ServiceWorkerStatusCode service_worker_status) { | 413 ServiceWorkerStatusCode service_worker_status) { |
359 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 414 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
360 if (service_worker_status != SERVICE_WORKER_OK) { | 415 if (service_worker_status != SERVICE_WORKER_OK) { |
361 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 416 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); |
362 return; | 417 return; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 push_registration_id, p256dh, auth); | 570 push_registration_id, p256dh, auth); |
516 } else { | 571 } else { |
517 // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count. | 572 // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count. |
518 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); | 573 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); |
519 } | 574 } |
520 } | 575 } |
521 | 576 |
522 void PushMessagingManager::SendSubscriptionError( | 577 void PushMessagingManager::SendSubscriptionError( |
523 const RegisterData& data, | 578 const RegisterData& data, |
524 PushRegistrationStatus status) { | 579 PushRegistrationStatus status) { |
525 // Only called from IO thread, but would be safe to call from UI thread. | |
526 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 580 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
527 data.callback.Run(status, base::nullopt /* endpoint */, | 581 data.callback.Run(status, base::nullopt /* endpoint */, |
528 base::nullopt /* options */, base::nullopt /* p256dh */, | 582 base::nullopt /* options */, base::nullopt /* p256dh */, |
529 base::nullopt /* auth */); | 583 base::nullopt /* auth */); |
530 RecordRegistrationStatus(status); | 584 RecordRegistrationStatus(status); |
531 } | 585 } |
532 | 586 |
533 void PushMessagingManager::SendSubscriptionSuccess( | 587 void PushMessagingManager::SendSubscriptionSuccess( |
534 const RegisterData& data, | 588 const RegisterData& data, |
535 PushRegistrationStatus status, | 589 PushRegistrationStatus status, |
536 const std::string& push_subscription_id, | 590 const std::string& push_subscription_id, |
537 const std::vector<uint8_t>& p256dh, | 591 const std::vector<uint8_t>& p256dh, |
538 const std::vector<uint8_t>& auth) { | 592 const std::vector<uint8_t>& auth) { |
539 // Only called from IO thread, but would be safe to call from UI thread. | |
540 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 593 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
541 if (!service_available_) { | 594 if (!service_available_) { |
542 // This shouldn't be possible in incognito mode, since we've already checked | 595 // This shouldn't be possible in incognito mode, since we've already checked |
543 // that we have an existing registration. Hence it's ok to throw an error. | 596 // that we have an existing registration. Hence it's ok to throw an error. |
544 DCHECK(!ui_core_->is_incognito()); | 597 DCHECK(!ui_core_->is_incognito()); |
545 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); | 598 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); |
546 return; | 599 return; |
547 } | 600 } |
548 | 601 |
549 const GURL endpoint = CreateEndpoint( | 602 const GURL endpoint = CreateEndpoint( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 // that we have an existing registration. Hence it's ok to throw an error. | 662 // that we have an existing registration. Hence it's ok to throw an error. |
610 DCHECK(!is_incognito()); | 663 DCHECK(!is_incognito()); |
611 BrowserThread::PostTask( | 664 BrowserThread::PostTask( |
612 BrowserThread::IO, FROM_HERE, | 665 BrowserThread::IO, FROM_HERE, |
613 base::Bind(&PushMessagingManager::DidUnregister, io_parent_, callback, | 666 base::Bind(&PushMessagingManager::DidUnregister, io_parent_, callback, |
614 PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); | 667 PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); |
615 return; | 668 return; |
616 } | 669 } |
617 | 670 |
618 push_service->Unsubscribe( | 671 push_service->Unsubscribe( |
619 requesting_origin, service_worker_registration_id, sender_id, | 672 PUSH_UNREGISTRATION_REASON_JAVASCRIPT_API, requesting_origin, |
| 673 service_worker_registration_id, sender_id, |
620 base::Bind(&Core::DidUnregisterFromService, | 674 base::Bind(&Core::DidUnregisterFromService, |
621 weak_factory_ui_to_ui_.GetWeakPtr(), callback, | 675 weak_factory_ui_to_ui_.GetWeakPtr(), callback, |
622 service_worker_registration_id)); | 676 service_worker_registration_id)); |
623 } | 677 } |
624 | 678 |
625 void PushMessagingManager::Core::DidUnregisterFromService( | 679 void PushMessagingManager::Core::DidUnregisterFromService( |
626 const UnsubscribeCallback& callback, | 680 const UnsubscribeCallback& callback, |
627 int64_t service_worker_registration_id, | 681 int64_t service_worker_registration_id, |
628 PushUnregistrationStatus unregistration_status) { | 682 PushUnregistrationStatus unregistration_status) { |
629 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 683 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 const GetSubscriptionCallback& callback, | 741 const GetSubscriptionCallback& callback, |
688 int64_t service_worker_registration_id, | 742 int64_t service_worker_registration_id, |
689 const std::vector<std::string>& push_subscription_id_and_sender_info, | 743 const std::vector<std::string>& push_subscription_id_and_sender_info, |
690 ServiceWorkerStatusCode service_worker_status) { | 744 ServiceWorkerStatusCode service_worker_status) { |
691 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 745 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
692 PushGetRegistrationStatus get_status = | 746 PushGetRegistrationStatus get_status = |
693 PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 747 PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; |
694 switch (service_worker_status) { | 748 switch (service_worker_status) { |
695 case SERVICE_WORKER_OK: { | 749 case SERVICE_WORKER_OK: { |
696 DCHECK_EQ(2u, push_subscription_id_and_sender_info.size()); | 750 DCHECK_EQ(2u, push_subscription_id_and_sender_info.size()); |
| 751 const std::string& push_subscription_id = |
| 752 push_subscription_id_and_sender_info[0]; |
| 753 const std::string& sender_info = push_subscription_id_and_sender_info[1]; |
697 | 754 |
698 if (!service_available_) { | 755 if (!service_available_) { |
699 // Return not found in incognito mode, so websites can't detect it. | 756 // Return not found in incognito mode, so websites can't detect it. |
700 get_status = | 757 get_status = |
701 ui_core_->is_incognito() | 758 ui_core_->is_incognito() |
702 ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND | 759 ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND |
703 : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; | 760 : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; |
704 break; | 761 break; |
705 } | 762 } |
706 | 763 |
707 ServiceWorkerRegistration* registration = | 764 ServiceWorkerRegistration* registration = |
708 service_worker_context_->GetLiveRegistration( | 765 service_worker_context_->GetLiveRegistration( |
709 service_worker_registration_id); | 766 service_worker_registration_id); |
710 const GURL origin = registration->pattern().GetOrigin(); | 767 const GURL origin = registration->pattern().GetOrigin(); |
711 | 768 |
712 const bool uses_standard_protocol = | 769 const bool uses_standard_protocol = IsApplicationServerKey(sender_info); |
713 IsApplicationServerKey(push_subscription_id_and_sender_info[1]); | 770 const GURL endpoint = |
714 const GURL endpoint = CreateEndpoint( | 771 CreateEndpoint(uses_standard_protocol, push_subscription_id); |
715 uses_standard_protocol, push_subscription_id_and_sender_info[0]); | |
716 | |
717 auto callback_ui = | |
718 base::Bind(&PushMessagingManager::DidGetSubscriptionKeys, | |
719 weak_factory_io_to_io_.GetWeakPtr(), callback, endpoint, | |
720 push_subscription_id_and_sender_info[1]); | |
721 | 772 |
722 BrowserThread::PostTask( | 773 BrowserThread::PostTask( |
723 BrowserThread::UI, FROM_HERE, | 774 BrowserThread::UI, FROM_HERE, |
724 base::Bind(&Core::GetEncryptionInfoOnUI, | 775 base::Bind(&Core::GetSubscriptionInfoOnUI, |
725 base::Unretained(ui_core_.get()), origin, | 776 base::Unretained(ui_core_.get()), origin, |
726 service_worker_registration_id, | 777 service_worker_registration_id, sender_info, |
727 push_subscription_id_and_sender_info[1], callback_ui)); | 778 push_subscription_id, |
| 779 base::Bind(&Core::GetSubscriptionDidGetInfoOnUI, |
| 780 ui_core_weak_ptr_, callback, origin, |
| 781 service_worker_registration_id, endpoint, |
| 782 sender_info))); |
728 | 783 |
729 return; | 784 return; |
730 } | 785 } |
731 case SERVICE_WORKER_ERROR_NOT_FOUND: { | 786 case SERVICE_WORKER_ERROR_NOT_FOUND: { |
732 get_status = PUSH_GETREGISTRATION_STATUS_REGISTRATION_NOT_FOUND; | 787 get_status = PUSH_GETREGISTRATION_STATUS_REGISTRATION_NOT_FOUND; |
733 break; | 788 break; |
734 } | 789 } |
735 case SERVICE_WORKER_ERROR_FAILED: { | 790 case SERVICE_WORKER_ERROR_FAILED: { |
736 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 791 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; |
737 break; | 792 break; |
(...skipping 20 matching lines...) Expand all Loading... |
758 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 813 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; |
759 break; | 814 break; |
760 } | 815 } |
761 } | 816 } |
762 callback.Run(get_status, base::nullopt /* endpoint */, | 817 callback.Run(get_status, base::nullopt /* endpoint */, |
763 base::nullopt /* options */, base::nullopt /* p256dh */, | 818 base::nullopt /* options */, base::nullopt /* p256dh */, |
764 base::nullopt /* auth */); | 819 base::nullopt /* auth */); |
765 RecordGetRegistrationStatus(get_status); | 820 RecordGetRegistrationStatus(get_status); |
766 } | 821 } |
767 | 822 |
768 void PushMessagingManager::DidGetSubscriptionKeys( | 823 void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI( |
769 const GetSubscriptionCallback& callback, | 824 const GetSubscriptionCallback& callback, |
| 825 const GURL& origin, |
| 826 int64_t service_worker_registration_id, |
770 const GURL& endpoint, | 827 const GURL& endpoint, |
771 const std::string& sender_info, | 828 const std::string& sender_info, |
772 bool success, | 829 bool is_valid, |
773 const std::vector<uint8_t>& p256dh, | 830 const std::vector<uint8_t>& p256dh, |
774 const std::vector<uint8_t>& auth) { | 831 const std::vector<uint8_t>& auth) { |
775 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 832 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
776 if (!success) { | 833 if (is_valid) { |
777 PushGetRegistrationStatus status = | 834 PushSubscriptionOptions options; |
778 PUSH_GETREGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE; | 835 // Chrome rejects subscription requests with userVisibleOnly false, so it |
| 836 // must have been true. TODO(harkness): If Chrome starts accepting silent |
| 837 // push subscriptions with userVisibleOnly false, the bool will need to be |
| 838 // stored. |
| 839 options.user_visible_only = true; |
| 840 options.sender_info = sender_info; |
779 | 841 |
780 callback.Run(status, base::nullopt /* endpoint */, | 842 PushGetRegistrationStatus status = PUSH_GETREGISTRATION_STATUS_SUCCESS; |
781 base::nullopt /* options */, base::nullopt /* p256dh */, | 843 |
782 base::nullopt /* auth */); | 844 BrowserThread::PostTask( |
| 845 BrowserThread::IO, FROM_HERE, |
| 846 base::Bind(callback, status, endpoint, options, p256dh, auth)); |
783 | 847 |
784 RecordGetRegistrationStatus(status); | 848 RecordGetRegistrationStatus(status); |
785 return; | 849 } else { |
| 850 // Uh-oh! Although there was a cached subscription in the Service Worker |
| 851 // database, it did not have matching counterparts in the |
| 852 // PushMessagingAppIdentifier map and/or GCM Store. Unsubscribe to fix this |
| 853 // inconsistency. |
| 854 PushGetRegistrationStatus status = |
| 855 PUSH_GETREGISTRATION_STATUS_STORAGE_CORRUPT; |
| 856 |
| 857 PushMessagingService* push_service = service(); |
| 858 DCHECK(push_service); // NOT_FOUND response can only come from service. |
| 859 push_service->Unsubscribe( |
| 860 PUSH_UNREGISTRATION_REASON_GET_SUBSCRIPTION_STORAGE_CORRUPT, origin, |
| 861 service_worker_registration_id, sender_info, |
| 862 base::Bind(&Core::GetSubscriptionDidUnsubscribe, |
| 863 weak_factory_ui_to_ui_.GetWeakPtr(), callback, status)); |
| 864 |
| 865 RecordGetRegistrationStatus(status); |
786 } | 866 } |
| 867 } |
787 | 868 |
788 PushSubscriptionOptions options; | 869 void PushMessagingManager::Core::GetSubscriptionDidUnsubscribe( |
789 // Chrome rejects subscription requests with userVisibleOnly false, so it must | 870 const GetSubscriptionCallback& callback, |
790 // have been true. TODO(harkness): If Chrome starts accepting silent push | 871 PushGetRegistrationStatus get_status, |
791 // subscriptions with userVisibleOnly false, the bool will need to be stored. | 872 PushUnregistrationStatus unsubscribe_status) { |
792 options.user_visible_only = true; | 873 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
793 options.sender_info = sender_info; | 874 BrowserThread::PostTask( |
794 | 875 BrowserThread::IO, FROM_HERE, |
795 callback.Run(PUSH_GETREGISTRATION_STATUS_SUCCESS, endpoint, options, p256dh, | 876 base::Bind(callback, get_status, base::nullopt /* endpoint */, |
796 auth); | 877 base::nullopt /* options */, base::nullopt /* p256dh */, |
797 | 878 base::nullopt /* auth */)); |
798 RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS); | |
799 } | 879 } |
800 | 880 |
801 // GetPermission methods on both IO and UI threads, merged in order of use from | 881 // GetPermission methods on both IO and UI threads, merged in order of use from |
802 // PushMessagingManager and Core. | 882 // PushMessagingManager and Core. |
803 // ----------------------------------------------------------------------------- | 883 // ----------------------------------------------------------------------------- |
804 | 884 |
805 void PushMessagingManager::GetPermissionStatus( | 885 void PushMessagingManager::GetPermissionStatus( |
806 int64_t service_worker_registration_id, | 886 int64_t service_worker_registration_id, |
807 bool user_visible, | 887 bool user_visible, |
808 const GetPermissionStatusCallback& callback) { | 888 const GetPermissionStatusCallback& callback) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 BrowserThread::PostTask( | 937 BrowserThread::PostTask( |
858 BrowserThread::IO, FROM_HERE, | 938 BrowserThread::IO, FROM_HERE, |
859 base::Bind(callback, blink::WebPushError::ErrorTypeNone, | 939 base::Bind(callback, blink::WebPushError::ErrorTypeNone, |
860 permission_status)); | 940 permission_status)); |
861 } | 941 } |
862 | 942 |
863 // Helper methods on both IO and UI threads, merged from | 943 // Helper methods on both IO and UI threads, merged from |
864 // PushMessagingManager and Core. | 944 // PushMessagingManager and Core. |
865 // ----------------------------------------------------------------------------- | 945 // ----------------------------------------------------------------------------- |
866 | 946 |
867 void PushMessagingManager::Core::GetEncryptionInfoOnUI( | 947 void PushMessagingManager::Core::GetSubscriptionInfoOnUI( |
868 const GURL& origin, | 948 const GURL& origin, |
869 int64_t service_worker_registration_id, | 949 int64_t service_worker_registration_id, |
870 const std::string& sender_id, | 950 const std::string& sender_id, |
871 const PushMessagingService::EncryptionInfoCallback& io_thread_callback) { | 951 const std::string& push_subscription_id, |
| 952 const PushMessagingService::SubscriptionInfoCallback& callback) { |
872 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 953 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
873 PushMessagingService* push_service = service(); | 954 PushMessagingService* push_service = service(); |
874 if (push_service) { | 955 if (!push_service) { |
875 push_service->GetEncryptionInfo( | 956 callback.Run(false /* is_valid */, std::vector<uint8_t>() /* p256dh */, |
876 origin, service_worker_registration_id, sender_id, | 957 std::vector<uint8_t>() /* auth */); |
877 base::Bind(&ForwardEncryptionInfoToIOThreadProxy, io_thread_callback)); | |
878 return; | 958 return; |
879 } | 959 } |
880 | 960 |
881 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 961 push_service->GetSubscriptionInfo(origin, service_worker_registration_id, |
882 base::Bind(io_thread_callback, false /* success */, | 962 sender_id, push_subscription_id, callback); |
883 std::vector<uint8_t>() /* p256dh */, | |
884 std::vector<uint8_t>() /* auth */)); | |
885 } | 963 } |
886 | 964 |
887 GURL PushMessagingManager::CreateEndpoint( | 965 GURL PushMessagingManager::CreateEndpoint( |
888 bool standard_protocol, | 966 bool standard_protocol, |
889 const std::string& subscription_id) const { | 967 const std::string& subscription_id) const { |
890 const GURL& base = | 968 const GURL& base = |
891 standard_protocol ? web_push_protocol_endpoint_ : default_endpoint_; | 969 standard_protocol ? web_push_protocol_endpoint_ : default_endpoint_; |
892 | 970 |
893 return GURL(base.spec() + subscription_id); | 971 return GURL(base.spec() + subscription_id); |
894 } | 972 } |
895 | 973 |
896 PushMessagingService* PushMessagingManager::Core::service() { | 974 PushMessagingService* PushMessagingManager::Core::service() { |
897 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 975 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
898 RenderProcessHost* process_host = | 976 RenderProcessHost* process_host = |
899 RenderProcessHost::FromID(render_process_id_); | 977 RenderProcessHost::FromID(render_process_id_); |
900 return process_host | 978 return process_host |
901 ? process_host->GetBrowserContext()->GetPushMessagingService() | 979 ? process_host->GetBrowserContext()->GetPushMessagingService() |
902 : nullptr; | 980 : nullptr; |
903 } | 981 } |
904 | 982 |
| 983 base::WeakPtr<PushMessagingManager::Core> |
| 984 PushMessagingManager::Core::GetWeakPtrFromIOParentConstructor() { |
| 985 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 986 return weak_factory_ui_to_ui_.GetWeakPtr(); |
| 987 } |
| 988 |
905 } // namespace content | 989 } // namespace content |
OLD | NEW |