blob: 5bf11c6d3a4ae35e101f45f67b871d8d24f60351 [file] [log] [blame]
// Copyright 2019 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 "third_party/blink/renderer/modules/indexeddb/web_idb_transaction_impl.h"
#include <cstddef>
#include <memory>
#include <utility>
#include "base/format_macros.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database_error.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
WebIDBTransactionImpl::WebIDBTransactionImpl(
scoped_refptr<base::SequencedTaskRunner> task_runner,
int64_t transaction_id)
: task_runner_(task_runner), transaction_id_(transaction_id) {}
WebIDBTransactionImpl::~WebIDBTransactionImpl() = default;
mojo::PendingAssociatedReceiver<mojom::blink::IDBTransaction>
WebIDBTransactionImpl::CreateReceiver() {
return transaction_.BindNewEndpointAndPassReceiver(task_runner_);
}
void WebIDBTransactionImpl::CreateObjectStore(int64_t object_store_id,
const String& name,
const IDBKeyPath& key_path,
bool auto_increment) {
transaction_->CreateObjectStore(object_store_id, name, key_path,
auto_increment);
}
void WebIDBTransactionImpl::DeleteObjectStore(int64_t object_store_id) {
transaction_->DeleteObjectStore(object_store_id);
}
void WebIDBTransactionImpl::Put(int64_t object_store_id,
std::unique_ptr<IDBValue> value,
std::unique_ptr<IDBKey> primary_key,
mojom::IDBPutMode put_mode,
std::unique_ptr<WebIDBCallbacks> callbacks,
Vector<IDBIndexKeys> index_keys) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, nullptr);
size_t index_keys_size = 0;
for (const auto& index_key : index_keys) {
index_keys_size++; // Account for index_key.first (int64_t).
for (const auto& key : index_key.keys) {
// Because all size estimates are based on RAM usage, it is impossible to
// overflow index_keys_size.
index_keys_size += key->SizeEstimate();
}
}
size_t arg_size =
value->DataSize() + primary_key->SizeEstimate() + index_keys_size;
if (arg_size >= max_put_value_size_) {
callbacks->Error(
mojom::blink::IDBException::kUnknownError,
String::Format("The serialized keys and/or value are too large"
" (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
arg_size, max_put_value_size_));
return;
}
callbacks->SetState(nullptr, transaction_id_);
transaction_->Put(object_store_id, std::move(value), std::move(primary_key),
put_mode, std::move(index_keys),
WTF::Bind(&WebIDBTransactionImpl::PutCallback,
WTF::Unretained(this), std::move(callbacks)));
}
void WebIDBTransactionImpl::PutCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
mojom::blink::IDBTransactionPutResultPtr result) {
if (result->is_error_result()) {
callbacks->Error(result->get_error_result()->error_code,
std::move(result->get_error_result()->error_message));
callbacks.reset();
return;
}
if (result->is_key()) {
callbacks->SuccessKey(std::move(result->get_key()));
callbacks.reset();
return;
}
}
void WebIDBTransactionImpl::PutAll(int64_t object_store_id,
Vector<mojom::blink::IDBPutParamsPtr> puts,
std::unique_ptr<WebIDBCallbacks> callbacks) {
IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, nullptr);
base::CheckedNumeric<size_t> index_keys_size = 0;
for (auto& put : puts) {
index_keys_size++;
for (const auto& index_key : put->index_keys) {
for (const auto& key : index_key.keys) {
index_keys_size += key->SizeEstimate();
}
}
}
base::CheckedNumeric<size_t> arg_size;
for (auto& put : puts) {
arg_size += put->value->DataSize();
arg_size += put->key->SizeEstimate();
}
arg_size += index_keys_size.ValueOrDie();
if (arg_size.ValueOrDie() >= max_put_value_size_) {
callbacks->Error(
mojom::blink::IDBException::kUnknownError,
String::Format("The serialized keys and/or values are too large"
" (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
base::checked_cast<size_t>(arg_size.ValueOrDie()),
max_put_value_size_));
return;
}
callbacks->SetState(nullptr, transaction_id_);
transaction_->PutAll(object_store_id, std::move(puts),
WTF::Bind(&WebIDBTransactionImpl::PutAllCallback,
WTF::Unretained(this), std::move(callbacks)));
}
void WebIDBTransactionImpl::PutAllCallback(
std::unique_ptr<WebIDBCallbacks> callbacks,
mojom::blink::IDBTransactionPutAllResultPtr result) {
if (result->is_error_result()) {
callbacks->Error(result->get_error_result()->error_code,
std::move(result->get_error_result()->error_message));
callbacks.reset();
return;
}
if (result->is_keys()) {
callbacks->SuccessKey(IDBKey::CreateArray(std::move(result->get_keys())));
callbacks.reset();
return;
}
}
void WebIDBTransactionImpl::Commit(int64_t num_errors_handled) {
transaction_->Commit(num_errors_handled);
}
} // namespace blink