Index: third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp |
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..37e8e4d586eb7b17ad6feaff929e7d8b3a94b895 |
--- /dev/null |
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp |
@@ -0,0 +1,97 @@ |
+// 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. |
+ |
+#include "modules/indexeddb/IDBRequestLoader.h" |
+ |
+#include "core/dom/DOMException.h" |
+#include "core/fileapi/FileReaderLoader.h" |
+#include "modules/indexeddb/IDBRequest.h" |
+#include "modules/indexeddb/IDBRequestQueueItem.h" |
+#include "modules/indexeddb/IDBValue.h" |
+#include "modules/indexeddb/IDBValueWrapping.h" |
+#include "public/platform/modules/indexeddb/WebIDBDatabaseException.h" |
+ |
+namespace blink { |
+ |
+IDBRequestLoader::IDBRequestLoader(IDBRequestQueueItem* queue_item, |
+ Vector<RefPtr<IDBValue>>* result_values) |
+ : queue_item_(queue_item), values_(result_values) { |
+ DCHECK(IDBValueUnwrapper::IsWrapped(*values_)); |
+ loader_ = FileReaderLoader::Create(FileReaderLoader::kReadByClient, this); |
+} |
+ |
+IDBRequestLoader::~IDBRequestLoader() { |
+ // TODO(pwnall): Do we need to call loader_->Cancel() here? |
+} |
+ |
+void IDBRequestLoader::Start() { |
+ // TODO(pwnall): Start() / StartNextValue() unwrap large values sequentially. |
+ // Consider parallelizing. The main issue is that the Blob reads |
+ // will have to be throttled somewhere, and the extra complexity |
+ // only benefits applications that use getAll(). |
+ current_value_ = values_->begin(); |
+ StartNextValue(); |
+} |
+ |
+void IDBRequestLoader::Cancel() { |
+ loader_->Cancel(); |
+} |
+ |
+void IDBRequestLoader::StartNextValue() { |
+ IDBValueUnwrapper unwrapper; |
+ |
+ while (true) { |
+ if (current_value_ == values_->end()) { |
+ ReportSuccess(); |
+ return; |
+ } |
+ if (unwrapper.Parse(current_value_->Get())) |
+ break; |
+ ++current_value_; |
+ } |
+ |
+ DCHECK(current_value_ != values_->end()); |
+ |
+ ExecutionContext* context = queue_item_->Request()->GetExecutionContext(); |
+ if (!context) { |
+ ReportError(); |
+ return; |
+ } |
+ |
+ wrapped_data_.ReserveCapacity(unwrapper.WrapperBlobSize()); |
+ loader_->Start(context, unwrapper.WrapperBlobHandle()); |
+} |
+ |
+void IDBRequestLoader::DidStartLoading() {} |
+ |
+void IDBRequestLoader::DidReceiveDataForClient(const char* data, |
+ unsigned data_length) { |
+ DCHECK_LE(wrapped_data_.size() + data_length, wrapped_data_.capacity()) |
+ << "The reader returned more data than we were prepared for"; |
+ |
+ wrapped_data_.Append(data, data_length); |
+} |
+ |
+void IDBRequestLoader::DidFinishLoading() { |
+ *current_value_ = IDBValueUnwrapper::CreateUnwrapped( |
+ current_value_->Get(), SharedBuffer::AdoptVector(wrapped_data_)); |
+ ++current_value_; |
+ |
+ StartNextValue(); |
+} |
+ |
+void IDBRequestLoader::DidFail(FileError::ErrorCode) { |
+ ReportError(); |
+} |
+ |
+void IDBRequestLoader::ReportSuccess() { |
+ queue_item_->OnResultLoadComplete(); |
+} |
+ |
+void IDBRequestLoader::ReportError() { |
+ queue_item_->OnResultLoadComplete( |
+ DOMException::Create(kDataError, "Failed to read large IndexedDB value")); |
+} |
+ |
+} // namespace blink |