Chromium Code Reviews| Index: content/browser/push_messaging/push_messaging_message_filter.cc |
| diff --git a/content/browser/push_messaging/push_messaging_message_filter.cc b/content/browser/push_messaging/push_messaging_message_filter.cc |
| index 107b06f337a52e97d5832841472045dc1bd46ddf..4417ed872aa699531fbeae22d4c9de602feaf080 100644 |
| --- a/content/browser/push_messaging/push_messaging_message_filter.cc |
| +++ b/content/browser/push_messaging/push_messaging_message_filter.cc |
| @@ -80,11 +80,10 @@ void ForwardEncryptionInfoToIOThreadProxy( |
| base::Bind(callback, success, p256dh, auth)); |
| } |
| -// Concatenates the subscription id with the endpoint base to create a new |
| -// GURL object containing the endpoint unique to the subscription. |
| -GURL CreatePushEndpoint(const GURL& push_endpoint_base, |
| - const std::string& push_subscription_id) { |
| - return GURL(push_endpoint_base.spec() + "/" + push_subscription_id); |
| +// Returns whether |sender_info| contains a valid application server key, that |
| +// is, a NIST P-256 public key in uncompressed format. |
| +bool IsApplicationServerKey(const std::string& sender_info) { |
|
harkness
2016/04/28 15:21:13
So, we still allow arbitrary formatted server keys
Peter Beverloo
2016/04/28 15:22:50
Yes.
|
| + return sender_info.size() == 65 && sender_info[0] == 0x04; |
| } |
| } // namespace |
| @@ -97,6 +96,7 @@ struct PushMessagingMessageFilter::RegisterData { |
| GURL requesting_origin; |
| int64_t service_worker_registration_id; |
| bool user_visible; |
| + bool uses_standard_protocol; |
| // The following member should only be read if FromDocument() is true. |
| int render_frame_id; |
| }; |
| @@ -185,6 +185,7 @@ PushMessagingMessageFilter::RegisterData::RegisterData() |
| : request_id(0), |
| service_worker_registration_id(0), |
| user_visible(false), |
| + uses_standard_protocol(false), |
| render_frame_id(ChildProcessHost::kInvalidUniqueID) {} |
| bool PushMessagingMessageFilter::RegisterData::FromDocument() const { |
| @@ -218,9 +219,15 @@ PushMessagingMessageFilter::PushMessagingMessageFilter( |
| // constructor finishes. |
| ui_core_.reset( |
| new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); |
| - PushMessagingService* push_service = ui_core_->service(); |
| - if (push_service) |
| - push_endpoint_base_ = push_service->GetPushEndpoint(); |
| + |
| + PushMessagingService* service = ui_core_->service(); |
| + service_available_ = !!service; |
| + |
| + if (service_available_) { |
| + default_endpoint_ = service->GetEndpoint(false /* standard_protocol */); |
| + web_push_protocol_endpoint_ = |
| + service->GetEndpoint(true /* standard_protocol */); |
| + } |
| } |
| PushMessagingMessageFilter::~PushMessagingMessageFilter() {} |
| @@ -262,6 +269,7 @@ void PushMessagingMessageFilter::OnSubscribeFromDocument( |
| data.service_worker_registration_id = service_worker_registration_id; |
| data.render_frame_id = render_frame_id; |
| data.user_visible = options.user_visible_only; |
| + data.uses_standard_protocol = IsApplicationServerKey(options.sender_info); |
| ServiceWorkerRegistration* service_worker_registration = |
| service_worker_context_->GetLiveRegistration( |
| @@ -289,6 +297,7 @@ void PushMessagingMessageFilter::OnSubscribeFromWorker( |
| data.request_id = request_id; |
| data.service_worker_registration_id = service_worker_registration_id; |
| data.user_visible = options.user_visible_only; |
| + data.uses_standard_protocol = IsApplicationServerKey(options.sender_info); |
| ServiceWorkerRegistration* service_worker_registration = |
| service_worker_context_->GetLiveRegistration( |
| @@ -551,23 +560,23 @@ void PushMessagingMessageFilter::SendSubscriptionSuccess( |
| const std::vector<uint8_t>& auth) { |
| // Only called from IO thread, but would be safe to call from UI thread. |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| - if (push_endpoint_base_.is_empty()) { |
| + if (!service_available_) { |
| // This shouldn't be possible in incognito mode, since we've already checked |
| // that we have an existing registration. Hence it's ok to throw an error. |
| DCHECK(!ui_core_->is_incognito()); |
| SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); |
| return; |
| } |
| + |
| + const GURL endpoint = |
| + CreateEndpoint(data.uses_standard_protocol, push_subscription_id); |
| + |
| if (data.FromDocument()) { |
| Send(new PushMessagingMsg_SubscribeFromDocumentSuccess( |
| - data.render_frame_id, data.request_id, |
| - CreatePushEndpoint(push_endpoint_base_, push_subscription_id), p256dh, |
| - auth)); |
| + data.render_frame_id, data.request_id, endpoint, p256dh, auth)); |
| } else { |
| Send(new PushMessagingMsg_SubscribeFromWorkerSuccess( |
| - data.request_id, |
| - CreatePushEndpoint(push_endpoint_base_, push_subscription_id), p256dh, |
| - auth)); |
| + data.request_id, endpoint, p256dh, auth)); |
| } |
| RecordRegistrationStatus(status); |
| } |
| @@ -788,15 +797,37 @@ void PushMessagingMessageFilter::OnGetSubscription( |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| // TODO(johnme): Validate arguments? |
| service_worker_context_->GetRegistrationUserData( |
| + service_worker_registration_id, kPushSenderIdServiceWorkerKey, |
| + base::Bind(&PushMessagingMessageFilter::DidGetSenderInfo, |
| + weak_factory_io_to_io_.GetWeakPtr(), request_id, |
| + service_worker_registration_id)); |
| +} |
| + |
| +void PushMessagingMessageFilter::DidGetSenderInfo( |
| + int request_id, |
| + int64_t service_worker_registration_id, |
| + const std::string& sender_info, |
| + ServiceWorkerStatusCode status) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + if (status != SERVICE_WORKER_OK) { |
| + DidGetSubscription(request_id, service_worker_registration_id, |
| + false /* uses_standard_protocol */, |
| + std::string() /* push_subscription_id */, status); |
| + return; |
| + } |
| + |
| + const bool uses_standard_protocol = IsApplicationServerKey(sender_info); |
| + service_worker_context_->GetRegistrationUserData( |
| service_worker_registration_id, kPushRegistrationIdServiceWorkerKey, |
| base::Bind(&PushMessagingMessageFilter::DidGetSubscription, |
| weak_factory_io_to_io_.GetWeakPtr(), request_id, |
| - service_worker_registration_id)); |
| + service_worker_registration_id, uses_standard_protocol)); |
| } |
| void PushMessagingMessageFilter::DidGetSubscription( |
| int request_id, |
| int64_t service_worker_registration_id, |
| + bool uses_standard_protocol, |
| const std::string& push_subscription_id, |
| ServiceWorkerStatusCode service_worker_status) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| @@ -804,7 +835,7 @@ void PushMessagingMessageFilter::DidGetSubscription( |
| PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; |
| switch (service_worker_status) { |
| case SERVICE_WORKER_OK: { |
| - if (push_endpoint_base_.is_empty()) { |
| + if (!service_available_) { |
| // Return not found in incognito mode, so websites can't detect it. |
| get_status = |
| ui_core_->is_incognito() |
| @@ -819,7 +850,7 @@ void PushMessagingMessageFilter::DidGetSubscription( |
| const GURL origin = registration->pattern().GetOrigin(); |
| const GURL endpoint = |
| - CreatePushEndpoint(push_endpoint_base_, push_subscription_id); |
| + CreateEndpoint(uses_standard_protocol, push_subscription_id); |
| auto callback = |
| base::Bind(&PushMessagingMessageFilter::DidGetSubscriptionKeys, |
| @@ -977,6 +1008,15 @@ void PushMessagingMessageFilter::SendIPC( |
| Send(message.release()); |
| } |
| +GURL PushMessagingMessageFilter::CreateEndpoint( |
| + bool standard_protocol, |
| + const std::string& subscription_id) const { |
| + const GURL& base = |
| + standard_protocol ? web_push_protocol_endpoint_ : default_endpoint_; |
| + |
| + return GURL(base.spec() + subscription_id); |
| +} |
| + |
| PushMessagingService* PushMessagingMessageFilter::Core::service() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| RenderProcessHost* process_host = |