Index: content/browser/renderer_host/render_process_host_impl.cc |
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc |
index 2ee3b3341f4d37f1a88e6a93bdab2075dc9e28e0..7b9b549357de20b2639ae467eec24f26d7ca7eaf 100644 |
--- a/content/browser/renderer_host/render_process_host_impl.cc |
+++ b/content/browser/renderer_host/render_process_host_impl.cc |
@@ -164,6 +164,7 @@ |
#include "ipc/attachment_broker_privileged.h" |
#include "ipc/ipc_channel.h" |
#include "ipc/ipc_logging.h" |
+#include "ipc/ipc_sender.h" |
#include "ipc/ipc_switches.h" |
#include "ipc/mojo/ipc_channel_mojo.h" |
#include "media/base/media_switches.h" |
@@ -447,6 +448,53 @@ std::string UintVectorToString(const std::vector<unsigned>& vector) { |
} // namespace |
+// SafeSenderProxy owns two IPC::Sender implementations which proxy to the |
+// RPH's own ChannelProxy. One enables immediate sends while the other enables |
+// IO-thread sends. These are both implemented via RPHI's SendImpl which safely |
+// avoids dereferencing the underlying ChannelProxy if it's been reset (e.g. |
+// after process death.) |
+class RenderProcessHostImpl::SafeSenderProxy { |
+ public: |
+ // |process| must outlive this object. |
+ explicit SafeSenderProxy(RenderProcessHostImpl* process) |
+ : process_(process), |
+ immediate_sender_(this, true /* send_now */), |
+ io_thread_sender_(this, false /* send_now */) {} |
+ ~SafeSenderProxy() {} |
+ |
+ IPC::Sender* immediate_sender() { return &immediate_sender_; } |
+ IPC::Sender* io_thread_sender() { return &io_thread_sender_; } |
+ |
+ bool SendImpl(IPC::Message* message, bool send_now) { |
+ return process_->SendImpl(message, send_now); |
+ } |
+ |
+ private: |
+ class SenderProxy : public IPC::Sender { |
+ public: |
+ SenderProxy(SafeSenderProxy* safe_proxy, bool send_now) |
+ : safe_proxy_(safe_proxy), send_now_(send_now) {} |
+ ~SenderProxy() override {} |
+ |
+ // IPC::Sender: |
+ bool Send(IPC::Message* message) override { |
+ return safe_proxy_->SendImpl(message, send_now_); |
+ } |
+ |
+ private: |
+ SafeSenderProxy* const safe_proxy_; |
+ const bool send_now_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SenderProxy); |
+ }; |
+ |
+ RenderProcessHostImpl* process_; |
+ SenderProxy immediate_sender_; |
+ SenderProxy io_thread_sender_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SafeSenderProxy); |
+}; |
+ |
RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
base::MessageLoop* g_in_process_thread; |
@@ -536,6 +584,7 @@ RenderProcessHostImpl::RenderProcessHostImpl( |
is_self_deleted_(false), |
#endif |
pending_views_(0), |
+ safe_sender_(new SafeSenderProxy(this)), |
mojo_application_host_(new MojoApplicationHost), |
visible_widgets_(0), |
is_process_backgrounded_(false), |
@@ -1015,6 +1064,45 @@ void RenderProcessHostImpl::CreateMessageFilters() { |
} |
} |
+bool RenderProcessHostImpl::SendImpl(IPC::Message* msg, bool send_now) { |
+ TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::SendImpl"); |
+#if !defined(OS_ANDROID) |
+ DCHECK(!msg->is_sync()); |
+#endif |
+ |
+ if (!channel_) { |
+#if defined(OS_ANDROID) |
+ if (msg->is_sync()) { |
+ delete msg; |
+ return false; |
+ } |
+#endif |
+ if (!is_initialized_) { |
+ queued_messages_.push(msg); |
+ return true; |
+ } else { |
+ delete msg; |
+ return false; |
+ } |
+ } |
+ |
+ if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { |
+#if defined(OS_ANDROID) |
+ if (msg->is_sync()) { |
+ delete msg; |
+ return false; |
+ } |
+#endif |
+ queued_messages_.push(msg); |
+ return true; |
+ } |
+ |
+ if (send_now) |
+ return channel_->SendNow(msg); |
+ |
+ return channel_->SendOnIPCThread(msg); |
+} |
+ |
void RenderProcessHostImpl::RegisterMojoServices() { |
#if !defined(OS_ANDROID) |
mojo_application_host_->service_registry()->AddService( |
@@ -1642,39 +1730,7 @@ bool RenderProcessHostImpl::FastShutdownIfPossible() { |
} |
bool RenderProcessHostImpl::Send(IPC::Message* msg) { |
- TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send"); |
-#if !defined(OS_ANDROID) |
- DCHECK(!msg->is_sync()); |
-#endif |
- |
- if (!channel_) { |
-#if defined(OS_ANDROID) |
- if (msg->is_sync()) { |
- delete msg; |
- return false; |
- } |
-#endif |
- if (!is_initialized_) { |
- queued_messages_.push(msg); |
- return true; |
- } else { |
- delete msg; |
- return false; |
- } |
- } |
- |
- if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { |
-#if defined(OS_ANDROID) |
- if (msg->is_sync()) { |
- delete msg; |
- return false; |
- } |
-#endif |
- queued_messages_.push(msg); |
- return true; |
- } |
- |
- return channel_->Send(msg); |
+ return SendImpl(msg, false /* send_now */); |
} |
bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
@@ -2030,6 +2086,14 @@ IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { |
return channel_.get(); |
} |
+IPC::Sender* RenderProcessHostImpl::GetImmediateSender() { |
+ return safe_sender_->immediate_sender(); |
+} |
+ |
+IPC::Sender* RenderProcessHostImpl::GetIOThreadSender() { |
+ return safe_sender_->io_thread_sender(); |
+} |
+ |
void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { |
channel_->AddFilter(filter->GetFilter()); |
} |