Index: content/renderer/indexed_db_message_filter.cc |
diff --git a/content/renderer/indexed_db_message_filter.cc b/content/renderer/indexed_db_message_filter.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..20538607cd39e845059c598ac1bd367809fdb93e |
--- /dev/null |
+++ b/content/renderer/indexed_db_message_filter.cc |
@@ -0,0 +1,145 @@ |
+// Copyright (c) 2011 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/common/indexed_db_message_filter.h" |
+ |
+#include "base/bind.h" |
+#include "base/location.h" |
+#include "content/common/indexed_db_messages.h" |
+#include "content/common/worker_task_runner.h" |
+#include "content/renderer/indexed_db_dispatcher.h" |
+#include "content/renderer/render_thread_impl.h" |
+ |
+namespace { |
+ |
+WorkerTaskRunner* worker_task_runner() { |
+ return ChildThread::current()->worker_task_runner(); |
+} |
+ |
+int current_worker_id() { |
+ return ChildThread::current()->worker_task_runner()->CurrentWorkerId(); |
+} |
+ |
+} |
+ |
+class IndexedDBMessageFilter::MsgForwarderTask : |
+ public WebKit::WebWorkerRunLoop::Task { |
+ public: |
+ MsgForwarderTask(const IPC::Message& msg, IndexedDBMessageFilter* filter) : |
+ msg_(msg), |
+ filter_(filter) { |
+ } |
+ virtual ~MsgForwarderTask() { } |
+ virtual void Run() { |
+ filter_->DispatchMessage(msg_); |
+ } |
+ private: |
+ const IPC::Message msg_; |
+ IndexedDBMessageFilter* filter_; |
+}; |
+ |
+IndexedDBMessageFilter::IndexedDBMessageFilter() : |
+ main_thread_loop_proxy_(base::MessageLoopProxy::current()) { |
+ // This is called on the main thread. |
+ // We want our ids to start at 1, 0 is used to indicate the main thread. |
+ DCHECK(!unique_id_.GetNext()); |
+} |
+ |
+IndexedDBMessageFilter::~IndexedDBMessageFilter() { |
+ // This seems to never be called. |
+} |
+ |
+bool IndexedDBMessageFilter::OnMessageReceived(const IPC::Message& msg) { |
+ if (IPC_MESSAGE_CLASS(msg) != IndexedDBMsgStart) |
+ return false; |
+ int callback_id = ExtractCallbackID(msg); |
+ switch(msg.type()) { |
+ case IndexedDBMsg_TransactionCallbacksAbort::ID: |
+ case IndexedDBMsg_TransactionCallbacksComplete::ID: |
+ LookupAndForwardToThread(msg, callback_id, transaction_id_to_run_loop_); |
+ break; |
+ default: |
+ ForwardToThread(msg, ExtractThreadID(callback_id)); |
+ } |
+ return true; |
+} |
+ |
+IndexedDBDispatcher* IndexedDBMessageFilter::thread_specific_idb_dispatcher() { |
+ if (idb_dispatcher_tls_.Get()) |
+ return idb_dispatcher_tls_.Get(); |
+ |
+ IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(this); |
+ idb_dispatcher_tls_.Set(dispatcher); |
+ return dispatcher; |
+} |
+ |
+void IndexedDBMessageFilter::onLoopRegistered() { |
+} |
+ |
+void IndexedDBMessageFilter::onLoopUnregistered() { |
+ if (idb_dispatcher_tls_.Get()) |
+ delete idb_dispatcher_tls_.Get(); |
+} |
+ |
+int IndexedDBMessageFilter::GetUniqueCallbackIDWithThreadID() { |
+ int id = unique_id_.GetNext(); |
+ return InjectThreadID(id, current_worker_id()); |
+} |
+ |
+void IndexedDBMessageFilter::DidRemoveTransactionID(int32 id) { |
+ base::AutoLock map_locker(map_lock_); |
+ int num_erased = transaction_id_to_run_loop_.erase(id); |
+ DCHECK_EQ(num_erased, 1); |
+} |
+ |
+void IndexedDBMessageFilter::DidAddTransactionID(int32 id) { |
+ base::AutoLock map_locker(map_lock_); |
+ transaction_id_to_run_loop_[id] = current_worker_id(); |
+} |
+ |
+void IndexedDBMessageFilter::LookupAndForwardToThread( |
+ const IPC::Message& msg, |
+ int32 callback_id, |
+ const CallbackIDToRunLoopMap& map) { |
+ base::AutoLock map_locker(map_lock_); |
+ CallbackIDToRunLoopMap::const_iterator iter = map.find(callback_id); |
+ |
+ DCHECK (iter != map.end()); |
+ ForwardToThread(msg, iter->second); |
+} |
+ |
+void IndexedDBMessageFilter::ForwardToThread(const IPC::Message& msg, |
+ int thread_id) { |
+ if (!thread_id) { |
+ ForwardToMainThread(msg); |
+ return; |
+ } |
+ MsgForwarderTask* task = new MsgForwarderTask(msg, this); |
+ worker_task_runner()->PostTask(thread_id, task); |
+} |
+ |
+void IndexedDBMessageFilter::ForwardToMainThread(const IPC::Message& msg) { |
+ main_thread_loop_proxy_->PostTask(FROM_HERE, |
+ base::Bind(&IndexedDBMessageFilter::DispatchMessage, this, msg)); |
+} |
+ |
+void IndexedDBMessageFilter::DispatchMessage(const IPC::Message& msg) { |
+ thread_specific_idb_dispatcher()->OnMessageReceived(msg); |
+} |
+ |
+int IndexedDBMessageFilter::ExtractCallbackID(const IPC::Message& msg) { |
+ return IPC::MessageIterator(msg).NextInt(); |
+} |
+ |
+// TODO(dgrogan): Get rid of this bit-twiddling and instead put the entire |
+// thread id in the outgoing and incoming IPCs. |
+int IndexedDBMessageFilter::ExtractThreadID(int callback_id) { |
+ return (callback_id & 0xFF000000) >> 24; |
+} |
+ |
+int IndexedDBMessageFilter::InjectThreadID(int callback_id, int thread_id) { |
+ DCHECK(thread_id <= 0xFF); |
+ DCHECK(callback_id <= 0x00FFFFFF); |
+ return callback_id | (thread_id << 24); |
+} |