chromium/services/network/public/cpp/url_loader_factory_builder.h

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SERVICES_NETWORK_PUBLIC_CPP_URL_LOADER_FACTORY_BUILDER_H_
#define SERVICES_NETWORK_PUBLIC_CPP_URL_LOADER_FACTORY_BUILDER_H_

#include <tuple>

#include "base/component_export.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/network_context.mojom.h"

namespace network {

// URLLoaderFactoryBuilder allows to build a URLLoaderFactory where requests
// go through interceptors/proxying URLLoaderFactories and finally processed by
// the terminal URLLoaderFactory.
// A request received by the resulting factory will be processed by the
// interceptors (in the order of `Append()` calls), and then finally passed to
// the terminal (given by `terminal_args` of `Finish*()` methods).
//
// URLLoaderFactoryBuilder connects pipes and URLLoaderFactories eagerly, and
// tries to minimize additional intermediate objects between them.
//
// Basic Usage:
//
//   // Start with no interceptors.
//   URLLoaderFactoryBuilder factory_builder;
//
//   // Add Interceptor 1.
//   mojo::PendingReceiver<mojom::URLLoaderFactory> receiver1;
//   mojo::PendingRemote<mojom::URLLoaderFactory> remote1;
//   std::tie(receiver1, remote1) = factory_builder.Append();
//   ...; // Connect the pipes so that the interceptor handles incoming requests
//        // from `receiver1` and forwards processed requests to `remote1`.
//
//   // Add Interceptor 2.
//   auto [receiver2, remote2] = factory_builder.Append();
//   ...; // Connect the pipes as well.
//
//   // Finish the builder by connecting to the terminal URLLoaderFactory,
//   // getting the resulting URLLoaderFactory.
//   // `result->CreateLoaderAndStart()` will go through Interceptor 1,
//   // Interceptor 2 (in the order of `Append()` calls) then `terminal`.
//   scoped_refptr<SharedURLLoaderFactory> terminal = ...;
//   scoped_refptr<SharedURLLoaderFactory> result =
//       std::move(factory_builder).Finish(std::move(terminal));
//
// See `url_loader_factory_builder_unittest.cc` for more concrete examples.
class COMPONENT_EXPORT(NETWORK_CPP) URLLoaderFactoryBuilder final {};

// `PendingRemote` -> `SharedURLLoaderFactory`:
// Wraps by `WrapperSharedURLLoaderFactory`.
template <>
COMPONENT_EXPORT(NETWORK_CPP)
scoped_refptr<SharedURLLoaderFactory> URLLoaderFactoryBuilder::WrapAs(
    mojo::PendingRemote<mojom::URLLoaderFactory> in);

// `SharedURLLoaderFactory` -> `PendingRemote`:
// Creates a new pipe and cloning.
template <>
COMPONENT_EXPORT(NETWORK_CPP)
mojo::PendingRemote<mojom::URLLoaderFactory> URLLoaderFactoryBuilder::WrapAs(
    scoped_refptr<SharedURLLoaderFactory> in);

// Similar to PendingSharedURLLoaderFactory, but also goes through
// `URLLoaderFactoryBuilder` when constructing the factory.
class COMPONENT_EXPORT(NETWORK_CPP)
    PendingSharedURLLoaderFactoryWithBuilder final
    : public PendingSharedURLLoaderFactory {};

}  // namespace network

#endif  // SERVICES_NETWORK_PUBLIC_CPP_URL_LOADER_FACTORY_BUILDER_H_