OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/browser/frame_host/render_frame_host_impl.h" | 5 #include "content/browser/frame_host/render_frame_host_impl.h" |
6 | 6 |
7 #include "base/macros.h" | 7 #include "base/macros.h" |
8 #include "content/browser/web_contents/web_contents_impl.h" | 8 #include "content/browser/web_contents/web_contents_impl.h" |
9 #include "content/common/frame_messages.h" | 9 #include "content/common/frame_messages.h" |
10 #include "content/public/browser/javascript_dialog_manager.h" | 10 #include "content/public/browser/javascript_dialog_manager.h" |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 TestJavaScriptDialogManager dialog_manager; | 240 TestJavaScriptDialogManager dialog_manager; |
241 wc->SetDelegate(&dialog_manager); | 241 wc->SetDelegate(&dialog_manager); |
242 | 242 |
243 EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); | 243 EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); |
244 // Make an iframe with a beforeunload handler. | 244 // Make an iframe with a beforeunload handler. |
245 std::string script = | 245 std::string script = |
246 "var iframe = document.createElement('iframe');" | 246 "var iframe = document.createElement('iframe');" |
247 "document.body.appendChild(iframe);" | 247 "document.body.appendChild(iframe);" |
248 "iframe.contentWindow.onbeforeunload=function(e){return 'x'};"; | 248 "iframe.contentWindow.onbeforeunload=function(e){return 'x'};"; |
249 EXPECT_TRUE(content::ExecuteScript(wc, script)); | 249 EXPECT_TRUE(content::ExecuteScript(wc, script)); |
250 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | 250 EXPECT_TRUE(WaitForLoadStop(wc)); |
| 251 // JavaScript onbeforeunload dialogs require a user gesture. |
| 252 for (auto* frame : wc->GetAllFrames()) |
| 253 frame->ExecuteJavaScriptWithUserGestureForTests(base::string16()); |
251 | 254 |
252 // Force a process switch by going to a privileged page. The beforeunload | 255 // Force a process switch by going to a privileged page. The beforeunload |
253 // timer will be started on the top-level frame but will be paused while the | 256 // timer will be started on the top-level frame but will be paused while the |
254 // beforeunload dialog is shown by the subframe. | 257 // beforeunload dialog is shown by the subframe. |
255 GURL web_ui_page(std::string(kChromeUIScheme) + "://" + | 258 GURL web_ui_page(std::string(kChromeUIScheme) + "://" + |
256 std::string(kChromeUIGpuHost)); | 259 std::string(kChromeUIGpuHost)); |
257 shell()->LoadURL(web_ui_page); | 260 shell()->LoadURL(web_ui_page); |
258 dialog_manager.Wait(); | 261 dialog_manager.Wait(); |
259 | 262 |
260 RenderFrameHostImpl* main_frame = | 263 RenderFrameHostImpl* main_frame = |
(...skipping 12 matching lines...) Expand all Loading... |
273 // There will be no beforeunload ACK, so if the beforeunload ACK timer isn't | 276 // There will be no beforeunload ACK, so if the beforeunload ACK timer isn't |
274 // functioning then the navigation will hang forever and this test will time | 277 // functioning then the navigation will hang forever and this test will time |
275 // out. If this waiting for the load stop works, this test won't time out. | 278 // out. If this waiting for the load stop works, this test won't time out. |
276 EXPECT_TRUE(WaitForLoadStop(wc)); | 279 EXPECT_TRUE(WaitForLoadStop(wc)); |
277 EXPECT_EQ(web_ui_page, wc->GetLastCommittedURL()); | 280 EXPECT_EQ(web_ui_page, wc->GetLastCommittedURL()); |
278 | 281 |
279 wc->SetDelegate(nullptr); | 282 wc->SetDelegate(nullptr); |
280 wc->SetJavaScriptDialogManagerForTesting(nullptr); | 283 wc->SetJavaScriptDialogManagerForTesting(nullptr); |
281 } | 284 } |
282 | 285 |
| 286 // Tests that a gesture is required in a frame before it can request a |
| 287 // beforeunload dialog. |
| 288 IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, |
| 289 BeforeUnloadDialogRequiresGesture) { |
| 290 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 291 TestJavaScriptDialogManager dialog_manager; |
| 292 wc->SetDelegate(&dialog_manager); |
| 293 |
| 294 EXPECT_TRUE(NavigateToURL( |
| 295 shell(), GetTestUrl("render_frame_host", "beforeunload.html"))); |
| 296 // Disable the hang monitor, otherwise there will be a race between the |
| 297 // beforeunload dialog and the beforeunload hang timer. |
| 298 wc->GetMainFrame()->DisableBeforeUnloadHangMonitorForTesting(); |
| 299 |
| 300 // Reload. There should be no beforeunload dialog because there was no gesture |
| 301 // on the page. If there was, this WaitForLoadStop call will hang. |
| 302 wc->GetController().Reload(ReloadType::NORMAL, false); |
| 303 EXPECT_TRUE(WaitForLoadStop(wc)); |
| 304 |
| 305 // Give the page a user gesture and try reloading again. This time there |
| 306 // should be a dialog. If there is no dialog, the call to Wait will hang. |
| 307 wc->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests( |
| 308 base::string16()); |
| 309 wc->GetController().Reload(ReloadType::NORMAL, false); |
| 310 dialog_manager.Wait(); |
| 311 |
| 312 // Answer the dialog. |
| 313 dialog_manager.callback().Run(true, base::string16()); |
| 314 EXPECT_TRUE(WaitForLoadStop(wc)); |
| 315 |
| 316 // The reload should have cleared the user gesture bit, so upon leaving again |
| 317 // there should be no beforeunload dialog. |
| 318 shell()->LoadURL(GURL("about:blank")); |
| 319 EXPECT_TRUE(WaitForLoadStop(wc)); |
| 320 |
| 321 wc->SetDelegate(nullptr); |
| 322 wc->SetJavaScriptDialogManagerForTesting(nullptr); |
| 323 } |
| 324 |
283 } // namespace content | 325 } // namespace content |
OLD | NEW |