blob: ab886046c6e5a0411b7667a89d35e376e8923ae1 [file] [log] [blame]
// Copyright 2019 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/browser/service_worker/fake_embedded_worker_instance_client.h"
#include <utility>
#include "base/bind.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
namespace content {
FakeEmbeddedWorkerInstanceClient::FakeEmbeddedWorkerInstanceClient(
EmbeddedWorkerTestHelper* helper)
: helper_(helper), binding_(this), weak_factory_(this) {}
FakeEmbeddedWorkerInstanceClient::~FakeEmbeddedWorkerInstanceClient() = default;
base::WeakPtr<FakeEmbeddedWorkerInstanceClient>
FakeEmbeddedWorkerInstanceClient::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
void FakeEmbeddedWorkerInstanceClient::Bind(
blink::mojom::EmbeddedWorkerInstanceClientRequest request) {
binding_.Bind(std::move(request));
binding_.set_connection_error_handler(
base::BindOnce(&FakeEmbeddedWorkerInstanceClient::OnConnectionError,
base::Unretained(this)));
if (quit_closure_for_bind_)
std::move(quit_closure_for_bind_).Run();
}
void FakeEmbeddedWorkerInstanceClient::RunUntilBound() {
if (binding_)
return;
base::RunLoop loop;
quit_closure_for_bind_ = loop.QuitClosure();
loop.Run();
}
void FakeEmbeddedWorkerInstanceClient::Disconnect() {
binding_.Close();
OnConnectionError();
}
void FakeEmbeddedWorkerInstanceClient::StartWorker(
blink::mojom::EmbeddedWorkerStartParamsPtr params) {
host_.Bind(std::move(params->instance_host));
start_params_ = std::move(params);
helper_->OnServiceWorkerRequest(
std::move(start_params_->service_worker_request));
host_->OnReadyForInspection();
if (start_params_->is_installed) {
EvaluateScript();
return;
}
// In production, new service workers would request their main script here,
// which causes the browser to write the script response in service worker
// storage. We do that manually here.
//
// TODO(falken): For new workers, this should use
// |script_loader_factory_ptr_info| from |start_params_->provider_info|
// to request the script and the browser process should be able to mock it.
// For installed workers, the map should already be populated.
helper_->PopulateScriptCacheMap(
start_params_->service_worker_version_id,
base::BindOnce(
&FakeEmbeddedWorkerInstanceClient::DidPopulateScriptCacheMap,
GetWeakPtr()));
}
void FakeEmbeddedWorkerInstanceClient::StopWorker() {
host_->OnStopped();
// Destroys |this|. This matches the production implementation, which
// calls OnStopped() from the worker thread and then posts task
// to the EmbeddedWorkerInstanceClient to have it self-destruct.
OnConnectionError();
}
void FakeEmbeddedWorkerInstanceClient::ResumeAfterDownload() {
EvaluateScript();
}
void FakeEmbeddedWorkerInstanceClient::DidPopulateScriptCacheMap() {
host_->OnScriptLoaded();
if (start_params_->pause_after_download) {
// We continue when ResumeAfterDownload() is called.
return;
}
EvaluateScript();
}
void FakeEmbeddedWorkerInstanceClient::OnConnectionError() {
// Destroys |this|.
helper_->RemoveInstanceClient(this);
}
void FakeEmbeddedWorkerInstanceClient::EvaluateScript() {
host_->OnScriptEvaluationStart();
host_->OnStarted(blink::mojom::ServiceWorkerStartStatus::kNormalCompletion,
helper_->GetNextThreadId(),
blink::mojom::EmbeddedWorkerStartTiming::New());
}
DelayedFakeEmbeddedWorkerInstanceClient::
DelayedFakeEmbeddedWorkerInstanceClient(EmbeddedWorkerTestHelper* helper)
: FakeEmbeddedWorkerInstanceClient(helper) {}
DelayedFakeEmbeddedWorkerInstanceClient::
~DelayedFakeEmbeddedWorkerInstanceClient() = default;
void DelayedFakeEmbeddedWorkerInstanceClient::UnblockStartWorker() {
switch (start_state_) {
case State::kWontBlock:
case State::kCompleted:
break;
case State::kWillBlock:
start_state_ = State::kWontBlock;
break;
case State::kBlocked:
FakeEmbeddedWorkerInstanceClient::StartWorker(std::move(start_params_));
start_state_ = State::kCompleted;
break;
}
}
void DelayedFakeEmbeddedWorkerInstanceClient::UnblockStopWorker() {
switch (stop_state_) {
case State::kWontBlock:
case State::kCompleted:
break;
case State::kWillBlock:
stop_state_ = State::kWontBlock;
break;
case State::kBlocked:
// Destroys |this|.
CompleteStopWorker();
return;
}
}
void DelayedFakeEmbeddedWorkerInstanceClient::RunUntilStartWorker() {
switch (start_state_) {
case State::kBlocked:
case State::kCompleted:
return;
case State::kWontBlock:
case State::kWillBlock:
break;
}
base::RunLoop loop;
quit_closure_for_start_worker_ = loop.QuitClosure();
loop.Run();
}
void DelayedFakeEmbeddedWorkerInstanceClient::RunUntilStopWorker() {
switch (stop_state_) {
case State::kBlocked:
case State::kCompleted:
return;
case State::kWontBlock:
case State::kWillBlock:
break;
}
base::RunLoop loop;
quit_closure_for_stop_worker_ = loop.QuitClosure();
loop.Run();
}
void DelayedFakeEmbeddedWorkerInstanceClient::StartWorker(
blink::mojom::EmbeddedWorkerStartParamsPtr params) {
switch (start_state_) {
case State::kWontBlock:
FakeEmbeddedWorkerInstanceClient::StartWorker(std::move(params));
start_state_ = State::kCompleted;
break;
case State::kWillBlock:
start_params_ = std::move(params);
start_state_ = State::kBlocked;
break;
case State::kCompleted:
case State::kBlocked:
NOTREACHED();
break;
}
if (quit_closure_for_start_worker_)
std::move(quit_closure_for_start_worker_).Run();
}
void DelayedFakeEmbeddedWorkerInstanceClient::StopWorker() {
switch (stop_state_) {
case State::kWontBlock:
// Run the closure before destroying.
if (quit_closure_for_stop_worker_)
std::move(quit_closure_for_stop_worker_).Run();
// Destroys |this|.
CompleteStopWorker();
return;
case State::kWillBlock:
case State::kBlocked:
stop_state_ = State::kBlocked;
break;
case State::kCompleted:
NOTREACHED();
break;
}
if (quit_closure_for_stop_worker_)
std::move(quit_closure_for_stop_worker_).Run();
}
void DelayedFakeEmbeddedWorkerInstanceClient::CompleteStopWorker() {
if (!host()) {
// host() might not be bound if start never was called or is blocked.
DCHECK(start_params_);
host().Bind(std::move(start_params_->instance_host));
}
// Destroys |this|.
FakeEmbeddedWorkerInstanceClient::StopWorker();
}
} // namespace content