Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc

Issue 2448943002: Refactor SecurityStateModel/Clients for simplicity and reusability. (Closed)
Patch Set: Remove *SecurityModelClient. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ssl/chrome_security_state_model_client.h"
6
7 #include <openssl/ssl.h>
8
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/macros.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/ssl/cert_verifier_browser_test.h"
15 #include "chrome/browser/ssl/chrome_security_state_model_client.h"
16 #include "chrome/browser/ssl/ssl_blocking_page.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_commands.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "chrome/test/base/in_process_browser_test.h"
25 #include "chrome/test/base/ui_test_utils.h"
26 #include "components/prefs/pref_service.h"
27 #include "components/security_state/switches.h"
28 #include "content/public/browser/interstitial_page.h"
29 #include "content/public/browser/navigation_controller.h"
30 #include "content/public/browser/navigation_entry.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/notification_types.h"
33 #include "content/public/browser/security_style_explanation.h"
34 #include "content/public/browser/security_style_explanations.h"
35 #include "content/public/browser/ssl_status.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/common/referrer.h"
38 #include "content/public/test/browser_test_utils.h"
39 #include "net/base/net_errors.h"
40 #include "net/cert/cert_status_flags.h"
41 #include "net/cert/cert_verify_result.h"
42 #include "net/cert/mock_cert_verifier.h"
43 #include "net/cert/sct_status_flags.h"
44 #include "net/cert/signed_certificate_timestamp.h"
45 #include "net/cert/signed_certificate_timestamp_and_status.h"
46 #include "net/cert/x509_certificate.h"
47 #include "net/dns/mock_host_resolver.h"
48 #include "net/ssl/ssl_cipher_suite_names.h"
49 #include "net/ssl/ssl_connection_status_flags.h"
50 #include "net/test/cert_test_util.h"
51 #include "net/test/embedded_test_server/embedded_test_server.h"
52 #include "net/test/embedded_test_server/request_handler_util.h"
53 #include "net/test/test_data_directory.h"
54 #include "net/test/url_request/url_request_failed_job.h"
55 #include "net/test/url_request/url_request_mock_http_job.h"
56 #include "net/url_request/url_request_filter.h"
57 #include "net/url_request/url_request_test_util.h"
58 #include "ui/base/l10n/l10n_util.h"
59
60 using security_state::SecurityStateModel;
61
62 namespace {
63
64 enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE };
65
66 const base::FilePath::CharType kDocRoot[] =
67 FILE_PATH_LITERAL("chrome/test/data");
68
69 // A WebContentsObserver useful for testing the SecurityStyleChanged()
70 // method: it keeps track of the latest security style and explanation
71 // that was fired.
72 class SecurityStyleTestObserver : public content::WebContentsObserver {
73 public:
74 explicit SecurityStyleTestObserver(content::WebContents* web_contents)
75 : content::WebContentsObserver(web_contents),
76 latest_security_style_(blink::WebSecurityStyleUnknown) {}
77 ~SecurityStyleTestObserver() override {}
78
79 void SecurityStyleChanged(blink::WebSecurityStyle security_style,
80 const content::SecurityStyleExplanations&
81 security_style_explanations) override {
82 latest_security_style_ = security_style;
83 latest_explanations_ = security_style_explanations;
84 }
85
86 blink::WebSecurityStyle latest_security_style() const {
87 return latest_security_style_;
88 }
89
90 const content::SecurityStyleExplanations& latest_explanations() const {
91 return latest_explanations_;
92 }
93
94 void ClearLatestSecurityStyleAndExplanations() {
95 latest_security_style_ = blink::WebSecurityStyleUnknown;
96 latest_explanations_ = content::SecurityStyleExplanations();
97 }
98
99 private:
100 blink::WebSecurityStyle latest_security_style_;
101 content::SecurityStyleExplanations latest_explanations_;
102
103 DISALLOW_COPY_AND_ASSIGN(SecurityStyleTestObserver);
104 };
105
106 // Check that |observer|'s latest event was for an expired certificate
107 // and that it saw the proper SecurityStyle and explanations.
108 void CheckBrokenSecurityStyle(const SecurityStyleTestObserver& observer,
109 int error,
110 Browser* browser,
111 net::X509Certificate* expected_cert) {
112 EXPECT_EQ(blink::WebSecurityStyleAuthenticationBroken,
113 observer.latest_security_style());
114
115 const content::SecurityStyleExplanations& expired_explanation =
116 observer.latest_explanations();
117 EXPECT_EQ(0u, expired_explanation.unauthenticated_explanations.size());
118 ASSERT_EQ(1u, expired_explanation.broken_explanations.size());
119 EXPECT_FALSE(expired_explanation.pkp_bypassed);
120 EXPECT_TRUE(expired_explanation.info_explanations.empty());
121
122 // Check that the summary and description are as expected.
123 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR),
124 expired_explanation.broken_explanations[0].summary);
125
126 base::string16 error_string = base::UTF8ToUTF16(net::ErrorToString(error));
127 EXPECT_EQ(l10n_util::GetStringFUTF8(
128 IDS_CERTIFICATE_CHAIN_ERROR_DESCRIPTION_FORMAT, error_string),
129 expired_explanation.broken_explanations[0].description);
130
131 // Check the associated certificate.
132 net::X509Certificate* cert = browser->tab_strip_model()
133 ->GetActiveWebContents()
134 ->GetController()
135 .GetActiveEntry()
136 ->GetSSL()
137 .certificate.get();
138 EXPECT_TRUE(cert->Equals(expected_cert));
139 EXPECT_TRUE(expired_explanation.broken_explanations[0].has_certificate);
140 }
141
142 // Checks that the given |secure_explanations| contains an appropriate
143 // explanation if the certificate status is valid.
144 void CheckSecureExplanations(
145 const std::vector<content::SecurityStyleExplanation>& secure_explanations,
146 CertificateStatus cert_status,
147 Browser* browser,
148 net::X509Certificate* expected_cert) {
149 ASSERT_EQ(cert_status == VALID_CERTIFICATE ? 2u : 1u,
150 secure_explanations.size());
151 if (cert_status == VALID_CERTIFICATE) {
152 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE),
153 secure_explanations[0].summary);
154 EXPECT_EQ(
155 l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION),
156 secure_explanations[0].description);
157 net::X509Certificate* cert = browser->tab_strip_model()
158 ->GetActiveWebContents()
159 ->GetController()
160 .GetActiveEntry()
161 ->GetSSL()
162 .certificate.get();
163 EXPECT_TRUE(cert->Equals(expected_cert));
164 EXPECT_TRUE(secure_explanations[0].has_certificate);
165 }
166
167 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_STRONG_SSL_SUMMARY),
168 secure_explanations.back().summary);
169
170 content::WebContents* web_contents =
171 browser->tab_strip_model()->GetActiveWebContents();
172 SecurityStateModel::SecurityInfo security_info;
173 ChromeSecurityStateModelClient::FromWebContents(web_contents)
174 ->GetSecurityInfo(&security_info);
175
176 const char *protocol, *key_exchange, *cipher, *mac;
177 int ssl_version =
178 net::SSLConnectionStatusToVersion(security_info.connection_status);
179 net::SSLVersionToString(&protocol, ssl_version);
180 bool is_aead, is_tls13;
181 uint16_t cipher_suite =
182 net::SSLConnectionStatusToCipherSuite(security_info.connection_status);
183 net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead,
184 &is_tls13, cipher_suite);
185 EXPECT_TRUE(is_aead);
186 EXPECT_EQ(nullptr, mac); // The default secure cipher does not have a MAC.
187 EXPECT_FALSE(is_tls13); // The default secure cipher is not TLS 1.3.
188
189 base::string16 key_exchange_name = base::ASCIIToUTF16(key_exchange);
190 if (security_info.key_exchange_group != 0) {
191 key_exchange_name = l10n_util::GetStringFUTF16(
192 IDS_SSL_KEY_EXCHANGE_WITH_GROUP, key_exchange_name,
193 base::ASCIIToUTF16(
194 SSL_get_curve_name(security_info.key_exchange_group)));
195 }
196
197 std::vector<base::string16> description_replacements;
198 description_replacements.push_back(base::ASCIIToUTF16(protocol));
199 description_replacements.push_back(key_exchange_name);
200 description_replacements.push_back(base::ASCIIToUTF16(cipher));
201 base::string16 secure_description = l10n_util::GetStringFUTF16(
202 IDS_STRONG_SSL_DESCRIPTION, description_replacements, nullptr);
203
204 EXPECT_EQ(secure_description,
205 base::ASCIIToUTF16(secure_explanations.back().description));
206 }
207
208 void CheckSecurityInfoForSecure(
209 content::WebContents* contents,
210 SecurityStateModel::SecurityLevel expect_security_level,
211 SecurityStateModel::SHA1DeprecationStatus expect_sha1_status,
212 SecurityStateModel::ContentStatus expect_mixed_content_status,
213 bool pkp_bypassed,
214 bool expect_cert_error) {
215 ASSERT_TRUE(contents);
216
217 ChromeSecurityStateModelClient* model_client =
218 ChromeSecurityStateModelClient::FromWebContents(contents);
219 ASSERT_TRUE(model_client);
220 SecurityStateModel::SecurityInfo security_info;
221 model_client->GetSecurityInfo(&security_info);
222 EXPECT_EQ(expect_security_level, security_info.security_level);
223 EXPECT_EQ(expect_sha1_status, security_info.sha1_deprecation_status);
224 EXPECT_EQ(expect_mixed_content_status, security_info.mixed_content_status);
225 EXPECT_TRUE(security_info.sct_verify_statuses.empty());
226 EXPECT_TRUE(security_info.scheme_is_cryptographic);
227 EXPECT_EQ(pkp_bypassed, security_info.pkp_bypassed);
228 EXPECT_EQ(expect_cert_error,
229 net::IsCertStatusError(security_info.cert_status));
230 EXPECT_GT(security_info.security_bits, 0);
231 EXPECT_TRUE(!!security_info.certificate);
232 }
233
234 void CheckSecurityInfoForNonSecure(content::WebContents* contents) {
235 ASSERT_TRUE(contents);
236
237 ChromeSecurityStateModelClient* model_client =
238 ChromeSecurityStateModelClient::FromWebContents(contents);
239 ASSERT_TRUE(model_client);
240 SecurityStateModel::SecurityInfo security_info;
241 model_client->GetSecurityInfo(&security_info);
242 EXPECT_EQ(SecurityStateModel::NONE, security_info.security_level);
243 EXPECT_EQ(SecurityStateModel::NO_DEPRECATED_SHA1,
244 security_info.sha1_deprecation_status);
245 EXPECT_EQ(SecurityStateModel::CONTENT_STATUS_NONE,
246 security_info.mixed_content_status);
247 EXPECT_TRUE(security_info.sct_verify_statuses.empty());
248 EXPECT_FALSE(security_info.scheme_is_cryptographic);
249 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status));
250 EXPECT_EQ(-1, security_info.security_bits);
251 EXPECT_FALSE(!!security_info.certificate);
252 }
253
254 void ProceedThroughInterstitial(content::WebContents* tab) {
255 content::InterstitialPage* interstitial_page = tab->GetInterstitialPage();
256 ASSERT_TRUE(interstitial_page);
257 ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
258 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
259 content::WindowedNotificationObserver observer(
260 content::NOTIFICATION_LOAD_STOP,
261 content::Source<content::NavigationController>(&tab->GetController()));
262 interstitial_page->Proceed();
263 observer.Wait();
264 }
265
266 void GetFilePathWithHostAndPortReplacement(
267 const std::string& original_file_path,
268 const net::HostPortPair& host_port_pair,
269 std::string* replacement_path) {
270 base::StringPairs replacement_text;
271 replacement_text.push_back(
272 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
273 net::test_server::GetFilePathWithReplacements(
274 original_file_path, replacement_text, replacement_path);
275 }
276
277 class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest {
278 public:
279 ChromeSecurityStateModelClientTest()
280 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
281 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
282 }
283
284 void SetUpCommandLine(base::CommandLine* command_line) override {
285 // Browser will both run and display insecure content.
286 command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
287 }
288
289 protected:
290 void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status,
291 int net_result) {
292 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate());
293 net::CertVerifyResult verify_result;
294 verify_result.is_issued_by_known_root = true;
295 verify_result.verified_cert = cert;
296 verify_result.cert_status = cert_status;
297
298 mock_cert_verifier()->AddResultForCert(cert, verify_result, net_result);
299 }
300
301 net::EmbeddedTestServer https_server_;
302
303 private:
304 DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClientTest);
305 };
306
307 GURL GetURLWithNonLocalHostname(net::EmbeddedTestServer* server,
308 const std::string& path) {
309 GURL::Replacements replace_host;
310 replace_host.SetHostStr("example.test");
311 return server->GetURL(path).ReplaceComponents(replace_host);
312 }
313
314 class ChromeSecurityStateModelClientTestWithPasswordCcSwitch
315 : public ChromeSecurityStateModelClientTest {
316 public:
317 ChromeSecurityStateModelClientTestWithPasswordCcSwitch()
318 : ChromeSecurityStateModelClientTest() {}
319
320 void SetUpOnMainThread() override {
321 ASSERT_TRUE(embedded_test_server()->Start());
322 ASSERT_TRUE(https_server_.Start());
323 host_resolver()->AddRule("*", embedded_test_server()->GetURL("/").host());
324 SetUpMockCertVerifierForHttpsServer(0, net::OK);
325 }
326
327 void SetUpCommandLine(base::CommandLine* command_line) override {
328 ChromeSecurityStateModelClientTest::SetUpCommandLine(command_line);
329 command_line->AppendSwitchASCII(
330 security_state::switches::kMarkHttpAs,
331 security_state::switches::kMarkHttpWithPasswordsOrCcWithChip);
332 }
333
334 private:
335 DISALLOW_COPY_AND_ASSIGN(
336 ChromeSecurityStateModelClientTestWithPasswordCcSwitch);
337 };
338
339 class SecurityStyleChangedTest : public InProcessBrowserTest {
340 public:
341 SecurityStyleChangedTest()
342 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
343 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
344 }
345
346 void SetUpCommandLine(base::CommandLine* command_line) override {
347 // Browser will both run and display insecure content.
348 command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
349 }
350
351 protected:
352 net::EmbeddedTestServer https_server_;
353
354 private:
355 DISALLOW_COPY_AND_ASSIGN(SecurityStyleChangedTest);
356 };
357
358 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpPage) {
359 ASSERT_TRUE(embedded_test_server()->Start());
360 ui_test_utils::NavigateToURL(
361 browser(), embedded_test_server()->GetURL("/ssl/google.html"));
362 content::WebContents* contents =
363 browser()->tab_strip_model()->GetActiveWebContents();
364 ASSERT_TRUE(contents);
365
366 ChromeSecurityStateModelClient* model_client =
367 ChromeSecurityStateModelClient::FromWebContents(contents);
368 ASSERT_TRUE(model_client);
369 SecurityStateModel::SecurityInfo security_info;
370 model_client->GetSecurityInfo(&security_info);
371 EXPECT_EQ(SecurityStateModel::NONE, security_info.security_level);
372 EXPECT_EQ(SecurityStateModel::NO_DEPRECATED_SHA1,
373 security_info.sha1_deprecation_status);
374 EXPECT_EQ(SecurityStateModel::CONTENT_STATUS_NONE,
375 security_info.mixed_content_status);
376 EXPECT_TRUE(security_info.sct_verify_statuses.empty());
377 EXPECT_FALSE(security_info.scheme_is_cryptographic);
378 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status));
379 EXPECT_FALSE(!!security_info.certificate);
380 EXPECT_EQ(-1, security_info.security_bits);
381 EXPECT_EQ(0, security_info.connection_status);
382 }
383
384 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpsPage) {
385 ASSERT_TRUE(https_server_.Start());
386 SetUpMockCertVerifierForHttpsServer(0, net::OK);
387
388 ui_test_utils::NavigateToURL(browser(),
389 https_server_.GetURL("/ssl/google.html"));
390 CheckSecurityInfoForSecure(
391 browser()->tab_strip_model()->GetActiveWebContents(),
392 SecurityStateModel::SECURE, SecurityStateModel::NO_DEPRECATED_SHA1,
393 SecurityStateModel::CONTENT_STATUS_NONE, false,
394 false /* expect cert status error */);
395 }
396
397 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, SHA1Broken) {
398 ASSERT_TRUE(https_server_.Start());
399 // The test server uses a long-lived cert by default, so a SHA1
400 // signature in it will register as a "broken" condition rather than
401 // "warning".
402 SetUpMockCertVerifierForHttpsServer(net::CERT_STATUS_SHA1_SIGNATURE_PRESENT,
403 net::OK);
404
405 ui_test_utils::NavigateToURL(browser(),
406 https_server_.GetURL("/ssl/google.html"));
407 CheckSecurityInfoForSecure(
408 browser()->tab_strip_model()->GetActiveWebContents(),
409 SecurityStateModel::DANGEROUS, SecurityStateModel::DEPRECATED_SHA1_MAJOR,
410 SecurityStateModel::CONTENT_STATUS_NONE, false,
411 false /* expect cert status error */);
412 }
413
414 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, MixedContent) {
415 ASSERT_TRUE(embedded_test_server()->Start());
416 ASSERT_TRUE(https_server_.Start());
417 SetUpMockCertVerifierForHttpsServer(0, net::OK);
418 host_resolver()->AddRule("example.test",
419 https_server_.GetURL("/title1.html").host());
420
421 net::HostPortPair replacement_pair = embedded_test_server()->host_port_pair();
422 replacement_pair.set_host("example.test");
423
424 // Navigate to an HTTPS page that displays mixed content.
425 std::string replacement_path;
426 GetFilePathWithHostAndPortReplacement(
427 "/ssl/page_displays_insecure_content.html",
428 replacement_pair, &replacement_path);
429 ui_test_utils::NavigateToURL(browser(),
430 https_server_.GetURL(replacement_path));
431 CheckSecurityInfoForSecure(
432 browser()->tab_strip_model()->GetActiveWebContents(),
433 SecurityStateModel::NONE, SecurityStateModel::NO_DEPRECATED_SHA1,
434 SecurityStateModel::CONTENT_STATUS_DISPLAYED, false,
435 false /* expect cert status error */);
436
437 // Navigate to an HTTPS page that displays mixed content dynamically.
438 GetFilePathWithHostAndPortReplacement(
439 "/ssl/page_with_dynamic_insecure_content.html",
440 replacement_pair, &replacement_path);
441 ui_test_utils::NavigateToURL(browser(),
442 https_server_.GetURL(replacement_path));
443 CheckSecurityInfoForSecure(
444 browser()->tab_strip_model()->GetActiveWebContents(),
445 SecurityStateModel::SECURE, SecurityStateModel::NO_DEPRECATED_SHA1,
446 SecurityStateModel::CONTENT_STATUS_NONE, false,
447 false /* expect cert status error */);
448 // Load the insecure image.
449 bool js_result = false;
450 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
451 browser()->tab_strip_model()->GetActiveWebContents(), "loadBadImage();",
452 &js_result));
453 EXPECT_TRUE(js_result);
454 CheckSecurityInfoForSecure(
455 browser()->tab_strip_model()->GetActiveWebContents(),
456 SecurityStateModel::NONE, SecurityStateModel::NO_DEPRECATED_SHA1,
457 SecurityStateModel::CONTENT_STATUS_DISPLAYED, false,
458 false /* expect cert status error */);
459
460 // Navigate to an HTTPS page that runs mixed content.
461 GetFilePathWithHostAndPortReplacement(
462 "/ssl/page_runs_insecure_content.html",
463 replacement_pair, &replacement_path);
464 ui_test_utils::NavigateToURL(browser(),
465 https_server_.GetURL(replacement_path));
466 CheckSecurityInfoForSecure(
467 browser()->tab_strip_model()->GetActiveWebContents(),
468 SecurityStateModel::DANGEROUS, SecurityStateModel::NO_DEPRECATED_SHA1,
469 SecurityStateModel::CONTENT_STATUS_RAN, false,
470 false /* expect cert status error */);
471
472 // Navigate to an HTTPS page that runs and displays mixed content.
473 GetFilePathWithHostAndPortReplacement(
474 "/ssl/page_runs_and_displays_insecure_content.html",
475 replacement_pair, &replacement_path);
476 ui_test_utils::NavigateToURL(browser(),
477 https_server_.GetURL(replacement_path));
478 CheckSecurityInfoForSecure(
479 browser()->tab_strip_model()->GetActiveWebContents(),
480 SecurityStateModel::DANGEROUS, SecurityStateModel::NO_DEPRECATED_SHA1,
481 SecurityStateModel::CONTENT_STATUS_DISPLAYED_AND_RAN, false,
482 false /* expect cert status error */);
483
484 // Navigate to an HTTPS page that runs mixed content in an iframe.
485 net::HostPortPair host_port_pair =
486 net::HostPortPair::FromURL(https_server_.GetURL("/title1.html"));
487 host_port_pair.set_host("different-host.test");
488 host_resolver()->AddRule("different-host.test",
489 https_server_.GetURL("/title1.html").host());
490 host_resolver()->AddRule(
491 "different-http-host.test",
492 embedded_test_server()->GetURL("/title1.html").host());
493 GetFilePathWithHostAndPortReplacement(
494 "/ssl/page_runs_insecure_content_in_iframe.html", host_port_pair,
495 &replacement_path);
496 ui_test_utils::NavigateToURL(browser(),
497 https_server_.GetURL(replacement_path));
498 CheckSecurityInfoForSecure(
499 browser()->tab_strip_model()->GetActiveWebContents(),
500 SecurityStateModel::DANGEROUS, SecurityStateModel::NO_DEPRECATED_SHA1,
501 SecurityStateModel::CONTENT_STATUS_RAN, false,
502 false /* expect cert status error */);
503 }
504
505 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
506 ActiveContentWithCertErrors) {
507 ASSERT_TRUE(https_server_.Start());
508 SetUpMockCertVerifierForHttpsServer(0, net::OK);
509
510 // Navigate to an HTTPS page and simulate active content with
511 // certificate errors.
512 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL("/title1.html"));
513 content::WebContents* web_contents =
514 browser()->tab_strip_model()->GetActiveWebContents();
515 ASSERT_TRUE(web_contents);
516 content::NavigationEntry* entry =
517 web_contents->GetController().GetVisibleEntry();
518 ASSERT_TRUE(entry);
519 entry->GetSSL().content_status |=
520 content::SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS;
521
522 ChromeSecurityStateModelClient* model_client =
523 ChromeSecurityStateModelClient::FromWebContents(web_contents);
524 ASSERT_TRUE(model_client);
525 SecurityStateModel::SecurityInfo security_info;
526 model_client->GetSecurityInfo(&security_info);
527
528 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status));
529 EXPECT_EQ(SecurityStateModel::DANGEROUS, security_info.security_level);
530 EXPECT_EQ(SecurityStateModel::CONTENT_STATUS_RAN,
531 security_info.content_with_cert_errors_status);
532 }
533
534 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
535 PassiveContentWithCertErrors) {
536 ASSERT_TRUE(https_server_.Start());
537 SetUpMockCertVerifierForHttpsServer(0, net::OK);
538
539 // Navigate to an HTTPS page and simulate passive content with
540 // certificate errors.
541 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL("/title1.html"));
542 content::WebContents* web_contents =
543 browser()->tab_strip_model()->GetActiveWebContents();
544 ASSERT_TRUE(web_contents);
545 content::NavigationEntry* entry =
546 web_contents->GetController().GetVisibleEntry();
547 ASSERT_TRUE(entry);
548 entry->GetSSL().content_status |=
549 content::SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS;
550
551 ChromeSecurityStateModelClient* model_client =
552 ChromeSecurityStateModelClient::FromWebContents(web_contents);
553 ASSERT_TRUE(model_client);
554 SecurityStateModel::SecurityInfo security_info;
555 model_client->GetSecurityInfo(&security_info);
556
557 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status));
558 EXPECT_EQ(SecurityStateModel::NONE, security_info.security_level);
559 EXPECT_EQ(SecurityStateModel::CONTENT_STATUS_DISPLAYED,
560 security_info.content_with_cert_errors_status);
561 }
562
563 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
564 ActiveAndPassiveContentWithCertErrors) {
565 ASSERT_TRUE(https_server_.Start());
566 SetUpMockCertVerifierForHttpsServer(0, net::OK);
567
568 // Navigate to an HTTPS page and simulate active and passive content
569 // with certificate errors.
570 ui_test_utils::NavigateToURL(browser(), https_server_.GetURL("/title1.html"));
571 content::WebContents* web_contents =
572 browser()->tab_strip_model()->GetActiveWebContents();
573 ASSERT_TRUE(web_contents);
574 content::NavigationEntry* entry =
575 web_contents->GetController().GetVisibleEntry();
576 ASSERT_TRUE(entry);
577 entry->GetSSL().content_status |=
578 content::SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS;
579 entry->GetSSL().content_status |=
580 content::SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS;
581
582 ChromeSecurityStateModelClient* model_client =
583 ChromeSecurityStateModelClient::FromWebContents(web_contents);
584 ASSERT_TRUE(model_client);
585 SecurityStateModel::SecurityInfo security_info;
586 model_client->GetSecurityInfo(&security_info);
587
588 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status));
589 EXPECT_EQ(SecurityStateModel::DANGEROUS, security_info.security_level);
590 EXPECT_EQ(SecurityStateModel::CONTENT_STATUS_DISPLAYED_AND_RAN,
591 security_info.content_with_cert_errors_status);
592 }
593
594 // Same as the test above but with a long-lived SHA1 cert.
595 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
596 MixedContentWithBrokenSHA1) {
597 ASSERT_TRUE(embedded_test_server()->Start());
598 ASSERT_TRUE(https_server_.Start());
599 // The test server uses a long-lived cert by default, so a SHA1
600 // signature in it will register as a "broken" condition rather than
601 // "warning".
602 SetUpMockCertVerifierForHttpsServer(net::CERT_STATUS_SHA1_SIGNATURE_PRESENT,
603 net::OK);
604
605 host_resolver()->AddRule("example.test",
606 https_server_.GetURL("/title1.html").host());
607
608 net::HostPortPair replacement_pair = embedded_test_server()->host_port_pair();
609 replacement_pair.set_host("example.test");
610
611 // Navigate to an HTTPS page that displays mixed content.
612 std::string replacement_path;
613 GetFilePathWithHostAndPortReplacement(
614 "/ssl/page_displays_insecure_content.html",
615 replacement_pair, &replacement_path);
616 ui_test_utils::NavigateToURL(browser(),
617 https_server_.GetURL(replacement_path));
618 CheckSecurityInfoForSecure(
619 browser()->tab_strip_model()->GetActiveWebContents(),
620 SecurityStateModel::DANGEROUS, SecurityStateModel::DEPRECATED_SHA1_MAJOR,
621 SecurityStateModel::CONTENT_STATUS_DISPLAYED, false,
622 false /* expect cert status error */);
623
624 // Navigate to an HTTPS page that displays mixed content dynamically.
625 GetFilePathWithHostAndPortReplacement(
626 "/ssl/page_with_dynamic_insecure_content.html",
627 replacement_pair, &replacement_path);
628 ui_test_utils::NavigateToURL(browser(),
629 https_server_.GetURL(replacement_path));
630 CheckSecurityInfoForSecure(
631 browser()->tab_strip_model()->GetActiveWebContents(),
632 SecurityStateModel::DANGEROUS, SecurityStateModel::DEPRECATED_SHA1_MAJOR,
633 SecurityStateModel::CONTENT_STATUS_NONE, false,
634 false /* expect cert status error */);
635 // Load the insecure image.
636 bool js_result = false;
637 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
638 browser()->tab_strip_model()->GetActiveWebContents(), "loadBadImage();",
639 &js_result));
640 EXPECT_TRUE(js_result);
641 CheckSecurityInfoForSecure(
642 browser()->tab_strip_model()->GetActiveWebContents(),
643 SecurityStateModel::DANGEROUS, SecurityStateModel::DEPRECATED_SHA1_MAJOR,
644 SecurityStateModel::CONTENT_STATUS_DISPLAYED, false,
645 false /* expect cert status error */);
646
647 // Navigate to an HTTPS page that runs mixed content.
648 GetFilePathWithHostAndPortReplacement(
649 "/ssl/page_runs_insecure_content.html",
650 replacement_pair, &replacement_path);
651 ui_test_utils::NavigateToURL(browser(),
652 https_server_.GetURL(replacement_path));
653 CheckSecurityInfoForSecure(
654 browser()->tab_strip_model()->GetActiveWebContents(),
655 SecurityStateModel::DANGEROUS, SecurityStateModel::DEPRECATED_SHA1_MAJOR,
656 SecurityStateModel::CONTENT_STATUS_RAN, false,
657 false /* expect cert status error */);
658
659 // Navigate to an HTTPS page that runs and displays mixed content.
660 GetFilePathWithHostAndPortReplacement(
661 "/ssl/page_runs_and_displays_insecure_content.html",
662 replacement_pair, &replacement_path);
663 ui_test_utils::NavigateToURL(browser(),
664 https_server_.GetURL(replacement_path));
665 CheckSecurityInfoForSecure(
666 browser()->tab_strip_model()->GetActiveWebContents(),
667 SecurityStateModel::DANGEROUS, SecurityStateModel::DEPRECATED_SHA1_MAJOR,
668 SecurityStateModel::CONTENT_STATUS_DISPLAYED_AND_RAN, false,
669 false /* expect cert status error */);
670 }
671
672 // Tests that the Content Security Policy block-all-mixed-content
673 // directive stops mixed content from running.
674 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
675 MixedContentStrictBlocking) {
676 ASSERT_TRUE(https_server_.Start());
677 SetUpMockCertVerifierForHttpsServer(0, net::OK);
678
679 // Navigate to an HTTPS page that tries to run mixed content in an
680 // iframe, with strict mixed content blocking.
681 std::string replacement_path;
682 net::HostPortPair host_port_pair =
683 net::HostPortPair::FromURL(https_server_.GetURL("/title1.html"));
684 host_port_pair.set_host("different-host.test");
685 host_resolver()->AddRule("different-host.test",
686 https_server_.GetURL("/title1.html").host());
687 GetFilePathWithHostAndPortReplacement(
688 "/ssl/page_runs_insecure_content_in_iframe_with_strict_blocking.html",
689 host_port_pair, &replacement_path);
690 ui_test_utils::NavigateToURL(browser(),
691 https_server_.GetURL(replacement_path));
692 CheckSecurityInfoForSecure(
693 browser()->tab_strip_model()->GetActiveWebContents(),
694 SecurityStateModel::SECURE, SecurityStateModel::NO_DEPRECATED_SHA1,
695 SecurityStateModel::CONTENT_STATUS_NONE, false,
696 false /* expect cert status error */);
697 }
698
699 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, BrokenHTTPS) {
700 ASSERT_TRUE(embedded_test_server()->Start());
701 ASSERT_TRUE(https_server_.Start());
702 SetUpMockCertVerifierForHttpsServer(net::CERT_STATUS_DATE_INVALID,
703 net::ERR_CERT_DATE_INVALID);
704
705 ui_test_utils::NavigateToURL(browser(),
706 https_server_.GetURL("/ssl/google.html"));
707 CheckSecurityInfoForSecure(
708 browser()->tab_strip_model()->GetActiveWebContents(),
709 SecurityStateModel::DANGEROUS, SecurityStateModel::NO_DEPRECATED_SHA1,
710 SecurityStateModel::CONTENT_STATUS_NONE, false,
711 true /* expect cert status error */);
712
713 ProceedThroughInterstitial(
714 browser()->tab_strip_model()->GetActiveWebContents());
715
716 CheckSecurityInfoForSecure(
717 browser()->tab_strip_model()->GetActiveWebContents(),
718 SecurityStateModel::DANGEROUS, SecurityStateModel::NO_DEPRECATED_SHA1,
719 SecurityStateModel::CONTENT_STATUS_NONE, false,
720 true /* expect cert status error */);
721
722 // Navigate to a broken HTTPS page that displays mixed content.
723 std::string replacement_path;
724 GetFilePathWithHostAndPortReplacement(
725 "/ssl/page_displays_insecure_content.html",
726 embedded_test_server()->host_port_pair(), &replacement_path);
727 ui_test_utils::NavigateToURL(browser(),
728 https_server_.GetURL(replacement_path));
729 CheckSecurityInfoForSecure(
730 browser()->tab_strip_model()->GetActiveWebContents(),
731 SecurityStateModel::DANGEROUS, SecurityStateModel::NO_DEPRECATED_SHA1,
732 SecurityStateModel::CONTENT_STATUS_DISPLAYED, false,
733 true /* expect cert status error */);
734 }
735
736 const char kReportURI[] = "https://report-hpkp.test";
737
738 class PKPModelClientTest : public ChromeSecurityStateModelClientTest {
739 public:
740 void SetUpOnMainThread() override {
741 ASSERT_TRUE(https_server_.Start());
742 url_request_context_getter_ = browser()->profile()->GetRequestContext();
743 content::BrowserThread::PostTask(
744 content::BrowserThread::IO, FROM_HERE,
745 base::Bind(&PKPModelClientTest::SetUpOnIOThread,
746 base::Unretained(this)));
747 }
748
749 void SetUpOnIOThread() {
750 net::URLRequestContext* request_context =
751 url_request_context_getter_->GetURLRequestContext();
752 net::TransportSecurityState* security_state =
753 request_context->transport_security_state();
754
755 base::Time expiration =
756 base::Time::Now() + base::TimeDelta::FromSeconds(10000);
757
758 net::HashValue hash(net::HASH_VALUE_SHA256);
759 memset(hash.data(), 0x99, hash.size());
760 net::HashValueVector hashes;
761 hashes.push_back(hash);
762
763 security_state->AddHPKP(https_server_.host_port_pair().host(), expiration,
764 true, hashes, GURL(kReportURI));
765 }
766
767 protected:
768 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
769 };
770
771 IN_PROC_BROWSER_TEST_F(PKPModelClientTest, PKPBypass) {
772 content::WebContents* web_contents =
773 browser()->tab_strip_model()->GetActiveWebContents();
774 SecurityStyleTestObserver observer(web_contents);
775
776 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate());
777 net::CertVerifyResult verify_result;
778 // PKP is bypassed when |is_issued_by_known_root| is false.
779 verify_result.is_issued_by_known_root = false;
780 verify_result.verified_cert = cert;
781 net::HashValue hash(net::HASH_VALUE_SHA256);
782 memset(hash.data(), 1, hash.size());
783 verify_result.public_key_hashes.push_back(hash);
784
785 mock_cert_verifier()->AddResultForCert(cert, verify_result, net::OK);
786
787 ui_test_utils::NavigateToURL(browser(),
788 https_server_.GetURL("/ssl/google.html"));
789
790 CheckSecurityInfoForSecure(
791 browser()->tab_strip_model()->GetActiveWebContents(),
792 SecurityStateModel::SECURE, SecurityStateModel::NO_DEPRECATED_SHA1,
793 SecurityStateModel::CONTENT_STATUS_NONE, true, false);
794
795 const content::SecurityStyleExplanations& explanation =
796 observer.latest_explanations();
797 EXPECT_TRUE(explanation.pkp_bypassed);
798 EXPECT_FALSE(explanation.info_explanations.empty());
799 }
800
801 IN_PROC_BROWSER_TEST_F(PKPModelClientTest, PKPEnforced) {
802 content::WebContents* web_contents =
803 browser()->tab_strip_model()->GetActiveWebContents();
804 SecurityStyleTestObserver observer(web_contents);
805
806 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate());
807 net::CertVerifyResult verify_result;
808 // PKP requires |is_issued_by_known_root| to be true.
809 verify_result.is_issued_by_known_root = true;
810 verify_result.verified_cert = cert;
811 net::HashValue hash(net::HASH_VALUE_SHA256);
812 memset(hash.data(), 1, hash.size());
813 verify_result.public_key_hashes.push_back(hash);
814
815 mock_cert_verifier()->AddResultForCert(cert, verify_result, net::OK);
816
817 ui_test_utils::NavigateToURL(browser(),
818 https_server_.GetURL("/ssl/google.html"));
819 CheckBrokenSecurityStyle(observer, net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN,
820 browser(), cert.get());
821 }
822
823 // Fails requests with ERR_IO_PENDING. Can be used to simulate a navigation
824 // that never stops loading.
825 class PendingJobInterceptor : public net::URLRequestInterceptor {
826 public:
827 PendingJobInterceptor() {}
828 ~PendingJobInterceptor() override {}
829
830 // URLRequestInterceptor implementation
831 net::URLRequestJob* MaybeInterceptRequest(
832 net::URLRequest* request,
833 net::NetworkDelegate* network_delegate) const override {
834 return new net::URLRequestFailedJob(request, network_delegate,
835 net::ERR_IO_PENDING);
836 }
837
838 private:
839 DISALLOW_COPY_AND_ASSIGN(PendingJobInterceptor);
840 };
841
842 void InstallLoadingInterceptor(const std::string& host) {
843 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
844 filter->AddHostnameInterceptor(
845 "http", host,
846 std::unique_ptr<net::URLRequestInterceptor>(new PendingJobInterceptor()));
847 }
848
849 class SecurityStateModelLoadingTest
850 : public ChromeSecurityStateModelClientTest {
851 public:
852 SecurityStateModelLoadingTest() : ChromeSecurityStateModelClientTest() {}
853 ~SecurityStateModelLoadingTest() override{};
854
855 protected:
856 void SetUpOnMainThread() override {
857 ASSERT_TRUE(embedded_test_server()->Start());
858
859 content::BrowserThread::PostTask(
860 content::BrowserThread::IO, FROM_HERE,
861 base::Bind(&InstallLoadingInterceptor,
862 embedded_test_server()->GetURL("/title1.html").host()));
863 }
864
865 DISALLOW_COPY_AND_ASSIGN(SecurityStateModelLoadingTest);
866 };
867
868 // Tests that navigation state changes cause the security state to be
869 // updated.
870 IN_PROC_BROWSER_TEST_F(SecurityStateModelLoadingTest, NavigationStateChanges) {
871 ASSERT_TRUE(https_server_.Start());
872 SetUpMockCertVerifierForHttpsServer(0, net::OK);
873
874 // Navigate to an HTTPS page.
875 ui_test_utils::NavigateToURL(browser(),
876 https_server_.GetURL("/ssl/google.html"));
877 CheckSecurityInfoForSecure(
878 browser()->tab_strip_model()->GetActiveWebContents(),
879 SecurityStateModel::SECURE, SecurityStateModel::NO_DEPRECATED_SHA1,
880 SecurityStateModel::CONTENT_STATUS_NONE, false,
881 false /* expect cert status error */);
882
883 // Navigate to a page that doesn't finish loading. Test that the
884 // security state is neutral while the page is loading.
885 browser()->OpenURL(content::OpenURLParams(
886 embedded_test_server()->GetURL("/title1.html"), content::Referrer(),
887 WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
888 CheckSecurityInfoForNonSecure(
889 browser()->tab_strip_model()->GetActiveWebContents());
890 }
891
892 // Tests that the NavigationEntry's flags for nonsecure password/credit
893 // card inputs are reflected in the VisibleSecurityState.
894 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
895 VisibleSecurityStateNonsecureFormInputs) {
896 ASSERT_TRUE(https_server_.Start());
897 ui_test_utils::NavigateToURL(browser(),
898 https_server_.GetURL("/ssl/google.html"));
899
900 content::WebContents* contents =
901 browser()->tab_strip_model()->GetActiveWebContents();
902 ASSERT_TRUE(contents);
903
904 ChromeSecurityStateModelClient* model_client =
905 ChromeSecurityStateModelClient::FromWebContents(contents);
906 ASSERT_TRUE(model_client);
907
908 // First, test that if the flags aren't set on the NavigationEntry,
909 // then they also aren't set on the VisibleSecurityState.
910 content::SSLStatus& ssl_status =
911 contents->GetController().GetVisibleEntry()->GetSSL();
912 ASSERT_FALSE(ssl_status.content_status &
913 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
914 ASSERT_FALSE(ssl_status.content_status &
915 content::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
916 SecurityStateModel::VisibleSecurityState
917 visible_security_state_no_sensitive_inputs;
918 model_client->GetVisibleSecurityState(
919 &visible_security_state_no_sensitive_inputs);
920 EXPECT_FALSE(visible_security_state_no_sensitive_inputs
921 .displayed_password_field_on_http);
922 EXPECT_FALSE(visible_security_state_no_sensitive_inputs
923 .displayed_credit_card_field_on_http);
924
925 // Now, set the flags on the NavigationEntry and test that they are
926 // reflected in the VisibleSecurityState.
927 ssl_status.content_status |=
928 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP;
929 ssl_status.content_status |=
930 content::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP;
931 SecurityStateModel::VisibleSecurityState
932 visible_security_state_sensitive_inputs;
933 model_client->GetVisibleSecurityState(
934 &visible_security_state_sensitive_inputs);
935 EXPECT_TRUE(
936 visible_security_state_sensitive_inputs.displayed_password_field_on_http);
937 EXPECT_TRUE(visible_security_state_sensitive_inputs
938 .displayed_credit_card_field_on_http);
939 }
940
941 // Tests that when a visible password field is detected on an HTTP page
942 // load, and when the command-line flag is set, the security level is
943 // downgraded to HTTP_SHOW_WARNING.
944 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
945 PasswordSecurityLevelDowngraded) {
946 content::WebContents* contents =
947 browser()->tab_strip_model()->GetActiveWebContents();
948 ASSERT_TRUE(contents);
949
950 ChromeSecurityStateModelClient* model_client =
951 ChromeSecurityStateModelClient::FromWebContents(contents);
952 ASSERT_TRUE(model_client);
953
954 ui_test_utils::NavigateToURL(
955 browser(), GetURLWithNonLocalHostname(embedded_test_server(),
956 "/password/simple_password.html"));
957 security_state::SecurityStateModel::SecurityInfo security_info;
958 model_client->GetSecurityInfo(&security_info);
959 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
960 security_info.security_level);
961
962 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
963 ASSERT_TRUE(entry);
964 EXPECT_TRUE(entry->GetSSL().content_status &
965 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
966 }
967
968 // Tests that when an invisible password field is present on an HTTP page
969 // load, and when the command-line flag is set, the security level is
970 // *not* downgraded to HTTP_SHOW_WARNING.
971 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
972 PasswordSecurityLevelNotDowngradedForInvisibleInput) {
973 content::WebContents* contents =
974 browser()->tab_strip_model()->GetActiveWebContents();
975 ASSERT_TRUE(contents);
976
977 ChromeSecurityStateModelClient* model_client =
978 ChromeSecurityStateModelClient::FromWebContents(contents);
979 ASSERT_TRUE(model_client);
980
981 ui_test_utils::NavigateToURL(
982 browser(),
983 GetURLWithNonLocalHostname(embedded_test_server(),
984 "/password/invisible_password.html"));
985 security_state::SecurityStateModel::SecurityInfo security_info;
986 model_client->GetSecurityInfo(&security_info);
987 EXPECT_EQ(security_state::SecurityStateModel::NONE,
988 security_info.security_level);
989
990 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
991 ASSERT_TRUE(entry);
992 EXPECT_FALSE(entry->GetSSL().content_status &
993 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
994 }
995
996 // Tests that when a visible password field is detected inside an iframe
997 // on an HTTP page load, and when the command-line flag is set, the
998 // security level is downgraded to HTTP_SHOW_WARNING.
999 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
1000 PasswordSecurityLevelDowngradedFromIframe) {
1001 content::WebContents* contents =
1002 browser()->tab_strip_model()->GetActiveWebContents();
1003 ASSERT_TRUE(contents);
1004
1005 ChromeSecurityStateModelClient* model_client =
1006 ChromeSecurityStateModelClient::FromWebContents(contents);
1007 ASSERT_TRUE(model_client);
1008
1009 ui_test_utils::NavigateToURL(
1010 browser(),
1011 GetURLWithNonLocalHostname(embedded_test_server(),
1012 "/password/simple_password_in_iframe.html"));
1013 security_state::SecurityStateModel::SecurityInfo security_info;
1014 model_client->GetSecurityInfo(&security_info);
1015 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1016 security_info.security_level);
1017
1018 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1019 ASSERT_TRUE(entry);
1020 EXPECT_TRUE(entry->GetSSL().content_status &
1021 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
1022 }
1023
1024 // Tests that when a visible password field is detected inside an iframe
1025 // on an HTTP page load, and when the command-line flag is set, the
1026 // security level is downgraded to HTTP_SHOW_WARNING, even if the iframe
1027 // itself was loaded over HTTPS.
1028 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
1029 PasswordSecurityLevelDowngradedFromHttpsIframe) {
1030 content::WebContents* contents =
1031 browser()->tab_strip_model()->GetActiveWebContents();
1032 ASSERT_TRUE(contents);
1033
1034 ChromeSecurityStateModelClient* model_client =
1035 ChromeSecurityStateModelClient::FromWebContents(contents);
1036 ASSERT_TRUE(model_client);
1037
1038 // Navigate to an HTTP URL, which loads an iframe using the host and port of
1039 // |https_server_|.
1040 std::string replacement_path;
1041 GetFilePathWithHostAndPortReplacement(
1042 "/password/simple_password_in_https_iframe.html",
1043 https_server_.host_port_pair(), &replacement_path);
1044 ui_test_utils::NavigateToURL(
1045 browser(),
1046 GetURLWithNonLocalHostname(embedded_test_server(), replacement_path));
1047 security_state::SecurityStateModel::SecurityInfo security_info;
1048 model_client->GetSecurityInfo(&security_info);
1049 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1050 security_info.security_level);
1051
1052 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1053 ASSERT_TRUE(entry);
1054 EXPECT_TRUE(entry->GetSSL().content_status &
1055 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
1056 }
1057
1058 // Tests that when a visible password field is detected on an HTTP page
1059 // load, and when the command-line flag is *not* set, the security level is
1060 // *not* downgraded to HTTP_SHOW_WARNING.
1061 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
1062 PasswordSecurityLevelNotDowngradedWithoutSwitch) {
1063 ASSERT_TRUE(embedded_test_server()->Start());
1064 host_resolver()->AddRule("*", embedded_test_server()->GetURL("/").host());
1065
1066 content::WebContents* contents =
1067 browser()->tab_strip_model()->GetActiveWebContents();
1068 ASSERT_TRUE(contents);
1069
1070 ChromeSecurityStateModelClient* model_client =
1071 ChromeSecurityStateModelClient::FromWebContents(contents);
1072 ASSERT_TRUE(model_client);
1073
1074 ui_test_utils::NavigateToURL(
1075 browser(), GetURLWithNonLocalHostname(embedded_test_server(),
1076 "/password/simple_password.html"));
1077 // The security level should not be HTTP_SHOW_WARNING, because the
1078 // command-line switch was not set.
1079 security_state::SecurityStateModel::SecurityInfo security_info;
1080 model_client->GetSecurityInfo(&security_info);
1081 EXPECT_EQ(security_state::SecurityStateModel::NONE,
1082 security_info.security_level);
1083
1084 // The appropriate SSLStatus flags should be set, however.
1085 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1086 ASSERT_TRUE(entry);
1087 EXPECT_TRUE(entry->GetSSL().content_status &
1088 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
1089 }
1090
1091 // Tests that when a visible password field is detected on an HTTPS page
1092 // load, and when the command-line flag is set, the security level is
1093 // *not* downgraded to HTTP_SHOW_WARNING.
1094 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
1095 PasswordSecurityLevelNotDowngradedOnHttps) {
1096 content::WebContents* contents =
1097 browser()->tab_strip_model()->GetActiveWebContents();
1098 ASSERT_TRUE(contents);
1099
1100 ChromeSecurityStateModelClient* model_client =
1101 ChromeSecurityStateModelClient::FromWebContents(contents);
1102 ASSERT_TRUE(model_client);
1103
1104 GURL url = GetURLWithNonLocalHostname(&https_server_,
1105 "/password/simple_password.html");
1106 ui_test_utils::NavigateToURL(browser(), url);
1107 // The security level should not be HTTP_SHOW_WARNING, because the page was
1108 // HTTPS instead of HTTP.
1109 security_state::SecurityStateModel::SecurityInfo security_info;
1110 model_client->GetSecurityInfo(&security_info);
1111 EXPECT_EQ(security_state::SecurityStateModel::SECURE,
1112 security_info.security_level);
1113
1114 // The SSLStatus flags should only be set if the top-level page load was HTTP,
1115 // which it was not in this case.
1116 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1117 ASSERT_TRUE(entry);
1118 EXPECT_FALSE(entry->GetSSL().content_status &
1119 content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
1120 }
1121
1122 // A Browser subclass that keeps track of messages that have been
1123 // added to the console. Messages can be retrieved or cleared with
1124 // console_messages() and ClearConsoleMessages(). The user of this class
1125 // can set a callback to run when the next console message notification
1126 // arrives.
1127 class ConsoleWebContentsDelegate : public Browser {
1128 public:
1129 explicit ConsoleWebContentsDelegate(const Browser::CreateParams& params)
1130 : Browser(params) {}
1131 ~ConsoleWebContentsDelegate() override {}
1132
1133 const std::vector<base::string16>& console_messages() const {
1134 return console_messages_;
1135 }
1136
1137 void set_console_message_callback(const base::Closure& callback) {
1138 console_message_callback_ = callback;
1139 }
1140
1141 void ClearConsoleMessages() { console_messages_.clear(); }
1142
1143 // content::WebContentsDelegate
1144 bool AddMessageToConsole(content::WebContents* source,
1145 int32_t level,
1146 const base::string16& message,
1147 int32_t line_no,
1148 const base::string16& source_id) override {
1149 console_messages_.push_back(message);
1150 if (!console_message_callback_.is_null()) {
1151 console_message_callback_.Run();
1152 console_message_callback_.Reset();
1153 }
1154 return true;
1155 }
1156
1157 private:
1158 std::vector<base::string16> console_messages_;
1159 base::Closure console_message_callback_;
1160
1161 DISALLOW_COPY_AND_ASSIGN(ConsoleWebContentsDelegate);
1162 };
1163
1164 // Checks that |delegate| has observed exactly one console message for
1165 // HTTP_SHOW_WARNING. To avoid brittleness, this just looks for keywords
1166 // in the string rather than the exact text.
1167 void CheckForOneHttpWarningConsoleMessage(
1168 ConsoleWebContentsDelegate* delegate) {
1169 const std::vector<base::string16>& messages = delegate->console_messages();
1170 ASSERT_EQ(1u, messages.size());
1171 EXPECT_NE(base::string16::npos,
1172 messages[0].find(base::ASCIIToUTF16("warning has been added")));
1173 }
1174
1175 // Checks that |delegate| has observed exactly one console message for
1176 // NONE that will be HTTP_SHOW_WARNING in future. To avoid brittleness,
1177 // this just looks for keywords in the string rather than the exact
1178 // text.
1179 void CheckForOneFutureHttpWarningConsoleMessage(
1180 ConsoleWebContentsDelegate* delegate) {
1181 const std::vector<base::string16>& messages = delegate->console_messages();
1182 ASSERT_EQ(1u, messages.size());
1183 EXPECT_NE(base::string16::npos,
1184 messages[0].find(base::ASCIIToUTF16("warning will be added")));
1185 }
1186
1187 // Tests that console messages are printed upon a call to
1188 // GetSecurityInfo() on an HTTP_SHOW_WARNING page, exactly once per
1189 // main-frame navigation.
1190 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
1191 ConsoleMessage) {
1192 ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate(
1193 Browser::CreateParams(browser()->profile()));
1194 content::WebContents* original_contents =
1195 browser()->tab_strip_model()->GetActiveWebContents();
1196 content::WebContents* contents =
1197 content::WebContents::Create(content::WebContents::CreateParams(
1198 original_contents->GetBrowserContext()));
1199 ASSERT_TRUE(contents);
1200 contents->SetDelegate(delegate);
1201 delegate->tab_strip_model()->AppendWebContents(contents, true);
1202 int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents);
1203 delegate->tab_strip_model()->ActivateTabAt(index, true);
1204 ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents());
1205
1206 // Navigate to an HTTP page. Use a non-local hostname so that is it
1207 // not considered secure.
1208 GURL http_url =
1209 GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html");
1210 ui_test_utils::NavigateToURL(delegate, http_url);
1211 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1212 ASSERT_TRUE(entry);
1213 EXPECT_EQ(http_url, entry->GetURL());
1214 EXPECT_TRUE(delegate->console_messages().empty());
1215
1216 // Trigger the HTTP_SHOW_WARNING state.
1217 base::RunLoop first_message;
1218 delegate->set_console_message_callback(first_message.QuitClosure());
1219 contents->OnPasswordInputShownOnHttp();
1220 first_message.Run();
1221
1222 // Check that the HTTP_SHOW_WARNING state was actually triggered.
1223 ChromeSecurityStateModelClient* client =
1224 ChromeSecurityStateModelClient::FromWebContents(contents);
1225 ASSERT_TRUE(client);
1226 security_state::SecurityStateModel::SecurityInfo security_info;
1227 client->GetSecurityInfo(&security_info);
1228 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1229 security_info.security_level);
1230
1231 // Check that the expected console message is present.
1232 ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate));
1233 delegate->ClearConsoleMessages();
1234
1235 // Two subsequent triggers of VisibleSSLStateChanged -- one on the
1236 // same navigation and one on another navigation -- should only result
1237 // in one additional console message.
1238 contents->OnCreditCardInputShownOnHttp();
1239 GURL second_http_url =
1240 GetURLWithNonLocalHostname(embedded_test_server(), "/title2.html");
1241 ui_test_utils::NavigateToURL(delegate, second_http_url);
1242 entry = contents->GetController().GetVisibleEntry();
1243 ASSERT_TRUE(entry);
1244 EXPECT_EQ(second_http_url, entry->GetURL());
1245
1246 base::RunLoop second_message;
1247 delegate->set_console_message_callback(second_message.QuitClosure());
1248 contents->OnPasswordInputShownOnHttp();
1249 second_message.Run();
1250
1251 client->GetSecurityInfo(&security_info);
1252 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1253 security_info.security_level);
1254
1255 ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate));
1256 }
1257
1258 // Tests that console messages are printed upon a call to
1259 // GetSecurityInfo() on a NONE page that will be marked
1260 // HTTP_SHOW_WARNING in future, exactly once per main-frame navigation.
1261 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, ConsoleMessage) {
1262 ASSERT_TRUE(embedded_test_server()->Start());
1263 host_resolver()->AddRule("*", embedded_test_server()->GetURL("/").host());
1264 ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate(
1265 Browser::CreateParams(browser()->profile()));
1266 content::WebContents* original_contents =
1267 browser()->tab_strip_model()->GetActiveWebContents();
1268 content::WebContents* contents =
1269 content::WebContents::Create(content::WebContents::CreateParams(
1270 original_contents->GetBrowserContext()));
1271 ASSERT_TRUE(contents);
1272 contents->SetDelegate(delegate);
1273 delegate->tab_strip_model()->AppendWebContents(contents, true);
1274 int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents);
1275 delegate->tab_strip_model()->ActivateTabAt(index, true);
1276 ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents());
1277
1278 // Navigate to an HTTP page. Use a non-local hostname so that is it
1279 // not considered secure.
1280 GURL http_url =
1281 GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html");
1282 ui_test_utils::NavigateToURL(delegate, http_url);
1283 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1284 ASSERT_TRUE(entry);
1285 EXPECT_EQ(http_url, entry->GetURL());
1286 EXPECT_TRUE(delegate->console_messages().empty());
1287
1288 // Trigger the a state that will be marked as HTTP_SHOW_WARNING in future.
1289 base::RunLoop first_message;
1290 delegate->set_console_message_callback(first_message.QuitClosure());
1291 contents->OnPasswordInputShownOnHttp();
1292 first_message.Run();
1293
1294 // Check that the correct state was actually triggered.
1295 ChromeSecurityStateModelClient* client =
1296 ChromeSecurityStateModelClient::FromWebContents(contents);
1297 ASSERT_TRUE(client);
1298 security_state::SecurityStateModel::SecurityInfo security_info;
1299 client->GetSecurityInfo(&security_info);
1300 EXPECT_EQ(security_state::SecurityStateModel::NONE,
1301 security_info.security_level);
1302 EXPECT_TRUE(security_info.displayed_private_user_data_input_on_http);
1303
1304 // Check that the expected console message is present.
1305 ASSERT_NO_FATAL_FAILURE(CheckForOneFutureHttpWarningConsoleMessage(delegate));
1306 delegate->ClearConsoleMessages();
1307
1308 // Two subsequent triggers of VisibleSSLStateChanged -- one on the
1309 // same navigation and one on another navigation -- should only result
1310 // in one additional console message.
1311 contents->OnCreditCardInputShownOnHttp();
1312 GURL second_http_url =
1313 GetURLWithNonLocalHostname(embedded_test_server(), "/title2.html");
1314 ui_test_utils::NavigateToURL(delegate, second_http_url);
1315 entry = contents->GetController().GetVisibleEntry();
1316 ASSERT_TRUE(entry);
1317 EXPECT_EQ(second_http_url, entry->GetURL());
1318
1319 base::RunLoop second_message;
1320 delegate->set_console_message_callback(second_message.QuitClosure());
1321 contents->OnPasswordInputShownOnHttp();
1322 second_message.Run();
1323
1324 client->GetSecurityInfo(&security_info);
1325 EXPECT_EQ(security_state::SecurityStateModel::NONE,
1326 security_info.security_level);
1327 EXPECT_TRUE(security_info.displayed_private_user_data_input_on_http);
1328
1329 ASSERT_NO_FATAL_FAILURE(CheckForOneFutureHttpWarningConsoleMessage(delegate));
1330 }
1331
1332 // Tests that additional HTTP_SHOW_WARNING console messages are not
1333 // printed after subframe navigations.
1334 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
1335 ConsoleMessageNotPrintedForFrameNavigation) {
1336 ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate(
1337 Browser::CreateParams(browser()->profile()));
1338 content::WebContents* original_contents =
1339 browser()->tab_strip_model()->GetActiveWebContents();
1340 content::WebContents* contents =
1341 content::WebContents::Create(content::WebContents::CreateParams(
1342 original_contents->GetBrowserContext()));
1343 ASSERT_TRUE(contents);
1344 contents->SetDelegate(delegate);
1345 delegate->tab_strip_model()->AppendWebContents(contents, true);
1346 int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents);
1347 delegate->tab_strip_model()->ActivateTabAt(index, true);
1348 ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents());
1349
1350 // Navigate to an HTTP page. Use a non-local hostname so that is it
1351 // not considered secure.
1352 GURL http_url = GetURLWithNonLocalHostname(embedded_test_server(),
1353 "/ssl/page_with_frame.html");
1354 ui_test_utils::NavigateToURL(delegate, http_url);
1355 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1356 ASSERT_TRUE(entry);
1357 EXPECT_EQ(http_url, entry->GetURL());
1358 EXPECT_TRUE(delegate->console_messages().empty());
1359
1360 // Trigger the HTTP_SHOW_WARNING state.
1361 base::RunLoop first_message;
1362 delegate->set_console_message_callback(first_message.QuitClosure());
1363 contents->OnPasswordInputShownOnHttp();
1364 first_message.Run();
1365
1366 // Check that the HTTP_SHOW_WARNING state was actually triggered.
1367 ChromeSecurityStateModelClient* client =
1368 ChromeSecurityStateModelClient::FromWebContents(contents);
1369 ASSERT_TRUE(client);
1370 security_state::SecurityStateModel::SecurityInfo security_info;
1371 client->GetSecurityInfo(&security_info);
1372 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1373 security_info.security_level);
1374
1375 // Check that the expected console message is present.
1376 ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate));
1377 delegate->ClearConsoleMessages();
1378
1379 // Navigate the subframe and trigger VisibleSSLStateChanged
1380 // again. While the security level is still HTTP_SHOW_WARNING, an
1381 // additional console message should not be logged because there was
1382 // already a console message logged for the current main-frame
1383 // navigation.
1384 content::WindowedNotificationObserver subframe_observer(
1385 content::NOTIFICATION_LOAD_STOP,
1386 content::Source<content::NavigationController>(
1387 &contents->GetController()));
1388 EXPECT_TRUE(content::ExecuteScript(
1389 contents, "document.getElementById('navFrame').src = '/title2.html';"));
1390 subframe_observer.Wait();
1391 contents->OnCreditCardInputShownOnHttp();
1392 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1393 security_info.security_level);
1394
1395 // Do a main frame navigation and then trigger HTTP_SHOW_WARNING
1396 // again. From the above subframe navigation and this main-frame
1397 // navigation, exactly one console message is expected.
1398 GURL second_http_url =
1399 GetURLWithNonLocalHostname(embedded_test_server(), "/title2.html");
1400 ui_test_utils::NavigateToURL(delegate, second_http_url);
1401 entry = contents->GetController().GetVisibleEntry();
1402 ASSERT_TRUE(entry);
1403 EXPECT_EQ(second_http_url, entry->GetURL());
1404
1405 base::RunLoop second_message;
1406 delegate->set_console_message_callback(second_message.QuitClosure());
1407 contents->OnPasswordInputShownOnHttp();
1408 second_message.Run();
1409
1410 client->GetSecurityInfo(&security_info);
1411 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1412 security_info.security_level);
1413 ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate));
1414 }
1415
1416 // Tests that additional HTTP_SHOW_WARNING console messages are not
1417 // printed after pushState navigations.
1418 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch,
1419 ConsoleMessageNotPrintedForPushStateNavigation) {
1420 ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate(
1421 Browser::CreateParams(browser()->profile()));
1422 content::WebContents* original_contents =
1423 browser()->tab_strip_model()->GetActiveWebContents();
1424 content::WebContents* contents =
1425 content::WebContents::Create(content::WebContents::CreateParams(
1426 original_contents->GetBrowserContext()));
1427 ASSERT_TRUE(contents);
1428 contents->SetDelegate(delegate);
1429 delegate->tab_strip_model()->AppendWebContents(contents, true);
1430 int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents);
1431 delegate->tab_strip_model()->ActivateTabAt(index, true);
1432 ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents());
1433
1434 // Navigate to an HTTP page. Use a non-local hostname so that is it
1435 // not considered secure.
1436 GURL http_url =
1437 GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html");
1438 ui_test_utils::NavigateToURL(delegate, http_url);
1439 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
1440 ASSERT_TRUE(entry);
1441 EXPECT_EQ(http_url, entry->GetURL());
1442 EXPECT_TRUE(delegate->console_messages().empty());
1443
1444 // Trigger the HTTP_SHOW_WARNING state.
1445 base::RunLoop first_message;
1446 delegate->set_console_message_callback(first_message.QuitClosure());
1447 contents->OnPasswordInputShownOnHttp();
1448 first_message.Run();
1449
1450 // Check that the HTTP_SHOW_WARNING state was actually triggered.
1451 ChromeSecurityStateModelClient* client =
1452 ChromeSecurityStateModelClient::FromWebContents(contents);
1453 ASSERT_TRUE(client);
1454 security_state::SecurityStateModel::SecurityInfo security_info;
1455 client->GetSecurityInfo(&security_info);
1456 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1457 security_info.security_level);
1458
1459 // Check that the expected console message is present.
1460 ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate));
1461 delegate->ClearConsoleMessages();
1462
1463 // Navigate with pushState and trigger VisibleSSLStateChanged
1464 // again. While the security level is still HTTP_SHOW_WARNING, an
1465 // additional console message should not be logged because there was
1466 // already a console message logged for the current main-frame
1467 // navigation.
1468 EXPECT_TRUE(content::ExecuteScript(
1469 contents, "history.pushState({ foo: 'bar' }, 'foo', 'bar');"));
1470 contents->OnCreditCardInputShownOnHttp();
1471 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1472 security_info.security_level);
1473
1474 // Do a main frame navigation and then trigger HTTP_SHOW_WARNING
1475 // again. From the above pushState navigation and this main-frame
1476 // navigation, exactly one console message is expected.
1477 GURL second_http_url =
1478 GetURLWithNonLocalHostname(embedded_test_server(), "/title2.html");
1479 ui_test_utils::NavigateToURL(delegate, second_http_url);
1480 entry = contents->GetController().GetVisibleEntry();
1481 ASSERT_TRUE(entry);
1482 EXPECT_EQ(second_http_url, entry->GetURL());
1483
1484 base::RunLoop second_message;
1485 delegate->set_console_message_callback(second_message.QuitClosure());
1486 contents->OnPasswordInputShownOnHttp();
1487 second_message.Run();
1488
1489 client->GetSecurityInfo(&security_info);
1490 EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING,
1491 security_info.security_level);
1492 ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate));
1493 }
1494
1495 // Tests that the SecurityStateModel for a WebContents is up to date
1496 // when the WebContents is inserted into a Browser's TabStripModel.
1497 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, AddedTab) {
1498 ASSERT_TRUE(https_server_.Start());
1499 SetUpMockCertVerifierForHttpsServer(0, net::OK);
1500
1501 content::WebContents* tab =
1502 browser()->tab_strip_model()->GetActiveWebContents();
1503 ASSERT_TRUE(tab);
1504
1505 content::WebContents* new_contents = content::WebContents::Create(
1506 content::WebContents::CreateParams(tab->GetBrowserContext()));
1507 content::NavigationController& controller = new_contents->GetController();
1508 ChromeSecurityStateModelClient::CreateForWebContents(new_contents);
1509 CheckSecurityInfoForNonSecure(new_contents);
1510 controller.LoadURL(https_server_.GetURL("/title1.html"), content::Referrer(),
1511 ui::PAGE_TRANSITION_TYPED, std::string());
1512 EXPECT_TRUE(content::WaitForLoadStop(new_contents));
1513 CheckSecurityInfoForSecure(new_contents, SecurityStateModel::SECURE,
1514 SecurityStateModel::NO_DEPRECATED_SHA1,
1515 SecurityStateModel::CONTENT_STATUS_NONE, false,
1516 false /* expect cert status error */);
1517
1518 browser()->tab_strip_model()->InsertWebContentsAt(0, new_contents,
1519 TabStripModel::ADD_NONE);
1520 CheckSecurityInfoForSecure(new_contents, SecurityStateModel::SECURE,
1521 SecurityStateModel::NO_DEPRECATED_SHA1,
1522 SecurityStateModel::CONTENT_STATUS_NONE, false,
1523 false /* expect cert status error */);
1524 }
1525
1526 // Tests that the WebContentsObserver::SecurityStyleChanged event fires
1527 // with the current style on HTTP, broken HTTPS, and valid HTTPS pages.
1528 IN_PROC_BROWSER_TEST_F(SecurityStyleChangedTest, SecurityStyleChangedObserver) {
1529 ASSERT_TRUE(https_server_.Start());
1530 ASSERT_TRUE(embedded_test_server()->Start());
1531
1532 net::EmbeddedTestServer https_test_server_expired(
1533 net::EmbeddedTestServer::TYPE_HTTPS);
1534 https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
1535 https_test_server_expired.ServeFilesFromSourceDirectory(
1536 base::FilePath(kDocRoot));
1537 ASSERT_TRUE(https_test_server_expired.Start());
1538
1539 content::WebContents* web_contents =
1540 browser()->tab_strip_model()->GetActiveWebContents();
1541 SecurityStyleTestObserver observer(web_contents);
1542
1543 // Visit an HTTP url.
1544 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
1545 ui_test_utils::NavigateToURL(browser(), http_url);
1546 EXPECT_EQ(blink::WebSecurityStyleUnauthenticated,
1547 observer.latest_security_style());
1548 EXPECT_EQ(0u,
1549 observer.latest_explanations().unauthenticated_explanations.size());
1550 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
1551 EXPECT_EQ(0u, observer.latest_explanations().secure_explanations.size());
1552 EXPECT_FALSE(observer.latest_explanations().scheme_is_cryptographic);
1553 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1554 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1555 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1556 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1557
1558 // Visit an (otherwise valid) HTTPS page that displays mixed content.
1559 std::string replacement_path;
1560 GetFilePathWithHostAndPortReplacement(
1561 "/ssl/page_displays_insecure_content.html",
1562 embedded_test_server()->host_port_pair(), &replacement_path);
1563
1564 GURL mixed_content_url(https_server_.GetURL(replacement_path));
1565 ui_test_utils::NavigateToURL(browser(), mixed_content_url);
1566 EXPECT_EQ(blink::WebSecurityStyleUnauthenticated,
1567 observer.latest_security_style());
1568
1569 const content::SecurityStyleExplanations& mixed_content_explanation =
1570 observer.latest_explanations();
1571 ASSERT_EQ(0u, mixed_content_explanation.unauthenticated_explanations.size());
1572 ASSERT_EQ(0u, mixed_content_explanation.broken_explanations.size());
1573 CheckSecureExplanations(mixed_content_explanation.secure_explanations,
1574 VALID_CERTIFICATE, browser(),
1575 https_server_.GetCertificate().get());
1576 EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic);
1577 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1578 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1579 EXPECT_TRUE(mixed_content_explanation.displayed_mixed_content);
1580 EXPECT_FALSE(mixed_content_explanation.ran_mixed_content);
1581 EXPECT_EQ(blink::WebSecurityStyleUnauthenticated,
1582 mixed_content_explanation.displayed_insecure_content_style);
1583 EXPECT_EQ(blink::WebSecurityStyleAuthenticationBroken,
1584 mixed_content_explanation.ran_insecure_content_style);
1585
1586 // Visit a broken HTTPS url.
1587 GURL expired_url(https_test_server_expired.GetURL("/title1.html"));
1588 ui_test_utils::NavigateToURL(browser(), expired_url);
1589
1590 // An interstitial should show, and an event for the lock icon on the
1591 // interstitial should fire.
1592 content::WaitForInterstitialAttach(web_contents);
1593 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
1594 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser(),
1595 https_test_server_expired.GetCertificate().get());
1596 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1597 INVALID_CERTIFICATE, browser(),
1598 https_test_server_expired.GetCertificate().get());
1599 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1600 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1601 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1602 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1603 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1604
1605 // Before clicking through, navigate to a different page, and then go
1606 // back to the interstitial.
1607 GURL valid_https_url(https_server_.GetURL("/title1.html"));
1608 ui_test_utils::NavigateToURL(browser(), valid_https_url);
1609 EXPECT_EQ(blink::WebSecurityStyleAuthenticated,
1610 observer.latest_security_style());
1611 EXPECT_EQ(0u,
1612 observer.latest_explanations().unauthenticated_explanations.size());
1613 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
1614 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1615 VALID_CERTIFICATE, browser(),
1616 https_server_.GetCertificate().get());
1617 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1618 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1619 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1620 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1621 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1622
1623 // After going back to the interstitial, an event for a broken lock
1624 // icon should fire again.
1625 ui_test_utils::NavigateToURL(browser(), expired_url);
1626 content::WaitForInterstitialAttach(web_contents);
1627 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
1628 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser(),
1629 https_test_server_expired.GetCertificate().get());
1630 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1631 INVALID_CERTIFICATE, browser(),
1632 https_test_server_expired.GetCertificate().get());
1633 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1634 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1635 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1636 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1637 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1638
1639 // Since the next expected style is the same as the previous, clear
1640 // the observer (to make sure that the event fires twice and we don't
1641 // just see the previous event's style).
1642 observer.ClearLatestSecurityStyleAndExplanations();
1643
1644 // Other conditions cannot be tested on this host after clicking
1645 // through because once the interstitial is clicked through, all URLs
1646 // for this host will remain in a broken state.
1647 ProceedThroughInterstitial(web_contents);
1648 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser(),
1649 https_test_server_expired.GetCertificate().get());
1650 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1651 INVALID_CERTIFICATE, browser(),
1652 https_test_server_expired.GetCertificate().get());
1653 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1654 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1655 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1656 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1657 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1658 }
1659
1660 // Visit a valid HTTPS page, then a broken HTTPS page, and then go back,
1661 // and test that the observed security style matches.
1662 #if defined(OS_CHROMEOS)
1663 // Flaky on Chrome OS. See https://crbug.com/638576.
1664 #define MAYBE_SecurityStyleChangedObserverGoBack \
1665 DISABLED_SecurityStyleChangedObserverGoBack
1666 #else
1667 #define MAYBE_SecurityStyleChangedObserverGoBack \
1668 SecurityStyleChangedObserverGoBack
1669 #endif
1670 IN_PROC_BROWSER_TEST_F(SecurityStyleChangedTest,
1671 MAYBE_SecurityStyleChangedObserverGoBack) {
1672 ASSERT_TRUE(https_server_.Start());
1673
1674 net::EmbeddedTestServer https_test_server_expired(
1675 net::EmbeddedTestServer::TYPE_HTTPS);
1676 https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
1677 https_test_server_expired.ServeFilesFromSourceDirectory(
1678 base::FilePath(kDocRoot));
1679 ASSERT_TRUE(https_test_server_expired.Start());
1680
1681 content::WebContents* web_contents =
1682 browser()->tab_strip_model()->GetActiveWebContents();
1683 SecurityStyleTestObserver observer(web_contents);
1684
1685 // Visit a valid HTTPS url.
1686 GURL valid_https_url(https_server_.GetURL("/title1.html"));
1687 ui_test_utils::NavigateToURL(browser(), valid_https_url);
1688 EXPECT_EQ(blink::WebSecurityStyleAuthenticated,
1689 observer.latest_security_style());
1690 EXPECT_EQ(0u,
1691 observer.latest_explanations().unauthenticated_explanations.size());
1692 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
1693 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1694 VALID_CERTIFICATE, browser(),
1695 https_server_.GetCertificate().get());
1696 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1697 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1698 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1699 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1700 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1701
1702 // Navigate to a bad HTTPS page on a different host, and then click
1703 // Back to verify that the previous good security style is seen again.
1704 GURL expired_https_url(https_test_server_expired.GetURL("/title1.html"));
1705 host_resolver()->AddRule("www.example_broken.test", "127.0.0.1");
1706 GURL::Replacements replace_host;
1707 replace_host.SetHostStr("www.example_broken.test");
1708 GURL https_url_different_host =
1709 expired_https_url.ReplaceComponents(replace_host);
1710
1711 ui_test_utils::NavigateToURL(browser(), https_url_different_host);
1712
1713 content::WaitForInterstitialAttach(web_contents);
1714 EXPECT_TRUE(web_contents->ShowingInterstitialPage());
1715 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID,
1716 browser(),
1717 https_test_server_expired.GetCertificate().get());
1718 ProceedThroughInterstitial(web_contents);
1719 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID,
1720 browser(),
1721 https_test_server_expired.GetCertificate().get());
1722 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1723 INVALID_CERTIFICATE, browser(),
1724 https_test_server_expired.GetCertificate().get());
1725 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1726 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1727 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1728 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1729 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1730
1731 content::WindowedNotificationObserver back_nav_load_observer(
1732 content::NOTIFICATION_LOAD_STOP,
1733 content::Source<content::NavigationController>(
1734 &web_contents->GetController()));
1735 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1736 back_nav_load_observer.Wait();
1737
1738 EXPECT_EQ(blink::WebSecurityStyleAuthenticated,
1739 observer.latest_security_style());
1740 EXPECT_EQ(0u,
1741 observer.latest_explanations().unauthenticated_explanations.size());
1742 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size());
1743 CheckSecureExplanations(observer.latest_explanations().secure_explanations,
1744 VALID_CERTIFICATE, browser(),
1745 https_server_.GetCertificate().get());
1746 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
1747 EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
1748 EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
1749 EXPECT_FALSE(observer.latest_explanations().displayed_mixed_content);
1750 EXPECT_FALSE(observer.latest_explanations().ran_mixed_content);
1751 }
1752
1753 // After AddNonsecureUrlHandler() is called, requests to this hostname
1754 // will use obsolete TLS settings.
1755 const char kMockNonsecureHostname[] = "example-nonsecure.test";
1756 const int kObsoleteTLSVersion = net::SSL_CONNECTION_VERSION_TLS1_1;
1757 // ECDHE_RSA + AES_128_CBC with HMAC-SHA1
1758 const uint16_t kObsoleteCipherSuite = 0xc013;
1759
1760 // A URLRequestMockHTTPJob that mocks a TLS connection with the obsolete
1761 // TLS settings specified in kObsoleteTLSVersion and
1762 // kObsoleteCipherSuite.
1763 class URLRequestObsoleteTLSJob : public net::URLRequestMockHTTPJob {
1764 public:
1765 URLRequestObsoleteTLSJob(net::URLRequest* request,
1766 net::NetworkDelegate* network_delegate,
1767 const base::FilePath& file_path,
1768 scoped_refptr<net::X509Certificate> cert,
1769 scoped_refptr<base::TaskRunner> task_runner)
1770 : net::URLRequestMockHTTPJob(request,
1771 network_delegate,
1772 file_path,
1773 task_runner),
1774 cert_(std::move(cert)) {}
1775
1776 void GetResponseInfo(net::HttpResponseInfo* info) override {
1777 net::URLRequestMockHTTPJob::GetResponseInfo(info);
1778 net::SSLConnectionStatusSetVersion(kObsoleteTLSVersion,
1779 &info->ssl_info.connection_status);
1780 net::SSLConnectionStatusSetCipherSuite(kObsoleteCipherSuite,
1781 &info->ssl_info.connection_status);
1782 info->ssl_info.cert = cert_;
1783 }
1784
1785 protected:
1786 ~URLRequestObsoleteTLSJob() override {}
1787
1788 private:
1789 const scoped_refptr<net::X509Certificate> cert_;
1790
1791 DISALLOW_COPY_AND_ASSIGN(URLRequestObsoleteTLSJob);
1792 };
1793
1794 // A URLRequestInterceptor that handles requests with
1795 // URLRequestObsoleteTLSJob jobs.
1796 class URLRequestNonsecureInterceptor : public net::URLRequestInterceptor {
1797 public:
1798 URLRequestNonsecureInterceptor(
1799 const base::FilePath& base_path,
1800 scoped_refptr<base::SequencedWorkerPool> worker_pool,
1801 scoped_refptr<net::X509Certificate> cert)
1802 : base_path_(base_path),
1803 worker_pool_(std::move(worker_pool)),
1804 cert_(std::move(cert)) {}
1805
1806 ~URLRequestNonsecureInterceptor() override {}
1807
1808 // net::URLRequestInterceptor:
1809 net::URLRequestJob* MaybeInterceptRequest(
1810 net::URLRequest* request,
1811 net::NetworkDelegate* network_delegate) const override {
1812 return new URLRequestObsoleteTLSJob(
1813 request, network_delegate, base_path_, cert_,
1814 worker_pool_->GetTaskRunnerWithShutdownBehavior(
1815 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
1816 }
1817
1818 private:
1819 const base::FilePath base_path_;
1820 const scoped_refptr<base::SequencedWorkerPool> worker_pool_;
1821 const scoped_refptr<net::X509Certificate> cert_;
1822
1823 DISALLOW_COPY_AND_ASSIGN(URLRequestNonsecureInterceptor);
1824 };
1825
1826 // Installs a handler to serve HTTPS requests to
1827 // |kMockNonsecureHostname| with connections that have obsolete TLS
1828 // settings.
1829 void AddNonsecureUrlHandler(
1830 const base::FilePath& base_path,
1831 scoped_refptr<net::X509Certificate> cert,
1832 scoped_refptr<base::SequencedWorkerPool> worker_pool) {
1833 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
1834 filter->AddHostnameInterceptor(
1835 "https", kMockNonsecureHostname,
1836 std::unique_ptr<net::URLRequestInterceptor>(
1837 new URLRequestNonsecureInterceptor(base_path, worker_pool, cert)));
1838 }
1839
1840 class BrowserTestNonsecureURLRequest : public InProcessBrowserTest {
1841 public:
1842 BrowserTestNonsecureURLRequest() : InProcessBrowserTest(), cert_(nullptr) {}
1843
1844 void SetUpInProcessBrowserTestFixture() override {
1845 cert_ =
1846 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
1847 ASSERT_TRUE(cert_);
1848 }
1849
1850 void SetUpOnMainThread() override {
1851 base::FilePath serve_file;
1852 PathService::Get(chrome::DIR_TEST_DATA, &serve_file);
1853 serve_file = serve_file.Append(FILE_PATH_LITERAL("title1.html"));
1854 content::BrowserThread::PostTask(
1855 content::BrowserThread::IO, FROM_HERE,
1856 base::Bind(
1857 &AddNonsecureUrlHandler, serve_file, cert_,
1858 make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
1859 }
1860
1861 private:
1862 scoped_refptr<net::X509Certificate> cert_;
1863
1864 DISALLOW_COPY_AND_ASSIGN(BrowserTestNonsecureURLRequest);
1865 };
1866
1867 // Tests that a connection with obsolete TLS settings does not get a
1868 // secure connection explanation.
1869 IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
1870 SecurityStyleChangedObserverNonsecureConnection) {
1871 content::WebContents* web_contents =
1872 browser()->tab_strip_model()->GetActiveWebContents();
1873 SecurityStyleTestObserver observer(web_contents);
1874
1875 ui_test_utils::NavigateToURL(
1876 browser(), GURL(std::string("https://") + kMockNonsecureHostname));
1877
1878 // The security style of the page doesn't get downgraded for obsolete
1879 // TLS settings, so it should remain at WebSecurityStyleAuthenticated.
1880 EXPECT_EQ(blink::WebSecurityStyleAuthenticated,
1881 observer.latest_security_style());
1882
1883 // The messages explaining the security style do, however, get
1884 // downgraded: SECURE_PROTOCOL_AND_CIPHERSUITE should not show up when
1885 // the TLS settings are obsolete.
1886 for (const auto& explanation :
1887 observer.latest_explanations().secure_explanations) {
1888 EXPECT_NE(l10n_util::GetStringUTF8(IDS_STRONG_SSL_SUMMARY),
1889 explanation.summary);
1890 }
1891
1892 // Populate description string replacement with values corresponding
1893 // to test constants.
1894 std::vector<base::string16> description_replacements;
1895 description_replacements.push_back(
1896 l10n_util::GetStringUTF16(IDS_SSL_AN_OBSOLETE_PROTOCOL));
1897 description_replacements.push_back(base::ASCIIToUTF16("TLS 1.1"));
1898 description_replacements.push_back(
1899 l10n_util::GetStringUTF16(IDS_SSL_A_STRONG_KEY_EXCHANGE));
1900 description_replacements.push_back(base::ASCIIToUTF16("ECDHE_RSA"));
1901 description_replacements.push_back(
1902 l10n_util::GetStringUTF16(IDS_SSL_AN_OBSOLETE_CIPHER));
1903 description_replacements.push_back(
1904 base::ASCIIToUTF16("AES_128_CBC with HMAC-SHA1"));
1905 base::string16 obsolete_description = l10n_util::GetStringFUTF16(
1906 IDS_OBSOLETE_SSL_DESCRIPTION, description_replacements, nullptr);
1907
1908 EXPECT_EQ(
1909 obsolete_description,
1910 base::ASCIIToUTF16(
1911 observer.latest_explanations().info_explanations[0].description));
1912 }
1913
1914 // After AddSCTUrlHandler() is called, requests to this hostname
1915 // will be served with Signed Certificate Timestamps.
1916 const char kMockHostnameWithSCTs[] = "example-scts.test";
1917
1918 // URLRequestJobWithSCTs mocks a connection that includes a set of dummy
1919 // SCTs with these statuses.
1920 const std::vector<net::ct::SCTVerifyStatus> kTestSCTStatuses{
1921 net::ct::SCT_STATUS_OK, net::ct::SCT_STATUS_LOG_UNKNOWN,
1922 net::ct::SCT_STATUS_OK};
1923
1924 // A URLRequestMockHTTPJob that mocks a TLS connection with SCTs
1925 // attached to it. The SCTs will have verification statuses
1926 // |kTestSCTStatuses|.
1927 class URLRequestJobWithSCTs : public net::URLRequestMockHTTPJob {
1928 public:
1929 URLRequestJobWithSCTs(net::URLRequest* request,
1930 net::NetworkDelegate* network_delegate,
1931 const base::FilePath& file_path,
1932 scoped_refptr<net::X509Certificate> cert,
1933 scoped_refptr<base::TaskRunner> task_runner)
1934 : net::URLRequestMockHTTPJob(request,
1935 network_delegate,
1936 file_path,
1937 task_runner),
1938 cert_(std::move(cert)) {}
1939
1940 void GetResponseInfo(net::HttpResponseInfo* info) override {
1941 net::URLRequestMockHTTPJob::GetResponseInfo(info);
1942 for (const auto& status : kTestSCTStatuses) {
1943 scoped_refptr<net::ct::SignedCertificateTimestamp> dummy_sct =
1944 new net::ct::SignedCertificateTimestamp();
1945 info->ssl_info.signed_certificate_timestamps.push_back(
1946 net::SignedCertificateTimestampAndStatus(dummy_sct, status));
1947 }
1948 info->ssl_info.cert = cert_;
1949 }
1950
1951 protected:
1952 ~URLRequestJobWithSCTs() override {}
1953
1954 private:
1955 const scoped_refptr<net::X509Certificate> cert_;
1956
1957 DISALLOW_COPY_AND_ASSIGN(URLRequestJobWithSCTs);
1958 };
1959
1960 // A URLRequestInterceptor that handles requests with
1961 // URLRequestJobWithSCTs jobs.
1962 class URLRequestWithSCTsInterceptor : public net::URLRequestInterceptor {
1963 public:
1964 URLRequestWithSCTsInterceptor(
1965 const base::FilePath& base_path,
1966 scoped_refptr<base::SequencedWorkerPool> worker_pool,
1967 scoped_refptr<net::X509Certificate> cert)
1968 : base_path_(base_path),
1969 worker_pool_(std::move(worker_pool)),
1970 cert_(std::move(cert)) {}
1971
1972 ~URLRequestWithSCTsInterceptor() override {}
1973
1974 // net::URLRequestInterceptor:
1975 net::URLRequestJob* MaybeInterceptRequest(
1976 net::URLRequest* request,
1977 net::NetworkDelegate* network_delegate) const override {
1978 return new URLRequestJobWithSCTs(
1979 request, network_delegate, base_path_, cert_,
1980 worker_pool_->GetTaskRunnerWithShutdownBehavior(
1981 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
1982 }
1983
1984 private:
1985 const base::FilePath base_path_;
1986 const scoped_refptr<base::SequencedWorkerPool> worker_pool_;
1987 const scoped_refptr<net::X509Certificate> cert_;
1988
1989 DISALLOW_COPY_AND_ASSIGN(URLRequestWithSCTsInterceptor);
1990 };
1991
1992 // Installs a handler to serve HTTPS requests to |kMockHostnameWithSCTs|
1993 // with connections that have SCTs.
1994 void AddSCTUrlHandler(const base::FilePath& base_path,
1995 scoped_refptr<net::X509Certificate> cert,
1996 scoped_refptr<base::SequencedWorkerPool> worker_pool) {
1997 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
1998 filter->AddHostnameInterceptor(
1999 "https", kMockHostnameWithSCTs,
2000 std::unique_ptr<net::URLRequestInterceptor>(
2001 new URLRequestWithSCTsInterceptor(base_path, worker_pool, cert)));
2002 }
2003
2004 class BrowserTestURLRequestWithSCTs : public InProcessBrowserTest {
2005 public:
2006 BrowserTestURLRequestWithSCTs() : InProcessBrowserTest(), cert_(nullptr) {}
2007
2008 void SetUpInProcessBrowserTestFixture() override {
2009 cert_ =
2010 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
2011 ASSERT_TRUE(cert_);
2012 }
2013
2014 void SetUpOnMainThread() override {
2015 base::FilePath serve_file;
2016 PathService::Get(chrome::DIR_TEST_DATA, &serve_file);
2017 serve_file = serve_file.Append(FILE_PATH_LITERAL("title1.html"));
2018 content::BrowserThread::PostTask(
2019 content::BrowserThread::IO, FROM_HERE,
2020 base::Bind(
2021 &AddSCTUrlHandler, serve_file, cert_,
2022 make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
2023 }
2024
2025 private:
2026 scoped_refptr<net::X509Certificate> cert_;
2027
2028 DISALLOW_COPY_AND_ASSIGN(BrowserTestURLRequestWithSCTs);
2029 };
2030
2031 // Tests that, when Signed Certificate Timestamps (SCTs) are served on a
2032 // connection, the SCTs verification statuses are exposed on the
2033 // SecurityInfo.
2034 IN_PROC_BROWSER_TEST_F(BrowserTestURLRequestWithSCTs,
2035 SecurityInfoWithSCTsAttached) {
2036 ui_test_utils::NavigateToURL(
2037 browser(), GURL(std::string("https://") + kMockHostnameWithSCTs));
2038
2039 content::WebContents* web_contents =
2040 browser()->tab_strip_model()->GetActiveWebContents();
2041 ASSERT_TRUE(web_contents);
2042 ChromeSecurityStateModelClient* model_client =
2043 ChromeSecurityStateModelClient::FromWebContents(web_contents);
2044 ASSERT_TRUE(model_client);
2045 SecurityStateModel::SecurityInfo security_info;
2046 model_client->GetSecurityInfo(&security_info);
2047 EXPECT_EQ(SecurityStateModel::SECURE, security_info.security_level);
2048 EXPECT_EQ(kTestSCTStatuses, security_info.sct_verify_statuses);
2049 }
2050
2051 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698