 Chromium Code Reviews
 Chromium Code Reviews Issue 2697793004:
  Push API: Validate storage before returning cached subscriptions  (Closed)
    
  
    Issue 2697793004:
  Push API: Validate storage before returning cached subscriptions  (Closed) 
  | 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_message_filter.h" | 5 #include "content/browser/push_messaging/push_messaging_message_filter.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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 | 44 | 
| 45 namespace { | 45 namespace { | 
| 46 | 46 | 
| 47 // Chrome currently does not support the Push API in incognito. | 47 // Chrome currently does not support the Push API in incognito. | 
| 48 const char kIncognitoPushUnsupportedMessage[] = | 48 const char kIncognitoPushUnsupportedMessage[] = | 
| 49 "Chrome currently does not support the Push API in incognito mode " | 49 "Chrome currently does not support the Push API in incognito mode " | 
| 50 "(https://crbug.com/401439). There is deliberately no way to " | 50 "(https://crbug.com/401439). There is deliberately no way to " | 
| 51 "feature-detect this, since incognito mode needs to be undetectable by " | 51 "feature-detect this, since incognito mode needs to be undetectable by " | 
| 52 "websites."; | 52 "websites."; | 
| 53 | 53 | 
| 54 // These UMA methods are only called from IO thread, but it would be acceptable | 54 // These UMA methods are called from the IO and/or UI threads. Racey but ok, see | 
| 55 // (even though slightly racy) to call them from UI thread as well, see | |
| 56 // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CW AXJJ1kJ | 55 // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CW AXJJ1kJ | 
| 57 void RecordRegistrationStatus(PushRegistrationStatus status) { | 56 void RecordRegistrationStatus(PushRegistrationStatus status) { | 
| 58 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || | 
| 58 BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 59 UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status, | 59 UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status, | 
| 60 PUSH_REGISTRATION_STATUS_LAST + 1); | 60 PUSH_REGISTRATION_STATUS_LAST + 1); | 
| 61 } | 61 } | 
| 62 | |
| 63 void RecordUnregistrationStatus(PushUnregistrationStatus status) { | 62 void RecordUnregistrationStatus(PushUnregistrationStatus status) { | 
| 64 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 63 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 65 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status, | 64 UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status, | 
| 66 PUSH_UNREGISTRATION_STATUS_LAST + 1); | 65 PUSH_UNREGISTRATION_STATUS_LAST + 1); | 
| 67 } | 66 } | 
| 68 | |
| 69 void RecordGetRegistrationStatus(PushGetRegistrationStatus status) { | 67 void RecordGetRegistrationStatus(PushGetRegistrationStatus status) { | 
| 70 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || | 
| 69 BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 71 UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status, | 70 UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status, | 
| 72 PUSH_GETREGISTRATION_STATUS_LAST + 1); | 71 PUSH_GETREGISTRATION_STATUS_LAST + 1); | 
| 73 } | 72 } | 
| 74 | 73 | 
| 75 // Curries the |success| and |p256dh| parameters over to |callback| and | 74 void UnregisterCallbackToClosure(const base::Closure& closure, | 
| 76 // posts a task to invoke |callback| on the IO thread. | 75 PushUnregistrationStatus status) { | 
| 77 void ForwardEncryptionInfoToIOThreadProxy( | 76 DCHECK(!closure.is_null()); | 
| 78 const PushMessagingService::EncryptionInfoCallback& callback, | 77 closure.Run(); | 
| 79 bool success, | |
| 80 const std::vector<uint8_t>& p256dh, | |
| 81 const std::vector<uint8_t>& auth) { | |
| 82 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 83 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 84 base::Bind(callback, success, p256dh, auth)); | |
| 85 } | 78 } | 
| 86 | 79 | 
| 87 // Returns whether |sender_info| contains a valid application server key, that | 80 // Returns whether |sender_info| contains a valid application server key, that | 
| 88 // is, a NIST P-256 public key in uncompressed format. | 81 // is, a NIST P-256 public key in uncompressed format. | 
| 89 bool IsApplicationServerKey(const std::string& sender_info) { | 82 bool IsApplicationServerKey(const std::string& sender_info) { | 
| 90 return sender_info.size() == 65 && sender_info[0] == 0x04; | 83 return sender_info.size() == 65 && sender_info[0] == 0x04; | 
| 91 } | 84 } | 
| 92 | 85 | 
| 93 // Returns sender_info if non-empty, otherwise checks if stored_sender_id | 86 // Returns sender_info if non-empty, otherwise checks if stored_sender_id | 
| 94 // may be used as a fallback and if so, returns stored_sender_id instead. | 87 // may be used as a fallback and if so, returns stored_sender_id instead. | 
| (...skipping 28 matching lines...) Expand all Loading... | |
| 123 }; | 116 }; | 
| 124 | 117 | 
| 125 // Inner core of this message filter which lives on the UI thread. | 118 // Inner core of this message filter which lives on the UI thread. | 
| 126 class PushMessagingMessageFilter::Core { | 119 class PushMessagingMessageFilter::Core { | 
| 127 public: | 120 public: | 
| 128 Core(const base::WeakPtr<PushMessagingMessageFilter>& io_parent, | 121 Core(const base::WeakPtr<PushMessagingMessageFilter>& io_parent, | 
| 129 int render_process_id); | 122 int render_process_id); | 
| 130 | 123 | 
| 131 // Public Register methods on UI thread -------------------------------------- | 124 // Public Register methods on UI thread -------------------------------------- | 
| 132 | 125 | 
| 126 // Callback called on UI thread. | |
| 127 void SubscribeDidGetInfoOnUI(const RegisterData& data, | |
| 128 const std::string& push_subscription_id, | |
| 129 const std::string& sender_id, | |
| 130 bool is_valid, | |
| 131 const std::vector<uint8_t>& p256dh, | |
| 132 const std::vector<uint8_t>& auth); | |
| 133 | |
| 133 // Called via PostTask from IO thread. | 134 // Called via PostTask from IO thread. | 
| 134 void RegisterOnUI(const RegisterData& data); | 135 void RegisterOnUI(const RegisterData& data); | 
| 135 | 136 | 
| 136 // Public Unregister methods on UI thread ------------------------------------ | 137 // Public Unregister methods on UI thread ------------------------------------ | 
| 137 | 138 | 
| 138 // Called via PostTask from IO thread. | 139 // Called via PostTask from IO thread. | 
| 139 void UnregisterFromService(int request_id, | 140 void UnregisterFromService(int request_id, | 
| 140 int64_t service_worker_registration_id, | 141 int64_t service_worker_registration_id, | 
| 141 const GURL& requesting_origin, | 142 const GURL& requesting_origin, | 
| 142 const std::string& sender_id); | 143 const std::string& sender_id); | 
| 143 | 144 | 
| 145 // Public GetSubscription methods on UI thread ------------------------------- | |
| 146 | |
| 147 // Callback called on UI thread. | |
| 148 void GetSubscriptionDidGetInfoOnUI(int request_id, | |
| 149 const GURL& origin, | |
| 150 int64_t service_worker_registration_id, | |
| 151 const GURL& endpoint, | |
| 152 const std::string& sender_info, | |
| 153 bool is_valid, | |
| 154 const std::vector<uint8_t>& p256dh, | |
| 155 const std::vector<uint8_t>& auth); | |
| 156 | |
| 157 // Callback called on UI thread. | |
| 158 void GetSubscriptionDidUnsubscribe( | |
| 159 int request_id, | |
| 160 PushGetRegistrationStatus get_status, | |
| 161 PushUnregistrationStatus unsubscribe_status); | |
| 162 | |
| 144 // Public GetPermission methods on UI thread --------------------------------- | 163 // Public GetPermission methods on UI thread --------------------------------- | 
| 145 | 164 | 
| 146 // Called via PostTask from IO thread. | 165 // Called via PostTask from IO thread. | 
| 147 void GetPermissionStatusOnUI(const GURL& requesting_origin, | 166 void GetPermissionStatusOnUI(const GURL& requesting_origin, | 
| 148 bool user_visible, | 167 bool user_visible, | 
| 149 int request_id); | 168 int request_id); | 
| 150 | 169 | 
| 151 // Public helper methods on UI thread ---------------------------------------- | 170 // Public helper methods on UI thread ---------------------------------------- | 
| 152 | 171 | 
| 153 // Called via PostTask from IO thread. The |io_thread_callback| callback | 172 // Called via PostTask from IO thread. |callback| will be run on UI thread. | 
| 154 // will be invoked on the IO thread. | 173 void GetSubscriptionInfoOnUI( | 
| 155 void GetEncryptionInfoOnUI( | |
| 156 const GURL& origin, | 174 const GURL& origin, | 
| 157 int64_t service_worker_registration_id, | 175 int64_t service_worker_registration_id, | 
| 158 const std::string& sender_id, | 176 const std::string& sender_id, | 
| 159 const PushMessagingService::EncryptionInfoCallback& io_thread_callback); | 177 const std::string& push_subscription_id, | 
| 178 const PushMessagingService::SubscriptionInfoCallback& callback); | |
| 160 | 179 | 
| 161 // Called (directly) from both the UI and IO threads. | 180 // Called (directly) from both the UI and IO threads. | 
| 162 bool is_incognito() const { return is_incognito_; } | 181 bool is_incognito() const { return is_incognito_; } | 
| 163 | 182 | 
| 164 // Returns a push messaging service. May return null. | 183 // Returns a push messaging service. May return null. | 
| 165 PushMessagingService* service(); | 184 PushMessagingService* service(); | 
| 166 | 185 | 
| 186 // Returns a weak ptr. Must only be called from the outer class's constructor. | |
| 187 base::WeakPtr<Core> GetWeakPtrFromIOParentConstructor(); | |
| 188 | |
| 167 private: | 189 private: | 
| 168 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 190 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 
| 169 friend class base::DeleteHelper<Core>; | 191 friend class base::DeleteHelper<Core>; | 
| 170 | 192 | 
| 171 ~Core(); | 193 ~Core(); | 
| 172 | 194 | 
| 173 // Private Register methods on UI thread ------------------------------------- | 195 // Private Register methods on UI thread ------------------------------------- | 
| 174 | 196 | 
| 175 void DidRequestPermissionInIncognito(const RegisterData& data, | 197 void DidRequestPermissionInIncognito(const RegisterData& data, | 
| 176 blink::mojom::PermissionStatus status); | 198 blink::mojom::PermissionStatus status); | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 : BrowserMessageFilter(PushMessagingMsgStart), | 254 : BrowserMessageFilter(PushMessagingMsgStart), | 
| 233 service_worker_context_(service_worker_context), | 255 service_worker_context_(service_worker_context), | 
| 234 weak_factory_io_to_io_(this) { | 256 weak_factory_io_to_io_(this) { | 
| 235 // Although this class is used only on the IO thread, it is constructed on UI. | 257 // Although this class is used only on the IO thread, it is constructed on UI. | 
| 236 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 258 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 237 // Normally, it would be unsafe to obtain a weak pointer from the UI thread, | 259 // Normally, it would be unsafe to obtain a weak pointer from the UI thread, | 
| 238 // but it's ok in the constructor since we can't be destroyed before our | 260 // but it's ok in the constructor since we can't be destroyed before our | 
| 239 // constructor finishes. | 261 // constructor finishes. | 
| 240 ui_core_.reset( | 262 ui_core_.reset( | 
| 241 new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); | 263 new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); | 
| 264 ui_core_weak_ptr_ = ui_core_->GetWeakPtrFromIOParentConstructor(); | |
| 242 | 265 | 
| 243 PushMessagingService* service = ui_core_->service(); | 266 PushMessagingService* service = ui_core_->service(); | 
| 244 service_available_ = !!service; | 267 service_available_ = !!service; | 
| 245 | 268 | 
| 246 if (service_available_) { | 269 if (service_available_) { | 
| 247 default_endpoint_ = service->GetEndpoint(false /* standard_protocol */); | 270 default_endpoint_ = service->GetEndpoint(false /* standard_protocol */); | 
| 248 web_push_protocol_endpoint_ = | 271 web_push_protocol_endpoint_ = | 
| 249 service->GetEndpoint(true /* standard_protocol */); | 272 service->GetEndpoint(true /* standard_protocol */); | 
| 250 } | 273 } | 
| 251 } | 274 } | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 weak_factory_io_to_io_.GetWeakPtr(), data)); | 332 weak_factory_io_to_io_.GetWeakPtr(), data)); | 
| 310 } | 333 } | 
| 311 | 334 | 
| 312 void PushMessagingMessageFilter::DidCheckForExistingRegistration( | 335 void PushMessagingMessageFilter::DidCheckForExistingRegistration( | 
| 313 const RegisterData& data, | 336 const RegisterData& data, | 
| 314 const std::vector<std::string>& push_registration_id_and_sender_id, | 337 const std::vector<std::string>& push_registration_id_and_sender_id, | 
| 315 ServiceWorkerStatusCode service_worker_status) { | 338 ServiceWorkerStatusCode service_worker_status) { | 
| 316 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 339 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 317 if (service_worker_status == SERVICE_WORKER_OK) { | 340 if (service_worker_status == SERVICE_WORKER_OK) { | 
| 318 DCHECK_EQ(2u, push_registration_id_and_sender_id.size()); | 341 DCHECK_EQ(2u, push_registration_id_and_sender_id.size()); | 
| 319 const auto& push_registration_id = push_registration_id_and_sender_id[0]; | 342 const auto& push_subscription_id = push_registration_id_and_sender_id[0]; | 
| 320 const auto& stored_sender_id = push_registration_id_and_sender_id[1]; | 343 const auto& stored_sender_id = push_registration_id_and_sender_id[1]; | 
| 321 std::string fixed_sender_id = | 344 std::string fixed_sender_id = | 
| 322 FixSenderInfo(data.options.sender_info, stored_sender_id); | 345 FixSenderInfo(data.options.sender_info, stored_sender_id); | 
| 323 if (fixed_sender_id.empty()) { | 346 if (fixed_sender_id.empty()) { | 
| 324 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 347 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 
| 325 return; | 348 return; | 
| 326 } | 349 } | 
| 327 if (fixed_sender_id != stored_sender_id) { | 350 if (fixed_sender_id != stored_sender_id) { | 
| 328 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SENDER_ID_MISMATCH); | 351 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SENDER_ID_MISMATCH); | 
| 329 return; | 352 return; | 
| 330 } | 353 } | 
| 331 auto callback = base::Bind( | |
| 332 &PushMessagingMessageFilter::DidGetEncryptionKeys, | |
| 333 weak_factory_io_to_io_.GetWeakPtr(), data, push_registration_id); | |
| 334 BrowserThread::PostTask( | 354 BrowserThread::PostTask( | 
| 335 BrowserThread::UI, FROM_HERE, | 355 BrowserThread::UI, FROM_HERE, | 
| 336 base::Bind(&Core::GetEncryptionInfoOnUI, | 356 base::Bind(&Core::GetSubscriptionInfoOnUI, | 
| 337 base::Unretained(ui_core_.get()), data.requesting_origin, | 357 base::Unretained(ui_core_.get()), data.requesting_origin, | 
| 338 data.service_worker_registration_id, fixed_sender_id, | 358 data.service_worker_registration_id, fixed_sender_id, | 
| 339 callback)); | 359 push_subscription_id, | 
| 360 base::Bind(&Core::SubscribeDidGetInfoOnUI, ui_core_weak_ptr_, | |
| 361 data, push_subscription_id, fixed_sender_id))); | |
| 340 return; | 362 return; | 
| 341 } | 363 } | 
| 342 // TODO(johnme): The spec allows the register algorithm to reject with an | 364 // TODO(johnme): The spec allows the register algorithm to reject with an | 
| 343 // AbortError when accessing storage fails. Perhaps we should do that if | 365 // AbortError when accessing storage fails. Perhaps we should do that if | 
| 344 // service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND instead of | 366 // service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND instead of | 
| 345 // attempting to do a fresh registration? | 367 // attempting to do a fresh registration? | 
| 346 // https://w3c.github.io/push-api/#widl-PushRegistrationManager-register-Promi se-PushRegistration | 368 // https://w3c.github.io/push-api/#widl-PushRegistrationManager-register-Promi se-PushRegistration | 
| 347 if (!data.options.sender_info.empty()) { | 369 if (!data.options.sender_info.empty()) { | 
| 348 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 370 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 
| 349 base::Bind(&Core::RegisterOnUI, | 371 base::Bind(&Core::RegisterOnUI, | 
| 350 base::Unretained(ui_core_.get()), data)); | 372 base::Unretained(ui_core_.get()), data)); | 
| 351 } else { | 373 } else { | 
| 352 // There is no existing registration and the sender_info passed in was | 374 // There is no existing registration and the sender_info passed in was | 
| 353 // empty, but perhaps there is a stored sender id we can use. | 375 // empty, but perhaps there is a stored sender id we can use. | 
| 354 service_worker_context_->GetRegistrationUserData( | 376 service_worker_context_->GetRegistrationUserData( | 
| 355 data.service_worker_registration_id, {kPushSenderIdServiceWorkerKey}, | 377 data.service_worker_registration_id, {kPushSenderIdServiceWorkerKey}, | 
| 356 base::Bind(&PushMessagingMessageFilter::DidGetSenderIdFromStorage, | 378 base::Bind(&PushMessagingMessageFilter::DidGetSenderIdFromStorage, | 
| 357 weak_factory_io_to_io_.GetWeakPtr(), data)); | 379 weak_factory_io_to_io_.GetWeakPtr(), data)); | 
| 358 } | 380 } | 
| 359 } | 381 } | 
| 360 | 382 | 
| 361 void PushMessagingMessageFilter::DidGetEncryptionKeys( | 383 void PushMessagingMessageFilter::Core::SubscribeDidGetInfoOnUI( | 
| 362 const RegisterData& data, | 384 const RegisterData& data, | 
| 363 const std::string& push_registration_id, | 385 const std::string& push_subscription_id, | 
| 364 bool success, | 386 const std::string& sender_id, | 
| 387 bool is_valid, | |
| 365 const std::vector<uint8_t>& p256dh, | 388 const std::vector<uint8_t>& p256dh, | 
| 366 const std::vector<uint8_t>& auth) { | 389 const std::vector<uint8_t>& auth) { | 
| 367 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 390 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 368 if (!success) { | 391 if (is_valid) { | 
| 369 SendSubscriptionError( | 392 BrowserThread::PostTask( | 
| 370 data, PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE); | 393 BrowserThread::IO, FROM_HERE, | 
| 371 return; | 394 base::Bind(&PushMessagingMessageFilter::SendSubscriptionSuccess, | 
| 395 io_parent_, data, | |
| 396 PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, | |
| 397 push_subscription_id, p256dh, auth)); | |
| 398 } else { | |
| 399 // Uh-oh! Although there was a cached subscription in the Service Worker | |
| 400 // database, it did not have matching counterparts in the | |
| 401 // PushMessagingAppIdentifier map and/or GCM Store. Unsubscribe and | |
| 402 // re-subscribe to fix this inconsistency. | |
| 403 | |
| 404 // Consider this subscription attempt to have failed. The re-subscribe will | |
| 405 // be logged to UMA as a separate subscription attempt. | |
| 406 RecordRegistrationStatus(PUSH_REGISTRATION_STATUS_STORAGE_CORRUPT); | |
| 407 | |
| 408 PushMessagingService* push_service = service(); | |
| 409 DCHECK(push_service); // NOT_FOUND response can only come from service. | |
| 
Peter Beverloo
2017/03/20 23:50:13
Core::GetSubscriptionInfoOnUI specifically returns
 
johnme
2017/03/30 18:36:38
Hmm yeah. In practice it shouldn't be possible to
 | |
| 410 push_service->Unsubscribe( | |
| 411 PUSH_UNREGISTRATION_REASON_SUBSCRIBE_STORAGE_CORRUPT, | |
| 412 data.requesting_origin, data.service_worker_registration_id, sender_id, | |
| 413 base::Bind(&UnregisterCallbackToClosure, | |
| 414 base::Bind(IgnoreResult(&BrowserThread::PostTask), | |
| 415 BrowserThread::IO, FROM_HERE, | |
| 416 base::Bind(&PushMessagingMessageFilter:: | |
| 417 DidCheckForExistingRegistration, | |
| 418 io_parent_, data, | |
| 419 // push_registration_id_and_sender_id | |
| 420 std::vector<std::string>(), | |
| 421 SERVICE_WORKER_ERROR_NOT_FOUND)))); | |
| 
Peter Beverloo
2017/03/20 23:50:13
This is deep. Like, literally. Can we maybe make i
 
johnme
2017/03/30 18:36:38
Done.
 | |
| 372 } | 422 } | 
| 373 | |
| 374 SendSubscriptionSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, | |
| 375 push_registration_id, p256dh, auth); | |
| 376 } | 423 } | 
| 377 | 424 | 
| 378 void PushMessagingMessageFilter::DidGetSenderIdFromStorage( | 425 void PushMessagingMessageFilter::DidGetSenderIdFromStorage( | 
| 379 const RegisterData& data, | 426 const RegisterData& data, | 
| 380 const std::vector<std::string>& stored_sender_id, | 427 const std::vector<std::string>& stored_sender_id, | 
| 381 ServiceWorkerStatusCode service_worker_status) { | 428 ServiceWorkerStatusCode service_worker_status) { | 
| 382 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 429 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 383 if (service_worker_status != SERVICE_WORKER_OK) { | 430 if (service_worker_status != SERVICE_WORKER_OK) { | 
| 384 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 431 SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 
| 385 return; | 432 return; | 
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 DCHECK(!is_incognito()); | 675 DCHECK(!is_incognito()); | 
| 629 BrowserThread::PostTask( | 676 BrowserThread::PostTask( | 
| 630 BrowserThread::IO, FROM_HERE, | 677 BrowserThread::IO, FROM_HERE, | 
| 631 base::Bind(&PushMessagingMessageFilter::DidUnregister, io_parent_, | 678 base::Bind(&PushMessagingMessageFilter::DidUnregister, io_parent_, | 
| 632 request_id, | 679 request_id, | 
| 633 PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); | 680 PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); | 
| 634 return; | 681 return; | 
| 635 } | 682 } | 
| 636 | 683 | 
| 637 push_service->Unsubscribe( | 684 push_service->Unsubscribe( | 
| 638 requesting_origin, service_worker_registration_id, sender_id, | 685 PUSH_UNREGISTRATION_REASON_JAVASCRIPT_API, requesting_origin, | 
| 686 service_worker_registration_id, sender_id, | |
| 639 base::Bind(&Core::DidUnregisterFromService, | 687 base::Bind(&Core::DidUnregisterFromService, | 
| 640 weak_factory_ui_to_ui_.GetWeakPtr(), request_id, | 688 weak_factory_ui_to_ui_.GetWeakPtr(), request_id, | 
| 641 service_worker_registration_id)); | 689 service_worker_registration_id)); | 
| 642 } | 690 } | 
| 643 | 691 | 
| 644 void PushMessagingMessageFilter::Core::DidUnregisterFromService( | 692 void PushMessagingMessageFilter::Core::DidUnregisterFromService( | 
| 645 int request_id, | 693 int request_id, | 
| 646 int64_t service_worker_registration_id, | 694 int64_t service_worker_registration_id, | 
| 647 PushUnregistrationStatus unregistration_status) { | 695 PushUnregistrationStatus unregistration_status) { | 
| 648 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 696 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 int request_id, | 750 int request_id, | 
| 703 int64_t service_worker_registration_id, | 751 int64_t service_worker_registration_id, | 
| 704 const std::vector<std::string>& push_subscription_id_and_sender_info, | 752 const std::vector<std::string>& push_subscription_id_and_sender_info, | 
| 705 ServiceWorkerStatusCode service_worker_status) { | 753 ServiceWorkerStatusCode service_worker_status) { | 
| 706 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 754 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 707 PushGetRegistrationStatus get_status = | 755 PushGetRegistrationStatus get_status = | 
| 708 PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 756 PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 
| 709 switch (service_worker_status) { | 757 switch (service_worker_status) { | 
| 710 case SERVICE_WORKER_OK: { | 758 case SERVICE_WORKER_OK: { | 
| 711 DCHECK_EQ(2u, push_subscription_id_and_sender_info.size()); | 759 DCHECK_EQ(2u, push_subscription_id_and_sender_info.size()); | 
| 760 const std::string& push_subscription_id = | |
| 761 push_subscription_id_and_sender_info[0]; | |
| 762 const std::string& sender_info = push_subscription_id_and_sender_info[1]; | |
| 712 | 763 | 
| 713 if (!service_available_) { | 764 if (!service_available_) { | 
| 714 // Return not found in incognito mode, so websites can't detect it. | 765 // Return not found in incognito mode, so websites can't detect it. | 
| 715 get_status = | 766 get_status = | 
| 716 ui_core_->is_incognito() | 767 ui_core_->is_incognito() | 
| 717 ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND | 768 ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND | 
| 718 : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; | 769 : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; | 
| 719 break; | 770 break; | 
| 720 } | 771 } | 
| 721 | 772 | 
| 722 ServiceWorkerRegistration* registration = | 773 ServiceWorkerRegistration* registration = | 
| 723 service_worker_context_->GetLiveRegistration( | 774 service_worker_context_->GetLiveRegistration( | 
| 724 service_worker_registration_id); | 775 service_worker_registration_id); | 
| 725 const GURL origin = registration->pattern().GetOrigin(); | 776 const GURL origin = registration->pattern().GetOrigin(); | 
| 726 | 777 | 
| 727 const bool uses_standard_protocol = | 778 const bool uses_standard_protocol = IsApplicationServerKey(sender_info); | 
| 728 IsApplicationServerKey(push_subscription_id_and_sender_info[1]); | 779 const GURL endpoint = | 
| 729 const GURL endpoint = CreateEndpoint( | 780 CreateEndpoint(uses_standard_protocol, push_subscription_id); | 
| 730 uses_standard_protocol, push_subscription_id_and_sender_info[0]); | |
| 731 | |
| 732 auto callback = | |
| 733 base::Bind(&PushMessagingMessageFilter::DidGetSubscriptionKeys, | |
| 734 weak_factory_io_to_io_.GetWeakPtr(), request_id, endpoint, | |
| 735 push_subscription_id_and_sender_info[1]); | |
| 736 | 781 | 
| 737 BrowserThread::PostTask( | 782 BrowserThread::PostTask( | 
| 738 BrowserThread::UI, FROM_HERE, | 783 BrowserThread::UI, FROM_HERE, | 
| 739 base::Bind(&Core::GetEncryptionInfoOnUI, | 784 base::Bind(&Core::GetSubscriptionInfoOnUI, | 
| 740 base::Unretained(ui_core_.get()), origin, | 785 base::Unretained(ui_core_.get()), origin, | 
| 741 service_worker_registration_id, | 786 service_worker_registration_id, sender_info, | 
| 742 push_subscription_id_and_sender_info[1], callback)); | 787 push_subscription_id, | 
| 788 base::Bind(&Core::GetSubscriptionDidGetInfoOnUI, | |
| 789 ui_core_weak_ptr_, request_id, origin, | |
| 790 service_worker_registration_id, endpoint, | |
| 791 sender_info))); | |
| 743 | 792 | 
| 744 return; | 793 return; | 
| 745 } | 794 } | 
| 746 case SERVICE_WORKER_ERROR_NOT_FOUND: { | 795 case SERVICE_WORKER_ERROR_NOT_FOUND: { | 
| 747 get_status = PUSH_GETREGISTRATION_STATUS_REGISTRATION_NOT_FOUND; | 796 get_status = PUSH_GETREGISTRATION_STATUS_REGISTRATION_NOT_FOUND; | 
| 748 break; | 797 break; | 
| 749 } | 798 } | 
| 750 case SERVICE_WORKER_ERROR_FAILED: { | 799 case SERVICE_WORKER_ERROR_FAILED: { | 
| 751 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 800 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 
| 752 break; | 801 break; | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 771 NOTREACHED() << "Got unexpected error code: " << service_worker_status | 820 NOTREACHED() << "Got unexpected error code: " << service_worker_status | 
| 772 << " " << ServiceWorkerStatusToString(service_worker_status); | 821 << " " << ServiceWorkerStatusToString(service_worker_status); | 
| 773 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 822 get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 
| 774 break; | 823 break; | 
| 775 } | 824 } | 
| 776 } | 825 } | 
| 777 Send(new PushMessagingMsg_GetSubscriptionError(request_id, get_status)); | 826 Send(new PushMessagingMsg_GetSubscriptionError(request_id, get_status)); | 
| 778 RecordGetRegistrationStatus(get_status); | 827 RecordGetRegistrationStatus(get_status); | 
| 779 } | 828 } | 
| 780 | 829 | 
| 781 void PushMessagingMessageFilter::DidGetSubscriptionKeys( | 830 void PushMessagingMessageFilter::Core::GetSubscriptionDidGetInfoOnUI( | 
| 782 int request_id, | 831 int request_id, | 
| 832 const GURL& origin, | |
| 833 int64_t service_worker_registration_id, | |
| 783 const GURL& endpoint, | 834 const GURL& endpoint, | 
| 784 const std::string& sender_info, | 835 const std::string& sender_info, | 
| 785 bool success, | 836 bool is_valid, | 
| 786 const std::vector<uint8_t>& p256dh, | 837 const std::vector<uint8_t>& p256dh, | 
| 787 const std::vector<uint8_t>& auth) { | 838 const std::vector<uint8_t>& auth) { | 
| 788 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 839 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 789 if (!success) { | 840 if (is_valid) { | 
| 841 PushSubscriptionOptions options; | |
| 842 // Chrome rejects subscription requests with userVisibleOnly false, so it | |
| 843 // must have been true. TODO(harkness): If Chrome starts accepting silent | |
| 844 // push subscriptions with userVisibleOnly false, the bool will need to be | |
| 845 // stored. | |
| 846 options.user_visible_only = true; | |
| 847 options.sender_info = sender_info; | |
| 848 | |
| 849 Send(new PushMessagingMsg_GetSubscriptionSuccess(request_id, endpoint, | |
| 850 options, p256dh, auth)); | |
| 851 | |
| 852 RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS); | |
| 853 } else { | |
| 854 // Uh-oh! Although there was a cached subscription in the Service Worker | |
| 855 // database, it did not have matching counterparts in the | |
| 856 // PushMessagingAppIdentifier map and/or GCM Store. Unsubscribe to fix this | |
| 857 // inconsistency. | |
| 790 PushGetRegistrationStatus status = | 858 PushGetRegistrationStatus status = | 
| 791 PUSH_GETREGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE; | 859 PUSH_GETREGISTRATION_STATUS_STORAGE_CORRUPT; | 
| 792 | 860 | 
| 793 Send(new PushMessagingMsg_GetSubscriptionError(request_id, status)); | 861 PushMessagingService* push_service = service(); | 
| 862 DCHECK(push_service); // NOT_FOUND response can only come from service. | |
| 863 push_service->Unsubscribe( | |
| 864 PUSH_UNREGISTRATION_REASON_GET_SUBSCRIPTION_STORAGE_CORRUPT, origin, | |
| 865 service_worker_registration_id, sender_info, | |
| 866 base::Bind(&Core::GetSubscriptionDidUnsubscribe, | |
| 867 weak_factory_ui_to_ui_.GetWeakPtr(), request_id, status)); | |
| 794 | 868 | 
| 795 RecordGetRegistrationStatus(status); | 869 RecordGetRegistrationStatus(status); | 
| 796 return; | |
| 797 } | 870 } | 
| 871 } | |
| 798 | 872 | 
| 799 PushSubscriptionOptions options; | 873 void PushMessagingMessageFilter::Core::GetSubscriptionDidUnsubscribe( | 
| 800 // Chrome rejects subscription requests with userVisibleOnly false, so it must | 874 int request_id, | 
| 801 // have been true. TODO(harkness): If Chrome starts accepting silent push | 875 PushGetRegistrationStatus get_status, | 
| 802 // subscriptions with userVisibleOnly false, the bool will need to be stored. | 876 PushUnregistrationStatus unsubscribe_status) { | 
| 803 options.user_visible_only = true; | 877 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 804 options.sender_info = sender_info; | 878 Send(new PushMessagingMsg_GetSubscriptionError(request_id, get_status)); | 
| 805 | |
| 806 Send(new PushMessagingMsg_GetSubscriptionSuccess(request_id, endpoint, | |
| 807 options, p256dh, auth)); | |
| 808 | |
| 809 RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS); | |
| 810 } | 879 } | 
| 811 | 880 | 
| 812 // 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 | 
| 813 // PushMessagingMessageFilter and Core. | 882 // PushMessagingMessageFilter and Core. | 
| 814 // ----------------------------------------------------------------------------- | 883 // ----------------------------------------------------------------------------- | 
| 815 | 884 | 
| 816 void PushMessagingMessageFilter::OnGetPermissionStatus( | 885 void PushMessagingMessageFilter::OnGetPermissionStatus( | 
| 817 int request_id, | 886 int request_id, | 
| 818 int64_t service_worker_registration_id, | 887 int64_t service_worker_registration_id, | 
| 819 bool user_visible) { | 888 bool user_visible) { | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 857 return; | 926 return; | 
| 858 } | 927 } | 
| 859 Send(new PushMessagingMsg_GetPermissionStatusSuccess(request_id, | 928 Send(new PushMessagingMsg_GetPermissionStatusSuccess(request_id, | 
| 860 permission_status)); | 929 permission_status)); | 
| 861 } | 930 } | 
| 862 | 931 | 
| 863 // Helper methods on both IO and UI threads, merged from | 932 // Helper methods on both IO and UI threads, merged from | 
| 864 // PushMessagingMessageFilter and Core. | 933 // PushMessagingMessageFilter and Core. | 
| 865 // ----------------------------------------------------------------------------- | 934 // ----------------------------------------------------------------------------- | 
| 866 | 935 | 
| 867 void PushMessagingMessageFilter::Core::GetEncryptionInfoOnUI( | 936 void PushMessagingMessageFilter::Core::GetSubscriptionInfoOnUI( | 
| 868 const GURL& origin, | 937 const GURL& origin, | 
| 869 int64_t service_worker_registration_id, | 938 int64_t service_worker_registration_id, | 
| 870 const std::string& sender_id, | 939 const std::string& sender_id, | 
| 871 const PushMessagingService::EncryptionInfoCallback& io_thread_callback) { | 940 const std::string& push_subscription_id, | 
| 941 const PushMessagingService::SubscriptionInfoCallback& callback) { | |
| 872 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 942 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 873 PushMessagingService* push_service = service(); | 943 PushMessagingService* push_service = service(); | 
| 874 if (push_service) { | 944 if (!push_service) { | 
| 875 push_service->GetEncryptionInfo( | 945 callback.Run(false /* is_valid */, std::vector<uint8_t>() /* p256dh */, | 
| 876 origin, service_worker_registration_id, sender_id, | 946 std::vector<uint8_t>() /* auth */); | 
| 877 base::Bind(&ForwardEncryptionInfoToIOThreadProxy, io_thread_callback)); | |
| 878 return; | 947 return; | 
| 879 } | 948 } | 
| 880 | 949 | 
| 881 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 950 push_service->GetSubscriptionInfo(origin, service_worker_registration_id, | 
| 882 base::Bind(io_thread_callback, false /* success */, | 951 sender_id, push_subscription_id, callback); | 
| 883 std::vector<uint8_t>() /* p256dh */, | |
| 884 std::vector<uint8_t>() /* auth */)); | |
| 885 } | 952 } | 
| 886 | 953 | 
| 887 void PushMessagingMessageFilter::Core::Send(IPC::Message* message) { | 954 void PushMessagingMessageFilter::Core::Send(IPC::Message* message) { | 
| 888 BrowserThread::PostTask( | 955 BrowserThread::PostTask( | 
| 889 BrowserThread::IO, FROM_HERE, | 956 BrowserThread::IO, FROM_HERE, | 
| 890 base::Bind(&PushMessagingMessageFilter::SendIPC, io_parent_, | 957 base::Bind(&PushMessagingMessageFilter::SendIPC, io_parent_, | 
| 891 base::Passed(base::WrapUnique(message)))); | 958 base::Passed(base::WrapUnique(message)))); | 
| 892 } | 959 } | 
| 893 | 960 | 
| 894 void PushMessagingMessageFilter::SendIPC( | 961 void PushMessagingMessageFilter::SendIPC( | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 907 | 974 | 
| 908 PushMessagingService* PushMessagingMessageFilter::Core::service() { | 975 PushMessagingService* PushMessagingMessageFilter::Core::service() { | 
| 909 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 976 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 910 RenderProcessHost* process_host = | 977 RenderProcessHost* process_host = | 
| 911 RenderProcessHost::FromID(render_process_id_); | 978 RenderProcessHost::FromID(render_process_id_); | 
| 912 return process_host | 979 return process_host | 
| 913 ? process_host->GetBrowserContext()->GetPushMessagingService() | 980 ? process_host->GetBrowserContext()->GetPushMessagingService() | 
| 914 : nullptr; | 981 : nullptr; | 
| 915 } | 982 } | 
| 916 | 983 | 
| 984 base::WeakPtr<PushMessagingMessageFilter::Core> | |
| 985 PushMessagingMessageFilter::Core::GetWeakPtrFromIOParentConstructor() { | |
| 
Peter Beverloo
2017/03/20 23:50:13
Would you mind summarising in two sentences or so
 
johnme
2017/03/30 18:36:38
weak_factory_ui_to_ui_ should not be public, as it
 | |
| 986 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 987 return weak_factory_ui_to_ui_.GetWeakPtr(); | |
| 988 } | |
| 989 | |
| 917 } // namespace content | 990 } // namespace content | 
| OLD | NEW |