Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher.cc
blobc0d1fb24d7a92961136a274c55c90dff347b25ec
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/WebIDBDatabaseCallbacks.h"
21 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
22 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
24 using blink::WebBlobInfo;
25 using blink::WebData;
26 using blink::WebIDBCallbacks;
27 using blink::WebIDBCursor;
28 using blink::WebIDBDatabase;
29 using blink::WebIDBDatabaseCallbacks;
30 using blink::WebIDBDatabaseError;
31 using blink::WebIDBKey;
32 using blink::WebIDBMetadata;
33 using blink::WebString;
34 using blink::WebVector;
35 using base::ThreadLocalPointer;
37 namespace content {
38 static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
39 g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
41 namespace {
43 IndexedDBDispatcher* const kHasBeenDeleted =
44 reinterpret_cast<IndexedDBDispatcher*>(0x1);
46 } // unnamed namespace
48 const size_t kMaxIDBMessageOverhead = 1024 * 1024; // 1MB; arbitrarily chosen.
49 const size_t kMaxIDBValueSizeInBytes =
50 IPC::Channel::kMaximumMessageSize - kMaxIDBMessageOverhead;
52 IndexedDBDispatcher::IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender)
53 : thread_safe_sender_(thread_safe_sender) {
54 g_idb_dispatcher_tls.Pointer()->Set(this);
57 IndexedDBDispatcher::~IndexedDBDispatcher() {
58 // Clear any pending callbacks - which may result in dispatch requests -
59 // before marking the dispatcher as deleted.
60 pending_callbacks_.Clear();
61 pending_database_callbacks_.Clear();
63 DCHECK(pending_callbacks_.IsEmpty());
64 DCHECK(pending_database_callbacks_.IsEmpty());
66 g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
69 IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance(
70 ThreadSafeSender* thread_safe_sender) {
71 if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
72 NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
73 g_idb_dispatcher_tls.Pointer()->Set(NULL);
75 if (g_idb_dispatcher_tls.Pointer()->Get())
76 return g_idb_dispatcher_tls.Pointer()->Get();
78 IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(thread_safe_sender);
79 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
80 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
81 return dispatcher;
84 void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
86 WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
87 const IndexedDBDatabaseMetadata& idb_metadata) {
88 WebIDBMetadata web_metadata;
89 web_metadata.id = idb_metadata.id;
90 web_metadata.name = idb_metadata.name;
91 web_metadata.version = idb_metadata.version;
92 web_metadata.intVersion = idb_metadata.int_version;
93 web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
94 web_metadata.objectStores =
95 WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
97 for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) {
98 const IndexedDBObjectStoreMetadata& idb_store_metadata =
99 idb_metadata.object_stores[i];
100 WebIDBMetadata::ObjectStore& web_store_metadata =
101 web_metadata.objectStores[i];
103 web_store_metadata.id = idb_store_metadata.id;
104 web_store_metadata.name = idb_store_metadata.name;
105 web_store_metadata.keyPath =
106 WebIDBKeyPathBuilder::Build(idb_store_metadata.key_path);
107 web_store_metadata.autoIncrement = idb_store_metadata.auto_increment;
108 web_store_metadata.maxIndexId = idb_store_metadata.max_index_id;
109 web_store_metadata.indexes =
110 WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size());
112 for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) {
113 const IndexedDBIndexMetadata& idb_index_metadata =
114 idb_store_metadata.indexes[j];
115 WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j];
117 web_index_metadata.id = idb_index_metadata.id;
118 web_index_metadata.name = idb_index_metadata.name;
119 web_index_metadata.keyPath =
120 WebIDBKeyPathBuilder::Build(idb_index_metadata.key_path);
121 web_index_metadata.unique = idb_index_metadata.unique;
122 web_index_metadata.multiEntry = idb_index_metadata.multi_entry;
126 return web_metadata;
129 void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
130 bool handled = true;
131 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
132 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
133 OnSuccessOpenCursor)
134 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance,
135 OnSuccessCursorContinue)
136 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
137 OnSuccessCursorContinue)
138 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
139 OnSuccessCursorPrefetch)
140 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
141 OnSuccessIDBDatabase)
142 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
143 OnSuccessIndexedDBKey)
144 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList,
145 OnSuccessStringList)
146 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue)
147 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger)
148 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined,
149 OnSuccessUndefined)
150 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError)
151 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked)
152 IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
153 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
154 OnForcedClose)
155 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
156 OnIntVersionChange)
157 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
158 IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
159 IPC_MESSAGE_UNHANDLED(handled = false)
160 IPC_END_MESSAGE_MAP()
161 // If a message gets here, IndexedDBMessageFilter already determined that it
162 // is an IndexedDB message.
163 DCHECK(handled) << "Didn't handle a message defined at line "
164 << IPC_MESSAGE_ID_LINE(msg.type());
167 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
168 return thread_safe_sender_->Send(msg);
171 void IndexedDBDispatcher::RequestIDBCursorAdvance(
172 unsigned long count,
173 WebIDBCallbacks* callbacks_ptr,
174 int32 ipc_cursor_id,
175 int64 transaction_id) {
176 // Reset all cursor prefetch caches except for this cursor.
177 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
179 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
181 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
182 Send(new IndexedDBHostMsg_CursorAdvance(
183 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count));
186 void IndexedDBDispatcher::RequestIDBCursorContinue(
187 const IndexedDBKey& key,
188 const IndexedDBKey& primary_key,
189 WebIDBCallbacks* callbacks_ptr,
190 int32 ipc_cursor_id,
191 int64 transaction_id) {
192 // Reset all cursor prefetch caches except for this cursor.
193 ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
195 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
197 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
198 Send(new IndexedDBHostMsg_CursorContinue(
199 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key));
202 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
203 int n,
204 WebIDBCallbacks* callbacks_ptr,
205 int32 ipc_cursor_id) {
206 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
208 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
209 Send(new IndexedDBHostMsg_CursorPrefetch(
210 ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n));
213 void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
214 int unused_prefetches,
215 int32 ipc_cursor_id) {
216 Send(new IndexedDBHostMsg_CursorPrefetchReset(
217 ipc_cursor_id, used_prefetches, unused_prefetches));
220 void IndexedDBDispatcher::RequestIDBFactoryOpen(
221 const base::string16& name,
222 int64 version,
223 int64 transaction_id,
224 WebIDBCallbacks* callbacks_ptr,
225 WebIDBDatabaseCallbacks* database_callbacks_ptr,
226 const std::string& database_identifier) {
227 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
228 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
229 database_callbacks_ptr);
231 IndexedDBHostMsg_FactoryOpen_Params params;
232 params.ipc_thread_id = CurrentWorkerId();
233 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
234 params.ipc_database_callbacks_id =
235 pending_database_callbacks_.Add(database_callbacks.release());
236 params.database_identifier = database_identifier;
237 params.name = name;
238 params.transaction_id = transaction_id;
239 params.version = version;
240 Send(new IndexedDBHostMsg_FactoryOpen(params));
243 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
244 WebIDBCallbacks* callbacks_ptr,
245 const std::string& database_identifier) {
246 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
248 IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
249 params.ipc_thread_id = CurrentWorkerId();
250 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
251 params.database_identifier = database_identifier;
252 Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
255 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
256 const base::string16& name,
257 WebIDBCallbacks* callbacks_ptr,
258 const std::string& database_identifier) {
259 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
261 IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
262 params.ipc_thread_id = CurrentWorkerId();
263 params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
264 params.database_identifier = database_identifier;
265 params.name = name;
266 Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
269 void IndexedDBDispatcher::RequestIDBDatabaseClose(
270 int32 ipc_database_id,
271 int32 ipc_database_callbacks_id) {
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::NotifyIDBDatabaseVersionChangeIgnored(
280 int32 ipc_database_id) {
281 Send(new IndexedDBHostMsg_DatabaseVersionChangeIgnored(ipc_database_id));
284 void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
285 int32 ipc_database_id,
286 int64 transaction_id,
287 WebIDBDatabaseCallbacks* database_callbacks_ptr,
288 WebVector<long long> object_store_ids,
289 blink::WebIDBTransactionMode mode) {
290 scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
291 database_callbacks_ptr);
292 IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
293 params.ipc_thread_id = CurrentWorkerId();
294 params.ipc_database_id = ipc_database_id;
295 params.transaction_id = transaction_id;
296 params.ipc_database_callbacks_id =
297 pending_database_callbacks_.Add(database_callbacks.release());
298 params.object_store_ids
299 .assign(object_store_ids.data(),
300 object_store_ids.data() + object_store_ids.size());
301 params.mode = mode;
303 Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
306 void IndexedDBDispatcher::RequestIDBDatabaseGet(
307 int32 ipc_database_id,
308 int64 transaction_id,
309 int64 object_store_id,
310 int64 index_id,
311 const IndexedDBKeyRange& key_range,
312 bool key_only,
313 WebIDBCallbacks* callbacks) {
314 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
315 IndexedDBHostMsg_DatabaseGet_Params params;
316 init_params(&params, callbacks);
317 params.ipc_database_id = ipc_database_id;
318 params.transaction_id = transaction_id;
319 params.object_store_id = object_store_id;
320 params.index_id = index_id;
321 params.key_range = key_range;
322 params.key_only = key_only;
323 Send(new IndexedDBHostMsg_DatabaseGet(params));
326 void IndexedDBDispatcher::RequestIDBDatabasePut(
327 int32 ipc_database_id,
328 int64 transaction_id,
329 int64 object_store_id,
330 const WebData& value,
331 const blink::WebVector<WebBlobInfo>& web_blob_info,
332 const IndexedDBKey& key,
333 blink::WebIDBPutMode put_mode,
334 WebIDBCallbacks* callbacks,
335 const WebVector<long long>& index_ids,
336 const WebVector<WebVector<WebIDBKey> >& index_keys) {
337 if (value.size() + key.size_estimate() > kMaxIDBValueSizeInBytes) {
338 callbacks->onError(WebIDBDatabaseError(
339 blink::WebIDBDatabaseExceptionUnknownError,
340 WebString::fromUTF8(base::StringPrintf(
341 "The serialized value is too large"
342 " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
343 value.size(),
344 kMaxIDBValueSizeInBytes).c_str())));
345 return;
348 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
349 IndexedDBHostMsg_DatabasePut_Params params;
350 init_params(&params, callbacks);
351 params.ipc_database_id = ipc_database_id;
352 params.transaction_id = transaction_id;
353 params.object_store_id = object_store_id;
355 params.value.bits.assign(value.data(), value.data() + value.size());
356 params.key = key;
357 params.put_mode = put_mode;
359 DCHECK_EQ(index_ids.size(), index_keys.size());
360 params.index_keys.resize(index_ids.size());
361 for (size_t i = 0, len = index_ids.size(); i < len; ++i) {
362 params.index_keys[i].first = index_ids[i];
363 params.index_keys[i].second.resize(index_keys[i].size());
364 for (size_t j = 0; j < index_keys[i].size(); ++j) {
365 params.index_keys[i].second[j] =
366 IndexedDBKey(IndexedDBKeyBuilder::Build(index_keys[i][j]));
370 params.value.blob_or_file_info.resize(web_blob_info.size());
371 for (size_t i = 0; i < web_blob_info.size(); ++i) {
372 const WebBlobInfo& info = web_blob_info[i];
373 IndexedDBMsg_BlobOrFileInfo& blob_or_file_info =
374 params.value.blob_or_file_info[i];
375 blob_or_file_info.is_file = info.isFile();
376 if (info.isFile()) {
377 blob_or_file_info.file_path = info.filePath();
378 blob_or_file_info.file_name = info.fileName();
379 blob_or_file_info.last_modified = info.lastModified();
381 blob_or_file_info.size = info.size();
382 blob_or_file_info.uuid = info.uuid().latin1();
383 DCHECK(blob_or_file_info.uuid.size());
384 blob_or_file_info.mime_type = info.type();
387 Send(new IndexedDBHostMsg_DatabasePut(params));
390 void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
391 int32 ipc_database_id,
392 int64 transaction_id,
393 int64 object_store_id,
394 int64 index_id,
395 const IndexedDBKeyRange& key_range,
396 blink::WebIDBCursorDirection direction,
397 bool key_only,
398 blink::WebIDBTaskType task_type,
399 WebIDBCallbacks* callbacks) {
400 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
401 IndexedDBHostMsg_DatabaseOpenCursor_Params params;
402 init_params(&params, callbacks);
403 params.ipc_database_id = ipc_database_id;
404 params.transaction_id = transaction_id;
405 params.object_store_id = object_store_id;
406 params.index_id = index_id;
407 params.key_range = key_range;
408 params.direction = direction;
409 params.key_only = key_only;
410 params.task_type = task_type;
411 Send(new IndexedDBHostMsg_DatabaseOpenCursor(params));
413 DCHECK(cursor_transaction_ids_.find(params.ipc_callbacks_id) ==
414 cursor_transaction_ids_.end());
415 cursor_transaction_ids_[params.ipc_callbacks_id] = transaction_id;
418 void IndexedDBDispatcher::RequestIDBDatabaseCount(
419 int32 ipc_database_id,
420 int64 transaction_id,
421 int64 object_store_id,
422 int64 index_id,
423 const IndexedDBKeyRange& key_range,
424 WebIDBCallbacks* callbacks) {
425 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
426 IndexedDBHostMsg_DatabaseCount_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 Send(new IndexedDBHostMsg_DatabaseCount(params));
436 void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
437 int32 ipc_database_id,
438 int64 transaction_id,
439 int64 object_store_id,
440 const IndexedDBKeyRange& key_range,
441 WebIDBCallbacks* callbacks) {
442 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
443 IndexedDBHostMsg_DatabaseDeleteRange_Params params;
444 init_params(&params, callbacks);
445 params.ipc_database_id = ipc_database_id;
446 params.transaction_id = transaction_id;
447 params.object_store_id = object_store_id;
448 params.key_range = key_range;
449 Send(new IndexedDBHostMsg_DatabaseDeleteRange(params));
452 void IndexedDBDispatcher::RequestIDBDatabaseClear(
453 int32 ipc_database_id,
454 int64 transaction_id,
455 int64 object_store_id,
456 WebIDBCallbacks* callbacks_ptr) {
457 ResetCursorPrefetchCaches(transaction_id, kAllCursors);
458 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
459 int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
460 Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
461 ipc_callbacks_id,
462 ipc_database_id,
463 transaction_id,
464 object_store_id));
467 void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
468 cursors_.erase(ipc_cursor_id);
471 void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) {
472 DCHECK_EQ(databases_.count(ipc_database_id), 1u);
473 databases_.erase(ipc_database_id);
476 void IndexedDBDispatcher::OnSuccessIDBDatabase(
477 int32 ipc_thread_id,
478 int32 ipc_callbacks_id,
479 int32 ipc_database_callbacks_id,
480 int32 ipc_object_id,
481 const IndexedDBDatabaseMetadata& idb_metadata) {
482 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
483 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
484 if (!callbacks)
485 return;
486 WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
487 // If an upgrade was performed, count will be non-zero.
488 WebIDBDatabase* database = NULL;
490 // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
491 // May already be deleted and removed from the table, but do not recreate..
492 if (ipc_object_id != kNoDatabase) {
493 DCHECK(!databases_.count(ipc_object_id));
494 database = databases_[ipc_object_id] = new WebIDBDatabaseImpl(
495 ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get());
498 callbacks->onSuccess(database, metadata);
499 pending_callbacks_.Remove(ipc_callbacks_id);
502 void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
503 int32 ipc_callbacks_id,
504 const IndexedDBKey& key) {
505 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
506 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
507 if (!callbacks)
508 return;
509 callbacks->onSuccess(WebIDBKeyBuilder::Build(key));
510 pending_callbacks_.Remove(ipc_callbacks_id);
513 void IndexedDBDispatcher::OnSuccessStringList(
514 int32 ipc_thread_id,
515 int32 ipc_callbacks_id,
516 const std::vector<base::string16>& value) {
517 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
518 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
519 if (!callbacks)
520 return;
521 callbacks->onSuccess(WebVector<WebString>(value));
522 pending_callbacks_.Remove(ipc_callbacks_id);
525 static void PrepareWebValueAndBlobInfo(
526 const IndexedDBMsg_Value& value,
527 WebData* web_value,
528 blink::WebVector<WebBlobInfo>* web_blob_info) {
529 if (value.bits.empty())
530 return;
532 web_value->assign(&*value.bits.begin(), value.bits.size());
533 blink::WebVector<WebBlobInfo> local_blob_info(value.blob_or_file_info.size());
534 for (size_t i = 0; i < value.blob_or_file_info.size(); ++i) {
535 const IndexedDBMsg_BlobOrFileInfo& info = value.blob_or_file_info[i];
536 if (info.is_file) {
537 local_blob_info[i] = WebBlobInfo(WebString::fromUTF8(info.uuid.c_str()),
538 info.file_path,
539 info.file_name,
540 info.mime_type,
541 info.last_modified,
542 info.size);
543 } else {
544 local_blob_info[i] = WebBlobInfo(
545 WebString::fromUTF8(info.uuid.c_str()), info.mime_type, info.size);
548 web_blob_info->swap(local_blob_info);
551 void IndexedDBDispatcher::OnSuccessValue(
552 const IndexedDBMsg_CallbacksSuccessValue_Params& params) {
553 DCHECK_EQ(params.ipc_thread_id, CurrentWorkerId());
554 WebIDBCallbacks* callbacks =
555 pending_callbacks_.Lookup(params.ipc_callbacks_id);
556 if (!callbacks)
557 return;
558 WebData web_value;
559 WebVector<WebBlobInfo> web_blob_info;
560 PrepareWebValueAndBlobInfo(params.value, &web_value, &web_blob_info);
561 if (params.value.primary_key.IsValid()) {
562 callbacks->onSuccess(web_value, web_blob_info,
563 WebIDBKeyBuilder::Build(params.value.primary_key),
564 WebIDBKeyPathBuilder::Build(params.value.key_path));
565 } else {
566 callbacks->onSuccess(web_value, web_blob_info);
567 cursor_transaction_ids_.erase(params.ipc_callbacks_id);
569 pending_callbacks_.Remove(params.ipc_callbacks_id);
572 void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id,
573 int32 ipc_callbacks_id,
574 int64 value) {
575 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
576 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
577 if (!callbacks)
578 return;
579 callbacks->onSuccess(value);
580 pending_callbacks_.Remove(ipc_callbacks_id);
583 void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id,
584 int32 ipc_callbacks_id) {
585 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
586 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
587 if (!callbacks)
588 return;
589 callbacks->onSuccess();
590 pending_callbacks_.Remove(ipc_callbacks_id);
593 void IndexedDBDispatcher::OnSuccessOpenCursor(
594 const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) {
595 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
596 int32 ipc_callbacks_id = p.ipc_callbacks_id;
597 int32 ipc_object_id = p.ipc_cursor_id;
598 const IndexedDBKey& key = p.key;
599 const IndexedDBKey& primary_key = p.primary_key;
600 WebData web_value;
601 WebVector<WebBlobInfo> web_blob_info;
602 PrepareWebValueAndBlobInfo(p.value, &web_value, &web_blob_info);
604 DCHECK(cursor_transaction_ids_.find(ipc_callbacks_id) !=
605 cursor_transaction_ids_.end());
606 int64 transaction_id = cursor_transaction_ids_[ipc_callbacks_id];
607 cursor_transaction_ids_.erase(ipc_callbacks_id);
609 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
610 if (!callbacks)
611 return;
613 WebIDBCursorImpl* cursor = new WebIDBCursorImpl(
614 ipc_object_id, transaction_id, thread_safe_sender_.get());
615 cursors_[ipc_object_id] = cursor;
616 callbacks->onSuccess(cursor,
617 WebIDBKeyBuilder::Build(key),
618 WebIDBKeyBuilder::Build(primary_key),
619 web_value,
620 web_blob_info);
622 pending_callbacks_.Remove(ipc_callbacks_id);
625 void IndexedDBDispatcher::OnSuccessCursorContinue(
626 const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) {
627 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
628 int32 ipc_callbacks_id = p.ipc_callbacks_id;
629 int32 ipc_cursor_id = p.ipc_cursor_id;
630 const IndexedDBKey& key = p.key;
631 const IndexedDBKey& primary_key = p.primary_key;
633 if (cursors_.find(ipc_cursor_id) == cursors_.end())
634 return;
636 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
637 if (!callbacks)
638 return;
640 WebData web_value;
641 WebVector<WebBlobInfo> web_blob_info;
642 PrepareWebValueAndBlobInfo(p.value, &web_value, &web_blob_info);
643 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
644 WebIDBKeyBuilder::Build(primary_key),
645 web_value,
646 web_blob_info);
648 pending_callbacks_.Remove(ipc_callbacks_id);
651 void IndexedDBDispatcher::OnSuccessCursorPrefetch(
652 const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) {
653 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
654 int32 ipc_callbacks_id = p.ipc_callbacks_id;
655 int32 ipc_cursor_id = p.ipc_cursor_id;
656 const std::vector<IndexedDBKey>& keys = p.keys;
657 const std::vector<IndexedDBKey>& primary_keys = p.primary_keys;
658 std::vector<WebData> values(p.values.size());
659 std::vector<WebVector<WebBlobInfo>> blob_infos(p.values.size());
660 for (size_t i = 0; i < p.values.size(); ++i)
661 PrepareWebValueAndBlobInfo(p.values[i], &values[i], &blob_infos[i]);
662 std::map<int32, WebIDBCursorImpl*>::const_iterator cur_iter =
663 cursors_.find(ipc_cursor_id);
664 if (cur_iter == cursors_.end())
665 return;
667 cur_iter->second->SetPrefetchData(keys, primary_keys, values, blob_infos);
669 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
670 DCHECK(callbacks);
671 cur_iter->second->CachedContinue(callbacks);
672 pending_callbacks_.Remove(ipc_callbacks_id);
675 void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id,
676 int32 ipc_callbacks_id,
677 int64 existing_version) {
678 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
679 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
680 DCHECK(callbacks);
681 callbacks->onBlocked(existing_version);
684 void IndexedDBDispatcher::OnUpgradeNeeded(
685 const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
686 DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
687 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id);
688 DCHECK(callbacks);
689 WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
690 DCHECK(!databases_.count(p.ipc_database_id));
691 databases_[p.ipc_database_id] =
692 new WebIDBDatabaseImpl(p.ipc_database_id,
693 p.ipc_database_callbacks_id,
694 thread_safe_sender_.get());
695 callbacks->onUpgradeNeeded(
696 p.old_version,
697 databases_[p.ipc_database_id],
698 metadata,
699 static_cast<blink::WebIDBDataLoss>(p.data_loss),
700 WebString::fromUTF8(p.data_loss_message));
703 void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
704 int32 ipc_callbacks_id,
705 int code,
706 const base::string16& message) {
707 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
708 WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
709 if (!callbacks)
710 return;
711 if (message.empty())
712 callbacks->onError(WebIDBDatabaseError(code));
713 else
714 callbacks->onError(WebIDBDatabaseError(code, message));
715 pending_callbacks_.Remove(ipc_callbacks_id);
716 cursor_transaction_ids_.erase(ipc_callbacks_id);
719 void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
720 int32 ipc_database_callbacks_id,
721 int64 transaction_id,
722 int code,
723 const base::string16& message) {
724 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
725 WebIDBDatabaseCallbacks* callbacks =
726 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
727 if (!callbacks)
728 return;
729 if (message.empty())
730 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code));
731 else
732 callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message));
735 void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id,
736 int32 ipc_database_callbacks_id,
737 int64 transaction_id) {
738 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
739 WebIDBDatabaseCallbacks* callbacks =
740 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
741 if (!callbacks)
742 return;
743 callbacks->onComplete(transaction_id);
746 void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id,
747 int32 ipc_database_callbacks_id) {
748 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
749 WebIDBDatabaseCallbacks* callbacks =
750 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
751 if (!callbacks)
752 return;
753 callbacks->onForcedClose();
756 void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
757 int32 ipc_database_callbacks_id,
758 int64 old_version,
759 int64 new_version) {
760 DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
761 WebIDBDatabaseCallbacks* callbacks =
762 pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
763 // callbacks would be NULL if a versionchange event is received after close
764 // has been called.
765 if (!callbacks)
766 return;
767 callbacks->onVersionChange(old_version, new_version);
770 void IndexedDBDispatcher::ResetCursorPrefetchCaches(
771 int64 transaction_id,
772 int32 ipc_exception_cursor_id) {
773 typedef std::map<int32, WebIDBCursorImpl*>::iterator Iterator;
774 for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
775 if (i->first == ipc_exception_cursor_id ||
776 i->second->transaction_id() != transaction_id)
777 continue;
778 i->second->ResetPrefetchCache();
782 } // namespace content