| 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 "chrome/browser/ssl/security_state_tab_helper.h" | 5 #include "chrome/browser/ssl/security_state_tab_helper.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 #include "third_party/boringssl/src/include/openssl/ssl.h" | 56 #include "third_party/boringssl/src/include/openssl/ssl.h" |
| 57 #include "ui/base/l10n/l10n_util.h" | 57 #include "ui/base/l10n/l10n_util.h" |
| 58 | 58 |
| 59 namespace { | 59 namespace { |
| 60 | 60 |
| 61 enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE }; | 61 enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE }; |
| 62 | 62 |
| 63 const base::FilePath::CharType kDocRoot[] = | 63 const base::FilePath::CharType kDocRoot[] = |
| 64 FILE_PATH_LITERAL("chrome/test/data"); | 64 FILE_PATH_LITERAL("chrome/test/data"); |
| 65 | 65 |
| 66 // Inject a script into the page. Used by tests that check for visible |
| 67 // password fields to wait for notifications about these |
| 68 // fields. Notifications about visible password fields are queued at the |
| 69 // end of the event loop, so waiting for a dummy script to run ensures |
| 70 // that these notifcations have been sent. |
| 71 void InjectScript(content::WebContents* contents) { |
| 72 bool js_result = false; |
| 73 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( |
| 74 contents, "window.domAutomationController.send(true);", &js_result)); |
| 75 EXPECT_TRUE(js_result); |
| 76 } |
| 77 |
| 66 // A WebContentsObserver useful for testing the DidChangeVisibleSecurityState() | 78 // A WebContentsObserver useful for testing the DidChangeVisibleSecurityState() |
| 67 // method: it keeps track of the latest security style and explanation that was | 79 // method: it keeps track of the latest security style and explanation that was |
| 68 // fired. | 80 // fired. |
| 69 class SecurityStyleTestObserver : public content::WebContentsObserver { | 81 class SecurityStyleTestObserver : public content::WebContentsObserver { |
| 70 public: | 82 public: |
| 71 explicit SecurityStyleTestObserver(content::WebContents* web_contents) | 83 explicit SecurityStyleTestObserver(content::WebContents* web_contents) |
| 72 : content::WebContentsObserver(web_contents), | 84 : content::WebContentsObserver(web_contents), |
| 73 latest_security_style_(blink::WebSecurityStyleUnknown) {} | 85 latest_security_style_(blink::WebSecurityStyleUnknown) {} |
| 74 ~SecurityStyleTestObserver() override {} | 86 ~SecurityStyleTestObserver() override {} |
| 75 | 87 |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 SetUpMockCertVerifierForHttpsServer(0, net::OK); | 336 SetUpMockCertVerifierForHttpsServer(0, net::OK); |
| 325 } | 337 } |
| 326 | 338 |
| 327 void SetUpCommandLine(base::CommandLine* command_line) override { | 339 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 328 SecurityStateTabHelperTest::SetUpCommandLine(command_line); | 340 SecurityStateTabHelperTest::SetUpCommandLine(command_line); |
| 329 command_line->AppendSwitchASCII( | 341 command_line->AppendSwitchASCII( |
| 330 security_state::switches::kMarkHttpAs, | 342 security_state::switches::kMarkHttpAs, |
| 331 security_state::switches::kMarkHttpWithPasswordsOrCcWithChip); | 343 security_state::switches::kMarkHttpWithPasswordsOrCcWithChip); |
| 332 } | 344 } |
| 333 | 345 |
| 346 // Navigates to an empty page and runs |javascript| to create a URL with with |
| 347 // a scheme of |scheme|. If |expect_warning| is true, expects a password |
| 348 // warning. |
| 349 void TestPasswordFieldOnBlobOrFilesystemURL(const std::string& scheme, |
| 350 const std::string& javascript, |
| 351 bool expect_warning) { |
| 352 content::WebContents* contents = |
| 353 browser()->tab_strip_model()->GetActiveWebContents(); |
| 354 ASSERT_TRUE(contents); |
| 355 |
| 356 SecurityStateTabHelper* helper = |
| 357 SecurityStateTabHelper::FromWebContents(contents); |
| 358 ASSERT_TRUE(helper); |
| 359 |
| 360 ui_test_utils::NavigateToURL( |
| 361 browser(), |
| 362 GetURLWithNonLocalHostname(embedded_test_server(), "/empty.html")); |
| 363 |
| 364 // Create a URL and navigate to it. |
| 365 std::string blob_or_filesystem_url; |
| 366 EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
| 367 contents, javascript, &blob_or_filesystem_url)); |
| 368 EXPECT_TRUE(GURL(blob_or_filesystem_url).SchemeIs(scheme)); |
| 369 |
| 370 ui_test_utils::NavigateToURL(browser(), GURL(blob_or_filesystem_url)); |
| 371 InjectScript(contents); |
| 372 security_state::SecurityInfo security_info; |
| 373 helper->GetSecurityInfo(&security_info); |
| 374 |
| 375 content::NavigationEntry* entry = |
| 376 contents->GetController().GetVisibleEntry(); |
| 377 ASSERT_TRUE(entry); |
| 378 |
| 379 if (expect_warning) { |
| 380 EXPECT_EQ(security_state::HTTP_SHOW_WARNING, |
| 381 security_info.security_level); |
| 382 EXPECT_TRUE(entry->GetSSL().content_status & |
| 383 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); |
| 384 } else { |
| 385 EXPECT_EQ(security_state::NONE, security_info.security_level); |
| 386 EXPECT_FALSE(entry->GetSSL().content_status & |
| 387 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); |
| 388 } |
| 389 } |
| 390 |
| 334 private: | 391 private: |
| 335 DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelperTestWithPasswordCcSwitch); | 392 DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelperTestWithPasswordCcSwitch); |
| 336 }; | 393 }; |
| 337 | 394 |
| 338 class DidChangeVisibleSecurityStateTest : public InProcessBrowserTest { | 395 class DidChangeVisibleSecurityStateTest : public InProcessBrowserTest { |
| 339 public: | 396 public: |
| 340 DidChangeVisibleSecurityStateTest() | 397 DidChangeVisibleSecurityStateTest() |
| 341 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { | 398 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { |
| 342 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); | 399 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); |
| 343 } | 400 } |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 | 988 |
| 932 // Navigate to a page that doesn't finish loading. Test that the | 989 // Navigate to a page that doesn't finish loading. Test that the |
| 933 // security state is neutral while the page is loading. | 990 // security state is neutral while the page is loading. |
| 934 browser()->OpenURL(content::OpenURLParams( | 991 browser()->OpenURL(content::OpenURLParams( |
| 935 embedded_test_server()->GetURL("/title1.html"), content::Referrer(), | 992 embedded_test_server()->GetURL("/title1.html"), content::Referrer(), |
| 936 WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false)); | 993 WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false)); |
| 937 CheckSecurityInfoForNonSecure( | 994 CheckSecurityInfoForNonSecure( |
| 938 browser()->tab_strip_model()->GetActiveWebContents()); | 995 browser()->tab_strip_model()->GetActiveWebContents()); |
| 939 } | 996 } |
| 940 | 997 |
| 941 // Inject a script into the page. Used by tests that check for visible | |
| 942 // password fields to wait for notifications about these | |
| 943 // fields. Notifications about visible password fields are queued at the | |
| 944 // end of the event loop, so waiting for a dummy script to run ensures | |
| 945 // that these notifcations have been sent. | |
| 946 void InjectScript(content::WebContents* contents) { | |
| 947 bool js_result = false; | |
| 948 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( | |
| 949 contents, "window.domAutomationController.send(true);", &js_result)); | |
| 950 EXPECT_TRUE(js_result); | |
| 951 } | |
| 952 | |
| 953 // Tests that when a visible password field is detected on an HTTP page | 998 // Tests that when a visible password field is detected on an HTTP page |
| 954 // load, and when the command-line flag is set, the security level is | 999 // load, and when the command-line flag is set, the security level is |
| 955 // downgraded to HTTP_SHOW_WARNING. | 1000 // downgraded to HTTP_SHOW_WARNING. |
| 956 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, | 1001 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, |
| 957 PasswordSecurityLevelDowngraded) { | 1002 PasswordSecurityLevelDowngraded) { |
| 958 content::WebContents* contents = | 1003 content::WebContents* contents = |
| 959 browser()->tab_strip_model()->GetActiveWebContents(); | 1004 browser()->tab_strip_model()->GetActiveWebContents(); |
| 960 ASSERT_TRUE(contents); | 1005 ASSERT_TRUE(contents); |
| 961 | 1006 |
| 962 SecurityStateTabHelper* helper = | 1007 SecurityStateTabHelper* helper = |
| 963 SecurityStateTabHelper::FromWebContents(contents); | 1008 SecurityStateTabHelper::FromWebContents(contents); |
| 964 ASSERT_TRUE(helper); | 1009 ASSERT_TRUE(helper); |
| 965 | 1010 |
| 966 ui_test_utils::NavigateToURL( | 1011 ui_test_utils::NavigateToURL( |
| 967 browser(), GetURLWithNonLocalHostname(embedded_test_server(), | 1012 browser(), GetURLWithNonLocalHostname(embedded_test_server(), |
| 968 "/password/simple_password.html")); | 1013 "/password/simple_password.html")); |
| 969 InjectScript(contents); | 1014 InjectScript(contents); |
| 970 security_state::SecurityInfo security_info; | 1015 security_state::SecurityInfo security_info; |
| 971 helper->GetSecurityInfo(&security_info); | 1016 helper->GetSecurityInfo(&security_info); |
| 972 EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); | 1017 EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); |
| 973 | 1018 |
| 974 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry(); | 1019 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry(); |
| 975 ASSERT_TRUE(entry); | 1020 ASSERT_TRUE(entry); |
| 976 EXPECT_TRUE(entry->GetSSL().content_status & | 1021 EXPECT_TRUE(entry->GetSSL().content_status & |
| 977 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); | 1022 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); |
| 978 } | 1023 } |
| 979 | 1024 |
| 1025 // Tests that when a visible password field is detected on a blob URL, and when |
| 1026 // the command-line flag is set, the security level is downgraded to |
| 1027 // HTTP_SHOW_WARNING. |
| 1028 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, |
| 1029 PasswordSecurityLevelDowngradedOnBlobUrl) { |
| 1030 TestPasswordFieldOnBlobOrFilesystemURL( |
| 1031 "blob", |
| 1032 "var blob = new Blob(['<html><form><input type=password></form></html>']," |
| 1033 " {type: 'text/html'});" |
| 1034 "window.domAutomationController.send(URL.createObjectURL(blob));", |
| 1035 true /* expect_warning */); |
| 1036 } |
| 1037 |
| 1038 // Tests that when no password field is detected on a blob URL, and when the |
| 1039 // command-line flag is set the security level is not downgraded to |
| 1040 // HTTP_SHOW_WARNING. |
| 1041 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, |
| 1042 DefaultSecurityLevelOnBlobUrl) { |
| 1043 TestPasswordFieldOnBlobOrFilesystemURL( |
| 1044 "blob", |
| 1045 "var blob = new Blob(['<html>no password or credit card field</html>']," |
| 1046 " {type: 'text/html'});" |
| 1047 "window.domAutomationController.send(URL.createObjectURL(blob));", |
| 1048 false /* expect_warning */); |
| 1049 } |
| 1050 |
| 1051 // Same as PasswordSecurityLevelDowngradedOnBlobUrl, but instead of a blob URL, |
| 1052 // this creates a filesystem URL. |
| 1053 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, |
| 1054 PasswordSecurityLevelDowngradedOnFilesystemUrl) { |
| 1055 TestPasswordFieldOnBlobOrFilesystemURL( |
| 1056 "filesystem", |
| 1057 "window.webkitRequestFileSystem(window.TEMPORARY, 4096, function(fs) {" |
| 1058 " fs.root.getFile('test.html', {create: true}, function(fileEntry) {" |
| 1059 " fileEntry.createWriter(function(writer) {" |
| 1060 " writer.onwriteend = function(e) {" |
| 1061 " window.domAutomationController.send(fileEntry.toURL());" |
| 1062 " };" |
| 1063 " var blob =" |
| 1064 " new Blob(['<html><form><input type=password></form></html>']," |
| 1065 " {type: 'text/html'});" |
| 1066 " writer.write(blob);" |
| 1067 " });" |
| 1068 " });" |
| 1069 "});", |
| 1070 true /* expect_warning */); |
| 1071 } |
| 1072 |
| 1073 // Same as DefaultSecurityLevelOnBlobUrl, but instead of a blob URL, |
| 1074 // this creates a filesystem URL. |
| 1075 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, |
| 1076 DefaultSecurityLevelOnFilesystemUrl) { |
| 1077 TestPasswordFieldOnBlobOrFilesystemURL( |
| 1078 "filesystem", |
| 1079 "window.webkitRequestFileSystem(window.TEMPORARY, 4096, function(fs) {" |
| 1080 " fs.root.getFile('test.html', {create: true}, function(fileEntry) {" |
| 1081 " fileEntry.createWriter(function(writer) {" |
| 1082 " writer.onwriteend = function(e) {" |
| 1083 " window.domAutomationController.send(fileEntry.toURL());" |
| 1084 " };" |
| 1085 " var blob =" |
| 1086 " new Blob(['<html>no password or credit card field</html>']," |
| 1087 " {type: 'text/html'});" |
| 1088 " writer.write(blob);" |
| 1089 " });" |
| 1090 " });" |
| 1091 "});", |
| 1092 false /* expect_warning */); |
| 1093 } |
| 1094 |
| 980 // Tests that when an invisible password field is present on an HTTP page | 1095 // Tests that when an invisible password field is present on an HTTP page |
| 981 // load, and when the command-line flag is set, the security level is | 1096 // load, and when the command-line flag is set, the security level is |
| 982 // *not* downgraded to HTTP_SHOW_WARNING. | 1097 // *not* downgraded to HTTP_SHOW_WARNING. |
| 983 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, | 1098 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch, |
| 984 PasswordSecurityLevelNotDowngradedForInvisibleInput) { | 1099 PasswordSecurityLevelNotDowngradedForInvisibleInput) { |
| 985 content::WebContents* contents = | 1100 content::WebContents* contents = |
| 986 browser()->tab_strip_model()->GetActiveWebContents(); | 1101 browser()->tab_strip_model()->GetActiveWebContents(); |
| 987 ASSERT_TRUE(contents); | 1102 ASSERT_TRUE(contents); |
| 988 | 1103 |
| 989 SecurityStateTabHelper* helper = | 1104 SecurityStateTabHelper* helper = |
| (...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2043 SecurityStateTabHelper* helper = | 2158 SecurityStateTabHelper* helper = |
| 2044 SecurityStateTabHelper::FromWebContents(web_contents); | 2159 SecurityStateTabHelper::FromWebContents(web_contents); |
| 2045 ASSERT_TRUE(helper); | 2160 ASSERT_TRUE(helper); |
| 2046 security_state::SecurityInfo security_info; | 2161 security_state::SecurityInfo security_info; |
| 2047 helper->GetSecurityInfo(&security_info); | 2162 helper->GetSecurityInfo(&security_info); |
| 2048 EXPECT_EQ(security_state::SECURE, security_info.security_level); | 2163 EXPECT_EQ(security_state::SECURE, security_info.security_level); |
| 2049 EXPECT_EQ(kTestSCTStatuses, security_info.sct_verify_statuses); | 2164 EXPECT_EQ(kTestSCTStatuses, security_info.sct_verify_statuses); |
| 2050 } | 2165 } |
| 2051 | 2166 |
| 2052 } // namespace | 2167 } // namespace |
| OLD | NEW |