Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: chrome/browser/ssl/ssl_error_classification.cc

Issue 400323002: Refactor the captive portal code to move from the ssl_blocking_page class to the ssl_error_classific (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved the histogram stuff Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ssl/ssl_error_classification.h" 5 #include "chrome/browser/ssl/ssl_error_classification.h"
6 6
7 #include "base/build_time.h" 7 #include "base/build_time.h"
8 #include "base/metrics/field_trial.h" 8 #include "base/metrics/field_trial.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
11 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
12 #include "components/network_time/network_time_tracker.h" 12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ssl/ssl_error_info.h"
15 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/web_contents.h"
17 #include "net/base/network_change_notifier.h"
13 #include "net/cert/x509_certificate.h" 18 #include "net/cert/x509_certificate.h"
14 19
20 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
21 #include "chrome/browser/captive_portal/captive_portal_service.h"
22 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
23 #endif
24
25 #if defined(OS_WIN)
26 #include "base/win/windows_version.h"
27 #endif
28
15 using base::Time; 29 using base::Time;
16 using base::TimeTicks; 30 using base::TimeTicks;
17 using base::TimeDelta; 31 using base::TimeDelta;
18 32
19 #if defined(OS_WIN)
20 #include "base/win/windows_version.h"
21 #endif
22
23 namespace { 33 namespace {
24 34
25 // Events for UMA. Do not reorder or change! 35 // Events for UMA. Do not reorder or change!
26 enum SSLInterstitialCause { 36 enum SSLInterstitialCause {
27 CLOCK_PAST, 37 CLOCK_PAST,
28 CLOCK_FUTURE, 38 CLOCK_FUTURE,
29 UNUSED_INTERSTITIAL_CAUSE_ENTRY, 39 UNUSED_INTERSTITIAL_CAUSE_ENTRY,
30 }; 40 };
31 41
42 // Events for UMA. Do not reorder or change!
43 enum SSLInterstitialCauseCaptivePortal {
44 CAPTIVE_PORTAL_DETECTION_ENABLED,
45 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
46 CAPTIVE_PORTAL_PROBE_COMPLETED,
47 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
48 CAPTIVE_PORTAL_NO_RESPONSE,
49 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
50 CAPTIVE_PORTAL_DETECTED,
51 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
52 UNUSED_CAPTIVE_PORTAL_EVENT,
53 };
54
32 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) { 55 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) {
33 if (overridable) { 56 if (overridable) {
34 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event, 57 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event,
35 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 58 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
36 } else { 59 } else {
37 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event, 60 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event,
38 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 61 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
39 } 62 }
40 } 63 }
41 64
65 void RecordCaptivePortalEventStats(SSLInterstitialCauseCaptivePortal event) {
66 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captive_portal",
67 event,
68 UNUSED_CAPTIVE_PORTAL_EVENT);
69 }
70
42 } // namespace 71 } // namespace
43 72
44 SSLErrorClassification::SSLErrorClassification( 73 SSLErrorClassification::SSLErrorClassification(
74 content::WebContents* web_contents,
45 base::Time current_time, 75 base::Time current_time,
76 int cert_error,
46 const net::X509Certificate& cert) 77 const net::X509Certificate& cert)
47 : current_time_(current_time), 78 : web_contents_(web_contents),
48 cert_(cert) { } 79 current_time_(current_time),
80 cert_error_(cert_error),
81 cert_(cert),
82 captive_portal_detection_enabled_(false),
83 captive_portal_probe_completed_(false),
84 captive_portal_no_response_(false),
85 captive_portal_detected_(false) {
86 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
87 Profile* profile = Profile::FromBrowserContext(
88 web_contents_->GetBrowserContext());
89 CaptivePortalService* captive_portal_service =
90 CaptivePortalServiceFactory::GetForProfile(profile);
91 captive_portal_detection_enabled_ = captive_portal_service ->enabled();
92 captive_portal_service ->DetectCaptivePortal();
93 registrar_.Add(this,
94 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
95 content::Source<Profile>(profile));
96 #endif
97 }
49 98
50 SSLErrorClassification::~SSLErrorClassification() { } 99 SSLErrorClassification::~SSLErrorClassification() { }
51 100
52 float SSLErrorClassification::InvalidDateSeverityScore() const { 101 void SSLErrorClassification::InvalidDateSeverityScore() const {
53 // Client-side characterisitics. Check whether the system's clock is wrong or 102 // Client-side characteristics. Check whether or not the system's clock is
54 // not and whether the user has encountered this error before or not. 103 // wrong and whether or not the user has encountered this error before.
55 float severity_date_score = 0.0f; 104 float severity_date_score = 0.0f;
56 105
57 static const float kClientWeight = 0.5f; 106 static const float kClientWeight = 0.5f;
58 static const float kSystemClockWeight = 0.75f; 107 static const float kSystemClockWeight = 0.75f;
59 static const float kSystemClockWrongWeight = 0.1f; 108 static const float kSystemClockWrongWeight = 0.1f;
60 static const float kSystemClockRightWeight = 1.0f; 109 static const float kSystemClockRightWeight = 1.0f;
61 110
62 static const float kServerWeight = 0.5f; 111 static const float kServerWeight = 0.5f;
63 static const float kCertificateExpiredWeight = 0.3f; 112 static const float kCertificateExpiredWeight = 0.3f;
64 static const float kNotYetValidWeight = 0.2f; 113 static const float kNotYetValidWeight = 0.2f;
65 114
66 if (IsUserClockInThePast(current_time_) || 115 if (IsUserClockInThePast(current_time_) ||
67 IsUserClockInTheFuture(current_time_)) { 116 IsUserClockInTheFuture(current_time_)) {
68 severity_date_score = kClientWeight * kSystemClockWeight * 117 severity_date_score = kClientWeight * kSystemClockWeight *
69 kSystemClockWrongWeight; 118 kSystemClockWrongWeight;
70 } else { 119 } else {
71 severity_date_score = kClientWeight * kSystemClockWeight * 120 severity_date_score = kClientWeight * kSystemClockWeight *
72 kSystemClockRightWeight; 121 kSystemClockRightWeight;
73 } 122 }
74 // TODO(radhikabhar): (crbug.com/393262) Check website settings. 123 // TODO(radhikabhar): (crbug.com/393262) Check website settings.
75 124
76 // Server-side characteristics. Check whether the certificate has expired or 125 // Server-side characteristics. Check whether the certificate has expired or
77 // is not yet valid. If the certificate has expired then factor the time which 126 // is not yet valid. If the certificate has expired then factor the time which
78 // has passed since expiry. 127 // has passed since expiry.
79 if (cert_.HasExpired()) { 128 if (cert_.HasExpired()) {
80 severity_date_score += kServerWeight * kCertificateExpiredWeight * 129 severity_date_score += kServerWeight * kCertificateExpiredWeight *
81 CalculateScoreTimePassedSinceExpiry(); 130 CalculateScoreTimePassedSinceExpiry();
82 } 131 }
83 if (current_time_ < cert_.valid_start()) 132 if (current_time_ < cert_.valid_start())
84 severity_date_score += kServerWeight * kNotYetValidWeight; 133 severity_date_score += kServerWeight * kNotYetValidWeight;
felt 2014/07/29 01:47:53 This no longer has a return value, so what's the
radhikabhar 2014/07/29 17:56:56 Again, I was thinking way ahead here when I have t
85 return severity_date_score; 134 }
135
136 void SSLErrorClassification::RecordUMAStatistics(bool overridable) const {
137 if (IsUserClockInThePast(base::Time::NowFromSystemTime()))
138 RecordSSLInterstitialCause(overridable, CLOCK_PAST);
139 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime()))
140 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE);
141 }
142
143 void SSLErrorClassification::RecordCaptivePortalUMAStatistics(
144 bool overridable) const {
145 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
146 if (captive_portal_detection_enabled_)
147 RecordCaptivePortalEventStats(
148 overridable ?
149 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE :
150 CAPTIVE_PORTAL_DETECTION_ENABLED);
151 if (captive_portal_probe_completed_)
152 RecordCaptivePortalEventStats(
153 overridable ?
154 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE :
155 CAPTIVE_PORTAL_PROBE_COMPLETED);
156 // Log only one of portal detected and no response results.
157 if (captive_portal_detected_)
158 RecordCaptivePortalEventStats(
159 overridable ?
160 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE :
161 CAPTIVE_PORTAL_DETECTED);
162 else if (captive_portal_no_response_)
163 RecordCaptivePortalEventStats(
164 overridable ?
165 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE :
166 CAPTIVE_PORTAL_NO_RESPONSE);
167 #endif
86 } 168 }
87 169
88 base::TimeDelta SSLErrorClassification::TimePassedSinceExpiry() const { 170 base::TimeDelta SSLErrorClassification::TimePassedSinceExpiry() const {
89 base::TimeDelta delta = current_time_ - cert_.valid_expiry(); 171 base::TimeDelta delta = current_time_ - cert_.valid_expiry();
90 return delta; 172 return delta;
91 } 173 }
92 174
93 float SSLErrorClassification::CalculateScoreTimePassedSinceExpiry() const { 175 float SSLErrorClassification::CalculateScoreTimePassedSinceExpiry() const {
94 base::TimeDelta delta = TimePassedSinceExpiry(); 176 base::TimeDelta delta = TimePassedSinceExpiry();
95 int64 time_passed = delta.InDays(); 177 int64 time_passed = delta.InDays();
96 const int64 kHighThreshold = 7; 178 const int64 kHighThreshold = 7;
97 const int64 kLowThreshold = 4; 179 const int64 kLowThreshold = 4;
98 static const float kHighThresholdWeight = 0.4f; 180 static const float kHighThresholdWeight = 0.4f;
99 static const float kMediumThresholdWeight = 0.3f; 181 static const float kMediumThresholdWeight = 0.3f;
100 static const float kLowThresholdWeight = 0.2f; 182 static const float kLowThresholdWeight = 0.2f;
101 if (time_passed >= kHighThreshold) 183 if (time_passed >= kHighThreshold)
102 return kHighThresholdWeight; 184 return kHighThresholdWeight;
103 else if (time_passed >= kLowThreshold) 185 else if (time_passed >= kLowThreshold)
104 return kMediumThresholdWeight; 186 return kMediumThresholdWeight;
105 else 187 else
106 return kLowThresholdWeight; 188 return kLowThresholdWeight;
107 } 189 }
108 190
191 float SSLErrorClassification::CalculateScoreEnvironments() const {
felt 2014/07/29 01:47:53 I'm confused, I still don't see this being invoked
radhikabhar 2014/07/29 17:56:56 This function only makes sense for the CERT_COMMON
192 static const float kWifiWeight = 0.7f;
193 static const float kCellularWeight = 0.7f;
194 static const float kHotspotWeight = 0.2f;
195 static const float kEthernetWeight = 0.7f;
196 static const float kOtherWeight = 0.7f;
197 net::NetworkChangeNotifier::ConnectionType type =
198 net::NetworkChangeNotifier::GetConnectionType();
199 if (type == net::NetworkChangeNotifier::CONNECTION_WIFI)
200 return kWifiWeight;
201 if (type == net::NetworkChangeNotifier::CONNECTION_2G ||
202 type == net::NetworkChangeNotifier::CONNECTION_3G ||
203 type == net::NetworkChangeNotifier::CONNECTION_4G ) {
204 return kCellularWeight;
205 }
206 if (type == net::NetworkChangeNotifier::CONNECTION_ETHERNET)
207 return kEthernetWeight;
208 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
209 // Assume if captive portals are detected then the user is connected using a
210 // hot spot.
211 if (captive_portal_probe_completed_ && captive_portal_detected_)
212 return kHotspotWeight;
213 #endif
214 return kOtherWeight;
215 }
216
109 bool SSLErrorClassification::IsUserClockInThePast(base::Time time_now) { 217 bool SSLErrorClassification::IsUserClockInThePast(base::Time time_now) {
110 base::Time build_time = base::GetBuildTime(); 218 base::Time build_time = base::GetBuildTime();
111 if (time_now < build_time - base::TimeDelta::FromDays(2)) 219 if (time_now < build_time - base::TimeDelta::FromDays(2))
112 return true; 220 return true;
113 return false; 221 return false;
114 } 222 }
115 223
116 bool SSLErrorClassification::IsUserClockInTheFuture(base::Time time_now) { 224 bool SSLErrorClassification::IsUserClockInTheFuture(base::Time time_now) {
117 base::Time build_time = base::GetBuildTime(); 225 base::Time build_time = base::GetBuildTime();
118 if (time_now > build_time + base::TimeDelta::FromDays(365)) 226 if (time_now > build_time + base::TimeDelta::FromDays(365))
119 return true; 227 return true;
120 return false; 228 return false;
121 } 229 }
122 230
123 bool SSLErrorClassification::IsWindowsVersionSP3OrLower() { 231 bool SSLErrorClassification::IsWindowsVersionSP3OrLower() {
124 #if defined(OS_WIN) 232 #if defined(OS_WIN)
125 const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance(); 233 const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
126 base::win::OSInfo::ServicePack service_pack = os_info->service_pack(); 234 base::win::OSInfo::ServicePack service_pack = os_info->service_pack();
127 if (os_info->version() < base::win::VERSION_VISTA && service_pack.major < 3) 235 if (os_info->version() < base::win::VERSION_VISTA && service_pack.major < 3)
128 return true; 236 return true;
129 #endif 237 #endif
130 return false; 238 return false;
131 } 239 }
132 240
133 void SSLErrorClassification::RecordUMAStatistics(bool overridable) { 241 void SSLErrorClassification::Observe(
134 if (IsUserClockInThePast(base::Time::NowFromSystemTime())) 242 int type,
135 RecordSSLInterstitialCause(overridable, CLOCK_PAST); 243 const content::NotificationSource& source,
136 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime())) 244 const content::NotificationDetails& details) {
137 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); 245 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
246 // When detection is disabled, captive portal service always sends
247 // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
248 if (!captive_portal_detection_enabled_)
249 return;
250 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
251 captive_portal_probe_completed_ = true;
252 CaptivePortalService::Results* results =
253 content::Details<CaptivePortalService::Results>(
254 details).ptr();
255 // If a captive portal was detected at any point when the interstitial was
256 // displayed, assume that the interstitial was caused by a captive portal.
257 // Example scenario:
258 // 1- Interstitial displayed and captive portal detected, setting the flag.
259 // 2- Captive portal detection automatically opens portal login page.
260 // 3- User logs in on the portal login page.
261 // A notification will be received here for RESULT_INTERNET_CONNECTED. Make
262 // sure we don't clear the captive protal flag, since the interstitial was
263 // potentially caused by the captive portal.
264 captive_portal_detected_ = captive_portal_detected_ ||
265 (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
266 // Also keep track of non-HTTP portals and error cases.
267 captive_portal_no_response_ = captive_portal_no_response_ ||
268 (results->result == captive_portal::RESULT_NO_RESPONSE);
269 if (SSLErrorInfo::NetErrorToErrorType(cert_error_) ==
270 SSLErrorInfo::CERT_DATE_INVALID) {
271 InvalidDateSeverityScore();
272 }
273 }
274 #endif
138 } 275 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698