Commit 558b5c42 authored by Kenichi Ishibashi's avatar Kenichi Ishibashi Committed by Commit Bot

Introduce ServiceWorkerResourceMetadataWriter

This CL adds ServiceWorkerResourceMetadataWriter which will be used by
browser/embedders to write metadata (V8 code cache) to storage. This
will be used after ServiceWorkerStorage is migrated to the storage
service.

Bug: 1055677
Change-Id: If2a18d89ce5483f8c4792c78309eceeedbdc22d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2138659
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#758183}
parent 6e07cdbd
......@@ -39,22 +39,35 @@ enum ServiceWorkerStorageOriginState {
// An interface that reads a service worker script (resource) to storage.
interface ServiceWorkerResourceReader {
// Reads the response head of the resource associated with this reader.
// |status| is the number of bytes read, or a //net error.
// Also returns metadata associated with the resource if it exists.
ReadResponseHead() =>
(int32 status, network.mojom.URLResponseHead response_head);
(int32 status,
network.mojom.URLResponseHead response_head,
mojo_base.mojom.BigBuffer? metadata);
// Reads the content of the resource associated with this reader.
ReadData(int64 size) => (handle<data_pipe_consumer> pipe);
// TODO(crbug.com/1055677): Add ways to read the metadata of the script.
};
// An interface that writes a service worker script (resource) to storage.
interface ServiceWorkerResourceWriter {
// Writes the response head to storage.
// Writes the response head to storage. Returns the number of bytes written,
// or a //net error.
WriteResponseHead(network.mojom.URLResponseHead response_head)
=> (int32 status);
// Write the content of the resource to storage.
// Writes the content of the resource to storage. Returns the number of bytes
// written, or a //net error.
WriteData(mojo_base.mojom.BigBuffer data) => (int32 status);
};
// An interface that writes a metadata (script cache) of a service worker script
// to storage.
interface ServiceWorkerResourceMetadataWriter {
// Writes the metadata of the resource associated with this writer. Returns
// the number of bytes written, or a //net error.
WriteMetadata(mojo_base.mojom.BigBuffer data) => (int32 status);
};
// Controls the state of service worker storage within a partition. This is a
// privileged interface and must not be brokered to untrusted clients.
//
......@@ -105,4 +118,8 @@ interface ServiceWorkerStorageControl {
// Creates a resource writer for the given |resource_id|.
CreateResourceWriter(int64 resource_id,
pending_receiver<ServiceWorkerResourceWriter> writer);
// Creates a metadata writer for the given |resource_id|.
CreateResourceMetadataWriter(
int64 resource_id,
pending_receiver<ServiceWorkerResourceMetadataWriter> writer);
};
......@@ -48,7 +48,8 @@ void DidReadInfo(
const net::HttpResponseInfo* http_info = buffer->http_info.get();
if (!http_info) {
DCHECK_LT(status, 0);
std::move(callback).Run(status, /*response_head=*/nullptr);
std::move(callback).Run(status, /*response_head=*/nullptr,
/*metadata=*/base::nullopt);
return;
}
......@@ -73,7 +74,13 @@ void DidReadInfo(
head->cert_status = http_info->ssl_info.cert_status;
head->ssl_info = http_info->ssl_info;
std::move(callback).Run(status, std::move(head));
base::Optional<mojo_base::BigBuffer> metadata;
if (http_info->metadata) {
metadata = mojo_base::BigBuffer(base::as_bytes(base::make_span(
http_info->metadata->data(), http_info->metadata->size())));
}
std::move(callback).Run(status, std::move(head), std::move(metadata));
}
} // namespace
......@@ -254,4 +261,22 @@ void ServiceWorkerResourceWriterImpl::WriteData(mojo_base::BigBuffer data,
writer_->WriteData(buffer.get(), buf_len, std::move(callback));
}
ServiceWorkerResourceMetadataWriterImpl::
ServiceWorkerResourceMetadataWriterImpl(
std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer)
: writer_(std::move(writer)) {
DCHECK(writer_);
}
ServiceWorkerResourceMetadataWriterImpl::
~ServiceWorkerResourceMetadataWriterImpl() = default;
void ServiceWorkerResourceMetadataWriterImpl::WriteMetadata(
mojo_base::BigBuffer data,
WriteMetadataCallback callback) {
int buf_len = data.size();
auto buffer = base::MakeRefCounted<BigIOBuffer>(std::move(data));
writer_->WriteMetadata(buffer.get(), buf_len, std::move(callback));
}
} // namespace content
......@@ -72,6 +72,32 @@ class ServiceWorkerResourceWriterImpl
const std::unique_ptr<ServiceWorkerResponseWriter> writer_;
};
// The implementation of storage::mojom::ServiceWorkerResourceMetadataWriter.
// Currently this class is an adaptor that uses
// ServiceWorkerResponseMetadataWriter internally.
// TODO(crbug.com/1055677): Fork the implementation of
// ServiceWorkerResponseMetadataWriter and stop using it.
class ServiceWorkerResourceMetadataWriterImpl
: public storage::mojom::ServiceWorkerResourceMetadataWriter {
public:
explicit ServiceWorkerResourceMetadataWriterImpl(
std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer);
ServiceWorkerResourceMetadataWriterImpl(
const ServiceWorkerResourceMetadataWriterImpl&) = delete;
ServiceWorkerResourceMetadataWriterImpl& operator=(
const ServiceWorkerResourceMetadataWriterImpl&) = delete;
~ServiceWorkerResourceMetadataWriterImpl() override;
private:
// storage::mojom::ServiceWorkerResourceMetadataWriter implementations:
void WriteMetadata(mojo_base::BigBuffer data,
WriteMetadataCallback callback) override;
const std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer_;
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_RESOURCE_OPS_H_
......@@ -163,4 +163,15 @@ void ServiceWorkerStorageControlImpl::CreateResourceWriter(
std::move(writer));
}
void ServiceWorkerStorageControlImpl::CreateResourceMetadataWriter(
int64_t resource_id,
mojo::PendingReceiver<storage::mojom::ServiceWorkerResourceMetadataWriter>
writer) {
DCHECK_NE(resource_id, blink::mojom::kInvalidServiceWorkerResourceId);
mojo::MakeSelfOwnedReceiver(
std::make_unique<ServiceWorkerResourceMetadataWriterImpl>(
storage_->CreateResponseMetadataWriter(resource_id)),
std::move(writer));
}
} // namespace content
......@@ -65,6 +65,10 @@ class CONTENT_EXPORT ServiceWorkerStorageControlImpl
int64_t resource_id,
mojo::PendingReceiver<storage::mojom::ServiceWorkerResourceWriter> writer)
override;
void CreateResourceMetadataWriter(
int64_t resource_id,
mojo::PendingReceiver<storage::mojom::ServiceWorkerResourceMetadataWriter>
writer) override;
const std::unique_ptr<ServiceWorkerStorage> storage_;
};
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string.h>
#include "content/browser/service_worker/service_worker_storage_control_impl.h"
#include "base/containers/span.h"
......@@ -29,13 +31,16 @@ using FindRegistrationResult =
namespace {
int ReadResponseHead(storage::mojom::ServiceWorkerResourceReader* reader,
network::mojom::URLResponseHeadPtr& out_response_head) {
network::mojom::URLResponseHeadPtr& out_response_head,
base::Optional<mojo_base::BigBuffer>& out_metadata) {
int return_value;
base::RunLoop loop;
reader->ReadResponseHead(base::BindLambdaForTesting(
[&](int result, network::mojom::URLResponseHeadPtr response_head) {
[&](int result, network::mojom::URLResponseHeadPtr response_head,
base::Optional<mojo_base::BigBuffer> metadata) {
return_value = result;
out_response_head = std::move(response_head);
out_metadata = std::move(metadata);
loop.Quit();
}));
loop.Run();
......@@ -83,6 +88,20 @@ int WriteResponseData(storage::mojom::ServiceWorkerResourceWriter* writer,
return return_value;
}
int WriteResponseMetadata(
storage::mojom::ServiceWorkerResourceMetadataWriter* writer,
mojo_base::BigBuffer metadata) {
int return_value;
base::RunLoop loop;
writer->WriteMetadata(std::move(metadata),
base::BindLambdaForTesting([&](int result) {
return_value = result;
loop.Quit();
}));
loop.Run();
return return_value;
}
} // namespace
class ServiceWorkerStorageControlImplTest : public testing::Test {
......@@ -271,6 +290,14 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
return writer;
}
mojo::Remote<storage::mojom::ServiceWorkerResourceMetadataWriter>
CreateResourceMetadataWriter(int64_t resource_id) {
mojo::Remote<storage::mojom::ServiceWorkerResourceMetadataWriter> writer;
storage()->CreateResourceMetadataWriter(
resource_id, writer.BindNewPipeAndPassReceiver());
return writer;
}
private:
base::ScopedTempDir user_data_directory_;
BrowserTaskEnvironment task_environment_;
......@@ -472,10 +499,12 @@ TEST_F(ServiceWorkerStorageControlImplTest, WriteAndReadResource) {
mojo::Remote<storage::mojom::ServiceWorkerResourceReader> reader =
CreateResourceReader(resource_id);
// Read the response head and the content.
// Read the response head, metadata and the content.
{
network::mojom::URLResponseHeadPtr response_head;
int result = ReadResponseHead(reader.get(), response_head);
base::Optional<mojo_base::BigBuffer> response_metadata;
int result =
ReadResponseHead(reader.get(), response_head, response_metadata);
ASSERT_GT(result, 0);
EXPECT_EQ(response_head->mime_type, "application/javascript");
......@@ -483,12 +512,37 @@ TEST_F(ServiceWorkerStorageControlImplTest, WriteAndReadResource) {
EXPECT_TRUE(response_head->ssl_info->is_valid());
EXPECT_EQ(response_head->ssl_info->cert->serial_number(),
ssl_info.cert->serial_number());
EXPECT_EQ(response_metadata, base::nullopt);
std::string data = ReadResponseData(reader.get(), data_size);
EXPECT_EQ(data, kData);
}
// TODO(crbug.com/1055677): Write metadata, read it then check the metadata.
const auto kMetadata = base::as_bytes(base::make_span("metadata"));
int metadata_size = kMetadata.size();
// Write metadata.
{
mojo::Remote<storage::mojom::ServiceWorkerResourceMetadataWriter>
metadata_writer = CreateResourceMetadataWriter(resource_id);
int result = WriteResponseMetadata(metadata_writer.get(),
mojo_base::BigBuffer(kMetadata));
ASSERT_EQ(result, metadata_size);
}
// Read the response head again. This time metadata should be read.
{
network::mojom::URLResponseHeadPtr response_head;
base::Optional<mojo_base::BigBuffer> response_metadata;
int result =
ReadResponseHead(reader.get(), response_head, response_metadata);
ASSERT_GT(result, 0);
ASSERT_TRUE(response_metadata.has_value());
EXPECT_EQ(response_metadata->size(), kMetadata.size());
EXPECT_EQ(
memcmp(response_metadata->data(), kMetadata.data(), kMetadata.size()),
0);
}
}
} // namespace content
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