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..2fb36880f1b27b0f057d04c699a383d722b24253 |
--- /dev/null |
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestLoader.cpp |
@@ -0,0 +1,156 @@ |
+// 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/IDBValue.h" |
+#include "modules/indexeddb/IDBValueUnwrapper.h" |
+#include "public/platform/modules/indexeddb/WebIDBDatabaseException.h" |
+ |
+namespace blink { |
+ |
+IDBRequestLoader::IDBRequestLoader(IDBRequest* request) |
+ : mode_(kUninitialized), request_(request) { |
+ loader_ = FileReaderLoader::Create(FileReaderLoader::kReadByClient, this); |
+} |
+ |
+IDBRequestLoader::~IDBRequestLoader() { |
+ // TODO(pwnall): Do we need to call loader_->Cancel() here? |
+} |
+ |
+bool IDBRequestLoader::NeedsUnwrapping(IDBValue* value) { |
+ return IDBValueUnwrapper::IsWrapped(value); |
+} |
+ |
+bool IDBRequestLoader::NeedUnwrapping(const Vector<RefPtr<IDBValue>>& values) { |
+ for (const auto& value : values) { |
+ if (IDBValueUnwrapper::IsWrapped(value.Get())) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+void IDBRequestLoader::Start(PassRefPtr<IDBValue> value) { |
+ DCHECK_EQ(mode_, kUninitialized) << "Start() has been called before"; |
+ |
+ values_.push_back(value); |
+ mode_ = kValue; |
+ StartNextValue(); |
+} |
+ |
+void IDBRequestLoader::Start(const Vector<RefPtr<IDBValue>>& values) { |
+ DCHECK_EQ(mode_, kUninitialized) << "Start() has been called before"; |
+ |
+ values_.AppendVector(values); |
+ mode_ = kValueArray; |
+ StartNextValue(); |
+} |
+ |
+void IDBRequestLoader::Start(IDBKey* key, |
+ IDBKey* primary_key, |
+ PassRefPtr<IDBValue> value) { |
+ DCHECK_EQ(mode_, kUninitialized) << "Start() has been called before"; |
+ |
+ key_ = key; |
+ primary_key_ = primary_key; |
+ values_.push_back(value); |
+ mode_ = kKeyPrimaryKeyValue; |
+ StartNextValue(); |
+} |
+ |
+void IDBRequestLoader::Start(std::unique_ptr<WebIDBCursor> backend, |
+ IDBKey* key, |
+ IDBKey* primary_key, |
+ PassRefPtr<IDBValue> value) { |
+ DCHECK_EQ(mode_, kUninitialized) << "Start() has been called before"; |
+ |
+ backend_ = std::move(backend); |
+ key_ = key; |
+ primary_key_ = primary_key; |
+ values_.push_back(value); |
+ mode_ = kBackendKeyPrimaryKeyValue; |
+ StartNextValue(); |
+} |
+ |
+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 = 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() { |
+ switch (mode_) { |
+ case kUninitialized: |
+ NOTREACHED() << "Start() was not called"; |
+ |
+ case kValue: |
+ DCHECK_EQ(values_.size(), 1U); |
+ request_->OnSuccess(values_[0]); |
+ break; |
+ |
+ case kValueArray: |
+ request_->OnSuccess(values_); |
+ break; |
+ |
+ case kKeyPrimaryKeyValue: |
+ DCHECK_EQ(values_.size(), 1U); |
+ request_->OnSuccess(key_, primary_key_, values_[0]); |
+ |
+ case kBackendKeyPrimaryKeyValue: |
+ DCHECK_EQ(values_.size(), 1U); |
+ request_->OnSuccess(std::move(backend_), key_, primary_key_, values_[0]); |
+ } |
+} |
+ |
+void IDBRequestLoader::ReportError() { |
+ request_->OnError( |
+ DOMException::Create(kWebIDBDatabaseExceptionDataError, |
+ "Failed to read large IndexedDB value")); |
+} |
+ |
+} // namespace blink |