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_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
;
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 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
,
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());
251 if (!dispatcher_host
->blob_storage_context())
253 for (i
= 0; i
< blob_info
.size(); ++i
) {
254 (*blob_or_file_info
)[i
].uuid
=
255 CreateBlobData(blob_info
[i
],
257 dispatcher_host
->Context()->TaskRunner());
262 template <class ParamType
, class MsgType
>
263 static void CreateBlobsAndSend(
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 ¶ms
->values
[i
].blob_or_file_info
, dispatcher_host
))
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 ¶ms
->values
[i
].blob_or_file_info
, dispatcher_host
))
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
;
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
);
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
;
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
));
366 IndexedDBMsg_CallbacksSuccessIDBCursor_Params
* p
= params
.get();
367 FillInBlobData(value
->blob_info
, &p
->value
.blob_or_file_info
);
368 RegisterBlobsAndSend(
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_
);
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_
;
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
));
412 IndexedDBMsg_CallbacksSuccessCursorContinue_Params
* p
= params
.get();
413 FillInBlobData(value
->blob_info
, &p
->value
.blob_or_file_info
);
414 RegisterBlobsAndSend(
416 base::Bind(CreateBlobsAndSend
<
417 IndexedDBMsg_CallbacksSuccessCursorContinue_Params
,
418 IndexedDBMsg_CallbacksSuccessCursorContinue
>,
419 base::Owned(params
.release()), dispatcher_host_
,
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 ¶ms
->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
,
475 base::Bind(BlobLookupForCursorPrefetch
,
476 base::Owned(params
.release()),
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_
);
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
));
512 IndexedDBMsg_CallbacksSuccessValue_Params
* p
= params
.get();
513 FillInBlobData(value
->blob_info
, &p
->value
.blob_or_file_info
);
514 RegisterBlobsAndSend(
516 base::Bind(CreateBlobsAndSend
<IndexedDBMsg_CallbacksSuccessValue_Params
,
517 IndexedDBMsg_CallbacksSuccessValue
>,
518 base::Owned(params
.release()), dispatcher_host_
,
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
));
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