| Index: content/browser/frame_host/render_frame_host_impl_browsertest.cc | 
| diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc | 
| index f975aa9981412c1962460d20e0290ca201c6878f..0200d46af4aadc3a7acde981a7c7b4ae20df07b7 100644 | 
| --- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc | 
| +++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc | 
| @@ -247,7 +247,10 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, | 
| "document.body.appendChild(iframe);" | 
| "iframe.contentWindow.onbeforeunload=function(e){return 'x'};"; | 
| EXPECT_TRUE(content::ExecuteScript(wc, script)); | 
| -  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | 
| +  EXPECT_TRUE(WaitForLoadStop(wc)); | 
| +  // JavaScript onbeforeunload dialogs require a user gesture. | 
| +  for (auto* frame : wc->GetAllFrames()) | 
| +    frame->ExecuteJavaScriptWithUserGestureForTests(base::string16()); | 
|  | 
| // Force a process switch by going to a privileged page. The beforeunload | 
| // timer will be started on the top-level frame but will be paused while the | 
| @@ -280,4 +283,43 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, | 
| wc->SetJavaScriptDialogManagerForTesting(nullptr); | 
| } | 
|  | 
| +// Tests that a gesture is required in a frame before it can request a | 
| +// beforeunload dialog. | 
| +IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, | 
| +                       BeforeUnloadDialogRequiresGesture) { | 
| +  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); | 
| +  TestJavaScriptDialogManager dialog_manager; | 
| +  wc->SetDelegate(&dialog_manager); | 
| + | 
| +  EXPECT_TRUE(NavigateToURL( | 
| +      shell(), GetTestUrl("render_frame_host", "beforeunload.html"))); | 
| +  // Disable the hang monitor, otherwise there will be a race between the | 
| +  // beforeunload dialog and the beforeunload hang timer. | 
| +  wc->GetMainFrame()->DisableBeforeUnloadHangMonitorForTesting(); | 
| + | 
| +  // Reload. There should be no beforeunload dialog because there was no gesture | 
| +  // on the page. If there was, this WaitForLoadStop call will hang. | 
| +  wc->GetController().Reload(ReloadType::NORMAL, false); | 
| +  EXPECT_TRUE(WaitForLoadStop(wc)); | 
| + | 
| +  // Give the page a user gesture and try reloading again. This time there | 
| +  // should be a dialog. If there is no dialog, the call to Wait will hang. | 
| +  wc->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests( | 
| +      base::string16()); | 
| +  wc->GetController().Reload(ReloadType::NORMAL, false); | 
| +  dialog_manager.Wait(); | 
| + | 
| +  // Answer the dialog. | 
| +  dialog_manager.callback().Run(true, base::string16()); | 
| +  EXPECT_TRUE(WaitForLoadStop(wc)); | 
| + | 
| +  // The reload should have cleared the user gesture bit, so upon leaving again | 
| +  // there should be no beforeunload dialog. | 
| +  shell()->LoadURL(GURL("about:blank")); | 
| +  EXPECT_TRUE(WaitForLoadStop(wc)); | 
| + | 
| +  wc->SetDelegate(nullptr); | 
| +  wc->SetJavaScriptDialogManagerForTesting(nullptr); | 
| +} | 
| + | 
| }  // namespace content | 
|  |