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