Chromium Code Reviews| Index: content/browser/service_worker/service_worker_dispatcher_host.cc |
| diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc |
| index 978aec5412311b3a389377e31e3973dbce3ccff8..f1033517549950d2c2df6012ae552356b483380b 100644 |
| --- a/content/browser/service_worker/service_worker_dispatcher_host.cc |
| +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc |
| @@ -35,6 +35,7 @@ |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/origin_util.h" |
| #include "ipc/ipc_message_macros.h" |
| +#include "net/http/http_util.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h" |
| #include "url/gurl.h" |
| @@ -55,6 +56,8 @@ const char kEnableNavigationPreloadErrorPrefix[] = |
| "Failed to enable or disable navigation preload: "; |
| const char kGetNavigationPreloadStateErrorPrefix[] = |
| "Failed to get navigation preload state: "; |
| +const char kSetNavigationPreloadHeaderErrorPrefix[] = |
| + "Failed to set navigation preload header: "; |
| const uint32_t kFilteredMessageClasses[] = { |
| ServiceWorkerMsgStart, EmbeddedWorkerMsgStart, |
| @@ -192,6 +195,8 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived( |
| OnEnableNavigationPreload) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetNavigationPreloadState, |
| OnGetNavigationPreloadState) |
| + IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetNavigationPreloadHeader, |
| + OnSetNavigationPreloadHeader) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| @@ -788,7 +793,83 @@ void ServiceWorkerDispatcherHost::OnGetNavigationPreloadState( |
| } |
| Send(new ServiceWorkerMsg_DidGetNavigationPreloadState( |
| - thread_id, request_id, registration->is_navigation_preload_enabled())); |
| + thread_id, request_id, |
| + NavigationPreloadState(registration->is_navigation_preload_enabled(), |
| + registration->navigation_preload_header()))); |
| +} |
| + |
| +void ServiceWorkerDispatcherHost::OnSetNavigationPreloadHeader( |
| + int thread_id, |
| + int request_id, |
| + int provider_id, |
| + int64_t registration_id, |
| + const std::string& value) { |
| + ProviderStatus provider_status; |
| + ServiceWorkerProviderHost* provider_host = |
| + GetProviderHostForRequest(&provider_status, provider_id); |
| + switch (provider_status) { |
| + case ProviderStatus::NO_CONTEXT: // fallthrough |
| + case ProviderStatus::DEAD_HOST: |
| + Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError( |
| + thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort, |
| + std::string(kSetNavigationPreloadHeaderErrorPrefix) + |
| + std::string(kShutdownErrorMessage))); |
| + return; |
| + case ProviderStatus::NO_HOST: |
| + bad_message::ReceivedBadMessage( |
| + this, bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_NO_HOST); |
| + return; |
| + case ProviderStatus::NO_URL: |
| + Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError( |
| + thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity, |
| + std::string(kSetNavigationPreloadHeaderErrorPrefix) + |
| + std::string(kNoDocumentURLErrorMessage))); |
| + return; |
| + case ProviderStatus::OK: |
| + break; |
| + } |
| + |
| + ServiceWorkerRegistration* registration = |
| + GetContext()->GetLiveRegistration(registration_id); |
| + if (!registration) { |
| + // |registration| must be alive because a renderer retains a registration |
| + // reference at this point. |
| + bad_message::ReceivedBadMessage( |
| + this, |
| + bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_REGISTRATION_ID); |
|
ncarter (slow)
2016/10/31 18:35:36
FYI: from some recent experience with bad_message:
falken
2016/11/01 00:35:28
Thanks, that's good to know.
|
| + return; |
| + } |
| + |
| + std::vector<GURL> urls = {provider_host->document_url(), |
| + registration->pattern()}; |
| + if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) { |
| + bad_message::ReceivedBadMessage( |
| + this, bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_INVALID_ORIGIN); |
| + return; |
| + } |
| + |
| + // TODO(falken): Ideally this would match Blink's isValidHTTPHeaderValue. |
| + // Chrome's check is less restrictive: it allows non-latin1 characters. |
| + if (!net::HttpUtil::IsValidHeaderValue(value)) { |
| + bad_message::ReceivedBadMessage( |
| + this, bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_VALUE); |
| + return; |
| + } |
| + |
| + if (!GetContentClient()->browser()->AllowServiceWorker( |
| + registration->pattern(), provider_host->topmost_frame_url(), |
| + resource_context_, render_process_id_, provider_host->frame_id())) { |
| + Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError( |
| + thread_id, request_id, WebServiceWorkerError::ErrorTypeDisabled, |
| + std::string(kSetNavigationPreloadHeaderErrorPrefix) + |
| + std::string(kUserDeniedPermissionMessage))); |
| + return; |
| + } |
| + |
| + // TODO(falken): Write to disk before resolving the promise. |
| + registration->SetNavigationPreloadHeader(value); |
| + Send(new ServiceWorkerMsg_DidSetNavigationPreloadHeader(thread_id, |
| + request_id)); |
| } |
| void ServiceWorkerDispatcherHost::OnPostMessageToWorker( |