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_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
;
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
;
38 static base::LazyInstance
<ThreadLocalPointer
<IndexedDBDispatcher
> >::Leaky
39 g_idb_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
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
);
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
.key_path
);
107 web_store_metadata
.autoIncrement
= idb_store_metadata
.auto_increment
;
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
.key_path
);
121 web_index_metadata
.unique
= idb_index_metadata
.unique
;
122 web_index_metadata
.multiEntry
= idb_index_metadata
.multi_entry
;
129 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
131 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher
, msg
)
132 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor
,
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
,
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
,
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
,
157 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange
,
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(
175 WebIDBCallbacks
* callbacks_ptr
,
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
,
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(
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
,
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
;
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
;
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());
305 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params
));
308 void IndexedDBDispatcher::RequestIDBDatabaseGet(
309 int32 ipc_database_id
,
310 int64 transaction_id
,
311 int64 object_store_id
,
313 const IndexedDBKeyRange
& key_range
,
315 WebIDBCallbacks
* callbacks
) {
316 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
317 IndexedDBHostMsg_DatabaseGet_Params params
;
318 init_params(¶ms
, 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).",
346 kMaxIDBValueSizeInBytes
).c_str())));
350 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
351 IndexedDBHostMsg_DatabasePut_Params params
;
352 init_params(¶ms
, 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
.bits
.assign(value
.data(), value
.data() + value
.size());
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
.value
.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
.value
.blob_or_file_info
[i
];
377 blob_or_file_info
.is_file
= 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
,
397 const IndexedDBKeyRange
& key_range
,
398 blink::WebIDBCursorDirection direction
,
400 blink::WebIDBTaskType task_type
,
401 WebIDBCallbacks
* callbacks
) {
402 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
403 IndexedDBHostMsg_DatabaseOpenCursor_Params params
;
404 init_params(¶ms
, 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
,
425 const IndexedDBKeyRange
& key_range
,
426 WebIDBCallbacks
* callbacks
) {
427 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
428 IndexedDBHostMsg_DatabaseCount_Params params
;
429 init_params(¶ms
, 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(¶ms
, 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(),
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(
480 int32 ipc_callbacks_id
,
481 int32 ipc_database_callbacks_id
,
483 const IndexedDBDatabaseMetadata
& idb_metadata
) {
484 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
485 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
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
);
511 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
));
512 pending_callbacks_
.Remove(ipc_callbacks_id
);
515 void IndexedDBDispatcher::OnSuccessStringList(
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
);
523 callbacks
->onSuccess(WebVector
<WebString
>(value
));
524 pending_callbacks_
.Remove(ipc_callbacks_id
);
527 static void PrepareWebValueAndBlobInfo(
528 const IndexedDBMsg_Value
& value
,
530 blink::WebVector
<WebBlobInfo
>* web_blob_info
) {
531 if (value
.bits
.empty())
534 web_value
->assign(&*value
.bits
.begin(), value
.bits
.size());
535 blink::WebVector
<WebBlobInfo
> local_blob_info(value
.blob_or_file_info
.size());
536 for (size_t i
= 0; i
< value
.blob_or_file_info
.size(); ++i
) {
537 const IndexedDBMsg_BlobOrFileInfo
& info
= value
.blob_or_file_info
[i
];
539 local_blob_info
[i
] = WebBlobInfo(WebString::fromUTF8(info
.uuid
.c_str()),
546 local_blob_info
[i
] = WebBlobInfo(
547 WebString::fromUTF8(info
.uuid
.c_str()), info
.mime_type
, info
.size
);
550 web_blob_info
->swap(local_blob_info
);
553 void IndexedDBDispatcher::OnSuccessValue(
554 const IndexedDBMsg_CallbacksSuccessValue_Params
& params
) {
555 DCHECK_EQ(params
.ipc_thread_id
, CurrentWorkerId());
556 WebIDBCallbacks
* callbacks
=
557 pending_callbacks_
.Lookup(params
.ipc_callbacks_id
);
561 WebVector
<WebBlobInfo
> web_blob_info
;
562 PrepareWebValueAndBlobInfo(params
.value
, &web_value
, &web_blob_info
);
563 callbacks
->onSuccess(web_value
, web_blob_info
);
564 pending_callbacks_
.Remove(params
.ipc_callbacks_id
);
565 cursor_transaction_ids_
.erase(params
.ipc_callbacks_id
);
568 void IndexedDBDispatcher::OnSuccessValueWithKey(
569 const IndexedDBMsg_CallbacksSuccessValueWithKey_Params
& params
) {
570 DCHECK_EQ(params
.ipc_thread_id
, CurrentWorkerId());
571 WebIDBCallbacks
* callbacks
=
572 pending_callbacks_
.Lookup(params
.ipc_callbacks_id
);
576 WebVector
<WebBlobInfo
> web_blob_info
;
577 PrepareWebValueAndBlobInfo(params
.value
, &web_value
, &web_blob_info
);
578 callbacks
->onSuccess(web_value
,
580 WebIDBKeyBuilder::Build(params
.primary_key
),
581 WebIDBKeyPathBuilder::Build(params
.key_path
));
582 pending_callbacks_
.Remove(params
.ipc_callbacks_id
);
585 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id
,
586 int32 ipc_callbacks_id
,
588 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
589 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
592 callbacks
->onSuccess(value
);
593 pending_callbacks_
.Remove(ipc_callbacks_id
);
596 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id
,
597 int32 ipc_callbacks_id
) {
598 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
599 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
602 callbacks
->onSuccess();
603 pending_callbacks_
.Remove(ipc_callbacks_id
);
606 void IndexedDBDispatcher::OnSuccessOpenCursor(
607 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params
& p
) {
608 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
609 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
610 int32 ipc_object_id
= p
.ipc_cursor_id
;
611 const IndexedDBKey
& key
= p
.key
;
612 const IndexedDBKey
& primary_key
= p
.primary_key
;
614 WebVector
<WebBlobInfo
> web_blob_info
;
615 PrepareWebValueAndBlobInfo(p
.value
, &web_value
, &web_blob_info
);
617 DCHECK(cursor_transaction_ids_
.find(ipc_callbacks_id
) !=
618 cursor_transaction_ids_
.end());
619 int64 transaction_id
= cursor_transaction_ids_
[ipc_callbacks_id
];
620 cursor_transaction_ids_
.erase(ipc_callbacks_id
);
622 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
626 WebIDBCursorImpl
* cursor
= new WebIDBCursorImpl(
627 ipc_object_id
, transaction_id
, thread_safe_sender_
.get());
628 cursors_
[ipc_object_id
] = cursor
;
629 callbacks
->onSuccess(cursor
,
630 WebIDBKeyBuilder::Build(key
),
631 WebIDBKeyBuilder::Build(primary_key
),
635 pending_callbacks_
.Remove(ipc_callbacks_id
);
638 void IndexedDBDispatcher::OnSuccessCursorContinue(
639 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params
& p
) {
640 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
641 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
642 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
643 const IndexedDBKey
& key
= p
.key
;
644 const IndexedDBKey
& primary_key
= p
.primary_key
;
646 if (cursors_
.find(ipc_cursor_id
) == cursors_
.end())
649 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
654 WebVector
<WebBlobInfo
> web_blob_info
;
655 PrepareWebValueAndBlobInfo(p
.value
, &web_value
, &web_blob_info
);
656 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
),
657 WebIDBKeyBuilder::Build(primary_key
),
661 pending_callbacks_
.Remove(ipc_callbacks_id
);
664 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
665 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params
& p
) {
666 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
667 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
668 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
669 const std::vector
<IndexedDBKey
>& keys
= p
.keys
;
670 const std::vector
<IndexedDBKey
>& primary_keys
= p
.primary_keys
;
671 std::vector
<WebData
> values(p
.values
.size());
672 std::vector
<WebVector
<WebBlobInfo
>> blob_infos(p
.values
.size());
673 for (size_t i
= 0; i
< p
.values
.size(); ++i
)
674 PrepareWebValueAndBlobInfo(p
.values
[i
], &values
[i
], &blob_infos
[i
]);
675 std::map
<int32
, WebIDBCursorImpl
*>::const_iterator cur_iter
=
676 cursors_
.find(ipc_cursor_id
);
677 if (cur_iter
== cursors_
.end())
680 cur_iter
->second
->SetPrefetchData(keys
, primary_keys
, values
, blob_infos
);
682 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
684 cur_iter
->second
->CachedContinue(callbacks
);
685 pending_callbacks_
.Remove(ipc_callbacks_id
);
688 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id
,
689 int32 ipc_callbacks_id
,
690 int64 existing_version
) {
691 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
692 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
694 callbacks
->onBlocked(existing_version
);
697 void IndexedDBDispatcher::OnUpgradeNeeded(
698 const IndexedDBMsg_CallbacksUpgradeNeeded_Params
& p
) {
699 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
700 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(p
.ipc_callbacks_id
);
702 WebIDBMetadata
metadata(ConvertMetadata(p
.idb_metadata
));
703 DCHECK(!databases_
.count(p
.ipc_database_id
));
704 databases_
[p
.ipc_database_id
] =
705 new WebIDBDatabaseImpl(p
.ipc_database_id
,
706 p
.ipc_database_callbacks_id
,
707 thread_safe_sender_
.get());
708 callbacks
->onUpgradeNeeded(
710 databases_
[p
.ipc_database_id
],
712 static_cast<blink::WebIDBDataLoss
>(p
.data_loss
),
713 WebString::fromUTF8(p
.data_loss_message
));
716 void IndexedDBDispatcher::OnError(int32 ipc_thread_id
,
717 int32 ipc_callbacks_id
,
719 const base::string16
& message
) {
720 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
721 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
725 callbacks
->onError(WebIDBDatabaseError(code
));
727 callbacks
->onError(WebIDBDatabaseError(code
, message
));
728 pending_callbacks_
.Remove(ipc_callbacks_id
);
729 cursor_transaction_ids_
.erase(ipc_callbacks_id
);
732 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id
,
733 int32 ipc_database_callbacks_id
,
734 int64 transaction_id
,
736 const base::string16
& message
) {
737 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
738 WebIDBDatabaseCallbacks
* callbacks
=
739 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
743 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
));
745 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
, message
));
748 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id
,
749 int32 ipc_database_callbacks_id
,
750 int64 transaction_id
) {
751 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
752 WebIDBDatabaseCallbacks
* callbacks
=
753 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
756 callbacks
->onComplete(transaction_id
);
759 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id
,
760 int32 ipc_database_callbacks_id
) {
761 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
762 WebIDBDatabaseCallbacks
* callbacks
=
763 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
766 callbacks
->onForcedClose();
769 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id
,
770 int32 ipc_database_callbacks_id
,
773 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
774 WebIDBDatabaseCallbacks
* callbacks
=
775 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
776 // callbacks would be NULL if a versionchange event is received after close
780 callbacks
->onVersionChange(old_version
, new_version
);
783 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
784 int64 transaction_id
,
785 int32 ipc_exception_cursor_id
) {
786 typedef std::map
<int32
, WebIDBCursorImpl
*>::iterator Iterator
;
787 for (Iterator i
= cursors_
.begin(); i
!= cursors_
.end(); ++i
) {
788 if (i
->first
== ipc_exception_cursor_id
||
789 i
->second
->transaction_id() != transaction_id
)
791 i
->second
->ResetPrefetchCache();
795 } // namespace content