Add ICU message format support
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_callbacks.cc
blobbfd0a8a0d06b3bc7db64fc04f4e230870067a429
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_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/blob/shareable_file_reference.h"
27 #include "storage/browser/quota/quota_manager.h"
29 using storage::ShareableFileReference;
31 namespace content {
33 namespace {
34 const int32 kNoCursor = -1;
35 const int32 kNoDatabaseCallbacks = -1;
36 const int64 kNoTransaction = -1;
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 sent_blocked_(false) {
53 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
54 int32 ipc_thread_id,
55 int32 ipc_callbacks_id,
56 int32 ipc_cursor_id)
57 : dispatcher_host_(dispatcher_host),
58 ipc_callbacks_id_(ipc_callbacks_id),
59 ipc_thread_id_(ipc_thread_id),
60 ipc_cursor_id_(ipc_cursor_id),
61 host_transaction_id_(kNoTransaction),
62 ipc_database_id_(kNoDatabase),
63 ipc_database_callbacks_id_(kNoDatabaseCallbacks),
64 data_loss_(blink::WebIDBDataLossNone),
65 sent_blocked_(false) {
68 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
69 int32 ipc_thread_id,
70 int32 ipc_callbacks_id,
71 int32 ipc_database_callbacks_id,
72 int64 host_transaction_id,
73 const GURL& origin_url)
74 : dispatcher_host_(dispatcher_host),
75 ipc_callbacks_id_(ipc_callbacks_id),
76 ipc_thread_id_(ipc_thread_id),
77 ipc_cursor_id_(kNoCursor),
78 host_transaction_id_(host_transaction_id),
79 origin_url_(origin_url),
80 ipc_database_id_(kNoDatabase),
81 ipc_database_callbacks_id_(ipc_database_callbacks_id),
82 data_loss_(blink::WebIDBDataLossNone),
83 sent_blocked_(false) {
86 IndexedDBCallbacks::~IndexedDBCallbacks() {}
88 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
89 DCHECK(dispatcher_host_.get());
91 dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
92 ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
93 dispatcher_host_ = NULL;
95 if (!connection_open_start_time_.is_null()) {
96 UMA_HISTOGRAM_MEDIUM_TIMES(
97 "WebCore.IndexedDB.OpenTime.Error",
98 base::TimeTicks::Now() - connection_open_start_time_);
99 connection_open_start_time_ = base::TimeTicks();
103 void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
104 DCHECK(dispatcher_host_.get());
106 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
107 DCHECK_EQ(kNoTransaction, host_transaction_id_);
108 DCHECK_EQ(kNoDatabase, ipc_database_id_);
109 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
110 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
112 std::vector<base::string16> list;
113 for (unsigned i = 0; i < value.size(); ++i)
114 list.push_back(value[i]);
116 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
117 ipc_thread_id_, ipc_callbacks_id_, list));
118 dispatcher_host_ = NULL;
121 void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
122 DCHECK(dispatcher_host_.get());
124 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
125 // No transaction/db callbacks for DeleteDatabase.
126 DCHECK_EQ(kNoTransaction == host_transaction_id_,
127 kNoDatabaseCallbacks == ipc_database_callbacks_id_);
128 DCHECK_EQ(kNoDatabase, ipc_database_id_);
130 if (sent_blocked_)
131 return;
133 sent_blocked_ = true;
134 dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
135 ipc_thread_id_, ipc_callbacks_id_, existing_version));
137 if (!connection_open_start_time_.is_null()) {
138 UMA_HISTOGRAM_MEDIUM_TIMES(
139 "WebCore.IndexedDB.OpenTime.Blocked",
140 base::TimeTicks::Now() - connection_open_start_time_);
141 connection_open_start_time_ = base::TimeTicks();
145 void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss,
146 std::string data_loss_message) {
147 DCHECK_NE(blink::WebIDBDataLossNone, data_loss);
148 data_loss_ = data_loss;
149 data_loss_message_ = data_loss_message;
152 void IndexedDBCallbacks::OnUpgradeNeeded(
153 int64 old_version,
154 scoped_ptr<IndexedDBConnection> connection,
155 const IndexedDBDatabaseMetadata& metadata) {
156 DCHECK(dispatcher_host_.get());
158 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
159 DCHECK_NE(kNoTransaction, host_transaction_id_);
160 DCHECK_EQ(kNoDatabase, ipc_database_id_);
161 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
163 dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_url_);
164 int32 ipc_database_id =
165 dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_url_);
166 if (ipc_database_id < 0)
167 return;
168 ipc_database_id_ = ipc_database_id;
169 IndexedDBMsg_CallbacksUpgradeNeeded_Params params;
170 params.ipc_thread_id = ipc_thread_id_;
171 params.ipc_callbacks_id = ipc_callbacks_id_;
172 params.ipc_database_id = ipc_database_id;
173 params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
174 params.old_version = old_version;
175 params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
176 params.data_loss = data_loss_;
177 params.data_loss_message = data_loss_message_;
178 dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
180 if (!connection_open_start_time_.is_null()) {
181 UMA_HISTOGRAM_MEDIUM_TIMES(
182 "WebCore.IndexedDB.OpenTime.UpgradeNeeded",
183 base::TimeTicks::Now() - connection_open_start_time_);
184 connection_open_start_time_ = base::TimeTicks();
188 void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
189 const IndexedDBDatabaseMetadata& metadata) {
190 DCHECK(dispatcher_host_.get());
192 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
193 DCHECK_NE(kNoTransaction, host_transaction_id_);
194 DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection);
195 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
197 scoped_refptr<IndexedDBCallbacks> self(this);
199 int32 ipc_object_id = kNoDatabase;
200 // Only register if the connection was not previously sent in OnUpgradeNeeded.
201 if (ipc_database_id_ == kNoDatabase) {
202 ipc_object_id = dispatcher_host_->Add(
203 connection.release(), ipc_thread_id_, origin_url_);
206 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
207 ipc_thread_id_,
208 ipc_callbacks_id_,
209 ipc_database_callbacks_id_,
210 ipc_object_id,
211 IndexedDBDispatcherHost::ConvertMetadata(metadata)));
212 dispatcher_host_ = NULL;
214 if (!connection_open_start_time_.is_null()) {
215 UMA_HISTOGRAM_MEDIUM_TIMES(
216 "WebCore.IndexedDB.OpenTime.Success",
217 base::TimeTicks::Now() - connection_open_start_time_);
218 connection_open_start_time_ = base::TimeTicks();
222 static std::string CreateBlobData(
223 const IndexedDBBlobInfo& blob_info,
224 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
225 base::TaskRunner* task_runner) {
226 if (!blob_info.uuid().empty()) {
227 // We're sending back a live blob, not a reference into our backing store.
228 return dispatcher_host->HoldBlobData(blob_info);
230 scoped_refptr<ShareableFileReference> shareable_file =
231 ShareableFileReference::Get(blob_info.file_path());
232 if (!shareable_file.get()) {
233 shareable_file = ShareableFileReference::GetOrCreate(
234 blob_info.file_path(),
235 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
236 task_runner);
237 if (!blob_info.release_callback().is_null())
238 shareable_file->AddFinalReleaseCallback(blob_info.release_callback());
240 return dispatcher_host->HoldBlobData(blob_info);
243 static bool CreateAllBlobs(
244 const std::vector<IndexedDBBlobInfo>& blob_info,
245 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info,
246 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) {
247 DCHECK_EQ(blob_info.size(), blob_or_file_info->size());
248 size_t i;
249 if (!dispatcher_host->blob_storage_context())
250 return false;
251 for (i = 0; i < blob_info.size(); ++i) {
252 (*blob_or_file_info)[i].uuid =
253 CreateBlobData(blob_info[i],
254 dispatcher_host,
255 dispatcher_host->Context()->TaskRunner());
257 return true;
260 template <class ParamType, class MsgType>
261 static void CreateBlobsAndSend(
262 ParamType* params,
263 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
264 const std::vector<IndexedDBBlobInfo>& blob_info,
265 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
266 DCHECK_CURRENTLY_ON(BrowserThread::IO);
267 if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host))
268 dispatcher_host->Send(new MsgType(*params));
271 static void BlobLookupForCursorPrefetch(
272 IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params,
273 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
274 const std::vector<IndexedDBValue>& values) {
275 DCHECK_CURRENTLY_ON(BrowserThread::IO);
276 DCHECK_EQ(values.size(), params->values.size());
278 for (size_t i = 0; i < values.size(); ++i) {
279 if (!CreateAllBlobs(values[i].blob_info,
280 &params->values[i].blob_or_file_info, dispatcher_host))
281 return;
284 dispatcher_host->Send(
285 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params));
288 static void BlobLookupForGetAll(
289 IndexedDBMsg_CallbacksSuccessArray_Params* params,
290 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
291 const std::vector<IndexedDBReturnValue>& values) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO);
293 DCHECK_EQ(values.size(), params->values.size());
295 for (size_t i = 0; i < values.size(); ++i) {
296 if (!CreateAllBlobs(values[i].blob_info,
297 &params->values[i].blob_or_file_info, dispatcher_host))
298 return;
301 dispatcher_host->Send(new IndexedDBMsg_CallbacksSuccessArray(*params));
304 static void FillInBlobData(
305 const std::vector<IndexedDBBlobInfo>& blob_info,
306 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
307 for (const auto& iter : blob_info) {
308 if (iter.is_file()) {
309 IndexedDBMsg_BlobOrFileInfo info;
310 info.is_file = true;
311 info.mime_type = iter.type();
312 info.file_name = iter.file_name();
313 info.file_path = iter.file_path().AsUTF16Unsafe();
314 info.size = iter.size();
315 info.last_modified = iter.last_modified().ToDoubleT();
316 blob_or_file_info->push_back(info);
317 } else {
318 IndexedDBMsg_BlobOrFileInfo info;
319 info.mime_type = iter.type();
320 info.size = iter.size();
321 blob_or_file_info->push_back(info);
326 void IndexedDBCallbacks::RegisterBlobsAndSend(
327 const std::vector<IndexedDBBlobInfo>& blob_info,
328 const base::Closure& callback) {
329 for (const auto& iter : blob_info) {
330 if (!iter.mark_used_callback().is_null())
331 iter.mark_used_callback().Run();
333 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
334 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
337 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
338 const IndexedDBKey& key,
339 const IndexedDBKey& primary_key,
340 IndexedDBValue* value) {
341 DCHECK(dispatcher_host_.get());
343 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
344 DCHECK_EQ(kNoTransaction, host_transaction_id_);
345 DCHECK_EQ(kNoDatabase, ipc_database_id_);
346 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
347 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
349 int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
350 scoped_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
351 new IndexedDBMsg_CallbacksSuccessIDBCursor_Params());
352 params->ipc_thread_id = ipc_thread_id_;
353 params->ipc_callbacks_id = ipc_callbacks_id_;
354 params->ipc_cursor_id = ipc_object_id;
355 params->key = key;
356 params->primary_key = primary_key;
357 if (value && !value->empty())
358 std::swap(params->value.bits, value->bits);
359 // TODO(alecflett): Avoid a copy here: the whole params object is
360 // being copied into the message.
361 if (!value || value->blob_info.empty()) {
362 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params));
363 } else {
364 IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get();
365 FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
366 RegisterBlobsAndSend(
367 value->blob_info,
368 base::Bind(
369 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params,
370 IndexedDBMsg_CallbacksSuccessIDBCursor>,
371 base::Owned(params.release()), dispatcher_host_, value->blob_info,
372 base::Unretained(&p->value.blob_or_file_info)));
374 dispatcher_host_ = NULL;
377 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
378 const IndexedDBKey& primary_key,
379 IndexedDBValue* value) {
380 DCHECK(dispatcher_host_.get());
382 DCHECK_NE(kNoCursor, ipc_cursor_id_);
383 DCHECK_EQ(kNoTransaction, host_transaction_id_);
384 DCHECK_EQ(kNoDatabase, ipc_database_id_);
385 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
386 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
388 IndexedDBCursor* idb_cursor =
389 dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
391 DCHECK(idb_cursor);
392 if (!idb_cursor)
393 return;
395 scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params(
396 new IndexedDBMsg_CallbacksSuccessCursorContinue_Params());
397 params->ipc_thread_id = ipc_thread_id_;
398 params->ipc_callbacks_id = ipc_callbacks_id_;
399 params->ipc_cursor_id = ipc_cursor_id_;
400 params->key = key;
401 params->primary_key = primary_key;
402 if (value && !value->empty())
403 std::swap(params->value.bits, value->bits);
404 // TODO(alecflett): Avoid a copy here: the whole params object is
405 // being copied into the message.
406 if (!value || value->blob_info.empty()) {
407 dispatcher_host_->Send(
408 new IndexedDBMsg_CallbacksSuccessCursorContinue(*params));
409 } else {
410 IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get();
411 FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
412 RegisterBlobsAndSend(
413 value->blob_info,
414 base::Bind(CreateBlobsAndSend<
415 IndexedDBMsg_CallbacksSuccessCursorContinue_Params,
416 IndexedDBMsg_CallbacksSuccessCursorContinue>,
417 base::Owned(params.release()), dispatcher_host_,
418 value->blob_info,
419 base::Unretained(&p->value.blob_or_file_info)));
421 dispatcher_host_ = NULL;
424 void IndexedDBCallbacks::OnSuccessWithPrefetch(
425 const std::vector<IndexedDBKey>& keys,
426 const std::vector<IndexedDBKey>& primary_keys,
427 std::vector<IndexedDBValue>* values) {
428 DCHECK_EQ(keys.size(), primary_keys.size());
429 DCHECK_EQ(keys.size(), values->size());
431 DCHECK(dispatcher_host_.get());
433 DCHECK_NE(kNoCursor, ipc_cursor_id_);
434 DCHECK_EQ(kNoTransaction, host_transaction_id_);
435 DCHECK_EQ(kNoDatabase, ipc_database_id_);
436 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
437 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
439 std::vector<IndexedDBKey> msg_keys;
440 std::vector<IndexedDBKey> msg_primary_keys;
442 for (size_t i = 0; i < keys.size(); ++i) {
443 msg_keys.push_back(keys[i]);
444 msg_primary_keys.push_back(primary_keys[i]);
447 scoped_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params(
448 new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params());
449 params->ipc_thread_id = ipc_thread_id_;
450 params->ipc_callbacks_id = ipc_callbacks_id_;
451 params->ipc_cursor_id = ipc_cursor_id_;
452 params->keys = msg_keys;
453 params->primary_keys = msg_primary_keys;
454 params->values.resize(values->size());
456 bool found_blob_info = false;
457 for (size_t i = 0; i < values->size(); ++i) {
458 params->values[i].bits.swap(values->at(i).bits);
459 if (!values->at(i).blob_info.empty()) {
460 found_blob_info = true;
461 FillInBlobData(values->at(i).blob_info,
462 &params->values[i].blob_or_file_info);
463 for (const auto& blob_iter : values->at(i).blob_info) {
464 if (!blob_iter.mark_used_callback().is_null())
465 blob_iter.mark_used_callback().Run();
470 if (found_blob_info) {
471 BrowserThread::PostTask(BrowserThread::IO,
472 FROM_HERE,
473 base::Bind(BlobLookupForCursorPrefetch,
474 base::Owned(params.release()),
475 dispatcher_host_,
476 *values));
477 } else {
478 dispatcher_host_->Send(
479 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
481 dispatcher_host_ = NULL;
484 void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
485 DCHECK(dispatcher_host_.get());
487 if (value && value->primary_key.IsValid()) {
488 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
489 } else {
490 DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
492 DCHECK_EQ(kNoTransaction, host_transaction_id_);
493 DCHECK_EQ(kNoDatabase, ipc_database_id_);
494 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
495 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
497 scoped_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(
498 new IndexedDBMsg_CallbacksSuccessValue_Params());
499 params->ipc_thread_id = ipc_thread_id_;
500 params->ipc_callbacks_id = ipc_callbacks_id_;
501 if (value && value->primary_key.IsValid()) {
502 params->value.primary_key = value->primary_key;
503 params->value.key_path = value->key_path;
505 if (value && !value->empty())
506 std::swap(params->value.bits, value->bits);
507 if (!value || value->blob_info.empty()) {
508 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params));
509 } else {
510 IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get();
511 FillInBlobData(value->blob_info, &p->value.blob_or_file_info);
512 RegisterBlobsAndSend(
513 value->blob_info,
514 base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params,
515 IndexedDBMsg_CallbacksSuccessValue>,
516 base::Owned(params.release()), dispatcher_host_,
517 value->blob_info,
518 base::Unretained(&p->value.blob_or_file_info)));
520 dispatcher_host_ = NULL;
523 void IndexedDBCallbacks::OnSuccessArray(
524 std::vector<IndexedDBReturnValue>* values,
525 const IndexedDBKeyPath& key_path) {
526 DCHECK(dispatcher_host_.get());
528 DCHECK_EQ(kNoTransaction, host_transaction_id_);
529 DCHECK_EQ(kNoDatabase, ipc_database_id_);
530 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
531 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
533 scoped_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params(
534 new IndexedDBMsg_CallbacksSuccessArray_Params());
535 params->ipc_thread_id = ipc_thread_id_;
536 params->ipc_callbacks_id = ipc_callbacks_id_;
537 params->values.resize(values->size());
539 bool found_blob_info = false;
540 for (size_t i = 0; i < values->size(); ++i) {
541 IndexedDBMsg_ReturnValue& pvalue = params->values[i];
542 IndexedDBReturnValue& value = (*values)[i];
543 pvalue.bits.swap(value.bits);
544 if (!value.blob_info.empty()) {
545 found_blob_info = true;
546 FillInBlobData(value.blob_info, &pvalue.blob_or_file_info);
547 for (const auto& blob_info : value.blob_info) {
548 if (!blob_info.mark_used_callback().is_null())
549 blob_info.mark_used_callback().Run();
552 pvalue.primary_key = value.primary_key;
553 pvalue.key_path = key_path;
556 if (found_blob_info) {
557 BrowserThread::PostTask(
558 BrowserThread::IO, FROM_HERE,
559 base::Bind(BlobLookupForGetAll, base::Owned(params.release()),
560 dispatcher_host_, *values));
561 } else {
562 dispatcher_host_->Send(
563 new IndexedDBMsg_CallbacksSuccessArray(*params.get()));
565 dispatcher_host_ = NULL;
568 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
569 DCHECK(dispatcher_host_.get());
571 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
572 DCHECK_EQ(kNoTransaction, host_transaction_id_);
573 DCHECK_EQ(kNoDatabase, ipc_database_id_);
574 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
575 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
577 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
578 ipc_thread_id_, ipc_callbacks_id_, value));
579 dispatcher_host_ = NULL;
582 void IndexedDBCallbacks::OnSuccess(int64 value) {
583 DCHECK(dispatcher_host_.get());
585 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
586 DCHECK_EQ(kNoTransaction, host_transaction_id_);
587 DCHECK_EQ(kNoDatabase, ipc_database_id_);
588 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
589 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
591 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
592 ipc_thread_id_, ipc_callbacks_id_, value));
593 dispatcher_host_ = NULL;
596 void IndexedDBCallbacks::OnSuccess() {
597 DCHECK(dispatcher_host_.get());
599 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
600 DCHECK_EQ(kNoTransaction, host_transaction_id_);
601 DCHECK_EQ(kNoDatabase, ipc_database_id_);
602 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
603 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
605 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
606 ipc_thread_id_, ipc_callbacks_id_));
607 dispatcher_host_ = NULL;
610 void IndexedDBCallbacks::SetConnectionOpenStartTime(
611 const base::TimeTicks& start_time) {
612 connection_open_start_time_ = start_time;
615 } // namespace content