| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/security_interstitials/core/ssl_error_ui.h" |
| |
| #include "base/i18n/time_formatting.h" |
| #include "components/security_interstitials/core/common_string_util.h" |
| #include "components/security_interstitials/core/metrics_helper.h" |
| #include "components/ssl_errors/error_classification.h" |
| #include "components/ssl_errors/error_info.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "ui/base/l10n/l10n_util.h" |
| |
| namespace security_interstitials { |
| namespace { |
| |
| // Path to the relevant help center page. Used if |support_url_| is invalid. |
| const char kHelpPath[] = "answer/6098869"; |
| |
| bool IsMasked(int options, SSLErrorUI::SSLErrorOptionsMask mask) { |
| return ((options & mask) != 0); |
| } |
| |
| } // namespace |
| |
| SSLErrorUI::SSLErrorUI(const GURL& request_url, |
| int cert_error, |
| const net::SSLInfo& ssl_info, |
| int display_options, |
| const base::Time& time_triggered, |
| const GURL& support_url, |
| ControllerClient* controller) |
| : request_url_(request_url), |
| cert_error_(cert_error), |
| ssl_info_(ssl_info), |
| time_triggered_(time_triggered), |
| support_url_(support_url), |
| requested_strict_enforcement_( |
| IsMasked(display_options, STRICT_ENFORCEMENT)), |
| soft_override_enabled_(IsMasked(display_options, SOFT_OVERRIDE_ENABLED)), |
| hard_override_enabled_( |
| !IsMasked(display_options, HARD_OVERRIDE_DISABLED)), |
| controller_(controller), |
| user_made_decision_(false) { |
| controller_->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW); |
| controller_->metrics_helper()->RecordUserInteraction( |
| MetricsHelper::TOTAL_VISITS); |
| ssl_errors::RecordUMAStatistics(soft_override_enabled_, time_triggered_, |
| request_url, cert_error_, *ssl_info_.cert); |
| } |
| |
| SSLErrorUI::~SSLErrorUI() { |
| // If the page is closing without an explicit decision, record it as not |
| // proceeding. |
| if (!user_made_decision_) { |
| controller_->metrics_helper()->RecordUserDecision( |
| MetricsHelper::DONT_PROCEED); |
| } |
| controller_->metrics_helper()->RecordShutdownMetrics(); |
| } |
| |
| void SSLErrorUI::PopulateStringsForHTML(base::DictionaryValue* load_time_data) { |
| DCHECK(load_time_data); |
| |
| // Shared with other errors. |
| common_string_util::PopulateSSLLayoutStrings(cert_error_, load_time_data); |
| common_string_util::PopulateSSLDebuggingStrings(ssl_info_, time_triggered_, |
| load_time_data); |
| |
| // Shared values for both the overridable and non-overridable versions. |
| load_time_data->SetBoolean("bad_clock", false); |
| load_time_data->SetBoolean("hide_primary_button", false); |
| load_time_data->SetString("tabTitle", |
| l10n_util::GetStringUTF16(IDS_SSL_V2_TITLE)); |
| load_time_data->SetString("heading", |
| l10n_util::GetStringUTF16(IDS_SSL_V2_HEADING)); |
| load_time_data->SetString( |
| "primaryParagraph", |
| l10n_util::GetStringFUTF16( |
| IDS_SSL_V2_PRIMARY_PARAGRAPH, |
| common_string_util::GetFormattedHostName(request_url_))); |
| load_time_data->SetString( |
| "recurrentErrorParagraph", |
| l10n_util::GetStringUTF16(IDS_SSL_V2_RECURRENT_ERROR_PARAGRAPH)); |
| load_time_data->SetBoolean("show_recurrent_error_paragraph", |
| controller_->HasSeenRecurrentError()); |
| |
| if (soft_override_enabled_) |
| PopulateOverridableStrings(load_time_data); |
| else |
| PopulateNonOverridableStrings(load_time_data); |
| } |
| |
| const net::SSLInfo& SSLErrorUI::ssl_info() const { |
| return ssl_info_; |
| } |
| |
| const base::Time& SSLErrorUI::time_triggered() const { |
| return time_triggered_; |
| } |
| |
| ControllerClient* SSLErrorUI::controller() const { |
| return controller_; |
| } |
| |
| int SSLErrorUI::cert_error() const { |
| return cert_error_; |
| } |
| |
| void SSLErrorUI::PopulateOverridableStrings( |
| base::DictionaryValue* load_time_data) { |
| DCHECK(soft_override_enabled_); |
| |
| base::string16 url(common_string_util::GetFormattedHostName(request_url_)); |
| ssl_errors::ErrorInfo error_info = ssl_errors::ErrorInfo::CreateError( |
| ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_), |
| ssl_info_.cert.get(), request_url_); |
| |
| load_time_data->SetBoolean("overridable", true); |
| load_time_data->SetBoolean("hide_primary_button", false); |
| load_time_data->SetString("explanationParagraph", error_info.details()); |
| load_time_data->SetString( |
| "primaryButtonText", |
| l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_SAFETY_BUTTON)); |
| load_time_data->SetString( |
| "finalParagraph", |
| l10n_util::GetStringFUTF16(IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH, url)); |
| } |
| |
| void SSLErrorUI::PopulateNonOverridableStrings( |
| base::DictionaryValue* load_time_data) { |
| DCHECK(!soft_override_enabled_); |
| |
| base::string16 url(common_string_util::GetFormattedHostName(request_url_)); |
| ssl_errors::ErrorInfo::ErrorType type = |
| ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_); |
| |
| load_time_data->SetBoolean("overridable", false); |
| load_time_data->SetBoolean("hide_primary_button", false); |
| load_time_data->SetString( |
| "explanationParagraph", |
| l10n_util::GetStringFUTF16(IDS_SSL_NONOVERRIDABLE_MORE, url)); |
| load_time_data->SetString("primaryButtonText", |
| l10n_util::GetStringUTF16(IDS_SSL_RELOAD)); |
| |
| // Customize the help link depending on the specific error type. |
| // Only mark as HSTS if none of the more specific error types apply, |
| // and use INVALID as a fallback if no other string is appropriate. |
| load_time_data->SetInteger("errorType", type); |
| int help_string = IDS_SSL_NONOVERRIDABLE_INVALID; |
| switch (type) { |
| case ssl_errors::ErrorInfo::CERT_REVOKED: |
| help_string = IDS_SSL_NONOVERRIDABLE_REVOKED; |
| break; |
| case ssl_errors::ErrorInfo::CERT_PINNED_KEY_MISSING: |
| help_string = IDS_SSL_NONOVERRIDABLE_PINNED; |
| break; |
| case ssl_errors::ErrorInfo::CERT_INVALID: |
| help_string = IDS_SSL_NONOVERRIDABLE_INVALID; |
| break; |
| default: |
| if (requested_strict_enforcement_) |
| help_string = IDS_SSL_NONOVERRIDABLE_HSTS; |
| } |
| load_time_data->SetString("finalParagraph", |
| l10n_util::GetStringFUTF16(help_string, url)); |
| } |
| |
| void SSLErrorUI::HandleCommand(SecurityInterstitialCommand command) { |
| switch (command) { |
| case CMD_DONT_PROCEED: { |
| controller_->metrics_helper()->RecordUserDecision( |
| MetricsHelper::DONT_PROCEED); |
| user_made_decision_ = true; |
| controller_->GoBack(); |
| break; |
| } |
| case CMD_PROCEED: { |
| if (hard_override_enabled_) { |
| controller_->metrics_helper()->RecordUserDecision( |
| MetricsHelper::PROCEED); |
| controller_->Proceed(); |
| user_made_decision_ = true; |
| } |
| break; |
| } |
| case CMD_DO_REPORT: { |
| controller_->SetReportingPreference(true); |
| break; |
| } |
| case CMD_DONT_REPORT: { |
| controller_->SetReportingPreference(false); |
| break; |
| } |
| case CMD_SHOW_MORE_SECTION: { |
| controller_->metrics_helper()->RecordUserInteraction( |
| security_interstitials::MetricsHelper::SHOW_ADVANCED); |
| break; |
| } |
| case CMD_OPEN_HELP_CENTER: { |
| controller_->metrics_helper()->RecordUserInteraction( |
| security_interstitials::MetricsHelper::SHOW_LEARN_MORE); |
| |
| // Add cert error code as a ref to support URL, this is used to expand the |
| // right section if the user is redirected to chrome://connection-help. |
| GURL::Replacements replacements; |
| // This has to be stored in a separate variable, otherwise asan throws a |
| // use-after-scope error |
| std::string cert_error_string = std::to_string(cert_error_); |
| replacements.SetRefStr(cert_error_string); |
| // If |support_url_| is invalid, use the default help center url. |
| controller_->OpenUrlInNewForegroundTab( |
| (support_url_.is_valid() |
| ? support_url_ |
| : controller_->GetBaseHelpCenterUrl().Resolve(kHelpPath)) |
| .ReplaceComponents(replacements)); |
| break; |
| } |
| case CMD_RELOAD: { |
| controller_->metrics_helper()->RecordUserInteraction( |
| security_interstitials::MetricsHelper::RELOAD); |
| controller_->Reload(); |
| break; |
| } |
| case CMD_OPEN_REPORTING_PRIVACY: { |
| controller_->OpenExtendedReportingPrivacyPolicy(true); |
| break; |
| } |
| case CMD_OPEN_WHITEPAPER: { |
| controller_->OpenExtendedReportingWhitepaper(true); |
| break; |
| } |
| case CMD_OPEN_DATE_SETTINGS: |
| case CMD_OPEN_DIAGNOSTIC: |
| case CMD_OPEN_LOGIN: |
| case CMD_REPORT_PHISHING_ERROR: { |
| // Not supported by the SSL error page. |
| NOTREACHED() << "Unsupported command: " << command; |
| break; |
| } |
| case CMD_ERROR: |
| case CMD_TEXT_FOUND: |
| case CMD_TEXT_NOT_FOUND: { |
| // Commands are for testing. |
| break; |
| } |
| } |
| } |
| |
| } // security_interstitials |