blob: 494c04efdc97ad8cd7d752e7438c3c3883cb3151 [file] [log] [blame]
// Copyright 2019 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 "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_server_properties.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
using net::test::IsOk;
// TODO(eroman): Test that cookies aren't sent.
namespace cert_verifier {
namespace {
const base::FilePath::CharType kDocRoot[] =
FILE_PATH_LITERAL("net/data/cert_net_fetcher_impl_unittest");
const char kMockURL[] = "http://mock.hanging.read/";
const char kMockSecureDnsHostname[] = "mock.secure.dns.check";
// Wait for the request to complete, and verify that it completed successfully
// with the indicated bytes.
void VerifySuccess(const std::string& expected_body,
net::CertNetFetcher::Request* request) {
net::Error actual_error;
std::vector<uint8_t> actual_body;
request->WaitForResult(&actual_error, &actual_body);
EXPECT_THAT(actual_error, IsOk());
EXPECT_EQ(expected_body, std::string(actual_body.begin(), actual_body.end()));
}
// Wait for the request to complete, and verify that it completed with the
// indicated failure.
void VerifyFailure(net::Error expected_error,
net::CertNetFetcher::Request* request) {
net::Error actual_error;
std::vector<uint8_t> actual_body;
request->WaitForResult(&actual_error, &actual_body);
EXPECT_EQ(expected_error, actual_error);
EXPECT_EQ(0u, actual_body.size());
}
class CertNetFetcherURLLoaderTest : public PlatformTest {
public:
CertNetFetcherURLLoaderTest() {
test_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
StartNetworkThread();
}
~CertNetFetcherURLLoaderTest() override {
if (!creation_thread_)
return;
creation_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CertNetFetcherURLLoaderTest::TeardownOnNetworkThread,
base::Unretained(this)));
creation_thread_->Stop();
}
protected:
net::CertNetFetcher* fetcher() const { return test_util_->fetcher().get(); }
void SetUseHangingURLLoader() { use_hanging_url_loader_ = true; }
void CreateFetcherOnNetworkThread(base::WaitableEvent* done) {
// Create the CertNetFetcherTestUtil.
if (use_hanging_url_loader_)
test_util_ = std::make_unique<CertNetFetcherTestUtilFakeLoader>();
else
test_util_ = std::make_unique<CertNetFetcherTestUtilRealLoader>();
done->Signal();
}
void CreateFetcher() {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
creation_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(
&CertNetFetcherURLLoaderTest::CreateFetcherOnNetworkThread,
base::Unretained(this), &done));
done.Wait();
}
void ShutdownFetcherOnNetworkThread(base::WaitableEvent* done) {
test_util_->fetcher()->Shutdown();
done->Signal();
}
void ShutdownFetcher() {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
creation_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(
&CertNetFetcherURLLoaderTest::ShutdownFetcherOnNetworkThread,
base::Unretained(this), &done));
done.Wait();
}
int NumCreatedRequests() {
int count = 0;
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
creation_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CertNetFetcherURLLoaderTest::CountCreatedRequests,
base::Unretained(this), &count, &done));
done.Wait();
return count;
}
void StartNetworkThread() {
// Start the network thread.
creation_thread_ = std::make_unique<base::Thread>("network thread");
base::Thread::Options options(base::MessagePumpType::IO, 0);
EXPECT_TRUE(creation_thread_->StartWithOptions(std::move(options)));
}
void ResetTestUtilOnNetworkThread(base::WaitableEvent* done) {
test_util_.reset();
done->Signal();
}
void ResetTestUtil() {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
creation_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(
&CertNetFetcherURLLoaderTest::ResetTestUtilOnNetworkThread,
base::Unretained(this), &done));
done.Wait();
}
void ResetTestURLLoaderFactoryOnNetworkThread(base::WaitableEvent* done) {
test_util_->ResetURLLoaderFactory();
done->Signal();
}
void ResetTestURLLoaderFactory() {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
creation_thread_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CertNetFetcherURLLoaderTest::
ResetTestURLLoaderFactoryOnNetworkThread,
base::Unretained(this), &done));
done.Wait();
}
void TeardownOnNetworkThread() {
if (!test_util_)
return;
test_util_->fetcher()->Shutdown();
DCHECK(test_util_->fetcher()->HasOneRef());
test_util_.reset();
}
void WaitForAlreadyPostedNetworkTasks() {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
creation_thread_->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CertNetFetcherURLLoaderTest::SignalDoneOnNetworkThread,
base::Unretained(this), &done));
done.Wait();
}
void SignalDoneOnNetworkThread(base::WaitableEvent* done) { done->Signal(); }
void CountCreatedRequests(int* count, base::WaitableEvent* done) {
DCHECK(!use_hanging_url_loader_);
*count = static_cast<CertNetFetcherTestUtilRealLoader*>(test_util_.get())
->shared_url_loader_factory()
->num_created_loaders();
done->Signal();
}
net::EmbeddedTestServer test_server_;
std::unique_ptr<base::Thread> creation_thread_;
std::unique_ptr<CertNetFetcherTestUtil> test_util_;
bool use_hanging_url_loader_ = false;
};
// Interceptor to check that secure DNS has been disabled.
class SecureDnsInterceptor : public net::URLRequestInterceptor {
public:
explicit SecureDnsInterceptor(bool* invoked_interceptor)
: invoked_interceptor_(invoked_interceptor) {}
~SecureDnsInterceptor() override = default;
private:
// URLRequestInterceptor implementation:
std::unique_ptr<net::URLRequestJob> MaybeInterceptRequest(
net::URLRequest* request) const override {
EXPECT_EQ(net::SecureDnsPolicy::kDisable, request->secure_dns_policy());
*invoked_interceptor_ = true;
return nullptr;
}
bool* invoked_interceptor_;
};
class CertNetFetcherURLLoaderTestWithSecureDnsInterceptor
: public CertNetFetcherURLLoaderTest,
public net::WithTaskEnvironment {
public:
CertNetFetcherURLLoaderTestWithSecureDnsInterceptor()
: invoked_interceptor_(false) {}
void SetUp() override {
net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
"http", kMockSecureDnsHostname,
std::make_unique<SecureDnsInterceptor>(&invoked_interceptor_));
}
void TearDown() override {
net::URLRequestFilter::GetInstance()->ClearHandlers();
}
bool invoked_interceptor() { return invoked_interceptor_; }
private:
bool invoked_interceptor_;
};
// Helper to start an AIA fetch using default parameters.
WARN_UNUSED_RESULT std::unique_ptr<net::CertNetFetcher::Request> StartRequest(
net::CertNetFetcher* fetcher,
const GURL& url) {
return fetcher->FetchCaIssuers(url, net::CertNetFetcher::DEFAULT,
net::CertNetFetcher::DEFAULT);
}
// Fetch a few unique URLs using GET in parallel. Each URL has a different body
// and Content-Type.
TEST_F(CertNetFetcherURLLoaderTest, ParallelFetchNoDuplicates) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
// Request a URL with Content-Type "application/pkix-cert"
GURL url1 = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request1 =
StartRequest(fetcher(), url1);
// Request a URL with Content-Type "application/pkix-crl"
GURL url2 = test_server_.GetURL("/root.crl");
std::unique_ptr<net::CertNetFetcher::Request> request2 =
StartRequest(fetcher(), url2);
// Request a URL with Content-Type "application/pkcs7-mime"
GURL url3 = test_server_.GetURL("/certs.p7c");
std::unique_ptr<net::CertNetFetcher::Request> request3 =
StartRequest(fetcher(), url3);
// Wait for all of the requests to complete and verify the fetch results.
VerifySuccess("-cert.crt-\n", request1.get());
VerifySuccess("-root.crl-\n", request2.get());
VerifySuccess("-certs.p7c-\n", request3.get());
EXPECT_EQ(3, NumCreatedRequests());
}
// Fetch a caIssuers URL which has an unexpected extension and Content-Type.
// The extension is .txt and the Content-Type is text/plain. Despite being
// unusual this succeeds as the extension and Content-Type are not required to
// be meaningful.
TEST_F(CertNetFetcherURLLoaderTest, ContentTypeDoesntMatter) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url = test_server_.GetURL("/foo.txt");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifySuccess("-foo.txt-\n", request.get());
}
// Fetch a URLs whose HTTP response code is not 200. These are considered
// failures.
TEST_F(CertNetFetcherURLLoaderTest, HttpStatusCode) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
// Response was HTTP status 404.
{
GURL url = test_server_.GetURL("/404.html");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifyFailure(net::ERR_HTTP_RESPONSE_CODE_FAILURE, request.get());
}
// Response was HTTP status 500.
{
GURL url = test_server_.GetURL("/500.html");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifyFailure(net::ERR_HTTP_RESPONSE_CODE_FAILURE, request.get());
}
}
// Fetching a URL with a Content-Disposition header should have no effect.
TEST_F(CertNetFetcherURLLoaderTest, ContentDisposition) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url = test_server_.GetURL("/downloadable.js");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifySuccess("-downloadable.js-\n", request.get());
}
// Verifies that a cacheable request will be served from the HTTP cache the
// second time it is requested.
TEST_F(CertNetFetcherURLLoaderTest, Cache) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
// Fetch a URL whose HTTP headers make it cacheable for 1 hour.
GURL url(test_server_.GetURL("/cacheable_1hr.crt"));
{
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifySuccess("-cacheable_1hr.crt-\n", request.get());
}
EXPECT_EQ(1, NumCreatedRequests());
// Kill the HTTP server.
ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
// Fetch again -- will fail unless served from cache.
{
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifySuccess("-cacheable_1hr.crt-\n", request.get());
}
EXPECT_EQ(2, NumCreatedRequests());
}
// Verify that the maximum response body constraints are enforced by fetching a
// resource that is larger than the limit.
TEST_F(CertNetFetcherURLLoaderTest, TooLarge) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
// This file has a response body 12 bytes long. So setting the maximum to 11
// bytes will cause it to fail.
GURL url(test_server_.GetURL("/certs.p7c"));
std::unique_ptr<net::CertNetFetcher::Request> request =
fetcher()->FetchCaIssuers(url, net::CertNetFetcher::DEFAULT, 11);
VerifyFailure(net::ERR_INSUFFICIENT_RESOURCES, request.get());
}
// Set the timeout to 10 milliseconds, and try fetching a URL that takes 5
// seconds to complete. It should fail due to a timeout.
TEST_F(CertNetFetcherURLLoaderTest, Hang) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url(test_server_.GetURL("/slow/certs.p7c?5"));
std::unique_ptr<net::CertNetFetcher::Request> request =
fetcher()->FetchCaIssuers(url, 10, net::CertNetFetcher::DEFAULT);
VerifyFailure(net::ERR_TIMED_OUT, request.get());
}
// Verify that if a response is gzip-encoded it gets inflated before being
// returned to the caller.
TEST_F(CertNetFetcherURLLoaderTest, Gzip) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url(test_server_.GetURL("/gzipped_crl"));
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifySuccess("-gzipped_crl-\n", request.get());
}
// Try fetching an unsupported URL scheme (https).
TEST_F(CertNetFetcherURLLoaderTest, HttpsNotAllowed) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url("https://foopy/foo.crt");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifyFailure(net::ERR_DISALLOWED_URL_SCHEME, request.get());
// No request was created because the URL scheme was unsupported.
EXPECT_EQ(0, NumCreatedRequests());
}
// Try fetching a URL which redirects to https.
TEST_F(CertNetFetcherURLLoaderTest, RedirectToHttpsNotAllowed) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url(test_server_.GetURL("/redirect_https"));
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifyFailure(net::ERR_DISALLOWED_URL_SCHEME, request.get());
EXPECT_EQ(1, NumCreatedRequests());
}
// Try fetching an unsupported URL scheme (https) and then immediately
// cancelling. This is a bit special because this codepath needs to post a task.
TEST_F(CertNetFetcherURLLoaderTest, CancelHttpsNotAllowed) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url("https://foopy/foo.crt");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
// Cancel the request (May or may not have started yet, as the request is
// running on another thread).
request.reset();
}
TEST_F(CertNetFetcherURLLoaderTest,
ReconnectsAfterURLLoaderFactoryDisconnection) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL cert_crt_url = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request1 =
StartRequest(fetcher(), cert_crt_url);
// Reset the URLLoaderFactory. It should reconnect afterwards and successfully
// complete the rest of the requests.
ResetTestURLLoaderFactory();
GURL root_url = test_server_.GetURL("/root.crl");
std::unique_ptr<net::CertNetFetcher::Request> request2 =
StartRequest(fetcher(), root_url);
GURL certs_p7c_url = test_server_.GetURL("/certs.p7c");
std::unique_ptr<net::CertNetFetcher::Request> request3 =
StartRequest(fetcher(), certs_p7c_url);
// Wait for all of the requests to complete and verify the fetch results.
VerifySuccess("-root.crl-\n", request2.get());
VerifySuccess("-certs.p7c-\n", request3.get());
// Depending on thread timing, |request1| may have completed successfully
// prior to the URLLoaderFactory being disconnected, or the disconnect may
// have caused the request to fail. Because it's timing dependent, and not
// relevant to the subsequent requests which must succeed, either state is
// allowed.
{
net::Error error;
std::vector<uint8_t> body;
request1->WaitForResult(&error, &body);
}
EXPECT_LE(2, NumCreatedRequests());
ResetTestURLLoaderFactory();
// Requests should work even after a second reset.
std::unique_ptr<net::CertNetFetcher::Request> request4 =
StartRequest(fetcher(), cert_crt_url);
std::unique_ptr<net::CertNetFetcher::Request> request5 =
StartRequest(fetcher(), root_url);
VerifySuccess("-cert.crt-\n", request4.get());
VerifySuccess("-root.crl-\n", request5.get());
}
// Start a few requests, and cancel one of them before running the message loop
// again.
TEST_F(CertNetFetcherURLLoaderTest, CancelBeforeRunningMessageLoop) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url1 = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request1 =
StartRequest(fetcher(), url1);
GURL url2 = test_server_.GetURL("/root.crl");
std::unique_ptr<net::CertNetFetcher::Request> request2 =
StartRequest(fetcher(), url2);
GURL url3 = test_server_.GetURL("/certs.p7c");
std::unique_ptr<net::CertNetFetcher::Request> request3 =
StartRequest(fetcher(), url3);
// Cancel the second request.
request2.reset();
// Wait for the non-cancelled requests to complete, and verify the fetch
// results.
VerifySuccess("-cert.crt-\n", request1.get());
VerifySuccess("-certs.p7c-\n", request3.get());
}
// Start several requests, and cancel one of them after the first has completed.
// TODO(eroman): Rename this test.
TEST_F(CertNetFetcherURLLoaderTest, CancelAfterRunningMessageLoop) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url1 = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request1 =
StartRequest(fetcher(), url1);
GURL url2 = test_server_.GetURL("/certs.p7c");
std::unique_ptr<net::CertNetFetcher::Request> request2 =
StartRequest(fetcher(), url2);
GURL url3("ftp://www.not.supported.com/foo");
std::unique_ptr<net::CertNetFetcher::Request> request3 =
StartRequest(fetcher(), url3);
// Wait for the ftp request to complete (it should complete right away since
// it doesn't even try to connect to the server).
VerifyFailure(net::ERR_DISALLOWED_URL_SCHEME, request3.get());
// Cancel the second outstanding request.
request2.reset();
// Wait for the first request to complete and verify the fetch result.
VerifySuccess("-cert.crt-\n", request1.get());
}
// Fetch the same URLs in parallel and verify that only 1 request is made per
// URL.
TEST_F(CertNetFetcherURLLoaderTest, ParallelFetchDuplicates) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url1 = test_server_.GetURL("/cert.crt");
GURL url2 = test_server_.GetURL("/root.crl");
// Issue 3 requests for url1, and 3 requests for url2
std::unique_ptr<net::CertNetFetcher::Request> request1 =
StartRequest(fetcher(), url1);
std::unique_ptr<net::CertNetFetcher::Request> request2 =
StartRequest(fetcher(), url2);
std::unique_ptr<net::CertNetFetcher::Request> request3 =
StartRequest(fetcher(), url1);
std::unique_ptr<net::CertNetFetcher::Request> request4 =
StartRequest(fetcher(), url2);
std::unique_ptr<net::CertNetFetcher::Request> request5 =
StartRequest(fetcher(), url2);
std::unique_ptr<net::CertNetFetcher::Request> request6 =
StartRequest(fetcher(), url1);
// Cancel all but one of the requests for url1.
request1.reset();
request3.reset();
// Wait for the remaining requests to finish and verify the fetch results.
VerifySuccess("-root.crl-\n", request2.get());
VerifySuccess("-root.crl-\n", request4.get());
VerifySuccess("-root.crl-\n", request5.get());
VerifySuccess("-cert.crt-\n", request6.get());
// Verify that only 2 URLRequests were started even though 6 requests were
// issued.
EXPECT_EQ(2, NumCreatedRequests());
}
// Cancel a request and then start another one for the same URL.
TEST_F(CertNetFetcherURLLoaderTest, CancelThenStart) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
GURL url = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request1 =
StartRequest(fetcher(), url);
request1.reset();
std::unique_ptr<net::CertNetFetcher::Request> request2 =
StartRequest(fetcher(), url);
std::unique_ptr<net::CertNetFetcher::Request> request3 =
StartRequest(fetcher(), url);
request3.reset();
// All but |request2| were canceled.
VerifySuccess("-cert.crt-\n", request2.get());
}
// Start duplicate requests and then cancel all of them.
TEST_F(CertNetFetcherURLLoaderTest, CancelAll) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
std::unique_ptr<net::CertNetFetcher::Request> requests[3];
GURL url = test_server_.GetURL("/cert.crt");
for (auto& request : requests) {
request = StartRequest(fetcher(), url);
}
// Cancel all the requests.
for (auto& request : requests) {
request.reset();
}
// Wait for the network thread so that all of the CreateLoaderAndStart
// messages are handled by the network thread.
WaitForAlreadyPostedNetworkTasks();
EXPECT_EQ(1, NumCreatedRequests());
}
// Tests that Requests are signalled for completion even if they are
// created after the CertNetFetcher has been shutdown.
TEST_F(CertNetFetcherURLLoaderTest, RequestsAfterShutdown) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
ShutdownFetcher();
GURL url = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
VerifyFailure(net::ERR_ABORTED, request.get());
EXPECT_EQ(0, NumCreatedRequests());
}
// Tests that Requests are signalled for completion if the fetcher is
// shutdown and the network thread stopped before the request is
// started.
TEST_F(CertNetFetcherURLLoaderTest,
RequestAfterShutdownAndNetworkThreadStopped) {
ASSERT_TRUE(test_server_.Start());
CreateFetcher();
ShutdownFetcher();
// Take a reference to our fetcher to keep it alive when we reset
// |test_util_|.
scoped_refptr<net::CertNetFetcher> fetcher_ref = fetcher();
ResetTestUtil();
creation_thread_.reset();
GURL url = test_server_.GetURL("/cert.crt");
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher_ref.get(), url);
VerifyFailure(net::ERR_ABORTED, request.get());
}
// Tests that outstanding Requests are cancelled when Shutdown is called.
TEST_F(CertNetFetcherURLLoaderTest, ShutdownCancelsRequests) {
SetUseHangingURLLoader();
CreateFetcher();
GURL url = GURL(kMockURL);
std::unique_ptr<net::CertNetFetcher::Request> request =
StartRequest(fetcher(), url);
ShutdownFetcher();
VerifyFailure(net::ERR_ABORTED, request.get());
}
TEST_F(CertNetFetcherURLLoaderTestWithSecureDnsInterceptor, SecureDnsDisabled) {
CreateFetcher();
std::unique_ptr<net::CertNetFetcher::Request> request = StartRequest(
fetcher(),
GURL("http://" + std::string(kMockSecureDnsHostname) + "/cert.crt"));
net::Error actual_error;
std::vector<uint8_t> actual_body;
request->WaitForResult(&actual_error, &actual_body);
EXPECT_TRUE(invoked_interceptor());
}
} // namespace
} // namespace cert_verifier