| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/renderer/service_worker/service_worker_context_client.h" |
| |
| #include <map> |
| #include <memory> |
| #include <utility> |
| |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/threading/thread_checker.h" |
| #include "base/threading/thread_local.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/time/time.h" |
| #include "base/trace_event/trace_event.h" |
| #include "content/child/background_sync/background_sync_type_converters.h" |
| #include "content/child/notifications/notification_data_conversions.h" |
| #include "content/child/request_extra_data.h" |
| #include "content/child/service_worker/service_worker_dispatcher.h" |
| #include "content/child/service_worker/service_worker_handle_reference.h" |
| #include "content/child/service_worker/service_worker_network_provider.h" |
| #include "content/child/service_worker/service_worker_provider_context.h" |
| #include "content/child/service_worker/service_worker_registration_handle_reference.h" |
| #include "content/child/service_worker/web_service_worker_impl.h" |
| #include "content/child/service_worker/web_service_worker_provider_impl.h" |
| #include "content/child/service_worker/web_service_worker_registration_impl.h" |
| #include "content/child/thread_safe_sender.h" |
| #include "content/child/web_data_consumer_handle_impl.h" |
| #include "content/child/web_url_loader_impl.h" |
| #include "content/child/webmessageportchannel_impl.h" |
| #include "content/common/devtools_messages.h" |
| #include "content/common/service_worker/embedded_worker_messages.h" |
| #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" |
| #include "content/common/service_worker/service_worker_messages.h" |
| #include "content/common/service_worker/service_worker_status_code.h" |
| #include "content/common/worker_url_loader_factory_provider.mojom.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/common/push_event_payload.h" |
| #include "content/public/common/referrer.h" |
| #include "content/public/renderer/content_renderer_client.h" |
| #include "content/public/renderer/document_state.h" |
| #include "content/renderer/devtools/devtools_agent.h" |
| #include "content/renderer/render_thread_impl.h" |
| #include "content/renderer/renderer_blink_platform_impl.h" |
| #include "content/renderer/service_worker/embedded_worker_devtools_agent.h" |
| #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h" |
| #include "content/renderer/service_worker/service_worker_fetch_context_impl.h" |
| #include "content/renderer/service_worker/service_worker_type_converters.h" |
| #include "content/renderer/service_worker/service_worker_type_util.h" |
| #include "ipc/ipc_message.h" |
| #include "ipc/ipc_message_macros.h" |
| #include "net/base/net_errors.h" |
| #include "net/http/http_response_headers.h" |
| #include "third_party/WebKit/public/platform/InterfaceProvider.h" |
| #include "third_party/WebKit/public/platform/URLConversion.h" |
| #include "third_party/WebKit/public/platform/WebMessagePortChannel.h" |
| #include "third_party/WebKit/public/platform/WebReferrerPolicy.h" |
| #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" |
| #include "third_party/WebKit/public/platform/WebString.h" |
| #include "third_party/WebKit/public/platform/WebURLResponse.h" |
| #include "third_party/WebKit/public/platform/modules/background_fetch/WebBackgroundFetchSettledFetch.h" |
| #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h" |
| #include "third_party/WebKit/public/platform/modules/payments/WebPaymentAppRequest.h" |
| #include "third_party/WebKit/public/platform/modules/payments/WebPaymentAppResponse.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientQueryOptions.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h" |
| #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponse.h" |
| #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h" |
| #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| // For now client must be a per-thread instance. |
| base::LazyInstance<base::ThreadLocalPointer<ServiceWorkerContextClient>>:: |
| Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER; |
| |
| // Called on the main thread only and blink owns it. |
| class WebServiceWorkerNetworkProviderImpl |
| : public blink::WebServiceWorkerNetworkProvider { |
| public: |
| explicit WebServiceWorkerNetworkProviderImpl( |
| std::unique_ptr<ServiceWorkerNetworkProvider> provider) |
| : provider_(std::move(provider)) {} |
| |
| // Blink calls this method for each request starting with the main script, |
| // we tag them with the provider id. |
| void WillSendRequest(blink::WebURLRequest& request) override { |
| std::unique_ptr<RequestExtraData> extra_data(new RequestExtraData); |
| extra_data->set_service_worker_provider_id(provider_->provider_id()); |
| extra_data->set_originated_from_service_worker(true); |
| // Service workers are only available in secure contexts, so all requests |
| // are initiated in a secure context. |
| extra_data->set_initiated_in_secure_context(true); |
| request.SetExtraData(extra_data.release()); |
| } |
| |
| int GetProviderID() const override { return provider_->provider_id(); } |
| |
| private: |
| std::unique_ptr<ServiceWorkerNetworkProvider> provider_; |
| }; |
| |
| class StreamHandleListener |
| : public blink::WebServiceWorkerStreamHandle::Listener { |
| public: |
| StreamHandleListener( |
| blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr) |
| : callback_ptr_(std::move(callback_ptr)) {} |
| |
| ~StreamHandleListener() override {} |
| |
| void OnAborted() override { callback_ptr_->OnAborted(); } |
| void OnCompleted() override { callback_ptr_->OnCompleted(); } |
| |
| private: |
| blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr_; |
| }; |
| |
| ServiceWorkerStatusCode EventResultToStatus( |
| blink::WebServiceWorkerEventResult result) { |
| switch (result) { |
| case blink::kWebServiceWorkerEventResultCompleted: |
| return SERVICE_WORKER_OK; |
| case blink::kWebServiceWorkerEventResultRejected: |
| return SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED; |
| } |
| NOTREACHED() << "Got invalid result: " << result; |
| return SERVICE_WORKER_ERROR_FAILED; |
| } |
| |
| blink::WebURLRequest::FetchRequestMode GetBlinkFetchRequestMode( |
| FetchRequestMode mode) { |
| return static_cast<blink::WebURLRequest::FetchRequestMode>(mode); |
| } |
| |
| blink::WebURLRequest::FetchCredentialsMode GetBlinkFetchCredentialsMode( |
| FetchCredentialsMode credentials_mode) { |
| return static_cast<blink::WebURLRequest::FetchCredentialsMode>( |
| credentials_mode); |
| } |
| |
| blink::WebURLRequest::FetchRedirectMode GetBlinkFetchRedirectMode( |
| FetchRedirectMode redirect_mode) { |
| return static_cast<blink::WebURLRequest::FetchRedirectMode>(redirect_mode); |
| } |
| |
| blink::WebURLRequest::RequestContext GetBlinkRequestContext( |
| RequestContextType request_context_type) { |
| return static_cast<blink::WebURLRequest::RequestContext>( |
| request_context_type); |
| } |
| |
| blink::WebURLRequest::FrameType GetBlinkFrameType( |
| RequestContextFrameType frame_type) { |
| return static_cast<blink::WebURLRequest::FrameType>(frame_type); |
| } |
| |
| blink::WebServiceWorkerClientInfo |
| ToWebServiceWorkerClientInfo(const ServiceWorkerClientInfo& client_info) { |
| DCHECK(client_info.IsValid()); |
| |
| blink::WebServiceWorkerClientInfo web_client_info; |
| |
| web_client_info.uuid = blink::WebString::FromASCII(client_info.client_uuid); |
| web_client_info.page_visibility_state = client_info.page_visibility_state; |
| web_client_info.is_focused = client_info.is_focused; |
| web_client_info.url = client_info.url; |
| web_client_info.frame_type = GetBlinkFrameType(client_info.frame_type); |
| web_client_info.client_type = client_info.client_type; |
| |
| return web_client_info; |
| } |
| |
| // Converts the |request| to its equivalent type in the Blink API. |
| // TODO(peter): Remove this when the Mojo FetchAPIRequest type exists. |
| void ToWebServiceWorkerRequest(const ServiceWorkerFetchRequest& request, |
| blink::WebServiceWorkerRequest* web_request) { |
| DCHECK(web_request); |
| |
| web_request->SetURL(blink::WebURL(request.url)); |
| web_request->SetMethod(blink::WebString::FromUTF8(request.method)); |
| for (const auto& pair : request.headers) { |
| web_request->SetHeader(blink::WebString::FromUTF8(pair.first), |
| blink::WebString::FromUTF8(pair.second)); |
| } |
| if (!request.blob_uuid.empty()) { |
| web_request->SetBlob(blink::WebString::FromASCII(request.blob_uuid), |
| request.blob_size); |
| } |
| web_request->SetReferrer( |
| blink::WebString::FromUTF8(request.referrer.url.spec()), |
| request.referrer.policy); |
| web_request->SetMode(GetBlinkFetchRequestMode(request.mode)); |
| web_request->SetIsMainResourceLoad(request.is_main_resource_load); |
| web_request->SetCredentialsMode( |
| GetBlinkFetchCredentialsMode(request.credentials_mode)); |
| web_request->SetRedirectMode( |
| GetBlinkFetchRedirectMode(request.redirect_mode)); |
| web_request->SetRequestContext( |
| GetBlinkRequestContext(request.request_context_type)); |
| web_request->SetFrameType(GetBlinkFrameType(request.frame_type)); |
| web_request->SetClientId(blink::WebString::FromUTF8(request.client_id)); |
| web_request->SetIsReload(request.is_reload); |
| } |
| |
| // Converts |response| to its equivalent type in the Blink API. |
| // TODO(peter): Remove this when the Mojo FetchAPIResponse type exists. |
| void ToWebServiceWorkerResponse(const ServiceWorkerResponse& response, |
| blink::WebServiceWorkerResponse* web_response) { |
| DCHECK(web_response); |
| |
| std::vector<blink::WebURL> url_list; |
| for (const GURL& url : response.url_list) |
| url_list.push_back(blink::WebURL(url)); |
| |
| web_response->SetURLList(blink::WebVector<blink::WebURL>(url_list)); |
| web_response->SetStatus(static_cast<unsigned short>(response.status_code)); |
| web_response->SetStatusText(blink::WebString::FromUTF8(response.status_text)); |
| web_response->SetResponseType(response.response_type); |
| for (const auto& pair : response.headers) { |
| web_response->SetHeader(blink::WebString::FromUTF8(pair.first), |
| blink::WebString::FromUTF8(pair.second)); |
| } |
| if (!response.blob_uuid.empty()) { |
| web_response->SetBlob(blink::WebString::FromASCII(response.blob_uuid), |
| response.blob_size); |
| } |
| web_response->SetError(response.error); |
| web_response->SetResponseTime(response.response_time.ToInternalValue()); |
| if (response.is_in_cache_storage) { |
| web_response->SetCacheStorageCacheName( |
| blink::WebString::FromUTF8(response.cache_storage_cache_name)); |
| } |
| |
| std::vector<blink::WebString> cors_exposed_header_names; |
| for (const auto& name : response.cors_exposed_header_names) |
| cors_exposed_header_names.push_back(blink::WebString::FromUTF8(name)); |
| |
| web_response->SetCorsExposedHeaderNames( |
| blink::WebVector<blink::WebString>(cors_exposed_header_names)); |
| } |
| |
| // Use this template in willDestroyWorkerContext to abort all the pending |
| // events callbacks. |
| template <typename T, class... TArgs> |
| void AbortPendingEventCallbacks(T& callbacks, TArgs... args) { |
| for (typename T::iterator it(&callbacks); !it.IsAtEnd(); it.Advance()) { |
| std::move(*it.GetCurrentValue()) |
| .Run(SERVICE_WORKER_ERROR_ABORT, args..., base::Time::Now()); |
| } |
| } |
| |
| template <typename Key, typename Callback> |
| void AbortPendingEventCallbacks(std::map<Key, Callback>& callbacks) { |
| for (auto& item : callbacks) |
| std::move(item.second).Run(SERVICE_WORKER_ERROR_ABORT, base::Time::Now()); |
| } |
| |
| } // namespace |
| |
| // Holding data that needs to be bound to the worker context on the |
| // worker thread. |
| struct ServiceWorkerContextClient::WorkerContextData { |
| using SimpleEventCallback = |
| base::OnceCallback<void(ServiceWorkerStatusCode, base::Time)>; |
| using ClientsCallbacksMap = |
| IDMap<std::unique_ptr<blink::WebServiceWorkerClientsCallbacks>>; |
| using ClaimClientsCallbacksMap = |
| IDMap<std::unique_ptr<blink::WebServiceWorkerClientsClaimCallbacks>>; |
| using ClientCallbacksMap = |
| IDMap<std::unique_ptr<blink::WebServiceWorkerClientCallbacks>>; |
| using SkipWaitingCallbacksMap = |
| IDMap<std::unique_ptr<blink::WebServiceWorkerSkipWaitingCallbacks>>; |
| using InstallEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchInstallEventCallback>>; |
| using ActivateEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchActivateEventCallback>>; |
| using BackgroundFetchAbortEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchBackgroundFetchAbortEventCallback>>; |
| using BackgroundFetchClickEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchBackgroundFetchClickEventCallback>>; |
| using BackgroundFetchFailEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchBackgroundFetchFailEventCallback>>; |
| using BackgroundFetchedEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchBackgroundFetchedEventCallback>>; |
| using SyncEventCallbacksMap = IDMap<std::unique_ptr<SyncCallback>>; |
| using NotificationClickEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchNotificationClickEventCallback>>; |
| using NotificationCloseEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchNotificationCloseEventCallback>>; |
| using PushEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchPushEventCallback>>; |
| using ExtendableMessageEventCallbacksMap = |
| IDMap<std::unique_ptr<DispatchExtendableMessageEventCallback>>; |
| using NavigationPreloadRequestsMap = IDMap< |
| std::unique_ptr<ServiceWorkerContextClient::NavigationPreloadRequest>>; |
| using InstallEventMethodsMap = |
| std::map<int, mojom::ServiceWorkerInstallEventMethodsAssociatedPtr>; |
| |
| explicit WorkerContextData(ServiceWorkerContextClient* owner) |
| : event_dispatcher_binding(owner), |
| weak_factory(owner), |
| proxy_weak_factory(owner->proxy_) {} |
| |
| ~WorkerContextData() { |
| DCHECK(thread_checker.CalledOnValidThread()); |
| } |
| |
| mojo::Binding<mojom::ServiceWorkerEventDispatcher> event_dispatcher_binding; |
| |
| // Pending callbacks for GetClientDocuments(). |
| ClientsCallbacksMap clients_callbacks; |
| |
| // Pending callbacks for OpenWindow() and FocusClient(). |
| ClientCallbacksMap client_callbacks; |
| |
| // Pending callbacks for SkipWaiting(). |
| SkipWaitingCallbacksMap skip_waiting_callbacks; |
| |
| // Pending callbacks for ClaimClients(). |
| ClaimClientsCallbacksMap claim_clients_callbacks; |
| |
| // Pending callbacks for Install Events. |
| InstallEventCallbacksMap install_event_callbacks; |
| |
| // Pending callbacks for Activate Events. |
| ActivateEventCallbacksMap activate_event_callbacks; |
| |
| // Pending callbacks for Background Fetch Abort Events. |
| BackgroundFetchAbortEventCallbacksMap background_fetch_abort_event_callbacks; |
| |
| // Pending callbacks for Background Fetch Click Events. |
| BackgroundFetchClickEventCallbacksMap background_fetch_click_event_callbacks; |
| |
| // Pending callbacks for Background Fetch Fail Events. |
| BackgroundFetchFailEventCallbacksMap background_fetch_fail_event_callbacks; |
| |
| // Pending callbacks for Background Fetched Events. |
| BackgroundFetchedEventCallbacksMap background_fetched_event_callbacks; |
| |
| // Pending callbacks for Background Sync Events. |
| SyncEventCallbacksMap sync_event_callbacks; |
| |
| // Pending callbacks for Payment App Response. |
| std::map<int /* payment_request_id */, |
| payments::mojom::PaymentAppResponseCallbackPtr> |
| payment_response_callbacks; |
| |
| // Pending callbacks for Payment Request Events. |
| std::map<int /* payment_request_id */, DispatchPaymentRequestEventCallback> |
| payment_request_event_callbacks; |
| |
| // Pending callbacks for Notification Click Events. |
| NotificationClickEventCallbacksMap notification_click_event_callbacks; |
| |
| // Pending callbacks for Notification Close Events. |
| NotificationCloseEventCallbacksMap notification_close_event_callbacks; |
| |
| // Pending callbacks for Push Events. |
| PushEventCallbacksMap push_event_callbacks; |
| |
| // Pending callbacks for Fetch Events. |
| std::map<int /* fetch_event_id */, SimpleEventCallback> fetch_event_callbacks; |
| |
| // Pending callbacks for respondWith on each fetch event. |
| std::map<int /* fetch_event_id */, |
| mojom::ServiceWorkerFetchResponseCallbackPtr> |
| fetch_response_callbacks; |
| |
| // Pending callbacks for Extendable Message Events. |
| ExtendableMessageEventCallbacksMap message_event_callbacks; |
| |
| // Pending navigation preload requests. |
| NavigationPreloadRequestsMap preload_requests; |
| |
| // Maps every install event id with its corresponding |
| // mojom::ServiceWorkerInstallEventMethodsAssociatedPt. |
| InstallEventMethodsMap install_methods_map; |
| |
| base::ThreadChecker thread_checker; |
| base::WeakPtrFactory<ServiceWorkerContextClient> weak_factory; |
| base::WeakPtrFactory<blink::WebServiceWorkerContextProxy> proxy_weak_factory; |
| }; |
| |
| class ServiceWorkerContextClient::NavigationPreloadRequest final |
| : public mojom::URLLoaderClient { |
| public: |
| NavigationPreloadRequest(int fetch_event_id, |
| const GURL& url, |
| mojom::FetchEventPreloadHandlePtr preload_handle) |
| : fetch_event_id_(fetch_event_id), |
| url_(url), |
| url_loader_(std::move(preload_handle->url_loader)), |
| binding_(this, std::move(preload_handle->url_loader_client_request)) {} |
| |
| ~NavigationPreloadRequest() override {} |
| |
| void OnReceiveResponse( |
| const ResourceResponseHead& response_head, |
| const base::Optional<net::SSLInfo>& ssl_info, |
| mojom::DownloadedTempFilePtr downloaded_file) override { |
| DCHECK(!response_); |
| DCHECK(!downloaded_file); |
| response_ = base::MakeUnique<blink::WebURLResponse>(); |
| // TODO(horo): Set report_security_info to true when DevTools is attached. |
| const bool report_security_info = false; |
| WebURLLoaderImpl::PopulateURLResponse(url_, response_head, response_.get(), |
| report_security_info); |
| MaybeReportResponseToClient(); |
| } |
| |
| void OnReceiveRedirect(const net::RedirectInfo& redirect_info, |
| const ResourceResponseHead& response_head) override { |
| DCHECK(!response_); |
| DCHECK(net::HttpResponseHeaders::IsRedirectResponseCode( |
| response_head.headers->response_code())); |
| |
| ServiceWorkerContextClient* client = |
| ServiceWorkerContextClient::ThreadSpecificInstance(); |
| if (!client) |
| return; |
| response_ = base::MakeUnique<blink::WebURLResponse>(); |
| WebURLLoaderImpl::PopulateURLResponse(url_, response_head, response_.get(), |
| false /* report_security_info */); |
| client->OnNavigationPreloadResponse(fetch_event_id_, std::move(response_), |
| nullptr); |
| // This will delete |this|. |
| client->OnNavigationPreloadComplete( |
| fetch_event_id_, response_head.response_start, |
| response_head.encoded_data_length, 0 /* encoded_body_length */, |
| 0 /* decoded_body_length */); |
| } |
| |
| void OnDataDownloaded(int64_t data_length, |
| int64_t encoded_data_length) override { |
| NOTREACHED(); |
| } |
| |
| void OnUploadProgress(int64_t current_position, |
| int64_t total_size, |
| OnUploadProgressCallback ack_callback) override { |
| NOTREACHED(); |
| } |
| |
| void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} |
| |
| void OnTransferSizeUpdated(int32_t transfer_size_diff) override { |
| } |
| |
| void OnStartLoadingResponseBody( |
| mojo::ScopedDataPipeConsumerHandle body) override { |
| DCHECK(!body_.is_valid()); |
| body_ = std::move(body); |
| MaybeReportResponseToClient(); |
| } |
| |
| void OnComplete(const ResourceRequestCompletionStatus& status) override { |
| if (status.error_code != net::OK) { |
| std::string message; |
| std::string unsanitized_message; |
| if (status.error_code == net::ERR_ABORTED) { |
| message = |
| "The service worker navigation preload request was cancelled " |
| "before 'preloadResponse' settled. If you intend to use " |
| "'preloadResponse', use waitUntil() or respondWith() to wait for " |
| "the promise to settle."; |
| } else { |
| message = |
| "The service worker navigation preload request failed with a " |
| "network error."; |
| unsanitized_message = |
| "The service worker navigation preload request failed with network " |
| "error: " + |
| net::ErrorToString(status.error_code) + "."; |
| } |
| |
| // This will delete |this|. |
| ReportErrorToClient(message, unsanitized_message); |
| return; |
| } |
| |
| ServiceWorkerContextClient* client = |
| ServiceWorkerContextClient::ThreadSpecificInstance(); |
| if (!client) |
| return; |
| if (response_) { |
| // When the response body from the server is empty, OnComplete() is called |
| // without OnStartLoadingResponseBody(). |
| DCHECK(!body_.is_valid()); |
| client->OnNavigationPreloadResponse(fetch_event_id_, std::move(response_), |
| nullptr); |
| } |
| // This will delete |this|. |
| client->OnNavigationPreloadComplete( |
| fetch_event_id_, status.completion_time, status.encoded_data_length, |
| status.encoded_body_length, status.decoded_body_length); |
| } |
| |
| private: |
| void MaybeReportResponseToClient() { |
| if (!response_ || !body_.is_valid()) |
| return; |
| ServiceWorkerContextClient* client = |
| ServiceWorkerContextClient::ThreadSpecificInstance(); |
| if (!client) |
| return; |
| |
| client->OnNavigationPreloadResponse( |
| fetch_event_id_, std::move(response_), |
| base::MakeUnique<WebDataConsumerHandleImpl>(std::move(body_))); |
| } |
| |
| void ReportErrorToClient(const std::string& message, |
| const std::string& unsanitized_message) { |
| ServiceWorkerContextClient* client = |
| ServiceWorkerContextClient::ThreadSpecificInstance(); |
| if (!client) |
| return; |
| // This will delete |this|. |
| client->OnNavigationPreloadError( |
| fetch_event_id_, base::MakeUnique<blink::WebServiceWorkerError>( |
| blink::WebServiceWorkerError::kErrorTypeNetwork, |
| blink::WebString::FromUTF8(message), |
| blink::WebString::FromUTF8(unsanitized_message))); |
| } |
| |
| const int fetch_event_id_; |
| const GURL url_; |
| mojom::URLLoaderPtr url_loader_; |
| mojo::Binding<mojom::URLLoaderClient> binding_; |
| |
| std::unique_ptr<blink::WebURLResponse> response_; |
| mojo::ScopedDataPipeConsumerHandle body_; |
| }; |
| |
| ServiceWorkerContextClient* |
| ServiceWorkerContextClient::ThreadSpecificInstance() { |
| return g_worker_client_tls.Pointer()->Get(); |
| } |
| |
| ServiceWorkerContextClient::ServiceWorkerContextClient( |
| int embedded_worker_id, |
| int64_t service_worker_version_id, |
| const GURL& service_worker_scope, |
| const GURL& script_url, |
| mojom::ServiceWorkerEventDispatcherRequest dispatcher_request, |
| mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host, |
| std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client) |
| : embedded_worker_id_(embedded_worker_id), |
| service_worker_version_id_(service_worker_version_id), |
| service_worker_scope_(service_worker_scope), |
| script_url_(script_url), |
| sender_(ChildThreadImpl::current()->thread_safe_sender()), |
| main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| proxy_(nullptr), |
| pending_dispatcher_request_(std::move(dispatcher_request)), |
| embedded_worker_client_(std::move(embedded_worker_client)) { |
| instance_host_ = |
| mojom::ThreadSafeEmbeddedWorkerInstanceHostAssociatedPtr::Create( |
| std::move(instance_host), main_thread_task_runner_); |
| TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker", |
| "ServiceWorkerContextClient::StartingWorkerContext", |
| this); |
| TRACE_EVENT_ASYNC_STEP_INTO0( |
| "ServiceWorker", |
| "ServiceWorkerContextClient::StartingWorkerContext", |
| this, |
| "PrepareWorker"); |
| } |
| |
| ServiceWorkerContextClient::~ServiceWorkerContextClient() {} |
| |
| void ServiceWorkerContextClient::OnMessageReceived( |
| int thread_id, |
| int embedded_worker_id, |
| const IPC::Message& message) { |
| CHECK_EQ(embedded_worker_id_, embedded_worker_id); |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(ServiceWorkerContextClient, message) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClient, OnDidGetClient) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClients, OnDidGetClients) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowResponse, |
| OnOpenWindowResponse) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowError, |
| OnOpenWindowError) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FocusClientResponse, |
| OnFocusClientResponse) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientResponse, |
| OnNavigateClientResponse) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NavigateClientError, |
| OnNavigateClientError) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidSkipWaiting, OnDidSkipWaiting) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidClaimClients, OnDidClaimClients) |
| IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ClaimClientsError, OnClaimClientsError) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| DCHECK(handled); |
| } |
| |
| blink::WebURL ServiceWorkerContextClient::Scope() const { |
| return service_worker_scope_; |
| } |
| |
| void ServiceWorkerContextClient::GetClient( |
| const blink::WebString& id, |
| std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) { |
| DCHECK(callbacks); |
| int request_id = context_->client_callbacks.Add(std::move(callbacks)); |
| Send(new ServiceWorkerHostMsg_GetClient(GetRoutingID(), request_id, |
| id.Utf8())); |
| } |
| |
| void ServiceWorkerContextClient::GetClients( |
| const blink::WebServiceWorkerClientQueryOptions& weboptions, |
| std::unique_ptr<blink::WebServiceWorkerClientsCallbacks> callbacks) { |
| DCHECK(callbacks); |
| int request_id = context_->clients_callbacks.Add(std::move(callbacks)); |
| ServiceWorkerClientQueryOptions options; |
| options.client_type = weboptions.client_type; |
| options.include_uncontrolled = weboptions.include_uncontrolled; |
| Send(new ServiceWorkerHostMsg_GetClients( |
| GetRoutingID(), request_id, options)); |
| } |
| |
| void ServiceWorkerContextClient::OpenWindow( |
| const blink::WebURL& url, |
| std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) { |
| DCHECK(callbacks); |
| int request_id = context_->client_callbacks.Add(std::move(callbacks)); |
| Send(new ServiceWorkerHostMsg_OpenWindow( |
| GetRoutingID(), request_id, url)); |
| } |
| |
| void ServiceWorkerContextClient::SetCachedMetadata(const blink::WebURL& url, |
| const char* data, |
| size_t size) { |
| std::vector<char> copy(data, data + size); |
| Send(new ServiceWorkerHostMsg_SetCachedMetadata(GetRoutingID(), url, copy)); |
| } |
| |
| void ServiceWorkerContextClient::ClearCachedMetadata(const blink::WebURL& url) { |
| Send(new ServiceWorkerHostMsg_ClearCachedMetadata(GetRoutingID(), url)); |
| } |
| |
| void ServiceWorkerContextClient::WorkerReadyForInspection() { |
| DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); |
| (*instance_host_)->OnReadyForInspection(); |
| } |
| |
| void ServiceWorkerContextClient::WorkerContextFailedToStart() { |
| DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); |
| DCHECK(!proxy_); |
| |
| (*instance_host_)->OnScriptLoadFailed(); |
| (*instance_host_)->OnStopped(); |
| |
| DCHECK(embedded_worker_client_); |
| embedded_worker_client_->WorkerContextDestroyed(); |
| } |
| |
| void ServiceWorkerContextClient::WorkerScriptLoaded() { |
| DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); |
| DCHECK(!proxy_); |
| |
| (*instance_host_)->OnScriptLoaded(); |
| } |
| |
| bool ServiceWorkerContextClient::HasAssociatedRegistration() { |
| return provider_context_ && provider_context_->HasAssociatedRegistration(); |
| } |
| |
| void ServiceWorkerContextClient::WorkerContextStarted( |
| blink::WebServiceWorkerContextProxy* proxy) { |
| DCHECK(!worker_task_runner_.get()); |
| DCHECK_NE(0, WorkerThread::GetCurrentId()); |
| worker_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| // g_worker_client_tls.Pointer()->Get() could return NULL if this context |
| // gets deleted before workerContextStarted() is called. |
| DCHECK(g_worker_client_tls.Pointer()->Get() == NULL); |
| DCHECK(!proxy_); |
| g_worker_client_tls.Pointer()->Set(this); |
| proxy_ = proxy; |
| |
| // Initialize pending callback maps. This needs to be freed on the |
| // same thread before the worker context goes away in |
| // willDestroyWorkerContext. |
| context_.reset(new WorkerContextData(this)); |
| |
| ServiceWorkerRegistrationObjectInfo registration_info; |
| ServiceWorkerVersionAttributes version_attrs; |
| provider_context_->GetAssociatedRegistration(®istration_info, |
| &version_attrs); |
| DCHECK_NE(registration_info.registration_id, |
| kInvalidServiceWorkerRegistrationId); |
| |
| DCHECK(pending_dispatcher_request_.is_pending()); |
| DCHECK(!context_->event_dispatcher_binding.is_bound()); |
| context_->event_dispatcher_binding.Bind( |
| std::move(pending_dispatcher_request_)); |
| |
| SetRegistrationInServiceWorkerGlobalScope(registration_info, version_attrs); |
| |
| (*instance_host_) |
| ->OnThreadStarted(WorkerThread::GetCurrentId(), |
| provider_context_->provider_id()); |
| |
| TRACE_EVENT_ASYNC_STEP_INTO0( |
| "ServiceWorker", |
| "ServiceWorkerContextClient::StartingWorkerContext", |
| this, |
| "ExecuteScript"); |
| } |
| |
| void ServiceWorkerContextClient::DidEvaluateWorkerScript(bool success) { |
| DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); |
| (*instance_host_)->OnScriptEvaluated(success); |
| |
| // Schedule a task to send back WorkerStarted asynchronously, |
| // so that at the time we send it we can be sure that the |
| // worker run loop has been started. |
| worker_task_runner_->PostTask( |
| FROM_HERE, base::Bind(&ServiceWorkerContextClient::SendWorkerStarted, |
| GetWeakPtr())); |
| } |
| |
| void ServiceWorkerContextClient::DidInitializeWorkerContext( |
| v8::Local<v8::Context> context) { |
| GetContentClient() |
| ->renderer() |
| ->DidInitializeServiceWorkerContextOnWorkerThread( |
| context, service_worker_version_id_, script_url_); |
| } |
| |
| void ServiceWorkerContextClient::WillDestroyWorkerContext( |
| v8::Local<v8::Context> context) { |
| // At this point WillStopCurrentWorkerThread is already called, so |
| // worker_task_runner_->RunsTasksInCurrentSequence() returns false |
| // (while we're still on the worker thread). |
| proxy_ = NULL; |
| |
| // Aborts all the pending events callbacks. |
| AbortPendingEventCallbacks(context_->install_event_callbacks, |
| false /* has_fetch_handler */); |
| AbortPendingEventCallbacks(context_->activate_event_callbacks); |
| AbortPendingEventCallbacks(context_->background_fetch_abort_event_callbacks); |
| AbortPendingEventCallbacks(context_->background_fetch_click_event_callbacks); |
| AbortPendingEventCallbacks(context_->background_fetch_fail_event_callbacks); |
| AbortPendingEventCallbacks(context_->background_fetched_event_callbacks); |
| AbortPendingEventCallbacks(context_->sync_event_callbacks); |
| AbortPendingEventCallbacks(context_->notification_click_event_callbacks); |
| AbortPendingEventCallbacks(context_->notification_close_event_callbacks); |
| AbortPendingEventCallbacks(context_->push_event_callbacks); |
| AbortPendingEventCallbacks(context_->fetch_event_callbacks); |
| AbortPendingEventCallbacks(context_->message_event_callbacks); |
| |
| // We have to clear callbacks now, as they need to be freed on the |
| // same thread. |
| context_.reset(); |
| |
| // This also lets the message filter stop dispatching messages to |
| // this client. |
| g_worker_client_tls.Pointer()->Set(NULL); |
| |
| GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread( |
| context, service_worker_version_id_, script_url_); |
| } |
| |
| void ServiceWorkerContextClient::WorkerContextDestroyed() { |
| DCHECK(g_worker_client_tls.Pointer()->Get() == NULL); |
| |
| // TODO(shimazu): The signals to the browser should be in the order: |
| // (1) WorkerStopped (via mojo call EmbeddedWorkerInstanceHost.OnStopped()) |
| // (2) ProviderDestroyed (via mojo call |
| // ServiceWorkerDispatcherHost.OnProviderDestroyed()), this is triggered by |
| // the following EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed(), |
| // which will eventually lead to destruction of the service worker provider. |
| // But currently EmbeddedWorkerInstanceHost interface is associated with |
| // EmbeddedWorkerInstanceClient interface, and ServiceWorkerDispatcherHost |
| // interface is associated with the IPC channel, since they are using |
| // different mojo message pipes, the FIFO ordering can not be guaranteed now. |
| // This will be solved once ServiceWorkerProvider{Host,Client} are mojoified |
| // and they are also associated with EmbeddedWorkerInstanceClient in other CLs |
| // (https://crrev.com/2653493009 and https://crrev.com/2779763004). |
| (*instance_host_)->OnStopped(); |
| |
| DCHECK(embedded_worker_client_); |
| main_thread_task_runner_->PostTask( |
| FROM_HERE, |
| base::Bind(&EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed, |
| base::Passed(&embedded_worker_client_))); |
| return; |
| } |
| |
| void ServiceWorkerContextClient::CountFeature(uint32_t feature) { |
| Send(new EmbeddedWorkerHostMsg_CountFeature(service_worker_version_id_, |
| feature)); |
| } |
| |
| void ServiceWorkerContextClient::ReportException( |
| const blink::WebString& error_message, |
| int line_number, |
| int column_number, |
| const blink::WebString& source_url) { |
| (*instance_host_) |
| ->OnReportException(error_message.Utf16(), line_number, column_number, |
| blink::WebStringToGURL(source_url)); |
| } |
| |
| void ServiceWorkerContextClient::ReportConsoleMessage( |
| int source, |
| int level, |
| const blink::WebString& message, |
| int line_number, |
| const blink::WebString& source_url) { |
| (*instance_host_) |
| ->OnReportConsoleMessage(source, level, message.Utf16(), line_number, |
| blink::WebStringToGURL(source_url)); |
| } |
| |
| void ServiceWorkerContextClient::SendDevToolsMessage( |
| int session_id, |
| int call_id, |
| const blink::WebString& message, |
| const blink::WebString& state_cookie) { |
| // Return if this context has been stopped. |
| if (!embedded_worker_client_) |
| return; |
| embedded_worker_client_->devtools_agent()->SendMessage( |
| sender_.get(), session_id, call_id, message.Utf8(), state_cookie.Utf8()); |
| } |
| |
| blink::WebDevToolsAgentClient::WebKitClientMessageLoop* |
| ServiceWorkerContextClient::CreateDevToolsMessageLoop() { |
| return DevToolsAgent::createMessageLoopWrapper(); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleActivateEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchActivateEventCallback* callback = |
| context_->activate_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->activate_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchBackgroundFetchAbortEventCallback* callback = |
| context_->background_fetch_abort_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->background_fetch_abort_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchBackgroundFetchClickEventCallback* callback = |
| context_->background_fetch_click_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->background_fetch_click_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchBackgroundFetchFailEventCallback* callback = |
| context_->background_fetch_fail_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->background_fetch_fail_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchBackgroundFetchedEventCallback* callback = |
| context_->background_fetched_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->background_fetched_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleExtendableMessageEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchExtendableMessageEventCallback* callback = |
| context_->message_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->message_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleInstallEvent( |
| int event_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchInstallEventCallback* callback = |
| context_->install_event_callbacks.Lookup(event_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| proxy_->HasFetchEventHandler(), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->install_event_callbacks.Remove(event_id); |
| context_->install_methods_map.erase(event_id); |
| } |
| |
| void ServiceWorkerContextClient::RespondToFetchEventWithNoResponse( |
| int fetch_event_id, |
| double event_dispatch_time) { |
| const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback = |
| context_->fetch_response_callbacks[fetch_event_id]; |
| DCHECK(response_callback.is_bound()); |
| response_callback->OnFallback(base::Time::FromDoubleT(event_dispatch_time)); |
| context_->fetch_response_callbacks.erase(fetch_event_id); |
| } |
| |
| void ServiceWorkerContextClient::RespondToFetchEvent( |
| int fetch_event_id, |
| const blink::WebServiceWorkerResponse& web_response, |
| double event_dispatch_time) { |
| ServiceWorkerResponse response( |
| GetServiceWorkerResponseFromWebResponse(web_response)); |
| const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback = |
| context_->fetch_response_callbacks[fetch_event_id]; |
| if (response.blob_uuid.size()) { |
| // Send the legacy IPC due to the ordering issue between respondWith and |
| // blob. |
| // TODO(shimazu): mojofy this IPC after blob starts using sync IPC for |
| // creation or is mojofied: https://crbug.com/611935. |
| Send(new ServiceWorkerHostMsg_FetchEventResponse( |
| GetRoutingID(), fetch_event_id, response, |
| base::Time::FromDoubleT(event_dispatch_time))); |
| } else { |
| response_callback->OnResponse(response, |
| base::Time::FromDoubleT(event_dispatch_time)); |
| } |
| context_->fetch_response_callbacks.erase(fetch_event_id); |
| } |
| |
| void ServiceWorkerContextClient::RespondToFetchEventWithResponseStream( |
| int fetch_event_id, |
| const blink::WebServiceWorkerResponse& web_response, |
| blink::WebServiceWorkerStreamHandle* web_body_as_stream, |
| double event_dispatch_time) { |
| ServiceWorkerResponse response( |
| GetServiceWorkerResponseFromWebResponse(web_response)); |
| const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback = |
| context_->fetch_response_callbacks[fetch_event_id]; |
| blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream = |
| blink::mojom::ServiceWorkerStreamHandle::New(); |
| blink::mojom::ServiceWorkerStreamCallbackPtr callback_ptr; |
| body_as_stream->callback_request = mojo::MakeRequest(&callback_ptr); |
| body_as_stream->stream = web_body_as_stream->DrainStreamDataPipe(); |
| |
| web_body_as_stream->SetListener( |
| base::MakeUnique<StreamHandleListener>(std::move(callback_ptr))); |
| |
| response_callback->OnResponseStream( |
| response, std::move(body_as_stream), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->fetch_response_callbacks.erase(fetch_event_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleFetchEvent( |
| int fetch_event_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| WorkerContextData::SimpleEventCallback callback = |
| std::move(context_->fetch_event_callbacks[fetch_event_id]); |
| DCHECK(callback); |
| std::move(callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->fetch_event_callbacks.erase(fetch_event_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleNotificationClickEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchNotificationClickEventCallback* callback = |
| context_->notification_click_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| |
| context_->notification_click_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleNotificationCloseEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchNotificationCloseEventCallback* callback = |
| context_->notification_close_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| |
| context_->notification_close_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandlePushEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchPushEventCallback* callback = |
| context_->push_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->push_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandleSyncEvent( |
| int request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| SyncCallback* callback = context_->sync_event_callbacks.Lookup(request_id); |
| DCHECK(callback); |
| DCHECK(*callback); |
| std::move(*callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->sync_event_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::RespondToPaymentRequestEvent( |
| int payment_request_id, |
| const blink::WebPaymentAppResponse& web_response, |
| double dispatch_event_time) { |
| const payments::mojom::PaymentAppResponseCallbackPtr& response_callback = |
| context_->payment_response_callbacks[payment_request_id]; |
| payments::mojom::PaymentAppResponsePtr response = |
| payments::mojom::PaymentAppResponse::New(); |
| response->method_name = web_response.method_name.Utf8(); |
| response_callback->OnPaymentAppResponse( |
| std::move(response), base::Time::FromDoubleT(dispatch_event_time)); |
| context_->payment_response_callbacks.erase(payment_request_id); |
| } |
| |
| void ServiceWorkerContextClient::DidHandlePaymentRequestEvent( |
| int payment_request_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| DispatchPaymentRequestEventCallback callback = |
| std::move(context_->payment_request_event_callbacks[payment_request_id]); |
| std::move(callback).Run(EventResultToStatus(result), |
| base::Time::FromDoubleT(event_dispatch_time)); |
| context_->payment_request_event_callbacks.erase(payment_request_id); |
| } |
| |
| std::unique_ptr<blink::WebServiceWorkerNetworkProvider> |
| ServiceWorkerContextClient::CreateServiceWorkerNetworkProvider() { |
| DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); |
| |
| // Create a content::ServiceWorkerNetworkProvider for this data source so |
| // we can observe its requests. |
| std::unique_ptr<ServiceWorkerNetworkProvider> provider = |
| base::MakeUnique<ServiceWorkerNetworkProvider>( |
| MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, |
| true /* is_parent_frame_secure */); |
| provider_context_ = provider->context(); |
| network_provider_id_ = provider->provider_id(); |
| |
| // Tell the network provider about which version to load. |
| provider->SetServiceWorkerVersionId(service_worker_version_id_, |
| embedded_worker_id_); |
| |
| // Blink is responsible for deleting the returned object. |
| return base::MakeUnique<WebServiceWorkerNetworkProviderImpl>( |
| std::move(provider)); |
| } |
| |
| std::unique_ptr<blink::WebWorkerFetchContext> |
| ServiceWorkerContextClient::CreateServiceWorkerFetchContext() { |
| DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); |
| DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch)); |
| mojom::WorkerURLLoaderFactoryProviderPtr worker_url_loader_factory_provider; |
| RenderThreadImpl::current() |
| ->blink_platform_impl() |
| ->GetInterfaceProvider() |
| ->GetInterface(mojo::MakeRequest(&worker_url_loader_factory_provider)); |
| |
| // Blink is responsible for deleting the returned object. |
| return base::MakeUnique<ServiceWorkerFetchContextImpl>( |
| script_url_, worker_url_loader_factory_provider.PassInterface(), |
| network_provider_id_); |
| } |
| |
| std::unique_ptr<blink::WebServiceWorkerProvider> |
| ServiceWorkerContextClient::CreateServiceWorkerProvider() { |
| DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); |
| DCHECK(provider_context_); |
| |
| // Blink is responsible for deleting the returned object. |
| return base::MakeUnique<WebServiceWorkerProviderImpl>( |
| sender_.get(), provider_context_.get()); |
| } |
| |
| void ServiceWorkerContextClient::PostMessageToClient( |
| const blink::WebString& uuid, |
| const blink::WebString& message, |
| blink::WebMessagePortChannelArray channels) { |
| Send(new ServiceWorkerHostMsg_PostMessageToClient( |
| GetRoutingID(), uuid.Utf8(), message.Utf16(), |
| WebMessagePortChannelImpl::ExtractMessagePorts(std::move(channels)))); |
| } |
| |
| void ServiceWorkerContextClient::Focus( |
| const blink::WebString& uuid, |
| std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callback) { |
| DCHECK(callback); |
| int request_id = context_->client_callbacks.Add(std::move(callback)); |
| Send(new ServiceWorkerHostMsg_FocusClient(GetRoutingID(), request_id, |
| uuid.Utf8())); |
| } |
| |
| void ServiceWorkerContextClient::Navigate( |
| const blink::WebString& uuid, |
| const blink::WebURL& url, |
| std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callback) { |
| DCHECK(callback); |
| int request_id = context_->client_callbacks.Add(std::move(callback)); |
| Send(new ServiceWorkerHostMsg_NavigateClient(GetRoutingID(), request_id, |
| uuid.Utf8(), url)); |
| } |
| |
| void ServiceWorkerContextClient::SkipWaiting( |
| std::unique_ptr<blink::WebServiceWorkerSkipWaitingCallbacks> callbacks) { |
| DCHECK(callbacks); |
| int request_id = context_->skip_waiting_callbacks.Add(std::move(callbacks)); |
| Send(new ServiceWorkerHostMsg_SkipWaiting(GetRoutingID(), request_id)); |
| } |
| |
| void ServiceWorkerContextClient::Claim( |
| std::unique_ptr<blink::WebServiceWorkerClientsClaimCallbacks> callbacks) { |
| DCHECK(callbacks); |
| int request_id = context_->claim_clients_callbacks.Add(std::move(callbacks)); |
| Send(new ServiceWorkerHostMsg_ClaimClients(GetRoutingID(), request_id)); |
| } |
| |
| void ServiceWorkerContextClient::RegisterForeignFetchScopes( |
| int install_event_id, |
| const blink::WebVector<blink::WebURL>& sub_scopes, |
| const blink::WebVector<blink::WebSecurityOrigin>& origins) { |
| DCHECK(context_->install_methods_map[install_event_id].is_bound()); |
| context_->install_methods_map[install_event_id]->RegisterForeignFetchScopes( |
| std::vector<GURL>(sub_scopes.begin(), sub_scopes.end()), |
| std::vector<url::Origin>(origins.begin(), origins.end())); |
| } |
| |
| void ServiceWorkerContextClient::DispatchSyncEvent( |
| const std::string& tag, |
| blink::mojom::BackgroundSyncEventLastChance last_chance, |
| DispatchSyncEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchSyncEvent"); |
| int request_id = context_->sync_event_callbacks.Add( |
| base::MakeUnique<SyncCallback>(std::move(callback))); |
| |
| // TODO(shimazu): Use typemap when this is moved to blink-side. |
| blink::WebServiceWorkerContextProxy::LastChanceOption web_last_chance = |
| mojo::ConvertTo<blink::WebServiceWorkerContextProxy::LastChanceOption>( |
| last_chance); |
| |
| // TODO(jkarlin): Make this blink::WebString::FromUTF8Lenient once |
| // https://crrev.com/1768063002/ lands. |
| proxy_->DispatchSyncEvent(request_id, blink::WebString::FromUTF8(tag), |
| web_last_chance); |
| } |
| |
| void ServiceWorkerContextClient::DispatchPaymentRequestEvent( |
| int payment_request_id, |
| payments::mojom::PaymentAppRequestPtr app_request, |
| payments::mojom::PaymentAppResponseCallbackPtr response_callback, |
| DispatchPaymentRequestEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchPaymentRequestEvent"); |
| context_->payment_response_callbacks.insert( |
| std::make_pair(payment_request_id, std::move(response_callback))); |
| context_->payment_request_event_callbacks.insert( |
| std::make_pair(payment_request_id, std::move(callback))); |
| |
| blink::WebPaymentAppRequest webAppRequest = |
| mojo::ConvertTo<blink::WebPaymentAppRequest>(std::move(app_request)); |
| proxy_->DispatchPaymentRequestEvent(payment_request_id, webAppRequest); |
| } |
| |
| void ServiceWorkerContextClient::Send(IPC::Message* message) { |
| sender_->Send(message); |
| } |
| |
| void ServiceWorkerContextClient::SendWorkerStarted() { |
| DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); |
| TRACE_EVENT_ASYNC_END0("ServiceWorker", |
| "ServiceWorkerContextClient::StartingWorkerContext", |
| this); |
| (*instance_host_)->OnStarted(); |
| } |
| |
| void ServiceWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope( |
| const ServiceWorkerRegistrationObjectInfo& info, |
| const ServiceWorkerVersionAttributes& attrs) { |
| DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); |
| ServiceWorkerDispatcher* dispatcher = |
| ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance( |
| sender_.get(), main_thread_task_runner_.get()); |
| |
| // Register a registration and its version attributes with the dispatcher |
| // living on the worker thread. |
| scoped_refptr<WebServiceWorkerRegistrationImpl> registration( |
| dispatcher->GetOrCreateRegistration(info, attrs)); |
| |
| proxy_->SetRegistration( |
| WebServiceWorkerRegistrationImpl::CreateHandle(registration)); |
| } |
| |
| void ServiceWorkerContextClient::DispatchActivateEvent( |
| DispatchActivateEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchActivateEvent"); |
| int request_id = context_->activate_event_callbacks.Add( |
| base::MakeUnique<DispatchActivateEventCallback>(std::move(callback))); |
| proxy_->DispatchActivateEvent(request_id); |
| } |
| |
| void ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent( |
| const std::string& tag, |
| DispatchBackgroundFetchAbortEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent"); |
| int request_id = context_->background_fetch_abort_event_callbacks.Add( |
| base::MakeUnique<DispatchBackgroundFetchAbortEventCallback>( |
| std::move(callback))); |
| |
| proxy_->DispatchBackgroundFetchAbortEvent(request_id, |
| blink::WebString::FromUTF8(tag)); |
| } |
| |
| void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent( |
| const std::string& tag, |
| mojom::BackgroundFetchState state, |
| DispatchBackgroundFetchClickEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent"); |
| int request_id = context_->background_fetch_click_event_callbacks.Add( |
| base::MakeUnique<DispatchBackgroundFetchClickEventCallback>( |
| std::move(callback))); |
| |
| // TODO(peter): Use typemap when this is moved to blink-side. |
| blink::WebServiceWorkerContextProxy::BackgroundFetchState web_state = |
| mojo::ConvertTo< |
| blink::WebServiceWorkerContextProxy::BackgroundFetchState>(state); |
| |
| proxy_->DispatchBackgroundFetchClickEvent( |
| request_id, blink::WebString::FromUTF8(tag), web_state); |
| } |
| |
| void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent( |
| const std::string& tag, |
| const std::vector<BackgroundFetchSettledFetch>& fetches, |
| DispatchBackgroundFetchFailEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent"); |
| int request_id = context_->background_fetch_fail_event_callbacks.Add( |
| base::MakeUnique<DispatchBackgroundFetchFailEventCallback>( |
| std::move(callback))); |
| |
| blink::WebVector<blink::WebBackgroundFetchSettledFetch> web_fetches( |
| fetches.size()); |
| for (size_t i = 0; i < fetches.size(); ++i) { |
| ToWebServiceWorkerRequest(fetches[i].request, &web_fetches[i].request); |
| ToWebServiceWorkerResponse(fetches[i].response, &web_fetches[i].response); |
| } |
| |
| proxy_->DispatchBackgroundFetchFailEvent( |
| request_id, blink::WebString::FromUTF8(tag), web_fetches); |
| } |
| |
| void ServiceWorkerContextClient::DispatchBackgroundFetchedEvent( |
| const std::string& tag, |
| const std::vector<BackgroundFetchSettledFetch>& fetches, |
| DispatchBackgroundFetchedEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchBackgroundFetchedEvent"); |
| int request_id = context_->background_fetched_event_callbacks.Add( |
| base::MakeUnique<DispatchBackgroundFetchedEventCallback>( |
| std::move(callback))); |
| |
| blink::WebVector<blink::WebBackgroundFetchSettledFetch> web_fetches( |
| fetches.size()); |
| for (size_t i = 0; i < fetches.size(); ++i) { |
| ToWebServiceWorkerRequest(fetches[i].request, &web_fetches[i].request); |
| ToWebServiceWorkerResponse(fetches[i].response, &web_fetches[i].response); |
| } |
| |
| proxy_->DispatchBackgroundFetchedEvent( |
| request_id, blink::WebString::FromUTF8(tag), web_fetches); |
| } |
| |
| void ServiceWorkerContextClient::DispatchInstallEvent( |
| mojom::ServiceWorkerInstallEventMethodsAssociatedPtrInfo client, |
| DispatchInstallEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchInstallEvent"); |
| |
| int event_id = context_->install_event_callbacks.Add( |
| base::MakeUnique<DispatchInstallEventCallback>(std::move(callback))); |
| |
| DCHECK(!context_->install_methods_map.count(event_id)); |
| mojom::ServiceWorkerInstallEventMethodsAssociatedPtr install_methods; |
| install_methods.Bind(std::move(client)); |
| context_->install_methods_map[event_id] = std::move(install_methods); |
| |
| proxy_->DispatchInstallEvent(event_id); |
| } |
| |
| void ServiceWorkerContextClient::DispatchExtendableMessageEvent( |
| mojom::ExtendableMessageEventPtr event, |
| DispatchExtendableMessageEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchExtendableMessageEvent"); |
| int request_id = context_->message_event_callbacks.Add( |
| base::MakeUnique<DispatchExtendableMessageEventCallback>( |
| std::move(callback))); |
| |
| blink::WebMessagePortChannelArray ports = |
| WebMessagePortChannelImpl::CreateFromMessagePipeHandles( |
| std::move(event->message_ports)); |
| if (event->source.client_info.IsValid()) { |
| blink::WebServiceWorkerClientInfo web_client = |
| ToWebServiceWorkerClientInfo(event->source.client_info); |
| proxy_->DispatchExtendableMessageEvent( |
| request_id, blink::WebString::FromUTF16(event->message), |
| event->source_origin, std::move(ports), web_client); |
| return; |
| } |
| |
| DCHECK(event->source.service_worker_info.IsValid()); |
| std::unique_ptr<ServiceWorkerHandleReference> handle = |
| ServiceWorkerHandleReference::Adopt(event->source.service_worker_info, |
| sender_.get()); |
| ServiceWorkerDispatcher* dispatcher = |
| ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance( |
| sender_.get(), main_thread_task_runner_.get()); |
| scoped_refptr<WebServiceWorkerImpl> worker = |
| dispatcher->GetOrCreateServiceWorker(std::move(handle)); |
| proxy_->DispatchExtendableMessageEvent( |
| request_id, blink::WebString::FromUTF16(event->message), |
| event->source_origin, std::move(ports), |
| WebServiceWorkerImpl::CreateHandle(worker)); |
| } |
| |
| void ServiceWorkerContextClient::DispatchFetchEvent( |
| int fetch_event_id, |
| const ServiceWorkerFetchRequest& request, |
| mojom::FetchEventPreloadHandlePtr preload_handle, |
| mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, |
| DispatchFetchEventCallback callback) { |
| std::unique_ptr<NavigationPreloadRequest> preload_request = |
| preload_handle |
| ? base::MakeUnique<NavigationPreloadRequest>( |
| fetch_event_id, request.url, std::move(preload_handle)) |
| : nullptr; |
| const bool navigation_preload_sent = !!preload_request; |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchFetchEvent"); |
| context_->fetch_response_callbacks.insert( |
| std::make_pair(fetch_event_id, std::move(response_callback))); |
| context_->fetch_event_callbacks.insert( |
| std::make_pair(fetch_event_id, std::move(callback))); |
| if (preload_request) { |
| context_->preload_requests.AddWithID(std::move(preload_request), |
| fetch_event_id); |
| } |
| |
| blink::WebServiceWorkerRequest web_request; |
| ToWebServiceWorkerRequest(request, &web_request); |
| |
| if (request.fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) { |
| proxy_->DispatchForeignFetchEvent(fetch_event_id, web_request); |
| } else { |
| proxy_->DispatchFetchEvent(fetch_event_id, web_request, |
| navigation_preload_sent); |
| } |
| } |
| |
| void ServiceWorkerContextClient::DispatchNotificationClickEvent( |
| const std::string& notification_id, |
| const PlatformNotificationData& notification_data, |
| int action_index, |
| const base::Optional<base::string16>& reply, |
| DispatchNotificationClickEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchNotificationClickEvent"); |
| |
| int request_id = context_->notification_click_event_callbacks.Add( |
| base::MakeUnique<DispatchNotificationClickEventCallback>( |
| std::move(callback))); |
| |
| blink::WebString web_reply; |
| if (reply) |
| web_reply = blink::WebString::FromUTF16(reply.value()); |
| |
| proxy_->DispatchNotificationClickEvent( |
| request_id, blink::WebString::FromUTF8(notification_id), |
| ToWebNotificationData(notification_data), action_index, web_reply); |
| } |
| |
| void ServiceWorkerContextClient::DispatchNotificationCloseEvent( |
| const std::string& notification_id, |
| const PlatformNotificationData& notification_data, |
| DispatchNotificationCloseEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchNotificationCloseEvent"); |
| |
| int request_id = context_->notification_close_event_callbacks.Add( |
| base::MakeUnique<DispatchNotificationCloseEventCallback>( |
| std::move(callback))); |
| |
| proxy_->DispatchNotificationCloseEvent( |
| request_id, blink::WebString::FromUTF8(notification_id), |
| ToWebNotificationData(notification_data)); |
| } |
| |
| void ServiceWorkerContextClient::DispatchPushEvent( |
| const PushEventPayload& payload, |
| DispatchPushEventCallback callback) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchPushEvent"); |
| int request_id = context_->push_event_callbacks.Add( |
| base::MakeUnique<DispatchPushEventCallback>(std::move(callback))); |
| |
| // Only set data to be a valid string if the payload had decrypted data. |
| blink::WebString data; |
| if (!payload.is_null) |
| data.Assign(blink::WebString::FromUTF8(payload.data)); |
| proxy_->DispatchPushEvent(request_id, data); |
| } |
| |
| void ServiceWorkerContextClient::OnDidGetClient( |
| int request_id, |
| const ServiceWorkerClientInfo& client) { |
| TRACE_EVENT0("ServiceWorker", "ServiceWorkerContextClient::OnDidGetClient"); |
| blink::WebServiceWorkerClientCallbacks* callbacks = |
| context_->client_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client; |
| if (!client.IsEmpty()) { |
| DCHECK(client.IsValid()); |
| web_client.reset(new blink::WebServiceWorkerClientInfo( |
| ToWebServiceWorkerClientInfo(client))); |
| } |
| callbacks->OnSuccess(std::move(web_client)); |
| context_->client_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnDidGetClients( |
| int request_id, const std::vector<ServiceWorkerClientInfo>& clients) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnDidGetClients"); |
| blink::WebServiceWorkerClientsCallbacks* callbacks = |
| context_->clients_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| blink::WebServiceWorkerClientsInfo info; |
| blink::WebVector<blink::WebServiceWorkerClientInfo> convertedClients( |
| clients.size()); |
| for (size_t i = 0; i < clients.size(); ++i) |
| convertedClients[i] = ToWebServiceWorkerClientInfo(clients[i]); |
| info.clients.Swap(convertedClients); |
| callbacks->OnSuccess(info); |
| context_->clients_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnOpenWindowResponse( |
| int request_id, |
| const ServiceWorkerClientInfo& client) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnOpenWindowResponse"); |
| blink::WebServiceWorkerClientCallbacks* callbacks = |
| context_->client_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client; |
| if (!client.IsEmpty()) { |
| DCHECK(client.IsValid()); |
| web_client.reset(new blink::WebServiceWorkerClientInfo( |
| ToWebServiceWorkerClientInfo(client))); |
| } |
| callbacks->OnSuccess(std::move(web_client)); |
| context_->client_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnOpenWindowError( |
| int request_id, |
| const std::string& message) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnOpenWindowError"); |
| blink::WebServiceWorkerClientCallbacks* callbacks = |
| context_->client_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| callbacks->OnError(blink::WebServiceWorkerError( |
| blink::WebServiceWorkerError::kErrorTypeNavigation, |
| blink::WebString::FromUTF8(message))); |
| context_->client_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnFocusClientResponse( |
| int request_id, const ServiceWorkerClientInfo& client) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnFocusClientResponse"); |
| blink::WebServiceWorkerClientCallbacks* callback = |
| context_->client_callbacks.Lookup(request_id); |
| if (!callback) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| if (!client.IsEmpty()) { |
| DCHECK(client.IsValid()); |
| std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client( |
| new blink::WebServiceWorkerClientInfo( |
| ToWebServiceWorkerClientInfo(client))); |
| callback->OnSuccess(std::move(web_client)); |
| } else { |
| callback->OnError(blink::WebServiceWorkerError( |
| blink::WebServiceWorkerError::kErrorTypeNotFound, |
| "The WindowClient was not found.")); |
| } |
| |
| context_->client_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnNavigateClientResponse( |
| int request_id, |
| const ServiceWorkerClientInfo& client) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnNavigateClientResponse"); |
| blink::WebServiceWorkerClientCallbacks* callbacks = |
| context_->client_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client; |
| if (!client.IsEmpty()) { |
| DCHECK(client.IsValid()); |
| web_client.reset(new blink::WebServiceWorkerClientInfo( |
| ToWebServiceWorkerClientInfo(client))); |
| } |
| callbacks->OnSuccess(std::move(web_client)); |
| context_->client_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnNavigateClientError(int request_id, |
| const GURL& url) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnNavigateClientError"); |
| blink::WebServiceWorkerClientCallbacks* callbacks = |
| context_->client_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| std::string message = "Cannot navigate to URL: " + url.spec(); |
| callbacks->OnError(blink::WebServiceWorkerError( |
| blink::WebServiceWorkerError::kErrorTypeNavigation, |
| blink::WebString::FromUTF8(message))); |
| context_->client_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnDidSkipWaiting(int request_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnDidSkipWaiting"); |
| blink::WebServiceWorkerSkipWaitingCallbacks* callbacks = |
| context_->skip_waiting_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| callbacks->OnSuccess(); |
| context_->skip_waiting_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnDidClaimClients(int request_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnDidClaimClients"); |
| blink::WebServiceWorkerClientsClaimCallbacks* callbacks = |
| context_->claim_clients_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| callbacks->OnSuccess(); |
| context_->claim_clients_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::OnClaimClientsError( |
| int request_id, |
| blink::WebServiceWorkerError::ErrorType error_type, |
| const base::string16& message) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::OnClaimClientsError"); |
| blink::WebServiceWorkerClientsClaimCallbacks* callbacks = |
| context_->claim_clients_callbacks.Lookup(request_id); |
| if (!callbacks) { |
| NOTREACHED() << "Got stray response: " << request_id; |
| return; |
| } |
| callbacks->OnError(blink::WebServiceWorkerError( |
| error_type, blink::WebString::FromUTF16(message))); |
| context_->claim_clients_callbacks.Remove(request_id); |
| } |
| |
| void ServiceWorkerContextClient::Ping(PingCallback callback) { |
| std::move(callback).Run(); |
| } |
| |
| void ServiceWorkerContextClient::OnNavigationPreloadResponse( |
| int fetch_event_id, |
| std::unique_ptr<blink::WebURLResponse> response, |
| std::unique_ptr<blink::WebDataConsumerHandle> data_consumer_handle) { |
| proxy_->OnNavigationPreloadResponse(fetch_event_id, std::move(response), |
| std::move(data_consumer_handle)); |
| } |
| |
| void ServiceWorkerContextClient::OnNavigationPreloadError( |
| int fetch_event_id, |
| std::unique_ptr<blink::WebServiceWorkerError> error) { |
| proxy_->OnNavigationPreloadError(fetch_event_id, std::move(error)); |
| context_->preload_requests.Remove(fetch_event_id); |
| } |
| |
| void ServiceWorkerContextClient::OnNavigationPreloadComplete( |
| int fetch_event_id, |
| base::TimeTicks completion_time, |
| int64_t encoded_data_length, |
| int64_t encoded_body_length, |
| int64_t decoded_body_length) { |
| proxy_->OnNavigationPreloadComplete( |
| fetch_event_id, (completion_time - base::TimeTicks()).InSecondsF(), |
| encoded_data_length, encoded_body_length, decoded_body_length); |
| context_->preload_requests.Remove(fetch_event_id); |
| } |
| |
| base::WeakPtr<ServiceWorkerContextClient> |
| ServiceWorkerContextClient::GetWeakPtr() { |
| DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); |
| DCHECK(context_); |
| return context_->weak_factory.GetWeakPtr(); |
| } |
| |
| } // namespace content |