| // 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 |