| 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..c32738337731383b6506a0c5cbd0bfaf945c8ffc 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,158 @@
|
| #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/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 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 +207,29 @@ void CheckSecurityInfoForNonSecure(content::WebContents* contents) {
|
| EXPECT_EQ(0, security_info.cert_id);
|
| }
|
|
|
| +void ProceedThroughInterstitial(content::WebContents* tab) {
|
| + content::InterstitialPage* interstitial_page = tab->GetInterstitialPage();
|
| + ASSERT_TRUE(interstitial_page);
|
| + ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
|
| + interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
|
| + content::WindowedNotificationObserver observer(
|
| + content::NOTIFICATION_LOAD_STOP,
|
| + content::Source<content::NavigationController>(&tab->GetController()));
|
| + interstitial_page->Proceed();
|
| + observer.Wait();
|
| +}
|
| +
|
| +void GetFilePathWithHostAndPortReplacement(
|
| + const std::string& original_file_path,
|
| + const net::HostPortPair& host_port_pair,
|
| + std::string* replacement_path) {
|
| + base::StringPairs replacement_text;
|
| + replacement_text.push_back(
|
| + make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
|
| + net::test_server::GetFilePathWithReplacements(
|
| + original_file_path, replacement_text, replacement_path);
|
| +}
|
| +
|
| class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest {
|
| public:
|
| ChromeSecurityStateModelClientTest()
|
| @@ -104,29 +242,6 @@ class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest {
|
| command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
|
| }
|
|
|
| - void ProceedThroughInterstitial(content::WebContents* tab) {
|
| - content::InterstitialPage* interstitial_page = tab->GetInterstitialPage();
|
| - ASSERT_TRUE(interstitial_page);
|
| - ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
|
| - interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
|
| - content::WindowedNotificationObserver observer(
|
| - content::NOTIFICATION_LOAD_STOP,
|
| - content::Source<content::NavigationController>(&tab->GetController()));
|
| - interstitial_page->Proceed();
|
| - observer.Wait();
|
| - }
|
| -
|
| - static void GetFilePathWithHostAndPortReplacement(
|
| - const std::string& original_file_path,
|
| - const net::HostPortPair& host_port_pair,
|
| - std::string* replacement_path) {
|
| - base::StringPairs replacement_text;
|
| - replacement_text.push_back(
|
| - make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
|
| - net::test_server::GetFilePathWithReplacements(
|
| - original_file_path, replacement_text, replacement_path);
|
| - }
|
| -
|
| protected:
|
| void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status,
|
| int net_result) {
|
| @@ -146,6 +261,25 @@ class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest {
|
| DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClientTest);
|
| };
|
|
|
| +class SecurityStyleChangedTest : public InProcessBrowserTest {
|
| + public:
|
| + SecurityStyleChangedTest()
|
| + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
|
| + https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
|
| + }
|
| +
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + // Browser will both run and display insecure content.
|
| + command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
|
| + }
|
| +
|
| + protected:
|
| + net::EmbeddedTestServer https_server_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(SecurityStyleChangedTest);
|
| +};
|
| +
|
| IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpPage) {
|
| ASSERT_TRUE(embedded_test_server()->Start());
|
| ui_test_utils::NavigateToURL(
|
| @@ -535,4 +669,329 @@ 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(SecurityStyleChangedTest, SecurityStyleChangedObserver) {
|
| + ASSERT_TRUE(https_server_.Start());
|
| + ASSERT_TRUE(embedded_test_server()->Start());
|
| +
|
| + 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());
|
| +
|
| + 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(SecurityStyleChangedTest,
|
| + SecurityStyleChangedObserverGoBack) {
|
| + ASSERT_TRUE(https_server_.Start());
|
| +
|
| + 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());
|
| +
|
| + 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 InProcessBrowserTest {
|
| + public:
|
| + BrowserTestNonsecureURLRequest() : InProcessBrowserTest(), 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
|
|
|