[IndexedDB] Adding traces, perf tests
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_callbacks.cc
blob16bb523757bcf8ae3f73fc19cd54942c03f4b05c
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"
7 #include <algorithm>
9 #include "base/metrics/histogram.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_return_value.h"
22 #include "content/browser/indexed_db/indexed_db_tracing.h"
23 #include "content/browser/indexed_db/indexed_db_value.h"
24 #include "content/common/indexed_db/indexed_db_constants.h"
25 #include "content/common/indexed_db/indexed_db_messages.h"
26 #include "storage/browser/blob/blob_storage_context.h"
27 #include "storage/browser/blob/shareable_file_reference.h"
28 #include "storage/browser/quota/quota_manager.h"
30 using storage::ShareableFileReference;
32 namespace content {
34 namespace {
35 const int32 kNoCursor = -1;
36 const int32 kNoDatabaseCallbacks = -1;
37 const int64 kNoTransaction = -1;
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) {
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) {
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) {
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_);
131 if (sent_blocked_)
132 return;
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(
154 int64 old_version,
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)
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));
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(
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;
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 base::TaskRunner* task_runner) {
227 if (!blob_info.uuid().empty()) {
228 // We're sending back a live blob, not a reference into our backing store.
229 return dispatcher_host->HoldBlobData(blob_info);
231 scoped_refptr<ShareableFileReference> shareable_file =
232 ShareableFileReference::Get(blob_info.file_path());
233 if (!shareable_file.get()) {
234 shareable_file = ShareableFileReference::GetOrCreate(
235 blob_info.file_path(),
236 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
237 task_runner);
238 if (!blob_info.release_callback().is_null())
239 shareable_file->AddFinalReleaseCallback(blob_info.release_callback());
241 return dispatcher_host->HoldBlobData(blob_info);
244 static bool CreateAllBlobs(
245 const std::vector<IndexedDBBlobInfo>& blob_info,
246 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info,
247 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) {
248 IDB_TRACE("IndexedDBCallbacks::CreateAllBlobs");
249 DCHECK_EQ(blob_info.size(), blob_or_file_info->size());
250 size_t i;
251 if (!dispatcher_host->blob_storage_context())
252 return false;
253 for (i = 0; i < blob_info.size(); ++i) {
254 (*blob_or_file_info)[i].uuid =
255 CreateBlobData(blob_info[i],
256 dispatcher_host,
257 dispatcher_host->Context()->TaskRunner());
259 return true;
262 template <class ParamType, class MsgType>
263 static void CreateBlobsAndSend(
264 ParamType* params,
265 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
266 const std::vector<IndexedDBBlobInfo>& blob_info,
267 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
268 DCHECK_CURRENTLY_ON(BrowserThread::IO);
269 if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
270 dispatcher_host->Send(new MsgType(*params));
273 static void BlobLookupForCursorPrefetch(
274 IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params,
275 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
276 const std::vector<IndexedDBValue>& values) {
277 DCHECK_CURRENTLY_ON(BrowserThread::IO);
278 DCHECK_EQ(values.size(), params->values.size());
280 for (size_t i = 0; i < values.size(); ++i) {
281 if (!CreateAllBlobs(values[i].blob_info,
282 &params->values[i].blob_or_file_info, dispatcher_host))
283 return;
286 dispatcher_host->Send(
287 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
290 static void BlobLookupForGetAll(
291 IndexedDBMsg_CallbacksSuccessArray_Params* params,
292 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
293 const std::vector<IndexedDBReturnValue>& values) {
294 DCHECK_CURRENTLY_ON(BrowserThread::IO);
295 DCHECK_EQ(values.size(), params->values.size());
297 for (size_t i = 0; i < values.size(); ++i) {
298 if (!CreateAllBlobs(values[i].blob_info,
299 &params->values[i].blob_or_file_info, dispatcher_host))
300 return;
303 dispatcher_host->Send(new IndexedDBMsg_CallbacksSuccessArray(*params));
306 static void FillInBlobData(
307 const std::vector<IndexedDBBlobInfo>& blob_info,
308 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
309 for (const auto& iter : blob_info) {
310 if (iter.is_file()) {
311 IndexedDBMsg_BlobOrFileInfo info;
312 info.is_file = true;
313 info.mime_type = iter.type();
314 info.file_name = iter.file_name();
315 info.file_path = iter.file_path().AsUTF16Unsafe();
316 info.size = iter.size();
317 info.last_modified = iter.last_modified().ToDoubleT();
318 blob_or_file_info->push_back(info);
319 } else {
320 IndexedDBMsg_BlobOrFileInfo info;
321 info.mime_type = iter.type();
322 info.size = iter.size();
323 blob_or_file_info->push_back(info);
328 void IndexedDBCallbacks::RegisterBlobsAndSend(
329 const std::vector<IndexedDBBlobInfo>& blob_info,
330 const base::Closure& callback) {
331 for (const auto& iter : blob_info) {
332 if (!iter.mark_used_callback().is_null())
333 iter.mark_used_callback().Run();
335 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
336 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
339 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
340 const IndexedDBKey& key,
341 const IndexedDBKey& primary_key,
342 IndexedDBValue* value) {
343 DCHECK(dispatcher_host_.get());
345 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
346 DCHECK_EQ(kNoTransaction, host_transaction_id_);
347 DCHECK_EQ(kNoDatabase, ipc_database_id_);
348 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
349 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
351 int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
352 scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
353 new IndexedDBMsg_CallbacksSuccessIDBCursor_Params());
354 params->ipc_thread_id = ipc_thread_id_;
355 params->ipc_callbacks_id = ipc_callbacks_id_;
356 params->ipc_cursor_id = ipc_object_id;
357 params->key = key;
358 params->primary_key = primary_key;
359 if (value && !value->empty())
360 std::swap(params->value.bits, value->bits);
361 // TODO(alecflett): Avoid a copy here: the whole params object is
362 // being copied into the message.
363 if (!value || value->blob_info.empty()) {
364 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
365 } else {
366 IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
367 FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
368 RegisterBlobsAndSend(
369 value->blob_info,
370 base::Bind(
371 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
372 IndexedDBMsg_CallbacksSuccessIDBCursor>,
373 base::Owned(params.release()), dispatcher_host_, value->blob_info,
374 base::Unretained(&p->value.blob_or_file_info)));
376 dispatcher_host_ = NULL;
379 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
380 const IndexedDBKey& primary_key,
381 IndexedDBValue* value) {
382 DCHECK(dispatcher_host_.get());
384 DCHECK_NE(kNoCursor, ipc_cursor_id_);
385 DCHECK_EQ(kNoTransaction, host_transaction_id_);
386 DCHECK_EQ(kNoDatabase, ipc_database_id_);
387 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
388 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
390 IndexedDBCursor* idb_cursor =
391 dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
393 DCHECK(idb_cursor);
394 if (!idb_cursor)
395 return;
397 scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params(
398 new IndexedDBMsg_CallbacksSuccessCursorContinue_Params());
399 params->ipc_thread_id = ipc_thread_id_;
400 params->ipc_callbacks_id = ipc_callbacks_id_;
401 params->ipc_cursor_id = ipc_cursor_id_;
402 params->key = key;
403 params->primary_key = primary_key;
404 if (value && !value->empty())
405 std::swap(params->value.bits, value->bits);
406 // TODO(alecflett): Avoid a copy here: the whole params object is
407 // being copied into the message.
408 if (!value || value->blob_info.empty()) {
409 dispatcher_host_->Send(
410 new IndexedDBMsg_CallbacksSuccessCursorContinue(*params));
411 } else {
412 IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get();
413 FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
414 RegisterBlobsAndSend(
415 value->blob_info,
416 base::Bind(CreateBlobsAndSend<
417 IndexedDBMsg_CallbacksSuccessCursorContinue_Params,
418 IndexedDBMsg_CallbacksSuccessCursorContinue>,
419 base::Owned(params.release()), dispatcher_host_,
420 value->blob_info,
421 base::Unretained(&p->value.blob_or_file_info)));
423 dispatcher_host_ = NULL;
426 void IndexedDBCallbacks::OnSuccessWithPrefetch(
427 const std::vector<IndexedDBKey>& keys,
428 const std::vector<IndexedDBKey>& primary_keys,
429 std::vector<IndexedDBValue>* values) {
430 DCHECK_EQ(keys.size(), primary_keys.size());
431 DCHECK_EQ(keys.size(), values->size());
433 DCHECK(dispatcher_host_.get());
435 DCHECK_NE(kNoCursor, ipc_cursor_id_);
436 DCHECK_EQ(kNoTransaction, host_transaction_id_);
437 DCHECK_EQ(kNoDatabase, ipc_database_id_);
438 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
439 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
441 std::vector<IndexedDBKey> msg_keys;
442 std::vector<IndexedDBKey> msg_primary_keys;
444 for (size_t i = 0; i < keys.size(); ++i) {
445 msg_keys.push_back(keys[i]);
446 msg_primary_keys.push_back(primary_keys[i]);
449 scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params(
450 new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params());
451 params->ipc_thread_id = ipc_thread_id_;
452 params->ipc_callbacks_id = ipc_callbacks_id_;
453 params->ipc_cursor_id = ipc_cursor_id_;
454 params->keys = msg_keys;
455 params->primary_keys = msg_primary_keys;
456 params->values.resize(values->size());
458 bool found_blob_info = false;
459 for (size_t i = 0; i < values->size(); ++i) {
460 params->values[i].bits.swap(values->at(i).bits);
461 if (!values->at(i).blob_info.empty()) {
462 found_blob_info = true;
463 FillInBlobData(values->at(i).blob_info,
464 &params->values[i].blob_or_file_info);
465 for (const auto& blob_iter : values->at(i).blob_info) {
466 if (!blob_iter.mark_used_callback().is_null())
467 blob_iter.mark_used_callback().Run();
472 if (found_blob_info) {
473 BrowserThread::PostTask(BrowserThread::IO,
474 FROM_HERE,
475 base::Bind(BlobLookupForCursorPrefetch,
476 base::Owned(params.release()),
477 dispatcher_host_,
478 *values));
479 } else {
480 dispatcher_host_->Send(
481 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
483 dispatcher_host_ = NULL;
486 void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
487 DCHECK(dispatcher_host_.get());
489 if (value && value->primary_key.IsValid()) {
490 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
491 } else {
492 DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
494 DCHECK_EQ(kNoTransaction, host_transaction_id_);
495 DCHECK_EQ(kNoDatabase, ipc_database_id_);
496 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
497 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
499 scoped_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(
500 new IndexedDBMsg_CallbacksSuccessValue_Params());
501 params->ipc_thread_id = ipc_thread_id_;
502 params->ipc_callbacks_id = ipc_callbacks_id_;
503 if (value && value->primary_key.IsValid()) {
504 params->value.primary_key = value->primary_key;
505 params->value.key_path = value->key_path;
507 if (value && !value->empty())
508 std::swap(params->value.bits, value->bits);
509 if (!value || value->blob_info.empty()) {
510 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params));
511 } else {
512 IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
513 FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
514 RegisterBlobsAndSend(
515 value->blob_info,
516 base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
517 IndexedDBMsg_CallbacksSuccessValue>,
518 base::Owned(params.release()), dispatcher_host_,
519 value->blob_info,
520 base::Unretained(&p->value.blob_or_file_info)));
522 dispatcher_host_ = NULL;
525 void IndexedDBCallbacks::OnSuccessArray(
526 std::vector<IndexedDBReturnValue>* values,
527 const IndexedDBKeyPath& key_path) {
528 DCHECK(dispatcher_host_.get());
530 DCHECK_EQ(kNoTransaction, host_transaction_id_);
531 DCHECK_EQ(kNoDatabase, ipc_database_id_);
532 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
533 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
535 scoped_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params(
536 new IndexedDBMsg_CallbacksSuccessArray_Params());
537 params->ipc_thread_id = ipc_thread_id_;
538 params->ipc_callbacks_id = ipc_callbacks_id_;
539 params->values.resize(values->size());
541 bool found_blob_info = false;
542 for (size_t i = 0; i < values->size(); ++i) {
543 IndexedDBMsg_ReturnValue& pvalue = params->values[i];
544 IndexedDBReturnValue& value = (*values)[i];
545 pvalue.bits.swap(value.bits);
546 if (!value.blob_info.empty()) {
547 found_blob_info = true;
548 FillInBlobData(value.blob_info, &pvalue.blob_or_file_info);
549 for (const auto& blob_info : value.blob_info) {
550 if (!blob_info.mark_used_callback().is_null())
551 blob_info.mark_used_callback().Run();
554 pvalue.primary_key = value.primary_key;
555 pvalue.key_path = key_path;
558 if (found_blob_info) {
559 BrowserThread::PostTask(
560 BrowserThread::IO, FROM_HERE,
561 base::Bind(BlobLookupForGetAll, base::Owned(params.release()),
562 dispatcher_host_, *values));
563 } else {
564 dispatcher_host_->Send(
565 new IndexedDBMsg_CallbacksSuccessArray(*params.get()));
567 dispatcher_host_ = NULL;
570 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
571 DCHECK(dispatcher_host_.get());
573 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
574 DCHECK_EQ(kNoTransaction, host_transaction_id_);
575 DCHECK_EQ(kNoDatabase, ipc_database_id_);
576 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
577 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
579 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
580 ipc_thread_id_, ipc_callbacks_id_, value));
581 dispatcher_host_ = NULL;
584 void IndexedDBCallbacks::OnSuccess(int64 value) {
585 DCHECK(dispatcher_host_.get());
587 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
588 DCHECK_EQ(kNoTransaction, host_transaction_id_);
589 DCHECK_EQ(kNoDatabase, ipc_database_id_);
590 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
591 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
593 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
594 ipc_thread_id_, ipc_callbacks_id_, value));
595 dispatcher_host_ = NULL;
598 void IndexedDBCallbacks::OnSuccess() {
599 DCHECK(dispatcher_host_.get());
601 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
602 DCHECK_EQ(kNoTransaction, host_transaction_id_);
603 DCHECK_EQ(kNoDatabase, ipc_database_id_);
604 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
605 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
607 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
608 ipc_thread_id_, ipc_callbacks_id_));
609 dispatcher_host_ = NULL;
612 void IndexedDBCallbacks::SetConnectionOpenStartTime(
613 const base::TimeTicks& start_time) {
614 connection_open_start_time_ = start_time;
617 } // namespace content