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