Commit fc657a9f authored by Kunihiko Sakamoto's avatar Kunihiko Sakamoto Committed by Commit Bot

Add unit test for SignedExchangeHandler

SignedExchangeCertFetcherFactory is introduced to inject a mock fetcher
to SignedExchangeHandler.

Bug: 803774
Change-Id: I2302c5f8162ae641e36edace42bfd02563083eb4
Reviewed-on: https://chromium-review.googlesource.com/964032
Commit-Queue: Kunihiko Sakamoto <ksakamoto@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Reviewed-by: default avatarTsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543637}
parent b7015866
...@@ -1667,6 +1667,8 @@ jumbo_source_set("browser") { ...@@ -1667,6 +1667,8 @@ jumbo_source_set("browser") {
"web_contents/web_drag_utils_win.h", "web_contents/web_drag_utils_win.h",
"web_package/signed_exchange_cert_fetcher.cc", "web_package/signed_exchange_cert_fetcher.cc",
"web_package/signed_exchange_cert_fetcher.h", "web_package/signed_exchange_cert_fetcher.h",
"web_package/signed_exchange_cert_fetcher_factory.cc",
"web_package/signed_exchange_cert_fetcher_factory.h",
"web_package/signed_exchange_consts.h", "web_package/signed_exchange_consts.h",
"web_package/signed_exchange_handler.cc", "web_package/signed_exchange_handler.cc",
"web_package/signed_exchange_handler.h", "web_package/signed_exchange_handler.h",
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "net/filter/source_stream.h" #include "net/filter/source_stream.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/http/http_util.h" #include "net/http/http_util.h"
...@@ -51,9 +52,7 @@ MockSignedExchangeHandlerFactory::~MockSignedExchangeHandlerFactory() = default; ...@@ -51,9 +52,7 @@ MockSignedExchangeHandlerFactory::~MockSignedExchangeHandlerFactory() = default;
std::unique_ptr<SignedExchangeHandler> MockSignedExchangeHandlerFactory::Create( std::unique_ptr<SignedExchangeHandler> MockSignedExchangeHandlerFactory::Create(
std::unique_ptr<net::SourceStream> body, std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback, ExchangeHeadersCallback headers_callback,
url::Origin request_initiator, std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory) {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter) {
return std::make_unique<MockSignedExchangeHandler>( return std::make_unique<MockSignedExchangeHandler>(
error_, request_url_, mime_type_, response_headers_, std::move(body), error_, request_url_, mime_type_, response_headers_, std::move(body),
std::move(headers_callback)); std::move(headers_callback));
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
namespace content { namespace content {
class SignedExchangeCertFetcherFactory;
class MockSignedExchangeHandler final : public SignedExchangeHandler { class MockSignedExchangeHandler final : public SignedExchangeHandler {
public: public:
MockSignedExchangeHandler(net::Error error, MockSignedExchangeHandler(net::Error error,
...@@ -32,8 +34,6 @@ class MockSignedExchangeHandlerFactory final ...@@ -32,8 +34,6 @@ class MockSignedExchangeHandlerFactory final
public: public:
using ExchangeHeadersCallback = using ExchangeHeadersCallback =
SignedExchangeHandler::ExchangeHeadersCallback; SignedExchangeHandler::ExchangeHeadersCallback;
using URLLoaderThrottlesGetter =
SignedExchangeHandler::URLLoaderThrottlesGetter;
// Creates a factory that creates SignedExchangeHandler which always fires // Creates a factory that creates SignedExchangeHandler which always fires
// a headers callback with the given |error|, |request_url|, |mime_type| // a headers callback with the given |error|, |request_url|, |mime_type|
...@@ -49,9 +49,8 @@ class MockSignedExchangeHandlerFactory final ...@@ -49,9 +49,8 @@ class MockSignedExchangeHandlerFactory final
std::unique_ptr<SignedExchangeHandler> Create( std::unique_ptr<SignedExchangeHandler> Create(
std::unique_ptr<net::SourceStream> body, std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback, ExchangeHeadersCallback headers_callback,
url::Origin request_initiator, std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory)
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, override;
URLLoaderThrottlesGetter url_loader_throttles_getter) override;
private: private:
const net::Error error_; const net::Error error_;
......
...@@ -45,6 +45,9 @@ class CONTENT_EXPORT SignedExchangeCertFetcher ...@@ -45,6 +45,9 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
// be called with the certificate if succeeded. Otherwise it will be called // be called with the certificate if succeeded. Otherwise it will be called
// with null. If the returned fetcher is destructed before the |callback| is // with null. If the returned fetcher is destructed before the |callback| is
// called, the request will be canceled and the |callback| will no be called. // called, the request will be canceled and the |callback| will no be called.
//
// Using SignedExchangeCertFetcherFactory is preferred rather than directly
// calling this.
static std::unique_ptr<SignedExchangeCertFetcher> CreateAndStart( static std::unique_ptr<SignedExchangeCertFetcher> CreateAndStart(
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory, scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
......
// 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/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/public/common/url_loader_throttle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
SignedExchangeCertFetcherFactory::~SignedExchangeCertFetcherFactory() = default;
class SignedExchangeCertFetcherFactoryImpl
: public SignedExchangeCertFetcherFactory {
public:
SignedExchangeCertFetcherFactoryImpl(
url::Origin request_initiator,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter)
: request_initiator_(std::move(request_initiator)),
url_loader_factory_(std::move(url_loader_factory)),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)) {}
std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
SignedExchangeCertFetcher::CertificateCallback callback) override;
private:
url::Origin request_initiator_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
};
std::unique_ptr<SignedExchangeCertFetcher>
SignedExchangeCertFetcherFactoryImpl::CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
SignedExchangeCertFetcher::CertificateCallback callback) {
DCHECK(url_loader_factory_);
DCHECK(url_loader_throttles_getter_);
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles =
std::move(url_loader_throttles_getter_).Run();
return SignedExchangeCertFetcher::CreateAndStart(
std::move(url_loader_factory_), std::move(throttles), cert_url,
std::move(request_initiator_), force_fetch, std::move(callback));
}
// static
std::unique_ptr<SignedExchangeCertFetcherFactory>
SignedExchangeCertFetcherFactory::Create(
url::Origin request_initiator,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter) {
return std::make_unique<SignedExchangeCertFetcherFactoryImpl>(
std::move(request_initiator), std::move(url_loader_factory),
std::move(url_loader_throttles_getter));
}
} // namespace content
// 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.
#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_CERT_FETCHER_FACTORY_H_
#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_CERT_FETCHER_FACTORY_H_
#include <memory>
#include <vector>
#include "content/browser/web_package/signed_exchange_cert_fetcher.h"
#include "content/common/content_export.h"
#include "url/origin.h"
namespace network {
class SharedURLLoaderFactory;
} // namespace network
namespace content {
class SignedExchangeCertFetcher;
class URLLoaderThrottle;
// An interface for creating SignedExchangeCertFetcher object.
class CONTENT_EXPORT SignedExchangeCertFetcherFactory {
public:
virtual ~SignedExchangeCertFetcherFactory();
// Creates a SignedExchangeCertFetcher and starts fetching the certificate.
// Can be called at most once.
virtual std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
SignedExchangeCertFetcher::CertificateCallback callback) = 0;
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
static std::unique_ptr<SignedExchangeCertFetcherFactory> Create(
url::Origin request_initiator,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter);
};
} // namespace content
#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_CERT_FETCHER_FACTORY_H_
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "content/browser/loader/merkle_integrity_source_stream.h" #include "content/browser/loader/merkle_integrity_source_stream.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher.h" #include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/browser/web_package/signed_exchange_consts.h" #include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_header.h" #include "content/browser/web_package/signed_exchange_header.h"
#include "content/browser/web_package/signed_exchange_signature_verifier.h" #include "content/browser/web_package/signed_exchange_signature_verifier.h"
...@@ -67,15 +67,11 @@ SignedExchangeHandler::SignedExchangeHandler( ...@@ -67,15 +67,11 @@ SignedExchangeHandler::SignedExchangeHandler(
std::string content_type, std::string content_type,
std::unique_ptr<net::SourceStream> body, std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback, ExchangeHeadersCallback headers_callback,
url::Origin request_initiator, std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter) scoped_refptr<net::URLRequestContextGetter> request_context_getter)
: headers_callback_(std::move(headers_callback)), : headers_callback_(std::move(headers_callback)),
source_(std::move(body)), source_(std::move(body)),
request_initiator_(std::move(request_initiator)), cert_fetcher_factory_(std::move(cert_fetcher_factory)),
url_loader_factory_(std::move(url_loader_factory)),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
request_context_getter_(std::move(request_context_getter)), request_context_getter_(std::move(request_context_getter)),
net_log_(net::NetLogWithSource::Make( net_log_(net::NetLogWithSource::Make(
request_context_getter_->GetURLRequestContext()->net_log(), request_context_getter_->GetURLRequestContext()->net_log(),
...@@ -231,15 +227,12 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() { ...@@ -231,15 +227,12 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
// may be empty. // may be empty.
DCHECK(cert_url.is_valid()); DCHECK(cert_url.is_valid());
DCHECK(url_loader_factory_); DCHECK(cert_fetcher_factory_);
DCHECK(url_loader_throttles_getter_); cert_fetcher_ = std::move(cert_fetcher_factory_)
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles = ->CreateFetcherAndStart(
std::move(url_loader_throttles_getter_).Run(); cert_url, false,
cert_fetcher_ = SignedExchangeCertFetcher::CreateAndStart( base::BindOnce(&SignedExchangeHandler::OnCertReceived,
std::move(url_loader_factory_), std::move(throttles), cert_url, base::Unretained(this)));
std::move(request_initiator_), false,
base::BindOnce(&SignedExchangeHandler::OnCertReceived,
base::Unretained(this)));
state_ = State::kFetchingCertificate; state_ = State::kFetchingCertificate;
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"), TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
......
...@@ -32,14 +32,13 @@ class X509Certificate; ...@@ -32,14 +32,13 @@ class X509Certificate;
} // namespace net } // namespace net
namespace network { namespace network {
class SharedURLLoaderFactory;
struct ResourceResponseHead; struct ResourceResponseHead;
} // namespace network } // namespace network
namespace content { namespace content {
class SignedExchangeCertFetcher; class SignedExchangeCertFetcher;
class URLLoaderThrottle; class SignedExchangeCertFetcherFactory;
// IMPORTANT: Currenly SignedExchangeHandler partially implements the verifying // IMPORTANT: Currenly SignedExchangeHandler partially implements the verifying
// logic. // logic.
...@@ -55,9 +54,6 @@ class CONTENT_EXPORT SignedExchangeHandler { ...@@ -55,9 +54,6 @@ class CONTENT_EXPORT SignedExchangeHandler {
std::unique_ptr<net::SourceStream> payload_stream, std::unique_ptr<net::SourceStream> payload_stream,
base::Optional<net::SSLInfo>)>; base::Optional<net::SSLInfo>)>;
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
// TODO(https://crbug.com/817187): Find a more sophisticated way to use a // TODO(https://crbug.com/817187): Find a more sophisticated way to use a
// MockCertVerifier in browser tests instead of using the static method. // MockCertVerifier in browser tests instead of using the static method.
static void SetCertVerifierForTesting(net::CertVerifier* cert_verifier); static void SetCertVerifierForTesting(net::CertVerifier* cert_verifier);
...@@ -67,16 +63,13 @@ class CONTENT_EXPORT SignedExchangeHandler { ...@@ -67,16 +63,13 @@ class CONTENT_EXPORT SignedExchangeHandler {
// Once constructed |this| starts reading the |body| and parses the response // Once constructed |this| starts reading the |body| and parses the response
// as a signed HTTP exchange. The response body of the exchange can be read // as a signed HTTP exchange. The response body of the exchange can be read
// from |payload_stream| passed to |headers_callback|. |url_loader_factory| // from |payload_stream| passed to |headers_callback|. |cert_fetcher_factory|
// and |url_loader_throttles_getter| are used to set up a network URLLoader to // is used to create a SignedExchangeCertFetcher that fetches the certificate.
// actually fetch the certificate.
SignedExchangeHandler( SignedExchangeHandler(
std::string content_type, std::string content_type,
std::unique_ptr<net::SourceStream> body, std::unique_ptr<net::SourceStream> body,
ExchangeHeadersCallback headers_callback, ExchangeHeadersCallback headers_callback,
url::Origin request_initiator, std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter); scoped_refptr<net::URLRequestContextGetter> request_context_getter);
~SignedExchangeHandler(); ~SignedExchangeHandler();
...@@ -114,13 +107,7 @@ class CONTENT_EXPORT SignedExchangeHandler { ...@@ -114,13 +107,7 @@ class CONTENT_EXPORT SignedExchangeHandler {
base::Optional<SignedExchangeHeader> header_; base::Optional<SignedExchangeHeader> header_;
// Used to create |cert_fetcher_|. std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory_;
url::Origin request_initiator_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// This getter is guaranteed to be valid at least until the headers callback
// is run.
URLLoaderThrottlesGetter url_loader_throttles_getter_;
std::unique_ptr<SignedExchangeCertFetcher> cert_fetcher_; std::unique_ptr<SignedExchangeCertFetcher> cert_fetcher_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_; scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
...@@ -149,10 +136,8 @@ class SignedExchangeHandlerFactory { ...@@ -149,10 +136,8 @@ class SignedExchangeHandlerFactory {
virtual std::unique_ptr<SignedExchangeHandler> Create( virtual std::unique_ptr<SignedExchangeHandler> Create(
std::unique_ptr<net::SourceStream> body, std::unique_ptr<net::SourceStream> body,
SignedExchangeHandler::ExchangeHeadersCallback headers_callback, SignedExchangeHandler::ExchangeHeadersCallback headers_callback,
url::Origin request_initiator, std::unique_ptr<SignedExchangeCertFetcherFactory>
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, cert_fetcher_factory) = 0;
SignedExchangeHandler::URLLoaderThrottlesGetter
url_loader_throttles_getter) = 0;
}; };
} // namespace content } // namespace content
......
// 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/web_package/signed_exchange_handler.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/filter/mock_source_stream.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
const uint64_t kSignatureHeaderDate = 1520834000;
const int kOutputBufferSize = 4096;
std::string GetTestFileContents(const char* name) {
base::FilePath path;
PathService::Get(content::DIR_TEST_DATA, &path);
path = path.AppendASCII("htxg").AppendASCII(name);
std::string contents;
CHECK(base::ReadFileToString(path, &contents));
return contents;
}
class MockSignedExchangeCertFetcherFactory
: public SignedExchangeCertFetcherFactory {
public:
MockSignedExchangeCertFetcherFactory(const GURL& expected_cert_url,
std::string cert_str)
: expected_cert_url_(expected_cert_url), cert_str_(cert_str) {}
std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
SignedExchangeCertFetcher::CertificateCallback callback) override {
EXPECT_EQ(cert_url, expected_cert_url_);
base::Optional<std::vector<base::StringPiece>> der_certs =
SignedExchangeCertFetcher::GetCertChainFromMessage(cert_str_);
DCHECK(der_certs);
scoped_refptr<net::X509Certificate> cert =
net::X509Certificate::CreateFromDERCertChain(*der_certs);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), cert));
return nullptr;
}
private:
const GURL expected_cert_url_;
const std::string cert_str_;
};
} // namespace
class SignedExchangeHandlerTest
: public ::testing::TestWithParam<net::MockSourceStream::Mode> {
public:
SignedExchangeHandlerTest()
: mock_cert_verifier_(std::make_unique<net::MockCertVerifier>()),
request_initiator_(
url::Origin::Create(GURL("https://htxg.example.com/test.htxg"))) {}
void SetUp() override {
SignedExchangeHandler::SetCertVerifierForTesting(mock_cert_verifier_.get());
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
feature_list_.InitAndEnableFeature(features::kSignedHTTPExchange);
output_buffer_ = new net::IOBuffer(kOutputBufferSize);
std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
source->set_read_one_byte_at_a_time(true);
source_ = source.get();
auto cert_fetcher_factory =
std::make_unique<MockSignedExchangeCertFetcherFactory>(
GURL("https://cert.example.org/cert.msg"),
GetTestFileContents("wildcard_example.org.public.pem.msg"));
request_context_getter_ = new net::TestURLRequestContextGetter(
scoped_task_environment_.GetMainThreadTaskRunner());
handler_ = std::make_unique<SignedExchangeHandler>(
"application/signed-exchange;v=b0", std::move(source),
base::BindOnce(&SignedExchangeHandlerTest::OnHeaderFound,
base::Unretained(this)),
std::move(cert_fetcher_factory), request_context_getter_);
}
void TearDown() override {
SignedExchangeHandler::SetCertVerifierForTesting(nullptr);
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Optional<base::Time>());
}
// Reads from |payload_stream_| until an error occurs or the EOF is reached.
// When an error occurs, returns the net error code. When an EOF is reached,
// returns the number of bytes read and appends data read to |output|.
int ReadPayloadStream(std::string* output) {
int bytes_read = 0;
while (true) {
net::TestCompletionCallback callback;
int rv = payload_stream_->Read(output_buffer_.get(), kOutputBufferSize,
callback.callback());
if (rv == net::ERR_IO_PENDING) {
while (source_->awaiting_completion())
source_->CompleteNextRead();
rv = callback.WaitForResult();
}
if (rv == net::OK)
break;
if (rv < net::OK)
return rv;
EXPECT_GT(rv, net::OK);
bytes_read += rv;
output->append(output_buffer_->data(), rv);
}
return bytes_read;
}
bool read_header() const { return read_header_; }
net::Error error() const { return error_; }
const network::ResourceResponseHead& resource_response() const {
return resource_response_;
}
void WaitForHeader() {
while (!read_header()) {
while (source_->awaiting_completion())
source_->CompleteNextRead();
scoped_task_environment_.RunUntilIdle();
}
}
protected:
std::unique_ptr<net::MockCertVerifier> mock_cert_verifier_;
net::MockSourceStream* source_;
std::unique_ptr<SignedExchangeHandler> handler_;
private:
void OnHeaderFound(net::Error error,
const GURL&,
const std::string&,
const network::ResourceResponseHead& resource_response,
std::unique_ptr<net::SourceStream> payload_stream,
base::Optional<net::SSLInfo>) {
read_header_ = true;
error_ = error;
resource_response_ = resource_response;
payload_stream_ = std::move(payload_stream);
}
base::test::ScopedFeatureList feature_list_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
const url::Origin request_initiator_;
scoped_refptr<net::IOBuffer> output_buffer_;
bool read_header_ = false;
net::Error error_;
network::ResourceResponseHead resource_response_;
std::unique_ptr<net::SourceStream> payload_stream_;
};
TEST_P(SignedExchangeHandlerTest, Empty) {
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
WaitForHeader();
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_FAILED, error());
}
TEST_P(SignedExchangeHandlerTest, Simple) {
mock_cert_verifier_->set_default_result(net::OK);
std::string contents = GetTestFileContents("test.example.org_test.htxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
WaitForHeader();
ASSERT_TRUE(read_header());
EXPECT_EQ(net::OK, error());
EXPECT_EQ(200, resource_response().headers->response_code());
std::string payload;
int rv = ReadPayloadStream(&payload);
std::string expected_payload = GetTestFileContents("test.html");
EXPECT_EQ(payload, expected_payload);
EXPECT_EQ(rv, static_cast<int>(expected_payload.size()));
}
TEST_P(SignedExchangeHandlerTest, ParseError) {
const uint8_t data[] = {0x00, 0x00, 0x01, 0x00};
source_->AddReadResult(reinterpret_cast<const char*>(data), sizeof(data),
net::OK, GetParam());
WaitForHeader();
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_FAILED, error());
}
TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
std::string contents = GetTestFileContents("test.example.org_test.htxg");
contents.resize(30);
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
WaitForHeader();
ASSERT_TRUE(read_header());
EXPECT_EQ(net::ERR_FAILED, error());
}
INSTANTIATE_TEST_CASE_P(SignedExchangeHandlerTests,
SignedExchangeHandlerTest,
::testing::Values(net::MockSourceStream::SYNC,
net::MockSourceStream::ASYNC));
} // namespace content
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "content/browser/loader/data_pipe_to_source_stream.h" #include "content/browser/loader/data_pipe_to_source_stream.h"
#include "content/browser/loader/source_stream_to_data_pipe.h" #include "content/browser/loader/source_stream_to_data_pipe.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/browser/web_package/signed_exchange_handler.h" #include "content/browser/web_package/signed_exchange_handler.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
#include "net/cert/cert_status_flags.h" #include "net/cert/cert_status_flags.h"
...@@ -165,13 +166,16 @@ void WebPackageLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) { ...@@ -165,13 +166,16 @@ void WebPackageLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
void WebPackageLoader::OnStartLoadingResponseBody( void WebPackageLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) { mojo::ScopedDataPipeConsumerHandle body) {
auto cert_fetcher_factory = SignedExchangeCertFetcherFactory::Create(
std::move(request_initiator_), std::move(url_loader_factory_),
std::move(url_loader_throttles_getter_));
if (g_signed_exchange_factory_for_testing_) { if (g_signed_exchange_factory_for_testing_) {
signed_exchange_handler_ = g_signed_exchange_factory_for_testing_->Create( signed_exchange_handler_ = g_signed_exchange_factory_for_testing_->Create(
std::make_unique<DataPipeToSourceStream>(std::move(body)), std::make_unique<DataPipeToSourceStream>(std::move(body)),
base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound, base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound,
weak_factory_.GetWeakPtr()), weak_factory_.GetWeakPtr()),
std::move(request_initiator_), std::move(url_loader_factory_), std::move(cert_fetcher_factory));
std::move(url_loader_throttles_getter_));
return; return;
} }
...@@ -179,9 +183,7 @@ void WebPackageLoader::OnStartLoadingResponseBody( ...@@ -179,9 +183,7 @@ void WebPackageLoader::OnStartLoadingResponseBody(
content_type_, std::make_unique<DataPipeToSourceStream>(std::move(body)), content_type_, std::make_unique<DataPipeToSourceStream>(std::move(body)),
base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound, base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound,
weak_factory_.GetWeakPtr()), weak_factory_.GetWeakPtr()),
std::move(request_initiator_), std::move(url_loader_factory_), std::move(cert_fetcher_factory), std::move(request_context_getter_));
std::move(url_loader_throttles_getter_),
std::move(request_context_getter_));
} }
void WebPackageLoader::OnComplete( void WebPackageLoader::OnComplete(
......
...@@ -1501,6 +1501,7 @@ test("content_unittests") { ...@@ -1501,6 +1501,7 @@ test("content_unittests") {
"../browser/web_contents/web_drag_dest_mac_unittest.mm", "../browser/web_contents/web_drag_dest_mac_unittest.mm",
"../browser/web_contents/web_drag_source_mac_unittest.mm", "../browser/web_contents/web_drag_source_mac_unittest.mm",
"../browser/web_package/signed_exchange_cert_fetcher_unittest.cc", "../browser/web_package/signed_exchange_cert_fetcher_unittest.cc",
"../browser/web_package/signed_exchange_handler_unittest.cc",
"../browser/web_package/signed_exchange_header_parser_unittest.cc", "../browser/web_package/signed_exchange_header_parser_unittest.cc",
"../browser/web_package/signed_exchange_header_unittest.cc", "../browser/web_package/signed_exchange_header_unittest.cc",
"../browser/web_package/signed_exchange_signature_verifier_unittest.cc", "../browser/web_package/signed_exchange_signature_verifier_unittest.cc",
......
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