Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher.cc
blob8275b2141faed34765bcdf82c89dcffa3e8f7c2d
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 <utility>
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;
26 using blink::WebData;
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;
39 namespace content {
40 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
41 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
43 namespace {
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 g_idb_dispatcher_tls.Pointer()->Set(this);
58 IndexedDBDispatcher::~IndexedDBDispatcher() {
59 // Clear any pending callbacks - which may result in dispatch requests -
60 // before marking the dispatcher as deleted.
61 pending_callbacks_.Clear();
62 pending_database_callbacks_.Clear();
64 DCHECK(pending_callbacks_.IsEmpty());
65 DCHECK(pending_database_callbacks_.IsEmpty());
67 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
70 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance(
71 ThreadSafeSender* thread_safe_sender) {
72 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
73 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
74 g_idb_dispatcher_tls.Pointer()->Set(NULL);
76 if (g_idb_dispatcher_tls.Pointer()->Get())
77 return g_idb_dispatcher_tls.Pointer()->Get();
79 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender);
80 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
81 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
82 return dispatcher;
85 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
87 WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
88 const IndexedDBDatabaseMetadata& idb_metadata) {
89 WebIDBMetadata web_metadata;
90 web_metadata.id = idb_metadata.id;
91 web_metadata.name = idb_metadata.name;
92 web_metadata.version = idb_metadata.version;
93 web_metadata.intVersion = idb_metadata.int_version;
94 web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
95 web_metadata.objectStores =
96 WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
98 for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) {
99 const IndexedDBObjectStoreMetadata& idb_store_metadata =
100 idb_metadata.object_stores[i];
101 WebIDBMetadata::ObjectStore& web_store_metadata =
102 web_metadata.objectStores[i];
104 web_store_metadata.id = idb_store_metadata.id;
105 web_store_metadata.name = idb_store_metadata.name;
106 web_store_metadata.keyPath =
107 WebIDBKeyPathBuilder::Build(idb_store_metadata.key_path);
108 web_store_metadata.autoIncrement = idb_store_metadata.auto_increment;
109 web_store_metadata.maxIndexId = idb_store_metadata.max_index_id;
110 web_store_metadata.indexes =
111 WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size());
113 for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) {
114 const IndexedDBIndexMetadata& idb_index_metadata =
115 idb_store_metadata.indexes[j];
116 WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j];
118 web_index_metadata.id = idb_index_metadata.id;
119 web_index_metadata.name = idb_index_metadata.name;
120 web_index_metadata.keyPath =
121 WebIDBKeyPathBuilder::Build(idb_index_metadata.key_path);
122 web_index_metadata.unique = idb_index_metadata.unique;
123 web_index_metadata.multiEntry = idb_index_metadata.multi_entry;
127 return web_metadata;
130 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
131 bool handled = true;
132 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
133 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
134 OnSuccessOpenCursor)
135 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance,
136 OnSuccessCursorContinue)
137 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
138 OnSuccessCursorContinue)
139 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
140 OnSuccessCursorPrefetch)
141 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
142 OnSuccessIDBDatabase)
143 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
144 OnSuccessIndexedDBKey)
145 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList,
146 OnSuccessStringList)
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessArray, OnSuccessArray)
148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue)
149 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined,
151 OnSuccessUndefined)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError)
153 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked)
154 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
156 OnForcedClose)
157 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
158 OnIntVersionChange)
159 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
160 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
161 IPC_MESSAGE_UNHANDLED(handled = false)
162 IPC_END_MESSAGE_MAP()
163 // If a message gets here, IndexedDBMessageFilter already determined that it
164 // is an IndexedDB message.
165 DCHECK(handled) << "Didn't handle a message defined at line "
166 << IPC_MESSAGE_ID_LINE(msg.type());
169 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
170 return thread_safe_sender_->Send(msg);
173 void IndexedDBDispatcher::RequestIDBCursorAdvance(
174 unsigned long count,
175 WebIDBCallbacks* callbacks_ptr,
176 int32 ipc_cursor_id,
177 int64 transaction_id) {
178 // Reset all cursor prefetch caches except for this cursor.
179 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
181 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
183 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
184 Send(new IndexedDBHostMsg_CursorAdvance(
185 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count));
188 void IndexedDBDispatcher::RequestIDBCursorContinue(
189 const IndexedDBKey& key,
190 const IndexedDBKey& primary_key,
191 WebIDBCallbacks* callbacks_ptr,
192 int32 ipc_cursor_id,
193 int64 transaction_id) {
194 // Reset all cursor prefetch caches except for this cursor.
195 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
197 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
199 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
200 Send(new IndexedDBHostMsg_CursorContinue(
201 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key));
204 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
205 int n,
206 WebIDBCallbacks* callbacks_ptr,
207 int32 ipc_cursor_id) {
208 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
210 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
211 Send(new IndexedDBHostMsg_CursorPrefetch(
212 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n));
215 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
216 int unused_prefetches,
217 int32 ipc_cursor_id) {
218 Send(new IndexedDBHostMsg_CursorPrefetchReset(
219 ipc_cursor_id, used_prefetches, unused_prefetches));
222 void IndexedDBDispatcher::RequestIDBFactoryOpen(
223 const base::string16& name,
224 int64 version,
225 int64 transaction_id,
226 WebIDBCallbacks* callbacks_ptr,
227 WebIDBDatabaseCallbacks* database_callbacks_ptr,
228 const std::string& database_identifier) {
229 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
230 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
231 database_callbacks_ptr);
233 IndexedDBHostMsg_FactoryOpen_Params params;
234 params.ipc_thread_id = CurrentWorkerId();
235 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
236 params.ipc_database_callbacks_id =
237 pending_database_callbacks_.Add(database_callbacks.release());
238 params.database_identifier = database_identifier;
239 params.name = name;
240 params.transaction_id = transaction_id;
241 params.version = version;
242 Send(new IndexedDBHostMsg_FactoryOpen(params));
245 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
246 WebIDBCallbacks* callbacks_ptr,
247 const std::string& database_identifier) {
248 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
250 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
251 params.ipc_thread_id = CurrentWorkerId();
252 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
253 params.database_identifier = database_identifier;
254 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
257 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
258 const base::string16& name,
259 WebIDBCallbacks* callbacks_ptr,
260 const std::string& database_identifier) {
261 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
263 IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
264 params.ipc_thread_id = CurrentWorkerId();
265 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
266 params.database_identifier = database_identifier;
267 params.name = name;
268 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
271 void IndexedDBDispatcher::RequestIDBDatabaseClose(
272 int32 ipc_database_id,
273 int32 ipc_database_callbacks_id) {
274 Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id));
275 // There won't be pending database callbacks if the transaction was aborted in
276 // the initial upgradeneeded event handler.
277 if (pending_database_callbacks_.Lookup(ipc_database_callbacks_id))
278 pending_database_callbacks_.Remove(ipc_database_callbacks_id);
281 void IndexedDBDispatcher::NotifyIDBDatabaseVersionChangeIgnored(
282 int32 ipc_database_id) {
283 Send(new IndexedDBHostMsg_DatabaseVersionChangeIgnored(ipc_database_id));
286 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
287 int32 ipc_database_id,
288 int64 transaction_id,
289 WebIDBDatabaseCallbacks* database_callbacks_ptr,
290 WebVector<long long> object_store_ids,
291 blink::WebIDBTransactionMode mode) {
292 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
293 database_callbacks_ptr);
294 IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
295 params.ipc_thread_id = CurrentWorkerId();
296 params.ipc_database_id = ipc_database_id;
297 params.transaction_id = transaction_id;
298 params.ipc_database_callbacks_id =
299 pending_database_callbacks_.Add(database_callbacks.release());
300 params.object_store_ids
301 .assign(object_store_ids.data(),
302 object_store_ids.data() + object_store_ids.size());
303 params.mode = mode;
305 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
308 void IndexedDBDispatcher::RequestIDBDatabaseGet(
309 int32 ipc_database_id,
310 int64 transaction_id,
311 int64 object_store_id,
312 int64 index_id,
313 const IndexedDBKeyRange& key_range,
314 bool key_only,
315 WebIDBCallbacks* callbacks) {
316 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
317 IndexedDBHostMsg_DatabaseGet_Params params;
318 init_params(&params, callbacks);
319 params.ipc_database_id = ipc_database_id;
320 params.transaction_id = transaction_id;
321 params.object_store_id = object_store_id;
322 params.index_id = index_id;
323 params.key_range = key_range;
324 params.key_only = key_only;
325 Send(new IndexedDBHostMsg_DatabaseGet(params));
328 void IndexedDBDispatcher::RequestIDBDatabaseGetAll(
329 int32 ipc_database_id,
330 int64 transaction_id,
331 int64 object_store_id,
332 int64 index_id,
333 const IndexedDBKeyRange& key_range,
334 bool key_only,
335 int64 max_count,
336 WebIDBCallbacks* callbacks) {
337 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
338 IndexedDBHostMsg_DatabaseGetAll_Params params;
339 init_params(&params, callbacks);
340 params.ipc_database_id = ipc_database_id;
341 params.transaction_id = transaction_id;
342 params.object_store_id = object_store_id;
343 params.index_id = index_id;
344 params.key_range = key_range;
345 params.key_only = key_only;
346 params.max_count = max_count;
347 Send(new IndexedDBHostMsg_DatabaseGetAll(params));
350 void IndexedDBDispatcher::RequestIDBDatabasePut(
351 int32 ipc_database_id,
352 int64 transaction_id,
353 int64 object_store_id,
354 const WebData& value,
355 const blink::WebVector<WebBlobInfo>& web_blob_info,
356 const IndexedDBKey& key,
357 blink::WebIDBPutMode put_mode,
358 WebIDBCallbacks* callbacks,
359 const WebVector<long long>& index_ids,
360 const WebVector<WebVector<WebIDBKey> >& index_keys) {
361 if (value.size() + key.size_estimate() > kMaxIDBValueSizeInBytes) {
362 callbacks->onError(WebIDBDatabaseError(
363 blink::WebIDBDatabaseExceptionUnknownError,
364 WebString::fromUTF8(base::StringPrintf(
365 "The serialized value is too large"
366 " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
367 value.size(),
368 kMaxIDBValueSizeInBytes).c_str())));
369 return;
372 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
373 IndexedDBHostMsg_DatabasePut_Params params;
374 init_params(&params, callbacks);
375 params.ipc_database_id = ipc_database_id;
376 params.transaction_id = transaction_id;
377 params.object_store_id = object_store_id;
379 params.value.bits.assign(value.data(), value.data() + value.size());
380 params.key = key;
381 params.put_mode = put_mode;
383 DCHECK_EQ(index_ids.size(), index_keys.size());
384 params.index_keys.resize(index_ids.size());
385 for (size_t i = 0, len = index_ids.size(); i < len; ++i) {
386 params.index_keys[i].first = index_ids[i];
387 params.index_keys[i].second.resize(index_keys[i].size());
388 for (size_t j = 0; j < index_keys[i].size(); ++j) {
389 params.index_keys[i].second[j] =
390 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys[i][j]));
394 params.value.blob_or_file_info.resize(web_blob_info.size());
395 for (size_t i = 0; i < web_blob_info.size(); ++i) {
396 const WebBlobInfo& info = web_blob_info[i];
397 IndexedDBMsg_BlobOrFileInfo& blob_or_file_info =
398 params.value.blob_or_file_info[i];
399 blob_or_file_info.is_file = info.isFile();
400 if (info.isFile()) {
401 blob_or_file_info.file_path = info.filePath();
402 blob_or_file_info.file_name = info.fileName();
403 blob_or_file_info.last_modified = info.lastModified();
405 blob_or_file_info.size = info.size();
406 blob_or_file_info.uuid = info.uuid().latin1();
407 DCHECK(blob_or_file_info.uuid.size());
408 blob_or_file_info.mime_type = info.type();
411 Send(new IndexedDBHostMsg_DatabasePut(params));
414 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
415 int32 ipc_database_id,
416 int64 transaction_id,
417 int64 object_store_id,
418 int64 index_id,
419 const IndexedDBKeyRange& key_range,
420 blink::WebIDBCursorDirection direction,
421 bool key_only,
422 blink::WebIDBTaskType task_type,
423 WebIDBCallbacks* callbacks) {
424 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
425 IndexedDBHostMsg_DatabaseOpenCursor_Params params;
426 init_params(&params, callbacks);
427 params.ipc_database_id = ipc_database_id;
428 params.transaction_id = transaction_id;
429 params.object_store_id = object_store_id;
430 params.index_id = index_id;
431 params.key_range = key_range;
432 params.direction = direction;
433 params.key_only = key_only;
434 params.task_type = task_type;
435 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params));
437 DCHECK(cursor_transaction_ids_.find(params.ipc_callbacks_id) ==
438 cursor_transaction_ids_.end());
439 cursor_transaction_ids_[params.ipc_callbacks_id] = transaction_id;
442 void IndexedDBDispatcher::RequestIDBDatabaseCount(
443 int32 ipc_database_id,
444 int64 transaction_id,
445 int64 object_store_id,
446 int64 index_id,
447 const IndexedDBKeyRange& key_range,
448 WebIDBCallbacks* callbacks) {
449 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
450 IndexedDBHostMsg_DatabaseCount_Params params;
451 init_params(&params, callbacks);
452 params.ipc_database_id = ipc_database_id;
453 params.transaction_id = transaction_id;
454 params.object_store_id = object_store_id;
455 params.index_id = index_id;
456 params.key_range = key_range;
457 Send(new IndexedDBHostMsg_DatabaseCount(params));
460 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
461 int32 ipc_database_id,
462 int64 transaction_id,
463 int64 object_store_id,
464 const IndexedDBKeyRange& key_range,
465 WebIDBCallbacks* callbacks) {
466 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
467 IndexedDBHostMsg_DatabaseDeleteRange_Params params;
468 init_params(&params, callbacks);
469 params.ipc_database_id = ipc_database_id;
470 params.transaction_id = transaction_id;
471 params.object_store_id = object_store_id;
472 params.key_range = key_range;
473 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params));
476 void IndexedDBDispatcher::RequestIDBDatabaseClear(
477 int32 ipc_database_id,
478 int64 transaction_id,
479 int64 object_store_id,
480 WebIDBCallbacks* callbacks_ptr) {
481 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
482 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
483 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
484 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
485 ipc_callbacks_id,
486 ipc_database_id,
487 transaction_id,
488 object_store_id));
491 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
492 cursors_.erase(ipc_cursor_id);
495 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) {
496 DCHECK_EQ(databases_.count(ipc_database_id), 1u);
497 databases_.erase(ipc_database_id);
500 void IndexedDBDispatcher::OnSuccessIDBDatabase(
501 int32 ipc_thread_id,
502 int32 ipc_callbacks_id,
503 int32 ipc_database_callbacks_id,
504 int32 ipc_object_id,
505 const IndexedDBDatabaseMetadata& idb_metadata) {
506 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
507 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
508 if (!callbacks)
509 return;
510 WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
511 // If an upgrade was performed, count will be non-zero.
512 WebIDBDatabase* database = NULL;
514 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
515 // May already be deleted and removed from the table, but do not recreate..
516 if (ipc_object_id != kNoDatabase) {
517 DCHECK(!databases_.count(ipc_object_id));
518 database = databases_[ipc_object_id] = new WebIDBDatabaseImpl(
519 ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get());
522 callbacks->onSuccess(database, metadata);
523 pending_callbacks_.Remove(ipc_callbacks_id);
526 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
527 int32 ipc_callbacks_id,
528 const IndexedDBKey& key) {
529 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
530 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
531 if (!callbacks)
532 return;
533 callbacks->onSuccess(WebIDBKeyBuilder::Build(key));
534 pending_callbacks_.Remove(ipc_callbacks_id);
537 void IndexedDBDispatcher::OnSuccessStringList(
538 int32 ipc_thread_id,
539 int32 ipc_callbacks_id,
540 const std::vector<base::string16>& value) {
541 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
542 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
543 if (!callbacks)
544 return;
545 callbacks->onSuccess(WebVector<WebString>(value));
546 pending_callbacks_.Remove(ipc_callbacks_id);
549 static void PrepareWebValue(const IndexedDBMsg_ReturnValue& value,
550 WebIDBValue* web_value) {
551 if (value.bits.empty())
552 return;
554 web_value->data.assign(&*value.bits.begin(), value.bits.size());
555 blink::WebVector<WebBlobInfo> local_blob_info(value.blob_or_file_info.size());
556 for (size_t i = 0; i < value.blob_or_file_info.size(); ++i) {
557 const IndexedDBMsg_BlobOrFileInfo& info = value.blob_or_file_info[i];
558 if (info.is_file) {
559 local_blob_info[i] = WebBlobInfo(
560 WebString::fromUTF8(info.uuid.c_str()), info.file_path,
561 info.file_name, info.mime_type, info.last_modified, info.size);
562 } else {
563 local_blob_info[i] = WebBlobInfo(WebString::fromUTF8(info.uuid.c_str()),
564 info.mime_type, info.size);
568 web_value->webBlobInfo.swap(local_blob_info);
569 web_value->primaryKey = WebIDBKeyBuilder::Build(value.primary_key);
570 web_value->keyPath = WebIDBKeyPathBuilder::Build(value.key_path);
573 static void PrepareWebValueAndBlobInfo(
574 const IndexedDBMsg_Value& value,
575 WebData* web_value,
576 blink::WebVector<WebBlobInfo>* web_blob_info) {
577 if (value.bits.empty())
578 return;
580 web_value->assign(&*value.bits.begin(), value.bits.size());
581 blink::WebVector<WebBlobInfo> local_blob_info(value.blob_or_file_info.size());
582 for (size_t i = 0; i < value.blob_or_file_info.size(); ++i) {
583 const IndexedDBMsg_BlobOrFileInfo& info = value.blob_or_file_info[i];
584 if (info.is_file) {
585 local_blob_info[i] = WebBlobInfo(WebString::fromUTF8(info.uuid.c_str()),
586 info.file_path,
587 info.file_name,
588 info.mime_type,
589 info.last_modified,
590 info.size);
591 } else {
592 local_blob_info[i] = WebBlobInfo(
593 WebString::fromUTF8(info.uuid.c_str()), info.mime_type, info.size);
596 web_blob_info->swap(local_blob_info);
599 void IndexedDBDispatcher::OnSuccessArray(
600 const IndexedDBMsg_CallbacksSuccessArray_Params& p) {
601 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
602 int32 ipc_callbacks_id = p.ipc_callbacks_id;
603 blink::WebVector<WebIDBValue> web_values(p.values.size());
604 for (size_t i = 0; i < p.values.size(); ++i)
605 PrepareWebValue(p.values[i], &web_values[i]);
606 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
607 DCHECK(callbacks);
608 callbacks->onSuccess(web_values);
609 pending_callbacks_.Remove(ipc_callbacks_id);
612 void IndexedDBDispatcher::OnSuccessValue(
613 const IndexedDBMsg_CallbacksSuccessValue_Params& params) {
614 DCHECK_EQ(params.ipc_thread_id, CurrentWorkerId());
615 WebIDBCallbacks* callbacks =
616 pending_callbacks_.Lookup(params.ipc_callbacks_id);
617 if (!callbacks)
618 return;
619 WebIDBValue web_value;
620 PrepareWebValue(params.value, &web_value);
621 if (params.value.primary_key.IsValid()) {
622 web_value.primaryKey = WebIDBKeyBuilder::Build(params.value.primary_key);
623 web_value.keyPath = WebIDBKeyPathBuilder::Build(params.value.key_path);
625 callbacks->onSuccess(web_value);
626 cursor_transaction_ids_.erase(params.ipc_callbacks_id);
627 pending_callbacks_.Remove(params.ipc_callbacks_id);
630 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id,
631 int32 ipc_callbacks_id,
632 int64 value) {
633 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
634 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
635 if (!callbacks)
636 return;
637 callbacks->onSuccess(value);
638 pending_callbacks_.Remove(ipc_callbacks_id);
641 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id,
642 int32 ipc_callbacks_id) {
643 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
644 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
645 if (!callbacks)
646 return;
647 callbacks->onSuccess();
648 pending_callbacks_.Remove(ipc_callbacks_id);
651 void IndexedDBDispatcher::OnSuccessOpenCursor(
652 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) {
653 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
654 int32 ipc_callbacks_id = p.ipc_callbacks_id;
655 int32 ipc_object_id = p.ipc_cursor_id;
656 const IndexedDBKey& key = p.key;
657 const IndexedDBKey& primary_key = p.primary_key;
658 WebData web_value;
659 WebVector<WebBlobInfo> web_blob_info;
660 PrepareWebValueAndBlobInfo(p.value, &web_value, &web_blob_info);
662 DCHECK(cursor_transaction_ids_.find(ipc_callbacks_id) !=
663 cursor_transaction_ids_.end());
664 int64 transaction_id = cursor_transaction_ids_[ipc_callbacks_id];
665 cursor_transaction_ids_.erase(ipc_callbacks_id);
667 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
668 if (!callbacks)
669 return;
671 WebIDBCursorImpl* cursor = new WebIDBCursorImpl(
672 ipc_object_id, transaction_id, thread_safe_sender_.get());
673 cursors_[ipc_object_id] = cursor;
674 callbacks->onSuccess(cursor,
675 WebIDBKeyBuilder::Build(key),
676 WebIDBKeyBuilder::Build(primary_key),
677 web_value,
678 web_blob_info);
680 pending_callbacks_.Remove(ipc_callbacks_id);
683 void IndexedDBDispatcher::OnSuccessCursorContinue(
684 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) {
685 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
686 int32 ipc_callbacks_id = p.ipc_callbacks_id;
687 int32 ipc_cursor_id = p.ipc_cursor_id;
688 const IndexedDBKey& key = p.key;
689 const IndexedDBKey& primary_key = p.primary_key;
691 if (cursors_.find(ipc_cursor_id) == cursors_.end())
692 return;
694 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
695 if (!callbacks)
696 return;
698 WebData web_value;
699 WebVector<WebBlobInfo> web_blob_info;
700 PrepareWebValueAndBlobInfo(p.value, &web_value, &web_blob_info);
701 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
702 WebIDBKeyBuilder::Build(primary_key),
703 web_value,
704 web_blob_info);
706 pending_callbacks_.Remove(ipc_callbacks_id);
709 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
710 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) {
711 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
712 int32 ipc_callbacks_id = p.ipc_callbacks_id;
713 int32 ipc_cursor_id = p.ipc_cursor_id;
714 const std::vector<IndexedDBKey>& keys = p.keys;
715 const std::vector<IndexedDBKey>& primary_keys = p.primary_keys;
716 std::vector<WebData> values(p.values.size());
717 std::vector<WebVector<WebBlobInfo>> blob_infos(p.values.size());
718 for (size_t i = 0; i < p.values.size(); ++i)
719 PrepareWebValueAndBlobInfo(p.values[i], &values[i], &blob_infos[i]);
720 std::map<int32, WebIDBCursorImpl*>::const_iterator cur_iter =
721 cursors_.find(ipc_cursor_id);
722 if (cur_iter == cursors_.end())
723 return;
725 cur_iter->second->SetPrefetchData(keys, primary_keys, values, blob_infos);
727 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
728 DCHECK(callbacks);
729 cur_iter->second->CachedContinue(callbacks);
730 pending_callbacks_.Remove(ipc_callbacks_id);
733 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id,
734 int32 ipc_callbacks_id,
735 int64 existing_version) {
736 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
737 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
738 DCHECK(callbacks);
739 callbacks->onBlocked(existing_version);
742 void IndexedDBDispatcher::OnUpgradeNeeded(
743 const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
744 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
745 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id);
746 DCHECK(callbacks);
747 WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
748 DCHECK(!databases_.count(p.ipc_database_id));
749 databases_[p.ipc_database_id] =
750 new WebIDBDatabaseImpl(p.ipc_database_id,
751 p.ipc_database_callbacks_id,
752 thread_safe_sender_.get());
753 callbacks->onUpgradeNeeded(
754 p.old_version,
755 databases_[p.ipc_database_id],
756 metadata,
757 static_cast<blink::WebIDBDataLoss>(p.data_loss),
758 WebString::fromUTF8(p.data_loss_message));
761 void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
762 int32 ipc_callbacks_id,
763 int code,
764 const base::string16& message) {
765 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
766 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
767 if (!callbacks)
768 return;
769 if (message.empty())
770 callbacks->onError(WebIDBDatabaseError(code));
771 else
772 callbacks->onError(WebIDBDatabaseError(code, message));
773 pending_callbacks_.Remove(ipc_callbacks_id);
774 cursor_transaction_ids_.erase(ipc_callbacks_id);
777 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
778 int32 ipc_database_callbacks_id,
779 int64 transaction_id,
780 int code,
781 const base::string16& message) {
782 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
783 WebIDBDatabaseCallbacks* callbacks =
784 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
785 if (!callbacks)
786 return;
787 if (message.empty())
788 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code));
789 else
790 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message));
793 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id,
794 int32 ipc_database_callbacks_id,
795 int64 transaction_id) {
796 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
797 WebIDBDatabaseCallbacks* callbacks =
798 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
799 if (!callbacks)
800 return;
801 callbacks->onComplete(transaction_id);
804 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id,
805 int32 ipc_database_callbacks_id) {
806 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
807 WebIDBDatabaseCallbacks* callbacks =
808 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
809 if (!callbacks)
810 return;
811 callbacks->onForcedClose();
814 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
815 int32 ipc_database_callbacks_id,
816 int64 old_version,
817 int64 new_version) {
818 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
819 WebIDBDatabaseCallbacks* callbacks =
820 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
821 // callbacks would be NULL if a versionchange event is received after close
822 // has been called.
823 if (!callbacks)
824 return;
825 callbacks->onVersionChange(old_version, new_version);
828 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
829 int64 transaction_id,
830 int32 ipc_exception_cursor_id) {
831 typedef std::map<int32, WebIDBCursorImpl*>::iterator Iterator;
832 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
833 if (i->first == ipc_exception_cursor_id ||
834 i->second->transaction_id() != transaction_id)
835 continue;
836 i->second->ResetPrefetchCache();
840 } // namespace content