Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/macros.h" | 5 #include "base/macros.h" |
| 6 #include "base/run_loop.h" | 6 #include "base/run_loop.h" |
| 7 #include "base/strings/pattern.h" | 7 #include "base/strings/pattern.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "base/values.h" | 9 #include "base/values.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 932 WaitForAppModalDialog(shell()); | 932 WaitForAppModalDialog(shell()); |
| 933 | 933 |
| 934 // Have the cross-site navigation commit. The main RenderFrameHost should | 934 // Have the cross-site navigation commit. The main RenderFrameHost should |
| 935 // still be loading after that. | 935 // still be loading after that. |
| 936 cross_site_delayer.WaitForNavigationFinished(); | 936 cross_site_delayer.WaitForNavigationFinished(); |
| 937 EXPECT_TRUE(shell()->web_contents()->IsLoading()); | 937 EXPECT_TRUE(shell()->web_contents()->IsLoading()); |
| 938 } | 938 } |
| 939 | 939 |
| 940 namespace { | 940 namespace { |
| 941 | 941 |
| 942 // Test implementation of WebContentsDelegate that handles and automatically | |
| 943 // cancels beforeunload dialogs. This class also listens for | |
| 944 // NavigationStateChanged(INVALIDATE_TYPE_URL) and records the state of | |
| 945 // GetVisibleURL(). | |
| 946 class DialogDismissingWebContentsDelegate : public JavaScriptDialogManager, | |
| 947 public WebContentsDelegate { | |
| 948 public: | |
| 949 DialogDismissingWebContentsDelegate() | |
| 950 : message_loop_runner_(new MessageLoopRunner) {} | |
| 951 ~DialogDismissingWebContentsDelegate() override {} | |
| 952 | |
| 953 void WaitForDialogDismissed() { | |
| 954 message_loop_runner_->Run(); | |
| 955 message_loop_runner_ = new MessageLoopRunner; | |
| 956 } | |
| 957 | |
| 958 // The recent of values of web_contents()->GetVisibleURL(), recorded each time | |
| 959 // this WebContentsDelegate gets an INVALIDATE_TYPE_URL event. | |
| 960 std::vector<GURL> GetAndClearVisibleUrlInvalidations() { | |
| 961 return std::move(visible_url_invalidations_); | |
| 962 } | |
| 963 | |
| 964 // WebContentsDelegate | |
| 965 | |
| 966 JavaScriptDialogManager* GetJavaScriptDialogManager( | |
| 967 WebContents* source) override { | |
| 968 return this; | |
| 969 } | |
| 970 void NavigationStateChanged(WebContents* web_contents, | |
| 971 InvalidateTypes invalidate_types) override { | |
| 972 if (invalidate_types & INVALIDATE_TYPE_URL) { | |
| 973 visible_url_invalidations_.push_back(web_contents->GetVisibleURL()); | |
| 974 } | |
| 975 } | |
| 976 | |
| 977 // JavaScriptDialogManager | |
| 978 | |
| 979 void RunJavaScriptDialog(WebContents* web_contents, | |
| 980 const GURL& origin_url, | |
| 981 JavaScriptDialogType dialog_type, | |
| 982 const base::string16& message_text, | |
| 983 const base::string16& default_prompt_text, | |
| 984 const DialogClosedCallback& callback, | |
| 985 bool* did_suppress_message) override {} | |
| 986 | |
| 987 void RunBeforeUnloadDialog(WebContents* web_contents, | |
| 988 bool is_reload, | |
| 989 const DialogClosedCallback& callback) override { | |
| 990 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 991 base::Bind(callback, false, base::string16())); | |
| 992 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 993 message_loop_runner_->QuitClosure()); | |
| 994 } | |
| 995 | |
| 996 bool HandleJavaScriptDialog(WebContents* web_contents, | |
| 997 bool accept, | |
| 998 const base::string16* prompt_override) override { | |
| 999 return true; | |
| 1000 } | |
| 1001 | |
| 1002 void CancelDialogs(WebContents* web_contents, bool reset_state) override {} | |
| 1003 | |
| 1004 private: | |
| 1005 std::vector<GURL> visible_url_invalidations_; | |
| 1006 | |
| 1007 // The MessageLoopRunner used to spin the message loop. | |
| 1008 scoped_refptr<MessageLoopRunner> message_loop_runner_; | |
| 1009 | |
| 1010 DISALLOW_COPY_AND_ASSIGN(DialogDismissingWebContentsDelegate); | |
| 1011 }; | |
| 1012 | |
| 1013 } // namespace | |
| 1014 | |
| 1015 // Test that if a BeforeUnload dialog is destroyed due to the commit of a | |
| 1016 // cross-site navigation, it will not reset the loading state. | |
|
Charlie Reis
2017/06/02 23:57:57
The test covers both same-site and cross-site, and
ncarter (slow)
2017/06/19 17:45:49
The coverage of the cross-process case was to make
| |
| 1017 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, | |
| 1018 DismissingBeforeUnloadDialogInvalidatesUrl) { | |
| 1019 ASSERT_TRUE(embedded_test_server()->Start()); | |
| 1020 const GURL kStartURL(embedded_test_server()->GetURL( | |
| 1021 "foo.com", "/render_frame_host/beforeunload.html")); | |
| 1022 const GURL kSameSiteURL( | |
| 1023 embedded_test_server()->GetURL("foo.com", "/title1.html")); | |
| 1024 const GURL kCrossSiteURL( | |
| 1025 embedded_test_server()->GetURL("bar.com", "/title1.html")); | |
| 1026 | |
| 1027 // Navigate to a first web page with a BeforeUnload event listener. | |
| 1028 EXPECT_TRUE(NavigateToURL(shell(), kStartURL)); | |
| 1029 | |
| 1030 DialogDismissingWebContentsDelegate web_contents_delegate; | |
| 1031 shell()->web_contents()->SetDelegate(&web_contents_delegate); | |
| 1032 | |
| 1033 // Send a user gesture (a side effect of ExecuteScript); otherwise the | |
| 1034 // beforeunload handler won't run. | |
| 1035 EXPECT_TRUE(ExecuteScript(shell(), "")); | |
|
Charlie Reis
2017/06/02 23:57:57
Avi added PrepContentsForBeforeUnloadTest for this
ncarter (slow)
2017/06/19 17:45:49
I was hoping that disabling the hang monitor timeo
| |
| 1036 | |
| 1037 // Start a same-site navigation that is cancelled because of the beforeunload | |
| 1038 // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the | |
| 1039 // cancellation, so that the location bar resets to the original URL. | |
| 1040 shell()->LoadURL(kSameSiteURL); | |
| 1041 EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL()); | |
| 1042 web_contents_delegate.WaitForDialogDismissed(); | |
| 1043 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | |
| 1044 EXPECT_EQ(std::vector<GURL>{kStartURL}, | |
| 1045 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); | |
|
Charlie Reis
2017/06/02 23:57:57
Sanity check: Is this the part that failed before,
ncarter (slow)
2017/06/19 17:45:49
Yes.
| |
| 1046 | |
| 1047 // Start a cross-site navigation that is cancelled because of the beforeunload | |
| 1048 // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the | |
| 1049 // cancellation, so that the location bar resets to the original URL. | |
| 1050 shell()->LoadURL(kCrossSiteURL); | |
| 1051 EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL()); | |
| 1052 web_contents_delegate.WaitForDialogDismissed(); | |
| 1053 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | |
| 1054 EXPECT_EQ(std::vector<GURL>{kStartURL}, | |
| 1055 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); | |
|
Charlie Reis
2017/06/02 23:57:57
Is this just for completeness, or did this cross-s
ncarter (slow)
2017/06/19 17:45:49
See above. This coverage different from CancelBefo
| |
| 1056 | |
| 1057 // Now clear the unload handler and re-try the navigations, which should now | |
| 1058 // succeed. INVALIDATE_TYPE_URL should happen on commit, with the value of the | |
| 1059 // new URL. | |
| 1060 EXPECT_TRUE(ExecuteScript(shell(), | |
| 1061 "window.onbeforeunload=function(e){return null;}")); | |
| 1062 shell()->LoadURL(kSameSiteURL); | |
| 1063 EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL()); | |
| 1064 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | |
| 1065 EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL()); | |
| 1066 EXPECT_EQ(std::vector<GURL>{kSameSiteURL}, | |
| 1067 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); | |
| 1068 | |
| 1069 shell()->LoadURL(kCrossSiteURL); | |
| 1070 EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL()); | |
| 1071 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); | |
| 1072 EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL()); | |
| 1073 EXPECT_EQ(std::vector<GURL>{kCrossSiteURL}, | |
| 1074 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); | |
| 1075 | |
| 1076 // Clear the test delegates. | |
| 1077 static_cast<WebContentsImpl*>(shell()->web_contents()) | |
| 1078 ->SetJavaScriptDialogManagerForTesting(nullptr); | |
| 1079 shell()->web_contents()->SetDelegate(shell()); | |
| 1080 } | |
| 1081 | |
| 1082 namespace { | |
| 1083 | |
| 942 class TestJavaScriptDialogManager : public JavaScriptDialogManager, | 1084 class TestJavaScriptDialogManager : public JavaScriptDialogManager, |
| 943 public WebContentsDelegate { | 1085 public WebContentsDelegate { |
| 944 public: | 1086 public: |
| 945 TestJavaScriptDialogManager() : message_loop_runner_(new MessageLoopRunner) {} | 1087 TestJavaScriptDialogManager() : message_loop_runner_(new MessageLoopRunner) {} |
| 946 ~TestJavaScriptDialogManager() override {} | 1088 ~TestJavaScriptDialogManager() override {} |
| 947 | 1089 |
| 948 void Wait() { | 1090 void Wait() { |
| 949 message_loop_runner_->Run(); | 1091 message_loop_runner_->Run(); |
| 950 message_loop_runner_ = new MessageLoopRunner; | 1092 message_loop_runner_ = new MessageLoopRunner; |
| 951 } | 1093 } |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1389 ASSERT_TRUE(saw_override); | 1531 ASSERT_TRUE(saw_override); |
| 1390 | 1532 |
| 1391 BrowserThread::PostTask( | 1533 BrowserThread::PostTask( |
| 1392 BrowserThread::IO, FROM_HERE, | 1534 BrowserThread::IO, FROM_HERE, |
| 1393 base::Bind(&ResourceDispatcherHost::SetDelegate, | 1535 base::Bind(&ResourceDispatcherHost::SetDelegate, |
| 1394 base::Unretained(ResourceDispatcherHostImpl::Get()), | 1536 base::Unretained(ResourceDispatcherHostImpl::Get()), |
| 1395 old_delegate)); | 1537 old_delegate)); |
| 1396 } | 1538 } |
| 1397 | 1539 |
| 1398 } // namespace content | 1540 } // namespace content |
| OLD | NEW |