Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher.cc
blob9e92b711c65261e1f2688d228ed361dd1af2dfbc
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/proxy_webidbcursor_impl.h"
13 #include "content/child/indexed_db/proxy_webidbdatabase_impl.h"
14 #include "content/child/thread_safe_sender.h"
15 #include "content/common/indexed_db/indexed_db_messages.h"
16 #include "ipc/ipc_channel.h"
17 #include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
18 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
19 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
21 using WebKit::WebData;
22 using WebKit::WebIDBCallbacks;
23 using WebKit::WebIDBDatabase;
24 using WebKit::WebIDBDatabaseCallbacks;
25 using WebKit::WebIDBDatabaseError;
26 using WebKit::WebIDBKey;
27 using WebKit::WebIDBMetadata;
28 using WebKit::WebString;
29 using WebKit::WebVector;
30 using base::ThreadLocalPointer;
31 using webkit_glue::WorkerTaskRunner;
33 namespace content {
34 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
35 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
37 namespace {
39 IndexedDBDispatcher* const kHasBeenDeleted =
40 reinterpret_cast<IndexedDBDispatcher*>(0x1);
42 int32 CurrentWorkerId() {
43 return WorkerTaskRunner::Instance()->CurrentWorkerId();
45 } // unnamed namespace
47 const size_t kMaxIDBValueSizeInBytes = 64 * 1024 * 1024;
49 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender)
50 : thread_safe_sender_(thread_safe_sender) {
51 g_idb_dispatcher_tls.Pointer()->Set(this);
54 IndexedDBDispatcher::~IndexedDBDispatcher() {
55 // Clear any pending callbacks - which may result in dispatch requests -
56 // before marking the dispatcher as deleted.
57 pending_callbacks_.Clear();
58 pending_database_callbacks_.Clear();
60 DCHECK(pending_callbacks_.IsEmpty());
61 DCHECK(pending_database_callbacks_.IsEmpty());
63 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
66 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance(
67 ThreadSafeSender* thread_safe_sender) {
68 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
69 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
70 g_idb_dispatcher_tls.Pointer()->Set(NULL);
72 if (g_idb_dispatcher_tls.Pointer()->Get())
73 return g_idb_dispatcher_tls.Pointer()->Get();
75 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender);
76 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
77 webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
78 return dispatcher;
81 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
83 WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
84 const IndexedDBDatabaseMetadata& idb_metadata) {
85 WebIDBMetadata web_metadata;
86 web_metadata.id = idb_metadata.id;
87 web_metadata.name = idb_metadata.name;
88 web_metadata.version = idb_metadata.version;
89 web_metadata.intVersion = idb_metadata.int_version;
90 web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
91 web_metadata.objectStores =
92 WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
94 for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) {
95 const IndexedDBObjectStoreMetadata& idb_store_metadata =
96 idb_metadata.object_stores[i];
97 WebIDBMetadata::ObjectStore& web_store_metadata =
98 web_metadata.objectStores[i];
100 web_store_metadata.id = idb_store_metadata.id;
101 web_store_metadata.name = idb_store_metadata.name;
102 web_store_metadata.keyPath =
103 WebIDBKeyPathBuilder::Build(idb_store_metadata.keyPath);
104 web_store_metadata.autoIncrement = idb_store_metadata.autoIncrement;
105 web_store_metadata.maxIndexId = idb_store_metadata.max_index_id;
106 web_store_metadata.indexes =
107 WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size());
109 for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) {
110 const IndexedDBIndexMetadata& idb_index_metadata =
111 idb_store_metadata.indexes[j];
112 WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j];
114 web_index_metadata.id = idb_index_metadata.id;
115 web_index_metadata.name = idb_index_metadata.name;
116 web_index_metadata.keyPath =
117 WebIDBKeyPathBuilder::Build(idb_index_metadata.keyPath);
118 web_index_metadata.unique = idb_index_metadata.unique;
119 web_index_metadata.multiEntry = idb_index_metadata.multiEntry;
123 return web_metadata;
126 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
127 bool handled = true;
128 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
129 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
130 OnSuccessOpenCursor)
131 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance,
132 OnSuccessCursorContinue)
133 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
134 OnSuccessCursorContinue)
135 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
136 OnSuccessCursorPrefetch)
137 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
138 OnSuccessIDBDatabase)
139 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
140 OnSuccessIndexedDBKey)
141 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList,
142 OnSuccessStringList)
143 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue)
144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValueWithKey,
145 OnSuccessValueWithKey)
146 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger)
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined,
148 OnSuccessUndefined)
149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked)
151 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
153 OnForcedClose)
154 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
155 OnIntVersionChange)
156 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
157 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
158 IPC_MESSAGE_UNHANDLED(handled = false)
159 IPC_END_MESSAGE_MAP()
160 // If a message gets here, IndexedDBMessageFilter already determined that it
161 // is an IndexedDB message.
162 DCHECK(handled) << "Didn't handle a message defined at line "
163 << IPC_MESSAGE_ID_LINE(msg.type());
166 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
167 return thread_safe_sender_->Send(msg);
170 void IndexedDBDispatcher::RequestIDBCursorAdvance(
171 unsigned long count,
172 WebIDBCallbacks* callbacks_ptr,
173 int32 ipc_cursor_id) {
174 // Reset all cursor prefetch caches except for this cursor.
175 ResetCursorPrefetchCaches(ipc_cursor_id);
177 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
179 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
180 Send(new IndexedDBHostMsg_CursorAdvance(
181 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count));
184 void IndexedDBDispatcher::RequestIDBCursorContinue(
185 const IndexedDBKey& key,
186 WebIDBCallbacks* callbacks_ptr,
187 int32 ipc_cursor_id) {
188 // Reset all cursor prefetch caches except for this cursor.
189 ResetCursorPrefetchCaches(ipc_cursor_id);
191 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
193 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
194 Send(new IndexedDBHostMsg_CursorContinue(
195 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key));
198 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
199 int n,
200 WebIDBCallbacks* callbacks_ptr,
201 int32 ipc_cursor_id) {
202 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
204 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
205 Send(new IndexedDBHostMsg_CursorPrefetch(
206 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n));
209 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
210 int unused_prefetches,
211 int32 ipc_cursor_id) {
212 Send(new IndexedDBHostMsg_CursorPrefetchReset(
213 ipc_cursor_id, used_prefetches, unused_prefetches));
216 void IndexedDBDispatcher::RequestIDBFactoryOpen(
217 const string16& name,
218 int64 version,
219 int64 transaction_id,
220 WebIDBCallbacks* callbacks_ptr,
221 WebIDBDatabaseCallbacks* database_callbacks_ptr,
222 const std::string& database_identifier) {
223 ResetCursorPrefetchCaches();
224 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
225 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
226 database_callbacks_ptr);
228 IndexedDBHostMsg_FactoryOpen_Params params;
229 params.ipc_thread_id = CurrentWorkerId();
230 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
231 params.ipc_database_callbacks_id =
232 pending_database_callbacks_.Add(database_callbacks.release());
233 params.database_identifier = database_identifier;
234 params.name = name;
235 params.transaction_id = transaction_id;
236 params.version = version;
237 Send(new IndexedDBHostMsg_FactoryOpen(params));
240 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
241 WebIDBCallbacks* callbacks_ptr,
242 const std::string& database_identifier) {
243 ResetCursorPrefetchCaches();
244 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
246 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
247 params.ipc_thread_id = CurrentWorkerId();
248 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
249 params.database_identifier = database_identifier;
250 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
253 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
254 const string16& name,
255 WebIDBCallbacks* callbacks_ptr,
256 const std::string& database_identifier) {
257 ResetCursorPrefetchCaches();
258 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
260 IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
261 params.ipc_thread_id = CurrentWorkerId();
262 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
263 params.database_identifier = database_identifier;
264 params.name = name;
265 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
268 void IndexedDBDispatcher::RequestIDBDatabaseClose(
269 int32 ipc_database_id,
270 int32 ipc_database_callbacks_id) {
271 ResetCursorPrefetchCaches();
272 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id));
273 // There won't be pending database callbacks if the transaction was aborted in
274 // the initial upgradeneeded event handler.
275 if (pending_database_callbacks_.Lookup(ipc_database_callbacks_id))
276 pending_database_callbacks_.Remove(ipc_database_callbacks_id);
279 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
280 int32 ipc_database_id,
281 int64 transaction_id,
282 WebIDBDatabaseCallbacks* database_callbacks_ptr,
283 WebVector<long long> object_store_ids,
284 unsigned short mode) {
285 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
286 database_callbacks_ptr);
287 IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
288 params.ipc_thread_id = CurrentWorkerId();
289 params.ipc_database_id = ipc_database_id;
290 params.transaction_id = transaction_id;
291 params.ipc_database_callbacks_id =
292 pending_database_callbacks_.Add(database_callbacks.release());
293 params.object_store_ids
294 .assign(object_store_ids.data(),
295 object_store_ids.data() + object_store_ids.size());
296 params.mode = mode;
298 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
301 void IndexedDBDispatcher::RequestIDBDatabaseGet(
302 int32 ipc_database_id,
303 int64 transaction_id,
304 int64 object_store_id,
305 int64 index_id,
306 const IndexedDBKeyRange& key_range,
307 bool key_only,
308 WebIDBCallbacks* callbacks) {
309 ResetCursorPrefetchCaches();
310 IndexedDBHostMsg_DatabaseGet_Params params;
311 init_params(params, callbacks);
312 params.ipc_database_id = ipc_database_id;
313 params.transaction_id = transaction_id;
314 params.object_store_id = object_store_id;
315 params.index_id = index_id;
316 params.key_range = key_range;
317 params.key_only = key_only;
318 Send(new IndexedDBHostMsg_DatabaseGet(params));
321 void IndexedDBDispatcher::RequestIDBDatabasePut(
322 int32 ipc_database_id,
323 int64 transaction_id,
324 int64 object_store_id,
325 const WebData& value,
326 const IndexedDBKey& key,
327 WebIDBDatabase::PutMode put_mode,
328 WebIDBCallbacks* callbacks,
329 const WebVector<long long>& index_ids,
330 const WebVector<WebVector<WebIDBKey> >& index_keys) {
332 if (value.size() > kMaxIDBValueSizeInBytes) {
333 callbacks->onError(WebIDBDatabaseError(
334 WebKit::WebIDBDatabaseExceptionUnknownError,
335 WebString::fromUTF8(base::StringPrintf(
336 "The serialized value is too large"
337 " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
338 value.size(),
339 kMaxIDBValueSizeInBytes).c_str())));
340 return;
343 ResetCursorPrefetchCaches();
344 IndexedDBHostMsg_DatabasePut_Params params;
345 init_params(params, callbacks);
346 params.ipc_database_id = ipc_database_id;
347 params.transaction_id = transaction_id;
348 params.object_store_id = object_store_id;
350 params.value.assign(value.data(), value.data() + value.size());
351 params.key = key;
352 params.put_mode = put_mode;
354 COMPILE_ASSERT(sizeof(params.index_ids[0]) == sizeof(index_ids[0]),
355 Cant_copy);
356 params.index_ids
357 .assign(index_ids.data(), index_ids.data() + index_ids.size());
359 params.index_keys.resize(index_keys.size());
360 for (size_t i = 0; i < index_keys.size(); ++i) {
361 params.index_keys[i].resize(index_keys[i].size());
362 for (size_t j = 0; j < index_keys[i].size(); ++j) {
363 params.index_keys[i][j] =
364 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys[i][j]));
367 Send(new IndexedDBHostMsg_DatabasePut(params));
370 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
371 int32 ipc_database_id,
372 int64 transaction_id,
373 int64 object_store_id,
374 int64 index_id,
375 const IndexedDBKeyRange& key_range,
376 unsigned short direction,
377 bool key_only,
378 WebIDBDatabase::TaskType task_type,
379 WebIDBCallbacks* callbacks) {
380 ResetCursorPrefetchCaches();
381 IndexedDBHostMsg_DatabaseOpenCursor_Params params;
382 init_params(params, callbacks);
383 params.ipc_database_id = ipc_database_id;
384 params.transaction_id = transaction_id;
385 params.object_store_id = object_store_id;
386 params.index_id = index_id;
387 params.key_range = key_range;
388 params.direction = direction;
389 params.key_only = key_only;
390 params.task_type = task_type;
391 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params));
394 void IndexedDBDispatcher::RequestIDBDatabaseCount(
395 int32 ipc_database_id,
396 int64 transaction_id,
397 int64 object_store_id,
398 int64 index_id,
399 const IndexedDBKeyRange& key_range,
400 WebIDBCallbacks* callbacks) {
401 ResetCursorPrefetchCaches();
402 IndexedDBHostMsg_DatabaseCount_Params params;
403 init_params(params, callbacks);
404 params.ipc_database_id = ipc_database_id;
405 params.transaction_id = transaction_id;
406 params.object_store_id = object_store_id;
407 params.index_id = index_id;
408 params.key_range = key_range;
409 Send(new IndexedDBHostMsg_DatabaseCount(params));
412 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
413 int32 ipc_database_id,
414 int64 transaction_id,
415 int64 object_store_id,
416 const IndexedDBKeyRange& key_range,
417 WebIDBCallbacks* callbacks) {
418 ResetCursorPrefetchCaches();
419 IndexedDBHostMsg_DatabaseDeleteRange_Params params;
420 init_params(params, callbacks);
421 params.ipc_database_id = ipc_database_id;
422 params.transaction_id = transaction_id;
423 params.object_store_id = object_store_id;
424 params.key_range = key_range;
425 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params));
428 void IndexedDBDispatcher::RequestIDBDatabaseClear(
429 int32 ipc_database_id,
430 int64 transaction_id,
431 int64 object_store_id,
432 WebIDBCallbacks* callbacks_ptr) {
433 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
434 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
435 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
436 ipc_callbacks_id,
437 ipc_database_id,
438 transaction_id,
439 object_store_id));
442 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
443 cursors_.erase(ipc_cursor_id);
446 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) {
447 DCHECK_EQ(databases_.count(ipc_database_id), 1u);
448 databases_.erase(ipc_database_id);
451 void IndexedDBDispatcher::OnSuccessIDBDatabase(
452 int32 ipc_thread_id,
453 int32 ipc_callbacks_id,
454 int32 ipc_database_callbacks_id,
455 int32 ipc_object_id,
456 const IndexedDBDatabaseMetadata& idb_metadata) {
457 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
458 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
459 if (!callbacks)
460 return;
461 WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
462 // If an upgrade was performed, count will be non-zero.
463 if (!databases_.count(ipc_object_id))
464 databases_[ipc_object_id] = new RendererWebIDBDatabaseImpl(
465 ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get());
466 DCHECK_EQ(databases_.count(ipc_object_id), 1u);
467 callbacks->onSuccess(databases_[ipc_object_id], metadata);
468 pending_callbacks_.Remove(ipc_callbacks_id);
471 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
472 int32 ipc_callbacks_id,
473 const IndexedDBKey& key) {
474 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
475 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
476 if (!callbacks)
477 return;
478 callbacks->onSuccess(WebIDBKeyBuilder::Build(key));
479 pending_callbacks_.Remove(ipc_callbacks_id);
482 void IndexedDBDispatcher::OnSuccessStringList(
483 int32 ipc_thread_id,
484 int32 ipc_callbacks_id,
485 const std::vector<string16>& value) {
486 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
487 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
488 if (!callbacks)
489 return;
490 callbacks->onSuccess(WebVector<WebString>(value));
491 pending_callbacks_.Remove(ipc_callbacks_id);
494 void IndexedDBDispatcher::OnSuccessValue(int32 ipc_thread_id,
495 int32 ipc_callbacks_id,
496 const std::string& value) {
497 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
498 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
499 if (!callbacks)
500 return;
501 WebData web_value;
502 if (value.size())
503 web_value.assign(&*value.begin(), value.size());
504 callbacks->onSuccess(web_value);
505 pending_callbacks_.Remove(ipc_callbacks_id);
508 void IndexedDBDispatcher::OnSuccessValueWithKey(
509 int32 ipc_thread_id,
510 int32 ipc_callbacks_id,
511 const std::string& value,
512 const IndexedDBKey& primary_key,
513 const IndexedDBKeyPath& key_path) {
514 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
515 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
516 if (!callbacks)
517 return;
518 WebData web_value;
519 if (value.size())
520 web_value.assign(&*value.begin(), value.size());
521 callbacks->onSuccess(web_value,
522 WebIDBKeyBuilder::Build(primary_key),
523 WebIDBKeyPathBuilder::Build(key_path));
524 pending_callbacks_.Remove(ipc_callbacks_id);
527 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id,
528 int32 ipc_callbacks_id,
529 int64 value) {
530 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
531 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
532 if (!callbacks)
533 return;
534 callbacks->onSuccess(value);
535 pending_callbacks_.Remove(ipc_callbacks_id);
538 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id,
539 int32 ipc_callbacks_id) {
540 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
541 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
542 if (!callbacks)
543 return;
544 callbacks->onSuccess();
545 pending_callbacks_.Remove(ipc_callbacks_id);
548 void IndexedDBDispatcher::OnSuccessOpenCursor(
549 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) {
550 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
551 int32 ipc_callbacks_id = p.ipc_callbacks_id;
552 int32 ipc_object_id = p.ipc_cursor_id;
553 const IndexedDBKey& key = p.key;
554 const IndexedDBKey& primary_key = p.primary_key;
555 WebData web_value;
556 if (p.value.size())
557 web_value.assign(&*p.value.begin(), p.value.size());
559 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
560 if (!callbacks)
561 return;
563 RendererWebIDBCursorImpl* cursor =
564 new RendererWebIDBCursorImpl(ipc_object_id, thread_safe_sender_.get());
565 cursors_[ipc_object_id] = cursor;
566 callbacks->onSuccess(cursor, WebIDBKeyBuilder::Build(key),
567 WebIDBKeyBuilder::Build(primary_key), web_value);
569 pending_callbacks_.Remove(ipc_callbacks_id);
572 void IndexedDBDispatcher::OnSuccessCursorContinue(
573 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) {
574 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
575 int32 ipc_callbacks_id = p.ipc_callbacks_id;
576 int32 ipc_cursor_id = p.ipc_cursor_id;
577 const IndexedDBKey& key = p.key;
578 const IndexedDBKey& primary_key = p.primary_key;
579 const std::string& value = p.value;
581 RendererWebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
582 DCHECK(cursor);
584 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
585 if (!callbacks)
586 return;
588 WebData web_value;
589 if (value.size())
590 web_value.assign(&*value.begin(), value.size());
591 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
592 WebIDBKeyBuilder::Build(primary_key), web_value);
594 pending_callbacks_.Remove(ipc_callbacks_id);
597 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
598 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) {
599 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
600 int32 ipc_callbacks_id = p.ipc_callbacks_id;
601 int32 ipc_cursor_id = p.ipc_cursor_id;
602 const std::vector<IndexedDBKey>& keys = p.keys;
603 const std::vector<IndexedDBKey>& primary_keys = p.primary_keys;
604 std::vector<WebData> values(p.values.size());
605 for (size_t i = 0; i < p.values.size(); ++i) {
606 if (p.values[i].size())
607 values[i].assign(&*p.values[i].begin(), p.values[i].size());
609 RendererWebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
610 DCHECK(cursor);
611 cursor->SetPrefetchData(keys, primary_keys, values);
613 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
614 DCHECK(callbacks);
615 cursor->CachedContinue(callbacks);
616 pending_callbacks_.Remove(ipc_callbacks_id);
619 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id,
620 int32 ipc_callbacks_id,
621 int64 existing_version) {
622 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
623 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
624 DCHECK(callbacks);
625 callbacks->onBlocked(existing_version);
628 void IndexedDBDispatcher::OnUpgradeNeeded(
629 const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
630 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
631 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id);
632 DCHECK(callbacks);
633 WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
634 DCHECK(!databases_.count(p.ipc_database_id));
635 databases_[p.ipc_database_id] =
636 new RendererWebIDBDatabaseImpl(p.ipc_database_id,
637 p.ipc_database_callbacks_id,
638 thread_safe_sender_.get());
639 callbacks->onUpgradeNeeded(
640 p.old_version,
641 databases_[p.ipc_database_id],
642 metadata,
643 static_cast<WebIDBCallbacks::DataLoss>(p.data_loss));
646 void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
647 int32 ipc_callbacks_id,
648 int code,
649 const string16& message) {
650 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
651 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
652 if (!callbacks)
653 return;
654 if (message.empty())
655 callbacks->onError(WebIDBDatabaseError(code));
656 else
657 callbacks->onError(WebIDBDatabaseError(code, message));
658 pending_callbacks_.Remove(ipc_callbacks_id);
661 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
662 int32 ipc_database_callbacks_id,
663 int64 transaction_id,
664 int code,
665 const string16& message) {
666 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
667 WebIDBDatabaseCallbacks* callbacks =
668 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
669 if (!callbacks)
670 return;
671 if (message.empty())
672 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code));
673 else
674 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message));
677 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id,
678 int32 ipc_database_callbacks_id,
679 int64 transaction_id) {
680 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
681 WebIDBDatabaseCallbacks* callbacks =
682 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
683 if (!callbacks)
684 return;
685 callbacks->onComplete(transaction_id);
688 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id,
689 int32 ipc_database_callbacks_id) {
690 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
691 WebIDBDatabaseCallbacks* callbacks =
692 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
693 if (!callbacks)
694 return;
695 callbacks->onForcedClose();
698 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
699 int32 ipc_database_callbacks_id,
700 int64 old_version,
701 int64 new_version) {
702 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
703 WebIDBDatabaseCallbacks* callbacks =
704 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
705 // callbacks would be NULL if a versionchange event is received after close
706 // has been called.
707 if (!callbacks)
708 return;
709 callbacks->onVersionChange(old_version, new_version);
712 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
713 int32 ipc_exception_cursor_id) {
714 typedef std::map<int32, RendererWebIDBCursorImpl*>::iterator Iterator;
715 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
716 if (i->first == ipc_exception_cursor_id)
717 continue;
718 i->second->ResetPrefetchCache();
722 } // namespace content