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 "base/format_macros.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/threading/thread_local.h"
11 #include "content/child/indexed_db/indexed_db_key_builders.h"
12 #include "content/child/indexed_db/webidbcursor_impl.h"
13 #include "content/child/indexed_db/webidbdatabase_impl.h"
14 #include "content/child/thread_safe_sender.h"
15 #include "content/common/indexed_db/indexed_db_constants.h"
16 #include "content/common/indexed_db/indexed_db_messages.h"
17 #include "ipc/ipc_channel.h"
18 #include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
19 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
20 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
23 using blink::WebIDBCallbacks
;
24 using blink::WebIDBDatabase
;
25 using blink::WebIDBDatabaseCallbacks
;
26 using blink::WebIDBDatabaseError
;
27 using blink::WebIDBKey
;
28 using blink::WebIDBMetadata
;
29 using blink::WebString
;
30 using blink::WebVector
;
31 using base::ThreadLocalPointer
;
32 using webkit_glue::WorkerTaskRunner
;
35 static base::LazyInstance
<ThreadLocalPointer
<IndexedDBDispatcher
> >::Leaky
36 g_idb_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
40 IndexedDBDispatcher
* const kHasBeenDeleted
=
41 reinterpret_cast<IndexedDBDispatcher
*>(0x1);
43 } // unnamed namespace
45 const size_t kMaxIDBValueSizeInBytes
= 64 * 1024 * 1024;
47 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender
* thread_safe_sender
)
48 : thread_safe_sender_(thread_safe_sender
) {
49 g_idb_dispatcher_tls
.Pointer()->Set(this);
52 IndexedDBDispatcher::~IndexedDBDispatcher() {
53 // Clear any pending callbacks - which may result in dispatch requests -
54 // before marking the dispatcher as deleted.
55 pending_callbacks_
.Clear();
56 pending_database_callbacks_
.Clear();
58 DCHECK(pending_callbacks_
.IsEmpty());
59 DCHECK(pending_database_callbacks_
.IsEmpty());
61 g_idb_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
64 IndexedDBDispatcher
* IndexedDBDispatcher::ThreadSpecificInstance(
65 ThreadSafeSender
* thread_safe_sender
) {
66 if (g_idb_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
67 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
68 g_idb_dispatcher_tls
.Pointer()->Set(NULL
);
70 if (g_idb_dispatcher_tls
.Pointer()->Get())
71 return g_idb_dispatcher_tls
.Pointer()->Get();
73 IndexedDBDispatcher
* dispatcher
= new IndexedDBDispatcher(thread_safe_sender
);
74 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
75 webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
79 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
81 WebIDBMetadata
IndexedDBDispatcher::ConvertMetadata(
82 const IndexedDBDatabaseMetadata
& idb_metadata
) {
83 WebIDBMetadata web_metadata
;
84 web_metadata
.id
= idb_metadata
.id
;
85 web_metadata
.name
= idb_metadata
.name
;
86 web_metadata
.version
= idb_metadata
.version
;
87 web_metadata
.intVersion
= idb_metadata
.int_version
;
88 web_metadata
.maxObjectStoreId
= idb_metadata
.max_object_store_id
;
89 web_metadata
.objectStores
=
90 WebVector
<WebIDBMetadata::ObjectStore
>(idb_metadata
.object_stores
.size());
92 for (size_t i
= 0; i
< idb_metadata
.object_stores
.size(); ++i
) {
93 const IndexedDBObjectStoreMetadata
& idb_store_metadata
=
94 idb_metadata
.object_stores
[i
];
95 WebIDBMetadata::ObjectStore
& web_store_metadata
=
96 web_metadata
.objectStores
[i
];
98 web_store_metadata
.id
= idb_store_metadata
.id
;
99 web_store_metadata
.name
= idb_store_metadata
.name
;
100 web_store_metadata
.keyPath
=
101 WebIDBKeyPathBuilder::Build(idb_store_metadata
.keyPath
);
102 web_store_metadata
.autoIncrement
= idb_store_metadata
.autoIncrement
;
103 web_store_metadata
.maxIndexId
= idb_store_metadata
.max_index_id
;
104 web_store_metadata
.indexes
=
105 WebVector
<WebIDBMetadata::Index
>(idb_store_metadata
.indexes
.size());
107 for (size_t j
= 0; j
< idb_store_metadata
.indexes
.size(); ++j
) {
108 const IndexedDBIndexMetadata
& idb_index_metadata
=
109 idb_store_metadata
.indexes
[j
];
110 WebIDBMetadata::Index
& web_index_metadata
= web_store_metadata
.indexes
[j
];
112 web_index_metadata
.id
= idb_index_metadata
.id
;
113 web_index_metadata
.name
= idb_index_metadata
.name
;
114 web_index_metadata
.keyPath
=
115 WebIDBKeyPathBuilder::Build(idb_index_metadata
.keyPath
);
116 web_index_metadata
.unique
= idb_index_metadata
.unique
;
117 web_index_metadata
.multiEntry
= idb_index_metadata
.multiEntry
;
124 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
126 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher
, msg
)
127 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor
,
129 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance
,
130 OnSuccessCursorContinue
)
131 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue
,
132 OnSuccessCursorContinue
)
133 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch
,
134 OnSuccessCursorPrefetch
)
135 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase
,
136 OnSuccessIDBDatabase
)
137 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey
,
138 OnSuccessIndexedDBKey
)
139 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList
,
141 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue
, OnSuccessValue
)
142 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValueWithKey
,
143 OnSuccessValueWithKey
)
144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger
, OnSuccessInteger
)
145 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined
,
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError
, OnError
)
148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked
, OnIntBlocked
)
149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded
, OnUpgradeNeeded
)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose
,
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange
,
154 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort
, OnAbort
)
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete
, OnComplete
)
156 IPC_MESSAGE_UNHANDLED(handled
= false)
157 IPC_END_MESSAGE_MAP()
158 // If a message gets here, IndexedDBMessageFilter already determined that it
159 // is an IndexedDB message.
160 DCHECK(handled
) << "Didn't handle a message defined at line "
161 << IPC_MESSAGE_ID_LINE(msg
.type());
164 bool IndexedDBDispatcher::Send(IPC::Message
* msg
) {
165 return thread_safe_sender_
->Send(msg
);
168 void IndexedDBDispatcher::RequestIDBCursorAdvance(
170 WebIDBCallbacks
* callbacks_ptr
,
171 int32 ipc_cursor_id
) {
172 // Reset all cursor prefetch caches except for this cursor.
173 ResetCursorPrefetchCaches(ipc_cursor_id
);
175 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
177 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
178 Send(new IndexedDBHostMsg_CursorAdvance(
179 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, count
));
182 void IndexedDBDispatcher::RequestIDBCursorContinue(
183 const IndexedDBKey
& key
,
184 const IndexedDBKey
& primary_key
,
185 WebIDBCallbacks
* callbacks_ptr
,
186 int32 ipc_cursor_id
) {
187 // Reset all cursor prefetch caches except for this cursor.
188 ResetCursorPrefetchCaches(ipc_cursor_id
);
190 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
192 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
193 Send(new IndexedDBHostMsg_CursorContinue(
194 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, key
, primary_key
));
197 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
199 WebIDBCallbacks
* callbacks_ptr
,
200 int32 ipc_cursor_id
) {
201 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
203 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
204 Send(new IndexedDBHostMsg_CursorPrefetch(
205 ipc_cursor_id
, CurrentWorkerId(), ipc_callbacks_id
, n
));
208 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches
,
209 int unused_prefetches
,
210 int32 ipc_cursor_id
) {
211 Send(new IndexedDBHostMsg_CursorPrefetchReset(
212 ipc_cursor_id
, used_prefetches
, unused_prefetches
));
215 void IndexedDBDispatcher::RequestIDBFactoryOpen(
216 const base::string16
& name
,
218 int64 transaction_id
,
219 WebIDBCallbacks
* callbacks_ptr
,
220 WebIDBDatabaseCallbacks
* database_callbacks_ptr
,
221 const std::string
& database_identifier
) {
222 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
223 scoped_ptr
<WebIDBDatabaseCallbacks
> database_callbacks(
224 database_callbacks_ptr
);
226 IndexedDBHostMsg_FactoryOpen_Params params
;
227 params
.ipc_thread_id
= CurrentWorkerId();
228 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
229 params
.ipc_database_callbacks_id
=
230 pending_database_callbacks_
.Add(database_callbacks
.release());
231 params
.database_identifier
= database_identifier
;
233 params
.transaction_id
= transaction_id
;
234 params
.version
= version
;
235 Send(new IndexedDBHostMsg_FactoryOpen(params
));
238 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
239 WebIDBCallbacks
* callbacks_ptr
,
240 const std::string
& database_identifier
) {
241 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
243 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params
;
244 params
.ipc_thread_id
= CurrentWorkerId();
245 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
246 params
.database_identifier
= database_identifier
;
247 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params
));
250 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
251 const base::string16
& name
,
252 WebIDBCallbacks
* callbacks_ptr
,
253 const std::string
& database_identifier
) {
254 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
256 IndexedDBHostMsg_FactoryDeleteDatabase_Params params
;
257 params
.ipc_thread_id
= CurrentWorkerId();
258 params
.ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
259 params
.database_identifier
= database_identifier
;
261 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params
));
264 void IndexedDBDispatcher::RequestIDBDatabaseClose(
265 int32 ipc_database_id
,
266 int32 ipc_database_callbacks_id
) {
267 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id
));
268 // There won't be pending database callbacks if the transaction was aborted in
269 // the initial upgradeneeded event handler.
270 if (pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
))
271 pending_database_callbacks_
.Remove(ipc_database_callbacks_id
);
274 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
275 int32 ipc_database_id
,
276 int64 transaction_id
,
277 WebIDBDatabaseCallbacks
* database_callbacks_ptr
,
278 WebVector
<long long> object_store_ids
,
279 unsigned short mode
) {
280 scoped_ptr
<WebIDBDatabaseCallbacks
> database_callbacks(
281 database_callbacks_ptr
);
282 IndexedDBHostMsg_DatabaseCreateTransaction_Params params
;
283 params
.ipc_thread_id
= CurrentWorkerId();
284 params
.ipc_database_id
= ipc_database_id
;
285 params
.transaction_id
= transaction_id
;
286 params
.ipc_database_callbacks_id
=
287 pending_database_callbacks_
.Add(database_callbacks
.release());
288 params
.object_store_ids
289 .assign(object_store_ids
.data(),
290 object_store_ids
.data() + object_store_ids
.size());
293 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params
));
296 void IndexedDBDispatcher::RequestIDBDatabaseGet(
297 int32 ipc_database_id
,
298 int64 transaction_id
,
299 int64 object_store_id
,
301 const IndexedDBKeyRange
& key_range
,
303 WebIDBCallbacks
* callbacks
) {
304 ResetCursorPrefetchCaches();
305 IndexedDBHostMsg_DatabaseGet_Params params
;
306 init_params(params
, callbacks
);
307 params
.ipc_database_id
= ipc_database_id
;
308 params
.transaction_id
= transaction_id
;
309 params
.object_store_id
= object_store_id
;
310 params
.index_id
= index_id
;
311 params
.key_range
= key_range
;
312 params
.key_only
= key_only
;
313 Send(new IndexedDBHostMsg_DatabaseGet(params
));
316 void IndexedDBDispatcher::RequestIDBDatabasePut(
317 int32 ipc_database_id
,
318 int64 transaction_id
,
319 int64 object_store_id
,
320 const WebData
& value
,
321 const IndexedDBKey
& key
,
322 WebIDBDatabase::PutMode put_mode
,
323 WebIDBCallbacks
* callbacks
,
324 const WebVector
<long long>& index_ids
,
325 const WebVector
<WebVector
<WebIDBKey
> >& index_keys
) {
327 if (value
.size() > kMaxIDBValueSizeInBytes
) {
328 callbacks
->onError(WebIDBDatabaseError(
329 blink::WebIDBDatabaseExceptionUnknownError
,
330 WebString::fromUTF8(base::StringPrintf(
331 "The serialized value is too large"
332 " (size=%" PRIuS
" bytes, max=%" PRIuS
" bytes).",
334 kMaxIDBValueSizeInBytes
).c_str())));
338 ResetCursorPrefetchCaches();
339 IndexedDBHostMsg_DatabasePut_Params params
;
340 init_params(params
, callbacks
);
341 params
.ipc_database_id
= ipc_database_id
;
342 params
.transaction_id
= transaction_id
;
343 params
.object_store_id
= object_store_id
;
345 params
.value
.assign(value
.data(), value
.data() + value
.size());
347 params
.put_mode
= put_mode
;
349 COMPILE_ASSERT(sizeof(params
.index_ids
[0]) == sizeof(index_ids
[0]),
352 .assign(index_ids
.data(), index_ids
.data() + index_ids
.size());
354 params
.index_keys
.resize(index_keys
.size());
355 for (size_t i
= 0; i
< index_keys
.size(); ++i
) {
356 params
.index_keys
[i
].resize(index_keys
[i
].size());
357 for (size_t j
= 0; j
< index_keys
[i
].size(); ++j
) {
358 params
.index_keys
[i
][j
] =
359 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys
[i
][j
]));
362 Send(new IndexedDBHostMsg_DatabasePut(params
));
365 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
366 int32 ipc_database_id
,
367 int64 transaction_id
,
368 int64 object_store_id
,
370 const IndexedDBKeyRange
& key_range
,
371 unsigned short direction
,
373 WebIDBDatabase::TaskType task_type
,
374 WebIDBCallbacks
* callbacks
) {
375 ResetCursorPrefetchCaches();
376 IndexedDBHostMsg_DatabaseOpenCursor_Params params
;
377 init_params(params
, callbacks
);
378 params
.ipc_database_id
= ipc_database_id
;
379 params
.transaction_id
= transaction_id
;
380 params
.object_store_id
= object_store_id
;
381 params
.index_id
= index_id
;
382 params
.key_range
= key_range
;
383 params
.direction
= direction
;
384 params
.key_only
= key_only
;
385 params
.task_type
= task_type
;
386 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params
));
389 void IndexedDBDispatcher::RequestIDBDatabaseCount(
390 int32 ipc_database_id
,
391 int64 transaction_id
,
392 int64 object_store_id
,
394 const IndexedDBKeyRange
& key_range
,
395 WebIDBCallbacks
* callbacks
) {
396 ResetCursorPrefetchCaches();
397 IndexedDBHostMsg_DatabaseCount_Params params
;
398 init_params(params
, callbacks
);
399 params
.ipc_database_id
= ipc_database_id
;
400 params
.transaction_id
= transaction_id
;
401 params
.object_store_id
= object_store_id
;
402 params
.index_id
= index_id
;
403 params
.key_range
= key_range
;
404 Send(new IndexedDBHostMsg_DatabaseCount(params
));
407 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
408 int32 ipc_database_id
,
409 int64 transaction_id
,
410 int64 object_store_id
,
411 const IndexedDBKeyRange
& key_range
,
412 WebIDBCallbacks
* callbacks
) {
413 ResetCursorPrefetchCaches();
414 IndexedDBHostMsg_DatabaseDeleteRange_Params params
;
415 init_params(params
, callbacks
);
416 params
.ipc_database_id
= ipc_database_id
;
417 params
.transaction_id
= transaction_id
;
418 params
.object_store_id
= object_store_id
;
419 params
.key_range
= key_range
;
420 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params
));
423 void IndexedDBDispatcher::RequestIDBDatabaseClear(
424 int32 ipc_database_id
,
425 int64 transaction_id
,
426 int64 object_store_id
,
427 WebIDBCallbacks
* callbacks_ptr
) {
428 ResetCursorPrefetchCaches();
429 scoped_ptr
<WebIDBCallbacks
> callbacks(callbacks_ptr
);
430 int32 ipc_callbacks_id
= pending_callbacks_
.Add(callbacks
.release());
431 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
438 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id
) {
439 cursors_
.erase(ipc_cursor_id
);
442 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id
) {
443 DCHECK_EQ(databases_
.count(ipc_database_id
), 1u);
444 databases_
.erase(ipc_database_id
);
447 void IndexedDBDispatcher::OnSuccessIDBDatabase(
449 int32 ipc_callbacks_id
,
450 int32 ipc_database_callbacks_id
,
452 const IndexedDBDatabaseMetadata
& idb_metadata
) {
453 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
454 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
457 WebIDBMetadata
metadata(ConvertMetadata(idb_metadata
));
458 // If an upgrade was performed, count will be non-zero.
459 WebIDBDatabase
* database
= NULL
;
461 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
462 // May already be deleted and removed from the table, but do not recreate..
463 if (ipc_object_id
!= kNoDatabase
) {
464 DCHECK(!databases_
.count(ipc_object_id
));
465 database
= databases_
[ipc_object_id
] = new WebIDBDatabaseImpl(
466 ipc_object_id
, ipc_database_callbacks_id
, thread_safe_sender_
.get());
469 callbacks
->onSuccess(database
, metadata
);
470 pending_callbacks_
.Remove(ipc_callbacks_id
);
473 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id
,
474 int32 ipc_callbacks_id
,
475 const IndexedDBKey
& key
) {
476 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
477 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
480 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
));
481 pending_callbacks_
.Remove(ipc_callbacks_id
);
484 void IndexedDBDispatcher::OnSuccessStringList(
486 int32 ipc_callbacks_id
,
487 const std::vector
<base::string16
>& value
) {
488 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
489 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
492 callbacks
->onSuccess(WebVector
<WebString
>(value
));
493 pending_callbacks_
.Remove(ipc_callbacks_id
);
496 void IndexedDBDispatcher::OnSuccessValue(int32 ipc_thread_id
,
497 int32 ipc_callbacks_id
,
498 const std::string
& value
) {
499 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
500 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
505 web_value
.assign(&*value
.begin(), value
.size());
506 callbacks
->onSuccess(web_value
);
507 pending_callbacks_
.Remove(ipc_callbacks_id
);
510 void IndexedDBDispatcher::OnSuccessValueWithKey(
512 int32 ipc_callbacks_id
,
513 const std::string
& value
,
514 const IndexedDBKey
& primary_key
,
515 const IndexedDBKeyPath
& key_path
) {
516 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
517 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
522 web_value
.assign(&*value
.begin(), value
.size());
523 callbacks
->onSuccess(web_value
,
524 WebIDBKeyBuilder::Build(primary_key
),
525 WebIDBKeyPathBuilder::Build(key_path
));
526 pending_callbacks_
.Remove(ipc_callbacks_id
);
529 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id
,
530 int32 ipc_callbacks_id
,
532 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
533 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
536 callbacks
->onSuccess(value
);
537 pending_callbacks_
.Remove(ipc_callbacks_id
);
540 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id
,
541 int32 ipc_callbacks_id
) {
542 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
543 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
546 callbacks
->onSuccess();
547 pending_callbacks_
.Remove(ipc_callbacks_id
);
550 void IndexedDBDispatcher::OnSuccessOpenCursor(
551 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params
& p
) {
552 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
553 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
554 int32 ipc_object_id
= p
.ipc_cursor_id
;
555 const IndexedDBKey
& key
= p
.key
;
556 const IndexedDBKey
& primary_key
= p
.primary_key
;
559 web_value
.assign(&*p
.value
.begin(), p
.value
.size());
561 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
565 WebIDBCursorImpl
* cursor
=
566 new WebIDBCursorImpl(ipc_object_id
, thread_safe_sender_
.get());
567 cursors_
[ipc_object_id
] = cursor
;
568 callbacks
->onSuccess(cursor
, WebIDBKeyBuilder::Build(key
),
569 WebIDBKeyBuilder::Build(primary_key
), web_value
);
571 pending_callbacks_
.Remove(ipc_callbacks_id
);
574 void IndexedDBDispatcher::OnSuccessCursorContinue(
575 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params
& p
) {
576 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
577 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
578 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
579 const IndexedDBKey
& key
= p
.key
;
580 const IndexedDBKey
& primary_key
= p
.primary_key
;
581 const std::string
& value
= p
.value
;
583 WebIDBCursorImpl
* cursor
= cursors_
[ipc_cursor_id
];
586 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
592 web_value
.assign(&*value
.begin(), value
.size());
593 callbacks
->onSuccess(WebIDBKeyBuilder::Build(key
),
594 WebIDBKeyBuilder::Build(primary_key
), web_value
);
596 pending_callbacks_
.Remove(ipc_callbacks_id
);
599 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
600 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params
& p
) {
601 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
602 int32 ipc_callbacks_id
= p
.ipc_callbacks_id
;
603 int32 ipc_cursor_id
= p
.ipc_cursor_id
;
604 const std::vector
<IndexedDBKey
>& keys
= p
.keys
;
605 const std::vector
<IndexedDBKey
>& primary_keys
= p
.primary_keys
;
606 std::vector
<WebData
> values(p
.values
.size());
607 for (size_t i
= 0; i
< p
.values
.size(); ++i
) {
608 if (p
.values
[i
].size())
609 values
[i
].assign(&*p
.values
[i
].begin(), p
.values
[i
].size());
611 WebIDBCursorImpl
* cursor
= cursors_
[ipc_cursor_id
];
613 cursor
->SetPrefetchData(keys
, primary_keys
, values
);
615 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
617 cursor
->CachedContinue(callbacks
);
618 pending_callbacks_
.Remove(ipc_callbacks_id
);
621 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id
,
622 int32 ipc_callbacks_id
,
623 int64 existing_version
) {
624 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
625 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
627 callbacks
->onBlocked(existing_version
);
630 void IndexedDBDispatcher::OnUpgradeNeeded(
631 const IndexedDBMsg_CallbacksUpgradeNeeded_Params
& p
) {
632 DCHECK_EQ(p
.ipc_thread_id
, CurrentWorkerId());
633 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(p
.ipc_callbacks_id
);
635 WebIDBMetadata
metadata(ConvertMetadata(p
.idb_metadata
));
636 DCHECK(!databases_
.count(p
.ipc_database_id
));
637 databases_
[p
.ipc_database_id
] =
638 new WebIDBDatabaseImpl(p
.ipc_database_id
,
639 p
.ipc_database_callbacks_id
,
640 thread_safe_sender_
.get());
641 callbacks
->onUpgradeNeeded(
643 databases_
[p
.ipc_database_id
],
645 static_cast<blink::WebIDBDataLoss
>(p
.data_loss
),
646 WebString::fromUTF8(p
.data_loss_message
));
649 void IndexedDBDispatcher::OnError(int32 ipc_thread_id
,
650 int32 ipc_callbacks_id
,
652 const base::string16
& message
) {
653 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
654 WebIDBCallbacks
* callbacks
= pending_callbacks_
.Lookup(ipc_callbacks_id
);
658 callbacks
->onError(WebIDBDatabaseError(code
));
660 callbacks
->onError(WebIDBDatabaseError(code
, message
));
661 pending_callbacks_
.Remove(ipc_callbacks_id
);
664 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id
,
665 int32 ipc_database_callbacks_id
,
666 int64 transaction_id
,
668 const base::string16
& message
) {
669 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
670 WebIDBDatabaseCallbacks
* callbacks
=
671 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
675 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
));
677 callbacks
->onAbort(transaction_id
, WebIDBDatabaseError(code
, message
));
680 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id
,
681 int32 ipc_database_callbacks_id
,
682 int64 transaction_id
) {
683 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
684 WebIDBDatabaseCallbacks
* callbacks
=
685 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
688 callbacks
->onComplete(transaction_id
);
691 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id
,
692 int32 ipc_database_callbacks_id
) {
693 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
694 WebIDBDatabaseCallbacks
* callbacks
=
695 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
698 callbacks
->onForcedClose();
701 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id
,
702 int32 ipc_database_callbacks_id
,
705 DCHECK_EQ(ipc_thread_id
, CurrentWorkerId());
706 WebIDBDatabaseCallbacks
* callbacks
=
707 pending_database_callbacks_
.Lookup(ipc_database_callbacks_id
);
708 // callbacks would be NULL if a versionchange event is received after close
712 callbacks
->onVersionChange(old_version
, new_version
);
715 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
716 int32 ipc_exception_cursor_id
) {
717 // TODO(jsbell): Only reset cursors from the same transaction.
718 typedef std::map
<int32
, WebIDBCursorImpl
*>::iterator Iterator
;
719 for (Iterator i
= cursors_
.begin(); i
!= cursors_
.end(); ++i
) {
720 if (i
->first
== ipc_exception_cursor_id
)
722 i
->second
->ResetPrefetchCache();
726 } // namespace content