Commit e6721964 authored by Matt Falkenhagen's avatar Matt Falkenhagen Committed by Commit Bot

Reland: shared worker: Self-terminate when network service crashes.

This treats the network service crashing like the worker's process
crashing, and prevents clients getting stuck with a broken worker.

Originally landed at: https://chromium-review.googlesource.com/c/1260903
It was reverted because the test flaked because the host was sometimes
not yet created. The diff in the reland is to wait for the host
to be created.

Bug: 848256
Change-Id: Ic656f0bf5a320526cf6f7715399f8f71db05619b
Reviewed-on: https://chromium-review.googlesource.com/c/1264139Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597063}
parent 9be0b2b7
...@@ -811,12 +811,8 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ServiceWorkerFetch) { ...@@ -811,12 +811,8 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ServiceWorkerFetch) {
service_worker_context->RemoveObserver(&observer); service_worker_context->RemoveObserver(&observer);
} }
// Make sure fetch from shared worker context works after crash. // Make sure shared workers terminate after crash.
// IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, SharedWorker) {
// Disabled since shared workers don't support recovery from a NS crash:
// https://crbug.com/848256.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
DISABLED_SharedWorkerFetch) {
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context())); BrowserContext::GetDefaultStoragePartition(browser_context()));
...@@ -827,19 +823,23 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ...@@ -827,19 +823,23 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
// Navigate to the page and prepare a shared worker. // Navigate to the page and prepare a shared worker.
EXPECT_TRUE(NavigateToURL(shell(), page_url)); EXPECT_TRUE(NavigateToURL(shell(), page_url));
// Fetch from the shared worker. // Fetch from the shared worker to ensure it has started.
const std::string script = const std::string script =
"fetch_from_shared_worker('" + fetch_url.spec() + "');"; "fetch_from_shared_worker('" + fetch_url.spec() + "');";
EXPECT_EQ("Echo", EvalJs(shell(), script)); EXPECT_EQ("Echo", EvalJs(shell(), script));
// Crash the NetworkService process. Existing interfaces should receive error // There should be one worker host. We will later wait for it to terminate.
// notifications at some point. SharedWorkerServiceImpl* service = partition->GetSharedWorkerService();
EXPECT_EQ(1u, service->worker_hosts_.size());
base::RunLoop loop;
service->SetWorkerTerminationCallbackForTesting(loop.QuitClosure());
// Crash the NetworkService process.
SimulateNetworkServiceCrash(); SimulateNetworkServiceCrash();
// Flush the interface to make sure the error notification was received.
partition->FlushNetworkInterfaceForTesting();
// Fetch from the shared worker again. // Wait for the worker to detect the crash and self-terminate.
EXPECT_EQ("Echo", EvalJs(shell(), script)); loop.Run();
EXPECT_TRUE(service->worker_hosts_.empty());
} }
// Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared // Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared
......
...@@ -292,7 +292,9 @@ void SharedWorkerHost::Start( ...@@ -292,7 +292,9 @@ void SharedWorkerHost::Start(
} }
// This is similar to // This is similar to
// RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve. // RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve, but this
// host doesn't observe network service crashes. Instead, the renderer detects
// the connection error and terminates the worker.
void SharedWorkerHost::CreateNetworkFactory( void SharedWorkerHost::CreateNetworkFactory(
network::mojom::URLLoaderFactoryRequest request) { network::mojom::URLLoaderFactoryRequest request) {
network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParamsPtr params =
...@@ -303,9 +305,6 @@ void SharedWorkerHost::CreateNetworkFactory( ...@@ -303,9 +305,6 @@ void SharedWorkerHost::CreateNetworkFactory(
service_->storage_partition()->GetNetworkContext()->CreateURLLoaderFactory( service_->storage_partition()->GetNetworkContext()->CreateURLLoaderFactory(
std::move(request), std::move(params)); std::move(request), std::move(params));
// TODO(crbug.com/848256): Detect connection error and send a IPC with a new
// network factory like UpdateSubresourceLoaderFactories does for frames.
} }
void SharedWorkerHost::AllowFileSystem( void SharedWorkerHost::AllowFileSystem(
......
...@@ -297,6 +297,12 @@ void SharedWorkerServiceImpl::TerminateAllWorkersForTesting( ...@@ -297,6 +297,12 @@ void SharedWorkerServiceImpl::TerminateAllWorkersForTesting(
} }
} }
void SharedWorkerServiceImpl::SetWorkerTerminationCallbackForTesting(
base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
terminate_all_workers_callback_ = std::move(callback);
}
void SharedWorkerServiceImpl::ConnectToWorker( void SharedWorkerServiceImpl::ConnectToWorker(
int process_id, int process_id,
int frame_id, int frame_id,
...@@ -363,7 +369,7 @@ void SharedWorkerServiceImpl::DestroyHost(SharedWorkerHost* host) { ...@@ -363,7 +369,7 @@ void SharedWorkerServiceImpl::DestroyHost(SharedWorkerHost* host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
worker_hosts_.erase(worker_hosts_.find(host)); worker_hosts_.erase(worker_hosts_.find(host));
// Complete the call to TerminateAllWorkersForTesting if no more workers. // Run the termination callback if no more workers.
if (worker_hosts_.empty() && terminate_all_workers_callback_) if (worker_hosts_.empty() && terminate_all_workers_callback_)
std::move(terminate_all_workers_callback_).Run(); std::move(terminate_all_workers_callback_).Run();
} }
......
...@@ -54,6 +54,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService { ...@@ -54,6 +54,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
const url::Origin& constructor_origin) override; const url::Origin& constructor_origin) override;
void TerminateAllWorkersForTesting(base::OnceClosure callback); void TerminateAllWorkersForTesting(base::OnceClosure callback);
void SetWorkerTerminationCallbackForTesting(base::OnceClosure callback);
// Creates the worker if necessary or connects to an already existing worker. // Creates the worker if necessary or connects to an already existing worker.
void ConnectToWorker( void ConnectToWorker(
...@@ -72,6 +73,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService { ...@@ -72,6 +73,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
private: private:
friend class SharedWorkerServiceImplTest; friend class SharedWorkerServiceImplTest;
friend class SharedWorkerHostTest; friend class SharedWorkerHostTest;
FRIEND_TEST_ALL_PREFIXES(NetworkServiceRestartBrowserTest, SharedWorker);
static void AddAdditionalRequestHeaders( static void AddAdditionalRequestHeaders(
network::ResourceRequest* resource_request, network::ResourceRequest* resource_request,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "content/public/common/appcache_info.h" #include "content/public/common/appcache_info.h"
#include "content/public/common/content_client.h" #include "content/public/common/content_client.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h" #include "content/public/common/origin_util.h"
#include "content/public/common/renderer_preferences.h" #include "content/public/common/renderer_preferences.h"
#include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/content_renderer_client.h"
...@@ -202,6 +203,14 @@ class WebServiceWorkerNetworkProviderForSharedWorker ...@@ -202,6 +203,14 @@ class WebServiceWorkerNetworkProviderForSharedWorker
std::unique_ptr<NavigationResponseOverrideParameters> response_override_; std::unique_ptr<NavigationResponseOverrideParameters> response_override_;
}; };
// "ForSharedWorker" is to avoid collisions in Jumbo builds.
bool IsOutOfProcessNetworkServiceForSharedWorker() {
return base::FeatureList::IsEnabled(network::features::kNetworkService) &&
!base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess);
}
} // namespace } // namespace
EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
...@@ -217,7 +226,7 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( ...@@ -217,7 +226,7 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
network::mojom::URLLoaderFactoryAssociatedPtrInfo network::mojom::URLLoaderFactoryAssociatedPtrInfo
main_script_loader_factory, main_script_loader_factory,
blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params, blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle,
mojom::ControllerServiceWorkerInfoPtr controller_info, mojom::ControllerServiceWorkerInfoPtr controller_info,
mojom::SharedWorkerHostPtr host, mojom::SharedWorkerHostPtr host,
mojom::SharedWorkerRequest request, mojom::SharedWorkerRequest request,
...@@ -272,10 +281,30 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( ...@@ -272,10 +281,30 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
base::nullopt /* subresource_overrides */); base::nullopt /* subresource_overrides */);
} }
if (subresource_loader_factories) { // |factory_bundle| is provided in the
// ServiceWorkerServicification or NetworkService case.
DCHECK(factory_bundle ||
!blink::ServiceWorkerUtils::IsServicificationEnabled());
if (factory_bundle) {
// 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.
// The default factory might not be to the network service if a feature like
// AppCache set itself to the default, but treat a connection error as fatal
// anyway so clients don't get stuck.
if (IsOutOfProcessNetworkServiceForSharedWorker()) {
default_factory_connection_error_handler_holder_.Bind(
std::move(factory_bundle->default_factory_info()));
default_factory_connection_error_handler_holder_->Clone(
mojo::MakeRequest(&factory_bundle->default_factory_info()));
default_factory_connection_error_handler_holder_
.set_connection_error_handler(base::BindOnce(
&EmbeddedSharedWorkerStub::Terminate, base::Unretained(this)));
}
subresource_loader_factories_->Update( subresource_loader_factories_->Update(
std::make_unique<ChildURLLoaderFactoryBundleInfo>( std::make_unique<ChildURLLoaderFactoryBundleInfo>(
std::move(subresource_loader_factories), std::move(factory_bundle),
nullptr /* prefetch_loader_factory_info */), nullptr /* prefetch_loader_factory_info */),
base::nullopt /* subresource_overrides */); base::nullopt /* subresource_overrides */);
} }
...@@ -466,7 +495,7 @@ void EmbeddedSharedWorkerStub::Connect(int connection_request_id, ...@@ -466,7 +495,7 @@ void EmbeddedSharedWorkerStub::Connect(int connection_request_id,
} }
void EmbeddedSharedWorkerStub::Terminate() { void EmbeddedSharedWorkerStub::Terminate() {
// After this we wouldn't get any IPC for this stub. // After this we should ignore any IPC for this stub.
running_ = false; running_ = false;
impl_->TerminateWorkerContext(); impl_->TerminateWorkerContext();
} }
......
...@@ -148,6 +148,12 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, ...@@ -148,6 +148,12 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient,
// taking a resource pre-requested by the browser process. // taking a resource pre-requested by the browser process.
std::unique_ptr<NavigationResponseOverrideParameters> response_override_; std::unique_ptr<NavigationResponseOverrideParameters> response_override_;
// Out-of-process NetworkService:
// Detects disconnection from the default factory of the loader factory bundle
// used by this worker (typically the network service).
network::mojom::URLLoaderFactoryPtr
default_factory_connection_error_handler_holder_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedSharedWorkerStub); DISALLOW_COPY_AND_ASSIGN(EmbeddedSharedWorkerStub);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment