| // 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 "base/guid.h" |
| #include "base/metrics/histogram.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| #include "content/browser/child_process_security_policy_impl.h" |
| #include "content/browser/fileapi/fileapi_message_filter.h" |
| #include "content/browser/indexed_db/indexed_db_blob_info.h" |
| #include "content/browser/indexed_db/indexed_db_connection.h" |
| #include "content/browser/indexed_db/indexed_db_context_impl.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/browser/indexed_db/indexed_db_value.h" |
| #include "content/common/indexed_db/indexed_db_constants.h" |
| #include "content/common/indexed_db/indexed_db_messages.h" |
| #include "storage/browser/blob/blob_storage_context.h" |
| #include "storage/browser/quota/quota_manager.h" |
| #include "storage/common/blob/blob_data.h" |
| #include "storage/common/blob/shareable_file_reference.h" |
| |
| using storage::ShareableFileReference; |
| |
| 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), |
| data_loss_(blink::WebIDBDataLossNone), |
| sent_blocked_(false) { |
| } |
| |
| 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), |
| data_loss_(blink::WebIDBDataLossNone), |
| sent_blocked_(false) { |
| } |
| |
| 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), |
| data_loss_(blink::WebIDBDataLossNone), |
| sent_blocked_(false) { |
| } |
| |
| 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; |
| |
| if (!connection_open_start_time_.is_null()) { |
| UMA_HISTOGRAM_MEDIUM_TIMES( |
| "WebCore.IndexedDB.OpenTime.Error", |
| base::TimeTicks::Now() - connection_open_start_time_); |
| connection_open_start_time_ = base::TimeTicks(); |
| } |
| } |
| |
| void IndexedDBCallbacks::OnSuccess(const std::vector<base::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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| std::vector<base::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_); |
| |
| if (sent_blocked_) |
| return; |
| |
| sent_blocked_ = true; |
| dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked( |
| ipc_thread_id_, ipc_callbacks_id_, existing_version)); |
| |
| if (!connection_open_start_time_.is_null()) { |
| UMA_HISTOGRAM_MEDIUM_TIMES( |
| "WebCore.IndexedDB.OpenTime.Blocked", |
| base::TimeTicks::Now() - connection_open_start_time_); |
| connection_open_start_time_ = base::TimeTicks(); |
| } |
| } |
| |
| void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss, |
| std::string data_loss_message) { |
| DCHECK_NE(blink::WebIDBDataLossNone, data_loss); |
| data_loss_ = data_loss; |
| data_loss_message_ = data_loss_message; |
| } |
| |
| void IndexedDBCallbacks::OnUpgradeNeeded( |
| int64 old_version, |
| scoped_ptr<IndexedDBConnection> connection, |
| const IndexedDBDatabaseMetadata& metadata) { |
| 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)); |
| |
| if (!connection_open_start_time_.is_null()) { |
| UMA_HISTOGRAM_MEDIUM_TIMES( |
| "WebCore.IndexedDB.OpenTime.UpgradeNeeded", |
| base::TimeTicks::Now() - connection_open_start_time_); |
| connection_open_start_time_ = base::TimeTicks(); |
| } |
| } |
| |
| 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 = 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; |
| |
| if (!connection_open_start_time_.is_null()) { |
| UMA_HISTOGRAM_MEDIUM_TIMES( |
| "WebCore.IndexedDB.OpenTime.Success", |
| base::TimeTicks::Now() - connection_open_start_time_); |
| connection_open_start_time_ = base::TimeTicks(); |
| } |
| } |
| |
| static std::string CreateBlobData( |
| const IndexedDBBlobInfo& blob_info, |
| scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, |
| storage::BlobStorageContext* blob_storage_context, |
| base::TaskRunner* task_runner) { |
| std::string uuid = blob_info.uuid(); |
| if (!uuid.empty()) { |
| // We're sending back a live blob, not a reference into our backing store. |
| scoped_ptr<storage::BlobDataHandle> blob_data_handle( |
| blob_storage_context->GetBlobDataFromUUID(uuid)); |
| dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass()); |
| return uuid; |
| } |
| scoped_refptr<ShareableFileReference> shareable_file = |
| ShareableFileReference::Get(blob_info.file_path()); |
| if (!shareable_file.get()) { |
| shareable_file = ShareableFileReference::GetOrCreate( |
| blob_info.file_path(), |
| ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, |
| task_runner); |
| if (!blob_info.release_callback().is_null()) |
| shareable_file->AddFinalReleaseCallback(blob_info.release_callback()); |
| } |
| |
| uuid = base::GenerateGUID(); |
| scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid); |
| blob_data->set_content_type(base::UTF16ToUTF8(blob_info.type())); |
| blob_data->AppendFile( |
| blob_info.file_path(), 0, blob_info.size(), blob_info.last_modified()); |
| scoped_ptr<storage::BlobDataHandle> blob_data_handle( |
| blob_storage_context->AddFinishedBlob(blob_data.get())); |
| dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass()); |
| |
| return uuid; |
| } |
| |
| static bool CreateAllBlobs( |
| const std::vector<IndexedDBBlobInfo>& blob_info, |
| std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info, |
| scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) { |
| DCHECK_EQ(blob_info.size(), blob_or_file_info->size()); |
| size_t i; |
| if (!dispatcher_host->blob_storage_context()) |
| return false; |
| for (i = 0; i < blob_info.size(); ++i) { |
| (*blob_or_file_info)[i].uuid = |
| CreateBlobData(blob_info[i], |
| dispatcher_host, |
| dispatcher_host->blob_storage_context(), |
| dispatcher_host->Context()->TaskRunner()); |
| } |
| return true; |
| } |
| |
| template <class ParamType, class MsgType> |
| static void CreateBlobsAndSend( |
| ParamType* params, |
| scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, |
| const std::vector<IndexedDBBlobInfo>& blob_info, |
| std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host)) |
| dispatcher_host->Send(new MsgType(*params)); |
| } |
| |
| static void BlobLookupForCursorPrefetch( |
| IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params, |
| scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, |
| const std::vector<IndexedDBValue>& values) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DCHECK_EQ(values.size(), params->blob_or_file_infos.size()); |
| |
| std::vector<IndexedDBValue>::const_iterator value_iter; |
| std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >::iterator blob_iter; |
| for (value_iter = values.begin(), blob_iter = |
| params->blob_or_file_infos.begin(); value_iter != values.end(); |
| ++value_iter, ++blob_iter) { |
| if (!CreateAllBlobs(value_iter->blob_info, &*blob_iter, dispatcher_host)) |
| return; |
| } |
| dispatcher_host->Send( |
| new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params)); |
| } |
| |
| static void FillInBlobData( |
| const std::vector<IndexedDBBlobInfo>& blob_info, |
| std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) { |
| for (const auto& iter : blob_info) { |
| if (iter.is_file()) { |
| IndexedDBMsg_BlobOrFileInfo info; |
| info.is_file = true; |
| info.mime_type = iter.type(); |
| info.file_name = iter.file_name(); |
| info.file_path = iter.file_path().AsUTF16Unsafe(); |
| info.size = iter.size(); |
| info.last_modified = iter.last_modified().ToDoubleT(); |
| blob_or_file_info->push_back(info); |
| } else { |
| IndexedDBMsg_BlobOrFileInfo info; |
| info.mime_type = iter.type(); |
| info.size = iter.size(); |
| blob_or_file_info->push_back(info); |
| } |
| } |
| } |
| |
| void IndexedDBCallbacks::RegisterBlobsAndSend( |
| const std::vector<IndexedDBBlobInfo>& blob_info, |
| const base::Closure& callback) { |
| for (const auto& iter : blob_info) { |
| if (!iter.mark_used_callback().is_null()) |
| iter.mark_used_callback().Run(); |
| } |
| DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback); |
| } |
| |
| void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor, |
| const IndexedDBKey& key, |
| const IndexedDBKey& primary_key, |
| IndexedDBValue* 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| int32 ipc_object_id = dispatcher_host_->Add(cursor.get()); |
| scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params( |
| new IndexedDBMsg_CallbacksSuccessIDBCursor_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->bits); |
| // TODO(alecflett): Avoid a copy here: the whole params object is |
| // being copied into the message. |
| if (!value || value->blob_info.empty()) { |
| dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params)); |
| } else { |
| IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get(); |
| FillInBlobData(value->blob_info, &p->blob_or_file_info); |
| RegisterBlobsAndSend( |
| value->blob_info, |
| base::Bind( |
| CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params, |
| IndexedDBMsg_CallbacksSuccessIDBCursor>, |
| base::Owned(params.release()), |
| dispatcher_host_, |
| value->blob_info, |
| base::Unretained(&p->blob_or_file_info))); |
| } |
| dispatcher_host_ = NULL; |
| } |
| |
| void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key, |
| const IndexedDBKey& primary_key, |
| IndexedDBValue* 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| IndexedDBCursor* idb_cursor = |
| dispatcher_host_->GetCursorFromId(ipc_cursor_id_); |
| |
| DCHECK(idb_cursor); |
| if (!idb_cursor) |
| return; |
| |
| scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params( |
| new IndexedDBMsg_CallbacksSuccessCursorContinue_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->bits); |
| // TODO(alecflett): Avoid a copy here: the whole params object is |
| // being copied into the message. |
| if (!value || value->blob_info.empty()) { |
| dispatcher_host_->Send( |
| new IndexedDBMsg_CallbacksSuccessCursorContinue(*params)); |
| } else { |
| IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get(); |
| FillInBlobData(value->blob_info, &p->blob_or_file_info); |
| RegisterBlobsAndSend( |
| value->blob_info, |
| base::Bind(CreateBlobsAndSend< |
| IndexedDBMsg_CallbacksSuccessCursorContinue_Params, |
| IndexedDBMsg_CallbacksSuccessCursorContinue>, |
| base::Owned(params.release()), |
| dispatcher_host_, |
| value->blob_info, |
| base::Unretained(&p->blob_or_file_info))); |
| } |
| dispatcher_host_ = NULL; |
| } |
| |
| void IndexedDBCallbacks::OnSuccessWithPrefetch( |
| const std::vector<IndexedDBKey>& keys, |
| const std::vector<IndexedDBKey>& primary_keys, |
| std::vector<IndexedDBValue>* 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| 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]); |
| } |
| |
| scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params( |
| new IndexedDBMsg_CallbacksSuccessCursorPrefetch_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; |
| std::vector<std::string>& values_bits = params->values; |
| values_bits.resize(values->size()); |
| std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >& values_blob_infos = |
| params->blob_or_file_infos; |
| values_blob_infos.resize(values->size()); |
| |
| bool found_blob_info = false; |
| std::vector<IndexedDBValue>::iterator iter = values->begin(); |
| for (size_t i = 0; iter != values->end(); ++iter, ++i) { |
| values_bits[i].swap(iter->bits); |
| if (iter->blob_info.size()) { |
| found_blob_info = true; |
| FillInBlobData(iter->blob_info, &values_blob_infos[i]); |
| for (const auto& blob_iter : iter->blob_info) { |
| if (!blob_iter.mark_used_callback().is_null()) |
| blob_iter.mark_used_callback().Run(); |
| } |
| } |
| } |
| |
| if (found_blob_info) { |
| BrowserThread::PostTask(BrowserThread::IO, |
| FROM_HERE, |
| base::Bind(BlobLookupForCursorPrefetch, |
| base::Owned(params.release()), |
| dispatcher_host_, |
| *values)); |
| } else { |
| dispatcher_host_->Send( |
| new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get())); |
| } |
| dispatcher_host_ = NULL; |
| } |
| |
| void IndexedDBCallbacks::OnSuccess(IndexedDBValue* 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| scoped_ptr<IndexedDBMsg_CallbacksSuccessValueWithKey_Params> params( |
| new IndexedDBMsg_CallbacksSuccessValueWithKey_Params()); |
| params->ipc_thread_id = ipc_thread_id_; |
| params->ipc_callbacks_id = ipc_callbacks_id_; |
| params->primary_key = key; |
| params->key_path = key_path; |
| if (value && !value->empty()) |
| std::swap(params->value, value->bits); |
| if (!value || value->blob_info.empty()) { |
| dispatcher_host_->Send( |
| new IndexedDBMsg_CallbacksSuccessValueWithKey(*params)); |
| } else { |
| IndexedDBMsg_CallbacksSuccessValueWithKey_Params* p = params.get(); |
| FillInBlobData(value->blob_info, &p->blob_or_file_info); |
| RegisterBlobsAndSend( |
| value->blob_info, |
| base::Bind( |
| CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValueWithKey_Params, |
| IndexedDBMsg_CallbacksSuccessValueWithKey>, |
| base::Owned(params.release()), |
| dispatcher_host_, |
| value->blob_info, |
| base::Unretained(&p->blob_or_file_info))); |
| } |
| dispatcher_host_ = NULL; |
| } |
| |
| void IndexedDBCallbacks::OnSuccess(IndexedDBValue* 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| scoped_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params( |
| new IndexedDBMsg_CallbacksSuccessValue_Params()); |
| params->ipc_thread_id = ipc_thread_id_; |
| params->ipc_callbacks_id = ipc_callbacks_id_; |
| if (value && !value->empty()) |
| std::swap(params->value, value->bits); |
| if (!value || value->blob_info.empty()) { |
| dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params)); |
| } else { |
| IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get(); |
| FillInBlobData(value->blob_info, &p->blob_or_file_info); |
| RegisterBlobsAndSend( |
| value->blob_info, |
| base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params, |
| IndexedDBMsg_CallbacksSuccessValue>, |
| base::Owned(params.release()), |
| dispatcher_host_, |
| value->blob_info, |
| base::Unretained(&p->blob_or_file_info))); |
| } |
| 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| 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_); |
| DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); |
| |
| dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined( |
| ipc_thread_id_, ipc_callbacks_id_)); |
| dispatcher_host_ = NULL; |
| } |
| |
| void IndexedDBCallbacks::SetConnectionOpenStartTime( |
| const base::TimeTicks& start_time) { |
| connection_open_start_time_ = start_time; |
| } |
| |
| } // namespace content |