/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.h"

#include <memory>
#include <utility>

#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/inspector/v8_inspector_string.h"
#include "third_party/blink/renderer/modules/indexed_db_names.h"
#include "third_party/blink/renderer/modules/indexeddb/global_indexed_db.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_factory.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_index.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_object_store.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

using blink::protocol::Array;
using blink::protocol::IndexedDB::DatabaseWithObjectStores;
using blink::protocol::IndexedDB::DataEntry;
using blink::protocol::IndexedDB::Key;
using blink::protocol::IndexedDB::KeyPath;
using blink::protocol::IndexedDB::KeyRange;
using blink::protocol::IndexedDB::ObjectStore;
using blink::protocol::IndexedDB::ObjectStoreIndex;
using blink::protocol::Maybe;
using blink::protocol::Response;

typedef blink::protocol::IndexedDB::Backend::RequestDatabaseNamesCallback
    RequestDatabaseNamesCallback;
typedef blink::protocol::IndexedDB::Backend::RequestDatabaseCallback
    RequestDatabaseCallback;
typedef blink::protocol::IndexedDB::Backend::RequestDataCallback
    RequestDataCallback;
typedef blink::protocol::IndexedDB::Backend::DeleteObjectStoreEntriesCallback
    DeleteObjectStoreEntriesCallback;
typedef blink::protocol::IndexedDB::Backend::ClearObjectStoreCallback
    ClearObjectStoreCallback;
typedef blink::protocol::IndexedDB::Backend::DeleteDatabaseCallback
    DeleteDatabaseCallback;

namespace blink {
namespace {

const char kIndexedDBObjectGroup[] = "indexeddb";
const char kNoDocumentError[] = "No document for given frame found";

Response AssertIDBFactory(Document* document, IDBFactory*& result) {
  LocalDOMWindow* dom_window = document->domWindow();
  if (!dom_window)
    return Response::Error("No IndexedDB factory for given frame found");
  IDBFactory* idb_factory = GlobalIndexedDB::indexedDB(*dom_window);

  if (!idb_factory)
    return Response::Error("No IndexedDB factory for given frame found");
  result = idb_factory;
  return Response::OK();
}

class GetDatabaseNamesCallback final : public EventListener {
  WTF_MAKE_NONCOPYABLE(GetDatabaseNamesCallback);

 public:
  static GetDatabaseNamesCallback* Create(
      std::unique_ptr<RequestDatabaseNamesCallback> request_callback,
      const String& security_origin) {
    return new GetDatabaseNamesCallback(std::move(request_callback),
                                        security_origin);
  }

  ~GetDatabaseNamesCallback() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext*, Event* event) override {
    if (event->type() != event_type_names::kSuccess) {
      request_callback_->sendFailure(Response::Error("Unexpected event type."));
      return;
    }

    IDBRequest* idb_request = static_cast<IDBRequest*>(event->target());
    IDBAny* request_result = idb_request->ResultAsAny();
    if (request_result->GetType() != IDBAny::kDOMStringListType) {
      request_callback_->sendFailure(
          Response::Error("Unexpected result type."));
      return;
    }

    DOMStringList* database_names_list = request_result->DomStringList();
    std::unique_ptr<protocol::Array<String>> database_names =
        protocol::Array<String>::create();
    for (uint32_t i = 0; i < database_names_list->length(); ++i)
      database_names->addItem(database_names_list->item(i));
    request_callback_->sendSuccess(std::move(database_names));
  }

 private:
  GetDatabaseNamesCallback(
      std::unique_ptr<RequestDatabaseNamesCallback> request_callback,
      const String& security_origin)
      : EventListener(EventListener::kCPPEventListenerType),
        request_callback_(std::move(request_callback)),
        security_origin_(security_origin) {}
  std::unique_ptr<RequestDatabaseNamesCallback> request_callback_;
  String security_origin_;
};

class DeleteCallback final : public EventListener {
  WTF_MAKE_NONCOPYABLE(DeleteCallback);

 public:
  static DeleteCallback* Create(
      std::unique_ptr<DeleteDatabaseCallback> request_callback,
      const String& security_origin) {
    return new DeleteCallback(std::move(request_callback), security_origin);
  }

  ~DeleteCallback() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext*, Event* event) override {
    if (event->type() != event_type_names::kSuccess) {
      request_callback_->sendFailure(
          Response::Error("Failed to delete database."));
      return;
    }
    request_callback_->sendSuccess();
  }

 private:
  DeleteCallback(std::unique_ptr<DeleteDatabaseCallback> request_callback,
                 const String& security_origin)
      : EventListener(EventListener::kCPPEventListenerType),
        request_callback_(std::move(request_callback)),
        security_origin_(security_origin) {}
  std::unique_ptr<DeleteDatabaseCallback> request_callback_;
  String security_origin_;
};

template <typename RequestCallback>
class OpenDatabaseCallback;
template <typename RequestCallback>
class UpgradeDatabaseCallback;

template <typename RequestCallback>
class ExecutableWithDatabase
    : public RefCounted<ExecutableWithDatabase<RequestCallback>> {
 public:
  virtual ~ExecutableWithDatabase() = default;
  virtual void Execute(IDBDatabase*, ScriptState*) = 0;
  virtual RequestCallback* GetRequestCallback() = 0;
  void Start(LocalFrame* frame, const String& database_name) {
    Document* document = frame ? frame->GetDocument() : nullptr;
    if (!document) {
      SendFailure(Response::Error(kNoDocumentError));
      return;
    }
    IDBFactory* idb_factory = nullptr;
    Response response = AssertIDBFactory(document, idb_factory);
    if (!response.isSuccess()) {
      SendFailure(response);
      return;
    }

    ScriptState* script_state = ToScriptStateForMainWorld(frame);
    if (!script_state) {
      SendFailure(Response::InternalError());
      return;
    }

    ScriptState::Scope scope(script_state);
    DoStart(idb_factory, script_state, document->GetSecurityOrigin(),
            database_name);
  }

 private:
  void DoStart(IDBFactory* idb_factory,
               ScriptState* script_state,
               const SecurityOrigin*,
               const String& database_name) {
    OpenDatabaseCallback<RequestCallback>* open_callback =
        OpenDatabaseCallback<RequestCallback>::Create(this, script_state);
    UpgradeDatabaseCallback<RequestCallback>* upgrade_callback =
        UpgradeDatabaseCallback<RequestCallback>::Create(this);
    DummyExceptionStateForTesting exception_state;
    IDBOpenDBRequest* idb_open_db_request =
        idb_factory->open(script_state, database_name, exception_state);
    if (exception_state.HadException()) {
      SendFailure(Response::Error("Could not open database."));
      return;
    }
    idb_open_db_request->addEventListener(event_type_names::kUpgradeneeded,
                                          upgrade_callback, false);
    idb_open_db_request->addEventListener(event_type_names::kSuccess,
                                          open_callback, false);
  }

  void SendFailure(Response response) {
    GetRequestCallback()->sendFailure(response);
  }
};

template <typename RequestCallback>
class OpenDatabaseCallback final : public EventListener {
 public:
  static OpenDatabaseCallback* Create(
      ExecutableWithDatabase<RequestCallback>* executable_with_database,
      ScriptState* script_state) {
    return new OpenDatabaseCallback(executable_with_database, script_state);
  }

  ~OpenDatabaseCallback() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext* context, Event* event) override {
    if (event->type() != event_type_names::kSuccess) {
      executable_with_database_->GetRequestCallback()->sendFailure(
          Response::Error("Unexpected event type."));
      return;
    }

    IDBOpenDBRequest* idb_open_db_request =
        static_cast<IDBOpenDBRequest*>(event->target());
    IDBAny* request_result = idb_open_db_request->ResultAsAny();
    if (request_result->GetType() != IDBAny::kIDBDatabaseType) {
      executable_with_database_->GetRequestCallback()->sendFailure(
          Response::Error("Unexpected result type."));
      return;
    }

    IDBDatabase* idb_database = request_result->IdbDatabase();
    executable_with_database_->Execute(idb_database, script_state_);
    V8PerIsolateData::From(script_state_->GetIsolate())->RunEndOfScopeTasks();
    idb_database->close();
  }

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(script_state_);
    EventListener::Trace(visitor);
  }

 private:
  OpenDatabaseCallback(
      ExecutableWithDatabase<RequestCallback>* executable_with_database,
      ScriptState* script_state)
      : EventListener(EventListener::kCPPEventListenerType),
        executable_with_database_(executable_with_database),
        script_state_(script_state) {}
  scoped_refptr<ExecutableWithDatabase<RequestCallback>>
      executable_with_database_;
  Member<ScriptState> script_state_;
};

template <typename RequestCallback>
class UpgradeDatabaseCallback final : public EventListener {
 public:
  static UpgradeDatabaseCallback* Create(
      ExecutableWithDatabase<RequestCallback>* executable_with_database) {
    return new UpgradeDatabaseCallback(executable_with_database);
  }

  ~UpgradeDatabaseCallback() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext* context, Event* event) override {
    if (event->type() != event_type_names::kUpgradeneeded) {
      executable_with_database_->GetRequestCallback()->sendFailure(
          Response::Error("Unexpected event type."));
      return;
    }

    // If an "upgradeneeded" event comes through then the database that
    // had previously been enumerated was deleted. We don't want to
    // implicitly re-create it here, so abort the transaction.
    IDBOpenDBRequest* idb_open_db_request =
        static_cast<IDBOpenDBRequest*>(event->target());
    NonThrowableExceptionState exception_state;
    idb_open_db_request->transaction()->abort(exception_state);
    executable_with_database_->GetRequestCallback()->sendFailure(
        Response::Error("Aborted upgrade."));
  }

 private:
  UpgradeDatabaseCallback(
      ExecutableWithDatabase<RequestCallback>* executable_with_database)
      : EventListener(EventListener::kCPPEventListenerType),
        executable_with_database_(executable_with_database) {}
  scoped_refptr<ExecutableWithDatabase<RequestCallback>>
      executable_with_database_;
};

IDBTransaction* TransactionForDatabase(
    ScriptState* script_state,
    IDBDatabase* idb_database,
    const String& object_store_name,
    const String& mode = indexed_db_names::kReadonly) {
  DummyExceptionStateForTesting exception_state;
  StringOrStringSequence scope;
  scope.SetString(object_store_name);
  IDBTransaction* idb_transaction =
      idb_database->transaction(script_state, scope, mode, exception_state);
  if (exception_state.HadException())
    return nullptr;
  return idb_transaction;
}

IDBObjectStore* ObjectStoreForTransaction(IDBTransaction* idb_transaction,
                                          const String& object_store_name) {
  DummyExceptionStateForTesting exception_state;
  IDBObjectStore* idb_object_store =
      idb_transaction->objectStore(object_store_name, exception_state);
  if (exception_state.HadException())
    return nullptr;
  return idb_object_store;
}

IDBIndex* IndexForObjectStore(IDBObjectStore* idb_object_store,
                              const String& index_name) {
  DummyExceptionStateForTesting exception_state;
  IDBIndex* idb_index = idb_object_store->index(index_name, exception_state);
  if (exception_state.HadException())
    return nullptr;
  return idb_index;
}

std::unique_ptr<KeyPath> KeyPathFromIDBKeyPath(const IDBKeyPath& idb_key_path) {
  std::unique_ptr<KeyPath> key_path;
  switch (idb_key_path.GetType()) {
    case IDBKeyPath::kNullType:
      key_path = KeyPath::create().setType(KeyPath::TypeEnum::Null).build();
      break;
    case IDBKeyPath::kStringType:
      key_path = KeyPath::create()
                     .setType(KeyPath::TypeEnum::String)
                     .setString(idb_key_path.GetString())
                     .build();
      break;
    case IDBKeyPath::kArrayType: {
      key_path = KeyPath::create().setType(KeyPath::TypeEnum::Array).build();
      std::unique_ptr<protocol::Array<String>> array =
          protocol::Array<String>::create();
      const Vector<String>& string_array = idb_key_path.Array();
      for (wtf_size_t i = 0; i < string_array.size(); ++i)
        array->addItem(string_array[i]);
      key_path->setArray(std::move(array));
      break;
    }
    default:
      NOTREACHED();
  }

  return key_path;
}

class DatabaseLoader final
    : public ExecutableWithDatabase<RequestDatabaseCallback> {
 public:
  static scoped_refptr<DatabaseLoader> Create(
      std::unique_ptr<RequestDatabaseCallback> request_callback) {
    return base::AdoptRef(new DatabaseLoader(std::move(request_callback)));
  }

  ~DatabaseLoader() override = default;

  void Execute(IDBDatabase* idb_database, ScriptState*) override {
    const IDBDatabaseMetadata database_metadata = idb_database->Metadata();

    std::unique_ptr<protocol::Array<protocol::IndexedDB::ObjectStore>>
        object_stores =
            protocol::Array<protocol::IndexedDB::ObjectStore>::create();

    for (const auto& store_map_entry : database_metadata.object_stores) {
      const IDBObjectStoreMetadata& object_store_metadata =
          *store_map_entry.value;

      std::unique_ptr<protocol::Array<protocol::IndexedDB::ObjectStoreIndex>>
          indexes =
              protocol::Array<protocol::IndexedDB::ObjectStoreIndex>::create();

      for (const auto& metadata_map_entry : object_store_metadata.indexes) {
        const IDBIndexMetadata& index_metadata = *metadata_map_entry.value;

        std::unique_ptr<ObjectStoreIndex> object_store_index =
            ObjectStoreIndex::create()
                .setName(index_metadata.name)
                .setKeyPath(KeyPathFromIDBKeyPath(index_metadata.key_path))
                .setUnique(index_metadata.unique)
                .setMultiEntry(index_metadata.multi_entry)
                .build();
        indexes->addItem(std::move(object_store_index));
      }

      std::unique_ptr<ObjectStore> object_store =
          ObjectStore::create()
              .setName(object_store_metadata.name)
              .setKeyPath(KeyPathFromIDBKeyPath(object_store_metadata.key_path))
              .setAutoIncrement(object_store_metadata.auto_increment)
              .setIndexes(std::move(indexes))
              .build();
      object_stores->addItem(std::move(object_store));
    }
    std::unique_ptr<DatabaseWithObjectStores> result =
        DatabaseWithObjectStores::create()
            .setName(idb_database->name())
            .setVersion(static_cast<int>(idb_database->version()))
            .setObjectStores(std::move(object_stores))
            .build();

    request_callback_->sendSuccess(std::move(result));
  }

  RequestDatabaseCallback* GetRequestCallback() override {
    return request_callback_.get();
  }

 private:
  DatabaseLoader(std::unique_ptr<RequestDatabaseCallback> request_callback)
      : request_callback_(std::move(request_callback)) {}
  std::unique_ptr<RequestDatabaseCallback> request_callback_;
};

static std::unique_ptr<IDBKey> IdbKeyFromInspectorObject(
    protocol::IndexedDB::Key* key) {
  std::unique_ptr<IDBKey> idb_key;

  if (!key)
    return nullptr;
  String type = key->getType();

  DEFINE_STATIC_LOCAL(String, number, ("number"));
  DEFINE_STATIC_LOCAL(String, string, ("string"));
  DEFINE_STATIC_LOCAL(String, date, ("date"));
  DEFINE_STATIC_LOCAL(String, array, ("array"));

  if (type == number) {
    if (!key->hasNumber())
      return nullptr;
    idb_key = IDBKey::CreateNumber(key->getNumber(0));
  } else if (type == string) {
    if (!key->hasString())
      return nullptr;
    idb_key = IDBKey::CreateString(key->getString(String()));
  } else if (type == date) {
    if (!key->hasDate())
      return nullptr;
    idb_key = IDBKey::CreateDate(key->getDate(0));
  } else if (type == array) {
    IDBKey::KeyArray key_array;
    auto* array = key->getArray(nullptr);
    for (size_t i = 0; array && i < array->length(); ++i)
      key_array.push_back(IdbKeyFromInspectorObject(array->get(i)));
    idb_key = IDBKey::CreateArray(std::move(key_array));
  } else {
    return nullptr;
  }

  return idb_key;
}

static IDBKeyRange* IdbKeyRangeFromKeyRange(
    protocol::IndexedDB::KeyRange* key_range) {
  std::unique_ptr<IDBKey> idb_lower =
      IdbKeyFromInspectorObject(key_range->getLower(nullptr));
  if (key_range->hasLower() && !idb_lower)
    return nullptr;

  std::unique_ptr<IDBKey> idb_upper =
      IdbKeyFromInspectorObject(key_range->getUpper(nullptr));
  if (key_range->hasUpper() && !idb_upper)
    return nullptr;

  IDBKeyRange::LowerBoundType lower_bound_type =
      key_range->getLowerOpen() ? IDBKeyRange::kLowerBoundOpen
                                : IDBKeyRange::kLowerBoundClosed;
  IDBKeyRange::UpperBoundType upper_bound_type =
      key_range->getUpperOpen() ? IDBKeyRange::kUpperBoundOpen
                                : IDBKeyRange::kUpperBoundClosed;
  return IDBKeyRange::Create(std::move(idb_lower), std::move(idb_upper),
                             lower_bound_type, upper_bound_type);
}

class DataLoader;

class OpenCursorCallback final : public EventListener {
 public:
  static OpenCursorCallback* Create(
      v8_inspector::V8InspectorSession* v8_session,
      ScriptState* script_state,
      std::unique_ptr<RequestDataCallback> request_callback,
      int skip_count,
      unsigned page_size) {
    return new OpenCursorCallback(v8_session, script_state,
                                  std::move(request_callback), skip_count,
                                  page_size);
  }

  ~OpenCursorCallback() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext*, Event* event) override {
    if (event->type() != event_type_names::kSuccess) {
      request_callback_->sendFailure(Response::Error("Unexpected event type."));
      return;
    }

    IDBRequest* idb_request = static_cast<IDBRequest*>(event->target());
    IDBAny* request_result = idb_request->ResultAsAny();
    if (request_result->GetType() == IDBAny::kIDBValueType) {
      end(false);
      return;
    }
    if (request_result->GetType() != IDBAny::kIDBCursorWithValueType) {
      request_callback_->sendFailure(
          Response::Error("Unexpected result type."));
      return;
    }

    IDBCursorWithValue* idb_cursor = request_result->IdbCursorWithValue();

    if (skip_count_) {
      DummyExceptionStateForTesting exception_state;
      idb_cursor->advance(skip_count_, exception_state);
      if (exception_state.HadException()) {
        request_callback_->sendFailure(
            Response::Error("Could not advance cursor."));
      }
      skip_count_ = 0;
      return;
    }

    if (result_->length() == page_size_) {
      end(true);
      return;
    }

    // Continue cursor before making injected script calls, otherwise
    // transaction might be finished.
    DummyExceptionStateForTesting exception_state;
    idb_cursor->Continue(nullptr, nullptr, IDBRequest::AsyncTraceState(),
                         exception_state);
    if (exception_state.HadException()) {
      request_callback_->sendFailure(
          Response::Error("Could not continue cursor."));
      return;
    }

    Document* document = To<Document>(ExecutionContext::From(script_state_));
    if (!document)
      return;
    ScriptState::Scope scope(script_state_);
    v8::Local<v8::Context> context = script_state_->GetContext();
    v8_inspector::StringView object_group =
        ToV8InspectorStringView(kIndexedDBObjectGroup);
    std::unique_ptr<DataEntry> data_entry =
        DataEntry::create()
            .setKey(v8_session_->wrapObject(
                context, idb_cursor->key(script_state_).V8Value(), object_group,
                true /* generatePreview */))
            .setPrimaryKey(v8_session_->wrapObject(
                context, idb_cursor->primaryKey(script_state_).V8Value(),
                object_group, true /* generatePreview */))
            .setValue(v8_session_->wrapObject(
                context, idb_cursor->value(script_state_).V8Value(),
                object_group, true /* generatePreview */))
            .build();
    result_->addItem(std::move(data_entry));
  }

  void end(bool has_more) {
    request_callback_->sendSuccess(std::move(result_), has_more);
  }

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(script_state_);
    EventListener::Trace(visitor);
  }

 private:
  OpenCursorCallback(v8_inspector::V8InspectorSession* v8_session,
                     ScriptState* script_state,
                     std::unique_ptr<RequestDataCallback> request_callback,
                     int skip_count,
                     unsigned page_size)
      : EventListener(EventListener::kCPPEventListenerType),
        v8_session_(v8_session),
        script_state_(script_state),
        request_callback_(std::move(request_callback)),
        skip_count_(skip_count),
        page_size_(page_size) {
    result_ = Array<DataEntry>::create();
  }

  v8_inspector::V8InspectorSession* v8_session_;
  Member<ScriptState> script_state_;
  std::unique_ptr<RequestDataCallback> request_callback_;
  int skip_count_;
  unsigned page_size_;
  std::unique_ptr<Array<DataEntry>> result_;
};

class DataLoader final : public ExecutableWithDatabase<RequestDataCallback> {
 public:
  static scoped_refptr<DataLoader> Create(
      v8_inspector::V8InspectorSession* v8_session,
      std::unique_ptr<RequestDataCallback> request_callback,
      const String& object_store_name,
      const String& index_name,
      IDBKeyRange* idb_key_range,
      int skip_count,
      unsigned page_size) {
    return base::AdoptRef(new DataLoader(
        v8_session, std::move(request_callback), object_store_name, index_name,
        idb_key_range, skip_count, page_size));
  }

  ~DataLoader() override = default;

  void Execute(IDBDatabase* idb_database, ScriptState* script_state) override {
    IDBTransaction* idb_transaction =
        TransactionForDatabase(script_state, idb_database, object_store_name_);
    if (!idb_transaction) {
      request_callback_->sendFailure(
          Response::Error("Could not get transaction"));
      return;
    }
    IDBObjectStore* idb_object_store =
        ObjectStoreForTransaction(idb_transaction, object_store_name_);
    if (!idb_object_store) {
      request_callback_->sendFailure(
          Response::Error("Could not get object store"));
      return;
    }

    IDBRequest* idb_request;
    if (!index_name_.IsEmpty()) {
      IDBIndex* idb_index = IndexForObjectStore(idb_object_store, index_name_);
      if (!idb_index) {
        request_callback_->sendFailure(Response::Error("Could not get index"));
        return;
      }

      idb_request = idb_index->openCursor(script_state, idb_key_range_.Get(),
                                          kWebIDBCursorDirectionNext);
    } else {
      idb_request = idb_object_store->openCursor(
          script_state, idb_key_range_.Get(), kWebIDBCursorDirectionNext);
    }
    OpenCursorCallback* open_cursor_callback = OpenCursorCallback::Create(
        v8_session_, script_state, std::move(request_callback_), skip_count_,
        page_size_);
    idb_request->addEventListener(event_type_names::kSuccess,
                                  open_cursor_callback, false);
  }

  RequestDataCallback* GetRequestCallback() override {
    return request_callback_.get();
  }
  DataLoader(v8_inspector::V8InspectorSession* v8_session,
             std::unique_ptr<RequestDataCallback> request_callback,
             const String& object_store_name,
             const String& index_name,
             IDBKeyRange* idb_key_range,
             int skip_count,
             unsigned page_size)
      : v8_session_(v8_session),
        request_callback_(std::move(request_callback)),
        object_store_name_(object_store_name),
        index_name_(index_name),
        idb_key_range_(idb_key_range),
        skip_count_(skip_count),
        page_size_(page_size) {}

  v8_inspector::V8InspectorSession* v8_session_;
  std::unique_ptr<RequestDataCallback> request_callback_;
  String object_store_name_;
  String index_name_;
  Persistent<IDBKeyRange> idb_key_range_;
  int skip_count_;
  unsigned page_size_;
};

}  // namespace

// static
InspectorIndexedDBAgent::InspectorIndexedDBAgent(
    InspectedFrames* inspected_frames,
    v8_inspector::V8InspectorSession* v8_session)
    : inspected_frames_(inspected_frames),
      v8_session_(v8_session),
      enabled_(&agent_state_, /*default_value=*/false) {}

InspectorIndexedDBAgent::~InspectorIndexedDBAgent() = default;

void InspectorIndexedDBAgent::Restore() {
  if (enabled_.Get())
    enable();
}

void InspectorIndexedDBAgent::DidCommitLoadForLocalFrame(LocalFrame* frame) {
  if (frame == inspected_frames_->Root()) {
    v8_session_->releaseObjectGroup(
        ToV8InspectorStringView(kIndexedDBObjectGroup));
  }
}

Response InspectorIndexedDBAgent::enable() {
  enabled_.Set(true);
  return Response::OK();
}

Response InspectorIndexedDBAgent::disable() {
  enabled_.Clear();
  v8_session_->releaseObjectGroup(
      ToV8InspectorStringView(kIndexedDBObjectGroup));
  return Response::OK();
}

void InspectorIndexedDBAgent::requestDatabaseNames(
    const String& security_origin,
    std::unique_ptr<RequestDatabaseNamesCallback> request_callback) {
  LocalFrame* frame =
      inspected_frames_->FrameWithSecurityOrigin(security_origin);
  Document* document = frame ? frame->GetDocument() : nullptr;
  if (!document) {
    request_callback->sendFailure(Response::Error(kNoDocumentError));
    return;
  }
  IDBFactory* idb_factory = nullptr;
  Response response = AssertIDBFactory(document, idb_factory);
  if (!response.isSuccess()) {
    request_callback->sendFailure(response);
    return;
  }

  ScriptState* script_state = ToScriptStateForMainWorld(frame);
  if (!script_state) {
    request_callback->sendFailure(Response::InternalError());
    return;
  }
  ScriptState::Scope scope(script_state);
  DummyExceptionStateForTesting exception_state;
  IDBRequest* idb_request =
      idb_factory->GetDatabaseNames(script_state, exception_state);
  if (exception_state.HadException()) {
    request_callback->sendFailure(
        Response::Error("Could not obtain database names."));
    return;
  }
  idb_request->addEventListener(
      event_type_names::kSuccess,
      GetDatabaseNamesCallback::Create(
          std::move(request_callback),
          document->GetSecurityOrigin()->ToRawString()),
      false);
}

void InspectorIndexedDBAgent::requestDatabase(
    const String& security_origin,
    const String& database_name,
    std::unique_ptr<RequestDatabaseCallback> request_callback) {
  scoped_refptr<DatabaseLoader> database_loader =
      DatabaseLoader::Create(std::move(request_callback));
  database_loader->Start(
      inspected_frames_->FrameWithSecurityOrigin(security_origin),
      database_name);
}

void InspectorIndexedDBAgent::requestData(
    const String& security_origin,
    const String& database_name,
    const String& object_store_name,
    const String& index_name,
    int skip_count,
    int page_size,
    Maybe<protocol::IndexedDB::KeyRange> key_range,
    std::unique_ptr<RequestDataCallback> request_callback) {
  IDBKeyRange* idb_key_range =
      key_range.isJust() ? IdbKeyRangeFromKeyRange(key_range.fromJust())
                         : nullptr;
  if (key_range.isJust() && !idb_key_range) {
    request_callback->sendFailure(Response::Error("Can not parse key range."));
    return;
  }

  scoped_refptr<DataLoader> data_loader = DataLoader::Create(
      v8_session_, std::move(request_callback), object_store_name, index_name,
      idb_key_range, skip_count, page_size);

  data_loader->Start(
      inspected_frames_->FrameWithSecurityOrigin(security_origin),
      database_name);
}

class DeleteObjectStoreEntriesListener final : public EventListener {
  WTF_MAKE_NONCOPYABLE(DeleteObjectStoreEntriesListener);

 public:
  static DeleteObjectStoreEntriesListener* Create(
      std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback) {
    return new DeleteObjectStoreEntriesListener(std::move(request_callback));
  }

  ~DeleteObjectStoreEntriesListener() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext*, Event* event) override {
    if (event->type() != event_type_names::kSuccess) {
      request_callback_->sendFailure(
          Response::Error("Failed to delete specified entries"));
      return;
    }

    request_callback_->sendSuccess();
  }

 private:
  DeleteObjectStoreEntriesListener(
      std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback)
      : EventListener(EventListener::kCPPEventListenerType),
        request_callback_(std::move(request_callback)) {}

  std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback_;
};

class DeleteObjectStoreEntries final
    : public ExecutableWithDatabase<DeleteObjectStoreEntriesCallback> {
 public:
  static scoped_refptr<DeleteObjectStoreEntries> Create(
      const String& object_store_name,
      IDBKeyRange* idb_key_range,
      std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback) {
    return AdoptRef(new DeleteObjectStoreEntries(
        object_store_name, idb_key_range, std::move(request_callback)));
  }

  DeleteObjectStoreEntries(
      const String& object_store_name,
      IDBKeyRange* idb_key_range,
      std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback)
      : object_store_name_(object_store_name),
        idb_key_range_(idb_key_range),
        request_callback_(std::move(request_callback)) {}

  void Execute(IDBDatabase* idb_database, ScriptState* script_state) override {
    IDBTransaction* idb_transaction =
        TransactionForDatabase(script_state, idb_database, object_store_name_,
                               indexed_db_names::kReadwrite);
    if (!idb_transaction) {
      request_callback_->sendFailure(
          Response::Error("Could not get transaction"));
      return;
    }
    IDBObjectStore* idb_object_store =
        ObjectStoreForTransaction(idb_transaction, object_store_name_);
    if (!idb_object_store) {
      request_callback_->sendFailure(
          Response::Error("Could not get object store"));
      return;
    }

    IDBRequest* idb_request =
        idb_object_store->deleteFunction(script_state, idb_key_range_.Get());
    idb_request->addEventListener(
        event_type_names::kSuccess,
        DeleteObjectStoreEntriesListener::Create(std::move(request_callback_)),
        false);
  }

  DeleteObjectStoreEntriesCallback* GetRequestCallback() override {
    return request_callback_.get();
  }

 private:
  const String object_store_name_;
  Persistent<IDBKeyRange> idb_key_range_;
  std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback_;
};

void InspectorIndexedDBAgent::deleteObjectStoreEntries(
    const String& security_origin,
    const String& database_name,
    const String& object_store_name,
    std::unique_ptr<protocol::IndexedDB::KeyRange> key_range,
    std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback) {
  IDBKeyRange* idb_key_range = IdbKeyRangeFromKeyRange(key_range.get());
  if (!idb_key_range) {
    request_callback->sendFailure(Response::Error("Can not parse key range"));
    return;
  }
  scoped_refptr<DeleteObjectStoreEntries> delete_object_store_entries =
      DeleteObjectStoreEntries::Create(object_store_name, idb_key_range,
                                       std::move(request_callback));
  delete_object_store_entries->Start(
      inspected_frames_->FrameWithSecurityOrigin(security_origin),
      database_name);
}

class ClearObjectStoreListener final : public EventListener {
  WTF_MAKE_NONCOPYABLE(ClearObjectStoreListener);

 public:
  static ClearObjectStoreListener* Create(
      std::unique_ptr<ClearObjectStoreCallback> request_callback) {
    return new ClearObjectStoreListener(std::move(request_callback));
  }

  ~ClearObjectStoreListener() override = default;

  bool operator==(const EventListener& other) const override {
    return this == &other;
  }

  void Invoke(ExecutionContext*, Event* event) override {
    if (event->type() != event_type_names::kComplete) {
      request_callback_->sendFailure(Response::Error("Unexpected event type."));
      return;
    }

    request_callback_->sendSuccess();
  }

 private:
  ClearObjectStoreListener(
      std::unique_ptr<ClearObjectStoreCallback> request_callback)
      : EventListener(EventListener::kCPPEventListenerType),
        request_callback_(std::move(request_callback)) {}

  std::unique_ptr<ClearObjectStoreCallback> request_callback_;
};

class ClearObjectStore final
    : public ExecutableWithDatabase<ClearObjectStoreCallback> {
 public:
  static scoped_refptr<ClearObjectStore> Create(
      const String& object_store_name,
      std::unique_ptr<ClearObjectStoreCallback> request_callback) {
    return base::AdoptRef(
        new ClearObjectStore(object_store_name, std::move(request_callback)));
  }

  ClearObjectStore(const String& object_store_name,
                   std::unique_ptr<ClearObjectStoreCallback> request_callback)
      : object_store_name_(object_store_name),
        request_callback_(std::move(request_callback)) {}

  void Execute(IDBDatabase* idb_database, ScriptState* script_state) override {
    IDBTransaction* idb_transaction =
        TransactionForDatabase(script_state, idb_database, object_store_name_,
                               indexed_db_names::kReadwrite);
    if (!idb_transaction) {
      request_callback_->sendFailure(
          Response::Error("Could not get transaction"));
      return;
    }
    IDBObjectStore* idb_object_store =
        ObjectStoreForTransaction(idb_transaction, object_store_name_);
    if (!idb_object_store) {
      request_callback_->sendFailure(
          Response::Error("Could not get object store"));
      return;
    }

    DummyExceptionStateForTesting exception_state;
    idb_object_store->clear(script_state, exception_state);
    DCHECK(!exception_state.HadException());
    if (exception_state.HadException()) {
      ExceptionCode ec = exception_state.Code();
      request_callback_->sendFailure(Response::Error(
          String::Format("Could not clear object store '%s': %d",
                         object_store_name_.Utf8().data(), ec)));
      return;
    }
    idb_transaction->addEventListener(
        event_type_names::kComplete,
        ClearObjectStoreListener::Create(std::move(request_callback_)), false);
  }

  ClearObjectStoreCallback* GetRequestCallback() override {
    return request_callback_.get();
  }

 private:
  const String object_store_name_;
  std::unique_ptr<ClearObjectStoreCallback> request_callback_;
};

void InspectorIndexedDBAgent::clearObjectStore(
    const String& security_origin,
    const String& database_name,
    const String& object_store_name,
    std::unique_ptr<ClearObjectStoreCallback> request_callback) {
  scoped_refptr<ClearObjectStore> clear_object_store =
      ClearObjectStore::Create(object_store_name, std::move(request_callback));
  clear_object_store->Start(
      inspected_frames_->FrameWithSecurityOrigin(security_origin),
      database_name);
}

void InspectorIndexedDBAgent::deleteDatabase(
    const String& security_origin,
    const String& database_name,
    std::unique_ptr<DeleteDatabaseCallback> request_callback) {
  LocalFrame* frame =
      inspected_frames_->FrameWithSecurityOrigin(security_origin);
  Document* document = frame ? frame->GetDocument() : nullptr;
  if (!document) {
    request_callback->sendFailure(Response::Error(kNoDocumentError));
    return;
  }
  IDBFactory* idb_factory = nullptr;
  Response response = AssertIDBFactory(document, idb_factory);
  if (!response.isSuccess()) {
    request_callback->sendFailure(response);
    return;
  }

  ScriptState* script_state = ToScriptStateForMainWorld(frame);
  if (!script_state) {
    request_callback->sendFailure(Response::InternalError());
    return;
  }
  ScriptState::Scope scope(script_state);
  DummyExceptionStateForTesting exception_state;
  IDBRequest* idb_request = idb_factory->CloseConnectionsAndDeleteDatabase(
      script_state, database_name, exception_state);
  if (exception_state.HadException()) {
    request_callback->sendFailure(
        Response::Error("Could not delete database."));
    return;
  }
  idb_request->addEventListener(
      event_type_names::kSuccess,
      DeleteCallback::Create(std::move(request_callback),
                             document->GetSecurityOrigin()->ToRawString()),
      false);
}

void InspectorIndexedDBAgent::Trace(blink::Visitor* visitor) {
  visitor->Trace(inspected_frames_);
  InspectorBaseAgent::Trace(visitor);
}

}  // namespace blink
