File: blob_storage_context.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 (270 lines) | stat: -rw-r--r-- 11,261 bytes parent folder | download | duplicates (9)
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
// Copyright 2013 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_STORAGE_CONTEXT_H_
#define STORAGE_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/trace_event/memory_dump_provider.h"
#include "components/services/storage/public/mojom/blob_storage_context.mojom.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 "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_entry.h"
#include "storage/browser/blob/blob_memory_controller.h"
#include "storage/browser/blob/blob_storage_constants.h"
#include "storage/browser/blob/blob_storage_registry.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"

namespace content {

class ChromeBlobStorageContext;

namespace indexed_db_backing_store_unittest {
class BlobStorageContextShim;
}  // namespace indexed_db_backing_store_unittest

}  // namespace content

namespace storage {

class BlobDataBuilder;
class BlobDataHandle;
class BlobDataSnapshot;
class ShareableBlobDataItem;

// This class handles the logistics of blob storage within the browser process.
// This class is not threadsafe, access on IO thread. In Chromium there is one
// instance per profile.
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobStorageContext
    : public base::trace_event::MemoryDumpProvider,
      public mojom::BlobStorageContext {
 public:
  using TransportAllowedCallback = BlobEntry::TransportAllowedCallback;
  using BuildAbortedCallback = BlobEntry::BuildAbortedCallback;

  // Initializes the context without disk support.
  BlobStorageContext();
  // Disk support is enabled if |file_runner| isn't null.
  BlobStorageContext(const base::FilePath& profile_directory,
                     const base::FilePath& blob_storage_directory,
                     scoped_refptr<base::TaskRunner> file_runner);

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

  ~BlobStorageContext() override;

  // The following three methods all lookup a BlobDataHandle based on some
  // input. If no blob matching the input exists these methods return null.
  std::unique_ptr<BlobDataHandle> GetBlobDataFromUUID(const std::string& uuid);
  // If this BlobStorageContext is deleted before this method finishes, the
  // callback will still be called with null.
  void GetBlobDataFromBlobRemote(
      mojo::PendingRemote<blink::mojom::Blob> blob,
      base::OnceCallback<void(std::unique_ptr<BlobDataHandle>)> callback);

  // Always returns a handle to a blob. Use BlobStatus::GetBlobStatus() and
  // BlobStatus::RunOnConstructionComplete(callback) to determine construction
  // completion and possible errors.
  std::unique_ptr<BlobDataHandle> AddFinishedBlob(
      std::unique_ptr<BlobDataBuilder> builder);

  std::unique_ptr<BlobDataHandle> AddFinishedBlob(
      const std::string& uuid,
      const std::string& content_type,
      const std::string& content_disposition,
      std::vector<scoped_refptr<ShareableBlobDataItem>> items);

  std::unique_ptr<BlobDataHandle> AddBrokenBlob(
      const std::string& uuid,
      const std::string& content_type,
      const std::string& content_disposition,
      BlobStatus reason);

  size_t blob_count() const { return registry_.blob_count(); }

  const BlobStorageRegistry& registry() { return registry_; }

  // This builds a blob with the given |input_builder| and returns a handle to
  // the constructed Blob. Blob metadata and data should be accessed through
  // this handle.
  // If there is data present that needs further population then we will call
  // |transport_allowed_callback| when we're ready for the user data to be
  // populated with the PENDING_DATA_POPULATION status. This can happen
  // synchronously or asynchronously. Otherwise |transport_allowed_callback|
  // should be null. In the further population case, the caller must call either
  // NotifyTransportComplete or CancelBuildingBlob after
  // |transport_allowed_callback| is called to signify the data is finished
  // populating or an error occurred (respectively).
  // If the returned handle is broken, then the possible error cases are:
  // * OUT_OF_MEMORY if we don't have enough memory to store the blob,
  // * REFERENCED_BLOB_BROKEN if a referenced blob is broken or we're
  //   referencing ourself.
  std::unique_ptr<BlobDataHandle> BuildBlob(
      std::unique_ptr<BlobDataBuilder> input_builder,
      TransportAllowedCallback transport_allowed_callback);

  // Similar to BuildBlob, but this merely registers a blob that will be built
  // in the future. The caller must later call either BuildPreregisteredBlob
  // (to actually start building the blob), or CancelBuildingBlob (if an error
  // occured).
  // The returned BlobDataHandle (as well as any handles returned by
  // GetBlobDataFromUUID before BuildPreregisteredBlob is called) will always
  // have kUnknownSize for its size. A BlobDataHandle with the correct size is
  // later returned by BuildPreregisteredBlob.
  std::unique_ptr<BlobDataHandle> AddFutureBlob(
      const std::string& uuid,
      const std::string& content_type,
      const std::string& content_disposition,
      BuildAbortedCallback build_aborted_callback);

  // Same as BuildBlob, but for a blob that was previously registered by calling
  // AddFutureBlob.
  std::unique_ptr<BlobDataHandle> BuildPreregisteredBlob(
      std::unique_ptr<BlobDataBuilder> input_builder,
      TransportAllowedCallback transport_allowed_callback);

  // This breaks a blob that is currently being built by using the BuildBlob
  // method above. Any callbacks waiting on this blob, including the
  // |transport_allowed_callback| callback given to BuildBlob, will be called
  // with this status code.
  void CancelBuildingBlob(const std::string& uuid, BlobStatus code);

  // After calling BuildBlob above, the caller should call this method to
  // notify the construction system that the unpopulated data in the given blob
  // has been. populated. Caller must have all pending items populated in the
  // original builder |input_builder| given in BuildBlob or we'll check-fail.
  // If there is no pending data in the |input_builder| for the BuildBlob call,
  // then this method doesn't need to be called.
  void NotifyTransportComplete(const std::string& uuid);

  const BlobMemoryController& memory_controller() { return memory_controller_; }

  base::WeakPtr<BlobStorageContext> AsWeakPtr() {
    return ptr_factory_.GetWeakPtr();
  }

  void Bind(mojo::PendingReceiver<mojom::BlobStorageContext> receiver);

  void set_limits_for_testing(const BlobStorageLimits& limits) {
    mutable_memory_controller()->set_limits_for_testing(limits);
  }

  void DisableFilePagingForTesting() {
    mutable_memory_controller()->DisableFilePaging(base::File::FILE_OK);
  }

 protected:
  friend class content::ChromeBlobStorageContext;
  friend class BlobBuilderFromStream;
  friend class BlobDataHandle;
  friend class BlobDataHandle::BlobDataHandleShared;
  friend class BlobRegistryImplTest;
  friend class BlobStorageContextTest;
  friend class BlobURLTokenImpl;
  friend class content::indexed_db_backing_store_unittest::
      BlobStorageContextShim;

  enum class TransportQuotaType { MEMORY, FILE };

  void IncrementBlobRefCount(const std::string& uuid);
  void DecrementBlobRefCount(const std::string& uuid);

  // This will return an empty snapshot until the blob is complete.
  // TODO(dmurph): After we make the snapshot method in BlobHandle private, then
  // make this DCHECK on the blob not being complete.
  std::unique_ptr<BlobDataSnapshot> CreateSnapshot(const std::string& uuid);

  BlobStatus GetBlobStatus(const std::string& uuid) const;

  // Runs |done| when construction completes with the final status of the blob.
  void RunOnConstructionComplete(const std::string& uuid,
                                 BlobStatusCallback done_callback);

  // Runs |done| when construction begins (when the blob is no longer
  // PENDING_CONSTRUCTION) with the new status of the blob.
  void RunOnConstructionBegin(const std::string& uuid,
                              BlobStatusCallback done_callback);

  BlobStorageRegistry* mutable_registry() { return &registry_; }

  BlobMemoryController* mutable_memory_controller() {
    return &memory_controller_;
  }

 private:
  std::unique_ptr<BlobDataHandle> BuildBlobInternal(
      BlobEntry* entry,
      std::unique_ptr<BlobDataBuilder> input_builder,
      TransportAllowedCallback transport_allowed_callback);

  std::unique_ptr<BlobDataHandle> CreateHandle(const std::string& uuid,
                                               BlobEntry* entry);

  void NotifyTransportCompleteInternal(BlobEntry* entry);

  void CancelBuildingBlobInternal(BlobEntry* entry, BlobStatus reason);

  void FinishBuilding(BlobEntry* entry);

  void RequestTransport(
      BlobEntry* entry,
      std::vector<BlobMemoryController::FileCreationInfo> files);

  // The files array is empty for memory quota request responses.
  void OnEnoughSpaceForTransport(
      const std::string& uuid,
      std::vector<BlobMemoryController::FileCreationInfo> files,
      bool can_fit);

  void OnEnoughSpaceForCopies(const std::string& uuid, bool can_fit);

  void OnDependentBlobFinished(const std::string& owning_blob_uuid,
                               BlobStatus reason);

  void ClearAndFreeMemory(BlobEntry* entry);

  // base::trace_event::MemoryDumpProvider implementation.
  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                    base::trace_event::ProcessMemoryDump* pmd) override;

  // mojom::BlobStorageContext implementation.
  void RegisterFromDataItem(mojo::PendingReceiver<blink::mojom::Blob> blob,
                            const std::string& uuid,
                            mojom::BlobDataItemPtr item) override;
  void RegisterFromMemory(mojo::PendingReceiver<::blink::mojom::Blob> blob,
                          const std::string& uuid,
                          mojo_base::BigBuffer data) override;
  void WriteBlobToFile(mojo::PendingRemote<::blink::mojom::Blob> blob,
                       const base::FilePath& path,
                       bool flush_on_write,
                       std::optional<base::Time> last_modified,
                       WriteBlobToFileCallback callback) override;
  void Clone(mojo::PendingReceiver<mojom::BlobStorageContext> cloned) override;

  base::FilePath profile_directory_;
  BlobStorageRegistry registry_;
  BlobMemoryController memory_controller_;
  mojo::ReceiverSet<mojom::BlobStorageContext> receivers_;
  base::WeakPtrFactory<BlobStorageContext> ptr_factory_{this};
};

}  // namespace storage

#endif  // STORAGE_BROWSER_BLOB_BLOB_STORAGE_CONTEXT_H_