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.
5 #include "content/browser/indexed_db/indexed_db_callbacks.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"
30 using storage::ShareableFileReference;
35 const int32 kNoCursor = -1;
36 const int32 kNoDatabaseCallbacks = -1;
37 const int64 kNoTransaction = -1;
40 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
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) {
54 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
56 int32 ipc_callbacks_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) {
69 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
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) {
87 IndexedDBCallbacks::~IndexedDBCallbacks() {}
89 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
90 DCHECK(dispatcher_host_.get());
92 dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
93 ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
94 dispatcher_host_ = NULL;
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();
104 void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
105 DCHECK(dispatcher_host_.get());
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_);
113 std::vector<base::string16> list;
114 for (unsigned i = 0; i < value.size(); ++i)
115 list.push_back(value[i]);
117 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
118 ipc_thread_id_, ipc_callbacks_id_, list));
119 dispatcher_host_ = NULL;
122 void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
123 DCHECK(dispatcher_host_.get());
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_);
134 sent_blocked_ = true;
135 dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
136 ipc_thread_id_, ipc_callbacks_id_, existing_version));
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();
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;
153 void IndexedDBCallbacks::OnUpgradeNeeded(
155 scoped_ptr<IndexedDBConnection> connection,
156 const IndexedDBDatabaseMetadata& metadata) {
157 DCHECK(dispatcher_host_.get());
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_);
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)
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));
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();
189 void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
190 const IndexedDBDatabaseMetadata& metadata) {
191 DCHECK(dispatcher_host_.get());
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_);
198 scoped_refptr<IndexedDBCallbacks> self(this);
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_);
207 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
210 ipc_database_callbacks_id_,
212 IndexedDBDispatcherHost::ConvertMetadata(metadata)));
213 dispatcher_host_ = NULL;
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();
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();
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());
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,
243 if (!blob_info.release_callback().is_null())
244 shareable_file->AddFinalReleaseCallback(blob_info.release_callback());
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());
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());
265 if (!dispatcher_host->blob_storage_context())
267 for (i = 0; i < blob_info.size(); ++i) {
268 (*blob_or_file_info)[i].uuid =
269 CreateBlobData(blob_info[i],
271 dispatcher_host->blob_storage_context(),
272 dispatcher_host->Context()->TaskRunner());
277 template <class ParamType, class MsgType>
278 static void CreateBlobsAndSend(
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));
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());
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))
303 dispatcher_host->Send(
304 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
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();
313 if (iter->is_file()) {
314 IndexedDBMsg_BlobOrFileInfo info;
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);
323 IndexedDBMsg_BlobOrFileInfo info;
324 info.mime_type = iter->type();
325 info.size = iter->size();
326 blob_or_file_info->push_back(info);
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();
339 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
340 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
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());
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_);
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;
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));
370 IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
371 FillInBlobData(value->blob_info, &p->blob_or_file_info);
372 RegisterBlobsAndSend(
375 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
376 IndexedDBMsg_CallbacksSuccessIDBCursor>,
377 base::Owned(params.release()),
380 base::Unretained(&p->blob_or_file_info)));
382 dispatcher_host_ = NULL;
385 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
386 const IndexedDBKey& primary_key,
387 IndexedDBValue* value) {
388 DCHECK(dispatcher_host_.get());
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_);
396 IndexedDBCursor* idb_cursor =
397 dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
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_;
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));
418 IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get();
419 FillInBlobData(value->blob_info, &p->blob_or_file_info);
420 RegisterBlobsAndSend(
422 base::Bind(CreateBlobsAndSend<
423 IndexedDBMsg_CallbacksSuccessCursorContinue_Params,
424 IndexedDBMsg_CallbacksSuccessCursorContinue>,
425 base::Owned(params.release()),
428 base::Unretained(&p->blob_or_file_info)));
430 dispatcher_host_ = NULL;
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());
440 DCHECK(dispatcher_host_.get());
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_);
448 std::vector<IndexedDBKey> msgKeys;
449 std::vector<IndexedDBKey> msgPrimaryKeys;
451 for (size_t i = 0; i < keys.size(); ++i) {
452 msgKeys.push_back(keys[i]);
453 msgPrimaryKeys.push_back(primary_keys[i]);
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());
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();
480 if (!blob_iter->mark_used_callback().is_null())
481 blob_iter->mark_used_callback().Run();
486 if (found_blob_info) {
487 BrowserThread::PostTask(BrowserThread::IO,
489 base::Bind(BlobLookupForCursorPrefetch,
490 base::Owned(params.release()),
494 dispatcher_host_->Send(
495 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
497 dispatcher_host_ = NULL;
500 void IndexedDBCallbacks::OnSuccess(IndexedDBValue* value,
501 const IndexedDBKey& key,
502 const IndexedDBKeyPath& key_path) {
503 DCHECK(dispatcher_host_.get());
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_);
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));
523 IndexedDBMsg_CallbacksSuccessValueWithKey_Params* p = params.get();
524 FillInBlobData(value->blob_info, &p->blob_or_file_info);
525 RegisterBlobsAndSend(
528 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValueWithKey_Params,
529 IndexedDBMsg_CallbacksSuccessValueWithKey>,
530 base::Owned(params.release()),
533 base::Unretained(&p->blob_or_file_info)));
535 dispatcher_host_ = NULL;
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_);
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));
555 IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
556 FillInBlobData(value->blob_info, &p->blob_or_file_info);
557 RegisterBlobsAndSend(
559 base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
560 IndexedDBMsg_CallbacksSuccessValue>,
561 base::Owned(params.release()),
564 base::Unretained(&p->blob_or_file_info)));
566 dispatcher_host_ = NULL;
569 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
570 DCHECK(dispatcher_host_.get());
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_);
578 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
579 ipc_thread_id_, ipc_callbacks_id_, value));
580 dispatcher_host_ = NULL;
583 void IndexedDBCallbacks::OnSuccess(int64 value) {
584 DCHECK(dispatcher_host_.get());
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_);
592 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
593 ipc_thread_id_, ipc_callbacks_id_, value));
594 dispatcher_host_ = NULL;
597 void IndexedDBCallbacks::OnSuccess() {
598 DCHECK(dispatcher_host_.get());
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_);
606 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
607 ipc_thread_id_, ipc_callbacks_id_));
608 dispatcher_host_ = NULL;
611 void IndexedDBCallbacks::SetConnectionOpenStartTime(
612 const base::TimeTicks& start_time) {
613 connection_open_start_time_ = start_time;
616 } // namespace content