1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137

content / browser / loader / subresource_proxying_url_loader_service.h [blame]

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

#ifndef CONTENT_BROWSER_LOADER_SUBRESOURCE_PROXYING_URL_LOADER_SERVICE_H_
#define CONTENT_BROWSER_LOADER_SUBRESOURCE_PROXYING_URL_LOADER_SERVICE_H_

#include <string>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/frame_tree_node_id.h"
#include "content/public/browser/weak_document_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "net/base/isolation_info.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"

namespace content {

class BrowserContext;
class PrefetchedSignedExchangeCache;
class PrefetchURLLoaderServiceContext;
class RenderFrameHostImpl;

// A URLLoaderFactory that can be passed to a renderer to intercept subresource
// requests.
//
// The renderer uses it for:
// - Prefetch requests including <link rel="prefetch">
// - Topics requests including fetch(<url>, {browsingTopics: true})
class CONTENT_EXPORT SubresourceProxyingURLLoaderService final
    : public network::mojom::URLLoaderFactory {
 public:
  struct CONTENT_EXPORT BindContext : public base::RefCounted<BindContext> {
    // `factory` is a clone of the default factory bundle for document
    // subresource requests.
    BindContext(FrameTreeNodeId frame_tree_node_id,
                scoped_refptr<network::SharedURLLoaderFactory> factory,
                base::WeakPtr<RenderFrameHostImpl> render_frame_host,
                scoped_refptr<PrefetchedSignedExchangeCache>
                    prefetched_signed_exchange_cache);

    // Set `document` to `committed_document`.
    void OnDidCommitNavigation(WeakDocumentPtr committed_document);

    const FrameTreeNodeId frame_tree_node_id;
    scoped_refptr<network::SharedURLLoaderFactory> factory;
    base::WeakPtr<RenderFrameHostImpl> render_frame_host;

    // This member is lazily initialized by EnsureCrossOriginFactory().
    scoped_refptr<network::SharedURLLoaderFactory> cross_origin_factory;

    scoped_refptr<PrefetchedSignedExchangeCache>
        prefetched_signed_exchange_cache;

    // This maps recursive prefetch tokens to IsolationInfos that they should be
    // fetched with.
    std::map<base::UnguessableToken, net::IsolationInfo>
        prefetch_isolation_infos;

    // Upon NavigationRequest::DidCommitNavigation(), `document` will be set to
    // the document that this `BindContext` is associated with. It will become
    // null whenever the document navigates away.
    WeakDocumentPtr document;

    // This must be the last member.
    base::WeakPtrFactory<SubresourceProxyingURLLoaderService::BindContext>
        weak_ptr_factory{this};

   private:
    ~BindContext();
    friend class base::RefCounted<BindContext>;
  };

  explicit SubresourceProxyingURLLoaderService(BrowserContext* browser_context);
  ~SubresourceProxyingURLLoaderService() override;

  SubresourceProxyingURLLoaderService(
      const SubresourceProxyingURLLoaderService&) = delete;
  SubresourceProxyingURLLoaderService& operator=(
      const SubresourceProxyingURLLoaderService&) = delete;

  base::WeakPtr<BindContext> GetFactory(
      mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
      FrameTreeNodeId frame_tree_node_id,
      scoped_refptr<network::SharedURLLoaderFactory>
          subresource_proxying_factory_bundle,
      base::WeakPtr<RenderFrameHostImpl> render_frame_host,
      scoped_refptr<PrefetchedSignedExchangeCache>
          prefetched_signed_exchange_cache);

  PrefetchURLLoaderServiceContext&
  prefetch_url_loader_service_context_for_testing() {
    return *prefetch_url_loader_service_context_;
  }

 private:
  // network::mojom::URLLoaderFactory:
  void CreateLoaderAndStart(
      mojo::PendingReceiver<network::mojom::URLLoader> receiver,
      int32_t request_id,
      uint32_t options,
      const network::ResourceRequest& resource_request_in,
      mojo::PendingRemote<network::mojom::URLLoaderClient> client,
      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
      override;
  void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
      override;

  void CreateSubresourceProxyingLoaderAndStart(
      mojo::PendingReceiver<network::mojom::URLLoader> receiver,
      int32_t request_id,
      uint32_t options,
      const network::ResourceRequest& resource_request_in,
      mojo::PendingRemote<network::mojom::URLLoaderClient> client,
      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);

  mojo::ReceiverSet<network::mojom::URLLoaderFactory,
                    scoped_refptr<BindContext>>
      loader_factory_receivers_;

  mojo::ReceiverSet<network::mojom::URLLoader,
                    std::unique_ptr<network::mojom::URLLoader>>
      subresource_proxying_loader_receivers_;

  std::unique_ptr<PrefetchURLLoaderServiceContext>
      prefetch_url_loader_service_context_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_LOADER_SUBRESOURCE_PROXYING_URL_LOADER_SERVICE_H_