Index: third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.h |
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.h b/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e2394616f4b305622dd66eb417fe9465da2845b5 |
--- /dev/null |
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestQueueItem.h |
@@ -0,0 +1,185 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef IDBRequestQueueItem_h |
+#define IDBRequestQueueItem_h |
+ |
+#include "platform/heap/Handle.h" |
+#include "platform/wtf/Allocator.h" |
+#include "platform/wtf/PassRefPtr.h" |
+#include "platform/wtf/RefPtr.h" |
+#include "platform/wtf/Vector.h" |
+ |
+#include <memory> |
+ |
+namespace blink { |
+ |
+class DOMException; |
+class IDBKey; |
+class IDBRequest; |
+class IDBRequestLoader; |
+class IDBValue; |
+class WebIDBCursor; |
+ |
+// 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 IDBRequestQueueItem { |
+ USING_FAST_MALLOC(IDBRequestQueueItem); |
+ |
+ public: |
+ IDBRequestQueueItem(IDBRequest*, |
+ DOMException*, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ int64_t, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ IDBKey*, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ PassRefPtr<IDBValue>, |
+ bool attach_loader, |
+ std::unique_ptr<WTF::Closure> on_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ const Vector<RefPtr<IDBValue>>&, |
+ bool attach_loader, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ IDBKey*, |
+ IDBKey* primary_key, |
+ PassRefPtr<IDBValue>, |
+ bool attach_loader, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ IDBRequestQueueItem(IDBRequest*, |
+ std::unique_ptr<WebIDBCursor>, |
+ IDBKey*, |
+ IDBKey* primary_key, |
+ PassRefPtr<IDBValue>, |
+ bool attach_loader, |
+ std::unique_ptr<WTF::Closure> on_result_load_complete); |
+ ~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 EnqueueResponse overload on the associated request. |
+ // |
+ // This should only be called by the request's IDBTransaction. |
+ void EnqueueResponse(); |
+ |
+ // Called by the associated IDBRequestLoader when result processing is done. |
+ void OnResultLoadComplete(); |
+ |
+ // Called by the associated IDBRequestLoader when result processing fails. |
+ void OnResultLoadComplete(DOMException* error); |
+ |
+ private: |
+ // The IDBRequest callback that will be called for this result. |
+ enum ResponseType { |
+ kCanceled, |
+ kCursorKeyPrimaryKeyValue, |
+ kError, |
+ kNumber, |
+ kKey, |
+ kKeyPrimaryKeyValue, |
+ kValue, |
+ kValueArray, |
+ kVoid, |
+ }; |
+ |
+ // The IDBRequest that will receive a callback for this result. |
+ Persistent<IDBRequest> request_; |
+ |
+ // The key argument to the IDBRequest callback. |
+ // |
+ // Only used if mode_ is kKeyPrimaryKeyValue. |
+ Persistent<IDBKey> key_; |
+ |
+ // The primary_key argument to the IDBRequest callback. |
+ // |
+ // Only used if mode_ is kKeyPrimaryKeyValue. |
+ Persistent<IDBKey> primary_key_; |
+ |
+ // The error argument to the IDBRequest callback. |
+ // |
+ // Only used if the mode_ is kError. |
+ Persistent<DOMException> error_; |
+ |
+ // All the values that will be passed back to the IDBRequest. |
+ Vector<RefPtr<IDBValue>> values_; |
+ |
+ // The cursor argument to the IDBRequest callback. |
+ std::unique_ptr<WebIDBCursor> cursor_; |
+ |
+ // Performs post-processing on this result. |
+ // |
+ // nullptr for results that do not require post-processing and for results |
+ // whose post-processing has completed. |
+ std::unique_ptr<IDBRequestLoader> loader_; |
+ |
+ // Called when result post-processing has completed. |
+ std::unique_ptr<WTF::Closure> on_result_load_complete_; |
+ |
+ // The integer value argument to the IDBRequest callback. |
+ int64_t int64_value_; |
+ |
+ // Identifies the IDBRequest::EnqueueResponse() overload that will be called. |
+ ResponseType response_type_; |
+ |
+ // False if this result still requires post-processing. |
+ bool ready_; |
+ |
+#if DCHECK_IS_ON() |
+ // True if the appropriate EnqueueResponse() method was called in IDBRequest. |
+ // |
+ // If CancelLoading() is called, the ResponseType might be kCanceled. In this |
+ // case, callback_fired_ can be set to true even though no EnqueueResponse() |
+ // call occurs. |
+ bool callback_fired_ = false; |
+#endif // DCHECK_IS_ON() |
+}; |
+ |
+using IDBRequestQueue = Deque<std::unique_ptr<IDBRequestQueueItem>>; |
+ |
+} // namespace blink |
+ |
+#endif // IDBRequestQueueItem_h |