Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Unified Diff: content/browser/frame_host/render_frame_host_manager_browsertest.cc

Issue 1151393003: Add ref-count on RenderViewHost for each new RenderFrameProxyHost. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix up formatting. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/frame_host/render_frame_host_manager_browsertest.cc
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index 9de16f8e9c0be905594f840c66bddc33e4f83358..d0b696fda5576c77a2dc9f34f6f75251287032ac 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -35,6 +35,7 @@
#include "content/shell/browser/shell.h"
#include "net/base/net_util.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
using base::ASCIIToUTF16;
@@ -87,6 +88,13 @@ class RenderFrameHostManagerTest : public ContentBrowserTest {
foo_host_port_.set_host(foo_com_);
}
+ void StartEmbeddedServer() {
+ // Support multiple sites on the embedded test server.
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ SetupCrossSiteRedirector(embedded_test_server());
+ }
+
// Returns a URL on foo.com with the given path.
GURL GetCrossSiteURL(const std::string& path) {
GURL cross_site_url(test_server()->GetURL(path));
@@ -1722,4 +1730,82 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
}
+// This class implements waiting for RenderFrameHost destruction. It relies on
+// the fact that RenderFrameDeleted event is fired when RenderFrameHost is
+// destroyed.
+// Note: RenderFrameDeleted is also fired when the process associated with the
+// RenderFrameHost crashes, so this cannot be used in cases where process dying
+// is expected.
ncarter (slow) 2015/05/22 23:03:14 If you wanted to make it robust against this, you
ncarter (slow) 2015/05/22 23:04:29 [but I'm okay with just leaving the "Note:" too]
+class RenderFrameHostDestructionObserver : public WebContentsObserver {
ncarter (slow) 2015/05/22 23:03:14 This is pretty similar to https://code.google.com/
nasko 2015/05/22 23:46:49 Might be a good idea. I'd leave that for another C
ncarter (slow) 2015/05/23 00:33:36 Acknowledged.
+ public:
+ explicit RenderFrameHostDestructionObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ message_loop_runner_(new MessageLoopRunner),
+ started_watching(false) {}
+ ~RenderFrameHostDestructionObserver() override {}
+
+ void Observe(RenderFrameHost* rfh) {
ncarter (slow) 2015/05/22 23:03:14 This shadows WebContentsObserver::Observe, which i
nasko 2015/05/22 23:46:50 Done.
+ started_watching = true;
+ watched_render_frame_hosts_.insert(rfh);
+ }
+
+ void Wait() {
+ if (!started_watching)
+ return;
+ message_loop_runner_->Run();
+ }
+
+ private:
+ // WebContentsObserver implementation:
+ void RenderFrameDeleted(RenderFrameHost* rfh) override {
ncarter (slow) 2015/05/22 23:03:14 This should be public.
nasko 2015/05/22 23:46:49 Why should it? I've changed it, but curious about
ncarter (slow) 2015/05/23 00:33:36 1. When you have something that's private in a der
nasko 2015/05/23 02:23:08 Acknowledged.
+ watched_render_frame_hosts_.erase(rfh);
+ if (!started_watching)
+ return;
+ if (watched_render_frame_hosts_.size() == 0) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, message_loop_runner_->QuitClosure());
+ }
+ }
+
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ bool started_watching;
+ std::set<RenderFrameHost*> watched_render_frame_hosts_;
+};
+
+// Ensures that no RenderFrameHost/RenderViewHost objects are leaked when
+// doing a simple cross-process navigation.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ CleanupOnCrossProcessNavigation) {
+ StartEmbeddedServer();
+
+ // Do an initial navigation and capture objects we expect to be cleaned up
+ // on cross-process navigation.
+ GURL start_url = embedded_test_server()->GetURL("/title1.html");
+ NavigateToURL(shell(), start_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ int32 orig_site_instance_id =
+ root->current_frame_host()->GetSiteInstance()->GetId();
+ int initial_process_id =
+ root->current_frame_host()->GetSiteInstance()->GetProcess()->GetID();
+ int initial_rfh_id = root->current_frame_host()->GetRoutingID();
+ int initial_rvh_id =
+ root->current_frame_host()->render_view_host()->GetRoutingID();
+
+ // Navigate cross-process and ensure that cleanup is performed as expected.
+ GURL cross_site_url =
+ embedded_test_server()->GetURL("foo.com", "/title2.html");
+ RenderFrameHostDestructionObserver rfh_observer(shell()->web_contents());
+ rfh_observer.Observe(root->current_frame_host());
+ NavigateToURL(shell(), cross_site_url);
+ rfh_observer.Wait();
+
+ EXPECT_NE(orig_site_instance_id,
+ root->current_frame_host()->GetSiteInstance()->GetId());
+ EXPECT_FALSE(RenderFrameHost::FromID(initial_process_id, initial_rfh_id));
+ EXPECT_FALSE(RenderViewHost::FromID(initial_process_id, initial_rvh_id));
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698