Chromium Code Reviews| Index: chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| diff --git a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| index d2c41d7c1bcc7e29bcbc91f3c32600f58cfbdc2b..f8a05147236c3b9c1b86d66225a27e52983db3d1 100644 |
| --- a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| +++ b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| @@ -8,43 +8,159 @@ |
| #include "base/files/file_path.h" |
| #include "base/macros.h" |
| #include "base/strings/string_split.h" |
| +#include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/ssl/cert_verifier_browser_test.h" |
| #include "chrome/browser/ssl/chrome_security_state_model_client.h" |
| #include "chrome/browser/ssl/ssl_blocking_page.h" |
| #include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/pref_names.h" |
| +#include "chrome/grit/generated_resources.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/prefs/pref_service.h" |
| #include "content/public/browser/cert_store.h" |
| #include "content/public/browser/interstitial_page.h" |
| #include "content/public/browser/navigation_controller.h" |
| +#include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| +#include "content/public/browser/security_style_explanation.h" |
| +#include "content/public/browser/security_style_explanations.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/referrer.h" |
| +#include "content/public/common/ssl_status.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "net/base/net_errors.h" |
| +#include "net/base/test_data_directory.h" |
| #include "net/cert/cert_status_flags.h" |
| #include "net/cert/cert_verify_result.h" |
| #include "net/cert/mock_cert_verifier.h" |
| #include "net/cert/x509_certificate.h" |
| +#include "net/cert/x509_certificate.h" |
|
msw
2016/05/18 17:20:24
nit: remove (duplicate of line above)
estark
2016/05/20 22:12:09
Done.
|
| #include "net/dns/mock_host_resolver.h" |
| +#include "net/ssl/ssl_cipher_suite_names.h" |
| +#include "net/ssl/ssl_connection_status_flags.h" |
| +#include "net/test/cert_test_util.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "net/test/embedded_test_server/request_handler_util.h" |
| #include "net/test/url_request/url_request_failed_job.h" |
| +#include "net/test/url_request/url_request_mock_http_job.h" |
| #include "net/url_request/url_request_filter.h" |
| +#include "net/url_request/url_request_test_util.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| using security_state::SecurityStateModel; |
| namespace { |
| +enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE }; |
| + |
| const base::FilePath::CharType kDocRoot[] = |
| FILE_PATH_LITERAL("chrome/test/data"); |
| +// A WebContentsObserver useful for testing the SecurityStyleChanged() |
| +// method: it keeps track of the latest security style and explanation |
| +// that was fired. |
| +class SecurityStyleTestObserver : public content::WebContentsObserver { |
| + public: |
| + explicit SecurityStyleTestObserver(content::WebContents* web_contents) |
| + : content::WebContentsObserver(web_contents), |
| + latest_security_style_(content::SECURITY_STYLE_UNKNOWN) {} |
| + ~SecurityStyleTestObserver() override {} |
| + |
| + void SecurityStyleChanged(content::SecurityStyle security_style, |
| + const content::SecurityStyleExplanations& |
| + security_style_explanations) override { |
| + latest_security_style_ = security_style; |
| + latest_explanations_ = security_style_explanations; |
| + } |
| + |
| + content::SecurityStyle latest_security_style() const { |
| + return latest_security_style_; |
| + } |
| + |
| + const content::SecurityStyleExplanations& latest_explanations() const { |
| + return latest_explanations_; |
| + } |
| + |
| + void ClearLatestSecurityStyleAndExplanations() { |
| + latest_security_style_ = content::SECURITY_STYLE_UNKNOWN; |
| + latest_explanations_ = content::SecurityStyleExplanations(); |
| + } |
| + |
| + private: |
| + content::SecurityStyle latest_security_style_; |
| + content::SecurityStyleExplanations latest_explanations_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SecurityStyleTestObserver); |
| +}; |
| + |
| +// Check that |observer|'s latest event was for an expired certificate |
| +// and that it saw the proper SecurityStyle and explanations. |
| +void CheckBrokenSecurityStyle(const SecurityStyleTestObserver& observer, |
| + int error, |
| + Browser* browser) { |
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, |
| + observer.latest_security_style()); |
| + |
| + const content::SecurityStyleExplanations& expired_explanation = |
| + observer.latest_explanations(); |
| + EXPECT_EQ(0u, expired_explanation.unauthenticated_explanations.size()); |
| + ASSERT_EQ(1u, expired_explanation.broken_explanations.size()); |
| + |
| + // Check that the summary and description are as expected. |
| + EXPECT_EQ(l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR), |
| + expired_explanation.broken_explanations[0].summary); |
| + |
| + base::string16 error_string = base::UTF8ToUTF16(net::ErrorToString(error)); |
| + EXPECT_EQ(l10n_util::GetStringFUTF8( |
| + IDS_CERTIFICATE_CHAIN_ERROR_DESCRIPTION_FORMAT, error_string), |
| + expired_explanation.broken_explanations[0].description); |
| + |
| + // Check the associated certificate id. |
| + int cert_id = browser->tab_strip_model() |
| + ->GetActiveWebContents() |
| + ->GetController() |
| + .GetActiveEntry() |
| + ->GetSSL() |
| + .cert_id; |
| + EXPECT_EQ(cert_id, expired_explanation.broken_explanations[0].cert_id); |
| +} |
| + |
| +// Checks that the given |secure_explanations| contains appropriate |
| +// an appropriate explanation if the certificate status is valid. |
| +void CheckSecureExplanations( |
| + const std::vector<content::SecurityStyleExplanation>& secure_explanations, |
| + CertificateStatus cert_status, |
| + Browser* browser) { |
| + ASSERT_EQ(cert_status == VALID_CERTIFICATE ? 2u : 1u, |
| + secure_explanations.size()); |
| + if (cert_status == VALID_CERTIFICATE) { |
| + EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE), |
| + secure_explanations[0].summary); |
| + EXPECT_EQ( |
| + l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION), |
| + secure_explanations[0].description); |
| + int cert_id = browser->tab_strip_model() |
| + ->GetActiveWebContents() |
| + ->GetController() |
| + .GetActiveEntry() |
| + ->GetSSL() |
| + .cert_id; |
| + EXPECT_EQ(cert_id, secure_explanations[0].cert_id); |
| + } |
| + |
| + EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE), |
| + secure_explanations.back().summary); |
| + EXPECT_EQ( |
| + l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE_DESCRIPTION), |
| + secure_explanations.back().description); |
| +} |
| + |
| void CheckSecurityInfoForSecure( |
| content::WebContents* contents, |
| SecurityStateModel::SecurityLevel expect_security_level, |
| @@ -92,6 +208,19 @@ void CheckSecurityInfoForNonSecure(content::WebContents* contents) { |
| EXPECT_EQ(0, security_info.cert_id); |
| } |
| +void SetUpMockCertVerifierForServer(net::MockCertVerifier* verifier, |
| + const net::EmbeddedTestServer& server, |
| + net::CertStatus cert_status, |
| + int net_result) { |
| + scoped_refptr<net::X509Certificate> cert(server.GetCertificate()); |
| + net::CertVerifyResult verify_result; |
| + verify_result.is_issued_by_known_root = true; |
| + verify_result.verified_cert = cert; |
| + verify_result.cert_status = cert_status; |
| + |
| + verifier->AddResultForCert(cert.get(), verify_result, net_result); |
| +} |
| + |
| class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest { |
| public: |
| ChromeSecurityStateModelClientTest() |
| @@ -130,14 +259,8 @@ class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest { |
| protected: |
| void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status, |
| int net_result) { |
| - scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate()); |
| - net::CertVerifyResult verify_result; |
| - verify_result.is_issued_by_known_root = true; |
| - verify_result.verified_cert = cert; |
| - verify_result.cert_status = cert_status; |
| - |
| - mock_cert_verifier()->AddResultForCert(cert.get(), verify_result, |
| - net_result); |
| + SetUpMockCertVerifierForServer(mock_cert_verifier(), https_server_, |
| + cert_status, net_result); |
| } |
| net::EmbeddedTestServer https_server_; |
| @@ -535,4 +658,340 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, AddedTab) { |
| false /* expect cert status error */); |
| } |
| +// Tests that the WebContentsObserver::SecurityStyleChanged event fires |
| +// with the current style on HTTP, broken HTTPS, and valid HTTPS pages. |
| +IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, |
| + SecurityStyleChangedObserver) { |
| + ASSERT_TRUE(https_server_.Start()); |
| + SetUpMockCertVerifierForHttpsServer(0, net::OK); |
|
msw
2016/05/18 17:20:24
q: Is this necessary? It wasn't part of the old te
estark
2016/05/20 22:12:09
Ehh, I did it to be consistent with the rest of th
|
| + |
| + net::EmbeddedTestServer https_test_server_expired( |
| + net::EmbeddedTestServer::TYPE_HTTPS); |
| + https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); |
| + https_test_server_expired.ServeFilesFromSourceDirectory( |
| + base::FilePath(kDocRoot)); |
| + ASSERT_TRUE(https_test_server_expired.Start()); |
| + SetUpMockCertVerifierForServer( |
| + mock_cert_verifier(), https_test_server_expired, |
| + net::CERT_STATUS_DATE_INVALID, net::ERR_CERT_DATE_INVALID); |
| + |
| + ASSERT_TRUE(embedded_test_server()->Start()); |
| + |
| + content::WebContents* web_contents = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + SecurityStyleTestObserver observer(web_contents); |
| + |
| + // Visit an HTTP url. |
| + GURL http_url(embedded_test_server()->GetURL("/")); |
| + ui_test_utils::NavigateToURL(browser(), http_url); |
| + EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, |
| + observer.latest_security_style()); |
| + EXPECT_EQ(0u, |
| + observer.latest_explanations().unauthenticated_explanations.size()); |
| + EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| + EXPECT_EQ(0u, observer.latest_explanations().secure_explanations.size()); |
| + EXPECT_FALSE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + |
| + // Visit an (otherwise valid) HTTPS page that displays mixed content. |
| + std::string replacement_path; |
| + GetFilePathWithHostAndPortReplacement( |
| + "/ssl/page_displays_insecure_content.html", |
| + embedded_test_server()->host_port_pair(), &replacement_path); |
| + |
| + GURL mixed_content_url(https_server_.GetURL(replacement_path)); |
| + ui_test_utils::NavigateToURL(browser(), mixed_content_url); |
| + EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, |
| + observer.latest_security_style()); |
| + |
| + const content::SecurityStyleExplanations& mixed_content_explanation = |
| + observer.latest_explanations(); |
| + ASSERT_EQ(0u, mixed_content_explanation.unauthenticated_explanations.size()); |
| + ASSERT_EQ(0u, mixed_content_explanation.broken_explanations.size()); |
| + CheckSecureExplanations(mixed_content_explanation.secure_explanations, |
| + VALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic); |
| + EXPECT_TRUE(mixed_content_explanation.displayed_insecure_content); |
| + EXPECT_FALSE(mixed_content_explanation.ran_insecure_content); |
| + EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, |
| + mixed_content_explanation.displayed_insecure_content_style); |
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, |
| + mixed_content_explanation.ran_insecure_content_style); |
| + |
| + // Visit a broken HTTPS url. |
| + GURL expired_url(https_test_server_expired.GetURL(std::string("/"))); |
| + ui_test_utils::NavigateToURL(browser(), expired_url); |
| + |
| + // An interstitial should show, and an event for the lock icon on the |
| + // interstitial should fire. |
| + content::WaitForInterstitialAttach(web_contents); |
| + EXPECT_TRUE(web_contents->ShowingInterstitialPage()); |
| + CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + INVALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| + |
| + // Before clicking through, navigate to a different page, and then go |
| + // back to the interstitial. |
| + GURL valid_https_url(https_server_.GetURL(std::string("/"))); |
| + ui_test_utils::NavigateToURL(browser(), valid_https_url); |
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| + observer.latest_security_style()); |
| + EXPECT_EQ(0u, |
| + observer.latest_explanations().unauthenticated_explanations.size()); |
| + EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + VALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| + |
| + // After going back to the interstitial, an event for a broken lock |
| + // icon should fire again. |
| + ui_test_utils::NavigateToURL(browser(), expired_url); |
| + content::WaitForInterstitialAttach(web_contents); |
| + EXPECT_TRUE(web_contents->ShowingInterstitialPage()); |
| + CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + INVALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| + |
| + // Since the next expected style is the same as the previous, clear |
| + // the observer (to make sure that the event fires twice and we don't |
| + // just see the previous event's style). |
| + observer.ClearLatestSecurityStyleAndExplanations(); |
| + |
| + // Other conditions cannot be tested on this host after clicking |
| + // through because once the interstitial is clicked through, all URLs |
| + // for this host will remain in a broken state. |
| + ProceedThroughInterstitial(web_contents); |
| + CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + INVALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| +} |
| + |
| +// Visit a valid HTTPS page, then a broken HTTPS page, and then go back, |
| +// and test that the observed security style matches. |
| +IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, |
| + SecurityStyleChangedObserverGoBack) { |
| + ASSERT_TRUE(https_server_.Start()); |
| + SetUpMockCertVerifierForHttpsServer(0, net::OK); |
| + |
| + net::EmbeddedTestServer https_test_server_expired( |
| + net::EmbeddedTestServer::TYPE_HTTPS); |
| + https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); |
| + https_test_server_expired.ServeFilesFromSourceDirectory( |
| + base::FilePath(kDocRoot)); |
| + ASSERT_TRUE(https_test_server_expired.Start()); |
| + SetUpMockCertVerifierForServer( |
| + mock_cert_verifier(), https_test_server_expired, |
| + net::CERT_STATUS_COMMON_NAME_INVALID, net::ERR_CERT_COMMON_NAME_INVALID); |
| + |
| + content::WebContents* web_contents = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + SecurityStyleTestObserver observer(web_contents); |
| + |
| + // Visit a valid HTTPS url. |
| + GURL valid_https_url(https_server_.GetURL(std::string("/"))); |
| + ui_test_utils::NavigateToURL(browser(), valid_https_url); |
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| + observer.latest_security_style()); |
| + EXPECT_EQ(0u, |
| + observer.latest_explanations().unauthenticated_explanations.size()); |
| + EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + VALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| + |
| + // Navigate to a bad HTTPS page on a different host, and then click |
| + // Back to verify that the previous good security style is seen again. |
| + GURL expired_https_url(https_test_server_expired.GetURL(std::string("/"))); |
| + host_resolver()->AddRule("www.example_broken.test", "127.0.0.1"); |
| + GURL::Replacements replace_host; |
| + replace_host.SetHostStr("www.example_broken.test"); |
| + GURL https_url_different_host = |
| + expired_https_url.ReplaceComponents(replace_host); |
| + |
| + ui_test_utils::NavigateToURL(browser(), https_url_different_host); |
| + |
| + content::WaitForInterstitialAttach(web_contents); |
| + EXPECT_TRUE(web_contents->ShowingInterstitialPage()); |
| + CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID, |
| + browser()); |
| + ProceedThroughInterstitial(web_contents); |
| + CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID, |
| + browser()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + INVALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| + |
| + content::WindowedNotificationObserver back_nav_load_observer( |
| + content::NOTIFICATION_LOAD_STOP, |
| + content::Source<content::NavigationController>( |
| + &web_contents->GetController())); |
| + chrome::GoBack(browser(), CURRENT_TAB); |
| + back_nav_load_observer.Wait(); |
| + |
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| + observer.latest_security_style()); |
| + EXPECT_EQ(0u, |
| + observer.latest_explanations().unauthenticated_explanations.size()); |
| + EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); |
| + CheckSecureExplanations(observer.latest_explanations().secure_explanations, |
| + VALID_CERTIFICATE, browser()); |
| + EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); |
| + EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); |
| + EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); |
| +} |
| + |
| +// After AddNonsecureUrlHandler() is called, requests to this hostname |
| +// will use obsolete TLS settings. |
| +const char kMockNonsecureHostname[] = "example-nonsecure.test"; |
| + |
| +// A URLRequestMockHTTPJob that mocks a TLS connection with an obsolete |
| +// protocol version. |
| +class URLRequestObsoleteTLSJob : public net::URLRequestMockHTTPJob { |
| + public: |
| + URLRequestObsoleteTLSJob(net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate, |
| + const base::FilePath& file_path, |
| + scoped_refptr<net::X509Certificate> cert, |
| + scoped_refptr<base::TaskRunner> task_runner) |
| + : net::URLRequestMockHTTPJob(request, |
| + network_delegate, |
| + file_path, |
| + task_runner), |
| + cert_(std::move(cert)) {} |
| + |
| + void GetResponseInfo(net::HttpResponseInfo* info) override { |
| + net::URLRequestMockHTTPJob::GetResponseInfo(info); |
| + net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_1, |
| + &info->ssl_info.connection_status); |
| + const uint16_t kTlsEcdheRsaWithAes128CbcSha = 0xc013; |
| + net::SSLConnectionStatusSetCipherSuite(kTlsEcdheRsaWithAes128CbcSha, |
| + &info->ssl_info.connection_status); |
| + info->ssl_info.cert = cert_; |
| + } |
| + |
| + protected: |
| + ~URLRequestObsoleteTLSJob() override {} |
| + |
| + private: |
| + const scoped_refptr<net::X509Certificate> cert_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(URLRequestObsoleteTLSJob); |
| +}; |
| + |
| +// A URLRequestInterceptor that handles requests with |
| +// URLRequestObsoleteTLSJob jobs. |
| +class URLRequestNonsecureInterceptor : public net::URLRequestInterceptor { |
| + public: |
| + URLRequestNonsecureInterceptor( |
| + const base::FilePath& base_path, |
| + scoped_refptr<base::SequencedWorkerPool> worker_pool, |
| + scoped_refptr<net::X509Certificate> cert) |
| + : base_path_(base_path), |
| + worker_pool_(std::move(worker_pool)), |
| + cert_(std::move(cert)) {} |
| + |
| + ~URLRequestNonsecureInterceptor() override {} |
| + |
| + // net::URLRequestInterceptor: |
| + net::URLRequestJob* MaybeInterceptRequest( |
| + net::URLRequest* request, |
| + net::NetworkDelegate* network_delegate) const override { |
| + return new URLRequestObsoleteTLSJob( |
| + request, network_delegate, base_path_, cert_, |
| + worker_pool_->GetTaskRunnerWithShutdownBehavior( |
| + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
| + } |
| + |
| + private: |
| + const base::FilePath base_path_; |
| + const scoped_refptr<base::SequencedWorkerPool> worker_pool_; |
| + const scoped_refptr<net::X509Certificate> cert_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(URLRequestNonsecureInterceptor); |
| +}; |
| + |
| +// Installs a handler to serve HTTPS requests to |
| +// |kMockNonsecureHostname| with connections that have obsolete TLS |
| +// settings. |
| +void AddNonsecureUrlHandler( |
| + const base::FilePath& base_path, |
| + scoped_refptr<net::X509Certificate> cert, |
| + scoped_refptr<base::SequencedWorkerPool> worker_pool) { |
| + net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); |
| + filter->AddHostnameInterceptor( |
| + "https", kMockNonsecureHostname, |
| + std::unique_ptr<net::URLRequestInterceptor>( |
| + new URLRequestNonsecureInterceptor(base_path, worker_pool, cert))); |
| +} |
| + |
| +class BrowserTestNonsecureURLRequest : public CertVerifierBrowserTest { |
| + public: |
| + BrowserTestNonsecureURLRequest() |
| + : CertVerifierBrowserTest(), cert_(nullptr) {} |
| + |
| + void SetUpInProcessBrowserTestFixture() override { |
| + cert_ = |
| + net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); |
| + ASSERT_TRUE(cert_); |
| + } |
| + |
| + void SetUpOnMainThread() override { |
| + base::FilePath serve_file; |
| + PathService::Get(chrome::DIR_TEST_DATA, &serve_file); |
| + serve_file = serve_file.Append(FILE_PATH_LITERAL("title1.html")); |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind( |
| + &AddNonsecureUrlHandler, serve_file, cert_, |
| + make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); |
| + } |
| + |
| + private: |
| + scoped_refptr<net::X509Certificate> cert_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BrowserTestNonsecureURLRequest); |
| +}; |
| + |
| +// Tests that a connection with obsolete TLS settings does not get a |
| +// secure connection explanation. |
| +IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, |
| + SecurityStyleChangedObserverNonsecureConnection) { |
| + content::WebContents* web_contents = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + SecurityStyleTestObserver observer(web_contents); |
| + |
| + ui_test_utils::NavigateToURL( |
| + browser(), GURL(std::string("https://") + kMockNonsecureHostname)); |
| + |
| + // The security style of the page doesn't get downgraded for obsolete |
| + // TLS settings, so it should remain at SECURITY_STYLE_AUTHENTICATED. |
| + EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, |
| + observer.latest_security_style()); |
| + |
| + // The messages explaining the security style do, however, get |
| + // downgraded: SECURE_PROTOCOL_AND_CIPHERSUITE should not show up when |
| + // the TLS settings are obsolete. |
| + for (const auto& explanation : |
| + observer.latest_explanations().secure_explanations) { |
| + EXPECT_NE(l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE), |
| + explanation.summary); |
| + } |
| +} |
| + |
| } // namespace |