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"
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
;
34 const int32 kNoCursor
= -1;
35 const int32 kNoDatabaseCallbacks
= -1;
36 const int64 kNoTransaction
= -1;
39 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost
* dispatcher_host
,
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
,
55 int32 ipc_callbacks_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
,
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_
);
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(
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)
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(
209 ipc_database_callbacks_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
,
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());
249 if (!dispatcher_host
->blob_storage_context())
251 for (i
= 0; i
< blob_info
.size(); ++i
) {
252 (*blob_or_file_info
)[i
].uuid
=
253 CreateBlobData(blob_info
[i
],
255 dispatcher_host
->Context()->TaskRunner());
260 template <class ParamType
, class MsgType
>
261 static void CreateBlobsAndSend(
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 ¶ms
->values
[i
].blob_or_file_info
, dispatcher_host
))
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 ¶ms
->values
[i
].blob_or_file_info
, dispatcher_host
))
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
;
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
);
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
;
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
));
364 IndexedDBMsg_CallbacksSuccessIDBCursor_Params
* p
= params
.get();
365 FillInBlobData(value
->blob_info
, &p
->value
.blob_or_file_info
);
366 RegisterBlobsAndSend(
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_
);
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_
;
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
));
410 IndexedDBMsg_CallbacksSuccessCursorContinue_Params
* p
= params
.get();
411 FillInBlobData(value
->blob_info
, &p
->value
.blob_or_file_info
);
412 RegisterBlobsAndSend(
414 base::Bind(CreateBlobsAndSend
<
415 IndexedDBMsg_CallbacksSuccessCursorContinue_Params
,
416 IndexedDBMsg_CallbacksSuccessCursorContinue
>,
417 base::Owned(params
.release()), dispatcher_host_
,
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 ¶ms
->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
,
473 base::Bind(BlobLookupForCursorPrefetch
,
474 base::Owned(params
.release()),
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_
);
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
));
510 IndexedDBMsg_CallbacksSuccessValue_Params
* p
= params
.get();
511 FillInBlobData(value
->blob_info
, &p
->value
.blob_or_file_info
);
512 RegisterBlobsAndSend(
514 base::Bind(CreateBlobsAndSend
<IndexedDBMsg_CallbacksSuccessValue_Params
,
515 IndexedDBMsg_CallbacksSuccessValue
>,
516 base::Owned(params
.release()), dispatcher_host_
,
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
));
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