| 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 // same-site or cross-site navigation, it will not reset the loading state. |
| 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 PrepContentsForBeforeUnloadTest(shell()->web_contents()); |
| 1033 |
| 1034 // Start a same-site navigation that is cancelled because of the beforeunload |
| 1035 // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the |
| 1036 // cancellation, so that the location bar resets to the original URL. |
| 1037 shell()->LoadURL(kSameSiteURL); |
| 1038 EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL()); |
| 1039 web_contents_delegate.WaitForDialogDismissed(); |
| 1040 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); |
| 1041 EXPECT_EQ(std::vector<GURL>{kStartURL}, |
| 1042 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); |
| 1043 |
| 1044 // Start a cross-site navigation that is cancelled because of the beforeunload |
| 1045 // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the |
| 1046 // cancellation, so that the location bar resets to the original URL. |
| 1047 shell()->LoadURL(kCrossSiteURL); |
| 1048 EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL()); |
| 1049 web_contents_delegate.WaitForDialogDismissed(); |
| 1050 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); |
| 1051 EXPECT_EQ(std::vector<GURL>{kStartURL}, |
| 1052 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); |
| 1053 |
| 1054 // Now clear the unload handler and re-try the navigations, which should now |
| 1055 // succeed. INVALIDATE_TYPE_URL should happen on commit, with the value of the |
| 1056 // new URL. |
| 1057 EXPECT_TRUE(ExecuteScript(shell(), |
| 1058 "window.onbeforeunload=function(e){return null;}")); |
| 1059 shell()->LoadURL(kSameSiteURL); |
| 1060 EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL()); |
| 1061 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); |
| 1062 EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL()); |
| 1063 EXPECT_EQ(std::vector<GURL>{kSameSiteURL}, |
| 1064 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); |
| 1065 |
| 1066 shell()->LoadURL(kCrossSiteURL); |
| 1067 EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL()); |
| 1068 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); |
| 1069 EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL()); |
| 1070 EXPECT_EQ(std::vector<GURL>{kCrossSiteURL}, |
| 1071 web_contents_delegate.GetAndClearVisibleUrlInvalidations()); |
| 1072 |
| 1073 // Clear the test delegates. |
| 1074 static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 1075 ->SetJavaScriptDialogManagerForTesting(nullptr); |
| 1076 shell()->web_contents()->SetDelegate(shell()); |
| 1077 } |
| 1078 |
| 1079 namespace { |
| 1080 |
| 942 class TestJavaScriptDialogManager : public JavaScriptDialogManager, | 1081 class TestJavaScriptDialogManager : public JavaScriptDialogManager, |
| 943 public WebContentsDelegate { | 1082 public WebContentsDelegate { |
| 944 public: | 1083 public: |
| 945 TestJavaScriptDialogManager() | 1084 TestJavaScriptDialogManager() |
| 946 : is_fullscreen_(false), message_loop_runner_(new MessageLoopRunner) {} | 1085 : is_fullscreen_(false), message_loop_runner_(new MessageLoopRunner) {} |
| 947 ~TestJavaScriptDialogManager() override {} | 1086 ~TestJavaScriptDialogManager() override {} |
| 948 | 1087 |
| 949 void Wait() { | 1088 void Wait() { |
| 950 message_loop_runner_->Run(); | 1089 message_loop_runner_->Run(); |
| 951 message_loop_runner_ = new MessageLoopRunner; | 1090 message_loop_runner_ = new MessageLoopRunner; |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 EXPECT_TRUE(content::ExecuteScript(wc, script)); | 1600 EXPECT_TRUE(content::ExecuteScript(wc, script)); |
| 1462 EXPECT_TRUE(NavigateToURL(shell(), url)); | 1601 EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 1463 dialog_manager.Wait(); | 1602 dialog_manager.Wait(); |
| 1464 EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); | 1603 EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); |
| 1465 | 1604 |
| 1466 wc->SetDelegate(nullptr); | 1605 wc->SetDelegate(nullptr); |
| 1467 wc->SetJavaScriptDialogManagerForTesting(nullptr); | 1606 wc->SetJavaScriptDialogManagerForTesting(nullptr); |
| 1468 } | 1607 } |
| 1469 | 1608 |
| 1470 } // namespace content | 1609 } // namespace content |
| OLD | NEW |