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.
5 #include "chrome/browser/ssl/cert_report_helper.h"
7 #include "base/logging.h"
8 #include "base/metrics/field_trial.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/rand_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ssl/ssl_cert_reporter.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/grit/generated_resources.h"
18 #include "components/security_interstitials/core/metrics_helper.h"
19 #include "components/variations/variations_associated_data.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/web_contents.h"
22 #include "ui/base/l10n/l10n_util.h"
24 // Constants for the HTTPSErrorReporter Finch experiment
25 const char CertReportHelper::kFinchExperimentName
[] = "ReportCertificateErrors";
26 const char CertReportHelper::kFinchGroupShowPossiblySend
[] =
27 "ShowAndPossiblySend";
28 const char CertReportHelper::kFinchGroupDontShowDontSend
[] =
29 "DontShowAndDontSend";
30 const char CertReportHelper::kFinchParamName
[] = "sendingThreshold";
32 CertReportHelper::CertReportHelper(
33 scoped_ptr
<SSLCertReporter
> ssl_cert_reporter
,
34 content::WebContents
* web_contents
,
35 const GURL
& request_url
,
36 const net::SSLInfo
& ssl_info
,
37 certificate_reporting::ErrorReport::InterstitialReason interstitial_reason
,
39 security_interstitials::MetricsHelper
* metrics_helper
)
40 : ssl_cert_reporter_(ssl_cert_reporter
.Pass()),
41 web_contents_(web_contents
),
42 request_url_(request_url
),
44 interstitial_reason_(interstitial_reason
),
45 overridable_(overridable
),
46 metrics_helper_(metrics_helper
) {}
48 CertReportHelper::~CertReportHelper() {
51 void CertReportHelper::PopulateExtendedReportingOption(
52 base::DictionaryValue
* load_time_data
) {
53 // Only show the checkbox if not off-the-record and if this client is
54 // part of the respective Finch group, and the feature is not disabled
56 const bool show
= ShouldShowCertificateReporterCheckbox();
58 load_time_data
->SetBoolean(interstitials::kDisplayCheckBox
, show
);
62 load_time_data
->SetBoolean(
63 interstitials::kBoxChecked
,
64 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled
));
66 const std::string privacy_link
= base::StringPrintf(
67 interstitials::kPrivacyLinkHtml
,
68 SecurityInterstitialPage::CMD_OPEN_REPORTING_PRIVACY
,
69 l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE
).c_str());
71 load_time_data
->SetString(
72 interstitials::kOptInLink
,
73 l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE
,
74 base::UTF8ToUTF16(privacy_link
)));
77 void CertReportHelper::FinishCertCollection(
78 certificate_reporting::ErrorReport::ProceedDecision user_proceeded
) {
79 if (!ShouldShowCertificateReporterCheckbox())
82 if (!IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled
))
85 if (metrics_helper_
) {
86 metrics_helper_
->RecordUserInteraction(
87 security_interstitials::MetricsHelper::EXTENDED_REPORTING_IS_ENABLED
);
90 if (!ShouldReportCertificateError())
93 std::string serialized_report
;
94 certificate_reporting::ErrorReport
report(request_url_
.host(), ssl_info_
);
96 report
.SetInterstitialInfo(
97 interstitial_reason_
, user_proceeded
,
99 ? certificate_reporting::ErrorReport::INTERSTITIAL_OVERRIDABLE
100 : certificate_reporting::ErrorReport::INTERSTITIAL_NOT_OVERRIDABLE
);
102 if (!report
.Serialize(&serialized_report
)) {
103 LOG(ERROR
) << "Failed to serialize certificate report.";
107 ssl_cert_reporter_
->ReportInvalidCertificateChain(serialized_report
);
110 void CertReportHelper::SetSSLCertReporterForTesting(
111 scoped_ptr
<SSLCertReporter
> ssl_cert_reporter
) {
112 ssl_cert_reporter_
= ssl_cert_reporter
.Pass();
115 bool CertReportHelper::ShouldShowCertificateReporterCheckbox() {
119 // Only show the checkbox iff the user is part of the respective Finch group
120 // and the window is not incognito and the feature is not disabled by policy.
121 const bool in_incognito
=
122 web_contents_
->GetBrowserContext()->IsOffTheRecord();
123 return base::FieldTrialList::FindFullName(kFinchExperimentName
) ==
124 kFinchGroupShowPossiblySend
&&
126 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingOptInAllowed
);
130 bool CertReportHelper::ShouldReportCertificateError() {
132 DCHECK(ShouldShowCertificateReporterCheckbox());
133 // Even in case the checkbox was shown, we don't send error reports
134 // for all of these users. Check the Finch configuration for a sending
135 // threshold and only send reports in case the threshold isn't exceeded.
136 const std::string param
=
137 variations::GetVariationParamValue(kFinchExperimentName
, kFinchParamName
);
138 if (!param
.empty()) {
139 double sendingThreshold
;
140 if (base::StringToDouble(param
, &sendingThreshold
)) {
141 if (sendingThreshold
>= 0.0 && sendingThreshold
<= 1.0)
142 return base::RandDouble() <= sendingThreshold
;
149 bool CertReportHelper::IsPrefEnabled(const char* pref
) {
151 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
152 return profile
->GetPrefs()->GetBoolean(pref
);