File: blob_url_registry.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (184 lines) | stat: -rw-r--r-- 8,079 bytes parent folder | download | duplicates (5)
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef STORAGE_BROWSER_BLOB_BLOB_URL_REGISTRY_H_
#define STORAGE_BROWSER_BLOB_BLOB_URL_REGISTRY_H_

#include <map>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/sequence_checker.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_associated_receiver_set.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "net/base/schemeful_site.h"
#include "storage/browser/blob/blob_storage_constants.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"

class GURL;

namespace storage {

// This class stores the mapping of blob Urls to blobs.
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobUrlRegistry {
 public:
  explicit BlobUrlRegistry(base::WeakPtr<BlobUrlRegistry> fallback = nullptr);

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

  ~BlobUrlRegistry();

  enum class MappingStatus {
    kIsMapped,
    // This refers to a third-party context attempting to access a Blob URL
    // created in a first-party context.
    kNotMappedCrossPartitionSameOriginAccessFirstPartyBlobURL,
    // This refers to either a first-party or different third-party context
    // attempting to access a Blob URL created in a third-party context.
    kNotMappedCrossPartitionSameOriginAccessThirdPartyBlobURL,
    kNotMappedOther
  };

  // Binds receivers corresponding to connections from renderer frame
  // contexts and stores them in `frame_receivers_`.
  // `partitioning_blob_url_closure` runs when the storage_key check fails
  // in `BlobURLStoreImpl::ResolveAsURLLoaderFactory` and increments the use
  // counter.
  void AddReceiver(
      const blink::StorageKey& storage_key,
      const url::Origin& renderer_origin,
      int render_process_host_id,
      mojo::PendingAssociatedReceiver<blink::mojom::BlobURLStore> receiver,
      base::RepeatingCallback<
          void(const GURL&,
               std::optional<blink::mojom::PartitioningBlobURLInfo>)>
          partitioning_blob_url_closure,
      base::RepeatingCallback<bool()> storage_access_check_callback,
      bool partitioning_disabled_by_policy = false);

  // Binds receivers corresponding to connections from renderer worker
  // contexts and stores them in `worker_receivers_`.
  void AddReceiver(
      const blink::StorageKey& storage_key,
      const url::Origin& renderer_origin,
      int render_process_host_id,
      mojo::PendingReceiver<blink::mojom::BlobURLStore> receiver,
      base::RepeatingCallback<bool()> storage_access_check_callback =
          base::BindRepeating([]() -> bool { return false; }),
      bool partitioning_disabled_by_policy = false,
      BlobURLValidityCheckBehavior validity_check_behavior =
          BlobURLValidityCheckBehavior::DEFAULT);

  // Returns the receivers corresponding to renderer frame contexts for use in
  // tests.
  auto& receivers_for_testing() { return frame_receivers_; }

  // Creates a URL mapping from blob to the given URL. Returns false if
  // there already is a map for the URL. The URL mapping will be associated with
  // the `storage_key`, and most subsequent URL lookup attempts will require a
  // matching StorageKey to succeed. `origin` is the origin of the Blob URL, and
  // `render_process_host_id` is the ID of the process where the blob URL
  // registration comes from.
  bool AddUrlMapping(
      const GURL& url,
      mojo::PendingRemote<blink::mojom::Blob> blob,
      const blink::StorageKey& storage_key,
      const url::Origin& renderer_origin,
      int render_process_host_id,
      // TODO(crbug.com/40775506): Remove these once experiment is over.
      const base::UnguessableToken& unsafe_agent_cluster_id,
      const std::optional<net::SchemefulSite>& unsafe_top_level_site);

  // Removes the given URL mapping associated with `storage_key`. Returns false
  // if the URL wasn't mapped.
  bool RemoveUrlMapping(const GURL& url, const blink::StorageKey& storage_key);

  // Returns whether the URL is mapped to a blob and whether the URL is
  // associated with `storage_key`.
  MappingStatus IsUrlMapped(const GURL& blob_url,
                            const blink::StorageKey& storage_key) const;

  // TODO(crbug.com/40775506): Remove this once experiment is over.
  std::optional<base::UnguessableToken> GetUnsafeAgentClusterID(
      const GURL& blob_url) const;
  std::optional<net::SchemefulSite> GetUnsafeTopLevelSite(
      const GURL& blob_url) const;

  // Returns the blob from the given url. Returns a null remote if the mapping
  // doesn't exist.
  mojo::PendingRemote<blink::mojom::Blob> GetBlobFromUrl(const GURL& url);

  size_t url_count() const { return url_to_blob_.size(); }

  void AddTokenMapping(const base::UnguessableToken& token,
                       const GURL& url,
                       mojo::PendingRemote<blink::mojom::Blob> blob);
  void RemoveTokenMapping(const base::UnguessableToken& token);
  bool GetTokenMapping(const base::UnguessableToken& token,
                       GURL* url,
                       mojo::PendingRemote<blink::mojom::Blob>* blob);

  // Returns the origin for a Blob URL navigation to `url`, given the precursor
  // origin and target process information.
  url::Origin GetOriginForNavigation(
      const GURL& url,
      const url::Origin& precursor_origin,
      std::optional<int> target_render_process_host_id);

  // Support adding a handler to be run when AddReceiver is called. This allows
  // browser tests to intercept incoming BlobURLStore connections and swap in
  // arbitrary BlobURLs to ensure that attempting to register certain blobs
  // causes the renderer to be terminated.
  using URLStoreCreationHook =
      base::RepeatingCallback<void(BlobUrlRegistry*, mojo::ReceiverId)>;
  static void SetURLStoreCreationHookForTesting(URLStoreCreationHook* hook);

  base::WeakPtr<BlobUrlRegistry> AsWeakPtr() {
    return weak_ptr_factory_.GetWeakPtr();
  }

 private:
  SEQUENCE_CHECKER(sequence_checker_);

  // Optional fallback BlobUrlRegistry. If lookups for URLs in this registry
  // fail, they are retried in the fallback registry. This is used to allow
  // "child" storage partitions to resolve URLs created by their "parent", while
  // not allowing the reverse.
  base::WeakPtr<BlobUrlRegistry> fallback_;

  std::map<GURL, mojo::PendingRemote<blink::mojom::Blob>> url_to_blob_;
  // TODO(crbug.com/40775506): Remove this once experiment is over.
  std::map<GURL, base::UnguessableToken> url_to_unsafe_agent_cluster_id_;
  std::map<GURL, net::SchemefulSite> url_to_unsafe_top_level_site_;
  std::map<base::UnguessableToken,
           std::pair<GURL, mojo::PendingRemote<blink::mojom::Blob>>>
      token_to_url_and_blob_;

  std::map<GURL, blink::StorageKey> url_to_storage_key_;
  std::map<GURL, url::Origin> url_to_origin_;
  std::map<GURL, int> url_to_render_process_host_id_;

  // When the renderer uses the BlobUrlRegistry from a frame context or from a
  // main thread worklet context, a navigation-associated interface is used to
  // preserve message ordering. The receiver corresponding to that connection is
  // an AssociatedReceiver and gets stored in `frame_receivers_`. For workers
  // and threaded worklets, the receiver is a Receiver and gets stored in
  // `worker_receivers_`.
  mojo::UniqueAssociatedReceiverSet<blink::mojom::BlobURLStore>
      frame_receivers_;
  mojo::UniqueReceiverSet<blink::mojom::BlobURLStore> worker_receivers_;

  base::WeakPtrFactory<BlobUrlRegistry> weak_ptr_factory_{this};
};

}  // namespace storage

#endif  // STORAGE_BROWSER_BLOB_BLOB_URL_REGISTRY_H_