Commit 00150c1b authored by sammc's avatar sammc Committed by Commit bot

Detect and clean up discarded mojo connections to deleted RenderFrames.

Currently, if a RenderFrame is deleted before the
ExchangeServiceProviders message is received in the renderer, the
message pipe handles contained in that message are retained, waiting for
a RenderFrame that has already been deleted. This changes
RenderThreadImpl::PendingRenderFrameConnect to detect when the browser
closes its handles to those message pipes and clean itself up when that
occurs.

BUG=457722

Review URL: https://codereview.chromium.org/1005893002

Cr-Commit-Position: refs/heads/master@{#320690}
parent cf78c4d6
...@@ -874,9 +874,10 @@ void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) { ...@@ -874,9 +874,10 @@ void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) {
scoped_refptr<PendingRenderFrameConnect> connection(it->second); scoped_refptr<PendingRenderFrameConnect> connection(it->second);
mojo::InterfaceRequest<mojo::ServiceProvider> services( mojo::InterfaceRequest<mojo::ServiceProvider> services(
connection->services.Pass()); connection->services().Pass());
mojo::ServiceProviderPtr exposed_services( mojo::ServiceProviderPtr exposed_services(
connection->exposed_services.Pass()); connection->exposed_services().Pass());
exposed_services.set_error_handler(nullptr);
pending_render_frame_connects_.erase(it); pending_render_frame_connects_.erase(it);
frame->BindServiceRegistry(services.Pass(), exposed_services.Pass()); frame->BindServiceRegistry(services.Pass(), exposed_services.Pass());
...@@ -911,8 +912,7 @@ void RenderThreadImpl::RegisterPendingRenderFrameConnect( ...@@ -911,8 +912,7 @@ void RenderThreadImpl::RegisterPendingRenderFrameConnect(
pending_render_frame_connects_.insert(std::make_pair( pending_render_frame_connects_.insert(std::make_pair(
routing_id, routing_id,
make_scoped_refptr(new PendingRenderFrameConnect( make_scoped_refptr(new PendingRenderFrameConnect(
services.Pass(), routing_id, services.Pass(), exposed_services.Pass()))));
exposed_services.Pass()))));
CHECK(result.second) << "Inserting a duplicate item."; CHECK(result.second) << "Inserting a duplicate item.";
} }
...@@ -1790,13 +1790,26 @@ void RenderThreadImpl::WidgetRestored() { ...@@ -1790,13 +1790,26 @@ void RenderThreadImpl::WidgetRestored() {
} }
RenderThreadImpl::PendingRenderFrameConnect::PendingRenderFrameConnect( RenderThreadImpl::PendingRenderFrameConnect::PendingRenderFrameConnect(
int routing_id,
mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::InterfaceRequest<mojo::ServiceProvider> services,
mojo::ServiceProviderPtr exposed_services) mojo::ServiceProviderPtr exposed_services)
: services(services.Pass()), : routing_id_(routing_id),
exposed_services(exposed_services.Pass()) { services_(services.Pass()),
exposed_services_(exposed_services.Pass()) {
// The RenderFrame may be deleted before the ExchangeServiceProviders message
// is received. In that case, the RenderFrameHost should close the connection,
// which is detected by setting an error handler on |exposed_services_|.
exposed_services_.set_error_handler(this);
} }
RenderThreadImpl::PendingRenderFrameConnect::~PendingRenderFrameConnect() { RenderThreadImpl::PendingRenderFrameConnect::~PendingRenderFrameConnect() {
} }
void RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError() {
size_t erased =
RenderThreadImpl::current()->pending_render_frame_connects_.erase(
routing_id_);
DCHECK_EQ(1u, erased);
}
} // namespace content } // namespace content
...@@ -606,19 +606,31 @@ class CONTENT_EXPORT RenderThreadImpl ...@@ -606,19 +606,31 @@ class CONTENT_EXPORT RenderThreadImpl
bool is_elastic_overscroll_enabled_; bool is_elastic_overscroll_enabled_;
unsigned use_image_texture_target_; unsigned use_image_texture_target_;
struct PendingRenderFrameConnect class PendingRenderFrameConnect
: public base::RefCounted<PendingRenderFrameConnect> { : public base::RefCounted<PendingRenderFrameConnect>,
public mojo::ErrorHandler {
public:
PendingRenderFrameConnect( PendingRenderFrameConnect(
int routing_id,
mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::InterfaceRequest<mojo::ServiceProvider> services,
mojo::ServiceProviderPtr exposed_services); mojo::ServiceProviderPtr exposed_services);
mojo::InterfaceRequest<mojo::ServiceProvider> services; mojo::InterfaceRequest<mojo::ServiceProvider>& services() {
mojo::ServiceProviderPtr exposed_services; return services_;
}
mojo::ServiceProviderPtr& exposed_services() { return exposed_services_; }
private: private:
friend class base::RefCounted<PendingRenderFrameConnect>; friend class base::RefCounted<PendingRenderFrameConnect>;
~PendingRenderFrameConnect(); ~PendingRenderFrameConnect() override;
void OnConnectionError() override;
int routing_id_;
mojo::InterfaceRequest<mojo::ServiceProvider> services_;
mojo::ServiceProviderPtr exposed_services_;
}; };
typedef std::map<int, scoped_refptr<PendingRenderFrameConnect>> typedef std::map<int, scoped_refptr<PendingRenderFrameConnect>>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment