blob: ad5b6599bc14d7ee2d66efd66edb0522e10596e8 [file] [log] [blame]
// 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/feature_list.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.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/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_utils.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/public/renderer/worker_thread.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/web_data_consumer_handle_impl.h"
#include "content/renderer/loader/web_url_loader_impl.h"
#include "content/renderer/loader/web_url_request_util.h"
#include "content/renderer/notifications/notification_data_conversions.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/service_worker/controller_service_worker_impl.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_network_provider.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/service_worker_timeout_timer.h"
#include "content/renderer/service_worker/service_worker_type_converters.h"
#include "content/renderer/service_worker/service_worker_type_util.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.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 "services/network/public/cpp/features.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/modules/background_fetch/web_background_fetch_settled_fetch.h"
#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
#include "third_party/blink/public/platform/modules/payments/web_payment_handler_response.h"
#include "third_party/blink/public/platform/modules/payments/web_payment_request_event_data.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_client_query_options.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_blob_registry.h"
#include "third_party/blink/public/platform/web_referrer_policy.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h"
#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_proxy.h"
using blink::WebURLRequest;
using blink::MessagePortChannel;
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(WebURLRequest& request) override {
auto extra_data = std::make_unique<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(std::move(extra_data));
}
std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
const WebURLRequest& request,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
if (render_thread && provider_->script_loader_factory() &&
ServiceWorkerUtils::IsServicificationEnabled() &&
IsScriptRequest(request)) {
// TODO(crbug.com/796425): Temporarily wrap the raw
// mojom::URLLoaderFactory pointer into SharedURLLoaderFactory.
return std::make_unique<WebURLLoaderImpl>(
render_thread->resource_dispatcher(), std::move(task_runner),
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
provider_->script_loader_factory()));
}
return nullptr;
}
network::mojom::URLLoaderFactory* script_loader_factory() {
return provider_->script_loader_factory();
}
int ProviderID() const override { return provider_->provider_id(); }
private:
static bool IsScriptRequest(const WebURLRequest& request) {
auto request_context = request.GetRequestContext();
return request_context == WebURLRequest::kRequestContextServiceWorker ||
request_context == WebURLRequest::kRequestContextScript ||
request_context == WebURLRequest::kRequestContextImport;
}
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_;
};
WebURLRequest::RequestContext GetBlinkRequestContext(
RequestContextType request_context_type) {
return static_cast<WebURLRequest::RequestContext>(request_context_type);
}
blink::WebServiceWorkerClientInfo ToWebServiceWorkerClientInfo(
blink::mojom::ServiceWorkerClientInfoPtr client_info) {
DCHECK(!client_info->client_uuid.empty());
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 = client_info->frame_type;
web_client_info.client_type = client_info->client_type;
return web_client_info;
}
void ToWebServiceWorkerRequest(const network::ResourceRequest& request,
const std::string request_body_blob_uuid,
uint64_t request_body_blob_size,
blink::mojom::BlobPtrInfo request_body_blob,
const std::string& client_id,
std::vector<blink::mojom::BlobPtrInfo> blob_ptrs,
blink::WebServiceWorkerRequest* web_request) {
DCHECK(web_request);
web_request->SetURL(blink::WebURL(request.url));
web_request->SetMethod(blink::WebString::FromUTF8(request.method));
if (!request.headers.IsEmpty()) {
for (net::HttpRequestHeaders::Iterator it(request.headers); it.GetNext();) {
web_request->SetHeader(blink::WebString::FromUTF8(it.name()),
blink::WebString::FromUTF8(it.value()));
}
}
// Non-S13nServiceWorker: The body is provided as a blob.
if (request_body_blob) {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
mojo::ScopedMessagePipeHandle blob_pipe = request_body_blob.PassHandle();
web_request->SetBlob(blink::WebString::FromASCII(request_body_blob_uuid),
request_body_blob_size, std::move(blob_pipe));
}
// S13nServiceWorker: The body is provided in |request|.
else if (request.request_body) {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
// |blob_ptrs| should be empty when Network Service is enabled.
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
blob_ptrs.empty());
blink::WebHTTPBody body = GetWebHTTPBodyForRequestBodyWithBlobPtrs(
*request.request_body, std::move(blob_ptrs));
body.SetUniqueBoundary();
web_request->SetBody(body);
}
web_request->SetReferrer(blink::WebString::FromUTF8(request.referrer.spec()),
Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
request.referrer_policy));
web_request->SetMode(request.fetch_request_mode);
web_request->SetIsMainResourceLoad(ServiceWorkerUtils::IsMainResourceType(
static_cast<ResourceType>(request.resource_type)));
web_request->SetCredentialsMode(request.fetch_credentials_mode);
web_request->SetCacheMode(
ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(request.load_flags));
web_request->SetRedirectMode(request.fetch_redirect_mode);
web_request->SetRequestContext(GetBlinkRequestContext(
static_cast<RequestContextType>(request.fetch_request_context_type)));
web_request->SetFrameType(request.fetch_frame_type);
web_request->SetClientId(blink::WebString::FromUTF8(client_id));
web_request->SetIsReload(ui::PageTransitionCoreTypeIs(
static_cast<ui::PageTransition>(request.transition_type),
ui::PAGE_TRANSITION_RELOAD));
web_request->SetIntegrity(
blink::WebString::FromUTF8(request.fetch_integrity));
web_request->SetKeepalive(request.keepalive);
web_request->SetIsHistoryNavigation(request.transition_type &
ui::PAGE_TRANSITION_FORWARD_BACK);
}
// 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));
}
web_request->SetReferrer(
blink::WebString::FromUTF8(request.referrer.url.spec()),
request.referrer.policy);
web_request->SetMode(request.mode);
web_request->SetIsMainResourceLoad(request.is_main_resource_load);
web_request->SetCredentialsMode(request.credentials_mode);
web_request->SetCacheMode(request.cache_mode);
web_request->SetRedirectMode(request.redirect_mode);
web_request->SetRequestContext(
GetBlinkRequestContext(request.request_context_type));
web_request->SetFrameType(request.frame_type);
web_request->SetClientId(blink::WebString::FromUTF8(request.client_id));
web_request->SetIsReload(request.is_reload);
web_request->SetIntegrity(blink::WebString::FromUTF8(request.integrity));
web_request->SetKeepalive(request.keepalive);
web_request->SetIsHistoryNavigation(request.is_history_navigation);
}
// 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()) {
DCHECK(response.blob);
mojo::ScopedMessagePipeHandle blob_pipe;
if (response.blob)
blob_pipe = response.blob->Clone().PassInterface().PassHandle();
web_response->SetBlob(blink::WebString::FromASCII(response.blob_uuid),
response.blob_size, std::move(blob_pipe));
}
web_response->SetError(response.error);
web_response->SetResponseTime(response.response_time);
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));
}
// Finds an event callback keyed by |event_id| from |map|, and runs the callback
// with |args|. Returns true if the callback was found and called, otherwise
// returns false.
template <typename MapType, class... Args>
bool RunEventCallback(MapType* map,
ServiceWorkerTimeoutTimer* timer,
int event_id,
Args... args) {
auto iter = map->find(event_id);
// The event may have been aborted.
if (iter == map->end())
return false;
std::move(iter->second).Run(args...);
map->erase(iter);
timer->EndEvent(event_id);
return true;
}
// Creates a callback which takes an |event_id|, which calls the given event's
// callback with ABORTED status and removes it from |map|.
template <typename MapType, typename... Args>
base::OnceCallback<void(int /* event_id */)> CreateAbortCallback(MapType* map,
Args... args) {
return base::BindOnce(
[](MapType* map, Args... args, base::Time dispatched_time, int event_id) {
auto iter = map->find(event_id);
DCHECK(iter != map->end());
std::move(iter->second)
.Run(blink::mojom::ServiceWorkerEventStatus::ABORTED,
std::forward<Args>(args)..., dispatched_time);
map->erase(iter);
},
map, std::forward<Args>(args)..., base::Time::Now());
}
void DidGetClients(
std::unique_ptr<blink::WebServiceWorkerClientsCallbacks> callbacks,
std::vector<blink::mojom::ServiceWorkerClientInfoPtr> clients) {
blink::WebServiceWorkerClientsInfo info;
blink::WebVector<blink::WebServiceWorkerClientInfo> web_clients(
clients.size());
for (size_t i = 0; i < clients.size(); ++i)
web_clients[i] = ToWebServiceWorkerClientInfo(std::move(clients[i]));
info.clients.Swap(web_clients);
callbacks->OnSuccess(info);
}
void DidClaimClients(
std::unique_ptr<blink::WebServiceWorkerClientsClaimCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
const base::Optional<std::string>& error_msg) {
if (error != blink::mojom::ServiceWorkerErrorType::kNone) {
callbacks->OnError(blink::WebServiceWorkerError(
error, blink::WebString::FromUTF8(*error_msg)));
return;
}
DCHECK(!error_msg);
callbacks->OnSuccess();
}
void DidGetClient(
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks,
blink::mojom::ServiceWorkerClientInfoPtr client) {
std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client;
if (client) {
web_client = std::make_unique<blink::WebServiceWorkerClientInfo>(
ToWebServiceWorkerClientInfo(std::move(client)));
}
callbacks->OnSuccess(std::move(web_client));
}
void DidSkipWaiting(
std::unique_ptr<blink::WebServiceWorkerSkipWaitingCallbacks> callbacks,
bool success) {
// OnError() should not be called here since per spec the promise returned by
// skipWaiting() can never reject.
if (!success)
return;
callbacks->OnSuccess();
}
void DidOpenWindow(
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks,
bool success,
blink::mojom::ServiceWorkerClientInfoPtr client,
const base::Optional<std::string>& error_msg) {
if (!success) {
DCHECK(!client);
callbacks->OnError(blink::WebServiceWorkerError(
blink::mojom::ServiceWorkerErrorType::kNavigation,
blink::WebString::FromUTF8(*error_msg)));
return;
}
std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client;
if (client) {
web_client = std::make_unique<blink::WebServiceWorkerClientInfo>(
ToWebServiceWorkerClientInfo(std::move(client)));
}
callbacks->OnSuccess(std::move(web_client));
}
void DidFocusClient(
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks,
blink::mojom::ServiceWorkerClientInfoPtr client) {
if (!client) {
callbacks->OnError(blink::WebServiceWorkerError(
blink::mojom::ServiceWorkerErrorType::kNotFound,
"The client was not found."));
return;
}
auto web_client = std::make_unique<blink::WebServiceWorkerClientInfo>(
ToWebServiceWorkerClientInfo(std::move(client)));
callbacks->OnSuccess(std::move(web_client));
}
void DidNavigateClient(
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks,
bool success,
blink::mojom::ServiceWorkerClientInfoPtr client,
const base::Optional<std::string>& error_msg) {
if (!success) {
DCHECK(!client);
callbacks->OnError(blink::WebServiceWorkerError(
blink::mojom::ServiceWorkerErrorType::kNavigation,
blink::WebString::FromUTF8(*error_msg)));
return;
}
std::unique_ptr<blink::WebServiceWorkerClientInfo> web_client;
if (client) {
web_client = std::make_unique<blink::WebServiceWorkerClientInfo>(
ToWebServiceWorkerClientInfo(std::move(client)));
}
callbacks->OnSuccess(std::move(web_client));
}
} // namespace
// Holding data that needs to be bound to the worker context on the
// worker thread.
struct ServiceWorkerContextClient::WorkerContextData {
explicit WorkerContextData(ServiceWorkerContextClient* owner)
: event_dispatcher_binding(owner),
weak_factory(owner),
proxy_weak_factory(owner->proxy_) {}
~WorkerContextData() {
DCHECK(thread_checker.CalledOnValidThread());
}
// Map from version id to JavaScript ServiceWorker object.
std::map<int64_t, WebServiceWorkerImpl*> workers_;
mojo::Binding<mojom::ServiceWorkerEventDispatcher> event_dispatcher_binding;
// Bound by the first Mojo call received on the service worker thread
// ServiceWorkerEventDispatcher::InitializeGlobalScope().
blink::mojom::ServiceWorkerHostAssociatedPtr service_worker_host;
// Maps for inflight event callbacks.
// These are mapped from an event id issued from ServiceWorkerTimeoutTimer to
// the Mojo callback to notify the end of the event.
std::map<int, DispatchInstallEventCallback> install_event_callbacks;
std::map<int, DispatchActivateEventCallback> activate_event_callbacks;
std::map<int, DispatchBackgroundFetchAbortEventCallback>
background_fetch_abort_event_callbacks;
std::map<int, DispatchBackgroundFetchClickEventCallback>
background_fetch_click_event_callbacks;
std::map<int, DispatchBackgroundFetchFailEventCallback>
background_fetch_fail_event_callbacks;
std::map<int, DispatchBackgroundFetchedEventCallback>
background_fetched_event_callbacks;
std::map<int, DispatchSyncEventCallback> sync_event_callbacks;
std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
abort_payment_result_callbacks;
std::map<int, DispatchCanMakePaymentEventCallback>
abort_payment_event_callbacks;
std::map<int, DispatchCanMakePaymentEventCallback>
can_make_payment_event_callbacks;
std::map<int, DispatchPaymentRequestEventCallback>
payment_request_event_callbacks;
std::map<int, DispatchNotificationClickEventCallback>
notification_click_event_callbacks;
std::map<int, DispatchNotificationCloseEventCallback>
notification_close_event_callbacks;
std::map<int, DispatchPushEventCallback> push_event_callbacks;
std::map<int, DispatchFetchEventCallback> fetch_event_callbacks;
std::map<int, DispatchCookieChangeEventCallback>
cookie_change_event_callbacks;
std::map<int, DispatchExtendableMessageEventCallback> message_event_callbacks;
// Maps for response callbacks.
// These are mapped from an event id to the Mojo interface pointer which is
// passed from the relevant DispatchSomeEvent() method.
std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
can_make_payment_result_callbacks;
std::map<int, payments::mojom::PaymentHandlerResponseCallbackPtr>
payment_response_callbacks;
std::map<int, mojom::ServiceWorkerFetchResponseCallbackPtr>
fetch_response_callbacks;
// Inflight navigation preload requests.
base::IDMap<std::unique_ptr<NavigationPreloadRequest>> preload_requests;
// S13nServiceWorker
// Timer triggered when the service worker considers it should be stopped or
// an event should be aborted.
std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer;
// S13nServiceWorker
// |controller_impl| should be destroyed before |timeout_timer| since the
// pipe needs to be disconnected before callbacks passed by
// DispatchSomeEvent() get destructed, which may be stored in |timeout_timer|
// as parameters of pending tasks added after a termination request.
std::unique_ptr<ControllerServiceWorkerImpl> controller_impl;
base::ThreadChecker thread_checker;
base::WeakPtrFactory<ServiceWorkerContextClient> weak_factory;
base::WeakPtrFactory<blink::WebServiceWorkerContextProxy> proxy_weak_factory;
};
class ServiceWorkerContextClient::NavigationPreloadRequest final
: public network::mojom::URLLoaderClient {
public:
NavigationPreloadRequest(
int fetch_event_id,
const GURL& url,
blink::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 network::ResourceResponseHead& response_head) override {
DCHECK(!response_);
response_ = std::make_unique<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 network::ResourceResponseHead& response_head) override {
DCHECK(!response_);
DCHECK(net::HttpResponseHeaders::IsRedirectResponseCode(
response_head.headers->response_code()));
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
if (!client)
return;
response_ = std::make_unique<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 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 network::URLLoaderCompletionStatus& 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_),
std::make_unique<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_, std::make_unique<blink::WebServiceWorkerError>(
blink::mojom::ServiceWorkerErrorType::kNetwork,
blink::WebString::FromUTF8(message),
blink::WebString::FromUTF8(unsanitized_message)));
}
const int fetch_event_id_;
const GURL url_;
network::mojom::URLLoaderPtr url_loader_;
mojo::Binding<network::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,
bool is_starting_installed_worker,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
: embedded_worker_id_(embedded_worker_id),
service_worker_version_id_(service_worker_version_id),
service_worker_scope_(service_worker_scope),
script_url_(script_url),
is_starting_installed_worker_(is_starting_installed_worker),
main_thread_task_runner_(std::move(main_thread_task_runner)),
proxy_(nullptr),
pending_dispatcher_request_(std::move(dispatcher_request)),
pending_controller_request_(std::move(controller_request)),
embedded_worker_client_(std::move(embedded_worker_client)) {
instance_host_ =
mojom::ThreadSafeEmbeddedWorkerInstanceHostAssociatedPtr::Create(
std::move(instance_host), main_thread_task_runner_);
// Create a content::ServiceWorkerNetworkProvider for this data source so
// we can observe its requests.
pending_network_provider_ = ServiceWorkerNetworkProvider::CreateForController(
std::move(provider_info));
provider_context_ = pending_network_provider_->context();
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
"ServiceWorkerContextClient", this,
"script_url", script_url_.spec());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
"ServiceWorker", "LOAD_SCRIPT", this, "Source",
(is_starting_installed_worker_ ? "InstalledScriptsManager"
: "ResourceLoader"));
}
ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
scoped_refptr<WebServiceWorkerImpl>
ServiceWorkerContextClient::GetOrCreateServiceWorkerObject(
blink::mojom::ServiceWorkerObjectInfoPtr info) {
if (!info)
return nullptr;
auto found = context_->workers_.find(info->version_id);
if (found != context_->workers_.end()) {
return found->second;
}
return WebServiceWorkerImpl::CreateForServiceWorkerGlobalScope(
std::move(info));
}
void ServiceWorkerContextClient::GetClient(
const blink::WebString& id,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->GetClient(
id.Utf8(), base::BindOnce(&DidGetClient, std::move(callbacks)));
}
void ServiceWorkerContextClient::GetClients(
const blink::WebServiceWorkerClientQueryOptions& weboptions,
std::unique_ptr<blink::WebServiceWorkerClientsCallbacks> callbacks) {
DCHECK(callbacks);
auto options = blink::mojom::ServiceWorkerClientQueryOptions::New(
weboptions.include_uncontrolled, weboptions.client_type);
context_->service_worker_host->GetClients(
std::move(options), base::BindOnce(&DidGetClients, std::move(callbacks)));
}
void ServiceWorkerContextClient::OpenNewTab(
const blink::WebURL& url,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->OpenNewTab(
url, base::BindOnce(&DidOpenWindow, std::move(callbacks)));
}
void ServiceWorkerContextClient::OpenPaymentHandlerWindow(
const blink::WebURL& url,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->OpenPaymentHandlerWindow(
url, base::BindOnce(&DidOpenWindow, std::move(callbacks)));
}
void ServiceWorkerContextClient::SetCachedMetadata(const blink::WebURL& url,
const char* data,
size_t size) {
context_->service_worker_host->SetCachedMetadata(
url, std::vector<uint8_t>(data, data + size));
}
void ServiceWorkerContextClient::ClearCachedMetadata(const blink::WebURL& url) {
context_->service_worker_host->ClearCachedMetadata(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_)->OnStopped();
TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ServiceWorkerContextClient",
this, "Status", "WorkerContextFailedToStart");
DCHECK(embedded_worker_client_);
embedded_worker_client_->WorkerContextDestroyed();
}
void ServiceWorkerContextClient::WorkerScriptLoaded() {
if (!is_starting_installed_worker_)
(*instance_host_)->OnScriptLoaded();
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "LOAD_SCRIPT", this);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "START_WORKER_CONTEXT",
this);
}
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 nullptr if this context
// gets deleted before workerContextStarted() is called.
DCHECK(g_worker_client_tls.Pointer()->Get() == nullptr);
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));
DCHECK(pending_dispatcher_request_.is_pending());
DCHECK(pending_controller_request_.is_pending());
DCHECK(!context_->event_dispatcher_binding.is_bound());
DCHECK(!context_->controller_impl);
context_->event_dispatcher_binding.Bind(
std::move(pending_dispatcher_request_));
if (ServiceWorkerUtils::IsServicificationEnabled()) {
context_->controller_impl = std::make_unique<ControllerServiceWorkerImpl>(
std::move(pending_controller_request_), GetWeakPtr());
}
(*instance_host_)->OnThreadStarted(WorkerThread::GetCurrentId());
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_CONTEXT",
this);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this);
}
void ServiceWorkerContextClient::DidEvaluateClassicScript(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::BindOnce(&ServiceWorkerContextClient::SendWorkerStarted,
GetWeakPtr()));
TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "EVALUATE_SCRIPT", this,
"Status", success ? "Success" : "Failure");
}
void ServiceWorkerContextClient::DidInitializeWorkerContext(
v8::Local<v8::Context> context) {
GetContentClient()
->renderer()
->DidInitializeServiceWorkerContextOnWorkerThread(
context, service_worker_version_id_, service_worker_scope_,
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_ = nullptr;
blob_registry_.reset();
// 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(nullptr);
GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread(
context, service_worker_version_id_, service_worker_scope_, script_url_);
}
void ServiceWorkerContextClient::WorkerContextDestroyed() {
DCHECK(g_worker_client_tls.Pointer()->Get() == nullptr);
// 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::BindOnce(&EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed,
std::move(embedded_worker_client_)));
}
void ServiceWorkerContextClient::CountFeature(
blink::mojom::WebFeature feature) {
(*instance_host_)->CountFeature(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::DidHandleActivateEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleActivateEvent", "event_id",
request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->activate_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleBackgroundFetchAbortEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->background_fetch_abort_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleBackgroundFetchClickEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->background_fetch_click_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleBackgroundFetchFailEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->background_fetch_fail_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->background_fetched_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleCookieChangeEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleCookieChangeEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->cookie_change_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleExtendableMessageEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleExtendableMessageEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->message_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleInstallEvent(
int event_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleInstallEvent", "event_id",
event_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->install_event_callbacks,
context_->timeout_timer.get(), event_id, status,
proxy_->HasFetchEventHandler(),
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::RespondToFetchEventWithNoResponse(
int fetch_event_id,
double event_dispatch_time) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::RespondToFetchEventWithNoResponse",
"event_id", fetch_event_id);
DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id));
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) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::RespondToFetchEvent", "event_id",
fetch_event_id);
DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id));
ServiceWorkerResponse response(
GetServiceWorkerResponseFromWebResponse(web_response));
const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
context_->fetch_response_callbacks[fetch_event_id];
if (!response.blob_uuid.empty()) {
// TODO(falken): Can we just keep |response.blob| and call OnResponse
// directly?
blink::mojom::BlobPtr blob_ptr;
DCHECK(response.blob);
blob_ptr = response.blob->TakeBlobPtr();
response.blob = nullptr;
response_callback->OnResponseBlob(
response, std::move(blob_ptr),
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) {
TRACE_EVENT1(
"ServiceWorker",
"ServiceWorkerContextClient::RespondToFetchEventWithResponseStream",
"event_id", fetch_event_id);
DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id));
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();
DCHECK(body_as_stream->stream.is_valid());
web_body_as_stream->SetListener(
std::make_unique<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 event_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
// This TRACE_EVENT is used for perf benchmark to confirm if all of fetch
// events have completed. (crbug.com/736697)
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleFetchEvent", "event_id",
event_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
if (RunEventCallback(&context_->fetch_event_callbacks,
context_->timeout_timer.get(), event_id, status,
base::Time::FromDoubleT(event_dispatch_time))) {
context_->fetch_response_callbacks.erase(event_id);
}
}
void ServiceWorkerContextClient::DidHandleNotificationClickEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleNotificationClickEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->notification_click_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleNotificationCloseEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleNotificationCloseEvent",
"event_id", request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->notification_close_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandlePushEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandlePushEvent", "event_id",
request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->push_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::DidHandleSyncEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleSyncEvent", "event_id",
request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
RunEventCallback(&context_->sync_event_callbacks,
context_->timeout_timer.get(), request_id, status,
base::Time::FromDoubleT(event_dispatch_time));
}
void ServiceWorkerContextClient::RespondToAbortPaymentEvent(
int event_id,
bool payment_aborted,
double dispatch_event_time) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::RespondToAbortPaymentEvent",
"event_id", event_id);
DCHECK(base::ContainsKey(context_->abort_payment_result_callbacks, event_id));
const payments::mojom::PaymentHandlerResponseCallbackPtr& result_callback =
context_->abort_payment_result_callbacks[event_id];
result_callback->OnResponseForAbortPayment(
payment_aborted, base::Time::FromDoubleT(dispatch_event_time));
context_->abort_payment_result_callbacks.erase(event_id);
}
void ServiceWorkerContextClient::DidHandleAbortPaymentEvent(
int event_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleAbortPaymentEvent",
"event_id", event_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
if (RunEventCallback(&context_->abort_payment_event_callbacks,
context_->timeout_timer.get(), event_id, status,
base::Time::FromDoubleT(dispatch_event_time))) {
context_->abort_payment_result_callbacks.erase(event_id);
}
}
void ServiceWorkerContextClient::RespondToCanMakePaymentEvent(
int event_id,
bool can_make_payment,
double dispatch_event_time) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::RespondToCanMakePaymentEvent",
"event_id", event_id);
DCHECK(
base::ContainsKey(context_->can_make_payment_result_callbacks, event_id));
const payments::mojom::PaymentHandlerResponseCallbackPtr& result_callback =
context_->can_make_payment_result_callbacks[event_id];
result_callback->OnResponseForCanMakePayment(
can_make_payment, base::Time::FromDoubleT(dispatch_event_time));
context_->can_make_payment_result_callbacks.erase(event_id);
}
void ServiceWorkerContextClient::DidHandleCanMakePaymentEvent(
int event_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandleCanMakePaymentEvent",
"event_id", event_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
if (RunEventCallback(&context_->can_make_payment_event_callbacks,
context_->timeout_timer.get(), event_id, status,
base::Time::FromDoubleT(dispatch_event_time))) {
context_->can_make_payment_result_callbacks.erase(event_id);
}
}
void ServiceWorkerContextClient::RespondToPaymentRequestEvent(
int payment_request_id,
const blink::WebPaymentHandlerResponse& web_response,
double dispatch_event_time) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::RespondToPaymentRequestEvent",
"event_id", payment_request_id);
DCHECK(base::ContainsKey(context_->payment_response_callbacks,
payment_request_id));
const payments::mojom::PaymentHandlerResponseCallbackPtr& response_callback =
context_->payment_response_callbacks[payment_request_id];
payments::mojom::PaymentHandlerResponsePtr response =
payments::mojom::PaymentHandlerResponse::New();
response->method_name = web_response.method_name.Utf8();
response->stringified_details = web_response.stringified_details.Utf8();
response_callback->OnResponseForPaymentRequest(
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::mojom::ServiceWorkerEventStatus status,
double event_dispatch_time) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DidHandlePaymentRequestEvent",
"event_id", payment_request_id, "status",
ServiceWorkerUtils::MojoEnumToString(status));
if (RunEventCallback(&context_->payment_request_event_callbacks,
context_->timeout_timer.get(), payment_request_id,
status, base::Time::FromDoubleT(event_dispatch_time))) {
context_->payment_response_callbacks.erase(payment_request_id);
}
}
std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
ServiceWorkerContextClient::CreateServiceWorkerNetworkProvider() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
return std::make_unique<WebServiceWorkerNetworkProviderImpl>(
std::move(pending_network_provider_));
}
std::unique_ptr<blink::WebWorkerFetchContext>
ServiceWorkerContextClient::CreateServiceWorkerFetchContext(
blink::WebServiceWorkerNetworkProvider* provider) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
scoped_refptr<ChildURLLoaderFactoryBundle> url_loader_factory_bundle =
RenderThreadImpl::current()
->blink_platform_impl()
->CreateDefaultURLLoaderFactoryBundle();
DCHECK(url_loader_factory_bundle);
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
script_loader_factory_info;
if (ServiceWorkerUtils::IsServicificationEnabled()) {
// TODO(crbug.com/796425): Temporarily wrap the raw
// mojom::URLLoaderFactory pointer into SharedURLLoaderFactory.
script_loader_factory_info =
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
static_cast<WebServiceWorkerNetworkProviderImpl*>(provider)
->script_loader_factory())
->Clone();
}
return std::make_unique<ServiceWorkerFetchContextImpl>(
script_url_, url_loader_factory_bundle->Clone(),
std::move(script_loader_factory_info), provider_context_->provider_id(),
GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
URLLoaderThrottleProviderType::kWorker),
GetContentClient()
->renderer()
->CreateWebSocketHandshakeThrottleProvider());
}
std::unique_ptr<blink::WebServiceWorkerProvider>
ServiceWorkerContextClient::CreateServiceWorkerProvider() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
DCHECK(provider_context_);
return std::make_unique<WebServiceWorkerProviderImpl>(
provider_context_.get());
}
void ServiceWorkerContextClient::PostMessageToClient(
const blink::WebString& uuid,
blink::TransferableMessage message) {
context_->service_worker_host->PostMessageToClient(uuid.Utf8(),
std::move(message));
}
void ServiceWorkerContextClient::Focus(
const blink::WebString& uuid,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->FocusClient(
uuid.Utf8(), base::BindOnce(&DidFocusClient, std::move(callbacks)));
}
void ServiceWorkerContextClient::Navigate(
const blink::WebString& uuid,
const blink::WebURL& url,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->NavigateClient(
uuid.Utf8(), url,
base::BindOnce(&DidNavigateClient, std::move(callbacks)));
}
void ServiceWorkerContextClient::SkipWaiting(
std::unique_ptr<blink::WebServiceWorkerSkipWaitingCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->SkipWaiting(
base::BindOnce(&DidSkipWaiting, std::move(callbacks)));
}
void ServiceWorkerContextClient::Claim(
std::unique_ptr<blink::WebServiceWorkerClientsClaimCallbacks> callbacks) {
DCHECK(callbacks);
context_->service_worker_host->ClaimClients(
base::BindOnce(&DidClaimClients, std::move(callbacks)));
}
void ServiceWorkerContextClient::DispatchOrQueueFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) {
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DispatchOrQueueFetchEvent", "url",
params->request.url.spec(), "queued",
RequestedTermination() ? "true" : "false");
if (RequestedTermination()) {
context_->timeout_timer->PushPendingTask(base::BindOnce(
&ServiceWorkerContextClient::DispatchFetchEvent, GetWeakPtr(),
std::move(params), std::move(response_callback), std::move(callback)));
return;
}
DispatchFetchEvent(std::move(params), std::move(response_callback),
std::move(callback));
}
void ServiceWorkerContextClient::DispatchSyncEvent(
const std::string& tag,
bool last_chance,
base::TimeDelta timeout,
DispatchSyncEventCallback callback) {
int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
CreateAbortCallback(&context_->sync_event_callbacks), timeout);
context_->sync_event_callbacks.emplace(request_id, std::move(callback));
TRACE_EVENT1("ServiceWorker", "ServiceWorkerContextClient::DispatchSyncEvent",
"request_id", request_id);
// TODO(jkarlin): Make this blink::WebString::FromUTF8Lenient once
// https://crrev.com/1768063002/ lands.
proxy_->DispatchSyncEvent(request_id, blink::WebString::FromUTF8(tag),
last_chance);
}
void ServiceWorkerContextClient::DispatchAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchAbortPaymentEventCallback callback) {
int event_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->abort_payment_event_callbacks));
context_->abort_payment_event_callbacks.emplace(event_id,
std::move(callback));
context_->abort_payment_result_callbacks.emplace(
event_id, std::move(response_callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchAbortPaymentEvent",
"event_id", event_id);
proxy_->DispatchAbortPaymentEvent(event_id);
}
void ServiceWorkerContextClient::DispatchCanMakePaymentEvent(
payments::mojom::CanMakePaymentEventDataPtr eventData,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchCanMakePaymentEventCallback callback) {
int event_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->can_make_payment_event_callbacks));
context_->can_make_payment_event_callbacks.emplace(event_id,
std::move(callback));
context_->can_make_payment_result_callbacks.emplace(
event_id, std::move(response_callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchCanMakePaymentEvent",
"event_id", event_id);
blink::WebCanMakePaymentEventData webEventData =
mojo::ConvertTo<blink::WebCanMakePaymentEventData>(std::move(eventData));
proxy_->DispatchCanMakePaymentEvent(event_id, webEventData);
}
void ServiceWorkerContextClient::DispatchPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr eventData,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchPaymentRequestEventCallback callback) {
int event_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->payment_request_event_callbacks));
context_->payment_request_event_callbacks.emplace(event_id,
std::move(callback));
context_->payment_response_callbacks.emplace(event_id,
std::move(response_callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchPaymentRequestEvent",
"event_id", event_id);
blink::WebPaymentRequestEventData webEventData =
mojo::ConvertTo<blink::WebPaymentRequestEventData>(std::move(eventData));
proxy_->DispatchPaymentRequestEvent(event_id, webEventData);
}
void ServiceWorkerContextClient::SendWorkerStarted() {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
mojom::EmbeddedWorkerStartTimingPtr timing =
mojom::EmbeddedWorkerStartTiming::New();
timing->start_worker_received_time = start_worker_received_time_;
(*instance_host_)->OnStarted(std::move(timing));
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "ServiceWorkerContextClient",
this);
// Start the idle timer.
context_->timeout_timer =
std::make_unique<ServiceWorkerTimeoutTimer>(base::BindRepeating(
&ServiceWorkerContextClient::OnIdleTimeout, base::Unretained(this)));
}
void ServiceWorkerContextClient::DispatchActivateEvent(
DispatchActivateEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->activate_event_callbacks));
context_->activate_event_callbacks.emplace(request_id, std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchActivateEvent",
"request_id", request_id);
proxy_->DispatchActivateEvent(request_id);
}
void ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchAbortEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->background_fetch_abort_event_callbacks));
context_->background_fetch_abort_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent",
"request_id", request_id);
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_->DispatchBackgroundFetchAbortEvent(
request_id, blink::WebString::FromUTF8(developer_id),
blink::WebString::FromUTF8(unique_id), web_fetches);
}
void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent(
const std::string& developer_id,
mojom::BackgroundFetchState state,
DispatchBackgroundFetchClickEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->background_fetch_click_event_callbacks));
context_->background_fetch_click_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent",
"request_id", request_id);
// 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(developer_id), web_state);
}
void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchFailEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->background_fetch_fail_event_callbacks));
context_->background_fetch_fail_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent",
"request_id", request_id);
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(developer_id),
blink::WebString::FromUTF8(unique_id), web_fetches);
}
void ServiceWorkerContextClient::DispatchBackgroundFetchedEvent(
const std::string& developer_id,
const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchedEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->background_fetched_event_callbacks));
context_->background_fetched_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchBackgroundFetchedEvent",
"request_id", request_id);
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(developer_id),
blink::WebString::FromUTF8(unique_id), web_fetches);
}
void ServiceWorkerContextClient::InitializeGlobalScope(
blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info) {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
// Connect to the blink::mojom::ServiceWorkerHost.
DCHECK(!context_->service_worker_host);
context_->service_worker_host.Bind(std::move(service_worker_host));
// Set ServiceWorkerGlobalScope#registration.
DCHECK_NE(registration_info->registration_id,
blink::mojom::kInvalidServiceWorkerRegistrationId);
DCHECK(registration_info->host_ptr_info.is_valid());
DCHECK(registration_info->request.is_pending());
proxy_->SetRegistration(WebServiceWorkerRegistrationImpl::CreateHandle(
WebServiceWorkerRegistrationImpl::CreateForServiceWorkerGlobalScope(
std::move(registration_info))));
proxy_->ReadyToEvaluateScript();
}
void ServiceWorkerContextClient::DispatchInstallEvent(
DispatchInstallEventCallback callback) {
int event_id = context_->timeout_timer->StartEvent(CreateAbortCallback(
&context_->install_event_callbacks, false /* has_fetch_handler */));
context_->install_event_callbacks.emplace(event_id, std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchInstallEvent", "event_id",
event_id);
proxy_->DispatchInstallEvent(event_id);
}
void ServiceWorkerContextClient::DispatchExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
DispatchExtendableMessageEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->message_event_callbacks));
context_->message_event_callbacks.emplace(request_id, std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchExtendableMessageEvent",
"request_id", request_id);
if (event->source_info_for_client) {
blink::WebServiceWorkerClientInfo web_client =
ToWebServiceWorkerClientInfo(std::move(event->source_info_for_client));
proxy_->DispatchExtendableMessageEvent(request_id,
std::move(event->message),
event->source_origin, web_client);
return;
}
DCHECK_NE(event->source_info_for_service_worker->version_id,
blink::mojom::kInvalidServiceWorkerVersionId);
scoped_refptr<WebServiceWorkerImpl> worker = GetOrCreateServiceWorkerObject(
std::move(event->source_info_for_service_worker));
proxy_->DispatchExtendableMessageEvent(
request_id, std::move(event->message), event->source_origin,
WebServiceWorkerImpl::CreateHandle(worker));
}
// S13nServiceWorker
void ServiceWorkerContextClient::DispatchFetchEvent(
blink::mojom::DispatchFetchEventParamsPtr params,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
DispatchFetchEventCallback callback) {
int event_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->fetch_event_callbacks));
context_->fetch_event_callbacks.emplace(event_id, std::move(callback));
context_->fetch_response_callbacks.emplace(event_id,
std::move(response_callback));
// This TRACE_EVENT is used for perf benchmark to confirm if all of fetch
// events have completed. (crbug.com/736697)
TRACE_EVENT2("ServiceWorker",
"ServiceWorkerContextClient::DispatchFetchEvent", "event_id",
event_id, "url", params->request.url.spec());
// Set up for navigation preload (FetchEvent#preloadResponse) if needed.
const bool navigation_preload_sent = !!params->preload_handle;
if (navigation_preload_sent) {
SetupNavigationPreload(event_id, params->request.url,
std::move(params->preload_handle));
}
// Dispatch the event to the service worker execution context.
blink::WebServiceWorkerRequest web_request;
ToWebServiceWorkerRequest(
std::move(params->request), params->request_body_blob_uuid,
params->request_body_blob_size, std::move(params->request_body_blob),
params->client_id, std::move(params->request_body_blob_ptrs),
&web_request);
proxy_->DispatchFetchEvent(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) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->notification_click_event_callbacks));
context_->notification_click_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchNotificationClickEvent",
"request_id", request_id);
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) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->notification_close_event_callbacks));
context_->notification_close_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchNotificationCloseEvent",
"request_id", request_id);
proxy_->DispatchNotificationCloseEvent(
request_id, blink::WebString::FromUTF8(notification_id),
ToWebNotificationData(notification_data));
}
void ServiceWorkerContextClient::DispatchPushEvent(
const PushEventPayload& payload,
DispatchPushEventCallback callback) {
int request_id = context_->timeout_timer->StartEventWithCustomTimeout(
CreateAbortCallback(&context_->push_event_callbacks),
base::TimeDelta::FromSeconds(mojom::kPushEventTimeoutSeconds));
context_->push_event_callbacks.emplace(request_id, std::move(callback));
TRACE_EVENT1("ServiceWorker", "ServiceWorkerContextClient::DispatchPushEvent",
"request_id", request_id);
// Only set data to be a valid string if the payload had decrypted data.
blink::WebString data;
if (!payload.is_null)
data = blink::WebString::FromUTF8(payload.data);
proxy_->DispatchPushEvent(request_id, data);
}
void ServiceWorkerContextClient::DispatchCookieChangeEvent(
const net::CanonicalCookie& cookie,
::network::mojom::CookieChangeCause cause,
DispatchCookieChangeEventCallback callback) {
int request_id = context_->timeout_timer->StartEvent(
CreateAbortCallback(&context_->cookie_change_event_callbacks));
context_->cookie_change_event_callbacks.emplace(request_id,
std::move(callback));
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::DispatchCookieChangeEvent",
"request_id", request_id);
// After onion-souping, the conversion below will be done by mojo directly.
DCHECK(!cookie.IsHttpOnly());
base::Optional<blink::WebCanonicalCookie> web_cookie_opt =
blink::WebCanonicalCookie::Create(
blink::WebString::FromUTF8(cookie.Name()),
blink::WebString::FromUTF8(cookie.Value()),
blink::WebString::FromUTF8(cookie.Domain()),
blink::WebString::FromUTF8(cookie.Path()), cookie.CreationDate(),
cookie.ExpiryDate(), cookie.LastAccessDate(), cookie.IsSecure(),
false /* cookie.IsHttpOnly() */,
static_cast<network::mojom::CookieSameSite>(cookie.SameSite()),
static_cast<network::mojom::CookiePriority>(cookie.Priority()));
DCHECK(web_cookie_opt.has_value());
proxy_->DispatchCookieChangeEvent(request_id, web_cookie_opt.value(), cause);
}
void ServiceWorkerContextClient::Ping(PingCallback callback) {
std::move(callback).Run();
}
void ServiceWorkerContextClient::SetIdleTimerDelayToZero() {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(context_);
DCHECK(context_->timeout_timer);
context_->timeout_timer->SetIdleTimerDelayToZero();
}
void ServiceWorkerContextClient::OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<blink::WebURLResponse> response,
std::unique_ptr<blink::WebDataConsumerHandle> data_consumer_handle) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::OnNavigationPreloadResponse",
"event_id", fetch_event_id);
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) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::OnNavigationPreloadError",
"event_id", fetch_event_id);
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) {
TRACE_EVENT1("ServiceWorker",
"ServiceWorkerContextClient::OnNavigationPreloadComplete",
"event_id", fetch_event_id);
proxy_->OnNavigationPreloadComplete(fetch_event_id, completion_time,
encoded_data_length, encoded_body_length,
decoded_body_length);
context_->preload_requests.Remove(fetch_event_id);
}
void ServiceWorkerContextClient::SetupNavigationPreload(
int fetch_event_id,
const GURL& url,
blink::mojom::FetchEventPreloadHandlePtr preload_handle) {
auto preload_request = std::make_unique<NavigationPreloadRequest>(
fetch_event_id, url, std::move(preload_handle));
context_->preload_requests.AddWithID(std::move(preload_request),
fetch_event_id);
}
void ServiceWorkerContextClient::OnIdleTimeout() {
// ServiceWorkerTimeoutTimer::did_idle_timeout() returns true if
// ServiceWorkerContextClient::OnIdleTiemout() has been called. It means
// termination has been requested.
DCHECK(RequestedTermination());
(*instance_host_)->RequestTermination();
}
bool ServiceWorkerContextClient::RequestedTermination() const {
return context_->timeout_timer->did_idle_timeout();
}
void ServiceWorkerContextClient::AddServiceWorkerObject(
int64_t version_id,
WebServiceWorkerImpl* worker) {
DCHECK(!base::ContainsKey(context_->workers_, version_id));
context_->workers_[version_id] = worker;
}
void ServiceWorkerContextClient::RemoveServiceWorkerObject(int64_t version_id) {
DCHECK(base::ContainsKey(context_->workers_, version_id));
context_->workers_.erase(version_id);
}
bool ServiceWorkerContextClient::ContainsServiceWorkerObjectForTesting(
int64_t version_id) {
return base::ContainsKey(context_->workers_, version_id);
}
base::WeakPtr<ServiceWorkerContextClient>
ServiceWorkerContextClient::GetWeakPtr() {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
DCHECK(context_);
return context_->weak_factory.GetWeakPtr();
}
// static
void ServiceWorkerContextClient::ResetThreadSpecificInstanceForTesting() {
g_worker_client_tls.Pointer()->Set(nullptr);
}
void ServiceWorkerContextClient::SetTimeoutTimerForTesting(
std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer) {
DCHECK(context_);
context_->timeout_timer = std::move(timeout_timer);
}
} // namespace content