| 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 23 matching lines...) Expand all Loading... |
| 34 #include "content/public/test/test_utils.h" | 34 #include "content/public/test/test_utils.h" |
| 35 #include "content/shell/browser/shell.h" | 35 #include "content/shell/browser/shell.h" |
| 36 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" | 36 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" |
| 37 #include "content/test/content_browser_test_utils_internal.h" | 37 #include "content/test/content_browser_test_utils_internal.h" |
| 38 #include "net/dns/mock_host_resolver.h" | 38 #include "net/dns/mock_host_resolver.h" |
| 39 #include "net/test/embedded_test_server/embedded_test_server.h" | 39 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 40 #include "testing/gmock/include/gmock/gmock.h" | 40 #include "testing/gmock/include/gmock/gmock.h" |
| 41 | 41 |
| 42 namespace content { | 42 namespace content { |
| 43 | 43 |
| 44 namespace { |
| 45 |
| 44 void ResizeWebContentsView(Shell* shell, const gfx::Size& size, | 46 void ResizeWebContentsView(Shell* shell, const gfx::Size& size, |
| 45 bool set_start_page) { | 47 bool set_start_page) { |
| 46 // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents | 48 // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents |
| 47 // works on Win and ChromeOS but not Linux - we need to resize the shell | 49 // works on Win and ChromeOS but not Linux - we need to resize the shell |
| 48 // window on Linux because if we don't, the next layout of the unchanged shell | 50 // window on Linux because if we don't, the next layout of the unchanged shell |
| 49 // window will resize WebContentsView back to the previous size. | 51 // window will resize WebContentsView back to the previous size. |
| 50 // SizeContents is a hack and should not be relied on. | 52 // SizeContents is a hack and should not be relied on. |
| 51 #if defined(OS_MACOSX) | 53 #if defined(OS_MACOSX) |
| 52 shell->SizeTo(size); | 54 shell->SizeTo(size); |
| 53 // If |set_start_page| is true, start with blank page to make sure resize | 55 // If |set_start_page| is true, start with blank page to make sure resize |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 int loadingStateChangedCount() const { return loadingStateChangedCount_; } | 193 int loadingStateChangedCount() const { return loadingStateChangedCount_; } |
| 192 int loadingStateToDifferentDocumentCount() const { | 194 int loadingStateToDifferentDocumentCount() const { |
| 193 return loadingStateToDifferentDocumentCount_; | 195 return loadingStateToDifferentDocumentCount_; |
| 194 } | 196 } |
| 195 | 197 |
| 196 private: | 198 private: |
| 197 int loadingStateChangedCount_; | 199 int loadingStateChangedCount_; |
| 198 int loadingStateToDifferentDocumentCount_; | 200 int loadingStateToDifferentDocumentCount_; |
| 199 }; | 201 }; |
| 200 | 202 |
| 203 class TestJavaScriptDialogManager : public JavaScriptDialogManager, |
| 204 public WebContentsDelegate { |
| 205 public: |
| 206 TestJavaScriptDialogManager() : message_loop_runner_(new MessageLoopRunner) {} |
| 207 ~TestJavaScriptDialogManager() override {} |
| 208 |
| 209 void Wait() { |
| 210 message_loop_runner_->Run(); |
| 211 message_loop_runner_ = new MessageLoopRunner; |
| 212 } |
| 213 |
| 214 std::string last_message() { return last_message_; } |
| 215 bool did_get_dialog() { return did_get_dialog_; } |
| 216 bool did_get_beforeunload() { return did_get_beforeunload_; } |
| 217 |
| 218 // WebContentsDelegate |
| 219 |
| 220 JavaScriptDialogManager* GetJavaScriptDialogManager( |
| 221 WebContents* source) override { |
| 222 return this; |
| 223 } |
| 224 |
| 225 // JavaScriptDialogManager |
| 226 |
| 227 void RunJavaScriptDialog(WebContents* web_contents, |
| 228 const GURL& origin_url, |
| 229 JavaScriptDialogType dialog_type, |
| 230 const base::string16& message_text, |
| 231 const base::string16& default_prompt_text, |
| 232 const DialogClosedCallback& callback, |
| 233 bool* did_suppress_message) override { |
| 234 did_get_dialog_ = true; |
| 235 last_message_ = base::UTF16ToUTF8(message_text); |
| 236 *did_suppress_message = true; |
| 237 |
| 238 message_loop_runner_->Quit(); |
| 239 }; |
| 240 |
| 241 void RunBeforeUnloadDialog(WebContents* web_contents, |
| 242 bool is_reload, |
| 243 const DialogClosedCallback& callback) override { |
| 244 did_get_beforeunload_ = true; |
| 245 |
| 246 message_loop_runner_->Quit(); |
| 247 } |
| 248 |
| 249 bool HandleJavaScriptDialog(WebContents* web_contents, |
| 250 bool accept, |
| 251 const base::string16* prompt_override) override { |
| 252 return true; |
| 253 } |
| 254 |
| 255 void CancelDialogs(WebContents* web_contents, bool reset_state) override {} |
| 256 |
| 257 private: |
| 258 std::string last_message_; |
| 259 |
| 260 bool did_get_dialog_ = false; |
| 261 bool did_get_beforeunload_ = false; |
| 262 |
| 263 // The MessageLoopRunner used to spin the message loop. |
| 264 scoped_refptr<MessageLoopRunner> message_loop_runner_; |
| 265 |
| 266 DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager); |
| 267 }; |
| 268 |
| 269 } // namespace |
| 270 |
| 201 // Test that DidStopLoading includes the correct URL in the details. | 271 // Test that DidStopLoading includes the correct URL in the details. |
| 202 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) { | 272 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) { |
| 203 ASSERT_TRUE(embedded_test_server()->Start()); | 273 ASSERT_TRUE(embedded_test_server()->Start()); |
| 204 | 274 |
| 205 LoadStopNotificationObserver load_observer( | 275 LoadStopNotificationObserver load_observer( |
| 206 &shell()->web_contents()->GetController()); | 276 &shell()->web_contents()->GetController()); |
| 207 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); | 277 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); |
| 208 load_observer.Wait(); | 278 load_observer.Wait(); |
| 209 | 279 |
| 210 EXPECT_EQ("/title1.html", load_observer.url_.path()); | 280 EXPECT_EQ("/title1.html", load_observer.url_.path()); |
| (...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 | 1043 |
| 974 Shell* new_shell = new_shell_observer.GetShell(); | 1044 Shell* new_shell = new_shell_observer.GetShell(); |
| 975 WaitForLoadStop(new_shell->web_contents()); | 1045 WaitForLoadStop(new_shell->web_contents()); |
| 976 | 1046 |
| 977 EXPECT_EQ("foo", | 1047 EXPECT_EQ("foo", |
| 978 static_cast<WebContentsImpl*>(new_shell->web_contents()) | 1048 static_cast<WebContentsImpl*>(new_shell->web_contents()) |
| 979 ->GetFrameTree()->root()->frame_name()); | 1049 ->GetFrameTree()->root()->frame_name()); |
| 980 } | 1050 } |
| 981 } | 1051 } |
| 982 | 1052 |
| 983 // TODO(clamy): Make the test work on Windows and on Mac. On Mac and Windows, | |
| 984 // there seem to be an issue with the ShellJavascriptDialogManager. | |
| 985 // Flaky on all platforms: https://crbug.com/655628 | |
| 986 // Test that if a BeforeUnload dialog is destroyed due to the commit of a | 1053 // Test that if a BeforeUnload dialog is destroyed due to the commit of a |
| 987 // cross-site navigation, it will not reset the loading state. | 1054 // cross-site navigation, it will not reset the loading state. |
| 988 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, | 1055 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, |
| 989 DISABLED_NoResetOnBeforeUnloadCanceledOnCommit) { | 1056 NoResetOnBeforeUnloadCanceledOnCommit) { |
| 1057 WebContentsImpl* contents = |
| 1058 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 1059 TestJavaScriptDialogManager dialog_manager; |
| 1060 contents->SetDelegate(&dialog_manager); |
| 1061 |
| 990 ASSERT_TRUE(embedded_test_server()->Start()); | 1062 ASSERT_TRUE(embedded_test_server()->Start()); |
| 991 const GURL kStartURL( | 1063 const GURL kStartURL( |
| 992 embedded_test_server()->GetURL("/hang_before_unload.html")); | 1064 embedded_test_server()->GetURL("/hang_before_unload.html")); |
| 993 const GURL kCrossSiteURL( | 1065 const GURL kCrossSiteURL( |
| 994 embedded_test_server()->GetURL("bar.com", "/title1.html")); | 1066 embedded_test_server()->GetURL("bar.com", "/title1.html")); |
| 995 | 1067 |
| 996 // Navigate to a first web page with a BeforeUnload event listener. | 1068 // Navigate to a first web page with a BeforeUnload event listener. |
| 997 EXPECT_TRUE(NavigateToURL(shell(), kStartURL)); | 1069 EXPECT_TRUE(NavigateToURL(shell(), kStartURL)); |
| 1070 // Disable the hang monitor, otherwise there will be a race between the |
| 1071 // beforeunload dialog and the beforeunload hang timer. |
| 1072 contents->GetMainFrame()->DisableBeforeUnloadHangMonitorForTesting(); |
| 998 | 1073 |
| 999 // Start a cross-site navigation that will not commit for the moment. | 1074 // Start a cross-site navigation that will not commit for the moment. |
| 1000 TestNavigationManager cross_site_delayer(shell()->web_contents(), | 1075 TestNavigationManager cross_site_delayer(contents, kCrossSiteURL); |
| 1001 kCrossSiteURL); | |
| 1002 shell()->LoadURL(kCrossSiteURL); | 1076 shell()->LoadURL(kCrossSiteURL); |
| 1003 EXPECT_TRUE(cross_site_delayer.WaitForRequestStart()); | 1077 EXPECT_TRUE(cross_site_delayer.WaitForRequestStart()); |
| 1004 | 1078 |
| 1005 // Click on a link in the page. This will show the BeforeUnload dialog. | 1079 // Click on a link in the page. This will show the BeforeUnload dialog. |
| 1006 // Ensure the dialog is not dismissed, which will cause it to still be | 1080 // Ensure the dialog is not dismissed, which will cause it to still be |
| 1007 // present when the cross-site navigation later commits. | 1081 // present when the cross-site navigation later commits. |
| 1008 // Note: the javascript function executed will not do the link click but | 1082 // Note: the javascript function executed will not do the link click but |
| 1009 // schedule it for afterwards. Since the BeforeUnload event is synchronous, | 1083 // schedule it for afterwards. Since the BeforeUnload event is synchronous, |
| 1010 // clicking on the link right away would cause the ExecuteScript to never | 1084 // clicking on the link right away would cause the ExecuteScript to never |
| 1011 // return. | 1085 // return. |
| 1012 SetShouldProceedOnBeforeUnload(shell(), false); | |
| 1013 EXPECT_TRUE(ExecuteScript(shell(), "clickLinkSoon()")); | 1086 EXPECT_TRUE(ExecuteScript(shell(), "clickLinkSoon()")); |
| 1014 WaitForAppModalDialog(shell()); | 1087 dialog_manager.Wait(); |
| 1088 EXPECT_TRUE(dialog_manager.did_get_beforeunload()); |
| 1015 | 1089 |
| 1016 // Have the cross-site navigation commit. The main RenderFrameHost should | 1090 // Have the cross-site navigation commit. The main RenderFrameHost should |
| 1017 // still be loading after that. | 1091 // still be loading after that. |
| 1018 cross_site_delayer.WaitForNavigationFinished(); | 1092 cross_site_delayer.WaitForNavigationFinished(); |
| 1019 EXPECT_TRUE(shell()->web_contents()->IsLoading()); | 1093 EXPECT_TRUE(shell()->web_contents()->IsLoading()); |
| 1094 |
| 1095 contents->SetDelegate(nullptr); |
| 1096 contents->SetJavaScriptDialogManagerForTesting(nullptr); |
| 1020 } | 1097 } |
| 1021 | 1098 |
| 1022 namespace { | 1099 namespace { |
| 1023 void NavigateToDataURLAndExpectBeforeUnload(Shell* shell, | 1100 void NavigateToDataURLAndExpectBeforeUnload(Shell* shell, |
| 1024 const std::string& html, | 1101 const std::string& html, |
| 1025 bool expect_onbeforeunload) { | 1102 bool expect_onbeforeunload) { |
| 1026 NavigateToURL(shell, GURL("data:text/html," + html)); | 1103 NavigateToURL(shell, GURL("data:text/html," + html)); |
| 1027 RenderFrameHostImpl* rfh = | 1104 RenderFrameHostImpl* rfh = |
| 1028 static_cast<RenderFrameHostImpl*>(shell->web_contents()->GetMainFrame()); | 1105 static_cast<RenderFrameHostImpl*>(shell->web_contents()->GetMainFrame()); |
| 1029 EXPECT_EQ(expect_onbeforeunload, rfh->ShouldDispatchBeforeUnload()); | 1106 EXPECT_EQ(expect_onbeforeunload, rfh->ShouldDispatchBeforeUnload()); |
| 1030 } | 1107 } |
| 1031 } // namespace | 1108 } // namespace |
| 1032 | 1109 |
| 1033 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NoOnBeforeUnload) { | 1110 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NoOnBeforeUnload) { |
| 1034 const std::string NO_BEFORE_UNLOAD_HTML = "<html><body>foo</body></html>"; | 1111 const std::string NO_BEFORE_UNLOAD_HTML = "<html><body>foo</body></html>"; |
| 1035 NavigateToDataURLAndExpectBeforeUnload(shell(), NO_BEFORE_UNLOAD_HTML, false); | 1112 NavigateToDataURLAndExpectBeforeUnload(shell(), NO_BEFORE_UNLOAD_HTML, false); |
| 1036 } | 1113 } |
| 1037 | 1114 |
| 1038 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OnBeforeUnload) { | 1115 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OnBeforeUnload) { |
| 1039 const std::string BEFORE_UNLOAD_HTML = | 1116 const std::string BEFORE_UNLOAD_HTML = |
| 1040 "<html><body><script>window.onbeforeunload=function(e) {}</script>" | 1117 "<html><body><script>window.onbeforeunload=function(e) {}</script>" |
| 1041 "</body></html>"; | 1118 "</body></html>"; |
| 1042 NavigateToDataURLAndExpectBeforeUnload(shell(), BEFORE_UNLOAD_HTML, true); | 1119 NavigateToDataURLAndExpectBeforeUnload(shell(), BEFORE_UNLOAD_HTML, true); |
| 1043 } | 1120 } |
| 1044 | 1121 |
| 1045 namespace { | |
| 1046 | |
| 1047 class TestJavaScriptDialogManager : public JavaScriptDialogManager, | |
| 1048 public WebContentsDelegate { | |
| 1049 public: | |
| 1050 TestJavaScriptDialogManager() : message_loop_runner_(new MessageLoopRunner) {} | |
| 1051 ~TestJavaScriptDialogManager() override {} | |
| 1052 | |
| 1053 void Wait() { | |
| 1054 message_loop_runner_->Run(); | |
| 1055 message_loop_runner_ = new MessageLoopRunner; | |
| 1056 } | |
| 1057 | |
| 1058 std::string last_message() { return last_message_; } | |
| 1059 | |
| 1060 // WebContentsDelegate | |
| 1061 | |
| 1062 JavaScriptDialogManager* GetJavaScriptDialogManager( | |
| 1063 WebContents* source) override { | |
| 1064 return this; | |
| 1065 } | |
| 1066 | |
| 1067 // JavaScriptDialogManager | |
| 1068 | |
| 1069 void RunJavaScriptDialog(WebContents* web_contents, | |
| 1070 const GURL& origin_url, | |
| 1071 JavaScriptDialogType dialog_type, | |
| 1072 const base::string16& message_text, | |
| 1073 const base::string16& default_prompt_text, | |
| 1074 const DialogClosedCallback& callback, | |
| 1075 bool* did_suppress_message) override { | |
| 1076 last_message_ = base::UTF16ToUTF8(message_text); | |
| 1077 *did_suppress_message = true; | |
| 1078 | |
| 1079 message_loop_runner_->Quit(); | |
| 1080 }; | |
| 1081 | |
| 1082 void RunBeforeUnloadDialog(WebContents* web_contents, | |
| 1083 bool is_reload, | |
| 1084 const DialogClosedCallback& callback) override {} | |
| 1085 | |
| 1086 bool HandleJavaScriptDialog(WebContents* web_contents, | |
| 1087 bool accept, | |
| 1088 const base::string16* prompt_override) override { | |
| 1089 return true; | |
| 1090 } | |
| 1091 | |
| 1092 void CancelDialogs(WebContents* web_contents, | |
| 1093 bool reset_state) override {} | |
| 1094 | |
| 1095 private: | |
| 1096 std::string last_message_; | |
| 1097 | |
| 1098 // The MessageLoopRunner used to spin the message loop. | |
| 1099 scoped_refptr<MessageLoopRunner> message_loop_runner_; | |
| 1100 | |
| 1101 DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager); | |
| 1102 }; | |
| 1103 | |
| 1104 } // namespace | |
| 1105 | |
| 1106 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, | 1122 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, |
| 1107 JavaScriptDialogsInMainAndSubframes) { | 1123 JavaScriptDialogsInMainAndSubframes) { |
| 1108 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); | 1124 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 1109 TestJavaScriptDialogManager dialog_manager; | 1125 TestJavaScriptDialogManager dialog_manager; |
| 1110 wc->SetDelegate(&dialog_manager); | 1126 wc->SetDelegate(&dialog_manager); |
| 1111 | 1127 |
| 1112 host_resolver()->AddRule("*", "127.0.0.1"); | 1128 host_resolver()->AddRule("*", "127.0.0.1"); |
| 1113 ASSERT_TRUE(embedded_test_server()->Start()); | 1129 ASSERT_TRUE(embedded_test_server()->Start()); |
| 1114 | 1130 |
| 1115 NavigateToURL(shell(), | 1131 NavigateToURL(shell(), |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1496 ASSERT_TRUE(saw_override); | 1512 ASSERT_TRUE(saw_override); |
| 1497 | 1513 |
| 1498 BrowserThread::PostTask( | 1514 BrowserThread::PostTask( |
| 1499 BrowserThread::IO, FROM_HERE, | 1515 BrowserThread::IO, FROM_HERE, |
| 1500 base::Bind(&ResourceDispatcherHost::SetDelegate, | 1516 base::Bind(&ResourceDispatcherHost::SetDelegate, |
| 1501 base::Unretained(ResourceDispatcherHostImpl::Get()), | 1517 base::Unretained(ResourceDispatcherHostImpl::Get()), |
| 1502 old_delegate)); | 1518 old_delegate)); |
| 1503 } | 1519 } |
| 1504 | 1520 |
| 1505 } // namespace content | 1521 } // namespace content |
| OLD | NEW |