Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: content/browser/push_messaging/push_messaging_manager.cc

Issue 2697793004: Push API: Validate storage before returning cached subscriptions (Closed)
Patch Set: Fix include Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/push_messaging/push_messaging_manager.h ('k') | content/child/push_messaging/push_provider.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698