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 c1f6ea58086569202275a28355b6d9c0927365a4..bb14f3dbe1b7b37af5e3b388a1ed4297388d4b35 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_(process_, true /* send_now */), |
+ io_thread_sender_(process_, false /* send_now */) {} |
+ ~SafeSenderProxy() {} |
+ |
+ IPC::Sender* immediate_sender() { return &immediate_sender_; } |
+ IPC::Sender* io_thread_sender() { return &io_thread_sender_; } |
+ |
+ bool SendImpl(std::unique_ptr<IPC::Message> message, bool send_now) { |
+ return process_->SendImpl(std::move(message), send_now); |
+ } |
piman
2016/05/24 17:24:51
nit: this is not needed any more, I think.
Ken Rockot(use gerrit already)
2016/05/24 18:00:08
Removed
|
+ |
+ private: |
+ class SenderProxy : public IPC::Sender { |
+ public: |
+ SenderProxy(RenderProcessHostImpl* process, bool send_now) |
+ : process_(process), send_now_(send_now) {} |
+ ~SenderProxy() override {} |
+ |
+ // IPC::Sender: |
+ bool Send(IPC::Message* message) override { |
+ return process_->SendImpl(base::WrapUnique(message), send_now_); |
+ } |
+ |
+ private: |
+ RenderProcessHostImpl* const process_; |
+ const bool send_now_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SenderProxy); |
+ }; |
+ |
+ RenderProcessHostImpl* const process_; |
piman
2016/05/24 17:24:51
nit: neither is this.
Ken Rockot(use gerrit already)
2016/05/24 18:00:08
Ditto
|
+ 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), |
@@ -648,10 +697,8 @@ RenderProcessHostImpl::~RenderProcessHostImpl() { |
#endif |
// We may have some unsent messages at this point, but that's OK. |
channel_.reset(); |
- while (!queued_messages_.empty()) { |
- delete queued_messages_.front(); |
+ while (!queued_messages_.empty()) |
queued_messages_.pop(); |
- } |
UnregisterHost(GetID()); |
@@ -1015,6 +1062,41 @@ void RenderProcessHostImpl::CreateMessageFilters() { |
} |
} |
+bool RenderProcessHostImpl::SendImpl(std::unique_ptr<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()) |
+ return false; |
+#endif |
+ if (!is_initialized_) { |
+ queued_messages_.emplace(std::move(msg)); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { |
+#if defined(OS_ANDROID) |
+ if (msg->is_sync()) |
+ return false; |
+#endif |
+ queued_messages_.emplace(std::move(msg)); |
+ return true; |
+ } |
+ |
+ if (send_now) |
+ return channel_->SendNow(std::move(msg)); |
+ |
+ return channel_->SendOnIPCThread(std::move(msg)); |
+} |
+ |
void RenderProcessHostImpl::RegisterMojoServices() { |
#if !defined(OS_ANDROID) |
mojo_application_host_->service_registry()->AddService( |
@@ -1643,39 +1725,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(base::WrapUnique(msg), false /* send_now */); |
} |
bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
@@ -2031,6 +2081,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()); |
} |
@@ -2376,10 +2434,8 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead, |
channel_.get()); |
#endif |
channel_.reset(); |
- while (!queued_messages_.empty()) { |
- delete queued_messages_.front(); |
+ while (!queued_messages_.empty()) |
queued_messages_.pop(); |
- } |
UpdateProcessPriority(); |
DCHECK(!is_process_backgrounded_); |
@@ -2556,7 +2612,7 @@ void RenderProcessHostImpl::OnProcessLaunched() { |
NotificationService::NoDetails()); |
while (!queued_messages_.empty()) { |
- Send(queued_messages_.front()); |
+ Send(queued_messages_.front().release()); |
queued_messages_.pop(); |
} |