blob: 0e8e130c4f13d9c99d022a1a8a59872a4ceced09 [file] [log] [blame]
// Copyright 2018 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/service_worker_script_loader_factory.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
// A URLLoaderFactory that returns 200 OK with an empty javascript to any
// request.
// TODO(bashi): Avoid duplicated MockNetworkURLLoaderFactory. This is almost the
// same as EmbeddedWorkerTestHelper::MockNetworkURLLoaderFactory.
class MockNetworkURLLoaderFactory final
: public network::mojom::URLLoaderFactory {
public:
MockNetworkURLLoaderFactory() = default;
// network::mojom::URLLoaderFactory implementation.
void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& url_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override {
const std::string headers =
"HTTP/1.1 200 OK\n"
"Content-Type: application/javascript\n\n";
net::HttpResponseInfo info;
info.headers = new net::HttpResponseHeaders(
net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
network::ResourceResponseHead response;
response.headers = info.headers;
response.headers->GetMimeType(&response.mime_type);
client->OnReceiveResponse(response);
const std::string body = "/*this body came from the network*/";
uint32_t bytes_written = body.size();
mojo::DataPipe data_pipe;
data_pipe.producer_handle->WriteData(body.data(), &bytes_written,
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
network::URLLoaderCompletionStatus status;
status.error_code = net::OK;
client->OnComplete(status);
}
void Clone(network::mojom::URLLoaderFactoryRequest request) override {
bindings_.AddBinding(this, std::move(request));
}
private:
mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
DISALLOW_COPY_AND_ASSIGN(MockNetworkURLLoaderFactory);
};
} // namespace
class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
public:
ServiceWorkerScriptLoaderFactoryTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
~ServiceWorkerScriptLoaderFactoryTest() override = default;
void SetUp() override {
helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
ServiceWorkerContextCore* context = helper_->context();
context->storage()->LazyInitializeForTest(base::DoNothing());
base::RunLoop().RunUntilIdle();
scope_ = GURL("https://host/scope");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = scope_;
registration_ = base::MakeRefCounted<ServiceWorkerRegistration>(
options, 1L /* registration_id */, context->AsWeakPtr());
version_ = base::MakeRefCounted<ServiceWorkerVersion>(
registration_.get(), GURL("https://host/script.js"),
blink::mojom::ScriptType::kClassic, context->storage()->NewVersionId(),
context->AsWeakPtr());
provider_host_ = CreateProviderHostForServiceWorkerContext(
helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
version_.get(), context->AsWeakPtr(), &remote_endpoint_);
network_loader_factory_ = std::make_unique<MockNetworkURLLoaderFactory>();
helper_->SetNetworkFactory(network_loader_factory_.get());
factory_ = std::make_unique<ServiceWorkerScriptLoaderFactory>(
helper_->context()->AsWeakPtr(), provider_host_,
helper_->url_loader_factory_getter()->GetNetworkFactory());
}
protected:
network::mojom::URLLoaderPtr CreateTestLoaderAndStart(
network::TestURLLoaderClient* client) {
network::mojom::URLLoaderPtr loader;
network::ResourceRequest resource_request;
resource_request.url = scope_;
resource_request.resource_type = RESOURCE_TYPE_SERVICE_WORKER;
factory_->CreateLoaderAndStart(
mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */,
network::mojom::kURLLoadOptionNone, resource_request,
client->CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
return loader;
}
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
GURL scope_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
std::unique_ptr<MockNetworkURLLoaderFactory> network_loader_factory_;
std::unique_ptr<ServiceWorkerScriptLoaderFactory> factory_;
};
TEST_F(ServiceWorkerScriptLoaderFactoryTest, Success) {
network::TestURLLoaderClient client;
network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
client.RunUntilComplete();
EXPECT_EQ(net::OK, client.completion_status().error_code);
}
TEST_F(ServiceWorkerScriptLoaderFactoryTest, Redundant) {
version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
network::TestURLLoaderClient client;
network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
client.RunUntilComplete();
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
TEST_F(ServiceWorkerScriptLoaderFactoryTest, NoProviderHost) {
helper_->context()->RemoveProviderHost(provider_host_->provider_id());
network::TestURLLoaderClient client;
network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
client.RunUntilComplete();
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
TEST_F(ServiceWorkerScriptLoaderFactoryTest, ContextDestroyed) {
helper_->ShutdownContext();
base::RunLoop().RunUntilIdle();
network::TestURLLoaderClient client;
network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
client.RunUntilComplete();
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
}
} // namespace content