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

Side by Side Diff: content/browser/site_per_process_browsertest.cc

Issue 156303004: With --site-per-process, avoid a crash when a subframe process goes away. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Disable on GTK, add test. Created 6 years, 10 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 #include "base/strings/stringprintf.h" 6 #include "base/strings/stringprintf.h"
7 #include "base/strings/utf_string_conversions.h" 7 #include "base/strings/utf_string_conversions.h"
8 #include "content/browser/frame_host/frame_tree.h" 8 #include "content/browser/frame_host/frame_tree.h"
9 #include "content/browser/renderer_host/render_view_host_impl.h" 9 #include "content/browser/renderer_host/render_view_host_impl.h"
10 #include "content/browser/web_contents/web_contents_impl.h" 10 #include "content/browser/web_contents/web_contents_impl.h"
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 seen_ = true; 154 seen_ = true;
155 if (!running_) 155 if (!running_)
156 return; 156 return;
157 157
158 message_loop_runner_->Quit(); 158 message_loop_runner_->Quit();
159 running_ = false; 159 running_ = false;
160 } 160 }
161 161
162 class SitePerProcessBrowserTest : public ContentBrowserTest { 162 class SitePerProcessBrowserTest : public ContentBrowserTest {
163 protected: 163 protected:
164 // Start at a data URL so each extra navigation creates a navigation entry.
165 // (The first navigation will silently be classified as AUTO_SUBFRAME.)
166 // TODO(creis): This won't be necessary when we can wait for LOAD_STOP.
167 void StartFrameAtDataURL() {
168 std::string data_url_script =
169 "var iframes = document.getElementById('test');iframes.src="
170 "'data:text/html,dataurl';";
171 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script));
172 }
173
164 bool NavigateIframeToURL(Shell* window, 174 bool NavigateIframeToURL(Shell* window,
165 const GURL& url, 175 const GURL& url,
166 std::string iframe_id) { 176 std::string iframe_id) {
177 // TODO(creis): This should wait for LOAD_STOP, but cross-site subframe
178 // navigations generate extra DidStartLoading and DidStopLoading messages.
179 // Until we replace swappedout:// with frame proxies, we need to listen for
180 // something else. For now, we trigger NEW_SUBFRAME navigations and listen
181 // for commit.
167 std::string script = base::StringPrintf( 182 std::string script = base::StringPrintf(
168 "var iframes = document.getElementById('%s');iframes.src='%s';", 183 "setTimeout(\""
184 "var iframes = document.getElementById('%s');iframes.src='%s';"
185 "\",0)",
169 iframe_id.c_str(), url.spec().c_str()); 186 iframe_id.c_str(), url.spec().c_str());
170 WindowedNotificationObserver load_observer( 187 WindowedNotificationObserver load_observer(
171 NOTIFICATION_LOAD_STOP, 188 NOTIFICATION_NAV_ENTRY_COMMITTED,
172 Source<NavigationController>( 189 Source<NavigationController>(
173 &shell()->web_contents()->GetController())); 190 &window->web_contents()->GetController()));
174 bool result = ExecuteScript(window->web_contents(), script); 191 bool result = ExecuteScript(window->web_contents(), script);
175 load_observer.Wait(); 192 load_observer.Wait();
176 return result; 193 return result;
177 } 194 }
178 195
179 void NavigateToURLContentInitiated(Shell* window, 196 void NavigateToURLContentInitiated(Shell* window,
180 const GURL& url, 197 const GURL& url,
181 bool should_replace_current_entry) { 198 bool should_replace_current_entry) {
182 std::string script; 199 std::string script;
183 if (should_replace_current_entry) 200 if (should_replace_current_entry)
184 script = base::StringPrintf("location.replace('%s')", url.spec().c_str()); 201 script = base::StringPrintf("location.replace('%s')", url.spec().c_str());
185 else 202 else
186 script = base::StringPrintf("location.href = '%s'", url.spec().c_str()); 203 script = base::StringPrintf("location.href = '%s'", url.spec().c_str());
187 TestNavigationObserver load_observer(shell()->web_contents(), 1); 204 TestNavigationObserver load_observer(shell()->web_contents(), 1);
188 bool result = ExecuteScript(window->web_contents(), script); 205 bool result = ExecuteScript(window->web_contents(), script);
189 EXPECT_TRUE(result); 206 EXPECT_TRUE(result);
190 load_observer.Wait(); 207 load_observer.Wait();
191 } 208 }
192 209
193 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 210 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
194 command_line->AppendSwitch(switches::kSitePerProcess); 211 command_line->AppendSwitch(switches::kSitePerProcess);
195 } 212 }
196 }; 213 };
197 214
198 // Ensure that we can complete a cross-process subframe navigation. 215 // Ensure that we can complete a cross-process subframe navigation.
199 // TODO(nasko): Disable this test for now, since enabling swapping out of 216 // This is disabled on GTK due to a NOTREACHED in
200 // RenderFrameHosts causes this to break. Fix this test once 217 // RenderWidgetHostViewChildFrame::AllocBackingStore. GTK support will be
nasko 2014/02/11 04:49:16 This reminded me that I worked around this in my b
Charlie Reis 2014/02/12 00:27:57 I'll give it a try in SetUpCommandLine.
201 // didFailProvisionalLoad is moved from RenderView to RenderFrame. 218 // removed before we support site-per-process.
202 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrossSiteIframe) { 219 #if defined(TOOLKIT_GTK)
220 #define MAYBE_CrossSiteIframe DISABLED_CrossSiteIframe
221 #else
222 #define MAYBE_CrossSiteIframe CrossSiteIframe
223 #endif
224 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrossSiteIframe) {
203 ASSERT_TRUE(test_server()->Start()); 225 ASSERT_TRUE(test_server()->Start());
204 net::SpawnedTestServer https_server( 226 net::SpawnedTestServer https_server(
205 net::SpawnedTestServer::TYPE_HTTPS, 227 net::SpawnedTestServer::TYPE_HTTPS,
206 net::SpawnedTestServer::kLocalhost, 228 net::SpawnedTestServer::kLocalhost,
207 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); 229 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
208 ASSERT_TRUE(https_server.Start()); 230 ASSERT_TRUE(https_server.Start());
209 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); 231 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
232 NavigateToURL(shell(), main_url);
210 233
211 NavigateToURL(shell(), main_url); 234 StartFrameAtDataURL();
212 235
213 SitePerProcessWebContentsObserver observer(shell()->web_contents()); 236 SitePerProcessWebContentsObserver observer(shell()->web_contents());
214 237
215 // Load same-site page into iframe. 238 // Load same-site page into iframe.
216 GURL http_url(test_server()->GetURL("files/title1.html")); 239 GURL http_url(test_server()->GetURL("files/title1.html"));
217 EXPECT_TRUE(NavigateIframeToURL(shell(), http_url, "test")); 240 EXPECT_TRUE(NavigateIframeToURL(shell(), http_url, "test"));
218 EXPECT_EQ(observer.navigation_url(), http_url); 241 EXPECT_EQ(http_url, observer.navigation_url());
219 EXPECT_TRUE(observer.navigation_succeeded()); 242 EXPECT_TRUE(observer.navigation_succeeded());
220 243
221 // Load cross-site page into iframe. 244 // Load cross-site page into iframe.
222 GURL https_url(https_server.GetURL("files/title1.html")); 245 GURL https_url(https_server.GetURL("files/title1.html"));
223 EXPECT_TRUE(NavigateIframeToURL(shell(), https_url, "test")); 246 EXPECT_TRUE(NavigateIframeToURL(shell(), https_url, "test"));
224 EXPECT_EQ(observer.navigation_url(), https_url); 247 EXPECT_EQ(https_url, observer.navigation_url());
225 EXPECT_TRUE(observer.navigation_succeeded()); 248 EXPECT_TRUE(observer.navigation_succeeded());
226 249
227 // Ensure that we have created a new process for the subframe. 250 // Ensure that we have created a new process for the subframe.
228 FrameTreeNode* root = 251 FrameTreeNode* root =
229 static_cast<WebContentsImpl*>(shell()->web_contents())-> 252 static_cast<WebContentsImpl*>(shell()->web_contents())->
230 GetFrameTree()->root(); 253 GetFrameTree()->root();
231 ASSERT_EQ(1U, root->child_count()); 254 ASSERT_EQ(1U, root->child_count());
232 FrameTreeNode* child = root->child_at(0); 255 FrameTreeNode* child = root->child_at(0);
233 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), 256 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(),
234 child->current_frame_host()->render_view_host()); 257 child->current_frame_host()->render_view_host());
235 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), 258 EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
236 child->current_frame_host()->render_view_host()->GetSiteInstance()); 259 child->current_frame_host()->render_view_host()->GetSiteInstance());
237 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), 260 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(),
238 child->current_frame_host()->GetProcess()); 261 child->current_frame_host()->GetProcess());
239 } 262 }
240 263
264 // Crash a subframe and ensures its children are cleared from the FrameTree.
265 // See http://crbug.com/338508.
266 #if defined(TOOLKIT_GTK)
267 #define MAYBE_CrashSubframe DISABLED_CrashSubframe
268 #else
269 #define MAYBE_CrashSubframe CrashSubframe
270 #endif
271 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrashSubframe) {
272 ASSERT_TRUE(test_server()->Start());
273 net::SpawnedTestServer https_server(
274 net::SpawnedTestServer::TYPE_HTTPS,
275 net::SpawnedTestServer::kLocalhost,
276 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
277 ASSERT_TRUE(https_server.Start());
278 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
279 NavigateToURL(shell(), main_url);
280
281 StartFrameAtDataURL();
282
283 // Load cross-site page into iframe.
284 GURL https_url(https_server.GetURL("files/title1.html"));
285 EXPECT_TRUE(NavigateIframeToURL(shell(), https_url, "test"));
nasko 2014/02/11 04:49:16 This reminds me that it soon might be the time to
Charlie Reis 2014/02/12 00:27:57 That will be great.
286
287 // Check the subframe process.
288 FrameTreeNode* root =
289 static_cast<WebContentsImpl*>(shell()->web_contents())->
290 GetFrameTree()->root();
291 ASSERT_EQ(1U, root->child_count());
292 FrameTreeNode* child = root->child_at(0);
293
294 // Crash the subframe process.
295 RenderProcessHost* root_process =
296 shell()->web_contents()->GetRenderProcessHost();
nasko 2014/02/11 04:49:16 nit: Why not keep it consistent with the next line
Charlie Reis 2014/02/12 00:27:57 Done.
297 RenderProcessHost* child_process = child->current_frame_host()->GetProcess();
298 RenderProcessHostWatcher crash_observer(
299 child_process,
300 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
301 base::KillProcess(child_process->GetHandle(), 0, false);
302 crash_observer.Wait();
303
304 // Ensure that the child frame still exists but has been cleared.
nasko 2014/02/11 04:49:16 nit: How are we testing that it is cleared?
Charlie Reis 2014/02/12 00:27:57 Heh, I started with some lines to check that the U
305 EXPECT_EQ(1U, root->child_count());
306
307 // Now crash the top-level page to clear the child frame.
308 RenderProcessHostWatcher crash_observer2(
nasko 2014/02/11 04:49:16 nit: Why not add local scope to avoid having varia
Charlie Reis 2014/02/12 00:27:57 Done.
309 root_process,
310 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
311 base::KillProcess(root_process->GetHandle(), 0, false);
312 crash_observer2.Wait();
313 EXPECT_EQ(0U, root->child_count());
314 }
315
241 // TODO(nasko): Disable this test until out-of-process iframes is ready and the 316 // TODO(nasko): Disable this test until out-of-process iframes is ready and the
242 // security checks are back in place. 317 // security checks are back in place.
243 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, 318 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
244 DISABLED_CrossSiteIframeRedirectOnce) { 319 DISABLED_CrossSiteIframeRedirectOnce) {
245 ASSERT_TRUE(test_server()->Start()); 320 ASSERT_TRUE(test_server()->Start());
246 net::SpawnedTestServer https_server( 321 net::SpawnedTestServer https_server(
247 net::SpawnedTestServer::TYPE_HTTPS, 322 net::SpawnedTestServer::TYPE_HTTPS,
248 net::SpawnedTestServer::kLocalhost, 323 net::SpawnedTestServer::kLocalhost,
249 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); 324 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
250 ASSERT_TRUE(https_server.Start()); 325 ASSERT_TRUE(https_server.Start());
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 // There should be two history entries. url2b should have replaced url1. url2b 669 // There should be two history entries. url2b should have replaced url1. url2b
595 // should not have replaced url3b. 670 // should not have replaced url3b.
596 EXPECT_TRUE(controller.GetPendingEntry() == NULL); 671 EXPECT_TRUE(controller.GetPendingEntry() == NULL);
597 EXPECT_EQ(2, controller.GetEntryCount()); 672 EXPECT_EQ(2, controller.GetEntryCount());
598 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); 673 EXPECT_EQ(1, controller.GetCurrentEntryIndex());
599 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); 674 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
600 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL()); 675 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL());
601 } 676 }
602 677
603 } // namespace content 678 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698