// 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 #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_constants.h" #include "content/common/indexed_db/indexed_db_messages.h" #include "webkit/browser/quota/quota_manager.h" namespace content { namespace { const int32 kNoCursor = -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& 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 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 connection, const IndexedDBDatabaseMetadata& metadata, blink::WebIDBDataLoss data_loss, std::string data_loss_message) { 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; params.data_loss_message = data_loss_message; dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params)); } void IndexedDBCallbacks::OnSuccess(scoped_ptr 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 self(this); int32 ipc_object_id = kNoDatabase; // Only register if the connection was not previously sent in OnUpgradeNeeded. if (ipc_database_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 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& keys, const std::vector& primary_keys, const std::vector& 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 msgKeys; std::vector 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