Chromium Code Reviews| 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..87013ab037769d85ac44e09c5db6e24df4e62578 |
| --- /dev/null |
| +++ b/content/renderer/indexed_db_message_filter.cc |
| @@ -0,0 +1,175 @@ |
| +// 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/renderer/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" |
| + |
| +IndexedDBMessageFilter::IndexedDBMessageFilter() : |
| + main_thread_loop_proxy_(base::MessageLoopProxy::current()) { |
| + // This is called on the main thread. |
| +} |
| + |
| +IndexedDBMessageFilter::~IndexedDBMessageFilter() { |
| + // This seems to never be called. |
| +} |
| + |
| +WorkerTaskRunner* worker_task_runner() { |
| + return ChildThread::current()->worker_task_runner(); |
| +} |
| + |
| +void IndexedDBMessageFilter::onLoopRegistered() { |
| +} |
| + |
| +void IndexedDBMessageFilter::onLoopUnregistered() { |
| + if (idb_dispatcher_tls_.Get()) |
| + delete idb_dispatcher_tls_.Get(); |
| +} |
| + |
| +int IndexedDBMessageFilter::current() { |
| + return ChildThread::current()->worker_task_runner()->CurrentWorkerId(); |
| +} |
| + |
| +int IndexedDBMessageFilter::current_worker_id() { |
| + return ChildThread::current()->worker_task_runner()->CurrentWorkerId(); |
| +} |
| + |
| +int ExtractThreadID(int callback_id) { |
| + return (callback_id & 0xFF000000) >> 24; |
| +} |
| + |
| +int IndexedDBMessageFilter::InjectThreadID(int response_id) { |
| + int32 thread_id = current(); |
| + DCHECK(thread_id <= 0xFF); |
|
michaeln
2011/12/01 21:42:05
(stashing this value in the high nibble :)
it loo
dgrogan
2011/12/01 22:49:00
High byte, but yeah.
michaeln
2011/12/02 00:15:03
Seems like it'd be fairly mechanical and limited t
|
| + DCHECK(response_id <= 0x00FFFFFF); |
| + return response_id | (thread_id << 24); |
| +} |
| + |
| +int IndexedDBMessageFilter::GetUniqueID() { |
| + base::AutoLock locker(id_lock_); |
| + int id = ++unique_id_; |
|
michaeln
2011/12/01 21:42:05
take a look at AtomicSequenceNumber
dgrogan
2011/12/01 22:49:00
Ah nice, thanks for the pointer.
|
| + return InjectThreadID(id); |
| +} |
| + |
| +int ExtractCallbackID(const IPC::Message& msg) { |
| + return IPC::MessageIterator(msg).NextInt(); |
| +} |
| + |
| +bool IndexedDBMessageFilter::OnMessageReceived(const IPC::Message& msg) { |
| + if (IPC_MESSAGE_CLASS(msg) != IndexedDBMsgStart) |
| + return false; |
| + int callback_id = ExtractCallbackID(msg); |
| +// Forward to worker task runner |
| + switch(msg.type()) { |
| + case IndexedDBMsg_TransactionCallbacksAbort::ID: |
| + case IndexedDBMsg_TransactionCallbacksComplete::ID: |
| + ForwardToThread(msg, callback_id, transaction_id_to_run_loop_); |
| + break; |
| + case IndexedDBMsg_DatabaseCallbacksVersionChange::ID: |
| + ForwardToThread(msg, callback_id, database_id_to_run_loop_); |
| + break; |
| + default: |
| + ForwardToThread(msg, ExtractThreadID(callback_id)); |
| + } |
| + return true; |
| +} |
| + |
| +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); |
| +} |
| + |
| +class MsgForwarderTask : public WebKit::WebWorkerRunLoop::Task { |
| + public: |
| + MsgForwarderTask(const IPC::Message& msg, IndexedDBMessageFilter* filter) : |
| + msg_(msg), |
| + filter_(filter) { |
| + } |
| + virtual ~MsgForwarderTask() { } |
| + virtual void Run() { |
| + IndexedDBDispatcher* dispatcher = filter_->thread_specific_idb_dispatcher(); |
| + dispatcher->OnMessageReceived(msg_); |
| + } |
| + private: |
| + const IPC::Message msg_; |
| + IndexedDBMessageFilter* filter_; |
| +}; |
| + |
| +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::ForwardToThread(const IPC::Message& msg, int32 id, |
| + const IDToRunLoopMap& map) { |
| + base::AutoLock map_locker(map_lock_); |
| + IDToRunLoopMap::const_iterator iter = map.find(id); |
| + if (iter == map.end()) { |
| + ForwardToMainThread(msg); |
| + return; |
| + } |
| + ForwardToThread(msg, iter->second); |
| +} |
| + |
| +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::RemoveForType(int32 id, WebKit::WebIDBCallbacks*) { |
| +} |
| + |
| +void IndexedDBMessageFilter::RemoveForType( |
| + int32 id, |
| + WebKit::WebIDBDatabaseCallbacks*) { |
| + RemoveFromMap(id, &database_id_to_run_loop_); |
| +} |
| + |
| +void IndexedDBMessageFilter::RemoveForType( |
| + int32 id, |
| + WebKit::WebIDBTransactionCallbacks*) { |
| + RemoveFromMap(id, &transaction_id_to_run_loop_); |
| +} |
| + |
| +void IndexedDBMessageFilter::RemoveFromMap(int32 id, IDToRunLoopMap* map) { |
| + // We don't store ids that are associated with the main thread. |
| + if (!current()) |
| + return; |
| + base::AutoLock map_locker(map_lock_); |
| + int num_erased = map->erase(id); |
| + DCHECK_EQ(num_erased, 1); |
| +} |
| + |
| +void IndexedDBMessageFilter::NotifyAddWithIDForType( |
| + int32 id, WebKit::WebIDBTransactionCallbacks* callbacks) { |
| + if (current()) { |
| + base::AutoLock map_locker(map_lock_); |
| + transaction_id_to_run_loop_[id] = current(); |
| + } |
| +} |
| + |
| +void IndexedDBMessageFilter::NotifyAddWithIDForType(int32 id, |
| + WebKit::WebIDBDatabaseCallbacks* callbacks) { |
| + if (current()) { |
| + base::AutoLock map_locker(map_lock_); |
| + database_id_to_run_loop_[id] = current(); |
| + } |
| +} |