| Index: content/browser/site_per_process_browsertest.cc | 
| diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc | 
| index ea4bb0da5c3fc3c61f87442773244420a49bf876..9f6363a2a82fe708ff92079c0c4935832adcf8f5 100644 | 
| --- a/content/browser/site_per_process_browsertest.cc | 
| +++ b/content/browser/site_per_process_browsertest.cc | 
| @@ -7920,4 +7920,68 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 
| EXPECT_TRUE(ExecuteScript(popup_shell->web_contents(), "true")); | 
| } | 
|  | 
| +// Tests that trying to navigate in the unload handler doesn't crash the | 
| +// browser. | 
| +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateInUnloadHandler) { | 
| +  GURL main_url(embedded_test_server()->GetURL( | 
| +      "a.com", "/cross_site_iframe_factory.html?a(b(b))")); | 
| +  NavigateToURL(shell(), main_url); | 
| + | 
| +  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) | 
| +                            ->GetFrameTree() | 
| +                            ->root(); | 
| + | 
| +  EXPECT_EQ( | 
| +      " Site A ------------ proxies for B\n" | 
| +      "   +--Site B ------- proxies for A\n" | 
| +      "        +--Site B -- proxies for A\n" | 
| +      "Where A = http://a.com/\n" | 
| +      "      B = http://b.com/", | 
| +      DepictFrameTree(root)); | 
| + | 
| +  int child_count = 0; | 
| +  EXPECT_TRUE(ExecuteScriptAndExtractInt( | 
| +      root->child_at(0)->current_frame_host(), | 
| +      "window.domAutomationController.send(frames.length);", &child_count)); | 
| +  EXPECT_EQ(1, child_count); | 
| + | 
| +  // Add an unload handler to B's subframe. | 
| +  EXPECT_TRUE( | 
| +      ExecuteScript(root->child_at(0)->child_at(0)->current_frame_host(), | 
| +                    "window.onunload=function(e){\n" | 
| +                    "    window.location = '#navigate';\n" | 
| +                    "};\n")); | 
| + | 
| +  // Navigate B's subframe to a cross-site C. | 
| +  std::string script = | 
| +      std::string("window.document.getElementById('child-0').src = \"") + | 
| +      embedded_test_server() | 
| +          ->GetURL("c.com", "/cross_site_iframe_factory.html") | 
| +          .spec() + | 
| +      "\""; | 
| +  EXPECT_TRUE( | 
| +      ExecuteScript(root->child_at(0)->current_frame_host(), script.c_str())); | 
| + | 
| +  // Wait until B's subframe RenderFrameHost is destroyed. | 
| +  RenderFrameDeletedObserver deleted_observer( | 
| +      root->child_at(0)->child_at(0)->current_frame_host()); | 
| +  deleted_observer.WaitUntilDeleted(); | 
| + | 
| +  // Check that C's subframe is alive and the navigation in the unload handler | 
| +  // was ignored. | 
| +  EXPECT_TRUE(ExecuteScriptAndExtractInt( | 
| +      root->child_at(0)->child_at(0)->current_frame_host(), | 
| +      "window.domAutomationController.send(frames.length);", &child_count)); | 
| +  EXPECT_EQ(0, child_count); | 
| + | 
| +  EXPECT_EQ( | 
| +      " Site A ------------ proxies for B C\n" | 
| +      "   +--Site B ------- proxies for A C\n" | 
| +      "        +--Site C -- proxies for A B\n" | 
| +      "Where A = http://a.com/\n" | 
| +      "      B = http://b.com/\n" | 
| +      "      C = http://c.com/", | 
| +      DepictFrameTree(root)); | 
| +} | 
| + | 
| }  // namespace content | 
|  |