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/chrome_security_state_model_client.h" | 5 #include "chrome/browser/ssl/chrome_security_state_model_client.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" |
| 11 #include "base/strings/utf_string_conversions.h" |
11 #include "chrome/browser/ssl/cert_verifier_browser_test.h" | 12 #include "chrome/browser/ssl/cert_verifier_browser_test.h" |
12 #include "chrome/browser/ssl/chrome_security_state_model_client.h" | 13 #include "chrome/browser/ssl/chrome_security_state_model_client.h" |
13 #include "chrome/browser/ssl/ssl_blocking_page.h" | 14 #include "chrome/browser/ssl/ssl_blocking_page.h" |
14 #include "chrome/browser/ui/browser.h" | 15 #include "chrome/browser/ui/browser.h" |
| 16 #include "chrome/browser/ui/browser_commands.h" |
15 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
16 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
17 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
18 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
| 21 #include "chrome/grit/generated_resources.h" |
19 #include "chrome/test/base/in_process_browser_test.h" | 22 #include "chrome/test/base/in_process_browser_test.h" |
20 #include "chrome/test/base/ui_test_utils.h" | 23 #include "chrome/test/base/ui_test_utils.h" |
21 #include "components/prefs/pref_service.h" | 24 #include "components/prefs/pref_service.h" |
22 #include "content/public/browser/cert_store.h" | 25 #include "content/public/browser/cert_store.h" |
23 #include "content/public/browser/interstitial_page.h" | 26 #include "content/public/browser/interstitial_page.h" |
24 #include "content/public/browser/navigation_controller.h" | 27 #include "content/public/browser/navigation_controller.h" |
| 28 #include "content/public/browser/navigation_entry.h" |
25 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
26 #include "content/public/browser/notification_types.h" | 30 #include "content/public/browser/notification_types.h" |
| 31 #include "content/public/browser/security_style_explanation.h" |
| 32 #include "content/public/browser/security_style_explanations.h" |
27 #include "content/public/browser/web_contents.h" | 33 #include "content/public/browser/web_contents.h" |
28 #include "content/public/common/referrer.h" | 34 #include "content/public/common/referrer.h" |
| 35 #include "content/public/common/ssl_status.h" |
29 #include "content/public/test/browser_test_utils.h" | 36 #include "content/public/test/browser_test_utils.h" |
30 #include "net/base/net_errors.h" | 37 #include "net/base/net_errors.h" |
| 38 #include "net/base/test_data_directory.h" |
31 #include "net/cert/cert_status_flags.h" | 39 #include "net/cert/cert_status_flags.h" |
32 #include "net/cert/cert_verify_result.h" | 40 #include "net/cert/cert_verify_result.h" |
33 #include "net/cert/mock_cert_verifier.h" | 41 #include "net/cert/mock_cert_verifier.h" |
34 #include "net/cert/x509_certificate.h" | 42 #include "net/cert/x509_certificate.h" |
35 #include "net/dns/mock_host_resolver.h" | 43 #include "net/dns/mock_host_resolver.h" |
| 44 #include "net/ssl/ssl_cipher_suite_names.h" |
| 45 #include "net/ssl/ssl_connection_status_flags.h" |
| 46 #include "net/test/cert_test_util.h" |
36 #include "net/test/embedded_test_server/embedded_test_server.h" | 47 #include "net/test/embedded_test_server/embedded_test_server.h" |
37 #include "net/test/embedded_test_server/request_handler_util.h" | 48 #include "net/test/embedded_test_server/request_handler_util.h" |
38 #include "net/test/url_request/url_request_failed_job.h" | 49 #include "net/test/url_request/url_request_failed_job.h" |
| 50 #include "net/test/url_request/url_request_mock_http_job.h" |
39 #include "net/url_request/url_request_filter.h" | 51 #include "net/url_request/url_request_filter.h" |
| 52 #include "net/url_request/url_request_test_util.h" |
| 53 #include "ui/base/l10n/l10n_util.h" |
40 | 54 |
41 using security_state::SecurityStateModel; | 55 using security_state::SecurityStateModel; |
42 | 56 |
43 namespace { | 57 namespace { |
44 | 58 |
| 59 enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE }; |
| 60 |
45 const base::FilePath::CharType kDocRoot[] = | 61 const base::FilePath::CharType kDocRoot[] = |
46 FILE_PATH_LITERAL("chrome/test/data"); | 62 FILE_PATH_LITERAL("chrome/test/data"); |
47 | 63 |
| 64 // A WebContentsObserver useful for testing the SecurityStyleChanged() |
| 65 // method: it keeps track of the latest security style and explanation |
| 66 // that was fired. |
| 67 class SecurityStyleTestObserver : public content::WebContentsObserver { |
| 68 public: |
| 69 explicit SecurityStyleTestObserver(content::WebContents* web_contents) |
| 70 : content::WebContentsObserver(web_contents), |
| 71 latest_security_style_(content::SECURITY_STYLE_UNKNOWN) {} |
| 72 ~SecurityStyleTestObserver() override {} |
| 73 |
| 74 void SecurityStyleChanged(content::SecurityStyle security_style, |
| 75 const content::SecurityStyleExplanations& |
| 76 security_style_explanations) override { |
| 77 latest_security_style_ = security_style; |
| 78 latest_explanations_ = security_style_explanations; |
| 79 } |
| 80 |
| 81 content::SecurityStyle latest_security_style() const { |
| 82 return latest_security_style_; |
| 83 } |
| 84 |
| 85 const content::SecurityStyleExplanations& latest_explanations() const { |
| 86 return latest_explanations_; |
| 87 } |
| 88 |
| 89 void ClearLatestSecurityStyleAndExplanations() { |
| 90 latest_security_style_ = content::SECURITY_STYLE_UNKNOWN; |
| 91 latest_explanations_ = content::SecurityStyleExplanations(); |
| 92 } |
| 93 |
| 94 private: |
| 95 content::SecurityStyle latest_security_style_; |
| 96 content::SecurityStyleExplanations latest_explanations_; |
| 97 |
| 98 DISALLOW_COPY_AND_ASSIGN(SecurityStyleTestObserver); |
| 99 }; |
| 100 |
| 101 // Check that |observer|'s latest event was for an expired certificate |
| 102 // and that it saw the proper SecurityStyle and explanations. |
| 103 void CheckBrokenSecurityStyle(const SecurityStyleTestObserver& observer, |
| 104 int error, |
| 105 Browser* browser) { |
| 106 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, |
| 107 observer.latest_security_style()); |
| 108 |
| 109 const content::SecurityStyleExplanations& expired_explanation = |
| 110 observer.latest_explanations(); |
| 111 EXPECT_EQ(0u, expired_explanation.unauthenticated_explanations.size()); |
| 112 ASSERT_EQ(1u, expired_explanation.broken_explanations.size()); |
| 113 |
| 114 // Check that the summary and description are as expected. |
| 115 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR), |
| 116 expired_explanation.broken_explanations[0].summary); |
| 117 |
| 118 base::string16 error_string = base::UTF8ToUTF16(net::ErrorToString(error)); |
| 119 EXPECT_EQ(l10n_util::GetStringFUTF8( |
| 120 IDS_CERTIFICATE_CHAIN_ERROR_DESCRIPTION_FORMAT, error_string), |
| 121 expired_explanation.broken_explanations[0].description); |
| 122 |
| 123 // Check the associated certificate id. |
| 124 int cert_id = browser->tab_strip_model() |
| 125 ->GetActiveWebContents() |
| 126 ->GetController() |
| 127 .GetActiveEntry() |
| 128 ->GetSSL() |
| 129 .cert_id; |
| 130 EXPECT_EQ(cert_id, expired_explanation.broken_explanations[0].cert_id); |
| 131 } |
| 132 |
| 133 // Checks that the given |secure_explanations| contains an appropriate |
| 134 // explanation if the certificate status is valid. |
| 135 void CheckSecureExplanations( |
| 136 const std::vector<content::SecurityStyleExplanation>& secure_explanations, |
| 137 CertificateStatus cert_status, |
| 138 Browser* browser) { |
| 139 ASSERT_EQ(cert_status == VALID_CERTIFICATE ? 2u : 1u, |
| 140 secure_explanations.size()); |
| 141 if (cert_status == VALID_CERTIFICATE) { |
| 142 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE), |
| 143 secure_explanations[0].summary); |
| 144 EXPECT_EQ( |
| 145 l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION), |
| 146 secure_explanations[0].description); |
| 147 int cert_id = browser->tab_strip_model() |
| 148 ->GetActiveWebContents() |
| 149 ->GetController() |
| 150 .GetActiveEntry() |
| 151 ->GetSSL() |
| 152 .cert_id; |
| 153 EXPECT_EQ(cert_id, secure_explanations[0].cert_id); |
| 154 } |
| 155 |
| 156 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE), |
| 157 secure_explanations.back().summary); |
| 158 EXPECT_EQ( |
| 159 l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE_DESCRIPTION), |
| 160 secure_explanations.back().description); |
| 161 } |
| 162 |
48 void CheckSecurityInfoForSecure( | 163 void CheckSecurityInfoForSecure( |
49 content::WebContents* contents, | 164 content::WebContents* contents, |
50 SecurityStateModel::SecurityLevel expect_security_level, | 165 SecurityStateModel::SecurityLevel expect_security_level, |
51 SecurityStateModel::SHA1DeprecationStatus expect_sha1_status, | 166 SecurityStateModel::SHA1DeprecationStatus expect_sha1_status, |
52 SecurityStateModel::MixedContentStatus expect_mixed_content_status, | 167 SecurityStateModel::MixedContentStatus expect_mixed_content_status, |
53 bool expect_cert_error) { | 168 bool expect_cert_error) { |
54 ASSERT_TRUE(contents); | 169 ASSERT_TRUE(contents); |
55 | 170 |
56 ChromeSecurityStateModelClient* model_client = | 171 ChromeSecurityStateModelClient* model_client = |
57 ChromeSecurityStateModelClient::FromWebContents(contents); | 172 ChromeSecurityStateModelClient::FromWebContents(contents); |
(...skipping 27 matching lines...) Expand all Loading... |
85 security_info.sha1_deprecation_status); | 200 security_info.sha1_deprecation_status); |
86 EXPECT_EQ(SecurityStateModel::NO_MIXED_CONTENT, | 201 EXPECT_EQ(SecurityStateModel::NO_MIXED_CONTENT, |
87 security_info.mixed_content_status); | 202 security_info.mixed_content_status); |
88 EXPECT_TRUE(security_info.sct_verify_statuses.empty()); | 203 EXPECT_TRUE(security_info.sct_verify_statuses.empty()); |
89 EXPECT_FALSE(security_info.scheme_is_cryptographic); | 204 EXPECT_FALSE(security_info.scheme_is_cryptographic); |
90 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status)); | 205 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status)); |
91 EXPECT_EQ(-1, security_info.security_bits); | 206 EXPECT_EQ(-1, security_info.security_bits); |
92 EXPECT_EQ(0, security_info.cert_id); | 207 EXPECT_EQ(0, security_info.cert_id); |
93 } | 208 } |
94 | 209 |
| 210 void ProceedThroughInterstitial(content::WebContents* tab) { |
| 211 content::InterstitialPage* interstitial_page = tab->GetInterstitialPage(); |
| 212 ASSERT_TRUE(interstitial_page); |
| 213 ASSERT_EQ(SSLBlockingPage::kTypeForTesting, |
| 214 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); |
| 215 content::WindowedNotificationObserver observer( |
| 216 content::NOTIFICATION_LOAD_STOP, |
| 217 content::Source<content::NavigationController>(&tab->GetController())); |
| 218 interstitial_page->Proceed(); |
| 219 observer.Wait(); |
| 220 } |
| 221 |
| 222 void GetFilePathWithHostAndPortReplacement( |
| 223 const std::string& original_file_path, |
| 224 const net::HostPortPair& host_port_pair, |
| 225 std::string* replacement_path) { |
| 226 base::StringPairs replacement_text; |
| 227 replacement_text.push_back( |
| 228 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); |
| 229 net::test_server::GetFilePathWithReplacements( |
| 230 original_file_path, replacement_text, replacement_path); |
| 231 } |
| 232 |
95 class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest { | 233 class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest { |
96 public: | 234 public: |
97 ChromeSecurityStateModelClientTest() | 235 ChromeSecurityStateModelClientTest() |
98 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { | 236 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { |
99 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); | 237 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); |
100 } | 238 } |
101 | 239 |
102 void SetUpCommandLine(base::CommandLine* command_line) override { | 240 void SetUpCommandLine(base::CommandLine* command_line) override { |
103 // Browser will both run and display insecure content. | 241 // Browser will both run and display insecure content. |
104 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); | 242 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); |
105 } | 243 } |
106 | 244 |
107 void ProceedThroughInterstitial(content::WebContents* tab) { | |
108 content::InterstitialPage* interstitial_page = tab->GetInterstitialPage(); | |
109 ASSERT_TRUE(interstitial_page); | |
110 ASSERT_EQ(SSLBlockingPage::kTypeForTesting, | |
111 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); | |
112 content::WindowedNotificationObserver observer( | |
113 content::NOTIFICATION_LOAD_STOP, | |
114 content::Source<content::NavigationController>(&tab->GetController())); | |
115 interstitial_page->Proceed(); | |
116 observer.Wait(); | |
117 } | |
118 | |
119 static void GetFilePathWithHostAndPortReplacement( | |
120 const std::string& original_file_path, | |
121 const net::HostPortPair& host_port_pair, | |
122 std::string* replacement_path) { | |
123 base::StringPairs replacement_text; | |
124 replacement_text.push_back( | |
125 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); | |
126 net::test_server::GetFilePathWithReplacements( | |
127 original_file_path, replacement_text, replacement_path); | |
128 } | |
129 | |
130 protected: | 245 protected: |
131 void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status, | 246 void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status, |
132 int net_result) { | 247 int net_result) { |
133 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate()); | 248 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate()); |
134 net::CertVerifyResult verify_result; | 249 net::CertVerifyResult verify_result; |
135 verify_result.is_issued_by_known_root = true; | 250 verify_result.is_issued_by_known_root = true; |
136 verify_result.verified_cert = cert; | 251 verify_result.verified_cert = cert; |
137 verify_result.cert_status = cert_status; | 252 verify_result.cert_status = cert_status; |
138 | 253 |
139 mock_cert_verifier()->AddResultForCert(cert.get(), verify_result, | 254 mock_cert_verifier()->AddResultForCert(cert.get(), verify_result, |
140 net_result); | 255 net_result); |
141 } | 256 } |
142 | 257 |
143 net::EmbeddedTestServer https_server_; | 258 net::EmbeddedTestServer https_server_; |
144 | 259 |
145 private: | 260 private: |
146 DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClientTest); | 261 DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClientTest); |
147 }; | 262 }; |
148 | 263 |
| 264 class SecurityStyleChangedTest : public InProcessBrowserTest { |
| 265 public: |
| 266 SecurityStyleChangedTest() |
| 267 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { |
| 268 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); |
| 269 } |
| 270 |
| 271 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 272 // Browser will both run and display insecure content. |
| 273 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); |
| 274 } |
| 275 |
| 276 protected: |
| 277 net::EmbeddedTestServer https_server_; |
| 278 |
| 279 private: |
| 280 DISALLOW_COPY_AND_ASSIGN(SecurityStyleChangedTest); |
| 281 }; |
| 282 |
149 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpPage) { | 283 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpPage) { |
150 ASSERT_TRUE(embedded_test_server()->Start()); | 284 ASSERT_TRUE(embedded_test_server()->Start()); |
151 ui_test_utils::NavigateToURL( | 285 ui_test_utils::NavigateToURL( |
152 browser(), embedded_test_server()->GetURL("/ssl/google.html")); | 286 browser(), embedded_test_server()->GetURL("/ssl/google.html")); |
153 content::WebContents* contents = | 287 content::WebContents* contents = |
154 browser()->tab_strip_model()->GetActiveWebContents(); | 288 browser()->tab_strip_model()->GetActiveWebContents(); |
155 ASSERT_TRUE(contents); | 289 ASSERT_TRUE(contents); |
156 | 290 |
157 ChromeSecurityStateModelClient* model_client = | 291 ChromeSecurityStateModelClient* model_client = |
158 ChromeSecurityStateModelClient::FromWebContents(contents); | 292 ChromeSecurityStateModelClient::FromWebContents(contents); |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 false /* expect cert status error */); | 662 false /* expect cert status error */); |
529 | 663 |
530 browser()->tab_strip_model()->InsertWebContentsAt(0, new_contents, | 664 browser()->tab_strip_model()->InsertWebContentsAt(0, new_contents, |
531 TabStripModel::ADD_NONE); | 665 TabStripModel::ADD_NONE); |
532 CheckSecurityInfoForSecure(new_contents, SecurityStateModel::SECURE, | 666 CheckSecurityInfoForSecure(new_contents, SecurityStateModel::SECURE, |
533 SecurityStateModel::NO_DEPRECATED_SHA1, | 667 SecurityStateModel::NO_DEPRECATED_SHA1, |
534 SecurityStateModel::NO_MIXED_CONTENT, | 668 SecurityStateModel::NO_MIXED_CONTENT, |
535 false /* expect cert status error */); | 669 false /* expect cert status error */); |
536 } | 670 } |
537 | 671 |
| 672 // Tests that the WebContentsObserver::SecurityStyleChanged event fires |
| 673 // with the current style on HTTP, broken HTTPS, and valid HTTPS pages. |
| 674 IN_PROC_BROWSER_TEST_F(SecurityStyleChangedTest, SecurityStyleChangedObserver) { |
| 675 ASSERT_TRUE(https_server_.Start()); |
| 676 ASSERT_TRUE(embedded_test_server()->Start()); |
| 677 |
| 678 net::EmbeddedTestServer https_test_server_expired( |
| 679 net::EmbeddedTestServer::TYPE_HTTPS); |
| 680 https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); |
| 681 https_test_server_expired.ServeFilesFromSourceDirectory( |
| 682 base::FilePath(kDocRoot)); |
| 683 ASSERT_TRUE(https_test_server_expired.Start()); |
| 684 |
| 685 content::WebContents* web_contents = |
| 686 browser()->tab_strip_model()->GetActiveWebContents(); |
| 687 SecurityStyleTestObserver observer(web_contents); |
| 688 |
| 689 // Visit an HTTP url. |
| 690 GURL http_url(embedded_test_server()->GetURL("/")); |
| 691 ui_test_utils::NavigateToURL(browser(), http_url); |
| 692 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, |
| 693 observer.latest_security_style()); |
| 694 EXPECT_EQ(0u, |
| 695 observer.latest_explanations().unauthenticated_explanations.size()); |
| 696 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| 697 EXPECT_EQ(0u, observer.latest_explanations().secure_explanations.size()); |
| 698 EXPECT_FALSE(observer.latest_explanations().scheme_is_cryptographic); |
| 699 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 700 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 701 |
| 702 // Visit an (otherwise valid) HTTPS page that displays mixed content. |
| 703 std::string replacement_path; |
| 704 GetFilePathWithHostAndPortReplacement( |
| 705 "/ssl/page_displays_insecure_content.html", |
| 706 embedded_test_server()->host_port_pair(), &replacement_path); |
| 707 |
| 708 GURL mixed_content_url(https_server_.GetURL(replacement_path)); |
| 709 ui_test_utils::NavigateToURL(browser(), mixed_content_url); |
| 710 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, |
| 711 observer.latest_security_style()); |
| 712 |
| 713 const content::SecurityStyleExplanations& mixed_content_explanation = |
| 714 observer.latest_explanations(); |
| 715 ASSERT_EQ(0u, mixed_content_explanation.unauthenticated_explanations.size()); |
| 716 ASSERT_EQ(0u, mixed_content_explanation.broken_explanations.size()); |
| 717 CheckSecureExplanations(mixed_content_explanation.secure_explanations, |
| 718 VALID_CERTIFICATE, browser()); |
| 719 EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic); |
| 720 EXPECT_TRUE(mixed_content_explanation.displayed_insecure_content); |
| 721 EXPECT_FALSE(mixed_content_explanation.ran_insecure_content); |
| 722 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, |
| 723 mixed_content_explanation.displayed_insecure_content_style); |
| 724 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, |
| 725 mixed_content_explanation.ran_insecure_content_style); |
| 726 |
| 727 // Visit a broken HTTPS url. |
| 728 GURL expired_url(https_test_server_expired.GetURL(std::string("/"))); |
| 729 ui_test_utils::NavigateToURL(browser(), expired_url); |
| 730 |
| 731 // An interstitial should show, and an event for the lock icon on the |
| 732 // interstitial should fire. |
| 733 content::WaitForInterstitialAttach(web_contents); |
| 734 EXPECT_TRUE(web_contents->ShowingInterstitialPage()); |
| 735 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); |
| 736 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 737 INVALID_CERTIFICATE, browser()); |
| 738 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 739 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 740 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 741 |
| 742 // Before clicking through, navigate to a different page, and then go |
| 743 // back to the interstitial. |
| 744 GURL valid_https_url(https_server_.GetURL(std::string("/"))); |
| 745 ui_test_utils::NavigateToURL(browser(), valid_https_url); |
| 746 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| 747 observer.latest_security_style()); |
| 748 EXPECT_EQ(0u, |
| 749 observer.latest_explanations().unauthenticated_explanations.size()); |
| 750 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| 751 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 752 VALID_CERTIFICATE, browser()); |
| 753 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 754 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 755 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 756 |
| 757 // After going back to the interstitial, an event for a broken lock |
| 758 // icon should fire again. |
| 759 ui_test_utils::NavigateToURL(browser(), expired_url); |
| 760 content::WaitForInterstitialAttach(web_contents); |
| 761 EXPECT_TRUE(web_contents->ShowingInterstitialPage()); |
| 762 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); |
| 763 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 764 INVALID_CERTIFICATE, browser()); |
| 765 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 766 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 767 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 768 |
| 769 // Since the next expected style is the same as the previous, clear |
| 770 // the observer (to make sure that the event fires twice and we don't |
| 771 // just see the previous event's style). |
| 772 observer.ClearLatestSecurityStyleAndExplanations(); |
| 773 |
| 774 // Other conditions cannot be tested on this host after clicking |
| 775 // through because once the interstitial is clicked through, all URLs |
| 776 // for this host will remain in a broken state. |
| 777 ProceedThroughInterstitial(web_contents); |
| 778 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); |
| 779 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 780 INVALID_CERTIFICATE, browser()); |
| 781 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 782 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 783 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 784 } |
| 785 |
| 786 // Visit a valid HTTPS page, then a broken HTTPS page, and then go back, |
| 787 // and test that the observed security style matches. |
| 788 IN_PROC_BROWSER_TEST_F(SecurityStyleChangedTest, |
| 789 SecurityStyleChangedObserverGoBack) { |
| 790 ASSERT_TRUE(https_server_.Start()); |
| 791 |
| 792 net::EmbeddedTestServer https_test_server_expired( |
| 793 net::EmbeddedTestServer::TYPE_HTTPS); |
| 794 https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); |
| 795 https_test_server_expired.ServeFilesFromSourceDirectory( |
| 796 base::FilePath(kDocRoot)); |
| 797 ASSERT_TRUE(https_test_server_expired.Start()); |
| 798 |
| 799 content::WebContents* web_contents = |
| 800 browser()->tab_strip_model()->GetActiveWebContents(); |
| 801 SecurityStyleTestObserver observer(web_contents); |
| 802 |
| 803 // Visit a valid HTTPS url. |
| 804 GURL valid_https_url(https_server_.GetURL(std::string("/"))); |
| 805 ui_test_utils::NavigateToURL(browser(), valid_https_url); |
| 806 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| 807 observer.latest_security_style()); |
| 808 EXPECT_EQ(0u, |
| 809 observer.latest_explanations().unauthenticated_explanations.size()); |
| 810 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| 811 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 812 VALID_CERTIFICATE, browser()); |
| 813 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 814 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 815 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 816 |
| 817 // Navigate to a bad HTTPS page on a different host, and then click |
| 818 // Back to verify that the previous good security style is seen again. |
| 819 GURL expired_https_url(https_test_server_expired.GetURL(std::string("/"))); |
| 820 host_resolver()->AddRule("www.example_broken.test", "127.0.0.1"); |
| 821 GURL::Replacements replace_host; |
| 822 replace_host.SetHostStr("www.example_broken.test"); |
| 823 GURL https_url_different_host = |
| 824 expired_https_url.ReplaceComponents(replace_host); |
| 825 |
| 826 ui_test_utils::NavigateToURL(browser(), https_url_different_host); |
| 827 |
| 828 content::WaitForInterstitialAttach(web_contents); |
| 829 EXPECT_TRUE(web_contents->ShowingInterstitialPage()); |
| 830 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID, |
| 831 browser()); |
| 832 ProceedThroughInterstitial(web_contents); |
| 833 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID, |
| 834 browser()); |
| 835 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 836 INVALID_CERTIFICATE, browser()); |
| 837 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 838 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 839 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 840 |
| 841 content::WindowedNotificationObserver back_nav_load_observer( |
| 842 content::NOTIFICATION_LOAD_STOP, |
| 843 content::Source<content::NavigationController>( |
| 844 &web_contents->GetController())); |
| 845 chrome::GoBack(browser(), CURRENT_TAB); |
| 846 back_nav_load_observer.Wait(); |
| 847 |
| 848 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| 849 observer.latest_security_style()); |
| 850 EXPECT_EQ(0u, |
| 851 observer.latest_explanations().unauthenticated_explanations.size()); |
| 852 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| 853 CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| 854 VALID_CERTIFICATE, browser()); |
| 855 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| 856 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| 857 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| 858 } |
| 859 |
| 860 // After AddNonsecureUrlHandler() is called, requests to this hostname |
| 861 // will use obsolete TLS settings. |
| 862 const char kMockNonsecureHostname[] = "example-nonsecure.test"; |
| 863 |
| 864 // A URLRequestMockHTTPJob that mocks a TLS connection with an obsolete |
| 865 // protocol version. |
| 866 class URLRequestObsoleteTLSJob : public net::URLRequestMockHTTPJob { |
| 867 public: |
| 868 URLRequestObsoleteTLSJob(net::URLRequest* request, |
| 869 net::NetworkDelegate* network_delegate, |
| 870 const base::FilePath& file_path, |
| 871 scoped_refptr<net::X509Certificate> cert, |
| 872 scoped_refptr<base::TaskRunner> task_runner) |
| 873 : net::URLRequestMockHTTPJob(request, |
| 874 network_delegate, |
| 875 file_path, |
| 876 task_runner), |
| 877 cert_(std::move(cert)) {} |
| 878 |
| 879 void GetResponseInfo(net::HttpResponseInfo* info) override { |
| 880 net::URLRequestMockHTTPJob::GetResponseInfo(info); |
| 881 net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_1, |
| 882 &info->ssl_info.connection_status); |
| 883 const uint16_t kTlsEcdheRsaWithAes128CbcSha = 0xc013; |
| 884 net::SSLConnectionStatusSetCipherSuite(kTlsEcdheRsaWithAes128CbcSha, |
| 885 &info->ssl_info.connection_status); |
| 886 info->ssl_info.cert = cert_; |
| 887 } |
| 888 |
| 889 protected: |
| 890 ~URLRequestObsoleteTLSJob() override {} |
| 891 |
| 892 private: |
| 893 const scoped_refptr<net::X509Certificate> cert_; |
| 894 |
| 895 DISALLOW_COPY_AND_ASSIGN(URLRequestObsoleteTLSJob); |
| 896 }; |
| 897 |
| 898 // A URLRequestInterceptor that handles requests with |
| 899 // URLRequestObsoleteTLSJob jobs. |
| 900 class URLRequestNonsecureInterceptor : public net::URLRequestInterceptor { |
| 901 public: |
| 902 URLRequestNonsecureInterceptor( |
| 903 const base::FilePath& base_path, |
| 904 scoped_refptr<base::SequencedWorkerPool> worker_pool, |
| 905 scoped_refptr<net::X509Certificate> cert) |
| 906 : base_path_(base_path), |
| 907 worker_pool_(std::move(worker_pool)), |
| 908 cert_(std::move(cert)) {} |
| 909 |
| 910 ~URLRequestNonsecureInterceptor() override {} |
| 911 |
| 912 // net::URLRequestInterceptor: |
| 913 net::URLRequestJob* MaybeInterceptRequest( |
| 914 net::URLRequest* request, |
| 915 net::NetworkDelegate* network_delegate) const override { |
| 916 return new URLRequestObsoleteTLSJob( |
| 917 request, network_delegate, base_path_, cert_, |
| 918 worker_pool_->GetTaskRunnerWithShutdownBehavior( |
| 919 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
| 920 } |
| 921 |
| 922 private: |
| 923 const base::FilePath base_path_; |
| 924 const scoped_refptr<base::SequencedWorkerPool> worker_pool_; |
| 925 const scoped_refptr<net::X509Certificate> cert_; |
| 926 |
| 927 DISALLOW_COPY_AND_ASSIGN(URLRequestNonsecureInterceptor); |
| 928 }; |
| 929 |
| 930 // Installs a handler to serve HTTPS requests to |
| 931 // |kMockNonsecureHostname| with connections that have obsolete TLS |
| 932 // settings. |
| 933 void AddNonsecureUrlHandler( |
| 934 const base::FilePath& base_path, |
| 935 scoped_refptr<net::X509Certificate> cert, |
| 936 scoped_refptr<base::SequencedWorkerPool> worker_pool) { |
| 937 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); |
| 938 filter->AddHostnameInterceptor( |
| 939 "https", kMockNonsecureHostname, |
| 940 std::unique_ptr<net::URLRequestInterceptor>( |
| 941 new URLRequestNonsecureInterceptor(base_path, worker_pool, cert))); |
| 942 } |
| 943 |
| 944 class BrowserTestNonsecureURLRequest : public InProcessBrowserTest { |
| 945 public: |
| 946 BrowserTestNonsecureURLRequest() : InProcessBrowserTest(), cert_(nullptr) {} |
| 947 |
| 948 void SetUpInProcessBrowserTestFixture() override { |
| 949 cert_ = |
| 950 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); |
| 951 ASSERT_TRUE(cert_); |
| 952 } |
| 953 |
| 954 void SetUpOnMainThread() override { |
| 955 base::FilePath serve_file; |
| 956 PathService::Get(chrome::DIR_TEST_DATA, &serve_file); |
| 957 serve_file = serve_file.Append(FILE_PATH_LITERAL("title1.html")); |
| 958 content::BrowserThread::PostTask( |
| 959 content::BrowserThread::IO, FROM_HERE, |
| 960 base::Bind( |
| 961 &AddNonsecureUrlHandler, serve_file, cert_, |
| 962 make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); |
| 963 } |
| 964 |
| 965 private: |
| 966 scoped_refptr<net::X509Certificate> cert_; |
| 967 |
| 968 DISALLOW_COPY_AND_ASSIGN(BrowserTestNonsecureURLRequest); |
| 969 }; |
| 970 |
| 971 // Tests that a connection with obsolete TLS settings does not get a |
| 972 // secure connection explanation. |
| 973 IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, |
| 974 SecurityStyleChangedObserverNonsecureConnection) { |
| 975 content::WebContents* web_contents = |
| 976 browser()->tab_strip_model()->GetActiveWebContents(); |
| 977 SecurityStyleTestObserver observer(web_contents); |
| 978 |
| 979 ui_test_utils::NavigateToURL( |
| 980 browser(), GURL(std::string("https://") + kMockNonsecureHostname)); |
| 981 |
| 982 // The security style of the page doesn't get downgraded for obsolete |
| 983 // TLS settings, so it should remain at SECURITY_STYLE_AUTHENTICATED. |
| 984 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| 985 observer.latest_security_style()); |
| 986 |
| 987 // The messages explaining the security style do, however, get |
| 988 // downgraded: SECURE_PROTOCOL_AND_CIPHERSUITE should not show up when |
| 989 // the TLS settings are obsolete. |
| 990 for (const auto& explanation : |
| 991 observer.latest_explanations().secure_explanations) { |
| 992 EXPECT_NE(l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE), |
| 993 explanation.summary); |
| 994 } |
| 995 } |
| 996 |
538 } // namespace | 997 } // namespace |
OLD | NEW |