// Copyright (c) 2013 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 "content/browser/indexed_db/indexed_db_cursor.h"

#include <stddef.h>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/logging.h"
#include "base/task/post_task.h"
#include "content/browser/indexed_db/indexed_db_callback_helpers.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"

using blink::IndexedDBKey;

namespace content {
namespace {
// This should never be script visible: the cursor should either be closed when
// it hits the end of the range (and script throws an error before the call
// could be made), if the transaction has finished (ditto), or if there's an
// incoming request from the front end but the transaction has aborted on the
// back end; in that case the tx will already have sent an abort to the request
// so this would be ignored.
IndexedDBDatabaseError CreateCursorClosedError() {
  return IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
                                "The cursor has been closed.");
}

IndexedDBDatabaseError CreateError(
    uint16_t code,
    const char* message,
    base::WeakPtr<IndexedDBTransaction> transaction) {
  if (transaction)
    transaction->IncrementNumErrorsSent();
  return IndexedDBDatabaseError(code, message);
}

}  // namespace

IndexedDBCursor::IndexedDBCursor(
    std::unique_ptr<IndexedDBBackingStore::Cursor> cursor,
    indexed_db::CursorType cursor_type,
    blink::mojom::IDBTaskType task_type,
    base::WeakPtr<IndexedDBTransaction> transaction)
    : task_type_(task_type),
      cursor_type_(cursor_type),
      transaction_(std::move(transaction)),
      cursor_(std::move(cursor)),
      closed_(false) {
  IDB_ASYNC_TRACE_BEGIN("IndexedDBCursor::open", this);
}

IndexedDBCursor::~IndexedDBCursor() {
  if (transaction_)
    transaction_->UnregisterOpenCursor(this);
  // Call to make sure we complete our lifetime trace.
  Close();
}

void IndexedDBCursor::Advance(
    uint32_t count,
    base::WeakPtr<content::IndexedDBDispatcherHost> dispatcher_host,
    blink::mojom::IDBCursor::AdvanceCallback callback) {
  IDB_TRACE("IndexedDBCursor::Advance");

  if (!transaction_)
    Close();
  if (closed_) {
    const IndexedDBDatabaseError error(CreateCursorClosedError());
    std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
        blink::mojom::IDBError::New(error.code(), error.message())));
    return;
  }

  blink::mojom::IDBCursor::AdvanceCallback aborting_callback =
      CreateCallbackAbortOnDestruct<blink::mojom::IDBCursor::AdvanceCallback,
                                    blink::mojom::IDBCursorResultPtr>(
          std::move(callback), transaction_);

  transaction_->ScheduleTask(
      task_type_,
      BindWeakOperation<IndexedDBCursor>(
          &IndexedDBCursor::CursorAdvanceOperation, ptr_factory_.GetWeakPtr(),
          count, std::move(dispatcher_host), std::move(aborting_callback)));
}

leveldb::Status IndexedDBCursor::CursorAdvanceOperation(
    uint32_t count,
    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
    blink::mojom::IDBCursor::AdvanceCallback callback,
    IndexedDBTransaction* /*transaction*/) {
  IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
  leveldb::Status s = leveldb::Status::OK();
  if (!dispatcher_host)
    return s;

  if (!cursor_ || !cursor_->Advance(count, &s)) {
    cursor_.reset();

    if (s.ok()) {
      std::move(callback).Run(blink::mojom::IDBCursorResult::NewEmpty(true));
      return s;
    }

    // CreateError() needs to be called before calling Close() so
    // |transaction_| is alive.
    auto error = CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
                             "Error advancing cursor", transaction_);
    Close();
    std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
        blink::mojom::IDBError::New(error.code(), error.message())));
    return s;
  }

  blink::mojom::IDBValuePtr mojo_value;
  std::vector<IndexedDBBlobInfo> blob_info;
  IndexedDBValue* value = Value();
  if (value) {
    mojo_value = IndexedDBValue::ConvertAndEraseValue(value);
    blob_info.swap(value->blob_info);

    if (!IndexedDBCallbacks::CreateAllBlobs(
            dispatcher_host->blob_storage_context(),
            IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
                blob_info, &mojo_value->blob_or_file_info))) {
      return s;
    }
  } else {
    mojo_value = blink::mojom::IDBValue::New();
  }

  std::vector<IndexedDBKey> keys = {key()};
  std::vector<IndexedDBKey> primary_keys = {primary_key()};
  std::vector<blink::mojom::IDBValuePtr> values;
  values.push_back(std::move(mojo_value));
  std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
      blink::mojom::IDBCursorValue::New(
          std::move(keys), std::move(primary_keys), std::move(values))));
  return s;
}

void IndexedDBCursor::Continue(
    base::WeakPtr<content::IndexedDBDispatcherHost> dispatcher_host,
    std::unique_ptr<IndexedDBKey> key,
    std::unique_ptr<IndexedDBKey> primary_key,
    blink::mojom::IDBCursor::CursorContinueCallback callback) {
  IDB_TRACE("IndexedDBCursor::Continue");
  if (!transaction_)
    Close();
  if (closed_) {
    const IndexedDBDatabaseError error(CreateCursorClosedError());
    std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
        blink::mojom::IDBError::New(error.code(), error.message())));
    return;
  }

  blink::mojom::IDBCursor::CursorContinueCallback aborting_callback =
      CreateCallbackAbortOnDestruct<
          blink::mojom::IDBCursor::CursorContinueCallback,
          blink::mojom::IDBCursorResultPtr>(std::move(callback), transaction_);

  transaction_->ScheduleTask(
      task_type_,
      BindWeakOperation<IndexedDBCursor>(
          &IndexedDBCursor::CursorContinueOperation, ptr_factory_.GetWeakPtr(),
          std::move(dispatcher_host), base::Passed(&key),
          base::Passed(&primary_key), std::move(aborting_callback)));
}

leveldb::Status IndexedDBCursor::CursorContinueOperation(
    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
    std::unique_ptr<IndexedDBKey> key,
    std::unique_ptr<IndexedDBKey> primary_key,
    blink::mojom::IDBCursor::CursorContinueCallback callback,
    IndexedDBTransaction* /*transaction*/) {
  IDB_TRACE("IndexedDBCursor::CursorContinueOperation");
  leveldb::Status s = leveldb::Status::OK();
  if (!dispatcher_host)
    return s;

  if (!cursor_ ||
      !cursor_->Continue(key.get(), primary_key.get(),
                         IndexedDBBackingStore::Cursor::SEEK, &s)) {
    cursor_.reset();
    if (s.ok()) {
      // This happens if we reach the end of the iterator and can't continue.
      std::move(callback).Run(blink::mojom::IDBCursorResult::NewEmpty(true));
      return s;
    }

    // |transaction_| must be valid for CreateError(), so we can't call
    // Close() until after calling CreateError().
    IndexedDBDatabaseError error =
        CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
                    "Error continuing cursor.", transaction_);
    Close();
    std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
        blink::mojom::IDBError::New(error.code(), error.message())));
    return s;
  }

  blink::mojom::IDBValuePtr mojo_value;
  std::vector<IndexedDBBlobInfo> blob_info;
  IndexedDBValue* value = Value();
  if (value) {
    mojo_value = IndexedDBValue::ConvertAndEraseValue(value);
    blob_info.swap(value->blob_info);

    if (!IndexedDBCallbacks::CreateAllBlobs(
            dispatcher_host->blob_storage_context(),
            IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
                blob_info, &mojo_value->blob_or_file_info))) {
      return s;
    }
  } else {
    mojo_value = blink::mojom::IDBValue::New();
  }

  std::vector<IndexedDBKey> keys = {this->key()};
  std::vector<IndexedDBKey> primary_keys = {this->primary_key()};
  std::vector<blink::mojom::IDBValuePtr> values;
  values.push_back(std::move(mojo_value));
  std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
      blink::mojom::IDBCursorValue::New(
          std::move(keys), std::move(primary_keys), std::move(values))));
  return s;
}

void IndexedDBCursor::PrefetchContinue(
    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
    int number_to_fetch,
    blink::mojom::IDBCursor::PrefetchCallback callback) {
  IDB_TRACE("IndexedDBCursor::PrefetchContinue");

  if (!transaction_)
    Close();
  if (closed_) {
    const IndexedDBDatabaseError error(CreateCursorClosedError());
    std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
        blink::mojom::IDBError::New(error.code(), error.message())));
    return;
  }

  blink::mojom::IDBCursor::PrefetchCallback aborting_callback =
      CreateCallbackAbortOnDestruct<blink::mojom::IDBCursor::PrefetchCallback,
                                    blink::mojom::IDBCursorResultPtr>(
          std::move(callback), transaction_);

  transaction_->ScheduleTask(
      task_type_, BindWeakOperation<IndexedDBCursor>(
                      &IndexedDBCursor::CursorPrefetchIterationOperation,
                      ptr_factory_.GetWeakPtr(), std::move(dispatcher_host),
                      number_to_fetch, std::move(aborting_callback)));
}

leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
    int number_to_fetch,
    blink::mojom::IDBCursor::PrefetchCallback callback,
    IndexedDBTransaction* /*transaction*/) {
  IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
  leveldb::Status s = leveldb::Status::OK();
  if (!dispatcher_host)
    return s;

  std::vector<IndexedDBKey> found_keys;
  std::vector<IndexedDBKey> found_primary_keys;
  std::vector<IndexedDBValue> found_values;

  saved_cursor_.reset();
  // TODO(cmumford): Use IPC::Channel::kMaximumMessageSize
  const size_t max_size_estimate = 10 * 1024 * 1024;
  size_t size_estimate = 0;

  // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
  //                 properly fail, caller will not know why, and any corruption
  //                 will be ignored.
  for (int i = 0; i < number_to_fetch; ++i) {
    if (!cursor_ || !cursor_->Continue(&s)) {
      cursor_.reset();
      if (s.ok()) {
        // We've reached the end, so just return what we have.
        break;
      }
      // |transaction_| must be valid for CreateError(), so we can't call
      // Close() until after calling CreateError().
      IndexedDBDatabaseError error =
          CreateError(blink::kWebIDBDatabaseExceptionUnknownError,
                      "Error continuing cursor.", transaction_);
      Close();
      std::move(callback).Run(blink::mojom::IDBCursorResult::NewErrorResult(
          blink::mojom::IDBError::New(error.code(), error.message())));
      return s;
    }

    if (i == 0) {
      // First prefetched result is always used, so that's the position
      // a cursor should be reset to if the prefetch is invalidated.
      saved_cursor_ = cursor_->Clone();
    }

    found_keys.push_back(cursor_->key());
    found_primary_keys.push_back(cursor_->primary_key());

    switch (cursor_type_) {
      case indexed_db::CURSOR_KEY_ONLY:
        found_values.push_back(IndexedDBValue());
        break;
      case indexed_db::CURSOR_KEY_AND_VALUE: {
        IndexedDBValue value;
        value.swap(*cursor_->value());
        size_estimate += value.SizeEstimate();
        found_values.push_back(value);
        break;
      }
      default:
        NOTREACHED();
    }
    size_estimate += cursor_->key().size_estimate();
    size_estimate += cursor_->primary_key().size_estimate();

    if (size_estimate > max_size_estimate)
      break;
  }

  if (found_keys.empty()) {
    std::move(callback).Run(blink::mojom::IDBCursorResult::NewEmpty(true));
    return s;
  }

  DCHECK_EQ(found_keys.size(), found_primary_keys.size());
  DCHECK_EQ(found_keys.size(), found_values.size());

  std::vector<blink::mojom::IDBValuePtr> mojo_values;
  mojo_values.reserve(found_values.size());
  for (size_t i = 0; i < found_values.size(); ++i) {
    mojo_values.push_back(
        IndexedDBValue::ConvertAndEraseValue(&found_values[i]));
  }

  std::vector<IndexedDBCallbacks::IndexedDBValueBlob> value_blobs;
  for (size_t i = 0; i < mojo_values.size(); ++i) {
    IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs(
        &value_blobs, found_values[i].blob_info,
        &mojo_values[i]->blob_or_file_info);
  }

  if (!IndexedDBCallbacks::CreateAllBlobs(
          dispatcher_host->blob_storage_context(), std::move(value_blobs))) {
    return s;
  }

  std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
      blink::mojom::IDBCursorValue::New(std::move(found_keys),
                                        std::move(found_primary_keys),
                                        std::move(mojo_values))));
  return s;
}

leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches,
                                               int /* unused_prefetches */) {
  IDB_TRACE("IndexedDBCursor::PrefetchReset");
  cursor_.swap(saved_cursor_);
  saved_cursor_.reset();
  leveldb::Status s;

  if (closed_)
    return s;
  // First prefetched result is always used.
  if (cursor_) {
    DCHECK_GT(used_prefetches, 0);
    for (int i = 0; i < used_prefetches - 1; ++i) {
      bool ok = cursor_->Continue(&s);
      DCHECK(ok);
    }
  }

  return s;
}

void IndexedDBCursor::OnRemoveBinding(base::OnceClosure remove_binding_cb) {
  remove_binding_cb_ = std::move(remove_binding_cb);
}

void IndexedDBCursor::RemoveBinding() {
  std::move(remove_binding_cb_).Run();
}

void IndexedDBCursor::Close() {
  if (closed_)
    return;
  IDB_ASYNC_TRACE_END("IndexedDBCursor::open", this);
  IDB_TRACE("IndexedDBCursor::Close");
  closed_ = true;
  cursor_.reset();
  saved_cursor_.reset();
  transaction_.reset();
}

}  // namespace content
