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