Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Unified Diff: third_party/WebKit/Source/modules/indexeddb/IDBRequest.h

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: Addressed last round of feedback. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
index 8d87624bcac2d2d92a7ef8b6ce0b121e7b11925d..200b824d72382437adc9fee51afe584c8046b2a9 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
@@ -46,6 +46,7 @@
#include "platform/blob/BlobData.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/HashMap.h"
+#include "platform/wtf/RefPtr.h"
#include "public/platform/WebBlobInfo.h"
#include "public/platform/modules/indexeddb/WebIDBCursor.h"
#include "public/platform/modules/indexeddb/WebIDBTypes.h"
@@ -112,24 +113,54 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
void SetPendingCursor(IDBCursor*);
void Abort();
- void EnqueueResponse(DOMException*);
- void EnqueueResponse(std::unique_ptr<WebIDBCursor>,
- IDBKey*,
- IDBKey* primary_key,
- PassRefPtr<IDBValue>);
- void EnqueueResponse(IDBKey*);
- void EnqueueResponse(PassRefPtr<IDBValue>);
- void EnqueueResponse(const Vector<RefPtr<IDBValue>>&);
- void EnqueueResponse();
- void EnqueueResponse(IDBKey*, IDBKey* primary_key, PassRefPtr<IDBValue>);
+ // Blink's delivery of results from IndexedDB's backing store to script is
+ // more complicated than prescribed in the IndexedDB specification.
+ //
+ // IDBValue, which holds responses from the backing store, is either the
+ // serialized V8 value, or a reference to a Blob that holds the serialized
+ // value. IDBValueWrapping.h has the motivation and details. This introduces
+ // the following complexities.
+ //
+ // 1) De-serialization is expensive, so it is done lazily in
+ // IDBRequest::result(), which is called synchronously from script. On the
+ // other hand, Blob data can only be fetched asynchronously. So, IDBValues
+ // that reference serialized data stored in Blobs must be processed before
+ // IDBRequest event handlers are invoked, because the event handler script may
+ // call IDBRequest::result().
+ //
+ // 2) The IDBRequest events must be dispatched (enqueued in DOMWindow's event
+ // queue) in the order in which the requests were issued. If an IDBValue
+ // references a Blob, the Blob processing must block event dispatch for all
+ // following IDBRequests in the same transaction.
+ //
+ // The Blob de-referencing and IDBRequest blocking is performed in the
+ // HandleResponse() overloads below. Each HandleResponse() overload is paired
+ // with a matching EnqueueResponse() overload, which is called when an
+ // IDBRequest's result event can be delivered to the application. All the
+ // HandleResponse() variants include a fast path that calls directly into
+ // EnqueueResponse() if no queueing is required.
+ //
+ // Some types of requests, such as indexedDB.openDatabase(), cannot be issued
+ // after a request that needs Blob processing, so their results are handled by
+ // having WebIDBCallbacksImpl call directly into EnqueueResponse(),
+ // EnqueueBlocked(), or EnqueueUpgradeNeeded().
+
+ void HandleResponse(DOMException*);
+ void HandleResponse(IDBKey*);
+ void HandleResponse(std::unique_ptr<WebIDBCursor>,
+ IDBKey*,
+ IDBKey* primary_key,
+ RefPtr<IDBValue>&&);
+ void HandleResponse(IDBKey*, IDBKey* primary_key, RefPtr<IDBValue>&&);
+ void HandleResponse(RefPtr<IDBValue>&&);
+ void HandleResponse(const Vector<RefPtr<IDBValue>>&);
+ void HandleResponse(int64_t);
+ void HandleResponse();
// Only used in webkitGetDatabaseNames(), which is deprecated and hopefully
// going away soon.
void EnqueueResponse(const Vector<String>&);
- // Overridden by IDBOpenDBRequest.
- virtual void EnqueueResponse(int64_t);
-
// Only IDBOpenDBRequest instances should receive these:
virtual void EnqueueBlocked(int64_t old_version) { NOTREACHED(); }
virtual void EnqueueUpgradeNeeded(int64_t old_version,
@@ -162,10 +193,30 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
IDBCursor* GetResultCursor() const;
- void StorePutOperationBlobs(
- HashMap<String, RefPtr<BlobDataHandle>> blob_handles) {
- transit_blob_handles_ = std::move(blob_handles);
+ // Used to hang onto Blobs until the browser process handles the request.
+ //
+ // Blobs are ref-counted on the browser side, and BlobDataHandles manage
+ // references from renderers. When a BlobDataHandle gets destroyed, the
+ // browser-side Blob gets derefenced, which might cause it to be destroyed as
+ // well.
+ //
+ // After script uses a Blob in a put() request, the Blink-side Blob object
+ // (which hangs onto the BlobDataHandle) may get garbage-collected. IDBRequest
+ // needs to hang onto the BlobDataHandle as well, to avoid having the
+ // browser-side Blob get destroyed before the IndexedDB request is processed.
+ inline Vector<RefPtr<BlobDataHandle>>* transit_blob_handles() {
+ return &transit_blob_handles_;
+ }
+
+#if DCHECK_IS_ON()
+ inline bool TransactionHasQueuedResults() const {
+ return transaction_ && transaction_->HasQueuedResults();
}
+#endif // DCHECK_IS_ON()
+
+#if DCHECK_IS_ON()
+ inline IDBRequestQueueItem* QueueItem() const { return queue_item_; }
+#endif // DCHECK_IS_ON()
protected:
IDBRequest(ScriptState*, IDBAny* source, IDBTransaction*);
@@ -175,10 +226,16 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
void EnqueueResultInternal(IDBAny*);
void SetResult(IDBAny*);
+ // Overridden by IDBOpenDBRequest.
+ virtual void EnqueueResponse(int64_t);
+
// EventTarget
DispatchEventResult DispatchEventInternal(Event*) override;
+ // Can be nullptr for requests that are not associated with a transaction,
+ // i.e. delete requests and completed or unsuccessful open requests.
Member<IDBTransaction> transaction_;
+
ReadyState ready_state_ = PENDING;
bool request_aborted_ = false; // May be aborted by transaction then receive
// async onsuccess; ignore vs. assert.
@@ -187,14 +244,26 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
v8::Isolate* isolate_;
private:
+ // Calls EnqueueResponse().
+ friend class IDBRequestQueueItem;
+
void SetResultCursor(IDBCursor*,
IDBKey*,
IDBKey* primary_key,
- PassRefPtr<IDBValue>);
+ RefPtr<IDBValue>&&);
void AckReceivedBlobs(const IDBValue*);
void AckReceivedBlobs(const Vector<RefPtr<IDBValue>>&);
- void ClearPutOperationBlobs() { transit_blob_handles_.clear(); }
+ void EnqueueResponse(DOMException*);
+ void EnqueueResponse(IDBKey*);
+ void EnqueueResponse(std::unique_ptr<WebIDBCursor>,
+ IDBKey*,
+ IDBKey* primary_key,
+ RefPtr<IDBValue>&&);
+ void EnqueueResponse(IDBKey*, IDBKey* primary_key, RefPtr<IDBValue>&&);
+ void EnqueueResponse(RefPtr<IDBValue>&&);
+ void EnqueueResponse(const Vector<RefPtr<IDBValue>>&);
+ void EnqueueResponse();
Member<IDBAny> source_;
Member<IDBAny> result_;
@@ -215,7 +284,7 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
Member<IDBKey> cursor_primary_key_;
RefPtr<IDBValue> cursor_value_;
- HashMap<String, RefPtr<BlobDataHandle>> transit_blob_handles_;
+ Vector<RefPtr<BlobDataHandle>> transit_blob_handles_;
bool did_fire_upgrade_needed_event_ = false;
bool prevent_propagation_ = false;
@@ -230,6 +299,12 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
// Pointer back to the WebIDBCallbacks that holds a persistent reference to
// this object.
WebIDBCallbacks* web_callbacks_ = nullptr;
+
+ // Non-null while this request is queued behind other requests that are still
+ // getting post-processed.
+ //
+ // The IDBRequestQueueItem is owned by the result queue in IDBTransaction.
+ IDBRequestQueueItem* queue_item_ = nullptr;
};
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698