Commit 5b34136f authored by Makoto Shimazu's avatar Makoto Shimazu Committed by Commit Bot

Serve cached metadata through ServiceWorkerSubresourceLoader

Currently we don't read the cached metadata (= blob's side data) at the
subresource loader. This patch is to read it and send it back to the client.

Bug: 856521
Change-Id: I8ba4010e6551ba32ff227e47390d974c64bfbfdc
Reviewed-on: https://chromium-review.googlesource.com/1116630Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Makoto Shimazu <shimazu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#571056}
parent 2ae64fcc
...@@ -439,18 +439,9 @@ void ServiceWorkerSubresourceLoader::StartResponse( ...@@ -439,18 +439,9 @@ void ServiceWorkerSubresourceLoader::StartResponse(
if (body_as_blob) { if (body_as_blob) {
DCHECK(!body_as_stream); DCHECK(!body_as_stream);
body_as_blob_ = std::move(body_as_blob); body_as_blob_ = std::move(body_as_blob);
mojo::ScopedDataPipeConsumerHandle data_pipe; body_as_blob_->ReadSideData(base::BindOnce(
int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody( &ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete,
&body_as_blob_, resource_request_.headers, base::Unretained(this)));
base::BindOnce(&ServiceWorkerSubresourceLoader::OnBlobReadingComplete,
weak_factory_.GetWeakPtr()),
&data_pipe);
if (error != net::OK) {
CommitCompleted(error);
return;
}
url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe));
// We continue in OnBlobReadingComplete().
return; return;
} }
...@@ -522,6 +513,25 @@ void ServiceWorkerSubresourceLoader::PauseReadingBodyFromNet() {} ...@@ -522,6 +513,25 @@ void ServiceWorkerSubresourceLoader::PauseReadingBodyFromNet() {}
void ServiceWorkerSubresourceLoader::ResumeReadingBodyFromNet() {} void ServiceWorkerSubresourceLoader::ResumeReadingBodyFromNet() {}
void ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete(
const base::Optional<std::vector<uint8_t>>& metadata) {
DCHECK(url_loader_client_);
if (metadata.has_value())
url_loader_client_->OnReceiveCachedMetadata(metadata.value());
mojo::ScopedDataPipeConsumerHandle data_pipe;
int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
&body_as_blob_, resource_request_.headers,
base::BindOnce(&ServiceWorkerSubresourceLoader::OnBlobReadingComplete,
weak_factory_.GetWeakPtr()),
&data_pipe);
if (error != net::OK) {
CommitCompleted(error);
return;
}
url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe));
// We continue in OnBlobReadingComplete().
}
void ServiceWorkerSubresourceLoader::OnBlobReadingComplete(int net_error) { void ServiceWorkerSubresourceLoader::OnBlobReadingComplete(int net_error) {
CommitCompleted(net_error); CommitCompleted(net_error);
body_as_blob_.reset(); body_as_blob_.reset();
......
...@@ -99,6 +99,8 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader ...@@ -99,6 +99,8 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
void PauseReadingBodyFromNet() override; void PauseReadingBodyFromNet() override;
void ResumeReadingBodyFromNet() override; void ResumeReadingBodyFromNet() override;
void OnBlobSideDataReadingComplete(
const base::Optional<std::vector<uint8_t>>& metadata);
void OnBlobReadingComplete(int net_error); void OnBlobReadingComplete(int net_error);
// Calls url_loader_client_->OnReceiveResponse() with |response_head_|. // Calls url_loader_client_->OnReceiveResponse() with |response_head_|.
......
...@@ -26,11 +26,49 @@ ...@@ -26,11 +26,49 @@
#include "services/network/test/test_data_pipe_getter.h" #include "services/network/test/test_data_pipe_getter.h"
#include "services/network/test/test_url_loader_client.h" #include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "url/origin.h" #include "url/origin.h"
namespace content { namespace content {
namespace service_worker_subresource_loader_unittest { namespace service_worker_subresource_loader_unittest {
// A simple blob implementation for serving data stored in a vector.
class FakeBlob final : public blink::mojom::Blob {
public:
FakeBlob(base::Optional<std::vector<uint8_t>> side_data, std::string body)
: side_data_(std::move(side_data)), body_(std::move(body)) {}
private:
// Implements blink::mojom::Blob.
void Clone(blink::mojom::BlobRequest) override { NOTREACHED(); }
void AsDataPipeGetter(network::mojom::DataPipeGetterRequest) override {
NOTREACHED();
}
void ReadRange(uint64_t offset,
uint64_t length,
mojo::ScopedDataPipeProducerHandle handle,
blink::mojom::BlobReaderClientPtr client) override {
NOTREACHED();
}
void ReadAll(mojo::ScopedDataPipeProducerHandle handle,
blink::mojom::BlobReaderClientPtr client) override {
EXPECT_TRUE(mojo::BlockingCopyFromString(body_, handle));
if (client) {
client->OnCalculatedSize(body_.size(), body_.size());
client->OnComplete(net::OK, body_.size());
}
}
void ReadSideData(ReadSideDataCallback callback) override {
std::move(callback).Run(side_data_);
}
void GetInternalUUID(GetInternalUUIDCallback callback) override {
NOTREACHED();
}
base::Optional<std::vector<uint8_t>> side_data_;
std::string body_;
};
// A simple URLLoaderFactory that responds with status 200 to every request. // A simple URLLoaderFactory that responds with status 200 to every request.
// This is the default network loader factory for // This is the default network loader factory for
// ServiceWorkerSubresourceLoaderTest. // ServiceWorkerSubresourceLoaderTest.
...@@ -155,6 +193,14 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { ...@@ -155,6 +193,14 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
redirect_location_header_ = redirect_location_header; redirect_location_header_ = redirect_location_header;
} }
void RespondWithBlob(base::Optional<std::vector<uint8_t>> metadata,
std::string body) {
response_mode_ = ResponseMode::kBlob;
mojo::MakeStrongBinding(
std::make_unique<FakeBlob>(std::move(metadata), std::move(body)),
mojo::MakeRequest(&blob_));
}
void ReadRequestBody(std::string* out_string) { void ReadRequestBody(std::string* out_string) {
ASSERT_TRUE(request_body_); ASSERT_TRUE(request_body_);
std::vector<network::DataElement>* elements = std::vector<network::DataElement>* elements =
...@@ -211,6 +257,12 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { ...@@ -211,6 +257,12 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time()); blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time());
break; break;
case ResponseMode::kBlob:
response_callback->OnResponseBlob(OkResponse(), std::move(blob_),
base::Time::Now());
std::move(callback).Run(
blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time());
break;
case ResponseMode::kFallbackResponse: case ResponseMode::kFallbackResponse:
response_callback->OnFallback(base::Time::Now()); response_callback->OnFallback(base::Time::Now());
std::move(callback).Run( std::move(callback).Run(
...@@ -255,6 +307,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { ...@@ -255,6 +307,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
kDefault, kDefault,
kAbort, kAbort,
kStream, kStream,
kBlob,
kFallbackResponse, kFallbackResponse,
kErrorResponse, kErrorResponse,
kRedirectResponse kRedirectResponse
...@@ -271,6 +324,9 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { ...@@ -271,6 +324,9 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker {
// For ResponseMode::kStream. // For ResponseMode::kStream.
blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_; blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
// For ResponseMode::kBlob.
blink::mojom::BlobPtr blob_;
// For ResponseMode::kRedirectResponse // For ResponseMode::kRedirectResponse
std::string redirect_location_header_; std::string redirect_location_header_;
...@@ -797,6 +853,85 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse_Abort) { ...@@ -797,6 +853,85 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse_Abort) {
blink::SERVICE_WORKER_OK, 1); blink::SERVICE_WORKER_OK, 1);
} }
TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) {
base::HistogramTester histogram_tester;
// Construct the Blob to respond with.
const std::string kResponseBody = "Here is sample text for the Blob.";
const std::vector<uint8_t> kMetadata = {0xE3, 0x81, 0x8F, 0xE3, 0x82,
0x8D, 0xE3, 0x81, 0xBF, 0xE3,
0x81, 0x86, 0xE3, 0x82, 0x80};
fake_controller_.RespondWithBlob(kMetadata, kResponseBody);
network::mojom::URLLoaderFactoryPtr factory =
CreateSubresourceLoaderFactory();
// Perform the request.
network::ResourceRequest request =
CreateRequest(GURL("https://www.example.com/foo.png"));
network::mojom::URLLoaderPtr loader;
std::unique_ptr<network::TestURLLoaderClient> client;
StartRequest(factory, request, &loader, &client);
client->RunUntilResponseReceived();
const network::ResourceResponseHead& info = client->response_head();
ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
// Test the cached metadata.
client->RunUntilCachedMetadataReceived();
EXPECT_EQ(client->cached_metadata(),
std::string(kMetadata.begin(), kMetadata.end()));
client->RunUntilComplete();
EXPECT_EQ(net::OK, client->completion_status().error_code);
// Test the body.
std::string response;
EXPECT_TRUE(client->response_body().is_valid());
EXPECT_TRUE(
mojo::BlockingCopyToString(client->response_body_release(), &response));
EXPECT_EQ(kResponseBody, response);
histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
blink::SERVICE_WORKER_OK, 1);
}
TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) {
base::HistogramTester histogram_tester;
// Construct the Blob to respond with.
const std::string kResponseBody = "Here is sample text for the Blob.";
fake_controller_.RespondWithBlob(base::nullopt, kResponseBody);
network::mojom::URLLoaderFactoryPtr factory =
CreateSubresourceLoaderFactory();
// Perform the request.
network::ResourceRequest request =
CreateRequest(GURL("https://www.example.com/foo.png"));
network::mojom::URLLoaderPtr loader;
std::unique_ptr<network::TestURLLoaderClient> client;
StartRequest(factory, request, &loader, &client);
client->RunUntilResponseReceived();
const network::ResourceResponseHead& info = client->response_head();
ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
client->RunUntilComplete();
EXPECT_EQ(net::OK, client->completion_status().error_code);
// Test the body.
std::string response;
EXPECT_TRUE(client->response_body().is_valid());
EXPECT_TRUE(
mojo::BlockingCopyToString(client->response_body_release(), &response));
EXPECT_EQ(kResponseBody, response);
EXPECT_FALSE(client->has_received_cached_metadata());
histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent,
blink::SERVICE_WORKER_OK, 1);
}
// Test when the service worker responds with network fallback. // Test when the service worker responds with network fallback.
// i.e., does not call respondWith(). // i.e., does not call respondWith().
TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) { TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) {
......
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