summaryrefslogtreecommitdiffstats
path: root/content/child/indexed_db/indexed_db_dispatcher.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/child/indexed_db/indexed_db_dispatcher.cc')
-rw-r--r--content/child/indexed_db/indexed_db_dispatcher.cc713
1 files changed, 713 insertions, 0 deletions
diff --git a/content/child/indexed_db/indexed_db_dispatcher.cc b/content/child/indexed_db/indexed_db_dispatcher.cc
new file mode 100644
index 0000000..24c403d
--- /dev/null
+++ b/content/child/indexed_db/indexed_db_dispatcher.cc
@@ -0,0 +1,713 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/indexed_db/indexed_db_dispatcher.h"
+
+#include "base/format_macros.h"
+#include "base/lazy_instance.h"
+#include "base/stringprintf.h"
+#include "base/threading/thread_local.h"
+#include "content/child/indexed_db/proxy_webidbcursor_impl.h"
+#include "content/child/indexed_db/proxy_webidbdatabase_impl.h"
+#include "content/common/child_thread.h"
+#include "content/common/indexed_db/indexed_db_messages.h"
+#include "ipc/ipc_channel.h"
+#include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
+#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
+#include "third_party/WebKit/public/platform/WebIDBKeyRange.h"
+
+using WebKit::WebData;
+using WebKit::WebIDBCallbacks;
+using WebKit::WebIDBDatabase;
+using WebKit::WebIDBDatabaseCallbacks;
+using WebKit::WebIDBDatabaseError;
+using WebKit::WebIDBKey;
+using WebKit::WebIDBKeyRange;
+using WebKit::WebIDBMetadata;
+using WebKit::WebString;
+using WebKit::WebVector;
+using base::ThreadLocalPointer;
+using webkit_glue::WorkerTaskRunner;
+
+namespace content {
+static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher> >::Leaky
+ g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
+
+namespace {
+
+IndexedDBDispatcher* const kHasBeenDeleted =
+ reinterpret_cast<IndexedDBDispatcher*>(0x1);
+
+int32 CurrentWorkerId() {
+ return WorkerTaskRunner::Instance()->CurrentWorkerId();
+}
+} // unnamed namespace
+
+const size_t kMaxIDBValueSizeInBytes = 64 * 1024 * 1024;
+
+IndexedDBDispatcher::IndexedDBDispatcher() {
+ g_idb_dispatcher_tls.Pointer()->Set(this);
+}
+
+IndexedDBDispatcher::~IndexedDBDispatcher() {
+ // Clear any pending callbacks - which may result in dispatch requests -
+ // before marking the dispatcher as deleted.
+ pending_callbacks_.Clear();
+ pending_database_callbacks_.Clear();
+
+ DCHECK(pending_callbacks_.IsEmpty());
+ DCHECK(pending_database_callbacks_.IsEmpty());
+
+ g_idb_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
+}
+
+IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance() {
+ if (g_idb_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
+ NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
+ g_idb_dispatcher_tls.Pointer()->Set(NULL);
+ }
+ if (g_idb_dispatcher_tls.Pointer()->Get())
+ return g_idb_dispatcher_tls.Pointer()->Get();
+
+ IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher;
+ if (WorkerTaskRunner::Instance()->CurrentWorkerId())
+ webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
+ return dispatcher;
+}
+
+void IndexedDBDispatcher::OnWorkerRunLoopStopped() { delete this; }
+
+WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
+ const IndexedDBDatabaseMetadata& idb_metadata) {
+ WebIDBMetadata web_metadata;
+ web_metadata.id = idb_metadata.id;
+ web_metadata.name = idb_metadata.name;
+ web_metadata.version = idb_metadata.version;
+ web_metadata.intVersion = idb_metadata.int_version;
+ web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
+ web_metadata.objectStores =
+ WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
+
+ for (size_t i = 0; i < idb_metadata.object_stores.size(); ++i) {
+ const IndexedDBObjectStoreMetadata& idb_store_metadata =
+ idb_metadata.object_stores[i];
+ WebIDBMetadata::ObjectStore& web_store_metadata =
+ web_metadata.objectStores[i];
+
+ web_store_metadata.id = idb_store_metadata.id;
+ web_store_metadata.name = idb_store_metadata.name;
+ web_store_metadata.keyPath = idb_store_metadata.keyPath;
+ web_store_metadata.autoIncrement = idb_store_metadata.autoIncrement;
+ web_store_metadata.maxIndexId = idb_store_metadata.max_index_id;
+ web_store_metadata.indexes =
+ WebVector<WebIDBMetadata::Index>(idb_store_metadata.indexes.size());
+
+ for (size_t j = 0; j < idb_store_metadata.indexes.size(); ++j) {
+ const IndexedDBIndexMetadata& idb_index_metadata =
+ idb_store_metadata.indexes[j];
+ WebIDBMetadata::Index& web_index_metadata = web_store_metadata.indexes[j];
+
+ web_index_metadata.id = idb_index_metadata.id;
+ web_index_metadata.name = idb_index_metadata.name;
+ web_index_metadata.keyPath = idb_index_metadata.keyPath;
+ web_index_metadata.unique = idb_index_metadata.unique;
+ web_index_metadata.multiEntry = idb_index_metadata.multiEntry;
+ }
+ }
+
+ return web_metadata;
+}
+
+void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcher, msg)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBCursor,
+ OnSuccessOpenCursor)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorAdvance,
+ OnSuccessCursorContinue)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue,
+ OnSuccessCursorContinue)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch,
+ OnSuccessCursorPrefetch)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
+ OnSuccessIDBDatabase)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey,
+ OnSuccessIndexedDBKey)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessStringList,
+ OnSuccessStringList)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValue, OnSuccessValue)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessValueWithKey,
+ OnSuccessValueWithKey)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessInteger, OnSuccessInteger)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessUndefined,
+ OnSuccessUndefined)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksError, OnError)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksIntBlocked, OnIntBlocked)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
+ OnForcedClose)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
+ OnIntVersionChange)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ // If a message gets here, IndexedDBMessageFilter already determined that it
+ // is an IndexedDB message.
+ DCHECK(handled) << "Didn't handle a message defined at line "
+ << IPC_MESSAGE_ID_LINE(msg.type());
+}
+
+bool IndexedDBDispatcher::Send(IPC::Message* msg) {
+ if (!ChildThread::current()) {
+ // Unexpected - this may be happening during shutdown.
+ NOTREACHED();
+ return false;
+ }
+ if (CurrentWorkerId()) {
+ scoped_refptr<IPC::SyncMessageFilter> filter(
+ ChildThread::current()->sync_message_filter());
+ return filter->Send(msg);
+ }
+ return ChildThread::current()->Send(msg);
+}
+
+void IndexedDBDispatcher::RequestIDBCursorAdvance(
+ unsigned long count,
+ WebIDBCallbacks* callbacks_ptr,
+ int32 ipc_cursor_id) {
+ // Reset all cursor prefetch caches except for this cursor.
+ ResetCursorPrefetchCaches(ipc_cursor_id);
+
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+
+ int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ Send(new IndexedDBHostMsg_CursorAdvance(
+ ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, count));
+}
+
+void IndexedDBDispatcher::RequestIDBCursorContinue(
+ const IndexedDBKey& key,
+ WebIDBCallbacks* callbacks_ptr,
+ int32 ipc_cursor_id) {
+ // Reset all cursor prefetch caches except for this cursor.
+ ResetCursorPrefetchCaches(ipc_cursor_id);
+
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+
+ int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ Send(new IndexedDBHostMsg_CursorContinue(
+ ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key));
+}
+
+void IndexedDBDispatcher::RequestIDBCursorPrefetch(
+ int n,
+ WebIDBCallbacks* callbacks_ptr,
+ int32 ipc_cursor_id) {
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+
+ int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ Send(new IndexedDBHostMsg_CursorPrefetch(
+ ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, n));
+}
+
+void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
+ int unused_prefetches,
+ int32 ipc_cursor_id) {
+ Send(new IndexedDBHostMsg_CursorPrefetchReset(
+ ipc_cursor_id, used_prefetches, unused_prefetches));
+}
+
+void IndexedDBDispatcher::RequestIDBFactoryOpen(
+ const string16& name,
+ int64 version,
+ int64 transaction_id,
+ WebIDBCallbacks* callbacks_ptr,
+ WebIDBDatabaseCallbacks* database_callbacks_ptr,
+ const string16& database_identifier) {
+ ResetCursorPrefetchCaches();
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
+ database_callbacks_ptr);
+
+ IndexedDBHostMsg_FactoryOpen_Params params;
+ params.ipc_thread_id = CurrentWorkerId();
+ params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ params.ipc_database_callbacks_id =
+ pending_database_callbacks_.Add(database_callbacks.release());
+ params.database_identifier = database_identifier;
+ params.name = name;
+ params.transaction_id = transaction_id;
+ params.version = version;
+ Send(new IndexedDBHostMsg_FactoryOpen(params));
+}
+
+void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
+ WebIDBCallbacks* callbacks_ptr,
+ const string16& database_identifier) {
+ ResetCursorPrefetchCaches();
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+
+ IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
+ params.ipc_thread_id = CurrentWorkerId();
+ params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ params.database_identifier = database_identifier;
+ Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
+}
+
+void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
+ const string16& name,
+ WebIDBCallbacks* callbacks_ptr,
+ const string16& database_identifier) {
+ ResetCursorPrefetchCaches();
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+
+ IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
+ params.ipc_thread_id = CurrentWorkerId();
+ params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ params.database_identifier = database_identifier;
+ params.name = name;
+ Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseClose(
+ int32 ipc_database_id,
+ int32 ipc_database_callbacks_id) {
+ ResetCursorPrefetchCaches();
+ Send(new IndexedDBHostMsg_DatabaseClose(ipc_database_id));
+ // There won't be pending database callbacks if the transaction was aborted in
+ // the initial upgradeneeded event handler.
+ if (pending_database_callbacks_.Lookup(ipc_database_callbacks_id))
+ pending_database_callbacks_.Remove(ipc_database_callbacks_id);
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ WebIDBDatabaseCallbacks* database_callbacks_ptr,
+ WebKit::WebVector<long long> object_store_ids,
+ unsigned short mode) {
+ scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
+ database_callbacks_ptr);
+ IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
+ params.ipc_thread_id = CurrentWorkerId();
+ params.ipc_database_id = ipc_database_id;
+ params.transaction_id = transaction_id;
+ params.ipc_database_callbacks_id =
+ pending_database_callbacks_.Add(database_callbacks.release());
+ params.object_store_ids
+ .assign(object_store_ids.data(),
+ object_store_ids.data() + object_store_ids.size());
+ params.mode = mode;
+
+ Send(new IndexedDBHostMsg_DatabaseCreateTransaction(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseGet(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKeyRange& key_range,
+ bool key_only,
+ WebIDBCallbacks* callbacks) {
+ ResetCursorPrefetchCaches();
+ IndexedDBHostMsg_DatabaseGet_Params params;
+ init_params(params, callbacks);
+ params.ipc_database_id = ipc_database_id;
+ params.transaction_id = transaction_id;
+ params.object_store_id = object_store_id;
+ params.index_id = index_id;
+ params.key_range = key_range;
+ params.key_only = key_only;
+ Send(new IndexedDBHostMsg_DatabaseGet(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabasePut(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ int64 object_store_id,
+ const WebData& value,
+ const IndexedDBKey& key,
+ WebIDBDatabase::PutMode put_mode,
+ WebIDBCallbacks* callbacks,
+ const WebVector<long long>& index_ids,
+ const WebVector<WebKit::WebVector<WebIDBKey> >& index_keys) {
+
+ if (value.size() > kMaxIDBValueSizeInBytes) {
+ callbacks->onError(WebIDBDatabaseError(
+ WebKit::WebIDBDatabaseExceptionUnknownError,
+ WebString::fromUTF8(base::StringPrintf(
+ "The serialized value is too large"
+ " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
+ value.size(),
+ kMaxIDBValueSizeInBytes).c_str())));
+ return;
+ }
+
+ ResetCursorPrefetchCaches();
+ IndexedDBHostMsg_DatabasePut_Params params;
+ init_params(params, callbacks);
+ params.ipc_database_id = ipc_database_id;
+ params.transaction_id = transaction_id;
+ params.object_store_id = object_store_id;
+
+ params.value.assign(value.data(), value.data() + value.size());
+ params.key = key;
+ params.put_mode = put_mode;
+
+ COMPILE_ASSERT(sizeof(params.index_ids[0]) == sizeof(index_ids[0]),
+ Cant_copy);
+ params.index_ids
+ .assign(index_ids.data(), index_ids.data() + index_ids.size());
+
+ params.index_keys.resize(index_keys.size());
+ for (size_t i = 0; i < index_keys.size(); ++i) {
+ params.index_keys[i].resize(index_keys[i].size());
+ for (size_t j = 0; j < index_keys[i].size(); ++j) {
+ params.index_keys[i][j] = IndexedDBKey(index_keys[i][j]);
+ }
+ }
+ Send(new IndexedDBHostMsg_DatabasePut(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKeyRange& key_range,
+ unsigned short direction,
+ bool key_only,
+ WebKit::WebIDBDatabase::TaskType task_type,
+ WebIDBCallbacks* callbacks) {
+ ResetCursorPrefetchCaches();
+ IndexedDBHostMsg_DatabaseOpenCursor_Params params;
+ init_params(params, callbacks);
+ params.ipc_database_id = ipc_database_id;
+ params.transaction_id = transaction_id;
+ params.object_store_id = object_store_id;
+ params.index_id = index_id;
+ params.key_range = IndexedDBKeyRange(key_range);
+ params.direction = direction;
+ params.key_only = key_only;
+ params.task_type = task_type;
+ Send(new IndexedDBHostMsg_DatabaseOpenCursor(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseCount(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKeyRange& key_range,
+ WebKit::WebIDBCallbacks* callbacks) {
+ ResetCursorPrefetchCaches();
+ IndexedDBHostMsg_DatabaseCount_Params params;
+ init_params(params, callbacks);
+ params.ipc_database_id = ipc_database_id;
+ params.transaction_id = transaction_id;
+ params.object_store_id = object_store_id;
+ params.index_id = index_id;
+ params.key_range = IndexedDBKeyRange(key_range);
+ Send(new IndexedDBHostMsg_DatabaseCount(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseDeleteRange(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ int64 object_store_id,
+ const IndexedDBKeyRange& key_range,
+ WebKit::WebIDBCallbacks* callbacks) {
+ ResetCursorPrefetchCaches();
+ IndexedDBHostMsg_DatabaseDeleteRange_Params params;
+ init_params(params, callbacks);
+ params.ipc_database_id = ipc_database_id;
+ params.transaction_id = transaction_id;
+ params.object_store_id = object_store_id;
+ params.key_range = key_range;
+ Send(new IndexedDBHostMsg_DatabaseDeleteRange(params));
+}
+
+void IndexedDBDispatcher::RequestIDBDatabaseClear(
+ int32 ipc_database_id,
+ int64 transaction_id,
+ int64 object_store_id,
+ WebKit::WebIDBCallbacks* callbacks_ptr) {
+ scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
+ Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
+ ipc_callbacks_id,
+ ipc_database_id,
+ transaction_id,
+ object_store_id));
+}
+
+void IndexedDBDispatcher::CursorDestroyed(int32 ipc_cursor_id) {
+ cursors_.erase(ipc_cursor_id);
+}
+
+void IndexedDBDispatcher::DatabaseDestroyed(int32 ipc_database_id) {
+ DCHECK_EQ(databases_.count(ipc_database_id), 1u);
+ databases_.erase(ipc_database_id);
+}
+
+void IndexedDBDispatcher::OnSuccessIDBDatabase(
+ int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ int32 ipc_database_callbacks_id,
+ int32 ipc_object_id,
+ const IndexedDBDatabaseMetadata& idb_metadata) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
+ // If an upgrade was performed, count will be non-zero.
+ if (!databases_.count(ipc_object_id))
+ databases_[ipc_object_id] = new RendererWebIDBDatabaseImpl(
+ ipc_object_id, ipc_database_callbacks_id);
+ DCHECK_EQ(databases_.count(ipc_object_id), 1u);
+ callbacks->onSuccess(databases_[ipc_object_id], metadata);
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ const IndexedDBKey& key) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onSuccess(WebIDBKey(key));
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessStringList(
+ int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ const std::vector<string16>& value) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onSuccess(WebVector<WebString>(value));
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessValue(int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ const std::vector<char>& value) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ WebData web_value;
+ if (value.size())
+ web_value.assign(&value.front(), value.size());
+ callbacks->onSuccess(web_value);
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessValueWithKey(
+ int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ const std::vector<char>& value,
+ const IndexedDBKey& primary_key,
+ const IndexedDBKeyPath& key_path) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ WebData web_value;
+ if (value.size())
+ web_value.assign(&value.front(), value.size());
+ callbacks->onSuccess(web_value, primary_key, key_path);
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessInteger(int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ int64 value) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onSuccess(value);
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessUndefined(int32 ipc_thread_id,
+ int32 ipc_callbacks_id) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onSuccess();
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessOpenCursor(
+ const IndexedDBMsg_CallbacksSuccessIDBCursor_Params& p) {
+ DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
+ int32 ipc_callbacks_id = p.ipc_callbacks_id;
+ int32 ipc_object_id = p.ipc_cursor_id;
+ const IndexedDBKey& key = p.key;
+ const IndexedDBKey& primary_key = p.primary_key;
+ WebData web_value;
+ if (p.value.size())
+ web_value.assign(&p.value.front(), p.value.size());
+
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+
+ RendererWebIDBCursorImpl* cursor =
+ new RendererWebIDBCursorImpl(ipc_object_id);
+ cursors_[ipc_object_id] = cursor;
+ callbacks->onSuccess(cursor, key, primary_key, web_value);
+
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessCursorContinue(
+ const IndexedDBMsg_CallbacksSuccessCursorContinue_Params& p) {
+ DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
+ int32 ipc_callbacks_id = p.ipc_callbacks_id;
+ int32 ipc_cursor_id = p.ipc_cursor_id;
+ const IndexedDBKey& key = p.key;
+ const IndexedDBKey& primary_key = p.primary_key;
+ const std::vector<char>& value = p.value;
+
+ RendererWebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
+ DCHECK(cursor);
+
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+
+ WebData web_value;
+ if (value.size())
+ web_value.assign(&value.front(), value.size());
+ callbacks->onSuccess(key, primary_key, web_value);
+
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnSuccessCursorPrefetch(
+ const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p) {
+ DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
+ int32 ipc_callbacks_id = p.ipc_callbacks_id;
+ int32 ipc_cursor_id = p.ipc_cursor_id;
+ const std::vector<IndexedDBKey>& keys = p.keys;
+ const std::vector<IndexedDBKey>& primary_keys = p.primary_keys;
+ std::vector<WebData> values(p.values.size());
+ for (size_t i = 0; i < p.values.size(); ++i) {
+ if (p.values[i].size())
+ values[i].assign(&p.values[i].front(), p.values[i].size());
+ }
+ RendererWebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
+ DCHECK(cursor);
+ cursor->SetPrefetchData(keys, primary_keys, values);
+
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ DCHECK(callbacks);
+ cursor->CachedContinue(callbacks);
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnIntBlocked(int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ int64 existing_version) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ DCHECK(callbacks);
+ callbacks->onBlocked(existing_version);
+}
+
+void IndexedDBDispatcher::OnUpgradeNeeded(
+ const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
+ DCHECK_EQ(p.ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(p.ipc_callbacks_id);
+ DCHECK(callbacks);
+ WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
+ DCHECK(!databases_.count(p.ipc_database_id));
+ databases_[p.ipc_database_id] = new RendererWebIDBDatabaseImpl(
+ p.ipc_database_id, p.ipc_database_callbacks_id);
+ callbacks->onUpgradeNeeded(
+ p.old_version, databases_[p.ipc_database_id], metadata);
+}
+
+void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
+ int32 ipc_callbacks_id,
+ int code,
+ const string16& message) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onError(WebIDBDatabaseError(code, message));
+ pending_callbacks_.Remove(ipc_callbacks_id);
+}
+
+void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
+ int32 ipc_database_callbacks_id,
+ int64 transaction_id,
+ int code,
+ const string16& message) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBDatabaseCallbacks* callbacks =
+ pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onAbort(transaction_id, WebIDBDatabaseError(code, message));
+}
+
+void IndexedDBDispatcher::OnComplete(int32 ipc_thread_id,
+ int32 ipc_database_callbacks_id,
+ int64 transaction_id) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBDatabaseCallbacks* callbacks =
+ pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onComplete(transaction_id);
+}
+
+void IndexedDBDispatcher::OnForcedClose(int32 ipc_thread_id,
+ int32 ipc_database_callbacks_id) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBDatabaseCallbacks* callbacks =
+ pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
+ if (!callbacks)
+ return;
+ callbacks->onForcedClose();
+}
+
+void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
+ int32 ipc_database_callbacks_id,
+ int64 old_version,
+ int64 new_version) {
+ DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
+ WebIDBDatabaseCallbacks* callbacks =
+ pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
+ // callbacks would be NULL if a versionchange event is received after close
+ // has been called.
+ if (!callbacks)
+ return;
+ callbacks->onVersionChange(old_version, new_version);
+}
+
+void IndexedDBDispatcher::ResetCursorPrefetchCaches(
+ int32 ipc_exception_cursor_id) {
+ typedef std::map<int32, RendererWebIDBCursorImpl*>::iterator Iterator;
+ for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
+ if (i->first == ipc_exception_cursor_id)
+ continue;
+ i->second->ResetPrefetchCache();
+ }
+}
+
+} // namespace content