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"
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_messages.h"
18 #include "ipc/ipc_channel.h"
19 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseCallbacks.h"
20 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseError.h"
21 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
22 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBValue.h"
24 using blink::WebBlobInfo
;
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::WebIDBValue
;
34 using blink::WebString
;
35 using blink::WebVector
;
36 using base::ThreadLocalPointer
;
39 static base::LazyInstance
<ThreadLocalPointer
<IndexedDBDispatcher
> >::Leaky
40 g_idb_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
44 IndexedDBDispatcher
* const kHasBeenDeleted
=
45 reinterpret_cast<IndexedDBDispatcher
*>(0x1);
47 } // unnamed namespace
49 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender
* thread_safe_sender
)
50 : thread_safe_sender_(thread_safe_sender
) {
51 g_idb_dispatcher_tls
.Pointer()->Set(this);
54 IndexedDBDispatcher::~IndexedDBDispatcher() {
55 // Clear any pending callbacks - which may result in dispatch requests -
56 // before marking the dispatcher as deleted.
57 pending_callbacks_
.Clear();
58 pending_database_callbacks_
.Clear();
60 DCHECK(pending_callbacks_
.IsEmpty());
61 DCHECK(pending_database_callbacks_
.IsEmpty());
63 g_idb_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
66 IndexedDBDispatcher
* IndexedDBDispatcher::ThreadSpecificInstance(
67 ThreadSafeSender
* thread_safe_sender
) {
68 if (g_idb_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
69 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
70 g_idb_dispatcher_tls
.Pointer()->Set(NULL
);
72 if (g_idb_dispatcher_tls
.Pointer()->Get())
73 return g_idb_dispatcher_tls
.Pointer()->Get();
75 IndexedDBDispatcher
* dispatcher
= new IndexedDBDispatcher(thread_safe_sender
);
76 if (WorkerThread::GetCurrentId())
77 WorkerThread::AddObserver(dispatcher
);
81 void IndexedDBDispatcher::WillStopCurrentWorkerThread() {
85 WebIDBMetadata
IndexedDBDispatcher::ConvertMetadata(
86 const IndexedDBDatabaseMetadata
& idb_metadata
) {
87 WebIDBMetadata web_metadata
;
88 web_metadata
.id
= idb_metadata
.id
;
89 web_metadata
.name
= idb_metadata
.name
;
90 web_metadata
.version
= idb_metadata
.version
;
91 web_metadata
.intVersion
= idb_metadata
.int_version
;
92 web_metadata
.maxObjectStoreId
= idb_metadata
.max_object_store_id
;
93 web_metadata
.objectStores
=
94 WebVector
<WebIDBMetadata::ObjectStore
>(idb_metadata
.object_stores
.size());
96 for (size_t i
= 0; i
< idb_metadata
.object_stores
.size(); ++i
) {
97 const IndexedDBObjectStoreMetadata
& idb_store_metadata
=
98 idb_metadata
.object_stores
[i
];
99 WebIDBMetadata::ObjectStore
& web_store_metadata
=
100 web_metadata
.objectStores
[i
];
102 web_store_metadata
.id
= idb_store_metadata
.id
;
103 web_store_metadata
.name
= idb_store_metadata
.name
;
104 web_store_metadata
.keyPath
=
105 WebIDBKeyPathBuilder::Build(idb_store_metadata
.key_path
);
106 web_store_metadata
.autoIncrement
= idb_store_metadata
.auto_increment
;
107 web_store_metadata
.maxIndexId
= idb_store_metadata
.max_index_id
;
108 web_store_metadata
.indexes
=
109 WebVector
<WebIDBMetadata::Index
>(idb_store_metadata
.indexes
.size());
111 for (size_t j
= 0; j
< idb_store_metadata
.indexes
.size(); ++j
) {
112 const IndexedDBIndexMetadata
& idb_index_metadata
=
113 idb_store_metadata
.indexes
[j
];
114 WebIDBMetadata::Index
& web_index_metadata
= web_store_metadata
.indexes
[j
];
116 web_index_metadata
.id
= idb_index_metadata
.id
;
117 web_index_metadata
.name
= idb_index_metadata
.name
;
118 web_index_metadata
.keyPath
=
119 WebIDBKeyPathBuilder::Build(idb_index_metadata
.key_path
);
120 web_index_metadata
.unique
= idb_index_metadata
.unique
;
121 web_index_metadata
.multiEntry
= idb_index_metadata
.multi_entry
;
128 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
130 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher
, msg
)
131 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor
,
133 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance
,
134 OnSuccessCursorContinue
)
135 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue
,
136 OnSuccessCursorContinue
)
137 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch
,
138 OnSuccessCursorPrefetch
)
139 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase
,
140 OnSuccessIDBDatabase
)
141 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey
,
142 OnSuccessIndexedDBKey
)
143 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList
,
145 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessArray
, OnSuccessArray
)
146 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue
, OnSuccessValue
)
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger
, OnSuccessInteger
)
148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined
,
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError
, OnError
)
151 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked
, OnIntBlocked
)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded
, OnUpgradeNeeded
)
153 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose
,
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange
,
157 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort
, OnAbort
)
158 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete
, OnComplete
)
159 IPC_MESSAGE_UNHANDLED(handled
= false)
160 IPC_END_MESSAGE_MAP()
161 // If a message gets here, IndexedDBMessageFilter already determined that it
162 // is an IndexedDB message.
163 DCHECK(handled
) << "Didn't handle a message defined at line "
164 << IPC_MESSAGE_ID_LINE(msg
.type());
167 bool IndexedDBDispatcher::Send(IPC::Message
* msg
) {
168 return thread_safe_sender_
->Send(msg
);
171 void IndexedDBDispatcher::RequestIDBCursorAdvance(
173 WebIDBCallbacks
* callbacks_ptr
,
175 int64 transaction_id
) {
176 // Reset all cursor prefetch caches except for this cursor.
177 ResetCursorPrefetchCaches(transaction_id
, ipc_cursor_id
);
179 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
181 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
182 Send(new IndexedDBHostMsg_CursorAdvance(
183 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, count
));
186 void IndexedDBDispatcher::RequestIDBCursorContinue(
187 const IndexedDBKey
& key
,
188 const IndexedDBKey
& primary_key
,
189 WebIDBCallbacks
* callbacks_ptr
,
191 int64 transaction_id
) {
192 // Reset all cursor prefetch caches except for this cursor.
193 ResetCursorPrefetchCaches(transaction_id
, ipc_cursor_id
);
195 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
197 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
198 Send(new IndexedDBHostMsg_CursorContinue(
199 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, key
, primary_key
));
202 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
204 WebIDBCallbacks
* callbacks_ptr
,
205 int32 ipc_cursor_id
) {
206 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
208 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
209 Send(new IndexedDBHostMsg_CursorPrefetch(
210 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, n
));
213 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches
,
214 int unused_prefetches
,
215 int32 ipc_cursor_id
) {
216 Send(new IndexedDBHostMsg_CursorPrefetchReset(
217 ipc_cursor_id
, used_prefetches
, unused_prefetches
));
220 void IndexedDBDispatcher::RequestIDBFactoryOpen(
221 const base::string16
& name
,
223 int64 transaction_id
,
224 WebIDBCallbacks
* callbacks_ptr
,
225 WebIDBDatabaseCallbacks
* database_callbacks_ptr
,
226 const std::string
& database_identifier
) {
227 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
228 scoped_ptr
<WebIDBDatabaseCallbacks
> database_callbacks(
229 database_callbacks_ptr
);
231 IndexedDBHostMsg_FactoryOpen_Params params
;
232 params
.ipc_thread_id
= CurrentWorkerId();
233 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
234 params
.ipc_database_callbacks_id
=
235 pending_database_callbacks_
.Add(database_callbacks
.release());
236 params
.database_identifier
= database_identifier
;
238 params
.transaction_id
= transaction_id
;
239 params
.version
= version
;
240 Send(new IndexedDBHostMsg_FactoryOpen(params
));
243 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
244 WebIDBCallbacks
* callbacks_ptr
,
245 const std::string
& database_identifier
) {
246 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
248 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params
;
249 params
.ipc_thread_id
= CurrentWorkerId();
250 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
251 params
.database_identifier
= database_identifier
;
252 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params
));
255 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
256 const base::string16
& name
,
257 WebIDBCallbacks
* callbacks_ptr
,
258 const std::string
& database_identifier
) {
259 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
261 IndexedDBHostMsg_FactoryDeleteDatabase_Params params
;
262 params
.ipc_thread_id
= CurrentWorkerId();
263 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
264 params
.database_identifier
= database_identifier
;
266 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params
));
269 void IndexedDBDispatcher::RequestIDBDatabaseClose(
270 int32 ipc_database_id
,
271 int32 ipc_database_callbacks_id
) {
272 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id
));
273 // There won't be pending database callbacks if the transaction was aborted in
274 // the initial upgradeneeded event handler.
275 if (pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
))
276 pending_database_callbacks_
.Remove(ipc_database_callbacks_id
);
279 void IndexedDBDispatcher::NotifyIDBDatabaseVersionChangeIgnored(
280 int32 ipc_database_id
) {
281 Send(new IndexedDBHostMsg_DatabaseVersionChangeIgnored(ipc_database_id
));
284 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
285 int32 ipc_database_id
,
286 int64 transaction_id
,
287 WebIDBDatabaseCallbacks
* database_callbacks_ptr
,
288 WebVector
<long long> object_store_ids
,
289 blink::WebIDBTransactionMode mode
) {
290 scoped_ptr
<WebIDBDatabaseCallbacks
> database_callbacks(
291 database_callbacks_ptr
);
292 IndexedDBHostMsg_DatabaseCreateTransaction_Params params
;
293 params
.ipc_thread_id
= CurrentWorkerId();
294 params
.ipc_database_id
= ipc_database_id
;
295 params
.transaction_id
= transaction_id
;
296 params
.ipc_database_callbacks_id
=
297 pending_database_callbacks_
.Add(database_callbacks
.release());
298 params
.object_store_ids
299 .assign(object_store_ids
.data(),
300 object_store_ids
.data() + object_store_ids
.size());
303 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params
));
306 void IndexedDBDispatcher::RequestIDBDatabaseGet(
307 int32 ipc_database_id
,
308 int64 transaction_id
,
309 int64 object_store_id
,
311 const IndexedDBKeyRange
& key_range
,
313 WebIDBCallbacks
* callbacks
) {
314 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
315 IndexedDBHostMsg_DatabaseGet_Params params
;
316 init_params(¶ms
, callbacks
);
317 params
.ipc_database_id
= ipc_database_id
;
318 params
.transaction_id
= transaction_id
;
319 params
.object_store_id
= object_store_id
;
320 params
.index_id
= index_id
;
321 params
.key_range
= key_range
;
322 params
.key_only
= key_only
;
323 Send(new IndexedDBHostMsg_DatabaseGet(params
));
326 void IndexedDBDispatcher::RequestIDBDatabaseGetAll(
327 int32 ipc_database_id
,
328 int64 transaction_id
,
329 int64 object_store_id
,
331 const IndexedDBKeyRange
& key_range
,
334 WebIDBCallbacks
* callbacks
) {
335 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
336 IndexedDBHostMsg_DatabaseGetAll_Params params
;
337 init_params(¶ms
, callbacks
);
338 params
.ipc_database_id
= ipc_database_id
;
339 params
.transaction_id
= transaction_id
;
340 params
.object_store_id
= object_store_id
;
341 params
.index_id
= index_id
;
342 params
.key_range
= key_range
;
343 params
.key_only
= key_only
;
344 params
.max_count
= max_count
;
345 Send(new IndexedDBHostMsg_DatabaseGetAll(params
));
348 void IndexedDBDispatcher::RequestIDBDatabasePut(
349 int32 ipc_database_id
,
350 int64 transaction_id
,
351 int64 object_store_id
,
352 const WebData
& value
,
353 const blink::WebVector
<WebBlobInfo
>& web_blob_info
,
354 const IndexedDBKey
& key
,
355 blink::WebIDBPutMode put_mode
,
356 WebIDBCallbacks
* callbacks
,
357 const WebVector
<long long>& index_ids
,
358 const WebVector
<WebVector
<WebIDBKey
> >& index_keys
) {
359 if (value
.size() + key
.size_estimate() > max_put_value_size_
) {
360 callbacks
->onError(WebIDBDatabaseError(
361 blink::WebIDBDatabaseExceptionUnknownError
,
362 WebString::fromUTF8(base::StringPrintf(
363 "The serialized value is too large"
364 " (size=%" PRIuS
" bytes, max=%" PRIuS
" bytes).",
366 max_put_value_size_
).c_str())));
370 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
371 IndexedDBHostMsg_DatabasePut_Params params
;
372 init_params(¶ms
, callbacks
);
373 params
.ipc_database_id
= ipc_database_id
;
374 params
.transaction_id
= transaction_id
;
375 params
.object_store_id
= object_store_id
;
377 params
.value
.bits
.assign(value
.data(), value
.data() + value
.size());
379 params
.put_mode
= put_mode
;
381 DCHECK_EQ(index_ids
.size(), index_keys
.size());
382 params
.index_keys
.resize(index_ids
.size());
383 for (size_t i
= 0, len
= index_ids
.size(); i
< len
; ++i
) {
384 params
.index_keys
[i
].first
= index_ids
[i
];
385 params
.index_keys
[i
].second
.resize(index_keys
[i
].size());
386 for (size_t j
= 0; j
< index_keys
[i
].size(); ++j
) {
387 params
.index_keys
[i
].second
[j
] =
388 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys
[i
][j
]));
392 params
.value
.blob_or_file_info
.resize(web_blob_info
.size());
393 for (size_t i
= 0; i
< web_blob_info
.size(); ++i
) {
394 const WebBlobInfo
& info
= web_blob_info
[i
];
395 IndexedDBMsg_BlobOrFileInfo
& blob_or_file_info
=
396 params
.value
.blob_or_file_info
[i
];
397 blob_or_file_info
.is_file
= info
.isFile();
399 blob_or_file_info
.file_path
= info
.filePath();
400 blob_or_file_info
.file_name
= info
.fileName();
401 blob_or_file_info
.last_modified
= info
.lastModified();
403 blob_or_file_info
.size
= info
.size();
404 blob_or_file_info
.uuid
= info
.uuid().latin1();
405 DCHECK(blob_or_file_info
.uuid
.size());
406 blob_or_file_info
.mime_type
= info
.type();
409 Send(new IndexedDBHostMsg_DatabasePut(params
));
412 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
413 int32 ipc_database_id
,
414 int64 transaction_id
,
415 int64 object_store_id
,
417 const IndexedDBKeyRange
& key_range
,
418 blink::WebIDBCursorDirection direction
,
420 blink::WebIDBTaskType task_type
,
421 WebIDBCallbacks
* callbacks
) {
422 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
423 IndexedDBHostMsg_DatabaseOpenCursor_Params params
;
424 init_params(¶ms
, callbacks
);
425 params
.ipc_database_id
= ipc_database_id
;
426 params
.transaction_id
= transaction_id
;
427 params
.object_store_id
= object_store_id
;
428 params
.index_id
= index_id
;
429 params
.key_range
= key_range
;
430 params
.direction
= direction
;
431 params
.key_only
= key_only
;
432 params
.task_type
= task_type
;
433 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params
));
435 DCHECK(cursor_transaction_ids_
.find(params
.ipc_callbacks_id
) ==
436 cursor_transaction_ids_
.end());
437 cursor_transaction_ids_
[params
.ipc_callbacks_id
] = transaction_id
;
440 void IndexedDBDispatcher::RequestIDBDatabaseCount(
441 int32 ipc_database_id
,
442 int64 transaction_id
,
443 int64 object_store_id
,
445 const IndexedDBKeyRange
& key_range
,
446 WebIDBCallbacks
* callbacks
) {
447 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
448 IndexedDBHostMsg_DatabaseCount_Params params
;
449 init_params(¶ms
, callbacks
);
450 params
.ipc_database_id
= ipc_database_id
;
451 params
.transaction_id
= transaction_id
;
452 params
.object_store_id
= object_store_id
;
453 params
.index_id
= index_id
;
454 params
.key_range
= key_range
;
455 Send(new IndexedDBHostMsg_DatabaseCount(params
));
458 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
459 int32 ipc_database_id
,
460 int64 transaction_id
,
461 int64 object_store_id
,
462 const IndexedDBKeyRange
& key_range
,
463 WebIDBCallbacks
* callbacks
) {
464 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
465 IndexedDBHostMsg_DatabaseDeleteRange_Params params
;
466 init_params(¶ms
, callbacks
);
467 params
.ipc_database_id
= ipc_database_id
;
468 params
.transaction_id
= transaction_id
;
469 params
.object_store_id
= object_store_id
;
470 params
.key_range
= key_range
;
471 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params
));
474 void IndexedDBDispatcher::RequestIDBDatabaseClear(
475 int32 ipc_database_id
,
476 int64 transaction_id
,
477 int64 object_store_id
,
478 WebIDBCallbacks
* callbacks_ptr
) {
479 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
480 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
481 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
482 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
489 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id
) {
490 cursors_
.erase(ipc_cursor_id
);
493 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id
) {
494 DCHECK_EQ(databases_
.count(ipc_database_id
), 1u);
495 databases_
.erase(ipc_database_id
);
498 void IndexedDBDispatcher::OnSuccessIDBDatabase(
500 int32 ipc_callbacks_id
,
501 int32 ipc_database_callbacks_id
,
503 const IndexedDBDatabaseMetadata
& idb_metadata
) {
504 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
505 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
508 WebIDBMetadata
metadata(ConvertMetadata(idb_metadata
));
509 // If an upgrade was performed, count will be non-zero.
510 WebIDBDatabase
* database
= NULL
;
512 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
513 // May already be deleted and removed from the table, but do not recreate..
514 if (ipc_object_id
!= kNoDatabase
) {
515 DCHECK(!databases_
.count(ipc_object_id
));
516 database
= databases_
[ipc_object_id
] = new WebIDBDatabaseImpl(
517 ipc_object_id
, ipc_database_callbacks_id
, thread_safe_sender_
.get());
520 callbacks
->onSuccess(database
, metadata
);
521 pending_callbacks_
.Remove(ipc_callbacks_id
);
524 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id
,
525 int32 ipc_callbacks_id
,
526 const IndexedDBKey
& key
) {
527 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
528 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
531 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
));
532 pending_callbacks_
.Remove(ipc_callbacks_id
);
535 void IndexedDBDispatcher::OnSuccessStringList(
537 int32 ipc_callbacks_id
,
538 const std::vector
<base::string16
>& value
) {
539 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
540 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
543 callbacks
->onSuccess(WebVector
<WebString
>(value
));
544 pending_callbacks_
.Remove(ipc_callbacks_id
);
547 static void PrepareWebValue(const IndexedDBMsg_ReturnValue
& value
,
548 WebIDBValue
* web_value
) {
549 if (value
.bits
.empty())
552 web_value
->data
.assign(&*value
.bits
.begin(), value
.bits
.size());
553 blink::WebVector
<WebBlobInfo
> local_blob_info(value
.blob_or_file_info
.size());
554 for (size_t i
= 0; i
< value
.blob_or_file_info
.size(); ++i
) {
555 const IndexedDBMsg_BlobOrFileInfo
& info
= value
.blob_or_file_info
[i
];
557 local_blob_info
[i
] = WebBlobInfo(
558 WebString::fromUTF8(info
.uuid
.c_str()), info
.file_path
,
559 info
.file_name
, info
.mime_type
, info
.last_modified
, info
.size
);
561 local_blob_info
[i
] = WebBlobInfo(WebString::fromUTF8(info
.uuid
.c_str()),
562 info
.mime_type
, info
.size
);
566 web_value
->webBlobInfo
.swap(local_blob_info
);
567 web_value
->primaryKey
= WebIDBKeyBuilder::Build(value
.primary_key
);
568 web_value
->keyPath
= WebIDBKeyPathBuilder::Build(value
.key_path
);
571 static void PrepareWebValueAndBlobInfo(
572 const IndexedDBMsg_Value
& value
,
574 blink::WebVector
<WebBlobInfo
>* web_blob_info
) {
575 if (value
.bits
.empty())
578 web_value
->assign(&*value
.bits
.begin(), value
.bits
.size());
579 blink::WebVector
<WebBlobInfo
> local_blob_info(value
.blob_or_file_info
.size());
580 for (size_t i
= 0; i
< value
.blob_or_file_info
.size(); ++i
) {
581 const IndexedDBMsg_BlobOrFileInfo
& info
= value
.blob_or_file_info
[i
];
583 local_blob_info
[i
] = WebBlobInfo(WebString::fromUTF8(info
.uuid
.c_str()),
590 local_blob_info
[i
] = WebBlobInfo(
591 WebString::fromUTF8(info
.uuid
.c_str()), info
.mime_type
, info
.size
);
594 web_blob_info
->swap(local_blob_info
);
597 void IndexedDBDispatcher::OnSuccessArray(
598 const IndexedDBMsg_CallbacksSuccessArray_Params
& p
) {
599 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
600 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
601 blink::WebVector
<WebIDBValue
> web_values(p
.values
.size());
602 for (size_t i
= 0; i
< p
.values
.size(); ++i
)
603 PrepareWebValue(p
.values
[i
], &web_values
[i
]);
604 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
606 callbacks
->onSuccess(web_values
);
607 pending_callbacks_
.Remove(ipc_callbacks_id
);
610 void IndexedDBDispatcher::OnSuccessValue(
611 const IndexedDBMsg_CallbacksSuccessValue_Params
& params
) {
612 DCHECK_EQ(params
.ipc_thread_id
, CurrentWorkerId());
613 WebIDBCallbacks
* callbacks
=
614 pending_callbacks_
.Lookup(params
.ipc_callbacks_id
);
617 WebIDBValue web_value
;
618 PrepareWebValue(params
.value
, &web_value
);
619 if (params
.value
.primary_key
.IsValid()) {
620 web_value
.primaryKey
= WebIDBKeyBuilder::Build(params
.value
.primary_key
);
621 web_value
.keyPath
= WebIDBKeyPathBuilder::Build(params
.value
.key_path
);
623 callbacks
->onSuccess(web_value
);
624 cursor_transaction_ids_
.erase(params
.ipc_callbacks_id
);
625 pending_callbacks_
.Remove(params
.ipc_callbacks_id
);
628 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id
,
629 int32 ipc_callbacks_id
,
631 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
632 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
635 callbacks
->onSuccess(value
);
636 pending_callbacks_
.Remove(ipc_callbacks_id
);
639 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id
,
640 int32 ipc_callbacks_id
) {
641 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
642 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
645 callbacks
->onSuccess();
646 pending_callbacks_
.Remove(ipc_callbacks_id
);
649 void IndexedDBDispatcher::OnSuccessOpenCursor(
650 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params
& p
) {
651 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
652 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
653 int32 ipc_object_id
= p
.ipc_cursor_id
;
654 const IndexedDBKey
& key
= p
.key
;
655 const IndexedDBKey
& primary_key
= p
.primary_key
;
657 WebVector
<WebBlobInfo
> web_blob_info
;
658 PrepareWebValueAndBlobInfo(p
.value
, &web_value
, &web_blob_info
);
660 DCHECK(cursor_transaction_ids_
.find(ipc_callbacks_id
) !=
661 cursor_transaction_ids_
.end());
662 int64 transaction_id
= cursor_transaction_ids_
[ipc_callbacks_id
];
663 cursor_transaction_ids_
.erase(ipc_callbacks_id
);
665 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
669 WebIDBCursorImpl
* cursor
= new WebIDBCursorImpl(
670 ipc_object_id
, transaction_id
, thread_safe_sender_
.get());
671 cursors_
[ipc_object_id
] = cursor
;
672 callbacks
->onSuccess(cursor
,
673 WebIDBKeyBuilder::Build(key
),
674 WebIDBKeyBuilder::Build(primary_key
),
678 pending_callbacks_
.Remove(ipc_callbacks_id
);
681 void IndexedDBDispatcher::OnSuccessCursorContinue(
682 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params
& p
) {
683 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
684 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
685 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
686 const IndexedDBKey
& key
= p
.key
;
687 const IndexedDBKey
& primary_key
= p
.primary_key
;
689 if (cursors_
.find(ipc_cursor_id
) == cursors_
.end())
692 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
697 WebVector
<WebBlobInfo
> web_blob_info
;
698 PrepareWebValueAndBlobInfo(p
.value
, &web_value
, &web_blob_info
);
699 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
),
700 WebIDBKeyBuilder::Build(primary_key
),
704 pending_callbacks_
.Remove(ipc_callbacks_id
);
707 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
708 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params
& p
) {
709 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
710 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
711 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
712 const std::vector
<IndexedDBKey
>& keys
= p
.keys
;
713 const std::vector
<IndexedDBKey
>& primary_keys
= p
.primary_keys
;
714 std::vector
<WebData
> values(p
.values
.size());
715 std::vector
<WebVector
<WebBlobInfo
>> blob_infos(p
.values
.size());
716 for (size_t i
= 0; i
< p
.values
.size(); ++i
)
717 PrepareWebValueAndBlobInfo(p
.values
[i
], &values
[i
], &blob_infos
[i
]);
718 std::map
<int32
, WebIDBCursorImpl
*>::const_iterator cur_iter
=
719 cursors_
.find(ipc_cursor_id
);
720 if (cur_iter
== cursors_
.end())
723 cur_iter
->second
->SetPrefetchData(keys
, primary_keys
, values
, blob_infos
);
725 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
727 cur_iter
->second
->CachedContinue(callbacks
);
728 pending_callbacks_
.Remove(ipc_callbacks_id
);
731 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id
,
732 int32 ipc_callbacks_id
,
733 int64 existing_version
) {
734 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
735 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
737 callbacks
->onBlocked(existing_version
);
740 void IndexedDBDispatcher::OnUpgradeNeeded(
741 const IndexedDBMsg_CallbacksUpgradeNeeded_Params
& p
) {
742 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
743 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(p
.ipc_callbacks_id
);
745 WebIDBMetadata
metadata(ConvertMetadata(p
.idb_metadata
));
746 DCHECK(!databases_
.count(p
.ipc_database_id
));
747 databases_
[p
.ipc_database_id
] =
748 new WebIDBDatabaseImpl(p
.ipc_database_id
,
749 p
.ipc_database_callbacks_id
,
750 thread_safe_sender_
.get());
751 callbacks
->onUpgradeNeeded(
753 databases_
[p
.ipc_database_id
],
755 static_cast<blink::WebIDBDataLoss
>(p
.data_loss
),
756 WebString::fromUTF8(p
.data_loss_message
));
759 void IndexedDBDispatcher::OnError(int32 ipc_thread_id
,
760 int32 ipc_callbacks_id
,
762 const base::string16
& message
) {
763 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
764 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
768 callbacks
->onError(WebIDBDatabaseError(code
));
770 callbacks
->onError(WebIDBDatabaseError(code
, message
));
771 pending_callbacks_
.Remove(ipc_callbacks_id
);
772 cursor_transaction_ids_
.erase(ipc_callbacks_id
);
775 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id
,
776 int32 ipc_database_callbacks_id
,
777 int64 transaction_id
,
779 const base::string16
& message
) {
780 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
781 WebIDBDatabaseCallbacks
* callbacks
=
782 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
786 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
));
788 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
, message
));
791 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id
,
792 int32 ipc_database_callbacks_id
,
793 int64 transaction_id
) {
794 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
795 WebIDBDatabaseCallbacks
* callbacks
=
796 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
799 callbacks
->onComplete(transaction_id
);
802 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id
,
803 int32 ipc_database_callbacks_id
) {
804 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
805 WebIDBDatabaseCallbacks
* callbacks
=
806 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
809 callbacks
->onForcedClose();
812 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id
,
813 int32 ipc_database_callbacks_id
,
816 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
817 WebIDBDatabaseCallbacks
* callbacks
=
818 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
819 // callbacks would be NULL if a versionchange event is received after close
823 callbacks
->onVersionChange(old_version
, new_version
);
826 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
827 int64 transaction_id
,
828 int32 ipc_exception_cursor_id
) {
829 typedef std::map
<int32
, WebIDBCursorImpl
*>::iterator Iterator
;
830 for (Iterator i
= cursors_
.begin(); i
!= cursors_
.end(); ++i
) {
831 if (i
->first
== ipc_exception_cursor_id
||
832 i
->second
->transaction_id() != transaction_id
)
834 i
->second
->ResetPrefetchCache();
838 } // namespace content