OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/browser/indexed_db/indexed_db_callbacks.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <algorithm> | |
10 #include <utility> | |
11 | |
12 #include "base/metrics/histogram.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "base/time/time.h" | |
15 #include "content/browser/child_process_security_policy_impl.h" | |
16 #include "content/browser/fileapi/fileapi_message_filter.h" | |
17 #include "content/browser/indexed_db/indexed_db_blob_info.h" | |
18 #include "content/browser/indexed_db/indexed_db_connection.h" | |
19 #include "content/browser/indexed_db/indexed_db_context_impl.h" | |
20 #include "content/browser/indexed_db/indexed_db_cursor.h" | |
21 #include "content/browser/indexed_db/indexed_db_database_callbacks.h" | |
22 #include "content/browser/indexed_db/indexed_db_database_error.h" | |
23 #include "content/browser/indexed_db/indexed_db_metadata.h" | |
24 #include "content/browser/indexed_db/indexed_db_return_value.h" | |
25 #include "content/browser/indexed_db/indexed_db_tracing.h" | |
26 #include "content/browser/indexed_db/indexed_db_value.h" | |
27 #include "content/common/indexed_db/indexed_db_constants.h" | |
28 #include "content/common/indexed_db/indexed_db_messages.h" | |
29 #include "storage/browser/blob/blob_storage_context.h" | |
30 #include "storage/browser/blob/shareable_file_reference.h" | |
31 #include "storage/browser/quota/quota_manager.h" | |
32 | |
33 using storage::ShareableFileReference; | |
34 | |
35 namespace content { | |
36 | |
37 namespace { | |
38 const int32_t kNoCursor = -1; | |
39 const int32_t kNoDatabaseCallbacks = -1; | |
40 const int64_t kNoTransaction = -1; | |
41 } | |
42 | |
43 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, | |
44 int32_t ipc_thread_id, | |
45 int32_t ipc_callbacks_id) | |
46 : dispatcher_host_(dispatcher_host), | |
47 ipc_callbacks_id_(ipc_callbacks_id), | |
48 ipc_thread_id_(ipc_thread_id), | |
49 ipc_cursor_id_(kNoCursor), | |
50 host_transaction_id_(kNoTransaction), | |
51 ipc_database_id_(kNoDatabase), | |
52 ipc_database_callbacks_id_(kNoDatabaseCallbacks), | |
53 data_loss_(blink::WebIDBDataLossNone), | |
54 sent_blocked_(false) {} | |
55 | |
56 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, | |
57 int32_t ipc_thread_id, | |
58 int32_t ipc_callbacks_id, | |
59 int32_t ipc_cursor_id) | |
60 : dispatcher_host_(dispatcher_host), | |
61 ipc_callbacks_id_(ipc_callbacks_id), | |
62 ipc_thread_id_(ipc_thread_id), | |
63 ipc_cursor_id_(ipc_cursor_id), | |
64 host_transaction_id_(kNoTransaction), | |
65 ipc_database_id_(kNoDatabase), | |
66 ipc_database_callbacks_id_(kNoDatabaseCallbacks), | |
67 data_loss_(blink::WebIDBDataLossNone), | |
68 sent_blocked_(false) {} | |
69 | |
70 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, | |
71 int32_t ipc_thread_id, | |
72 int32_t ipc_callbacks_id, | |
73 int32_t ipc_database_callbacks_id, | |
74 int64_t host_transaction_id, | |
75 const url::Origin& origin) | |
76 : dispatcher_host_(dispatcher_host), | |
77 ipc_callbacks_id_(ipc_callbacks_id), | |
78 ipc_thread_id_(ipc_thread_id), | |
79 ipc_cursor_id_(kNoCursor), | |
80 host_transaction_id_(host_transaction_id), | |
81 origin_(origin), | |
82 ipc_database_id_(kNoDatabase), | |
83 ipc_database_callbacks_id_(ipc_database_callbacks_id), | |
84 data_loss_(blink::WebIDBDataLossNone), | |
85 sent_blocked_(false) {} | |
86 | |
87 IndexedDBCallbacks::~IndexedDBCallbacks() {} | |
88 | |
89 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) { | |
90 DCHECK(dispatcher_host_.get()); | |
91 | |
92 dispatcher_host_->Send(new IndexedDBMsg_CallbacksError( | |
93 ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message())); | |
94 dispatcher_host_ = NULL; | |
95 | |
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(); | |
101 } | |
102 } | |
103 | |
104 void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) { | |
105 DCHECK(dispatcher_host_.get()); | |
106 | |
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_); | |
112 | |
113 std::vector<base::string16> list; | |
114 for (unsigned i = 0; i < value.size(); ++i) | |
115 list.push_back(value[i]); | |
116 | |
117 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList( | |
118 ipc_thread_id_, ipc_callbacks_id_, list)); | |
119 dispatcher_host_ = NULL; | |
120 } | |
121 | |
122 void IndexedDBCallbacks::OnBlocked(int64_t existing_version) { | |
123 DCHECK(dispatcher_host_.get()); | |
124 | |
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_); | |
130 | |
131 if (sent_blocked_) | |
132 return; | |
133 | |
134 sent_blocked_ = true; | |
135 dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked( | |
136 ipc_thread_id_, ipc_callbacks_id_, existing_version)); | |
137 | |
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(); | |
143 } | |
144 } | |
145 | |
146 void IndexedDBCallbacks::OnUpgradeNeeded( | |
147 int64_t old_version, | |
148 std::unique_ptr<IndexedDBConnection> connection, | |
149 const IndexedDBDatabaseMetadata& metadata, | |
150 const IndexedDBDataLossInfo& data_loss_info) { | |
151 DCHECK(dispatcher_host_.get()); | |
152 | |
153 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
154 DCHECK_NE(kNoTransaction, host_transaction_id_); | |
155 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
156 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
157 | |
158 data_loss_ = data_loss_info.status; | |
159 dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_); | |
160 int32_t ipc_database_id = | |
161 dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_); | |
162 if (ipc_database_id < 0) | |
163 return; | |
164 ipc_database_id_ = ipc_database_id; | |
165 IndexedDBMsg_CallbacksUpgradeNeeded_Params params; | |
166 params.ipc_thread_id = ipc_thread_id_; | |
167 params.ipc_callbacks_id = ipc_callbacks_id_; | |
168 params.ipc_database_id = ipc_database_id; | |
169 params.ipc_database_callbacks_id = ipc_database_callbacks_id_; | |
170 params.old_version = old_version; | |
171 params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata); | |
172 params.data_loss = data_loss_info.status; | |
173 params.data_loss_message = data_loss_info.message; | |
174 dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params)); | |
175 | |
176 if (!connection_open_start_time_.is_null()) { | |
177 UMA_HISTOGRAM_MEDIUM_TIMES( | |
178 "WebCore.IndexedDB.OpenTime.UpgradeNeeded", | |
179 base::TimeTicks::Now() - connection_open_start_time_); | |
180 connection_open_start_time_ = base::TimeTicks(); | |
181 } | |
182 } | |
183 | |
184 void IndexedDBCallbacks::OnSuccess( | |
185 std::unique_ptr<IndexedDBConnection> connection, | |
186 const IndexedDBDatabaseMetadata& metadata) { | |
187 DCHECK(dispatcher_host_.get()); | |
188 | |
189 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
190 DCHECK_NE(kNoTransaction, host_transaction_id_); | |
191 DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection); | |
192 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
193 | |
194 scoped_refptr<IndexedDBCallbacks> self(this); | |
195 | |
196 int32_t ipc_object_id = kNoDatabase; | |
197 // Only register if the connection was not previously sent in OnUpgradeNeeded. | |
198 if (ipc_database_id_ == kNoDatabase) { | |
199 ipc_object_id = | |
200 dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_); | |
201 } | |
202 | |
203 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase( | |
204 ipc_thread_id_, | |
205 ipc_callbacks_id_, | |
206 ipc_database_callbacks_id_, | |
207 ipc_object_id, | |
208 IndexedDBDispatcherHost::ConvertMetadata(metadata))); | |
209 dispatcher_host_ = NULL; | |
210 | |
211 if (!connection_open_start_time_.is_null()) { | |
212 UMA_HISTOGRAM_MEDIUM_TIMES( | |
213 "WebCore.IndexedDB.OpenTime.Success", | |
214 base::TimeTicks::Now() - connection_open_start_time_); | |
215 connection_open_start_time_ = base::TimeTicks(); | |
216 } | |
217 } | |
218 | |
219 static std::string CreateBlobData( | |
220 const IndexedDBBlobInfo& blob_info, | |
221 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, | |
222 base::TaskRunner* task_runner) { | |
223 if (!blob_info.uuid().empty()) { | |
224 // We're sending back a live blob, not a reference into our backing store. | |
225 return dispatcher_host->HoldBlobData(blob_info); | |
226 } | |
227 scoped_refptr<ShareableFileReference> shareable_file = | |
228 ShareableFileReference::Get(blob_info.file_path()); | |
229 if (!shareable_file.get()) { | |
230 shareable_file = ShareableFileReference::GetOrCreate( | |
231 blob_info.file_path(), | |
232 ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE, | |
233 task_runner); | |
234 if (!blob_info.release_callback().is_null()) | |
235 shareable_file->AddFinalReleaseCallback(blob_info.release_callback()); | |
236 } | |
237 return dispatcher_host->HoldBlobData(blob_info); | |
238 } | |
239 | |
240 static bool CreateAllBlobs( | |
241 const std::vector<IndexedDBBlobInfo>& blob_info, | |
242 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info, | |
243 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host) { | |
244 IDB_TRACE("IndexedDBCallbacks::CreateAllBlobs"); | |
245 DCHECK_EQ(blob_info.size(), blob_or_file_info->size()); | |
246 size_t i; | |
247 if (!dispatcher_host->blob_storage_context()) | |
248 return false; | |
249 for (i = 0; i < blob_info.size(); ++i) { | |
250 (*blob_or_file_info)[i].uuid = | |
251 CreateBlobData(blob_info[i], dispatcher_host, | |
252 dispatcher_host->context()->TaskRunner()); | |
253 } | |
254 return true; | |
255 } | |
256 | |
257 template <class ParamType, class MsgType> | |
258 static void CreateBlobsAndSend( | |
259 ParamType* params, | |
260 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, | |
261 const std::vector<IndexedDBBlobInfo>& blob_info, | |
262 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) { | |
263 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
264 if (CreateAllBlobs(blob_info, blob_or_file_info, dispatcher_host)) | |
265 dispatcher_host->Send(new MsgType(*params)); | |
266 } | |
267 | |
268 static void BlobLookupForCursorPrefetch( | |
269 IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params* params, | |
270 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, | |
271 const std::vector<IndexedDBValue>& values) { | |
272 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
273 DCHECK_EQ(values.size(), params->values.size()); | |
274 | |
275 for (size_t i = 0; i < values.size(); ++i) { | |
276 if (!CreateAllBlobs(values[i].blob_info, | |
277 ¶ms->values[i].blob_or_file_info, dispatcher_host)) | |
278 return; | |
279 } | |
280 | |
281 dispatcher_host->Send( | |
282 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params)); | |
283 } | |
284 | |
285 static void BlobLookupForGetAll( | |
286 IndexedDBMsg_CallbacksSuccessArray_Params* params, | |
287 scoped_refptr<IndexedDBDispatcherHost> dispatcher_host, | |
288 const std::vector<IndexedDBReturnValue>& values) { | |
289 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
290 DCHECK_EQ(values.size(), params->values.size()); | |
291 | |
292 for (size_t i = 0; i < values.size(); ++i) { | |
293 if (!CreateAllBlobs(values[i].blob_info, | |
294 ¶ms->values[i].blob_or_file_info, dispatcher_host)) | |
295 return; | |
296 } | |
297 | |
298 dispatcher_host->Send(new IndexedDBMsg_CallbacksSuccessArray(*params)); | |
299 } | |
300 | |
301 static void FillInBlobData( | |
302 const std::vector<IndexedDBBlobInfo>& blob_info, | |
303 std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) { | |
304 for (const auto& iter : blob_info) { | |
305 if (iter.is_file()) { | |
306 IndexedDBMsg_BlobOrFileInfo info; | |
307 info.is_file = true; | |
308 info.mime_type = iter.type(); | |
309 info.file_name = iter.file_name(); | |
310 info.file_path = iter.file_path().AsUTF16Unsafe(); | |
311 info.size = iter.size(); | |
312 info.last_modified = iter.last_modified().ToDoubleT(); | |
313 blob_or_file_info->push_back(info); | |
314 } else { | |
315 IndexedDBMsg_BlobOrFileInfo info; | |
316 info.mime_type = iter.type(); | |
317 info.size = iter.size(); | |
318 blob_or_file_info->push_back(info); | |
319 } | |
320 } | |
321 } | |
322 | |
323 void IndexedDBCallbacks::RegisterBlobsAndSend( | |
324 const std::vector<IndexedDBBlobInfo>& blob_info, | |
325 const base::Closure& callback) { | |
326 for (const auto& iter : blob_info) { | |
327 if (!iter.mark_used_callback().is_null()) | |
328 iter.mark_used_callback().Run(); | |
329 } | |
330 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
331 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback); | |
332 } | |
333 | |
334 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor, | |
335 const IndexedDBKey& key, | |
336 const IndexedDBKey& primary_key, | |
337 IndexedDBValue* value) { | |
338 DCHECK(dispatcher_host_.get()); | |
339 | |
340 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
341 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
342 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
343 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
344 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
345 | |
346 int32_t ipc_object_id = dispatcher_host_->Add(cursor.get()); | |
347 std::unique_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params( | |
348 new IndexedDBMsg_CallbacksSuccessIDBCursor_Params()); | |
349 params->ipc_thread_id = ipc_thread_id_; | |
350 params->ipc_callbacks_id = ipc_callbacks_id_; | |
351 params->ipc_cursor_id = ipc_object_id; | |
352 params->key = key; | |
353 params->primary_key = primary_key; | |
354 if (value && !value->empty()) | |
355 std::swap(params->value.bits, value->bits); | |
356 // TODO(alecflett): Avoid a copy here: the whole params object is | |
357 // being copied into the message. | |
358 if (!value || value->blob_info.empty()) { | |
359 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(*params)); | |
360 } else { | |
361 IndexedDBMsg_CallbacksSuccessIDBCursor_Params* p = params.get(); | |
362 FillInBlobData(value->blob_info, &p->value.blob_or_file_info); | |
363 RegisterBlobsAndSend( | |
364 value->blob_info, | |
365 base::Bind( | |
366 CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessIDBCursor_Params, | |
367 IndexedDBMsg_CallbacksSuccessIDBCursor>, | |
368 base::Owned(params.release()), dispatcher_host_, value->blob_info, | |
369 base::Unretained(&p->value.blob_or_file_info))); | |
370 } | |
371 dispatcher_host_ = NULL; | |
372 } | |
373 | |
374 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key, | |
375 const IndexedDBKey& primary_key, | |
376 IndexedDBValue* value) { | |
377 DCHECK(dispatcher_host_.get()); | |
378 | |
379 DCHECK_NE(kNoCursor, ipc_cursor_id_); | |
380 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
381 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
382 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
383 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
384 | |
385 IndexedDBCursor* idb_cursor = | |
386 dispatcher_host_->GetCursorFromId(ipc_cursor_id_); | |
387 | |
388 DCHECK(idb_cursor); | |
389 if (!idb_cursor) | |
390 return; | |
391 | |
392 std::unique_ptr<IndexedDBMsg_CallbacksSuccessCursorContinue_Params> params( | |
393 new IndexedDBMsg_CallbacksSuccessCursorContinue_Params()); | |
394 params->ipc_thread_id = ipc_thread_id_; | |
395 params->ipc_callbacks_id = ipc_callbacks_id_; | |
396 params->ipc_cursor_id = ipc_cursor_id_; | |
397 params->key = key; | |
398 params->primary_key = primary_key; | |
399 if (value && !value->empty()) | |
400 std::swap(params->value.bits, value->bits); | |
401 // TODO(alecflett): Avoid a copy here: the whole params object is | |
402 // being copied into the message. | |
403 if (!value || value->blob_info.empty()) { | |
404 dispatcher_host_->Send( | |
405 new IndexedDBMsg_CallbacksSuccessCursorContinue(*params)); | |
406 } else { | |
407 IndexedDBMsg_CallbacksSuccessCursorContinue_Params* p = params.get(); | |
408 FillInBlobData(value->blob_info, &p->value.blob_or_file_info); | |
409 RegisterBlobsAndSend( | |
410 value->blob_info, | |
411 base::Bind(CreateBlobsAndSend< | |
412 IndexedDBMsg_CallbacksSuccessCursorContinue_Params, | |
413 IndexedDBMsg_CallbacksSuccessCursorContinue>, | |
414 base::Owned(params.release()), dispatcher_host_, | |
415 value->blob_info, | |
416 base::Unretained(&p->value.blob_or_file_info))); | |
417 } | |
418 dispatcher_host_ = NULL; | |
419 } | |
420 | |
421 void IndexedDBCallbacks::OnSuccessWithPrefetch( | |
422 const std::vector<IndexedDBKey>& keys, | |
423 const std::vector<IndexedDBKey>& primary_keys, | |
424 std::vector<IndexedDBValue>* values) { | |
425 DCHECK_EQ(keys.size(), primary_keys.size()); | |
426 DCHECK_EQ(keys.size(), values->size()); | |
427 | |
428 DCHECK(dispatcher_host_.get()); | |
429 | |
430 DCHECK_NE(kNoCursor, ipc_cursor_id_); | |
431 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
432 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
433 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
434 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
435 | |
436 std::vector<IndexedDBKey> msg_keys; | |
437 std::vector<IndexedDBKey> msg_primary_keys; | |
438 | |
439 for (size_t i = 0; i < keys.size(); ++i) { | |
440 msg_keys.push_back(keys[i]); | |
441 msg_primary_keys.push_back(primary_keys[i]); | |
442 } | |
443 | |
444 std::unique_ptr<IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params> params( | |
445 new IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params()); | |
446 params->ipc_thread_id = ipc_thread_id_; | |
447 params->ipc_callbacks_id = ipc_callbacks_id_; | |
448 params->ipc_cursor_id = ipc_cursor_id_; | |
449 params->keys = msg_keys; | |
450 params->primary_keys = msg_primary_keys; | |
451 params->values.resize(values->size()); | |
452 | |
453 bool found_blob_info = false; | |
454 for (size_t i = 0; i < values->size(); ++i) { | |
455 params->values[i].bits.swap(values->at(i).bits); | |
456 if (!values->at(i).blob_info.empty()) { | |
457 found_blob_info = true; | |
458 FillInBlobData(values->at(i).blob_info, | |
459 ¶ms->values[i].blob_or_file_info); | |
460 for (const auto& blob_iter : values->at(i).blob_info) { | |
461 if (!blob_iter.mark_used_callback().is_null()) | |
462 blob_iter.mark_used_callback().Run(); | |
463 } | |
464 } | |
465 } | |
466 | |
467 if (found_blob_info) { | |
468 BrowserThread::PostTask(BrowserThread::IO, | |
469 FROM_HERE, | |
470 base::Bind(BlobLookupForCursorPrefetch, | |
471 base::Owned(params.release()), | |
472 dispatcher_host_, | |
473 *values)); | |
474 } else { | |
475 dispatcher_host_->Send( | |
476 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get())); | |
477 } | |
478 dispatcher_host_ = NULL; | |
479 } | |
480 | |
481 void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) { | |
482 DCHECK(dispatcher_host_.get()); | |
483 | |
484 if (value && value->primary_key.IsValid()) { | |
485 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
486 } else { | |
487 DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL); | |
488 } | |
489 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
490 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
491 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
492 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
493 | |
494 std::unique_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params( | |
495 new IndexedDBMsg_CallbacksSuccessValue_Params()); | |
496 params->ipc_thread_id = ipc_thread_id_; | |
497 params->ipc_callbacks_id = ipc_callbacks_id_; | |
498 if (value && value->primary_key.IsValid()) { | |
499 params->value.primary_key = value->primary_key; | |
500 params->value.key_path = value->key_path; | |
501 } | |
502 if (value && !value->empty()) | |
503 std::swap(params->value.bits, value->bits); | |
504 if (!value || value->blob_info.empty()) { | |
505 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(*params)); | |
506 } else { | |
507 IndexedDBMsg_CallbacksSuccessValue_Params* p = params.get(); | |
508 FillInBlobData(value->blob_info, &p->value.blob_or_file_info); | |
509 RegisterBlobsAndSend( | |
510 value->blob_info, | |
511 base::Bind(CreateBlobsAndSend<IndexedDBMsg_CallbacksSuccessValue_Params, | |
512 IndexedDBMsg_CallbacksSuccessValue>, | |
513 base::Owned(params.release()), dispatcher_host_, | |
514 value->blob_info, | |
515 base::Unretained(&p->value.blob_or_file_info))); | |
516 } | |
517 dispatcher_host_ = NULL; | |
518 } | |
519 | |
520 void IndexedDBCallbacks::OnSuccessArray( | |
521 std::vector<IndexedDBReturnValue>* values, | |
522 const IndexedDBKeyPath& key_path) { | |
523 DCHECK(dispatcher_host_.get()); | |
524 | |
525 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
526 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
527 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
528 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
529 | |
530 std::unique_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params( | |
531 new IndexedDBMsg_CallbacksSuccessArray_Params()); | |
532 params->ipc_thread_id = ipc_thread_id_; | |
533 params->ipc_callbacks_id = ipc_callbacks_id_; | |
534 params->values.resize(values->size()); | |
535 | |
536 bool found_blob_info = false; | |
537 for (size_t i = 0; i < values->size(); ++i) { | |
538 IndexedDBMsg_ReturnValue& pvalue = params->values[i]; | |
539 IndexedDBReturnValue& value = (*values)[i]; | |
540 pvalue.bits.swap(value.bits); | |
541 if (!value.blob_info.empty()) { | |
542 found_blob_info = true; | |
543 FillInBlobData(value.blob_info, &pvalue.blob_or_file_info); | |
544 for (const auto& blob_info : value.blob_info) { | |
545 if (!blob_info.mark_used_callback().is_null()) | |
546 blob_info.mark_used_callback().Run(); | |
547 } | |
548 } | |
549 pvalue.primary_key = value.primary_key; | |
550 pvalue.key_path = key_path; | |
551 } | |
552 | |
553 if (found_blob_info) { | |
554 BrowserThread::PostTask( | |
555 BrowserThread::IO, FROM_HERE, | |
556 base::Bind(BlobLookupForGetAll, base::Owned(params.release()), | |
557 dispatcher_host_, *values)); | |
558 } else { | |
559 dispatcher_host_->Send( | |
560 new IndexedDBMsg_CallbacksSuccessArray(*params.get())); | |
561 } | |
562 dispatcher_host_ = NULL; | |
563 } | |
564 | |
565 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) { | |
566 DCHECK(dispatcher_host_.get()); | |
567 | |
568 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
569 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
570 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
571 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
572 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
573 | |
574 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey( | |
575 ipc_thread_id_, ipc_callbacks_id_, value)); | |
576 dispatcher_host_ = NULL; | |
577 } | |
578 | |
579 void IndexedDBCallbacks::OnSuccess(int64_t value) { | |
580 DCHECK(dispatcher_host_.get()); | |
581 | |
582 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
583 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
584 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
585 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
586 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
587 | |
588 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger( | |
589 ipc_thread_id_, ipc_callbacks_id_, value)); | |
590 dispatcher_host_ = NULL; | |
591 } | |
592 | |
593 void IndexedDBCallbacks::OnSuccess() { | |
594 DCHECK(dispatcher_host_.get()); | |
595 | |
596 DCHECK_EQ(kNoCursor, ipc_cursor_id_); | |
597 DCHECK_EQ(kNoTransaction, host_transaction_id_); | |
598 DCHECK_EQ(kNoDatabase, ipc_database_id_); | |
599 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); | |
600 DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); | |
601 | |
602 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined( | |
603 ipc_thread_id_, ipc_callbacks_id_)); | |
604 dispatcher_host_ = NULL; | |
605 } | |
606 | |
607 void IndexedDBCallbacks::SetConnectionOpenStartTime( | |
608 const base::TimeTicks& start_time) { | |
609 connection_open_start_time_ = start_time; | |
610 } | |
611 | |
612 } // namespace content | |
OLD | NEW |