ssl_error_ui.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #include "components/security_interstitials/core/ssl_error_ui.h"
  5. #include "base/i18n/time_formatting.h"
  6. #include "build/build_config.h"
  7. #include "components/security_interstitials/core/common_string_util.h"
  8. #include "components/security_interstitials/core/controller_client.h"
  9. #include "components/security_interstitials/core/metrics_helper.h"
  10. #include "components/security_interstitials/core/ssl_error_options_mask.h"
  11. #include "components/ssl_errors/error_classification.h"
  12. #include "components/ssl_errors/error_info.h"
  13. #include "components/strings/grit/components_strings.h"
  14. #include "ui/base/l10n/l10n_util.h"
  15. namespace security_interstitials {
  16. namespace {
  17. // Path to the relevant help center page. Used if |support_url_| is invalid.
  18. const char kHelpPath[] = "answer/6098869";
  19. bool IsMasked(int options, SSLErrorOptionsMask mask) {
  20. return ((options & mask) != 0);
  21. }
  22. } // namespace
  23. SSLErrorUI::SSLErrorUI(const GURL& request_url,
  24. int cert_error,
  25. const net::SSLInfo& ssl_info,
  26. int display_options,
  27. const base::Time& time_triggered,
  28. const GURL& support_url,
  29. ControllerClient* controller)
  30. : request_url_(request_url),
  31. cert_error_(cert_error),
  32. ssl_info_(ssl_info),
  33. time_triggered_(time_triggered),
  34. support_url_(support_url),
  35. requested_strict_enforcement_(
  36. IsMasked(display_options, STRICT_ENFORCEMENT)),
  37. soft_override_enabled_(IsMasked(display_options, SOFT_OVERRIDE_ENABLED)),
  38. hard_override_enabled_(
  39. !IsMasked(display_options, HARD_OVERRIDE_DISABLED)),
  40. controller_(controller),
  41. user_made_decision_(false) {
  42. controller_->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW);
  43. controller_->metrics_helper()->RecordUserInteraction(
  44. MetricsHelper::TOTAL_VISITS);
  45. ssl_errors::RecordUMAStatistics(soft_override_enabled_, time_triggered_,
  46. request_url, cert_error_, *ssl_info_.cert);
  47. }
  48. SSLErrorUI::~SSLErrorUI() {
  49. // If the page is closing without an explicit decision, record it as not
  50. // proceeding.
  51. if (!user_made_decision_) {
  52. controller_->metrics_helper()->RecordUserDecision(
  53. MetricsHelper::DONT_PROCEED);
  54. }
  55. controller_->metrics_helper()->RecordShutdownMetrics();
  56. }
  57. void SSLErrorUI::PopulateStringsForHTML(base::Value::Dict& load_time_data) {
  58. // Shared with other errors.
  59. common_string_util::PopulateSSLLayoutStrings(cert_error_, load_time_data);
  60. common_string_util::PopulateSSLDebuggingStrings(ssl_info_, time_triggered_,
  61. load_time_data);
  62. // Shared values for both the overridable and non-overridable versions.
  63. load_time_data.Set("bad_clock", false);
  64. load_time_data.Set("hide_primary_button", false);
  65. load_time_data.Set("tabTitle", l10n_util::GetStringUTF16(IDS_SSL_V2_TITLE));
  66. load_time_data.Set("heading", l10n_util::GetStringUTF16(IDS_SSL_V2_HEADING));
  67. load_time_data.Set(
  68. "primaryParagraph",
  69. l10n_util::GetStringFUTF16(
  70. IDS_SSL_V2_PRIMARY_PARAGRAPH,
  71. common_string_util::GetFormattedHostName(request_url_)));
  72. load_time_data.Set(
  73. "recurrentErrorParagraph",
  74. l10n_util::GetStringUTF16(IDS_SSL_V2_RECURRENT_ERROR_PARAGRAPH));
  75. load_time_data.Set("show_recurrent_error_paragraph",
  76. controller_->HasSeenRecurrentError());
  77. if (soft_override_enabled_)
  78. PopulateOverridableStrings(load_time_data);
  79. else
  80. PopulateNonOverridableStrings(load_time_data);
  81. }
  82. const net::SSLInfo& SSLErrorUI::ssl_info() const {
  83. return ssl_info_;
  84. }
  85. const base::Time& SSLErrorUI::time_triggered() const {
  86. return time_triggered_;
  87. }
  88. ControllerClient* SSLErrorUI::controller() const {
  89. return controller_;
  90. }
  91. int SSLErrorUI::cert_error() const {
  92. return cert_error_;
  93. }
  94. void SSLErrorUI::PopulateOverridableStrings(base::Value::Dict& load_time_data) {
  95. DCHECK(soft_override_enabled_);
  96. std::u16string url(common_string_util::GetFormattedHostName(request_url_));
  97. ssl_errors::ErrorInfo error_info = ssl_errors::ErrorInfo::CreateError(
  98. ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_),
  99. ssl_info_.cert.get(), request_url_);
  100. load_time_data.Set("overridable", true);
  101. load_time_data.Set("hide_primary_button", false);
  102. load_time_data.Set("explanationParagraph", error_info.details());
  103. load_time_data.Set(
  104. "primaryButtonText",
  105. l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_SAFETY_BUTTON));
  106. // On iOS, offer to close the page instead of navigating to NTP when unable to
  107. // go back. See crbug.com/1058476 for discussion.
  108. #if BUILDFLAG(IS_IOS)
  109. if (!controller()->CanGoBack()) {
  110. load_time_data.Set(
  111. "primaryButtonText",
  112. l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_CLOSE_PAGE_BUTTON));
  113. load_time_data.Set("primary_button_close_page", true);
  114. }
  115. #endif
  116. load_time_data.Set(
  117. "finalParagraph",
  118. l10n_util::GetStringFUTF16(IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH, url));
  119. }
  120. void SSLErrorUI::PopulateNonOverridableStrings(
  121. base::Value::Dict& load_time_data) {
  122. DCHECK(!soft_override_enabled_);
  123. std::u16string url(common_string_util::GetFormattedHostName(request_url_));
  124. ssl_errors::ErrorInfo::ErrorType type =
  125. ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_);
  126. load_time_data.Set("overridable", false);
  127. load_time_data.Set("hide_primary_button", false);
  128. load_time_data.Set(
  129. "explanationParagraph",
  130. l10n_util::GetStringFUTF16(IDS_SSL_NONOVERRIDABLE_MORE, url));
  131. load_time_data.Set("primaryButtonText",
  132. l10n_util::GetStringUTF16(IDS_SSL_RELOAD));
  133. // Customize the help link depending on the specific error type.
  134. // Only mark as HSTS if none of the more specific error types apply,
  135. // and use INVALID as a fallback if no other string is appropriate.
  136. load_time_data.Set("errorType", type);
  137. int help_string = IDS_SSL_NONOVERRIDABLE_INVALID;
  138. switch (type) {
  139. case ssl_errors::ErrorInfo::CERT_REVOKED:
  140. help_string = IDS_SSL_NONOVERRIDABLE_REVOKED;
  141. break;
  142. case ssl_errors::ErrorInfo::CERT_PINNED_KEY_MISSING:
  143. help_string = IDS_SSL_NONOVERRIDABLE_PINNED;
  144. break;
  145. case ssl_errors::ErrorInfo::CERT_INVALID:
  146. help_string = IDS_SSL_NONOVERRIDABLE_INVALID;
  147. break;
  148. default:
  149. if (requested_strict_enforcement_)
  150. help_string = IDS_SSL_NONOVERRIDABLE_HSTS;
  151. }
  152. load_time_data.Set("finalParagraph",
  153. l10n_util::GetStringFUTF16(help_string, url));
  154. }
  155. void SSLErrorUI::HandleCommand(SecurityInterstitialCommand command) {
  156. switch (command) {
  157. case CMD_DONT_PROCEED: {
  158. controller_->metrics_helper()->RecordUserDecision(
  159. MetricsHelper::DONT_PROCEED);
  160. user_made_decision_ = true;
  161. controller_->GoBack();
  162. break;
  163. }
  164. case CMD_PROCEED: {
  165. if (hard_override_enabled_) {
  166. controller_->metrics_helper()->RecordUserDecision(
  167. MetricsHelper::PROCEED);
  168. controller_->Proceed();
  169. user_made_decision_ = true;
  170. }
  171. break;
  172. }
  173. case CMD_DO_REPORT: {
  174. controller_->SetReportingPreference(true);
  175. break;
  176. }
  177. case CMD_DONT_REPORT: {
  178. controller_->SetReportingPreference(false);
  179. break;
  180. }
  181. case CMD_SHOW_MORE_SECTION: {
  182. controller_->metrics_helper()->RecordUserInteraction(
  183. security_interstitials::MetricsHelper::SHOW_ADVANCED);
  184. break;
  185. }
  186. case CMD_OPEN_HELP_CENTER: {
  187. controller_->metrics_helper()->RecordUserInteraction(
  188. security_interstitials::MetricsHelper::SHOW_LEARN_MORE);
  189. // Add cert error code as a ref to support URL, this is used to expand the
  190. // right section if the user is redirected to chrome://connection-help.
  191. GURL::Replacements replacements;
  192. // This has to be stored in a separate variable, otherwise asan throws a
  193. // use-after-scope error
  194. std::string cert_error_string = std::to_string(cert_error_);
  195. replacements.SetRefStr(cert_error_string);
  196. // If |support_url_| is invalid, use the default help center url.
  197. controller_->OpenUrlInNewForegroundTab(
  198. (support_url_.is_valid()
  199. ? support_url_
  200. : controller_->GetBaseHelpCenterUrl().Resolve(kHelpPath))
  201. .ReplaceComponents(replacements));
  202. break;
  203. }
  204. case CMD_RELOAD: {
  205. controller_->metrics_helper()->RecordUserInteraction(
  206. security_interstitials::MetricsHelper::RELOAD);
  207. controller_->Reload();
  208. break;
  209. }
  210. case CMD_OPEN_REPORTING_PRIVACY: {
  211. controller_->OpenExtendedReportingPrivacyPolicy(true);
  212. break;
  213. }
  214. case CMD_OPEN_WHITEPAPER: {
  215. controller_->OpenExtendedReportingWhitepaper(true);
  216. break;
  217. }
  218. case CMD_OPEN_ENHANCED_PROTECTION_SETTINGS: {
  219. controller_->metrics_helper()->RecordUserInteraction(
  220. security_interstitials::MetricsHelper::OPEN_ENHANCED_PROTECTION);
  221. controller_->OpenEnhancedProtectionSettings();
  222. break;
  223. }
  224. case CMD_OPEN_DATE_SETTINGS:
  225. case CMD_OPEN_DIAGNOSTIC:
  226. case CMD_OPEN_LOGIN:
  227. case CMD_REPORT_PHISHING_ERROR: {
  228. // Not supported by the SSL error page.
  229. NOTREACHED() << "Unsupported command: " << command;
  230. break;
  231. }
  232. case CMD_ERROR:
  233. case CMD_TEXT_FOUND:
  234. case CMD_TEXT_NOT_FOUND: {
  235. // Commands are for testing.
  236. break;
  237. }
  238. }
  239. }
  240. } // security_interstitials