IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher.cc
blobd2de316656853bb10c659f3ebb26f31873547ead
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"
22 using blink::WebData;
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;
34 namespace content {
35 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
36 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
38 namespace {
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);
76 return 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;
121 return web_metadata;
124 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
125 bool handled = true;
126 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
127 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
128 OnSuccessOpenCursor)
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,
140 OnSuccessStringList)
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,
146 OnSuccessUndefined)
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,
151 OnForcedClose)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
153 OnIntVersionChange)
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(
169 unsigned long count,
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(
198 int n,
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,
217 int64 version,
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;
232 params.name = name;
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;
260 params.name = name;
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());
291 params.mode = mode;
293 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
296 void IndexedDBDispatcher::RequestIDBDatabaseGet(
297 int32 ipc_database_id,
298 int64 transaction_id,
299 int64 object_store_id,
300 int64 index_id,
301 const IndexedDBKeyRange& key_range,
302 bool key_only,
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).",
333 value.size(),
334 kMaxIDBValueSizeInBytes).c_str())));
335 return;
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());
346 params.key = key;
347 params.put_mode = put_mode;
349 COMPILE_ASSERT(sizeof(params.index_ids[0]) == sizeof(index_ids[0]),
350 Cant_copy);
351 params.index_ids
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,
369 int64 index_id,
370 const IndexedDBKeyRange& key_range,
371 unsigned short direction,
372 bool key_only,
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,
393 int64 index_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(),
432 ipc_callbacks_id,
433 ipc_database_id,
434 transaction_id,
435 object_store_id));
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(
448 int32 ipc_thread_id,
449 int32 ipc_callbacks_id,
450 int32 ipc_database_callbacks_id,
451 int32 ipc_object_id,
452 const IndexedDBDatabaseMetadata& idb_metadata) {
453 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
454 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
455 if (!callbacks)
456 return;
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);
478 if (!callbacks)
479 return;
480 callbacks->onSuccess(WebIDBKeyBuilder::Build(key));
481 pending_callbacks_.Remove(ipc_callbacks_id);
484 void IndexedDBDispatcher::OnSuccessStringList(
485 int32 ipc_thread_id,
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);
490 if (!callbacks)
491 return;
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);
501 if (!callbacks)
502 return;
503 WebData web_value;
504 if (value.size())
505 web_value.assign(&*value.begin(), value.size());
506 callbacks->onSuccess(web_value);
507 pending_callbacks_.Remove(ipc_callbacks_id);
510 void IndexedDBDispatcher::OnSuccessValueWithKey(
511 int32 ipc_thread_id,
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);
518 if (!callbacks)
519 return;
520 WebData web_value;
521 if (value.size())
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,
531 int64 value) {
532 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
533 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
534 if (!callbacks)
535 return;
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);
544 if (!callbacks)
545 return;
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;
557 WebData web_value;
558 if (p.value.size())
559 web_value.assign(&*p.value.begin(), p.value.size());
561 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
562 if (!callbacks)
563 return;
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];
584 DCHECK(cursor);
586 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
587 if (!callbacks)
588 return;
590 WebData web_value;
591 if (value.size())
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];
612 DCHECK(cursor);
613 cursor->SetPrefetchData(keys, primary_keys, values);
615 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
616 DCHECK(callbacks);
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);
626 DCHECK(callbacks);
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);
634 DCHECK(callbacks);
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(
642 p.old_version,
643 databases_[p.ipc_database_id],
644 metadata,
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,
651 int code,
652 const base::string16& message) {
653 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
654 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
655 if (!callbacks)
656 return;
657 if (message.empty())
658 callbacks->onError(WebIDBDatabaseError(code));
659 else
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,
667 int code,
668 const base::string16& message) {
669 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
670 WebIDBDatabaseCallbacks* callbacks =
671 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
672 if (!callbacks)
673 return;
674 if (message.empty())
675 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code));
676 else
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);
686 if (!callbacks)
687 return;
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);
696 if (!callbacks)
697 return;
698 callbacks->onForcedClose();
701 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
702 int32 ipc_database_callbacks_id,
703 int64 old_version,
704 int64 new_version) {
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
709 // has been called.
710 if (!callbacks)
711 return;
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)
721 continue;
722 i->second->ResetPrefetchCache();
726 } // namespace content