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

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

Issue 2697793004: Push API: Validate storage before returning cached subscriptions (Closed)
Patch Set: Comment out PUSH_GETREGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE Created 3 years, 10 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_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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698