Index: content/child/child_thread.cc |
diff --git a/content/child/child_thread.cc b/content/child/child_thread.cc |
index 3ecdb584d8e5b3af784ac98a45eeb9aa531daab0..e549023114e643d1bac601c074058e2042fa2f0b 100644 |
--- a/content/child/child_thread.cc |
+++ b/content/child/child_thread.cc |
@@ -13,6 +13,7 @@ |
#include "base/basictypes.h" |
#include "base/command_line.h" |
#include "base/debug/leak_annotations.h" |
+#include "base/id_map.h" |
#include "base/lazy_instance.h" |
#include "base/logging.h" |
#include "base/message_loop/message_loop.h" |
@@ -39,6 +40,7 @@ |
#include "content/child/thread_safe_sender.h" |
#include "content/child/websocket_dispatcher.h" |
#include "content/common/child_process_messages.h" |
+#include "content/common/message_port_messages.h" |
#include "content/public/common/content_switches.h" |
#include "ipc/ipc_logging.h" |
#include "ipc/ipc_switches.h" |
@@ -193,6 +195,62 @@ void QuitMainThreadMessageLoop() { |
} // namespace |
+MessagePortBypassFilter::MessagePortBypassFilter( |
+ base::SingleThreadTaskRunner* ipc_task_runner) |
+ : ipc_task_runner_(ipc_task_runner), |
+ child_thread_loop_(base::MessageLoopProxy::current()) {} |
+ |
+MessagePortBypassFilter::~MessagePortBypassFilter() {} |
+ |
+bool MessagePortBypassFilter::OnMessageReceived(const IPC::Message& message) { |
+ DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
+ IPC::Listener* listener = routes_.Lookup(message.routing_id()); |
+ if (!listener) |
+ return false; |
+ if (message.type() != MessagePortMsg_Message::ID) |
+ return false; |
+ return listener->OnMessageReceived(message); |
+} |
+ |
+bool MessagePortBypassFilter::GetSupportedMessageClasses( |
+ std::vector<uint32>* supported_message_classes) const { |
+ supported_message_classes->push_back(MessagePortMsgStart); |
+ return true; |
+} |
+ |
+void MessagePortBypassFilter::AddRoute(int32 routing_id, |
+ IPC::Listener* listener) { |
+ DCHECK(child_thread_loop_->BelongsToCurrentThread()); |
+ ipc_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind( |
+ &MessagePortBypassFilter::AddRouteOnIO, this, routing_id, listener)); |
+} |
+ |
+void MessagePortBypassFilter::AddRouteOnIO(int32 routing_id, |
+ IPC::Listener* listener) { |
+ DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
+ routes_.AddWithID(listener, routing_id); |
+} |
+ |
+void MessagePortBypassFilter::RemoveRoute(int32 routing_id, |
+ const base::Closure& callback) { |
+ DCHECK(child_thread_loop_->BelongsToCurrentThread()); |
+ ipc_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&MessagePortBypassFilter::RemoveRouteOnIO, |
+ this, |
+ routing_id, |
+ callback)); |
+} |
+ |
+void MessagePortBypassFilter::RemoveRouteOnIO(int32 routing_id, |
+ const base::Closure& callback) { |
+ DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
+ routes_.Remove(routing_id); |
+ child_thread_loop_->PostTask(FROM_HERE, callback); |
+} |
+ |
ChildThread::ChildThreadMessageRouter::ChildThreadMessageRouter( |
IPC::Sender* sender) |
: sender_(sender) {} |
@@ -263,6 +321,8 @@ void ChildThread::Init() { |
new QuotaMessageFilter(thread_safe_sender_.get()); |
quota_dispatcher_.reset(new QuotaDispatcher(thread_safe_sender_.get(), |
quota_message_filter_.get())); |
+ message_port_bypass_filter_ = new MessagePortBypassFilter( |
+ ChildProcess::current()->io_message_loop_proxy()); |
channel_->AddFilter(histogram_message_filter_.get()); |
channel_->AddFilter(sync_message_filter_.get()); |
@@ -271,6 +331,7 @@ void ChildThread::Init() { |
channel_->AddFilter(resource_message_filter_.get()); |
channel_->AddFilter(quota_message_filter_->GetFilter()); |
channel_->AddFilter(service_worker_message_filter_->GetFilter()); |
+ channel_->AddFilter(message_port_bypass_filter_.get()); |
// In single process mode we may already have a power monitor |
if (!base::PowerMonitor::Get()) { |