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

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

Powered by Google App Engine
This is Rietveld 408576698