Commit de4add06 authored by Natalie Chouinard's avatar Natalie Chouinard Committed by Commit Bot

Revert "Add URLLoaderFactory for loading resources from a WebBundle"

This reverts commit def0fa3e.

Reason for revert: WebBundleSubresourceLoaderFactoryTest.MetadataParseError failing on android-marshmallow-arm64-rel
https://ci.chromium.org/p/chromium/builders/ci/android-marshmallow-arm64-rel

Original change's description:
> Add URLLoaderFactory for loading resources from a WebBundle
> 
> In follow-up CLs, this factory will be created by LinkWebBundle, and
> will be used to load subresources from Web Bundles.
> 
> Bug: 1082020
> Change-Id: I231e8c85f740e3588c2ba4c518378cd26a36a79d
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2275986
> Reviewed-by: Hayato Ito <hayato@chromium.org>
> Reviewed-by: Tsuyoshi Horo <horo@chromium.org>
> Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
> Commit-Queue: Kunihiko Sakamoto <ksakamoto@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#786147}

TBR=horo@chromium.org,kinuko@chromium.org,hayato@chromium.org,ksakamoto@chromium.org

Change-Id: Idbdb87829da52eff4f87306efaa5b136406a79ee
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1082020
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2288767Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Commit-Queue: Natalie Chouinard <chouinard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786573}
parent 4764c48f
......@@ -10,8 +10,6 @@ static_library("web_package") {
"web_bundle_parser.h",
"web_bundle_parser_factory.cc",
"web_bundle_parser_factory.h",
"web_bundle_utils.cc",
"web_bundle_utils.h",
]
deps = [
......@@ -19,7 +17,6 @@ static_library("web_package") {
"//components/cbor",
"//mojo/public/cpp/bindings",
"//net",
"//services/network/public/mojom",
]
public_deps = [ "//components/web_package/mojom" ]
......
......@@ -2,7 +2,6 @@ include_rules = [
"+components/cbor",
"+mojo/public/cpp",
"+net",
"+services/network/public/mojom"
]
specific_include_rules = {
......
// Copyright 2020 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 "components/web_package/web_bundle_utils.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "components/web_package/mojom/web_bundle_parser.mojom.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace web_package {
namespace {
constexpr char kCrLf[] = "\r\n";
} // namespace
network::mojom::URLResponseHeadPtr CreateResourceResponse(
const web_package::mojom::BundleResponsePtr& response) {
std::vector<std::string> header_strings;
header_strings.push_back("HTTP/1.1 ");
header_strings.push_back(base::NumberToString(response->response_code));
header_strings.push_back(" ");
header_strings.push_back(net::GetHttpReasonPhrase(
static_cast<net::HttpStatusCode>(response->response_code)));
header_strings.push_back(kCrLf);
for (const auto& it : response->response_headers) {
header_strings.push_back(it.first);
header_strings.push_back(": ");
header_strings.push_back(it.second);
header_strings.push_back(kCrLf);
}
header_strings.push_back(kCrLf);
auto response_head = network::mojom::URLResponseHead::New();
response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(base::JoinString(header_strings, "")));
response_head->headers->GetMimeTypeAndCharset(&response_head->mime_type,
&response_head->charset);
return response_head;
}
} // namespace web_package
// Copyright 2020 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.
#ifndef COMPONENTS_WEB_PACKAGE_WEB_BUNDLE_UTILS_H_
#define COMPONENTS_WEB_PACKAGE_WEB_BUNDLE_UTILS_H_
#include "components/web_package/mojom/web_bundle_parser.mojom-forward.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
namespace web_package {
network::mojom::URLResponseHeadPtr CreateResourceResponse(
const web_package::mojom::BundleResponsePtr& response);
} // namespace web_package
#endif // COMPONENTS_WEB_PACKAGE_WEB_BUNDLE_UTILS_H_
......@@ -8,9 +8,9 @@
#include <string>
#include <vector>
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "components/web_package/web_bundle_utils.h"
#include "content/browser/web_package/web_bundle_reader.h"
#include "content/browser/web_package/web_bundle_source.h"
#include "content/public/browser/content_browser_client.h"
......@@ -30,6 +30,36 @@ namespace content {
namespace {
constexpr char kCrLf[] = "\r\n";
network::mojom::URLResponseHeadPtr CreateResourceResponse(
const web_package::mojom::BundleResponsePtr& response) {
DCHECK_EQ(net::HTTP_OK, response->response_code);
std::vector<std::string> header_strings;
header_strings.push_back("HTTP/1.1 ");
header_strings.push_back(base::NumberToString(response->response_code));
header_strings.push_back(" ");
header_strings.push_back(net::GetHttpReasonPhrase(
static_cast<net::HttpStatusCode>(response->response_code)));
header_strings.push_back(kCrLf);
for (const auto& it : response->response_headers) {
header_strings.push_back(it.first);
header_strings.push_back(": ");
header_strings.push_back(it.second);
header_strings.push_back(kCrLf);
}
header_strings.push_back(kCrLf);
auto response_head = network::mojom::URLResponseHead::New();
response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(base::JoinString(header_strings, "")));
response_head->headers->GetMimeTypeAndCharset(&response_head->mime_type,
&response_head->charset);
return response_head;
}
void AddResponseParseErrorMessageToConsole(
int frame_tree_node_id,
const web_package::mojom::BundleResponseParseErrorPtr& error) {
......@@ -106,7 +136,7 @@ class WebBundleURLLoaderFactory::EntryLoader final
return;
}
auto response_head = web_package::CreateResourceResponse(response);
auto response_head = CreateResourceResponse(response);
if (byte_range_) {
if (byte_range_->ComputeBounds(response->payload_length)) {
response_head->headers->UpdateWithNewRange(
......
......@@ -112,8 +112,6 @@ blink_platform_sources("loader") {
"fetch/unique_identifier.h",
"fetch/url_loader/request_conversion.cc",
"fetch/url_loader/request_conversion.h",
"fetch/url_loader/web_bundle_subresource_loader.cc",
"fetch/url_loader/web_bundle_subresource_loader.h",
"fetch/url_loader/worker_main_script_loader.cc",
"fetch/url_loader/worker_main_script_loader.h",
"fetch/url_loader/worker_main_script_loader_client.h",
......@@ -135,7 +133,6 @@ blink_platform_sources("loader") {
deps = [
":make_platform_loader_generated_fetch_initiator_type_names",
"//components/link_header_util",
"//components/web_package",
"//services/network/public/cpp",
"//services/network/public/mojom:mojom_blink",
]
......@@ -169,7 +166,6 @@ jumbo_source_set("unit_tests") {
"fetch/response_body_loader_test.cc",
"fetch/shared_buffer_bytes_consumer_test.cc",
"fetch/source_keyed_cached_metadata_handler_test.cc",
"fetch/url_loader/web_bundle_subresource_loader_test.cc",
"fetch/url_loader/worker_main_script_loader_unittest.cc",
"ftp_directory_listing_test.cc",
"link_header_test.cc",
......@@ -180,8 +176,6 @@ jumbo_source_set("unit_tests") {
configs += [ "//third_party/blink/renderer/platform:blink_platform_config" ]
deps = [
"//components/web_package:test_support",
"//services/network:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/blink/renderer/platform:platform",
......
......@@ -2,12 +2,4 @@ specific_include_rules = {
"request_conversion.cc" : [
"+media/media_buildflags.h"
],
"web_bundle_subresource_loader.cc" : [
"+components/web_package",
],
"web_bundle_subresource_loader_test.cc" : [
"+components/web_package",
"+net/traffic_annotation/network_traffic_annotation_test_helper.h",
"+services/network/test/test_url_loader_client.h",
],
}
// Copyright 2020 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_WEB_BUNDLE_SUBRESOURCE_LOADER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_WEB_BUNDLE_SUBRESOURCE_LOADER_H_
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
// Creates a network::mojom::URLLoaderFactory that can load resources from a
// WebBundle, and binds it to |factory_receiver|.
PLATFORM_EXPORT void CreateWebBundleSubresourceLoaderFactory(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver,
mojo::ScopedDataPipeConsumerHandle bundle_body);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_WEB_BUNDLE_SUBRESOURCE_LOADER_H_
// Copyright 2020 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.h"
#include "base/test/task_environment.h"
#include "components/web_package/test_support/web_bundle_builder.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace {
const char kResourceUrl[] = "https://example.com/";
const char kResourceUrl2[] = "https://example.com/another";
const char kResourceUrl3[] = "https://example.com/yetanother";
std::vector<uint8_t> CreateSmallBundle() {
web_package::test::WebBundleBuilder builder(kResourceUrl,
"" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "200"}, {"content-type", "text/plain"}},
"body");
return builder.CreateBundle();
}
std::vector<uint8_t> CreateLargeBundle() {
web_package::test::WebBundleBuilder builder(kResourceUrl,
"" /* manifest_url */);
builder.AddExchange(kResourceUrl,
{{":status", "200"}, {"content-type", "text/plain"}},
"body");
builder.AddExchange(kResourceUrl2,
{{":status", "200"}, {"content-type", "text/plain"}},
std::string(10000, 'a'));
builder.AddExchange(kResourceUrl3,
{{":status", "200"}, {"content-type", "text/plain"}},
"body");
return builder.CreateBundle();
}
} // namespace
class WebBundleSubresourceLoaderFactoryTest : public ::testing::Test {
public:
void SetUp() override {
mojo::ScopedDataPipeConsumerHandle consumer;
ASSERT_EQ(CreateDataPipe(nullptr, &bundle_data_destination_, &consumer),
MOJO_RESULT_OK);
CreateWebBundleSubresourceLoaderFactory(
loader_factory_.BindNewPipeAndPassReceiver(), std::move(consumer));
}
void WriteBundle(base::span<const uint8_t> data) {
mojo::BlockingCopyFromString(
std::string(reinterpret_cast<const char*>(data.data()), data.size()),
bundle_data_destination_);
}
void FinishWritingBundle() { bundle_data_destination_.reset(); }
struct StartRequestResult {
mojo::Remote<network::mojom::URLLoader> loader;
std::unique_ptr<network::TestURLLoaderClient> client;
};
StartRequestResult StartRequest(const GURL& url) {
return StartRequestWithLoaderFactory(loader_factory_, url);
}
protected:
StartRequestResult StartRequestWithLoaderFactory(
mojo::Remote<network::mojom::URLLoaderFactory>& factory,
const GURL& url) {
network::ResourceRequest request;
request.url = url;
request.method = "GET";
StartRequestResult result;
result.client = std::make_unique<network::TestURLLoaderClient>();
factory->CreateLoaderAndStart(
result.loader.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
0 /* request_id */, 0 /* options */, request,
result.client->CreateRemote(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
return result;
}
mojo::Remote<network::mojom::URLLoaderFactory> loader_factory_;
private:
mojo::ScopedDataPipeProducerHandle bundle_data_destination_;
base::test::TaskEnvironment task_environment;
};
TEST_F(WebBundleSubresourceLoaderFactoryTest, Basic) {
WriteBundle(CreateSmallBundle());
FinishWritingBundle();
auto request = StartRequest(GURL(kResourceUrl));
request.client->RunUntilComplete();
EXPECT_EQ(net::OK, request.client->completion_status().error_code);
std::string body;
EXPECT_TRUE(mojo::BlockingCopyToString(
request.client->response_body_release(), &body));
EXPECT_EQ("body", body);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, Clone) {
mojo::Remote<network::mojom::URLLoaderFactory> cloned_factory_;
loader_factory_->Clone(cloned_factory_.BindNewPipeAndPassReceiver());
WriteBundle(CreateSmallBundle());
FinishWritingBundle();
auto request =
StartRequestWithLoaderFactory(cloned_factory_, GURL(kResourceUrl));
request.client->RunUntilComplete();
EXPECT_EQ(net::OK, request.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, MetadataParseError) {
std::vector<uint8_t> bundle = CreateSmallBundle();
bundle[4] ^= 1; // Mutate magic bytes.
WriteBundle(bundle);
FinishWritingBundle();
auto request = StartRequest(GURL(kResourceUrl));
request.client->RunUntilComplete();
EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
request.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, ResponseParseError) {
web_package::test::WebBundleBuilder builder(kResourceUrl,
"" /* manifest_url */);
// An invalid response.
builder.AddExchange(kResourceUrl, {{":status", "0"}}, "body");
WriteBundle(builder.CreateBundle());
FinishWritingBundle();
auto request = StartRequest(GURL(kResourceUrl));
request.client->RunUntilComplete();
EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
request.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, ResourceNotFoundInBundle) {
WriteBundle(CreateSmallBundle());
FinishWritingBundle();
auto request = StartRequest(GURL("https://example.com/no-such-resource"));
request.client->RunUntilComplete();
EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
request.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, StartRequestBeforeReadingBundle) {
auto request = StartRequest(GURL(kResourceUrl));
WriteBundle(CreateSmallBundle());
FinishWritingBundle();
request.client->RunUntilComplete();
EXPECT_EQ(net::OK, request.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, MultipleRequests) {
auto request1 = StartRequest(GURL(kResourceUrl));
auto request2 = StartRequest(GURL(kResourceUrl2));
std::vector<uint8_t> bundle = CreateLargeBundle();
// Write the first 10kB of the bundle in which the bundle's metadata and the
// response for kResourceUrl are included.
ASSERT_GT(bundle.size(), 10000U);
WriteBundle(base::make_span(bundle).subspan(0, 10000));
request1.client->RunUntilComplete();
EXPECT_EQ(net::OK, request1.client->completion_status().error_code);
EXPECT_FALSE(request2.client->has_received_completion());
// Write the rest of the data.
WriteBundle(base::make_span(bundle).subspan(10000));
FinishWritingBundle();
request2.client->RunUntilComplete();
EXPECT_EQ(net::OK, request2.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, CancelRequest) {
auto request_to_complete1 = StartRequest(GURL(kResourceUrl));
auto request_to_complete2 = StartRequest(GURL(kResourceUrl2));
auto request_to_cancel1 = StartRequest(GURL(kResourceUrl));
auto request_to_cancel2 = StartRequest(GURL(kResourceUrl2));
auto request_to_cancel3 = StartRequest(GURL(kResourceUrl3));
// Cancel request before getting metadata.
request_to_cancel1.loader.reset();
std::vector<uint8_t> bundle = CreateLargeBundle();
// Write the first 10kB of the bundle in which the bundle's metadata, response
// for kResourceUrl, and response header for kResourceUrl2 are included.
ASSERT_GT(bundle.size(), 10000U);
WriteBundle(base::make_span(bundle).subspan(0, 10000));
// This makes sure the bytes written above are consumed by WebBundle parser.
request_to_complete1.client->RunUntilComplete();
// Cancel request after reading response header, but before reading body.
request_to_cancel2.loader.reset();
// Cancel request after getting metadata, but before reading response header.
request_to_cancel3.loader.reset();
// Write the rest of the data.
WriteBundle(base::make_span(bundle).subspan(10000));
FinishWritingBundle();
request_to_complete2.client->RunUntilComplete();
EXPECT_EQ(net::OK,
request_to_complete2.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest,
FactoryDestructionCancelsInflightRequests) {
auto request = StartRequest(GURL(kResourceUrl));
loader_factory_.reset();
WriteBundle(CreateSmallBundle());
FinishWritingBundle();
request.client->RunUntilComplete();
EXPECT_EQ(net::ERR_FAILED, request.client->completion_status().error_code);
}
TEST_F(WebBundleSubresourceLoaderFactoryTest, TruncatedBundle) {
std::vector<uint8_t> bundle = CreateSmallBundle();
// Truncate in the middle of responses section.
bundle.resize(bundle.size() - 10);
WriteBundle(std::move(bundle));
FinishWritingBundle();
auto request = StartRequest(GURL(kResourceUrl));
request.client->RunUntilComplete();
EXPECT_EQ(net::ERR_INVALID_WEB_BUNDLE,
request.client->completion_status().error_code);
}
} // namespace blink
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