Commit 4555a6ec authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

Avoid starting a shared worker if the RenderFrameHost no longer exists

This will avoid starting a shared worker and immediately stopping it
because the client is destroyed right after.

The goal of this CL is to avoid sending a OnClientAdded notification to
SharedWorkerService observers for a frame that is already destroyed.

Bug: 993029
Change-Id: Idd075c13a751113a77b38474ff19e26bf8e9a1c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1835164
Commit-Queue: Patrick Monette <pmonette@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702751}
parent 876250a3
......@@ -490,6 +490,10 @@ void SharedWorkerHost::SetServiceWorkerHandle(
service_worker_handle_ = std::move(service_worker_handle);
}
bool SharedWorkerHost::HasClients() const {
return !clients_.empty();
}
mojo::Remote<blink::mojom::SharedWorker>
SharedWorkerHost::TerminateRemoteWorkerForTesting() {
mojo::Remote<blink::mojom::SharedWorker> worker = std::move(worker_);
......
......@@ -132,6 +132,9 @@ class CONTENT_EXPORT SharedWorkerHost
void SetServiceWorkerHandle(
std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle);
// Returns true if this worker is connected to at least one client.
bool HasClients() const;
const SharedWorkerInstance& instance() const { return instance_; }
int worker_process_id() const { return worker_process_id_; }
......
......@@ -346,6 +346,18 @@ void SharedWorkerServiceImpl::StartWorker(
return;
}
// Also drop this request if |client|'s render frame host no longer exists and
// the worker has no other clients. This is possible if the frame was deleted
// between the CreateWorker() and DidCreateScriptLoader() calls. This avoids
// starting a shared worker and immediately stopping it because its sole
// client is already being torn down and avoids sending a OnClientAdded()
// notification for a frame that is already destroyed.
if (!RenderFrameHost::FromID(client_process_id, frame_id) &&
!host->HasClients()) {
DestroyHost(host.get());
return;
}
// Get the factory used to instantiate the new shared worker instance in
// the target process.
mojo::PendingRemote<blink::mojom::SharedWorkerFactory> factory;
......
......@@ -289,6 +289,38 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
base::RunLoop().RunUntilIdle();
}
// Tests that the shared worker will not be started if the hosting web contents
// is destroyed while the script is being fetched.
TEST_F(SharedWorkerServiceImplTest, WebContentsDestroyed) {
std::unique_ptr<TestWebContents> web_contents =
CreateWebContents(GURL("http://example.com/"));
TestRenderFrameHost* render_frame_host = web_contents->GetMainFrame();
MockRenderProcessHost* renderer_host = render_frame_host->GetProcess();
const int process_id = renderer_host->GetID();
renderer_host->OverrideBinderForTesting(
blink::mojom::SharedWorkerFactory::Name_,
base::BindRepeating(&SharedWorkerServiceImplTest::BindSharedWorkerFactory,
base::Unretained(this), process_id));
MockSharedWorkerClient client;
MessagePortChannel local_port;
const GURL kUrl("http://example.com/w.js");
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host, render_frame_host->GetRoutingID()),
kUrl, "name", &client, &local_port);
// Now asynchronously destroy |web_contents| so that the startup sequence at
// least reaches SharedWorkerServiceImpl::DidCreateScriptLoader().
// reaches at least the DidCreateScriptLoader()
base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
std::move(web_contents));
base::RunLoop().RunUntilIdle();
// The shared worker creation request was dropped.
EXPECT_TRUE(!client.CheckReceivedOnCreated());
}
TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
// The first renderer host.
std::unique_ptr<TestWebContents> web_contents0 =
......
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