| 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 | 
|  |