blob: 46270db75311620877979a1bec17e1464fc9b51e [file] [log] [blame]
// Copyright (c) 2012 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_callbacks.h"
#include <algorithm>
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/common/indexed_db/indexed_db_messages.h"
#include "webkit/browser/quota/quota_manager.h"
using WebKit::WebIDBCallbacks;
namespace content {
namespace {
const int32 kNoCursor = -1;
const int32 kNoDatabase = -1;
const int32 kNoDatabaseCallbacks = -1;
const int64 kNoTransaction = -1;
}
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32 ipc_thread_id,
int32 ipc_callbacks_id)
: dispatcher_host_(dispatcher_host),
ipc_callbacks_id_(ipc_callbacks_id),
ipc_thread_id_(ipc_thread_id),
ipc_cursor_id_(kNoCursor),
host_transaction_id_(kNoTransaction),
ipc_database_id_(kNoDatabase),
ipc_database_callbacks_id_(kNoDatabaseCallbacks) {}
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32 ipc_thread_id,
int32 ipc_callbacks_id,
int32 ipc_cursor_id)
: dispatcher_host_(dispatcher_host),
ipc_callbacks_id_(ipc_callbacks_id),
ipc_thread_id_(ipc_thread_id),
ipc_cursor_id_(ipc_cursor_id),
host_transaction_id_(kNoTransaction),
ipc_database_id_(kNoDatabase),
ipc_database_callbacks_id_(kNoDatabaseCallbacks) {}
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32 ipc_thread_id,
int32 ipc_callbacks_id,
int32 ipc_database_callbacks_id,
int64 host_transaction_id,
const GURL& origin_url)
: dispatcher_host_(dispatcher_host),
ipc_callbacks_id_(ipc_callbacks_id),
ipc_thread_id_(ipc_thread_id),
ipc_cursor_id_(kNoCursor),
host_transaction_id_(host_transaction_id),
origin_url_(origin_url),
ipc_database_id_(kNoDatabase),
ipc_database_callbacks_id_(ipc_database_callbacks_id) {}
IndexedDBCallbacks::~IndexedDBCallbacks() {}
void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
DCHECK(dispatcher_host_.get());
dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
std::vector<string16> list;
for (unsigned i = 0; i < value.size(); ++i)
list.push_back(value[i]);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
ipc_thread_id_, ipc_callbacks_id_, list));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
// No transaction/db callbacks for DeleteDatabase.
DCHECK_EQ(kNoTransaction == host_transaction_id_,
kNoDatabaseCallbacks == ipc_database_callbacks_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
ipc_thread_id_, ipc_callbacks_id_, existing_version));
}
void IndexedDBCallbacks::OnUpgradeNeeded(
int64 old_version,
scoped_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata,
WebIDBCallbacks::DataLoss data_loss) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_NE(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_url_);
int32 ipc_database_id =
dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_url_);
if (ipc_database_id < 0)
return;
ipc_database_id_ = ipc_database_id;
IndexedDBMsg_CallbacksUpgradeNeeded_Params params;
params.ipc_thread_id = ipc_thread_id_;
params.ipc_callbacks_id = ipc_callbacks_id_;
params.ipc_database_id = ipc_database_id;
params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
params.old_version = old_version;
params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
params.data_loss = data_loss;
dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
}
void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_NE(kNoTransaction, host_transaction_id_);
DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection);
DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
scoped_refptr<IndexedDBCallbacks> self(this);
int32 ipc_object_id = ipc_database_id_;
if (ipc_object_id == kNoDatabase) {
ipc_object_id = dispatcher_host_->Add(
connection.release(), ipc_thread_id_, origin_url_);
}
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
ipc_thread_id_,
ipc_callbacks_id_,
ipc_database_callbacks_id_,
ipc_object_id,
IndexedDBDispatcherHost::ConvertMetadata(metadata)));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
const IndexedDBKey& key,
const IndexedDBKey& primary_key,
std::string* value) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
params.ipc_thread_id = ipc_thread_id_;
params.ipc_callbacks_id = ipc_callbacks_id_;
params.ipc_cursor_id = ipc_object_id;
params.key = key;
params.primary_key = primary_key;
if (value && !value->empty())
std::swap(params.value, *value);
// TODO(alecflett): Avoid a copy here: the whole params object is
// being copied into the message.
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(params));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
const IndexedDBKey& primary_key,
std::string* value) {
DCHECK(dispatcher_host_.get());
DCHECK_NE(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
IndexedDBCursor* idb_cursor =
dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
DCHECK(idb_cursor);
if (!idb_cursor)
return;
IndexedDBMsg_CallbacksSuccessCursorContinue_Params params;
params.ipc_thread_id = ipc_thread_id_;
params.ipc_callbacks_id = ipc_callbacks_id_;
params.ipc_cursor_id = ipc_cursor_id_;
params.key = key;
params.primary_key = primary_key;
if (value && !value->empty())
std::swap(params.value, *value);
// TODO(alecflett): Avoid a copy here: the whole params object is
// being copied into the message.
dispatcher_host_->Send(
new IndexedDBMsg_CallbacksSuccessCursorContinue(params));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccessWithPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
const std::vector<std::string>& values) {
DCHECK_EQ(keys.size(), primary_keys.size());
DCHECK_EQ(keys.size(), values.size());
DCHECK(dispatcher_host_.get());
DCHECK_NE(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
std::vector<IndexedDBKey> msgKeys;
std::vector<IndexedDBKey> msgPrimaryKeys;
for (size_t i = 0; i < keys.size(); ++i) {
msgKeys.push_back(keys[i]);
msgPrimaryKeys.push_back(primary_keys[i]);
}
IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params params;
params.ipc_thread_id = ipc_thread_id_;
params.ipc_callbacks_id = ipc_callbacks_id_;
params.ipc_cursor_id = ipc_cursor_id_;
params.keys = msgKeys;
params.primary_keys = msgPrimaryKeys;
params.values = values;
dispatcher_host_->Send(
new IndexedDBMsg_CallbacksSuccessCursorPrefetch(params));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(std::string* value,
const IndexedDBKey& key,
const IndexedDBKeyPath& key_path) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
std::string value_copy;
if (value && !value->empty())
std::swap(value_copy, *value);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValueWithKey(
ipc_thread_id_,
ipc_callbacks_id_,
// TODO(alecflett): Avoid a copy here.
value_copy,
key,
key_path));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(std::string* value) {
DCHECK(dispatcher_host_.get());
DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
std::string value_copy;
if (value && !value->empty())
std::swap(value_copy, *value);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(
ipc_thread_id_,
ipc_callbacks_id_,
// TODO(alecflett): avoid a copy here.
value_copy));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
ipc_thread_id_, ipc_callbacks_id_, value));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess(int64 value) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
ipc_thread_id_, ipc_callbacks_id_, value));
dispatcher_host_ = NULL;
}
void IndexedDBCallbacks::OnSuccess() {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
DCHECK_EQ(kNoTransaction, host_transaction_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
ipc_thread_id_, ipc_callbacks_id_));
dispatcher_host_ = NULL;
}
} // namespace content