Commit 692e7e03 authored by Kenichi Ishibashi's avatar Kenichi Ishibashi Committed by Commit Bot

service worker: Add an interface to notify resource write completion

This CL introduces a mojo interface that works as a client of
ServiceWorkerResourceReader. Call sites of the reader can pass
a remote that implements the interface to receive OnComplete()
notification. This kind of notification is required to replace
old resource reader in ServiceWorkerInstalledScriptReader.

Bug: 1055677
Change-Id: I1038298942d892bcc69a9dd9edebae73a63d29c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2279304
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786571}
parent d8cb1701
...@@ -56,6 +56,14 @@ enum ServiceWorkerStorageOriginState { ...@@ -56,6 +56,14 @@ enum ServiceWorkerStorageOriginState {
kDelete, kDelete,
}; };
// A notifier interface for ServiceWorkerResourceReader::ReadData().
interface ServiceWorkerDataPipeStateNotifier {
// Called when ReadData() completes. On success, |status| is the number of
// bytes written. On failure, |status| is a //net error, which is a negative
// number.
OnComplete(int32 status);
};
// An interface that reads a service worker script (resource) to storage. // An interface that reads a service worker script (resource) to storage.
interface ServiceWorkerResourceReader { interface ServiceWorkerResourceReader {
// Reads the response head of the resource associated with this reader. // Reads the response head of the resource associated with this reader.
...@@ -66,7 +74,9 @@ interface ServiceWorkerResourceReader { ...@@ -66,7 +74,9 @@ interface ServiceWorkerResourceReader {
network.mojom.URLResponseHead? response_head, network.mojom.URLResponseHead? response_head,
mojo_base.mojom.BigBuffer? metadata); mojo_base.mojom.BigBuffer? metadata);
// Reads the content of the resource associated with this reader. // Reads the content of the resource associated with this reader.
ReadData(int64 size) => (handle<data_pipe_consumer> pipe); ReadData(int64 size,
pending_remote<ServiceWorkerDataPipeStateNotifier> notifier) =>
(handle<data_pipe_consumer> pipe);
}; };
// An interface that writes a service worker script (resource) to storage. // An interface that writes a service worker script (resource) to storage.
......
...@@ -624,7 +624,8 @@ int ServiceWorkerCacheWriter::ReadResponseHead( ...@@ -624,7 +624,8 @@ int ServiceWorkerCacheWriter::ReadResponseHead(
return adapter->result(); return adapter->result();
} }
class ServiceWorkerCacheWriter::DataPipeReader { class ServiceWorkerCacheWriter::DataPipeReader
: public storage::mojom::ServiceWorkerDataPipeStateNotifier {
public: public:
DataPipeReader(storage::mojom::ServiceWorkerResourceReader* reader, DataPipeReader(storage::mojom::ServiceWorkerResourceReader* reader,
ServiceWorkerCacheWriter* owner, ServiceWorkerCacheWriter* owner,
...@@ -646,8 +647,9 @@ class ServiceWorkerCacheWriter::DataPipeReader { ...@@ -646,8 +647,9 @@ class ServiceWorkerCacheWriter::DataPipeReader {
if (!data_.is_valid()) { if (!data_.is_valid()) {
// This is the initial call of Read(). Call ReadData() to get a data pipe // This is the initial call of Read(). Call ReadData() to get a data pipe
// to read the body. // to read the body.
DCHECK(!receiver_.is_bound());
reader_->ReadData( reader_->ReadData(
-1, -1, receiver_.BindNewPipeAndPassRemote(),
base::BindOnce(&ServiceWorkerCacheWriter::DataPipeReader::OnReadData, base::BindOnce(&ServiceWorkerCacheWriter::DataPipeReader::OnReadData,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
return; return;
...@@ -685,6 +687,11 @@ class ServiceWorkerCacheWriter::DataPipeReader { ...@@ -685,6 +687,11 @@ class ServiceWorkerCacheWriter::DataPipeReader {
ReadInternal(MOJO_RESULT_OK); ReadInternal(MOJO_RESULT_OK);
} }
// storage::mojom::ServiceWorkerDataPipeStateNotifier override:
void OnComplete(int32_t status) override {
// TODO(https://crbug.com/1055677): notify of errors.
}
// Parameters set on Read(). // Parameters set on Read().
net::IOBuffer* buffer_ = nullptr; net::IOBuffer* buffer_ = nullptr;
uint32_t num_bytes_to_read_ = 0; uint32_t num_bytes_to_read_ = 0;
...@@ -701,6 +708,9 @@ class ServiceWorkerCacheWriter::DataPipeReader { ...@@ -701,6 +708,9 @@ class ServiceWorkerCacheWriter::DataPipeReader {
mojo::SimpleWatcher watcher_; mojo::SimpleWatcher watcher_;
scoped_refptr<base::SequencedTaskRunner> task_runner_; scoped_refptr<base::SequencedTaskRunner> task_runner_;
mojo::Receiver<storage::mojom::ServiceWorkerDataPipeStateNotifier> receiver_{
this};
base::WeakPtrFactory<DataPipeReader> weak_factory_{this}; base::WeakPtrFactory<DataPipeReader> weak_factory_{this};
}; };
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "content/browser/service_worker/service_worker_resource_ops.h" #include "content/browser/service_worker/service_worker_resource_ops.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/cpp/net_adapters.h" #include "services/network/public/cpp/net_adapters.h"
#include "third_party/blink/public/common/blob/blob_utils.h" #include "third_party/blink/public/common/blob/blob_utils.h"
...@@ -86,15 +87,20 @@ void DidReadInfo( ...@@ -86,15 +87,20 @@ void DidReadInfo(
class ServiceWorkerResourceReaderImpl::DataReader { class ServiceWorkerResourceReaderImpl::DataReader {
public: public:
DataReader(base::WeakPtr<ServiceWorkerResourceReaderImpl> owner, DataReader(
size_t total_bytes_to_read, base::WeakPtr<ServiceWorkerResourceReaderImpl> owner,
mojo::ScopedDataPipeProducerHandle producer_handle) size_t total_bytes_to_read,
mojo::PendingRemote<storage::mojom::ServiceWorkerDataPipeStateNotifier>
notifier,
mojo::ScopedDataPipeProducerHandle producer_handle)
: owner_(std::move(owner)), : owner_(std::move(owner)),
total_bytes_to_read_(total_bytes_to_read), total_bytes_to_read_(total_bytes_to_read),
notifier_(std::move(notifier)),
producer_handle_(std::move(producer_handle)), producer_handle_(std::move(producer_handle)),
watcher_(FROM_HERE, watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL, mojo::SimpleWatcher::ArmingPolicy::MANUAL,
base::SequencedTaskRunnerHandle::Get()) { base::SequencedTaskRunnerHandle::Get()) {
DCHECK(notifier_);
watcher_.Watch(producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, watcher_.Watch(producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
base::BindRepeating(&DataReader::OnWritable, base::BindRepeating(&DataReader::OnWritable,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
...@@ -166,6 +172,11 @@ class ServiceWorkerResourceReaderImpl::DataReader { ...@@ -166,6 +172,11 @@ class ServiceWorkerResourceReaderImpl::DataReader {
void Complete(int status) { void Complete(int status) {
watcher_.Cancel(); watcher_.Cancel();
producer_handle_.reset(); producer_handle_.reset();
if (notifier_.is_connected()) {
notifier_->OnComplete(status);
}
if (owner_) { if (owner_) {
owner_->DidReadDataComplete(); owner_->DidReadDataComplete();
} }
...@@ -174,6 +185,7 @@ class ServiceWorkerResourceReaderImpl::DataReader { ...@@ -174,6 +185,7 @@ class ServiceWorkerResourceReaderImpl::DataReader {
base::WeakPtr<ServiceWorkerResourceReaderImpl> owner_; base::WeakPtr<ServiceWorkerResourceReaderImpl> owner_;
const size_t total_bytes_to_read_; const size_t total_bytes_to_read_;
size_t current_bytes_read_ = 0; size_t current_bytes_read_ = 0;
mojo::Remote<storage::mojom::ServiceWorkerDataPipeStateNotifier> notifier_;
mojo::ScopedDataPipeProducerHandle producer_handle_; mojo::ScopedDataPipeProducerHandle producer_handle_;
mojo::SimpleWatcher watcher_; mojo::SimpleWatcher watcher_;
scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_; scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_;
...@@ -197,8 +209,11 @@ void ServiceWorkerResourceReaderImpl::ReadResponseHead( ...@@ -197,8 +209,11 @@ void ServiceWorkerResourceReaderImpl::ReadResponseHead(
std::move(callback))); std::move(callback)));
} }
void ServiceWorkerResourceReaderImpl::ReadData(int64_t size, void ServiceWorkerResourceReaderImpl::ReadData(
ReadDataCallback callback) { int64_t size,
mojo::PendingRemote<storage::mojom::ServiceWorkerDataPipeStateNotifier>
notifier,
ReadDataCallback callback) {
MojoCreateDataPipeOptions options; MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions); options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE; options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
...@@ -215,6 +230,7 @@ void ServiceWorkerResourceReaderImpl::ReadData(int64_t size, ...@@ -215,6 +230,7 @@ void ServiceWorkerResourceReaderImpl::ReadData(int64_t size,
} }
data_reader_ = std::make_unique<DataReader>(weak_factory_.GetWeakPtr(), size, data_reader_ = std::make_unique<DataReader>(weak_factory_.GetWeakPtr(), size,
std::move(notifier),
std::move(producer_handle)); std::move(producer_handle));
std::move(callback).Run(std::move(consumer_handle)); std::move(callback).Run(std::move(consumer_handle));
} }
......
...@@ -32,7 +32,11 @@ class ServiceWorkerResourceReaderImpl ...@@ -32,7 +32,11 @@ class ServiceWorkerResourceReaderImpl
private: private:
// storage::mojom::ServiceWorkerResourceReader implementations: // storage::mojom::ServiceWorkerResourceReader implementations:
void ReadResponseHead(ReadResponseHeadCallback callback) override; void ReadResponseHead(ReadResponseHeadCallback callback) override;
void ReadData(int64_t size, ReadDataCallback callback) override; void ReadData(
int64_t size,
mojo::PendingRemote<storage::mojom::ServiceWorkerDataPipeStateNotifier>
notifier,
ReadDataCallback callback) override;
void DidReadDataComplete(); void DidReadDataComplete();
......
...@@ -43,6 +43,11 @@ struct ReadResponseHeadResult { ...@@ -43,6 +43,11 @@ struct ReadResponseHeadResult {
base::Optional<mojo_base::BigBuffer> metadata; base::Optional<mojo_base::BigBuffer> metadata;
}; };
struct ReadDataResult {
int status;
std::string data;
};
struct GetRegistrationsForOriginResult { struct GetRegistrationsForOriginResult {
DatabaseStatus status; DatabaseStatus status;
std::vector<storage::mojom::SerializedServiceWorkerRegistrationPtr> std::vector<storage::mojom::SerializedServiceWorkerRegistrationPtr>
...@@ -95,19 +100,56 @@ ReadResponseHeadResult ReadResponseHead( ...@@ -95,19 +100,56 @@ ReadResponseHeadResult ReadResponseHead(
return result; return result;
} }
std::string ReadResponseData( class MockServiceWorkerDataPipeStateNotifier
: public storage::mojom::ServiceWorkerDataPipeStateNotifier {
public:
MockServiceWorkerDataPipeStateNotifier() = default;
mojo::PendingRemote<storage::mojom::ServiceWorkerDataPipeStateNotifier>
BindNewPipeAndPassRemote() {
return receiver_.BindNewPipeAndPassRemote();
}
int32_t WaitUntilComplete() {
if (!complete_status_.has_value()) {
loop_.Run();
DCHECK(complete_status_.has_value());
}
return *complete_status_;
}
private:
void OnComplete(int32_t status) override {
complete_status_ = status;
if (loop_.running())
loop_.Quit();
}
base::Optional<int32_t> complete_status_;
base::RunLoop loop_;
mojo::Receiver<storage::mojom::ServiceWorkerDataPipeStateNotifier> receiver_{
this};
};
ReadDataResult ReadResponseData(
storage::mojom::ServiceWorkerResourceReader* reader, storage::mojom::ServiceWorkerResourceReader* reader,
int data_size) { int data_size) {
MockServiceWorkerDataPipeStateNotifier notifier;
mojo::ScopedDataPipeConsumerHandle data_consumer; mojo::ScopedDataPipeConsumerHandle data_consumer;
base::RunLoop loop; base::RunLoop loop;
reader->ReadData(data_size, base::BindLambdaForTesting( reader->ReadData(
[&](mojo::ScopedDataPipeConsumerHandle pipe) { data_size, notifier.BindNewPipeAndPassRemote(),
data_consumer = std::move(pipe); base::BindLambdaForTesting([&](mojo::ScopedDataPipeConsumerHandle pipe) {
loop.Quit(); data_consumer = std::move(pipe);
})); loop.Quit();
}));
loop.Run(); loop.Run();
return ReadDataPipe(std::move(data_consumer)); ReadDataResult result;
result.data = ReadDataPipe(std::move(data_consumer));
result.status = notifier.WaitUntilComplete();
return result;
} }
int WriteResponseHead(storage::mojom::ServiceWorkerResourceWriter* writer, int WriteResponseHead(storage::mojom::ServiceWorkerResourceWriter* writer,
...@@ -612,7 +654,7 @@ class ServiceWorkerStorageControlImplTest : public testing::Test { ...@@ -612,7 +654,7 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
return result; return result;
} }
std::string ReadResource(int64_t resource_id, int data_size) { ReadDataResult ReadResource(int64_t resource_id, int data_size) {
mojo::Remote<storage::mojom::ServiceWorkerResourceReader> reader = mojo::Remote<storage::mojom::ServiceWorkerResourceReader> reader =
CreateResourceReader(resource_id); CreateResourceReader(resource_id);
return ReadResponseData(reader.get(), data_size); return ReadResponseData(reader.get(), data_size);
...@@ -1007,8 +1049,9 @@ TEST_F(ServiceWorkerStorageControlImplTest, WriteAndReadResource) { ...@@ -1007,8 +1049,9 @@ TEST_F(ServiceWorkerStorageControlImplTest, WriteAndReadResource) {
ssl_info.cert->serial_number()); ssl_info.cert->serial_number());
EXPECT_EQ(result.metadata, base::nullopt); EXPECT_EQ(result.metadata, base::nullopt);
std::string data = ReadResponseData(reader.get(), data_size); ReadDataResult data_result = ReadResponseData(reader.get(), data_size);
EXPECT_EQ(data, kData); ASSERT_EQ(data_result.status, data_size);
EXPECT_EQ(data_result.data, kData);
} }
const auto kMetadata = base::as_bytes(base::make_span("metadata")); const auto kMetadata = base::as_bytes(base::make_span("metadata"));
...@@ -1491,12 +1534,16 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) { ...@@ -1491,12 +1534,16 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
// Resources shouldn't be purged because there is an active reference. // Resources shouldn't be purged because there is an active reference.
{ {
std::string read_resource_data1 = ReadDataResult read_resource_result1 =
ReadResource(resource_id1, resource_data1.size()); ReadResource(resource_id1, resource_data1.size());
ASSERT_EQ(read_resource_data1, resource_data1); ASSERT_EQ(read_resource_result1.status,
std::string read_resource_data2 = static_cast<int32_t>(resource_data1.size()));
EXPECT_EQ(read_resource_result1.data, resource_data1);
ReadDataResult read_resource_result2 =
ReadResource(resource_id2, resource_data2.size()); ReadResource(resource_id2, resource_data2.size());
ASSERT_EQ(read_resource_data2, resource_data2); ASSERT_EQ(read_resource_result2.status,
static_cast<int32_t>(resource_data2.size()));
EXPECT_EQ(read_resource_result2.data, resource_data2);
} }
// Drop the second reference. // Drop the second reference.
...@@ -1505,12 +1552,14 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) { ...@@ -1505,12 +1552,14 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
// Resources should have been purged. // Resources should have been purged.
{ {
std::string read_resource_data1 = ReadDataResult read_resource_result1 =
ReadResource(resource_id1, resource_data1.size()); ReadResource(resource_id1, resource_data1.size());
ASSERT_EQ(read_resource_data1, ""); ASSERT_EQ(read_resource_result1.status, net::ERR_CACHE_MISS);
std::string read_resource_data2 = EXPECT_EQ(read_resource_result1.data, "");
ReadDataResult read_resource_result2 =
ReadResource(resource_id2, resource_data2.size()); ReadResource(resource_id2, resource_data2.size());
ASSERT_EQ(read_resource_data2, ""); ASSERT_EQ(read_resource_result2.status, net::ERR_CACHE_MISS);
EXPECT_EQ(read_resource_result2.data, "");
} }
} }
......
...@@ -559,8 +559,11 @@ void MockServiceWorkerResourceReader::ReadResponseHead( ...@@ -559,8 +559,11 @@ void MockServiceWorkerResourceReader::ReadResponseHead(
pending_read_response_head_callback_ = std::move(callback); pending_read_response_head_callback_ = std::move(callback);
} }
void MockServiceWorkerResourceReader::ReadData(int64_t, void MockServiceWorkerResourceReader::ReadData(
ReadDataCallback callback) { int64_t,
mojo::PendingRemote<
storage::mojom::ServiceWorkerDataPipeStateNotifier> /*notifier*/,
ReadDataCallback callback) {
DCHECK(!body_.is_valid()); DCHECK(!body_.is_valid());
mojo::ScopedDataPipeConsumerHandle consumer; mojo::ScopedDataPipeConsumerHandle consumer;
MojoCreateDataPipeOptions options; MojoCreateDataPipeOptions options;
......
...@@ -239,7 +239,11 @@ class MockServiceWorkerResourceReader ...@@ -239,7 +239,11 @@ class MockServiceWorkerResourceReader
void ReadResponseHead( void ReadResponseHead(
storage::mojom::ServiceWorkerResourceReader::ReadResponseHeadCallback storage::mojom::ServiceWorkerResourceReader::ReadResponseHeadCallback
callback) override; callback) override;
void ReadData(int64_t, ReadDataCallback callback) override; void ReadData(
int64_t,
mojo::PendingRemote<storage::mojom::ServiceWorkerDataPipeStateNotifier>
notifier,
ReadDataCallback callback) override;
// Test helpers. ExpectReadResponseHead() and ExpectReadData() give precise // Test helpers. ExpectReadResponseHead() and ExpectReadData() give precise
// control over both the data to be written and the result to return. // control over both the data to be written and the result to return.
......
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