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/modules/indexeddb/WebIDBDatabaseCallbacks.h"
21 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseError.h"
22 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
23 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBValue.h"
25 using blink::WebBlobInfo
;
27 using blink::WebIDBCallbacks
;
28 using blink::WebIDBCursor
;
29 using blink::WebIDBDatabase
;
30 using blink::WebIDBDatabaseCallbacks
;
31 using blink::WebIDBDatabaseError
;
32 using blink::WebIDBKey
;
33 using blink::WebIDBMetadata
;
34 using blink::WebIDBValue
;
35 using blink::WebString
;
36 using blink::WebVector
;
37 using base::ThreadLocalPointer
;
40 static base::LazyInstance
<ThreadLocalPointer
<IndexedDBDispatcher
> >::Leaky
41 g_idb_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
45 IndexedDBDispatcher
* const kHasBeenDeleted
=
46 reinterpret_cast<IndexedDBDispatcher
*>(0x1);
48 } // unnamed namespace
50 const size_t kMaxIDBValueSizeInBytes
=
51 IPC::Channel::kMaximumMessageSize
- kMaxIDBMessageOverhead
;
53 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender
* thread_safe_sender
)
54 : thread_safe_sender_(thread_safe_sender
),
55 max_put_value_size_(kMaxIDBValueSizeInBytes
) {
56 g_idb_dispatcher_tls
.Pointer()->Set(this);
59 IndexedDBDispatcher::~IndexedDBDispatcher() {
60 // Clear any pending callbacks - which may result in dispatch requests -
61 // before marking the dispatcher as deleted.
62 pending_callbacks_
.Clear();
63 pending_database_callbacks_
.Clear();
65 DCHECK(pending_callbacks_
.IsEmpty());
66 DCHECK(pending_database_callbacks_
.IsEmpty());
68 g_idb_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
71 IndexedDBDispatcher
* IndexedDBDispatcher::ThreadSpecificInstance(
72 ThreadSafeSender
* thread_safe_sender
) {
73 if (g_idb_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
74 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
75 g_idb_dispatcher_tls
.Pointer()->Set(NULL
);
77 if (g_idb_dispatcher_tls
.Pointer()->Get())
78 return g_idb_dispatcher_tls
.Pointer()->Get();
80 IndexedDBDispatcher
* dispatcher
= new IndexedDBDispatcher(thread_safe_sender
);
81 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
82 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
86 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
88 WebIDBMetadata
IndexedDBDispatcher::ConvertMetadata(
89 const IndexedDBDatabaseMetadata
& idb_metadata
) {
90 WebIDBMetadata web_metadata
;
91 web_metadata
.id
= idb_metadata
.id
;
92 web_metadata
.name
= idb_metadata
.name
;
93 web_metadata
.version
= idb_metadata
.version
;
94 web_metadata
.intVersion
= idb_metadata
.int_version
;
95 web_metadata
.maxObjectStoreId
= idb_metadata
.max_object_store_id
;
96 web_metadata
.objectStores
=
97 WebVector
<WebIDBMetadata::ObjectStore
>(idb_metadata
.object_stores
.size());
99 for (size_t i
= 0; i
< idb_metadata
.object_stores
.size(); ++i
) {
100 const IndexedDBObjectStoreMetadata
& idb_store_metadata
=
101 idb_metadata
.object_stores
[i
];
102 WebIDBMetadata::ObjectStore
& web_store_metadata
=
103 web_metadata
.objectStores
[i
];
105 web_store_metadata
.id
= idb_store_metadata
.id
;
106 web_store_metadata
.name
= idb_store_metadata
.name
;
107 web_store_metadata
.keyPath
=
108 WebIDBKeyPathBuilder::Build(idb_store_metadata
.key_path
);
109 web_store_metadata
.autoIncrement
= idb_store_metadata
.auto_increment
;
110 web_store_metadata
.maxIndexId
= idb_store_metadata
.max_index_id
;
111 web_store_metadata
.indexes
=
112 WebVector
<WebIDBMetadata::Index
>(idb_store_metadata
.indexes
.size());
114 for (size_t j
= 0; j
< idb_store_metadata
.indexes
.size(); ++j
) {
115 const IndexedDBIndexMetadata
& idb_index_metadata
=
116 idb_store_metadata
.indexes
[j
];
117 WebIDBMetadata::Index
& web_index_metadata
= web_store_metadata
.indexes
[j
];
119 web_index_metadata
.id
= idb_index_metadata
.id
;
120 web_index_metadata
.name
= idb_index_metadata
.name
;
121 web_index_metadata
.keyPath
=
122 WebIDBKeyPathBuilder::Build(idb_index_metadata
.key_path
);
123 web_index_metadata
.unique
= idb_index_metadata
.unique
;
124 web_index_metadata
.multiEntry
= idb_index_metadata
.multi_entry
;
131 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
133 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher
, msg
)
134 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor
,
136 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance
,
137 OnSuccessCursorContinue
)
138 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue
,
139 OnSuccessCursorContinue
)
140 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch
,
141 OnSuccessCursorPrefetch
)
142 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase
,
143 OnSuccessIDBDatabase
)
144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey
,
145 OnSuccessIndexedDBKey
)
146 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList
,
148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessArray
, OnSuccessArray
)
149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue
, OnSuccessValue
)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger
, OnSuccessInteger
)
151 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined
,
153 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError
, OnError
)
154 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked
, OnIntBlocked
)
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded
, OnUpgradeNeeded
)
156 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose
,
158 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange
,
160 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort
, OnAbort
)
161 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete
, OnComplete
)
162 IPC_MESSAGE_UNHANDLED(handled
= false)
163 IPC_END_MESSAGE_MAP()
164 // If a message gets here, IndexedDBMessageFilter already determined that it
165 // is an IndexedDB message.
166 DCHECK(handled
) << "Didn't handle a message defined at line "
167 << IPC_MESSAGE_ID_LINE(msg
.type());
170 bool IndexedDBDispatcher::Send(IPC::Message
* msg
) {
171 return thread_safe_sender_
->Send(msg
);
174 void IndexedDBDispatcher::RequestIDBCursorAdvance(
176 WebIDBCallbacks
* callbacks_ptr
,
178 int64 transaction_id
) {
179 // Reset all cursor prefetch caches except for this cursor.
180 ResetCursorPrefetchCaches(transaction_id
, ipc_cursor_id
);
182 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
184 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
185 Send(new IndexedDBHostMsg_CursorAdvance(
186 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, count
));
189 void IndexedDBDispatcher::RequestIDBCursorContinue(
190 const IndexedDBKey
& key
,
191 const IndexedDBKey
& primary_key
,
192 WebIDBCallbacks
* callbacks_ptr
,
194 int64 transaction_id
) {
195 // Reset all cursor prefetch caches except for this cursor.
196 ResetCursorPrefetchCaches(transaction_id
, ipc_cursor_id
);
198 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
200 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
201 Send(new IndexedDBHostMsg_CursorContinue(
202 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, key
, primary_key
));
205 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
207 WebIDBCallbacks
* callbacks_ptr
,
208 int32 ipc_cursor_id
) {
209 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
211 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
212 Send(new IndexedDBHostMsg_CursorPrefetch(
213 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, n
));
216 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches
,
217 int unused_prefetches
,
218 int32 ipc_cursor_id
) {
219 Send(new IndexedDBHostMsg_CursorPrefetchReset(
220 ipc_cursor_id
, used_prefetches
, unused_prefetches
));
223 void IndexedDBDispatcher::RequestIDBFactoryOpen(
224 const base::string16
& name
,
226 int64 transaction_id
,
227 WebIDBCallbacks
* callbacks_ptr
,
228 WebIDBDatabaseCallbacks
* database_callbacks_ptr
,
229 const std::string
& database_identifier
) {
230 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
231 scoped_ptr
<WebIDBDatabaseCallbacks
> database_callbacks(
232 database_callbacks_ptr
);
234 IndexedDBHostMsg_FactoryOpen_Params params
;
235 params
.ipc_thread_id
= CurrentWorkerId();
236 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
237 params
.ipc_database_callbacks_id
=
238 pending_database_callbacks_
.Add(database_callbacks
.release());
239 params
.database_identifier
= database_identifier
;
241 params
.transaction_id
= transaction_id
;
242 params
.version
= version
;
243 Send(new IndexedDBHostMsg_FactoryOpen(params
));
246 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
247 WebIDBCallbacks
* callbacks_ptr
,
248 const std::string
& database_identifier
) {
249 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
251 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params
;
252 params
.ipc_thread_id
= CurrentWorkerId();
253 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
254 params
.database_identifier
= database_identifier
;
255 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params
));
258 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
259 const base::string16
& name
,
260 WebIDBCallbacks
* callbacks_ptr
,
261 const std::string
& database_identifier
) {
262 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
264 IndexedDBHostMsg_FactoryDeleteDatabase_Params params
;
265 params
.ipc_thread_id
= CurrentWorkerId();
266 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
267 params
.database_identifier
= database_identifier
;
269 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params
));
272 void IndexedDBDispatcher::RequestIDBDatabaseClose(
273 int32 ipc_database_id
,
274 int32 ipc_database_callbacks_id
) {
275 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id
));
276 // There won't be pending database callbacks if the transaction was aborted in
277 // the initial upgradeneeded event handler.
278 if (pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
))
279 pending_database_callbacks_
.Remove(ipc_database_callbacks_id
);
282 void IndexedDBDispatcher::NotifyIDBDatabaseVersionChangeIgnored(
283 int32 ipc_database_id
) {
284 Send(new IndexedDBHostMsg_DatabaseVersionChangeIgnored(ipc_database_id
));
287 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
288 int32 ipc_database_id
,
289 int64 transaction_id
,
290 WebIDBDatabaseCallbacks
* database_callbacks_ptr
,
291 WebVector
<long long> object_store_ids
,
292 blink::WebIDBTransactionMode mode
) {
293 scoped_ptr
<WebIDBDatabaseCallbacks
> database_callbacks(
294 database_callbacks_ptr
);
295 IndexedDBHostMsg_DatabaseCreateTransaction_Params params
;
296 params
.ipc_thread_id
= CurrentWorkerId();
297 params
.ipc_database_id
= ipc_database_id
;
298 params
.transaction_id
= transaction_id
;
299 params
.ipc_database_callbacks_id
=
300 pending_database_callbacks_
.Add(database_callbacks
.release());
301 params
.object_store_ids
302 .assign(object_store_ids
.data(),
303 object_store_ids
.data() + object_store_ids
.size());
306 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params
));
309 void IndexedDBDispatcher::RequestIDBDatabaseGet(
310 int32 ipc_database_id
,
311 int64 transaction_id
,
312 int64 object_store_id
,
314 const IndexedDBKeyRange
& key_range
,
316 WebIDBCallbacks
* callbacks
) {
317 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
318 IndexedDBHostMsg_DatabaseGet_Params params
;
319 init_params(¶ms
, callbacks
);
320 params
.ipc_database_id
= ipc_database_id
;
321 params
.transaction_id
= transaction_id
;
322 params
.object_store_id
= object_store_id
;
323 params
.index_id
= index_id
;
324 params
.key_range
= key_range
;
325 params
.key_only
= key_only
;
326 Send(new IndexedDBHostMsg_DatabaseGet(params
));
329 void IndexedDBDispatcher::RequestIDBDatabaseGetAll(
330 int32 ipc_database_id
,
331 int64 transaction_id
,
332 int64 object_store_id
,
334 const IndexedDBKeyRange
& key_range
,
337 WebIDBCallbacks
* callbacks
) {
338 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
339 IndexedDBHostMsg_DatabaseGetAll_Params params
;
340 init_params(¶ms
, callbacks
);
341 params
.ipc_database_id
= ipc_database_id
;
342 params
.transaction_id
= transaction_id
;
343 params
.object_store_id
= object_store_id
;
344 params
.index_id
= index_id
;
345 params
.key_range
= key_range
;
346 params
.key_only
= key_only
;
347 params
.max_count
= max_count
;
348 Send(new IndexedDBHostMsg_DatabaseGetAll(params
));
351 void IndexedDBDispatcher::RequestIDBDatabasePut(
352 int32 ipc_database_id
,
353 int64 transaction_id
,
354 int64 object_store_id
,
355 const WebData
& value
,
356 const blink::WebVector
<WebBlobInfo
>& web_blob_info
,
357 const IndexedDBKey
& key
,
358 blink::WebIDBPutMode put_mode
,
359 WebIDBCallbacks
* callbacks
,
360 const WebVector
<long long>& index_ids
,
361 const WebVector
<WebVector
<WebIDBKey
> >& index_keys
) {
362 if (value
.size() + key
.size_estimate() > max_put_value_size_
) {
363 callbacks
->onError(WebIDBDatabaseError(
364 blink::WebIDBDatabaseExceptionUnknownError
,
365 WebString::fromUTF8(base::StringPrintf(
366 "The serialized value is too large"
367 " (size=%" PRIuS
" bytes, max=%" PRIuS
" bytes).",
369 max_put_value_size_
).c_str())));
373 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
374 IndexedDBHostMsg_DatabasePut_Params params
;
375 init_params(¶ms
, callbacks
);
376 params
.ipc_database_id
= ipc_database_id
;
377 params
.transaction_id
= transaction_id
;
378 params
.object_store_id
= object_store_id
;
380 params
.value
.bits
.assign(value
.data(), value
.data() + value
.size());
382 params
.put_mode
= put_mode
;
384 DCHECK_EQ(index_ids
.size(), index_keys
.size());
385 params
.index_keys
.resize(index_ids
.size());
386 for (size_t i
= 0, len
= index_ids
.size(); i
< len
; ++i
) {
387 params
.index_keys
[i
].first
= index_ids
[i
];
388 params
.index_keys
[i
].second
.resize(index_keys
[i
].size());
389 for (size_t j
= 0; j
< index_keys
[i
].size(); ++j
) {
390 params
.index_keys
[i
].second
[j
] =
391 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys
[i
][j
]));
395 params
.value
.blob_or_file_info
.resize(web_blob_info
.size());
396 for (size_t i
= 0; i
< web_blob_info
.size(); ++i
) {
397 const WebBlobInfo
& info
= web_blob_info
[i
];
398 IndexedDBMsg_BlobOrFileInfo
& blob_or_file_info
=
399 params
.value
.blob_or_file_info
[i
];
400 blob_or_file_info
.is_file
= info
.isFile();
402 blob_or_file_info
.file_path
= info
.filePath();
403 blob_or_file_info
.file_name
= info
.fileName();
404 blob_or_file_info
.last_modified
= info
.lastModified();
406 blob_or_file_info
.size
= info
.size();
407 blob_or_file_info
.uuid
= info
.uuid().latin1();
408 DCHECK(blob_or_file_info
.uuid
.size());
409 blob_or_file_info
.mime_type
= info
.type();
412 Send(new IndexedDBHostMsg_DatabasePut(params
));
415 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
416 int32 ipc_database_id
,
417 int64 transaction_id
,
418 int64 object_store_id
,
420 const IndexedDBKeyRange
& key_range
,
421 blink::WebIDBCursorDirection direction
,
423 blink::WebIDBTaskType task_type
,
424 WebIDBCallbacks
* callbacks
) {
425 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
426 IndexedDBHostMsg_DatabaseOpenCursor_Params params
;
427 init_params(¶ms
, callbacks
);
428 params
.ipc_database_id
= ipc_database_id
;
429 params
.transaction_id
= transaction_id
;
430 params
.object_store_id
= object_store_id
;
431 params
.index_id
= index_id
;
432 params
.key_range
= key_range
;
433 params
.direction
= direction
;
434 params
.key_only
= key_only
;
435 params
.task_type
= task_type
;
436 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params
));
438 DCHECK(cursor_transaction_ids_
.find(params
.ipc_callbacks_id
) ==
439 cursor_transaction_ids_
.end());
440 cursor_transaction_ids_
[params
.ipc_callbacks_id
] = transaction_id
;
443 void IndexedDBDispatcher::RequestIDBDatabaseCount(
444 int32 ipc_database_id
,
445 int64 transaction_id
,
446 int64 object_store_id
,
448 const IndexedDBKeyRange
& key_range
,
449 WebIDBCallbacks
* callbacks
) {
450 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
451 IndexedDBHostMsg_DatabaseCount_Params params
;
452 init_params(¶ms
, callbacks
);
453 params
.ipc_database_id
= ipc_database_id
;
454 params
.transaction_id
= transaction_id
;
455 params
.object_store_id
= object_store_id
;
456 params
.index_id
= index_id
;
457 params
.key_range
= key_range
;
458 Send(new IndexedDBHostMsg_DatabaseCount(params
));
461 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
462 int32 ipc_database_id
,
463 int64 transaction_id
,
464 int64 object_store_id
,
465 const IndexedDBKeyRange
& key_range
,
466 WebIDBCallbacks
* callbacks
) {
467 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
468 IndexedDBHostMsg_DatabaseDeleteRange_Params params
;
469 init_params(¶ms
, callbacks
);
470 params
.ipc_database_id
= ipc_database_id
;
471 params
.transaction_id
= transaction_id
;
472 params
.object_store_id
= object_store_id
;
473 params
.key_range
= key_range
;
474 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params
));
477 void IndexedDBDispatcher::RequestIDBDatabaseClear(
478 int32 ipc_database_id
,
479 int64 transaction_id
,
480 int64 object_store_id
,
481 WebIDBCallbacks
* callbacks_ptr
) {
482 ResetCursorPrefetchCaches(transaction_id
, kAllCursors
);
483 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
484 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
485 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
492 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id
) {
493 cursors_
.erase(ipc_cursor_id
);
496 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id
) {
497 DCHECK_EQ(databases_
.count(ipc_database_id
), 1u);
498 databases_
.erase(ipc_database_id
);
501 void IndexedDBDispatcher::OnSuccessIDBDatabase(
503 int32 ipc_callbacks_id
,
504 int32 ipc_database_callbacks_id
,
506 const IndexedDBDatabaseMetadata
& idb_metadata
) {
507 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
508 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
511 WebIDBMetadata
metadata(ConvertMetadata(idb_metadata
));
512 // If an upgrade was performed, count will be non-zero.
513 WebIDBDatabase
* database
= NULL
;
515 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
516 // May already be deleted and removed from the table, but do not recreate..
517 if (ipc_object_id
!= kNoDatabase
) {
518 DCHECK(!databases_
.count(ipc_object_id
));
519 database
= databases_
[ipc_object_id
] = new WebIDBDatabaseImpl(
520 ipc_object_id
, ipc_database_callbacks_id
, thread_safe_sender_
.get());
523 callbacks
->onSuccess(database
, metadata
);
524 pending_callbacks_
.Remove(ipc_callbacks_id
);
527 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id
,
528 int32 ipc_callbacks_id
,
529 const IndexedDBKey
& key
) {
530 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
531 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
534 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
));
535 pending_callbacks_
.Remove(ipc_callbacks_id
);
538 void IndexedDBDispatcher::OnSuccessStringList(
540 int32 ipc_callbacks_id
,
541 const std::vector
<base::string16
>& value
) {
542 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
543 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
546 callbacks
->onSuccess(WebVector
<WebString
>(value
));
547 pending_callbacks_
.Remove(ipc_callbacks_id
);
550 static void PrepareWebValue(const IndexedDBMsg_ReturnValue
& value
,
551 WebIDBValue
* web_value
) {
552 if (value
.bits
.empty())
555 web_value
->data
.assign(&*value
.bits
.begin(), value
.bits
.size());
556 blink::WebVector
<WebBlobInfo
> local_blob_info(value
.blob_or_file_info
.size());
557 for (size_t i
= 0; i
< value
.blob_or_file_info
.size(); ++i
) {
558 const IndexedDBMsg_BlobOrFileInfo
& info
= value
.blob_or_file_info
[i
];
560 local_blob_info
[i
] = WebBlobInfo(
561 WebString::fromUTF8(info
.uuid
.c_str()), info
.file_path
,
562 info
.file_name
, info
.mime_type
, info
.last_modified
, info
.size
);
564 local_blob_info
[i
] = WebBlobInfo(WebString::fromUTF8(info
.uuid
.c_str()),
565 info
.mime_type
, info
.size
);
569 web_value
->webBlobInfo
.swap(local_blob_info
);
570 web_value
->primaryKey
= WebIDBKeyBuilder::Build(value
.primary_key
);
571 web_value
->keyPath
= WebIDBKeyPathBuilder::Build(value
.key_path
);
574 static void PrepareWebValueAndBlobInfo(
575 const IndexedDBMsg_Value
& value
,
577 blink::WebVector
<WebBlobInfo
>* web_blob_info
) {
578 if (value
.bits
.empty())
581 web_value
->assign(&*value
.bits
.begin(), value
.bits
.size());
582 blink::WebVector
<WebBlobInfo
> local_blob_info(value
.blob_or_file_info
.size());
583 for (size_t i
= 0; i
< value
.blob_or_file_info
.size(); ++i
) {
584 const IndexedDBMsg_BlobOrFileInfo
& info
= value
.blob_or_file_info
[i
];
586 local_blob_info
[i
] = WebBlobInfo(WebString::fromUTF8(info
.uuid
.c_str()),
593 local_blob_info
[i
] = WebBlobInfo(
594 WebString::fromUTF8(info
.uuid
.c_str()), info
.mime_type
, info
.size
);
597 web_blob_info
->swap(local_blob_info
);
600 void IndexedDBDispatcher::OnSuccessArray(
601 const IndexedDBMsg_CallbacksSuccessArray_Params
& p
) {
602 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
603 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
604 blink::WebVector
<WebIDBValue
> web_values(p
.values
.size());
605 for (size_t i
= 0; i
< p
.values
.size(); ++i
)
606 PrepareWebValue(p
.values
[i
], &web_values
[i
]);
607 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
609 callbacks
->onSuccess(web_values
);
610 pending_callbacks_
.Remove(ipc_callbacks_id
);
613 void IndexedDBDispatcher::OnSuccessValue(
614 const IndexedDBMsg_CallbacksSuccessValue_Params
& params
) {
615 DCHECK_EQ(params
.ipc_thread_id
, CurrentWorkerId());
616 WebIDBCallbacks
* callbacks
=
617 pending_callbacks_
.Lookup(params
.ipc_callbacks_id
);
620 WebIDBValue web_value
;
621 PrepareWebValue(params
.value
, &web_value
);
622 if (params
.value
.primary_key
.IsValid()) {
623 web_value
.primaryKey
= WebIDBKeyBuilder::Build(params
.value
.primary_key
);
624 web_value
.keyPath
= WebIDBKeyPathBuilder::Build(params
.value
.key_path
);
626 callbacks
->onSuccess(web_value
);
627 cursor_transaction_ids_
.erase(params
.ipc_callbacks_id
);
628 pending_callbacks_
.Remove(params
.ipc_callbacks_id
);
631 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id
,
632 int32 ipc_callbacks_id
,
634 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
635 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
638 callbacks
->onSuccess(value
);
639 pending_callbacks_
.Remove(ipc_callbacks_id
);
642 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id
,
643 int32 ipc_callbacks_id
) {
644 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
645 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
648 callbacks
->onSuccess();
649 pending_callbacks_
.Remove(ipc_callbacks_id
);
652 void IndexedDBDispatcher::OnSuccessOpenCursor(
653 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params
& p
) {
654 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
655 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
656 int32 ipc_object_id
= p
.ipc_cursor_id
;
657 const IndexedDBKey
& key
= p
.key
;
658 const IndexedDBKey
& primary_key
= p
.primary_key
;
660 WebVector
<WebBlobInfo
> web_blob_info
;
661 PrepareWebValueAndBlobInfo(p
.value
, &web_value
, &web_blob_info
);
663 DCHECK(cursor_transaction_ids_
.find(ipc_callbacks_id
) !=
664 cursor_transaction_ids_
.end());
665 int64 transaction_id
= cursor_transaction_ids_
[ipc_callbacks_id
];
666 cursor_transaction_ids_
.erase(ipc_callbacks_id
);
668 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
672 WebIDBCursorImpl
* cursor
= new WebIDBCursorImpl(
673 ipc_object_id
, transaction_id
, thread_safe_sender_
.get());
674 cursors_
[ipc_object_id
] = cursor
;
675 callbacks
->onSuccess(cursor
,
676 WebIDBKeyBuilder::Build(key
),
677 WebIDBKeyBuilder::Build(primary_key
),
681 pending_callbacks_
.Remove(ipc_callbacks_id
);
684 void IndexedDBDispatcher::OnSuccessCursorContinue(
685 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params
& p
) {
686 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
687 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
688 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
689 const IndexedDBKey
& key
= p
.key
;
690 const IndexedDBKey
& primary_key
= p
.primary_key
;
692 if (cursors_
.find(ipc_cursor_id
) == cursors_
.end())
695 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
700 WebVector
<WebBlobInfo
> web_blob_info
;
701 PrepareWebValueAndBlobInfo(p
.value
, &web_value
, &web_blob_info
);
702 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
),
703 WebIDBKeyBuilder::Build(primary_key
),
707 pending_callbacks_
.Remove(ipc_callbacks_id
);
710 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
711 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params
& p
) {
712 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
713 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
714 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
715 const std::vector
<IndexedDBKey
>& keys
= p
.keys
;
716 const std::vector
<IndexedDBKey
>& primary_keys
= p
.primary_keys
;
717 std::vector
<WebData
> values(p
.values
.size());
718 std::vector
<WebVector
<WebBlobInfo
>> blob_infos(p
.values
.size());
719 for (size_t i
= 0; i
< p
.values
.size(); ++i
)
720 PrepareWebValueAndBlobInfo(p
.values
[i
], &values
[i
], &blob_infos
[i
]);
721 std::map
<int32
, WebIDBCursorImpl
*>::const_iterator cur_iter
=
722 cursors_
.find(ipc_cursor_id
);
723 if (cur_iter
== cursors_
.end())
726 cur_iter
->second
->SetPrefetchData(keys
, primary_keys
, values
, blob_infos
);
728 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
730 cur_iter
->second
->CachedContinue(callbacks
);
731 pending_callbacks_
.Remove(ipc_callbacks_id
);
734 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id
,
735 int32 ipc_callbacks_id
,
736 int64 existing_version
) {
737 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
738 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
740 callbacks
->onBlocked(existing_version
);
743 void IndexedDBDispatcher::OnUpgradeNeeded(
744 const IndexedDBMsg_CallbacksUpgradeNeeded_Params
& p
) {
745 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
746 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(p
.ipc_callbacks_id
);
748 WebIDBMetadata
metadata(ConvertMetadata(p
.idb_metadata
));
749 DCHECK(!databases_
.count(p
.ipc_database_id
));
750 databases_
[p
.ipc_database_id
] =
751 new WebIDBDatabaseImpl(p
.ipc_database_id
,
752 p
.ipc_database_callbacks_id
,
753 thread_safe_sender_
.get());
754 callbacks
->onUpgradeNeeded(
756 databases_
[p
.ipc_database_id
],
758 static_cast<blink::WebIDBDataLoss
>(p
.data_loss
),
759 WebString::fromUTF8(p
.data_loss_message
));
762 void IndexedDBDispatcher::OnError(int32 ipc_thread_id
,
763 int32 ipc_callbacks_id
,
765 const base::string16
& message
) {
766 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
767 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
771 callbacks
->onError(WebIDBDatabaseError(code
));
773 callbacks
->onError(WebIDBDatabaseError(code
, message
));
774 pending_callbacks_
.Remove(ipc_callbacks_id
);
775 cursor_transaction_ids_
.erase(ipc_callbacks_id
);
778 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id
,
779 int32 ipc_database_callbacks_id
,
780 int64 transaction_id
,
782 const base::string16
& message
) {
783 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
784 WebIDBDatabaseCallbacks
* callbacks
=
785 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
789 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
));
791 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
, message
));
794 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id
,
795 int32 ipc_database_callbacks_id
,
796 int64 transaction_id
) {
797 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
798 WebIDBDatabaseCallbacks
* callbacks
=
799 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
802 callbacks
->onComplete(transaction_id
);
805 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id
,
806 int32 ipc_database_callbacks_id
) {
807 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
808 WebIDBDatabaseCallbacks
* callbacks
=
809 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
812 callbacks
->onForcedClose();
815 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id
,
816 int32 ipc_database_callbacks_id
,
819 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
820 WebIDBDatabaseCallbacks
* callbacks
=
821 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
822 // callbacks would be NULL if a versionchange event is received after close
826 callbacks
->onVersionChange(old_version
, new_version
);
829 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
830 int64 transaction_id
,
831 int32 ipc_exception_cursor_id
) {
832 typedef std::map
<int32
, WebIDBCursorImpl
*>::iterator Iterator
;
833 for (Iterator i
= cursors_
.begin(); i
!= cursors_
.end(); ++i
) {
834 if (i
->first
== ipc_exception_cursor_id
||
835 i
->second
->transaction_id() != transaction_id
)
837 i
->second
->ResetPrefetchCache();
841 } // namespace content