| 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 |