1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/indexed_db/indexed_db_callbacks.h" 6 7 #include <algorithm> 8 9 #include "base/guid.h" 10 #include "base/metrics/histogram.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/time/time.h" 13 #include "content/browser/child_process_security_policy_impl.h" 14 #include "content/browser/fileapi/fileapi_message_filter.h" 15 #include "content/browser/indexed_db/indexed_db_blob_info.h" 16 #include "content/browser/indexed_db/indexed_db_connection.h" 17 #include "content/browser/indexed_db/indexed_db_context_impl.h" 18 #include "content/browser/indexed_db/indexed_db_cursor.h" 19 #include "content/browser/indexed_db/indexed_db_database_callbacks.h" 20 #include "content/browser/indexed_db/indexed_db_database_error.h" 21 #include "content/browser/indexed_db/indexed_db_metadata.h" 22 #include "content/browser/indexed_db/indexed_db_value.h" 23 #include "content/common/indexed_db/indexed_db_constants.h" 24 #include "content/common/indexed_db/indexed_db_messages.h" 25 #include "storage/browser/blob/blob_storage_context.h" 26 #include "storage/browser/quota/quota_manager.h" 27 #include "storage/common/blob/blob_data.h" 28 #include "storage/common/blob/shareable_file_reference.h" 29 30 using storage::ShareableFileReference; 31 32 namespace content { 33 34 namespace { 35 const int32 kNoCursor = -1; 36 const int32 kNoDatabaseCallbacks = -1; 37 const int64 kNoTransaction = -1; 38 } 39 40 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, 41 int32 ipc_thread_id, 42 int32 ipc_callbacks_id) 43 : dispatcher_host_(dispatcher_host), 44 ipc_callbacks_id_(ipc_callbacks_id), 45 ipc_thread_id_(ipc_thread_id), 46 ipc_cursor_id_(kNoCursor), 47 host_transaction_id_(kNoTransaction), 48 ipc_database_id_(kNoDatabase), 49 ipc_database_callbacks_id_(kNoDatabaseCallbacks), 50 data_loss_(blink::WebIDBDataLossNone), 51 sent_blocked_(false) { 52 } 53 54 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, 55 int32 ipc_thread_id, 56 int32 ipc_callbacks_id, 57 int32 ipc_cursor_id) 58 : dispatcher_host_(dispatcher_host), 59 ipc_callbacks_id_(ipc_callbacks_id), 60 ipc_thread_id_(ipc_thread_id), 61 ipc_cursor_id_(ipc_cursor_id), 62 host_transaction_id_(kNoTransaction), 63 ipc_database_id_(kNoDatabase), 64 ipc_database_callbacks_id_(kNoDatabaseCallbacks), 65 data_loss_(blink::WebIDBDataLossNone), 66 sent_blocked_(false) { 67 } 68 69 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, 70 int32 ipc_thread_id, 71 int32 ipc_callbacks_id, 72 int32 ipc_database_callbacks_id, 73 int64 host_transaction_id, 74 const GURL& origin_url) 75 : dispatcher_host_(dispatcher_host), 76 ipc_callbacks_id_(ipc_callbacks_id), 77 ipc_thread_id_(ipc_thread_id), 78 ipc_cursor_id_(kNoCursor), 79 host_transaction_id_(host_transaction_id), 80 origin_url_(origin_url), 81 ipc_database_id_(kNoDatabase), 82 ipc_database_callbacks_id_(ipc_database_callbacks_id), 83 data_loss_(blink::WebIDBDataLossNone), 84 sent_blocked_(false) { 85 } 86 87 IndexedDBCallbacks::~IndexedDBCallbacks() {} 88 89 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) { 90 DCHECK(dispatcher_host_.get()); 91 92 dispatcher_host_->Send(new IndexedDBMsg_CallbacksError( 93 ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message())); 94 dispatcher_host_ = NULL; 95 96 if (!connection_open_start_time_.is_null()) { 97 UMA_HISTOGRAM_MEDIUM_TIMES( 98 "WebCore.IndexedDB.OpenTime.Error", 99 base::TimeTicks::Now() - connection_open_start_time_); 100 connection_open_start_time_ = base::TimeTicks(); 101 } 102 } 103 104 void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) { 105 DCHECK(dispatcher_host_.get()); 106 107 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 108 DCHECK_EQ(kNoTransaction, host_transaction_id_); 109 DCHECK_EQ(kNoDatabase, ipc_database_id_); 110 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 111 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 112 113 std::vector<base::string16> list; 114 for (unsigned i = 0; i < value.size(); ++i) 115 list.push_back(value[i]); 116 117 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList( 118 ipc_thread_id_, ipc_callbacks_id_, list)); 119 dispatcher_host_ = NULL; 120 } 121 122 void IndexedDBCallbacks::OnBlocked(int64 existing_version) { 123 DCHECK(dispatcher_host_.get()); 124 125 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 126 // No transaction/db callbacks for DeleteDatabase. 127 DCHECK_EQ(kNoTransaction == host_transaction_id_, 128 kNoDatabaseCallbacks == ipc_database_callbacks_id_); 129 DCHECK_EQ(kNoDatabase, ipc_database_id_); 130 131 if (sent_blocked_) 132 return; 133 134 sent_blocked_ = true; 135 dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked( 136 ipc_thread_id_, ipc_callbacks_id_, existing_version)); 137 138 if (!connection_open_start_time_.is_null()) { 139 UMA_HISTOGRAM_MEDIUM_TIMES( 140 "WebCore.IndexedDB.OpenTime.Blocked", 141 base::TimeTicks::Now() - connection_open_start_time_); 142 connection_open_start_time_ = base::TimeTicks(); 143 } 144 } 145 146 void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss, 147 std::string data_loss_message) { 148 DCHECK_NE(blink::WebIDBDataLossNone, data_loss); 149 data_loss_ = data_loss; 150 data_loss_message_ = data_loss_message; 151 } 152 153 void IndexedDBCallbacks::OnUpgradeNeeded( 154 int64 old_version, 155 scoped_ptr<IndexedDBConnection> connection, 156 const IndexedDBDatabaseMetadata& metadata) { 157 DCHECK(dispatcher_host_.get()); 158 159 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 160 DCHECK_NE(kNoTransaction, host_transaction_id_); 161 DCHECK_EQ(kNoDatabase, ipc_database_id_); 162 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 163 164 dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_url_); 165 int32 ipc_database_id = 166 dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_url_); 167 if (ipc_database_id < 0) 168 return; 169 ipc_database_id_ = ipc_database_id; 170 IndexedDBMsg_CallbacksUpgradeNeeded_Params params; 171 params.ipc_thread_id = ipc_thread_id_; 172 params.ipc_callbacks_id = ipc_callbacks_id_; 173 params.ipc_database_id = ipc_database_id; 174 params.ipc_database_callbacks_id = ipc_database_callbacks_id_; 175 params.old_version = old_version; 176 params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata); 177 params.data_loss = data_loss_; 178 params.data_loss_message = data_loss_message_; 179 dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params)); 180 181 if (!connection_open_start_time_.is_null()) { 182 UMA_HISTOGRAM_MEDIUM_TIMES( 183 "WebCore.IndexedDB.OpenTime.UpgradeNeeded", 184 base::TimeTicks::Now() - connection_open_start_time_); 185 connection_open_start_time_ = base::TimeTicks(); 186 } 187 } 188 189 void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection, 190 const IndexedDBDatabaseMetadata& metadata) { 191 DCHECK(dispatcher_host_.get()); 192 193 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 194 DCHECK_NE(kNoTransaction, host_transaction_id_); 195 DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection); 196 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 197 198 scoped_refptr<IndexedDBCallbacks> self(this); 199 200 int32 ipc_object_id = kNoDatabase; 201 // Only register if the connection was not previously sent in OnUpgradeNeeded. 202 if (ipc_database_id_ == kNoDatabase) { 203 ipc_object_id = dispatcher_host_->Add( 204 connection.release(), ipc_thread_id_, origin_url_); 205 } 206 207 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase( 208 ipc_thread_id_, 209 ipc_callbacks_id_, 210 ipc_database_callbacks_id_, 211 ipc_object_id, 212 IndexedDBDispatcherHost::ConvertMetadata(metadata))); 213 dispatcher_host_ = NULL; 214 215 if (!connection_open_start_time_.is_null()) { 216 UMA_HISTOGRAM_MEDIUM_TIMES( 217 "WebCore.IndexedDB.OpenTime.Success", 218 base::TimeTicks::Now() - connection_open_start_time_); 219 connection_open_start_time_ = base::TimeTicks(); 220 } 221 } 222 223 static std::string CreateBlobData( 224 const IndexedDBBlobInfo& blob_info, 225 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, 226 storage::BlobStorageContext* blob_storage_context, 227 base::TaskRunner* task_runner) { 228 std::string uuid = blob_info.uuid(); 229 if (!uuid.empty()) { 230 // We're sending back a live blob, not a reference into our backing store. 231 scoped_ptr<storage::BlobDataHandle> blob_data_handle( 232 blob_storage_context->GetBlobDataFromUUID(uuid)); 233 dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass()); 234 return uuid; 235 } 236 scoped_refptr<ShareableFileReference> shareable_file = 237 ShareableFileReference::Get(blob_info.file_path()); 238 if (!shareable_file.get()) { 239 shareable_file = ShareableFileReference::GetOrCreate( 240 blob_info.file_path(), 241 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, 242 task_runner); 243 if (!blob_info.release_callback().is_null()) 244 shareable_file->AddFinalReleaseCallback(blob_info.release_callback()); 245 } 246 247 uuid = base::GenerateGUID(); 248 scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid); 249 blob_data->set_content_type(base::UTF16ToUTF8(blob_info.type())); 250 blob_data->AppendFile( 251 blob_info.file_path(), 0, blob_info.size(), blob_info.last_modified()); 252 scoped_ptr<storage::BlobDataHandle> blob_data_handle( 253 blob_storage_context->AddFinishedBlob(blob_data.get())); 254 dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass()); 255 256 return uuid; 257 } 258 259 static bool CreateAllBlobs( 260 const std::vector<IndexedDBBlobInfo>& blob_info, 261 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info, 262 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) { 263 DCHECK_EQ(blob_info.size(), blob_or_file_info->size()); 264 size_t i; 265 if (!dispatcher_host->blob_storage_context()) 266 return false; 267 for (i = 0; i < blob_info.size(); ++i) { 268 (*blob_or_file_info)[i].uuid = 269 CreateBlobData(blob_info[i], 270 dispatcher_host, 271 dispatcher_host->blob_storage_context(), 272 dispatcher_host->Context()->TaskRunner()); 273 } 274 return true; 275 } 276 277 template <class ParamType, class MsgType> 278 static void CreateBlobsAndSend( 279 ParamType* params, 280 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, 281 const std::vector<IndexedDBBlobInfo>& blob_info, 282 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) { 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 284 if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host)) 285 dispatcher_host->Send(new MsgType(*params)); 286 } 287 288 static void BlobLookupForCursorPrefetch( 289 IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params, 290 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, 291 const std::vector<IndexedDBValue>& values) { 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 293 DCHECK_EQ(values.size(), params->blob_or_file_infos.size()); 294 295 std::vector<IndexedDBValue>::const_iterator value_iter; 296 std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >::iterator blob_iter; 297 for (value_iter = values.begin(), blob_iter = 298 params->blob_or_file_infos.begin(); value_iter != values.end(); 299 ++value_iter, ++blob_iter) { 300 if (!CreateAllBlobs(value_iter->blob_info, &*blob_iter, dispatcher_host)) 301 return; 302 } 303 dispatcher_host->Send( 304 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params)); 305 } 306 307 static void FillInBlobData( 308 const std::vector<IndexedDBBlobInfo>& blob_info, 309 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) { 310 for (std::vector<IndexedDBBlobInfo>::const_iterator iter = blob_info.begin(); 311 iter != blob_info.end(); 312 ++iter) { 313 if (iter->is_file()) { 314 IndexedDBMsg_BlobOrFileInfo info; 315 info.is_file = true; 316 info.mime_type = iter->type(); 317 info.file_name = iter->file_name(); 318 info.file_path = iter->file_path().AsUTF16Unsafe(); 319 info.size = iter->size(); 320 info.last_modified = iter->last_modified().ToDoubleT(); 321 blob_or_file_info->push_back(info); 322 } else { 323 IndexedDBMsg_BlobOrFileInfo info; 324 info.mime_type = iter->type(); 325 info.size = iter->size(); 326 blob_or_file_info->push_back(info); 327 } 328 } 329 } 330 331 void IndexedDBCallbacks::RegisterBlobsAndSend( 332 const std::vector<IndexedDBBlobInfo>& blob_info, 333 const base::Closure& callback) { 334 std::vector<IndexedDBBlobInfo>::const_iterator iter; 335 for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) { 336 if (!iter->mark_used_callback().is_null()) 337 iter->mark_used_callback().Run(); 338 } 339 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); 340 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback); 341 } 342 343 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor, 344 const IndexedDBKey& key, 345 const IndexedDBKey& primary_key, 346 IndexedDBValue* value) { 347 DCHECK(dispatcher_host_.get()); 348 349 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 350 DCHECK_EQ(kNoTransaction, host_transaction_id_); 351 DCHECK_EQ(kNoDatabase, ipc_database_id_); 352 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 353 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 354 355 int32 ipc_object_id = dispatcher_host_->Add(cursor.get()); 356 scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params( 357 new IndexedDBMsg_CallbacksSuccessIDBCursor_Params()); 358 params->ipc_thread_id = ipc_thread_id_; 359 params->ipc_callbacks_id = ipc_callbacks_id_; 360 params->ipc_cursor_id = ipc_object_id; 361 params->key = key; 362 params->primary_key = primary_key; 363 if (value && !value->empty()) 364 std::swap(params->value, value->bits); 365 // TODO(alecflett): Avoid a copy here: the whole params object is 366 // being copied into the message. 367 if (!value || value->blob_info.empty()) { 368 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params)); 369 } else { 370 IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get(); 371 FillInBlobData(value->blob_info, &p->blob_or_file_info); 372 RegisterBlobsAndSend( 373 value->blob_info, 374 base::Bind( 375 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params, 376 IndexedDBMsg_CallbacksSuccessIDBCursor>, 377 base::Owned(params.release()), 378 dispatcher_host_, 379 value->blob_info, 380 base::Unretained(&p->blob_or_file_info))); 381 } 382 dispatcher_host_ = NULL; 383 } 384 385 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key, 386 const IndexedDBKey& primary_key, 387 IndexedDBValue* value) { 388 DCHECK(dispatcher_host_.get()); 389 390 DCHECK_NE(kNoCursor, ipc_cursor_id_); 391 DCHECK_EQ(kNoTransaction, host_transaction_id_); 392 DCHECK_EQ(kNoDatabase, ipc_database_id_); 393 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 394 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 395 396 IndexedDBCursor* idb_cursor = 397 dispatcher_host_->GetCursorFromId(ipc_cursor_id_); 398 399 DCHECK(idb_cursor); 400 if (!idb_cursor) 401 return; 402 403 scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params( 404 new IndexedDBMsg_CallbacksSuccessCursorContinue_Params()); 405 params->ipc_thread_id = ipc_thread_id_; 406 params->ipc_callbacks_id = ipc_callbacks_id_; 407 params->ipc_cursor_id = ipc_cursor_id_; 408 params->key = key; 409 params->primary_key = primary_key; 410 if (value && !value->empty()) 411 std::swap(params->value, value->bits); 412 // TODO(alecflett): Avoid a copy here: the whole params object is 413 // being copied into the message. 414 if (!value || value->blob_info.empty()) { 415 dispatcher_host_->Send( 416 new IndexedDBMsg_CallbacksSuccessCursorContinue(*params)); 417 } else { 418 IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get(); 419 FillInBlobData(value->blob_info, &p->blob_or_file_info); 420 RegisterBlobsAndSend( 421 value->blob_info, 422 base::Bind(CreateBlobsAndSend< 423 IndexedDBMsg_CallbacksSuccessCursorContinue_Params, 424 IndexedDBMsg_CallbacksSuccessCursorContinue>, 425 base::Owned(params.release()), 426 dispatcher_host_, 427 value->blob_info, 428 base::Unretained(&p->blob_or_file_info))); 429 } 430 dispatcher_host_ = NULL; 431 } 432 433 void IndexedDBCallbacks::OnSuccessWithPrefetch( 434 const std::vector<IndexedDBKey>& keys, 435 const std::vector<IndexedDBKey>& primary_keys, 436 std::vector<IndexedDBValue>* values) { 437 DCHECK_EQ(keys.size(), primary_keys.size()); 438 DCHECK_EQ(keys.size(), values->size()); 439 440 DCHECK(dispatcher_host_.get()); 441 442 DCHECK_NE(kNoCursor, ipc_cursor_id_); 443 DCHECK_EQ(kNoTransaction, host_transaction_id_); 444 DCHECK_EQ(kNoDatabase, ipc_database_id_); 445 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 446 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 447 448 std::vector<IndexedDBKey> msgKeys; 449 std::vector<IndexedDBKey> msgPrimaryKeys; 450 451 for (size_t i = 0; i < keys.size(); ++i) { 452 msgKeys.push_back(keys[i]); 453 msgPrimaryKeys.push_back(primary_keys[i]); 454 } 455 456 scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params( 457 new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params()); 458 params->ipc_thread_id = ipc_thread_id_; 459 params->ipc_callbacks_id = ipc_callbacks_id_; 460 params->ipc_cursor_id = ipc_cursor_id_; 461 params->keys = msgKeys; 462 params->primary_keys = msgPrimaryKeys; 463 std::vector<std::string>& values_bits = params->values; 464 values_bits.resize(values->size()); 465 std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >& values_blob_infos = 466 params->blob_or_file_infos; 467 values_blob_infos.resize(values->size()); 468 469 bool found_blob_info = false; 470 std::vector<IndexedDBValue>::iterator iter = values->begin(); 471 for (size_t i = 0; iter != values->end(); ++iter, ++i) { 472 values_bits[i].swap(iter->bits); 473 if (iter->blob_info.size()) { 474 found_blob_info = true; 475 FillInBlobData(iter->blob_info, &values_blob_infos[i]); 476 std::vector<IndexedDBBlobInfo>::const_iterator blob_iter; 477 for (blob_iter = iter->blob_info.begin(); 478 blob_iter != iter->blob_info.end(); 479 ++blob_iter) { 480 if (!blob_iter->mark_used_callback().is_null()) 481 blob_iter->mark_used_callback().Run(); 482 } 483 } 484 } 485 486 if (found_blob_info) { 487 BrowserThread::PostTask(BrowserThread::IO, 488 FROM_HERE, 489 base::Bind(BlobLookupForCursorPrefetch, 490 base::Owned(params.release()), 491 dispatcher_host_, 492 *values)); 493 } else { 494 dispatcher_host_->Send( 495 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get())); 496 } 497 dispatcher_host_ = NULL; 498 } 499 500 void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value, 501 const IndexedDBKey& key, 502 const IndexedDBKeyPath& key_path) { 503 DCHECK(dispatcher_host_.get()); 504 505 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 506 DCHECK_EQ(kNoTransaction, host_transaction_id_); 507 DCHECK_EQ(kNoDatabase, ipc_database_id_); 508 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 509 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 510 511 scoped_ptr<IndexedDBMsg_CallbacksSuccessValueWithKey_Params> params( 512 new IndexedDBMsg_CallbacksSuccessValueWithKey_Params()); 513 params->ipc_thread_id = ipc_thread_id_; 514 params->ipc_callbacks_id = ipc_callbacks_id_; 515 params->primary_key = key; 516 params->key_path = key_path; 517 if (value && !value->empty()) 518 std::swap(params->value, value->bits); 519 if (!value || value->blob_info.empty()) { 520 dispatcher_host_->Send( 521 new IndexedDBMsg_CallbacksSuccessValueWithKey(*params)); 522 } else { 523 IndexedDBMsg_CallbacksSuccessValueWithKey_Params* p = params.get(); 524 FillInBlobData(value->blob_info, &p->blob_or_file_info); 525 RegisterBlobsAndSend( 526 value->blob_info, 527 base::Bind( 528 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValueWithKey_Params, 529 IndexedDBMsg_CallbacksSuccessValueWithKey>, 530 base::Owned(params.release()), 531 dispatcher_host_, 532 value->blob_info, 533 base::Unretained(&p->blob_or_file_info))); 534 } 535 dispatcher_host_ = NULL; 536 } 537 538 void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value) { 539 DCHECK(dispatcher_host_.get()); 540 DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL); 541 DCHECK_EQ(kNoTransaction, host_transaction_id_); 542 DCHECK_EQ(kNoDatabase, ipc_database_id_); 543 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 544 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 545 546 scoped_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params( 547 new IndexedDBMsg_CallbacksSuccessValue_Params()); 548 params->ipc_thread_id = ipc_thread_id_; 549 params->ipc_callbacks_id = ipc_callbacks_id_; 550 if (value && !value->empty()) 551 std::swap(params->value, value->bits); 552 if (!value || value->blob_info.empty()) { 553 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params)); 554 } else { 555 IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get(); 556 FillInBlobData(value->blob_info, &p->blob_or_file_info); 557 RegisterBlobsAndSend( 558 value->blob_info, 559 base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params, 560 IndexedDBMsg_CallbacksSuccessValue>, 561 base::Owned(params.release()), 562 dispatcher_host_, 563 value->blob_info, 564 base::Unretained(&p->blob_or_file_info))); 565 } 566 dispatcher_host_ = NULL; 567 } 568 569 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) { 570 DCHECK(dispatcher_host_.get()); 571 572 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 573 DCHECK_EQ(kNoTransaction, host_transaction_id_); 574 DCHECK_EQ(kNoDatabase, ipc_database_id_); 575 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 576 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 577 578 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey( 579 ipc_thread_id_, ipc_callbacks_id_, value)); 580 dispatcher_host_ = NULL; 581 } 582 583 void IndexedDBCallbacks::OnSuccess(int64 value) { 584 DCHECK(dispatcher_host_.get()); 585 586 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 587 DCHECK_EQ(kNoTransaction, host_transaction_id_); 588 DCHECK_EQ(kNoDatabase, ipc_database_id_); 589 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 590 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 591 592 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger( 593 ipc_thread_id_, ipc_callbacks_id_, value)); 594 dispatcher_host_ = NULL; 595 } 596 597 void IndexedDBCallbacks::OnSuccess() { 598 DCHECK(dispatcher_host_.get()); 599 600 DCHECK_EQ(kNoCursor, ipc_cursor_id_); 601 DCHECK_EQ(kNoTransaction, host_transaction_id_); 602 DCHECK_EQ(kNoDatabase, ipc_database_id_); 603 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); 604 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); 605 606 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined( 607 ipc_thread_id_, ipc_callbacks_id_)); 608 dispatcher_host_ = NULL; 609 } 610 611 void IndexedDBCallbacks::SetConnectionOpenStartTime( 612 const base::TimeTicks& start_time) { 613 connection_open_start_time_ = start_time; 614 } 615 616 } // namespace content 617