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/interstitials/security_interstitial_metrics_helper.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ssl/ssl_cert_reporter.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/grit/generated_resources.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 CertificateErrorReport::InterstitialReason interstitial_reason
,
39 SecurityInterstitialMetricsHelper
* 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
) {
49 CertReportHelper::~CertReportHelper() {
52 void CertReportHelper::PopulateExtendedReportingOption(
53 base::DictionaryValue
* load_time_data
) {
54 // Only show the checkbox if not off-the-record and if this client is
55 // part of the respective Finch group, and the feature is not disabled
57 const bool show
= ShouldShowCertificateReporterCheckbox();
59 load_time_data
->SetBoolean(interstitials::kDisplayCheckBox
, show
);
63 load_time_data
->SetBoolean(
64 interstitials::kBoxChecked
,
65 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled
));
67 const std::string privacy_link
= base::StringPrintf(
68 interstitials::kPrivacyLinkHtml
,
69 SecurityInterstitialPage::CMD_OPEN_REPORTING_PRIVACY
,
70 l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE
).c_str());
72 load_time_data
->SetString(
73 interstitials::kOptInLink
,
74 l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE
,
75 base::UTF8ToUTF16(privacy_link
)));
78 void CertReportHelper::FinishCertCollection(
79 CertificateErrorReport::ProceedDecision user_proceeded
) {
80 if (!ShouldShowCertificateReporterCheckbox())
83 if (!IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled
))
86 if (metrics_helper_
) {
87 metrics_helper_
->RecordUserInteraction(
88 SecurityInterstitialMetricsHelper::EXTENDED_REPORTING_IS_ENABLED
);
91 if (!ShouldReportCertificateError())
94 std::string serialized_report
;
95 CertificateErrorReport
report(request_url_
.host(), ssl_info_
);
97 report
.SetInterstitialInfo(
98 interstitial_reason_
, user_proceeded
,
99 overridable_
? CertificateErrorReport::INTERSTITIAL_OVERRIDABLE
100 : CertificateErrorReport::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
);