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 |