chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Overview
//
// The main entry point is CertNetFetcherURLLoader. This is an implementation of
// net::CertNetFetcher that provides a service for fetching network requests.
//
// The interface for net::CertNetFetcher is synchronous, however allows
// overlapping requests. When starting a request CertNetFetcherURLLoader
// returns a net::CertNetFetcher::Request (CertNetFetcherRequestImpl) that the
// caller can use to cancel the fetch, or wait for it to complete
// (blocking).
//
// The CertNetFetcherURLLoader is shared between a creation thread and a
// caller thread that waits for fetches to happen on the creation thread.
//
// The classes are mainly organized based on their thread affinity:
//
// ---------------
// Straddles caller thread and creation thread
// ---------------
//
// CertNetFetcherURLLoader (implements CertNetFetcher)
//   * Main entry point. Must be created and shutdown from the creation thread.
//   * Provides a service to start/cancel/wait for URL fetches, to be
//     used on the caller thread.
//   * Returns callers a net::CertNetFetcher::Request as a handle
//   * Requests can run in parallel, however will block the current thread when
//     reading results.
//   * Posts tasks to creation thread to coordinate actual work
//
// RequestCore
//   * Reference-counted bridge between CertNetFetcherRequestImpl and the
//     dependencies on the creation thread
//   * Holds the result of the request, a WaitableEvent for signaling
//     completion, and pointers for canceling work on creation thread.
//
// ---------------
// Lives on caller thread
// ---------------
//
// CertNetFetcherRequestImpl (implements net::CertNetFetcher::Request)
//   * Wrapper for cancelling events, or waiting for a request to complete
//   * Waits on a WaitableEvent to complete requests.
//
// ---------------
// Lives on creation thread
// ---------------
//
// AsyncCertNetFetcherURLLoader
//   * Asynchronous manager for outstanding requests. Handles de-duplication,
//     timeouts, and actual integration with network stack. This is where the
//     majority of the logic lives.
//   * Signals completion of requests through RequestCore's WaitableEvent.
//   * Attaches requests to Jobs for the purpose of de-duplication

#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"

#include <memory>
#include <tuple>
#include <utility>

#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/containers/to_vector.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/not_fatal_until.h"
#include "base/numerics/safe_math.h"
#include "base/ranges/algorithm.h"
#include "base/sequence_checker.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"

// TODO(eroman): Add support for POST parameters.
// TODO(eroman): Add controls for bypassing the cache.
// TODO(eroman): Add a maximum number of in-flight jobs/requests.
// TODO(eroman): Add NetLog integration.

namespace cert_verifier {

namespace {

// NOTE: This code uses the SimpleURLLoader interface, so the maximum response
// sizes must be smaller than the limits imposed on
// SimpleURLLoader::DownloadToString.

// The maximum size in bytes for the response body when fetching a CRL.
const int kMaxResponseSizeInBytesForCrl =;

// The maximum size in bytes for the response body when fetching an AIA URL
// (caIssuers/OCSP).
const int kMaxResponseSizeInBytesForAia =;

// The default timeout in seconds for fetch requests.
const int kTimeoutSeconds =;

class Job;

struct JobToRequestParamsComparator;

struct JobComparator {};

// Would be a set<unique_ptr> but extraction of owned objects from a set of
// owned types doesn't come until C++17.
JobSet;

BindNewURLLoaderFactoryCallback;

}  // namespace

// AsyncCertNetFetcherURLLoader manages URLLoaders in an async fashion on the
// creation thread.
//
//  * Schedules
//  * De-duplicates requests
class CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader {};

namespace {

// Policy for which URLs are allowed to be fetched. This is called both for the
// initial URL and for each redirect. Returns OK on success or a net error
// code on failure.
net::Error CanFetchUrl(const GURL& url) {}

base::TimeDelta GetTimeout(int timeout_milliseconds) {}

size_t GetMaxResponseBytes(int max_response_bytes,
                           size_t default_max_response_bytes) {}

enum HttpMethod {};

}  // namespace

// RequestCore tracks an outstanding call to Fetch(). It is
// reference-counted for ease of sharing between threads.
class CertNetFetcherURLLoader::RequestCore
    : public base::RefCountedThreadSafe<RequestCore> {};

struct CertNetFetcherURLLoader::RequestParams {};

CertNetFetcherURLLoader::RequestParams::RequestParams()
    :{}

bool CertNetFetcherURLLoader::RequestParams::operator<(
    const RequestParams& other) const {}

namespace {

// Job tracks an outstanding URLLoader as well as all of the pending requests
// for it.
class Job {};

}  // namespace

void CertNetFetcherURLLoader::RequestCore::SignalImmediateError() {}

void CertNetFetcherURLLoader::RequestCore::CancelJob() {}

void CertNetFetcherURLLoader::RequestCore::CancelJobOnTaskRunner() {}

namespace {

Job::Job(std::unique_ptr<CertNetFetcherURLLoader::RequestParams> request_params,
         CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader* parent)
    :{}

Job::~Job() {}

void Job::AttachRequest(
    scoped_refptr<CertNetFetcherURLLoader::RequestCore> request) {}

void Job::DetachRequest(CertNetFetcherURLLoader::RequestCore* request) {}

void Job::StartURLLoader(network::mojom::URLLoaderFactory* factory) {}

void Job::Cancel() {}

void Job::OnReceivedRedirect(
    const GURL& url_before_redirect,
    const net::RedirectInfo& redirect_info,
    const network::mojom::URLResponseHead& response_head,
    std::vector<std::string>* removed_headers) {}

void Job::OnResponseStarted(
    const GURL& final_url,
    const network::mojom::URLResponseHead& response_head) {}

void Job::OnUrlLoaderCompleted(std::unique_ptr<std::string> response_body) {}

void Job::OnJobCompleted(net::Error error,
                         std::unique_ptr<std::string> response_body) {}

void Job::CompleteAndClearRequests(net::Error error,
                                   std::unique_ptr<std::string> response_body) {}

void Job::FailRequest(net::Error error) {}

}  // namespace

CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
    AsyncCertNetFetcherURLLoader(
        mojo::PendingRemote<network::mojom::URLLoaderFactory>
            factory_pending_remote,
        BindNewURLLoaderFactoryCallback bind_new_url_loader_factory_cb)
    :{}

CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
    ~AsyncCertNetFetcherURLLoader() {}

void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
    DisconnectURLLoaderFactoryForTesting() {}

bool JobComparator::operator()(const Job* job1, const Job* job2) const {}

void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::Fetch(
    std::unique_ptr<RequestParams> request_params,
    scoped_refptr<RequestCore> request) {}

void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::Shutdown() {}

void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
    RebindURLLoaderFactory() {}

namespace {

struct JobToRequestParamsComparator {};

}  // namespace

Job* CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::FindJob(
    const RequestParams& params) {}

std::unique_ptr<Job>
CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::RemoveJob(Job* job) {}

namespace {

class CertNetFetcherRequestImpl : public net::CertNetFetcher::Request {};

}  // namespace

CertNetFetcherURLLoader::CertNetFetcherURLLoader()
    :{}

CertNetFetcherURLLoader::~CertNetFetcherURLLoader() = default;

void CertNetFetcherURLLoader::SetURLLoaderFactoryAndReconnector(
    mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
    base::RepeatingCallback<
        void(mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
        bind_new_url_loader_factory_cb) {}

// static
base::TimeDelta CertNetFetcherURLLoader::GetDefaultTimeoutForTesting() {}

void CertNetFetcherURLLoader::DisconnectURLLoaderFactoryForTesting() {}

void CertNetFetcherURLLoader::Shutdown() {}

std::unique_ptr<net::CertNetFetcher::Request>
CertNetFetcherURLLoader::FetchCaIssuers(const GURL& url,
                                        int timeout_milliseconds,
                                        int max_response_bytes) {}

std::unique_ptr<net::CertNetFetcher::Request> CertNetFetcherURLLoader::FetchCrl(
    const GURL& url,
    int timeout_milliseconds,
    int max_response_bytes) {}

std::unique_ptr<net::CertNetFetcher::Request>
CertNetFetcherURLLoader::FetchOcsp(const GURL& url,
                                   int timeout_milliseconds,
                                   int max_response_bytes) {}

void CertNetFetcherURLLoader::DoFetchOnTaskRunner(
    std::unique_ptr<RequestParams> request_params,
    scoped_refptr<RequestCore> request) {}

std::unique_ptr<CertNetFetcherURLLoader::Request>
CertNetFetcherURLLoader::DoFetch(
    std::unique_ptr<RequestParams> request_params) {}

}  // namespace cert_verifier