[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher.cc
blob9cd48e2c1cefae65b5039d87d45cbd4d11aa6494
1 // Copyright 2013 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/child/indexed_db/indexed_db_dispatcher.h"
7 #include <utility>
9 #include "base/format_macros.h"
10 #include "base/lazy_instance.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/thread_local.h"
13 #include "content/child/indexed_db/indexed_db_key_builders.h"
14 #include "content/child/indexed_db/webidbcursor_impl.h"
15 #include "content/child/indexed_db/webidbdatabase_impl.h"
16 #include "content/child/thread_safe_sender.h"
17 #include "content/common/indexed_db/indexed_db_constants.h"
18 #include "content/common/indexed_db/indexed_db_messages.h"
19 #include "ipc/ipc_channel.h"
20 #include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
21 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
22 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
24 using blink::WebBlobInfo;
25 using blink::WebData;
26 using blink::WebIDBCallbacks;
27 using blink::WebIDBCursor;
28 using blink::WebIDBDatabase;
29 using blink::WebIDBDatabaseCallbacks;
30 using blink::WebIDBDatabaseError;
31 using blink::WebIDBKey;
32 using blink::WebIDBMetadata;
33 using blink::WebString;
34 using blink::WebVector;
35 using base::ThreadLocalPointer;
37 namespace content {
38 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
39 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
41 namespace {
43 IndexedDBDispatcher* const kHasBeenDeleted =
44 reinterpret_cast<IndexedDBDispatcher*>(0x1);
46 } // unnamed namespace
48 const size_t kMaxIDBMessageOverhead = 1024 * 1024; // 1MB; arbitrarily chosen.
49 const size_t kMaxIDBValueSizeInBytes =
50 IPC::Channel::kMaximumMessageSize - kMaxIDBMessageOverhead;
52 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender)
53 : thread_safe_sender_(thread_safe_sender) {
54 g_idb_dispatcher_tls.Pointer()->Set(this);
57 IndexedDBDispatcher::~IndexedDBDispatcher() {
58 // Clear any pending callbacks - which may result in dispatch requests -
59 // before marking the dispatcher as deleted.
60 pending_callbacks_.Clear();
61 pending_database_callbacks_.Clear();
63 DCHECK(pending_callbacks_.IsEmpty());
64 DCHECK(pending_database_callbacks_.IsEmpty());
66 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
69 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance(
70 ThreadSafeSender* thread_safe_sender) {
71 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
72 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
73 g_idb_dispatcher_tls.Pointer()->Set(NULL);
75 if (g_idb_dispatcher_tls.Pointer()->Get())
76 return g_idb_dispatcher_tls.Pointer()->Get();
78 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender);
79 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
80 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
81 return dispatcher;
84 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
86 WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
87 const IndexedDBDatabaseMetadata& idb_metadata) {
88 WebIDBMetadata web_metadata;
89 web_metadata.id = idb_metadata.id;
90 web_metadata.name = idb_metadata.name;
91 web_metadata.version = idb_metadata.version;
92 web_metadata.intVersion = idb_metadata.int_version;
93 web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
94 web_metadata.objectStores =
95 WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
97 for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) {
98 const IndexedDBObjectStoreMetadata& idb_store_metadata =
99 idb_metadata.object_stores[i];
100 WebIDBMetadata::ObjectStore& web_store_metadata =
101 web_metadata.objectStores[i];
103 web_store_metadata.id = idb_store_metadata.id;
104 web_store_metadata.name = idb_store_metadata.name;
105 web_store_metadata.keyPath =
106 WebIDBKeyPathBuilder::Build(idb_store_metadata.keyPath);
107 web_store_metadata.autoIncrement = idb_store_metadata.autoIncrement;
108 web_store_metadata.maxIndexId = idb_store_metadata.max_index_id;
109 web_store_metadata.indexes =
110 WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size());
112 for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) {
113 const IndexedDBIndexMetadata& idb_index_metadata =
114 idb_store_metadata.indexes[j];
115 WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j];
117 web_index_metadata.id = idb_index_metadata.id;
118 web_index_metadata.name = idb_index_metadata.name;
119 web_index_metadata.keyPath =
120 WebIDBKeyPathBuilder::Build(idb_index_metadata.keyPath);
121 web_index_metadata.unique = idb_index_metadata.unique;
122 web_index_metadata.multiEntry = idb_index_metadata.multiEntry;
126 return web_metadata;
129 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
130 bool handled = true;
131 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
132 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
133 OnSuccessOpenCursor)
134 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance,
135 OnSuccessCursorContinue)
136 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
137 OnSuccessCursorContinue)
138 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
139 OnSuccessCursorPrefetch)
140 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
141 OnSuccessIDBDatabase)
142 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
143 OnSuccessIndexedDBKey)
144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList,
145 OnSuccessStringList)
146 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue)
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValueWithKey,
148 OnSuccessValueWithKey)
149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined,
151 OnSuccessUndefined)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError)
153 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked)
154 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
156 OnForcedClose)
157 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
158 OnIntVersionChange)
159 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
160 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
161 IPC_MESSAGE_UNHANDLED(handled = false)
162 IPC_END_MESSAGE_MAP()
163 // If a message gets here, IndexedDBMessageFilter already determined that it
164 // is an IndexedDB message.
165 DCHECK(handled) << "Didn't handle a message defined at line "
166 << IPC_MESSAGE_ID_LINE(msg.type());
169 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
170 return thread_safe_sender_->Send(msg);
173 void IndexedDBDispatcher::RequestIDBCursorAdvance(
174 unsigned long count,
175 WebIDBCallbacks* callbacks_ptr,
176 int32 ipc_cursor_id,
177 int64 transaction_id) {
178 // Reset all cursor prefetch caches except for this cursor.
179 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
181 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
183 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
184 Send(new IndexedDBHostMsg_CursorAdvance(
185 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count));
188 void IndexedDBDispatcher::RequestIDBCursorContinue(
189 const IndexedDBKey& key,
190 const IndexedDBKey& primary_key,
191 WebIDBCallbacks* callbacks_ptr,
192 int32 ipc_cursor_id,
193 int64 transaction_id) {
194 // Reset all cursor prefetch caches except for this cursor.
195 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
197 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
199 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
200 Send(new IndexedDBHostMsg_CursorContinue(
201 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key));
204 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
205 int n,
206 WebIDBCallbacks* callbacks_ptr,
207 int32 ipc_cursor_id) {
208 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
210 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
211 Send(new IndexedDBHostMsg_CursorPrefetch(
212 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n));
215 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
216 int unused_prefetches,
217 int32 ipc_cursor_id) {
218 Send(new IndexedDBHostMsg_CursorPrefetchReset(
219 ipc_cursor_id, used_prefetches, unused_prefetches));
222 void IndexedDBDispatcher::RequestIDBFactoryOpen(
223 const base::string16& name,
224 int64 version,
225 int64 transaction_id,
226 WebIDBCallbacks* callbacks_ptr,
227 WebIDBDatabaseCallbacks* database_callbacks_ptr,
228 const std::string& database_identifier) {
229 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
230 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
231 database_callbacks_ptr);
233 IndexedDBHostMsg_FactoryOpen_Params params;
234 params.ipc_thread_id = CurrentWorkerId();
235 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
236 params.ipc_database_callbacks_id =
237 pending_database_callbacks_.Add(database_callbacks.release());
238 params.database_identifier = database_identifier;
239 params.name = name;
240 params.transaction_id = transaction_id;
241 params.version = version;
242 Send(new IndexedDBHostMsg_FactoryOpen(params));
245 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
246 WebIDBCallbacks* callbacks_ptr,
247 const std::string& database_identifier) {
248 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
250 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
251 params.ipc_thread_id = CurrentWorkerId();
252 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
253 params.database_identifier = database_identifier;
254 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
257 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
258 const base::string16& name,
259 WebIDBCallbacks* callbacks_ptr,
260 const std::string& database_identifier) {
261 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
263 IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
264 params.ipc_thread_id = CurrentWorkerId();
265 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
266 params.database_identifier = database_identifier;
267 params.name = name;
268 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
271 void IndexedDBDispatcher::RequestIDBDatabaseClose(
272 int32 ipc_database_id,
273 int32 ipc_database_callbacks_id) {
274 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id));
275 // There won't be pending database callbacks if the transaction was aborted in
276 // the initial upgradeneeded event handler.
277 if (pending_database_callbacks_.Lookup(ipc_database_callbacks_id))
278 pending_database_callbacks_.Remove(ipc_database_callbacks_id);
281 void IndexedDBDispatcher::NotifyIDBDatabaseVersionChangeIgnored(
282 int32 ipc_database_id) {
283 Send(new IndexedDBHostMsg_DatabaseVersionChangeIgnored(ipc_database_id));
286 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
287 int32 ipc_database_id,
288 int64 transaction_id,
289 WebIDBDatabaseCallbacks* database_callbacks_ptr,
290 WebVector<long long> object_store_ids,
291 blink::WebIDBTransactionMode mode) {
292 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
293 database_callbacks_ptr);
294 IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
295 params.ipc_thread_id = CurrentWorkerId();
296 params.ipc_database_id = ipc_database_id;
297 params.transaction_id = transaction_id;
298 params.ipc_database_callbacks_id =
299 pending_database_callbacks_.Add(database_callbacks.release());
300 params.object_store_ids
301 .assign(object_store_ids.data(),
302 object_store_ids.data() + object_store_ids.size());
303 params.mode = mode;
305 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
308 void IndexedDBDispatcher::RequestIDBDatabaseGet(
309 int32 ipc_database_id,
310 int64 transaction_id,
311 int64 object_store_id,
312 int64 index_id,
313 const IndexedDBKeyRange& key_range,
314 bool key_only,
315 WebIDBCallbacks* callbacks) {
316 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
317 IndexedDBHostMsg_DatabaseGet_Params params;
318 init_params(&params, callbacks);
319 params.ipc_database_id = ipc_database_id;
320 params.transaction_id = transaction_id;
321 params.object_store_id = object_store_id;
322 params.index_id = index_id;
323 params.key_range = key_range;
324 params.key_only = key_only;
325 Send(new IndexedDBHostMsg_DatabaseGet(params));
328 void IndexedDBDispatcher::RequestIDBDatabasePut(
329 int32 ipc_database_id,
330 int64 transaction_id,
331 int64 object_store_id,
332 const WebData& value,
333 const blink::WebVector<WebBlobInfo>& web_blob_info,
334 const IndexedDBKey& key,
335 blink::WebIDBPutMode put_mode,
336 WebIDBCallbacks* callbacks,
337 const WebVector<long long>& index_ids,
338 const WebVector<WebVector<WebIDBKey> >& index_keys) {
339 if (value.size() + key.size_estimate() > kMaxIDBValueSizeInBytes) {
340 callbacks->onError(WebIDBDatabaseError(
341 blink::WebIDBDatabaseExceptionUnknownError,
342 WebString::fromUTF8(base::StringPrintf(
343 "The serialized value is too large"
344 " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
345 value.size(),
346 kMaxIDBValueSizeInBytes).c_str())));
347 return;
350 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
351 IndexedDBHostMsg_DatabasePut_Params params;
352 init_params(&params, callbacks);
353 params.ipc_database_id = ipc_database_id;
354 params.transaction_id = transaction_id;
355 params.object_store_id = object_store_id;
357 params.value.assign(value.data(), value.data() + value.size());
358 params.key = key;
359 params.put_mode = put_mode;
361 DCHECK_EQ(index_ids.size(), index_keys.size());
362 params.index_keys.resize(index_ids.size());
363 for (size_t i = 0, len = index_ids.size(); i < len; ++i) {
364 params.index_keys[i].first = index_ids[i];
365 params.index_keys[i].second.resize(index_keys[i].size());
366 for (size_t j = 0; j < index_keys[i].size(); ++j) {
367 params.index_keys[i].second[j] =
368 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys[i][j]));
372 params.blob_or_file_info.resize(web_blob_info.size());
373 for (size_t i = 0; i < web_blob_info.size(); ++i) {
374 const WebBlobInfo& info = web_blob_info[i];
375 IndexedDBMsg_BlobOrFileInfo& blob_or_file_info =
376 params.blob_or_file_info[i];
377 blob_or_file_info.is_file = info.isFile();
378 if (info.isFile()) {
379 blob_or_file_info.file_path = info.filePath();
380 blob_or_file_info.file_name = info.fileName();
381 blob_or_file_info.last_modified = info.lastModified();
383 blob_or_file_info.size = info.size();
384 blob_or_file_info.uuid = info.uuid().latin1();
385 DCHECK(blob_or_file_info.uuid.size());
386 blob_or_file_info.mime_type = info.type();
389 Send(new IndexedDBHostMsg_DatabasePut(params));
392 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
393 int32 ipc_database_id,
394 int64 transaction_id,
395 int64 object_store_id,
396 int64 index_id,
397 const IndexedDBKeyRange& key_range,
398 blink::WebIDBCursorDirection direction,
399 bool key_only,
400 blink::WebIDBTaskType task_type,
401 WebIDBCallbacks* callbacks) {
402 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
403 IndexedDBHostMsg_DatabaseOpenCursor_Params params;
404 init_params(&params, callbacks);
405 params.ipc_database_id = ipc_database_id;
406 params.transaction_id = transaction_id;
407 params.object_store_id = object_store_id;
408 params.index_id = index_id;
409 params.key_range = key_range;
410 params.direction = direction;
411 params.key_only = key_only;
412 params.task_type = task_type;
413 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params));
415 DCHECK(cursor_transaction_ids_.find(params.ipc_callbacks_id) ==
416 cursor_transaction_ids_.end());
417 cursor_transaction_ids_[params.ipc_callbacks_id] = transaction_id;
420 void IndexedDBDispatcher::RequestIDBDatabaseCount(
421 int32 ipc_database_id,
422 int64 transaction_id,
423 int64 object_store_id,
424 int64 index_id,
425 const IndexedDBKeyRange& key_range,
426 WebIDBCallbacks* callbacks) {
427 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
428 IndexedDBHostMsg_DatabaseCount_Params params;
429 init_params(&params, callbacks);
430 params.ipc_database_id = ipc_database_id;
431 params.transaction_id = transaction_id;
432 params.object_store_id = object_store_id;
433 params.index_id = index_id;
434 params.key_range = key_range;
435 Send(new IndexedDBHostMsg_DatabaseCount(params));
438 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
439 int32 ipc_database_id,
440 int64 transaction_id,
441 int64 object_store_id,
442 const IndexedDBKeyRange& key_range,
443 WebIDBCallbacks* callbacks) {
444 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
445 IndexedDBHostMsg_DatabaseDeleteRange_Params params;
446 init_params(&params, callbacks);
447 params.ipc_database_id = ipc_database_id;
448 params.transaction_id = transaction_id;
449 params.object_store_id = object_store_id;
450 params.key_range = key_range;
451 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params));
454 void IndexedDBDispatcher::RequestIDBDatabaseClear(
455 int32 ipc_database_id,
456 int64 transaction_id,
457 int64 object_store_id,
458 WebIDBCallbacks* callbacks_ptr) {
459 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
460 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
461 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
462 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
463 ipc_callbacks_id,
464 ipc_database_id,
465 transaction_id,
466 object_store_id));
469 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
470 cursors_.erase(ipc_cursor_id);
473 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) {
474 DCHECK_EQ(databases_.count(ipc_database_id), 1u);
475 databases_.erase(ipc_database_id);
478 void IndexedDBDispatcher::OnSuccessIDBDatabase(
479 int32 ipc_thread_id,
480 int32 ipc_callbacks_id,
481 int32 ipc_database_callbacks_id,
482 int32 ipc_object_id,
483 const IndexedDBDatabaseMetadata& idb_metadata) {
484 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
485 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
486 if (!callbacks)
487 return;
488 WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
489 // If an upgrade was performed, count will be non-zero.
490 WebIDBDatabase* database = NULL;
492 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
493 // May already be deleted and removed from the table, but do not recreate..
494 if (ipc_object_id != kNoDatabase) {
495 DCHECK(!databases_.count(ipc_object_id));
496 database = databases_[ipc_object_id] = new WebIDBDatabaseImpl(
497 ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get());
500 callbacks->onSuccess(database, metadata);
501 pending_callbacks_.Remove(ipc_callbacks_id);
504 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
505 int32 ipc_callbacks_id,
506 const IndexedDBKey& key) {
507 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
508 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
509 if (!callbacks)
510 return;
511 callbacks->onSuccess(WebIDBKeyBuilder::Build(key));
512 pending_callbacks_.Remove(ipc_callbacks_id);
515 void IndexedDBDispatcher::OnSuccessStringList(
516 int32 ipc_thread_id,
517 int32 ipc_callbacks_id,
518 const std::vector<base::string16>& value) {
519 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
520 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
521 if (!callbacks)
522 return;
523 callbacks->onSuccess(WebVector<WebString>(value));
524 pending_callbacks_.Remove(ipc_callbacks_id);
527 static void PrepareWebValueAndBlobInfo(
528 const std::string& value,
529 const std::vector<IndexedDBMsg_BlobOrFileInfo>& blob_info,
530 WebData* web_value,
531 blink::WebVector<WebBlobInfo>* web_blob_info) {
533 if (value.empty())
534 return;
536 web_value->assign(&*value.begin(), value.size());
537 blink::WebVector<WebBlobInfo> local_blob_info(blob_info.size());
538 for (size_t i = 0; i < blob_info.size(); ++i) {
539 const IndexedDBMsg_BlobOrFileInfo& info = blob_info[i];
540 if (info.is_file) {
541 local_blob_info[i] = WebBlobInfo(WebString::fromUTF8(info.uuid.c_str()),
542 info.file_path,
543 info.file_name,
544 info.mime_type,
545 info.last_modified,
546 info.size);
547 } else {
548 local_blob_info[i] = WebBlobInfo(
549 WebString::fromUTF8(info.uuid.c_str()), info.mime_type, info.size);
552 web_blob_info->swap(local_blob_info);
555 void IndexedDBDispatcher::OnSuccessValue(
556 const IndexedDBMsg_CallbacksSuccessValue_Params& params) {
557 DCHECK_EQ(params.ipc_thread_id, CurrentWorkerId());
558 WebIDBCallbacks* callbacks =
559 pending_callbacks_.Lookup(params.ipc_callbacks_id);
560 if (!callbacks)
561 return;
562 WebData web_value;
563 WebVector<WebBlobInfo> web_blob_info;
564 PrepareWebValueAndBlobInfo(
565 params.value, params.blob_or_file_info, &web_value, &web_blob_info);
566 callbacks->onSuccess(web_value, web_blob_info);
567 pending_callbacks_.Remove(params.ipc_callbacks_id);
568 cursor_transaction_ids_.erase(params.ipc_callbacks_id);
571 void IndexedDBDispatcher::OnSuccessValueWithKey(
572 const IndexedDBMsg_CallbacksSuccessValueWithKey_Params& params) {
573 DCHECK_EQ(params.ipc_thread_id, CurrentWorkerId());
574 WebIDBCallbacks* callbacks =
575 pending_callbacks_.Lookup(params.ipc_callbacks_id);
576 if (!callbacks)
577 return;
578 WebData web_value;
579 WebVector<WebBlobInfo> web_blob_info;
580 PrepareWebValueAndBlobInfo(
581 params.value, params.blob_or_file_info, &web_value, &web_blob_info);
582 callbacks->onSuccess(web_value,
583 web_blob_info,
584 WebIDBKeyBuilder::Build(params.primary_key),
585 WebIDBKeyPathBuilder::Build(params.key_path));
586 pending_callbacks_.Remove(params.ipc_callbacks_id);
589 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id,
590 int32 ipc_callbacks_id,
591 int64 value) {
592 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
593 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
594 if (!callbacks)
595 return;
596 callbacks->onSuccess(value);
597 pending_callbacks_.Remove(ipc_callbacks_id);
600 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id,
601 int32 ipc_callbacks_id) {
602 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
603 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
604 if (!callbacks)
605 return;
606 callbacks->onSuccess();
607 pending_callbacks_.Remove(ipc_callbacks_id);
610 void IndexedDBDispatcher::OnSuccessOpenCursor(
611 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) {
612 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
613 int32 ipc_callbacks_id = p.ipc_callbacks_id;
614 int32 ipc_object_id = p.ipc_cursor_id;
615 const IndexedDBKey& key = p.key;
616 const IndexedDBKey& primary_key = p.primary_key;
617 WebData web_value;
618 WebVector<WebBlobInfo> web_blob_info;
619 PrepareWebValueAndBlobInfo(
620 p.value, p.blob_or_file_info, &web_value, &web_blob_info);
622 DCHECK(cursor_transaction_ids_.find(ipc_callbacks_id) !=
623 cursor_transaction_ids_.end());
624 int64 transaction_id = cursor_transaction_ids_[ipc_callbacks_id];
625 cursor_transaction_ids_.erase(ipc_callbacks_id);
627 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
628 if (!callbacks)
629 return;
631 WebIDBCursorImpl* cursor = new WebIDBCursorImpl(
632 ipc_object_id, transaction_id, thread_safe_sender_.get());
633 cursors_[ipc_object_id] = cursor;
634 callbacks->onSuccess(cursor,
635 WebIDBKeyBuilder::Build(key),
636 WebIDBKeyBuilder::Build(primary_key),
637 web_value,
638 web_blob_info);
640 pending_callbacks_.Remove(ipc_callbacks_id);
643 void IndexedDBDispatcher::OnSuccessCursorContinue(
644 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) {
645 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
646 int32 ipc_callbacks_id = p.ipc_callbacks_id;
647 int32 ipc_cursor_id = p.ipc_cursor_id;
648 const IndexedDBKey& key = p.key;
649 const IndexedDBKey& primary_key = p.primary_key;
650 const std::string& value = p.value;
652 if (cursors_.find(ipc_cursor_id) == cursors_.end())
653 return;
655 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
656 if (!callbacks)
657 return;
659 WebData web_value;
660 WebVector<WebBlobInfo> web_blob_info;
661 PrepareWebValueAndBlobInfo(
662 value, p.blob_or_file_info, &web_value, &web_blob_info);
663 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
664 WebIDBKeyBuilder::Build(primary_key),
665 web_value,
666 web_blob_info);
668 pending_callbacks_.Remove(ipc_callbacks_id);
671 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
672 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) {
673 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
674 int32 ipc_callbacks_id = p.ipc_callbacks_id;
675 int32 ipc_cursor_id = p.ipc_cursor_id;
676 const std::vector<IndexedDBKey>& keys = p.keys;
677 const std::vector<IndexedDBKey>& primary_keys = p.primary_keys;
678 std::vector<WebData> values(p.values.size());
679 DCHECK_EQ(p.values.size(), p.blob_or_file_infos.size());
680 std::vector<WebVector<WebBlobInfo> > blob_infos(p.blob_or_file_infos.size());
681 for (size_t i = 0; i < p.values.size(); ++i) {
682 PrepareWebValueAndBlobInfo(
683 p.values[i], p.blob_or_file_infos[i], &values[i], &blob_infos[i]);
685 std::map<int32, WebIDBCursorImpl*>::const_iterator cur_iter =
686 cursors_.find(ipc_cursor_id);
687 if (cur_iter == cursors_.end())
688 return;
690 cur_iter->second->SetPrefetchData(keys, primary_keys, values, blob_infos);
692 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
693 DCHECK(callbacks);
694 cur_iter->second->CachedContinue(callbacks);
695 pending_callbacks_.Remove(ipc_callbacks_id);
698 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id,
699 int32 ipc_callbacks_id,
700 int64 existing_version) {
701 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
702 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
703 DCHECK(callbacks);
704 callbacks->onBlocked(existing_version);
707 void IndexedDBDispatcher::OnUpgradeNeeded(
708 const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
709 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
710 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id);
711 DCHECK(callbacks);
712 WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
713 DCHECK(!databases_.count(p.ipc_database_id));
714 databases_[p.ipc_database_id] =
715 new WebIDBDatabaseImpl(p.ipc_database_id,
716 p.ipc_database_callbacks_id,
717 thread_safe_sender_.get());
718 callbacks->onUpgradeNeeded(
719 p.old_version,
720 databases_[p.ipc_database_id],
721 metadata,
722 static_cast<blink::WebIDBDataLoss>(p.data_loss),
723 WebString::fromUTF8(p.data_loss_message));
726 void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
727 int32 ipc_callbacks_id,
728 int code,
729 const base::string16& message) {
730 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
731 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
732 if (!callbacks)
733 return;
734 if (message.empty())
735 callbacks->onError(WebIDBDatabaseError(code));
736 else
737 callbacks->onError(WebIDBDatabaseError(code, message));
738 pending_callbacks_.Remove(ipc_callbacks_id);
739 cursor_transaction_ids_.erase(ipc_callbacks_id);
742 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
743 int32 ipc_database_callbacks_id,
744 int64 transaction_id,
745 int code,
746 const base::string16& message) {
747 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
748 WebIDBDatabaseCallbacks* callbacks =
749 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
750 if (!callbacks)
751 return;
752 if (message.empty())
753 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code));
754 else
755 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message));
758 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id,
759 int32 ipc_database_callbacks_id,
760 int64 transaction_id) {
761 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
762 WebIDBDatabaseCallbacks* callbacks =
763 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
764 if (!callbacks)
765 return;
766 callbacks->onComplete(transaction_id);
769 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id,
770 int32 ipc_database_callbacks_id) {
771 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
772 WebIDBDatabaseCallbacks* callbacks =
773 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
774 if (!callbacks)
775 return;
776 callbacks->onForcedClose();
779 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
780 int32 ipc_database_callbacks_id,
781 int64 old_version,
782 int64 new_version) {
783 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
784 WebIDBDatabaseCallbacks* callbacks =
785 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
786 // callbacks would be NULL if a versionchange event is received after close
787 // has been called.
788 if (!callbacks)
789 return;
790 callbacks->onVersionChange(old_version, new_version);
793 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
794 int64 transaction_id,
795 int32 ipc_exception_cursor_id) {
796 typedef std::map<int32, WebIDBCursorImpl*>::iterator Iterator;
797 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
798 if (i->first == ipc_exception_cursor_id ||
799 i->second->transaction_id() != transaction_id)
800 continue;
801 i->second->ResetPrefetchCache();
805 } // namespace content