blob: 65a66ec426b8a105bca22672235291f64149bdcb [file] [log] [blame]
// Copyright 2014 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/worker/embedded_shared_worker_stub.h"
#include <stdint.h>
#include <utility>
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/origin_util.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/web_worker_fetch_context_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "ipc/ipc_message_macros.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/web/web_shared_worker.h"
#include "third_party/blink/public/web/web_shared_worker_client.h"
#include "url/origin.h"
namespace content {
EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
blink::mojom::SharedWorkerInfoPtr info,
const std::string& user_agent,
bool pause_on_start,
const base::UnguessableToken& devtools_worker_token,
const blink::mojom::RendererPreferences& renderer_preferences,
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
preference_watcher_receiver,
mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
content_settings,
blink::mojom::ServiceWorkerProviderInfoForClientPtr
service_worker_provider_info,
const base::UnguessableToken& appcache_host_id,
blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
subresource_loader_factory_bundle_info,
blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
mojo::PendingRemote<blink::mojom::SharedWorkerHost> host,
mojo::PendingReceiver<blink::mojom::SharedWorker> receiver,
service_manager::mojom::InterfaceProviderPtr interface_provider,
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker)
: receiver_(this, std::move(receiver)),
host_(std::move(host)),
url_(info->url),
renderer_preferences_(renderer_preferences),
preference_watcher_receiver_(std::move(preference_watcher_receiver)) {
DCHECK(main_script_load_params);
DCHECK(subresource_loader_factory_bundle_info);
// Initialize the response override for the main worker script loaded by the
// browser process.
response_override_ = std::make_unique<NavigationResponseOverrideParameters>();
response_override_->url_loader_client_endpoints =
std::move(main_script_load_params->url_loader_client_endpoints);
response_override_->response_head =
std::move(main_script_load_params->response_head);
response_override_->response_body =
std::move(main_script_load_params->response_body);
response_override_->redirect_responses =
std::move(main_script_load_params->redirect_response_heads);
response_override_->redirect_infos = main_script_load_params->redirect_infos;
// If the network service crashes, then self-destruct so clients don't get
// stuck with a worker with a broken loader. Self-destruction is effectively
// the same as the worker's process crashing.
if (IsOutOfProcessNetworkService()) {
default_factory_connection_error_handler_holder_.Bind(std::move(
subresource_loader_factory_bundle_info->pending_default_factory()));
default_factory_connection_error_handler_holder_->Clone(
subresource_loader_factory_bundle_info->pending_default_factory()
.InitWithNewPipeAndPassReceiver());
default_factory_connection_error_handler_holder_
.set_connection_error_handler(base::BindOnce(
&EmbeddedSharedWorkerStub::Terminate, base::Unretained(this)));
}
// Initialize the subresource loader factory bundle passed by the browser
// process.
subresource_loader_factory_bundle_ =
base::MakeRefCounted<ChildURLLoaderFactoryBundle>(
std::make_unique<ChildURLLoaderFactoryBundleInfo>(
std::move(subresource_loader_factory_bundle_info)));
if (service_worker_provider_info) {
service_worker_provider_context_ =
base::MakeRefCounted<ServiceWorkerProviderContext>(
blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker,
std::move(service_worker_provider_info->client_receiver),
std::move(service_worker_provider_info->host_remote),
std::move(controller_info), subresource_loader_factory_bundle_);
}
impl_ = blink::WebSharedWorker::Create(this);
impl_->StartWorkerContext(
url_, blink::WebString::FromUTF8(info->name),
blink::WebString::FromUTF8(user_agent),
blink::WebString::FromUTF8(info->content_security_policy),
info->content_security_policy_type, info->creation_address_space,
appcache_host_id, devtools_worker_token, content_settings.PassPipe(),
interface_provider.PassInterface().PassHandle(),
browser_interface_broker.PassPipe(), pause_on_start);
// If the host drops its connection, then self-destruct.
receiver_.set_disconnect_handler(base::BindOnce(
&EmbeddedSharedWorkerStub::Terminate, base::Unretained(this)));
}
EmbeddedSharedWorkerStub::~EmbeddedSharedWorkerStub() {
// Destruction closes our connection to the host, triggering the host to
// cleanup and notify clients of this worker going away.
}
void EmbeddedSharedWorkerStub::WorkerReadyForInspection(
mojo::ScopedMessagePipeHandle devtools_agent_remote_handle,
mojo::ScopedMessagePipeHandle devtools_agent_host_receiver_handle) {
mojo::PendingRemote<blink::mojom::DevToolsAgent> remote(
std::move(devtools_agent_remote_handle),
blink::mojom::DevToolsAgent::Version_);
mojo::PendingReceiver<blink::mojom::DevToolsAgentHost> receiver(
std::move(devtools_agent_host_receiver_handle));
host_->OnReadyForInspection(std::move(remote), std::move(receiver));
}
void EmbeddedSharedWorkerStub::WorkerScriptLoadFailed() {
host_->OnScriptLoadFailed();
pending_channels_.clear();
}
void EmbeddedSharedWorkerStub::WorkerScriptEvaluated(bool success) {
DCHECK(!running_);
running_ = true;
// Process any pending connections.
for (auto& item : pending_channels_)
ConnectToChannel(item.first, std::move(item.second));
pending_channels_.clear();
}
void EmbeddedSharedWorkerStub::CountFeature(blink::mojom::WebFeature feature) {
host_->OnFeatureUsed(feature);
}
void EmbeddedSharedWorkerStub::WorkerContextClosed() {
host_->OnContextClosed();
}
void EmbeddedSharedWorkerStub::WorkerContextDestroyed() {
delete this;
}
scoped_refptr<blink::WebWorkerFetchContext>
EmbeddedSharedWorkerStub::CreateWorkerFetchContext() {
// Make the factory used for service worker network fallback (that should
// skip AppCache if it is provided).
std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory =
subresource_loader_factory_bundle_->CloneWithoutAppCacheFactory();
scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context =
WebWorkerFetchContextImpl::Create(
service_worker_provider_context_.get(),
std::move(renderer_preferences_),
std::move(preference_watcher_receiver_),
subresource_loader_factory_bundle_->Clone(),
std::move(fallback_factory));
// TODO(horo): To get the correct first_party_to_cookies for the shared
// worker, we need to check the all documents bounded by the shared worker.
// (crbug.com/723553)
// https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-07#section-2.1.2
worker_fetch_context->set_site_for_cookies(url_);
worker_fetch_context->set_origin_url(url_.GetOrigin());
DCHECK(response_override_);
worker_fetch_context->SetResponseOverrideForMainScript(
std::move(response_override_));
return worker_fetch_context;
}
void EmbeddedSharedWorkerStub::ConnectToChannel(
int connection_request_id,
blink::MessagePortChannel channel) {
impl_->Connect(std::move(channel));
host_->OnConnected(connection_request_id);
}
void EmbeddedSharedWorkerStub::Connect(int connection_request_id,
mojo::ScopedMessagePipeHandle port) {
blink::MessagePortChannel channel(std::move(port));
if (running_) {
ConnectToChannel(connection_request_id, std::move(channel));
} else {
// If two documents try to load a SharedWorker at the same time, the
// mojom::SharedWorker::Connect() for one of the documents can come in
// before the worker is started. Just queue up the connect and deliver it
// once the worker starts.
pending_channels_.emplace_back(connection_request_id, std::move(channel));
}
}
void EmbeddedSharedWorkerStub::Terminate() {
// After this we should ignore any IPC for this stub.
running_ = false;
impl_->TerminateWorkerContext();
}
} // namespace content