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

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: Call the function from the Observe function 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
55 void RecordSSLInterstitialSeverityScore(float ssl_severity_score,
56 int cert_error) {
57 if (SSLErrorInfo::NetErrorToErrorType(cert_error) ==
58 SSLErrorInfo::CERT_DATE_INVALID) {
59 UMA_HISTOGRAM_CUSTOM_COUNTS("interstitial.ssl.severity_score.date_invalid",
60 static_cast<int>(ssl_severity_score * 100),
61 0, 100, 20);
62 }
63 }
64
32 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) { 65 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) {
33 if (overridable) { 66 if (overridable) {
34 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event, 67 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event,
35 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 68 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
36 } else { 69 } else {
37 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event, 70 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event,
38 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 71 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
39 } 72 }
40 } 73 }
41 74
75 void RecordCaptivePortalEventStats(SSLInterstitialCauseCaptivePortal event) {
76 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captive_portal",
77 event,
78 UNUSED_CAPTIVE_PORTAL_EVENT);
79 }
80
42 } // namespace 81 } // namespace
43 82
44 SSLErrorClassification::SSLErrorClassification( 83 SSLErrorClassification::SSLErrorClassification(
84 content::WebContents* web_contents,
45 base::Time current_time, 85 base::Time current_time,
86 int cert_error,
46 const net::X509Certificate& cert) 87 const net::X509Certificate& cert)
47 : current_time_(current_time), 88 : web_contents_(web_contents),
48 cert_(cert) { } 89 current_time_(current_time),
90 cert_error_(cert_error),
91 cert_(cert),
92 captive_portal_detection_enabled_(false),
93 captive_portal_probe_completed_(false),
94 captive_portal_no_response_(false),
95 captive_portal_detected_(false) {
96 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
97 Profile* profile = Profile::FromBrowserContext(
98 web_contents_->GetBrowserContext());
99 CaptivePortalService* captive_portal_service =
100 CaptivePortalServiceFactory::GetForProfile(profile);
101 captive_portal_detection_enabled_ = captive_portal_service ->enabled();
102 captive_portal_service ->DetectCaptivePortal();
103 registrar_.Add(this,
104 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
105 content::Source<Profile>(profile));
106 #endif
107 }
49 108
50 SSLErrorClassification::~SSLErrorClassification() { } 109 SSLErrorClassification::~SSLErrorClassification() { }
51 110
52 float SSLErrorClassification::InvalidDateSeverityScore() const { 111 void SSLErrorClassification::InvalidDateSeverityScore() const {
53 // Client-side characterisitics. Check whether the system's clock is wrong or 112 // 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. 113 // wrong and whether or not the user has encountered this error before.
55 float severity_date_score = 0.0f; 114 float severity_date_score = 0.0f;
56 115
57 static const float kClientWeight = 0.5f; 116 static const float kClientWeight = 0.5f;
58 static const float kSystemClockWeight = 0.75f; 117 static const float kSystemClockWeight = 0.75f;
59 static const float kSystemClockWrongWeight = 0.1f; 118 static const float kSystemClockWrongWeight = 0.1f;
60 static const float kSystemClockRightWeight = 1.0f; 119 static const float kSystemClockRightWeight = 1.0f;
61 120
62 static const float kServerWeight = 0.5f; 121 static const float kServerWeight = 0.5f;
63 static const float kCertificateExpiredWeight = 0.3f; 122 static const float kCertificateExpiredWeight = 0.3f;
64 static const float kNotYetValidWeight = 0.2f; 123 static const float kNotYetValidWeight = 0.2f;
(...skipping 10 matching lines...) Expand all
75 134
76 // Server-side characteristics. Check whether the certificate has expired or 135 // 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 136 // is not yet valid. If the certificate has expired then factor the time which
78 // has passed since expiry. 137 // has passed since expiry.
79 if (cert_.HasExpired()) { 138 if (cert_.HasExpired()) {
80 severity_date_score += kServerWeight * kCertificateExpiredWeight * 139 severity_date_score += kServerWeight * kCertificateExpiredWeight *
81 CalculateScoreTimePassedSinceExpiry(); 140 CalculateScoreTimePassedSinceExpiry();
82 } 141 }
83 if (current_time_ < cert_.valid_start()) 142 if (current_time_ < cert_.valid_start())
84 severity_date_score += kServerWeight * kNotYetValidWeight; 143 severity_date_score += kServerWeight * kNotYetValidWeight;
85 return severity_date_score; 144 RecordSSLInterstitialSeverityScore(severity_date_score, cert_error_);
145 }
146
147 void SSLErrorClassification::RecordUMAStatistics(bool overridable) const {
148 if (IsUserClockInThePast(base::Time::NowFromSystemTime()))
149 RecordSSLInterstitialCause(overridable, CLOCK_PAST);
150 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime()))
151 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE);
152 }
153
154 void SSLErrorClassification::RecordCaptivePortalUMAStatistics(
155 bool overridable) const {
156 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
157 if (captive_portal_detection_enabled_)
158 RecordCaptivePortalEventStats(
159 overridable ?
160 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE :
161 CAPTIVE_PORTAL_DETECTION_ENABLED);
162 if (captive_portal_probe_completed_)
163 RecordCaptivePortalEventStats(
164 overridable ?
165 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE :
166 CAPTIVE_PORTAL_PROBE_COMPLETED);
167 // Log only one of portal detected and no response results.
168 if (captive_portal_detected_)
169 RecordCaptivePortalEventStats(
170 overridable ?
171 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE :
172 CAPTIVE_PORTAL_DETECTED);
173 else if (captive_portal_no_response_)
174 RecordCaptivePortalEventStats(
175 overridable ?
176 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE :
177 CAPTIVE_PORTAL_NO_RESPONSE);
178 #endif
86 } 179 }
87 180
88 base::TimeDelta SSLErrorClassification::TimePassedSinceExpiry() const { 181 base::TimeDelta SSLErrorClassification::TimePassedSinceExpiry() const {
89 base::TimeDelta delta = current_time_ - cert_.valid_expiry(); 182 base::TimeDelta delta = current_time_ - cert_.valid_expiry();
90 return delta; 183 return delta;
91 } 184 }
92 185
93 float SSLErrorClassification::CalculateScoreTimePassedSinceExpiry() const { 186 float SSLErrorClassification::CalculateScoreTimePassedSinceExpiry() const {
94 base::TimeDelta delta = TimePassedSinceExpiry(); 187 base::TimeDelta delta = TimePassedSinceExpiry();
95 int64 time_passed = delta.InDays(); 188 int64 time_passed = delta.InDays();
96 const int64 kHighThreshold = 7; 189 const int64 kHighThreshold = 7;
97 const int64 kLowThreshold = 4; 190 const int64 kLowThreshold = 4;
98 static const float kHighThresholdWeight = 0.4f; 191 static const float kHighThresholdWeight = 0.4f;
99 static const float kMediumThresholdWeight = 0.3f; 192 static const float kMediumThresholdWeight = 0.3f;
100 static const float kLowThresholdWeight = 0.2f; 193 static const float kLowThresholdWeight = 0.2f;
101 if (time_passed >= kHighThreshold) 194 if (time_passed >= kHighThreshold)
102 return kHighThresholdWeight; 195 return kHighThresholdWeight;
103 else if (time_passed >= kLowThreshold) 196 else if (time_passed >= kLowThreshold)
104 return kMediumThresholdWeight; 197 return kMediumThresholdWeight;
105 else 198 else
106 return kLowThresholdWeight; 199 return kLowThresholdWeight;
107 } 200 }
108 201
202 float SSLErrorClassification::CalculateScoreEnvironments() const {
203 static const float kWifiWeight = 0.7f;
204 static const float kCellularWeight = 0.7f;
205 static const float kHotspotWeight = 0.2f;
206 static const float kEthernetWeight = 0.7f;
207 static const float kOtherWeight = 0.7f;
208 net::NetworkChangeNotifier::ConnectionType type =
209 net::NetworkChangeNotifier::GetConnectionType();
210 if (type == net::NetworkChangeNotifier::CONNECTION_WIFI)
211 return kWifiWeight;
212 if (type == net::NetworkChangeNotifier::CONNECTION_2G ||
213 type == net::NetworkChangeNotifier::CONNECTION_3G ||
214 type == net::NetworkChangeNotifier::CONNECTION_4G ) {
215 return kCellularWeight;
216 }
217 if (type == net::NetworkChangeNotifier::CONNECTION_ETHERNET)
218 return kEthernetWeight;
219 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
220 // Assume if captive portals are detected then the user is connected using a
221 // hot spot.
222 if (captive_portal_probe_completed_ && captive_portal_detected_)
223 return kHotspotWeight;
224 #endif
225 return kOtherWeight;
226 }
227
109 bool SSLErrorClassification::IsUserClockInThePast(base::Time time_now) { 228 bool SSLErrorClassification::IsUserClockInThePast(base::Time time_now) {
110 base::Time build_time = base::GetBuildTime(); 229 base::Time build_time = base::GetBuildTime();
111 if (time_now < build_time - base::TimeDelta::FromDays(2)) 230 if (time_now < build_time - base::TimeDelta::FromDays(2))
112 return true; 231 return true;
113 return false; 232 return false;
114 } 233 }
115 234
116 bool SSLErrorClassification::IsUserClockInTheFuture(base::Time time_now) { 235 bool SSLErrorClassification::IsUserClockInTheFuture(base::Time time_now) {
117 base::Time build_time = base::GetBuildTime(); 236 base::Time build_time = base::GetBuildTime();
118 if (time_now > build_time + base::TimeDelta::FromDays(365)) 237 if (time_now > build_time + base::TimeDelta::FromDays(365))
119 return true; 238 return true;
120 return false; 239 return false;
121 } 240 }
122 241
123 bool SSLErrorClassification::IsWindowsVersionSP3OrLower() { 242 bool SSLErrorClassification::IsWindowsVersionSP3OrLower() {
124 #if defined(OS_WIN) 243 #if defined(OS_WIN)
125 const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance(); 244 const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
126 base::win::OSInfo::ServicePack service_pack = os_info->service_pack(); 245 base::win::OSInfo::ServicePack service_pack = os_info->service_pack();
127 if (os_info->version() < base::win::VERSION_VISTA && service_pack.major < 3) 246 if (os_info->version() < base::win::VERSION_VISTA && service_pack.major < 3)
128 return true; 247 return true;
129 #endif 248 #endif
130 return false; 249 return false;
131 } 250 }
132 251
133 void SSLErrorClassification::RecordUMAStatistics(bool overridable) { 252 void SSLErrorClassification::Observe(
134 if (IsUserClockInThePast(base::Time::NowFromSystemTime())) 253 int type,
135 RecordSSLInterstitialCause(overridable, CLOCK_PAST); 254 const content::NotificationSource& source,
136 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime())) 255 const content::NotificationDetails& details) {
137 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); 256 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
257 // When detection is disabled, captive portal service always sends
258 // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
259 if (!captive_portal_detection_enabled_)
260 return;
261 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
262 captive_portal_probe_completed_ = true;
263 CaptivePortalService::Results* results =
264 content::Details<CaptivePortalService::Results>(
265 details).ptr();
266 // If a captive portal was detected at any point when the interstitial was
267 // displayed, assume that the interstitial was caused by a captive portal.
268 // Example scenario:
269 // 1- Interstitial displayed and captive portal detected, setting the flag.
270 // 2- Captive portal detection automatically opens portal login page.
271 // 3- User logs in on the portal login page.
272 // A notification will be received here for RESULT_INTERNET_CONNECTED. Make
273 // sure we don't clear the captive protal flag, since the interstitial was
274 // potentially caused by the captive portal.
275 captive_portal_detected_ = captive_portal_detected_ ||
276 (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
277 // Also keep track of non-HTTP portals and error cases.
278 captive_portal_no_response_ = captive_portal_no_response_ ||
279 (results->result == captive_portal::RESULT_NO_RESPONSE);
280 if (SSLErrorInfo::NetErrorToErrorType(cert_error_) ==
281 SSLErrorInfo::CERT_DATE_INVALID) {
282 InvalidDateSeverityScore();
radhikabhar 2014/07/28 23:02:35 Since the function for CalculateScoreEnvironments
283 }
284 }
285 #endif
138 } 286 }
OLDNEW
« no previous file with comments | « chrome/browser/ssl/ssl_error_classification.h ('k') | chrome/browser/ssl/ssl_error_classification_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698