File: idb_request_queue_item.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (228 lines) | stat: -rw-r--r-- 8,957 bytes parent folder | download | duplicates (6)
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
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_REQUEST_QUEUE_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_REQUEST_QUEUE_ITEM_H_

#include <memory>

#include "base/dcheck_is_on.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_record_array.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

class DOMException;
class IDBDatabaseGetAllResultSinkImpl;
class IDBKey;
class IDBRequest;
class IDBRequestLoader;
class IDBRequestTest;
class IDBValue;

// Queues up a transaction's IDBRequest results for orderly delivery.
//
// The IndexedDB specification requires that the events corresponding to IDB
// request results fire in the order in which the requests were issued. The
// browser-side backend processes requests in order, but the Blink side may need
// to perform post-processing on the results (e.g. large value unwrapping).
// When a result needs post-processing, this queue captures all results received
// during the post-processing steps. The events for these results may only fire
// after the post-processed result's event is fired.
//
// A queue item holds a Persistent (not garbage-collected) reference to the
// IDBRequest whose result it will deliver. This creates a reference cycle,
// because IDBRequest holds a pointer to its IDBTransaction, and IDBTransaction
// stores all pending IDBRequestQueueItem instances for its requests in a queue
// via non-garbage-collected pointers (std::unique_ptr). To avoid leaks, the
// request-processing code must ensure that IDBTransaction's queue gets drained
// at some point, even if the transaction's ExecutionContext goes away. The
// lifecycle tests in IDBTransactionTest aim to cover this requirement.
//
// Given that the cycle above exists, the closures passed to IDBRequestQueueItem
// can safely store Persistent pointers the IDBRequest or to the IDBTransaction.
class MODULES_EXPORT IDBRequestQueueItem {
  USING_FAST_MALLOC(IDBRequestQueueItem);

 public:
  IDBRequestQueueItem(IDBRequest*,
                      DOMException*,
                      base::OnceClosure on_result_ready);
  IDBRequestQueueItem(IDBRequest*, int64_t, base::OnceClosure on_result_ready);
  IDBRequestQueueItem(IDBRequest*, base::OnceClosure on_result_ready);
  IDBRequestQueueItem(IDBRequest*,
                      std::unique_ptr<IDBKey>,
                      base::OnceClosure on_result_ready);
  IDBRequestQueueItem(IDBRequest*,
                      std::unique_ptr<IDBValue>,
                      base::OnceClosure on_load_complete);
  IDBRequestQueueItem(IDBRequest*,
                      std::unique_ptr<IDBKey>,
                      std::unique_ptr<IDBKey> primary_key,
                      std::unique_ptr<IDBValue>,
                      base::OnceClosure on_result_ready);
  IDBRequestQueueItem(
      IDBRequest*,
      mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> pending_cursor,
      std::unique_ptr<IDBKey>,
      std::unique_ptr<IDBKey> primary_key,
      std::unique_ptr<IDBValue>,
      base::OnceClosure on_result_ready);
  // Asynchronous fetching of multiple results.
  IDBRequestQueueItem(
      IDBRequest*,
      mojom::blink::IDBGetAllResultType get_all_result_type,
      mojo::PendingAssociatedReceiver<mojom::blink::IDBDatabaseGetAllResultSink>
          receiver,
      base::OnceClosure on_result_ready);

  ~IDBRequestQueueItem();

  // False if this result still requires post-processing.
  inline bool IsReady() { return ready_; }

  // The request whose queued result is tracked by this item.
  inline IDBRequest* Request() { return request_; }

  // Starts post-processing the IDBRequest's result.
  //
  // This method must be called after the IDBRequestQueueItem is enqueued into
  // the appropriate queue, because it is possible for the loading operation to
  // complete synchronously, in which case IDBTransaction::OnResultReady() will
  // be called with the (presumably) enqueued IDBRequest before this method
  // returns.
  void StartLoading();

  // Stops post-processing the IDBRequest's result.
  //
  // This method may be called without an associated StartLoading().
  void CancelLoading();

  // Calls the correct SendResult overload on the associated request.
  //
  // This should only be called by the request's IDBTransaction.
  void SendResult();

 private:
  friend class IDBDatabaseGetAllResultSinkImpl;
  friend class IDBRequestTest;

  // The IDBRequest callback that will be called for this result.
  enum ResponseType {
    kCanceled,
    kCursorKeyPrimaryKeyValue,
    kError,
    kNumber,
    kKey,
    kKeyArray,
    kKeyPrimaryKeyValue,
    kRecordArray,
    kValue,
    kValueArray,
    kVoid,
  };

  // Checks `values_` for wrapped entries and, if there are any, creates
  // `loader_` to unwrap them. Returns whether the loader was created.
  // Note that `values_` is std::move'd into the loader when it's created.
  bool MaybeCreateLoader();

  // Callback run from IDBRequestLoader with the unwrapped values.
  void OnLoadComplete(Vector<std::unique_ptr<IDBValue>>&& values,
                      DOMException* error);

  // Handle completion of post-processing, if any, of the result.
  void OnResultReady();

  // The IDBRequest that will receive a callback for this result.
  Persistent<IDBRequest> request_;

  // The error argument to the IDBRequest callback.
  //
  // Only used if the `response_type_` is `kError`.
  Persistent<DOMException> error_;

  // The key argument to the IDBRequest callback.
  //
  // Only used if `response_type_` is `kKey`, `kKeyPrimaryKeyValue` or
  // `kCursorKeyPrimaryKeyValue`.
  std::unique_ptr<IDBKey> key_;

  // The primary_key argument to the IDBRequest callback.
  //
  // Only used if `response_type_` is `kKeyPrimaryKeyValue` or
  // `kCursorKeyPrimaryKeyValue`.
  std::unique_ptr<IDBKey> primary_key_;

  // Contains 3 vectors: 1 for primary keys, 1 for values and 1 for index keys.
  // Several kinds of `response_type_` use 1 or more of these vectors:
  //
  // (1) `kValue`, `kKeyPrimaryKeyValue` and `kCursorKeyPrimaryKeyValue` store
  //     a single value in `records_.values`:
  //
  // (2) `kKeyArray` stores keys in `records_.primary_keys` for `getAllKeys()`.
  //
  // (3) `kValueArray` stores values in `records_.values` for `getAll()`.
  //
  // (4) `kRecordArray` stores primary keys, index keys and values in
  //     `records_` for `getAllRecords()`.  The vectors are parallel.
  //     `IDBObject::getAllRecords()` leaves `records_.index_keys` empty.
  IDBRecordArray records_;

  // The cursor argument to the IDBRequest callback.
  mojo::PendingAssociatedRemote<mojom::blink::IDBCursor> pending_cursor_;

  // Asynchronous result collection for get all.
  std::unique_ptr<IDBDatabaseGetAllResultSinkImpl> get_all_sink_;

  // Performs post-processing on this result.
  //
  // nullptr for results that do not require post-processing and for results
  // whose post-processing has completed.
  Persistent<IDBRequestLoader> loader_;

  // Called when result post-processing has completed.
  base::OnceClosure on_result_ready_;

  // The integer value argument to the IDBRequest callback.
  int64_t int64_value_;

  // Identifies the IDBRequest::SendResult() overload that will be called.
  ResponseType response_type_;

  // This always starts as false. Call `StartLoading()` to begin loading and
  // post-processing. If none is required, `ready_` will be set to true and
  // `on_result_ready_` will be fired immediately.
  bool ready_ = false;

  // True iff this result has started loading.
  bool started_loading_ = false;

#if DCHECK_IS_ON()
  // True if the appropriate `SendResult()` method was called in `IDBRequest`.
  //
  // If `CancelLoading()` is called, `response_type_` might be `kCanceled`. In
  // this case, `result_sent_` can be set to true even though no
  // `IDBRequest::SendResult()` call occurs.
  bool result_sent_ = false;
#endif  // DCHECK_IS_ON()

  // A WeakPtr to this class is passed in the callback to IDBRequestLoader for
  // correctness and future-proofing. There is no known case currently where
  // the callback is dispatched after we're destroyed.
  base::WeakPtrFactory<IDBRequestQueueItem> weak_factory_{this};
};

using IDBRequestQueue = Deque<std::unique_ptr<IDBRequestQueueItem>>;

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_REQUEST_QUEUE_ITEM_H_