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

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: Added comments Created 6 years, 5 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 "content/public/browser/notification_service.h"
15 #include "content/public/browser/web_contents.h"
16 #include "net/base/network_change_notifier.h"
13 #include "net/cert/x509_certificate.h" 17 #include "net/cert/x509_certificate.h"
14 18
19 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
20 #include "chrome/browser/captive_portal/captive_portal_service.h"
21 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
22 #endif
23
15 using base::Time; 24 using base::Time;
16 using base::TimeTicks; 25 using base::TimeTicks;
17 using base::TimeDelta; 26 using base::TimeDelta;
18 27
19 namespace { 28 namespace {
20 29
21 // Events for UMA. Do not reorder or change! 30 // Events for UMA. Do not reorder or change!
22 enum SSLInterstitialCause { 31 enum SSLInterstitialCause {
23 CLOCK_PAST, 32 CLOCK_PAST,
24 CLOCK_FUTURE, 33 CLOCK_FUTURE,
25 UNUSED_INTERSTITIAL_CAUSE_ENTRY, 34 UNUSED_INTERSTITIAL_CAUSE_ENTRY,
26 }; 35 };
27 36
37 // Events for UMA. Do not reorder or change!
38 enum SSLBlockingPageCaptivePortal {
felt 2014/07/18 23:53:42 SSLInterstitialCauseCaptivePortal maybe?
radhikabhar 2014/07/21 16:05:11 Done.
39 CAPTIVE_PORTAL_DETECTION_ENABLED,
40 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
41 CAPTIVE_PORTAL_PROBE_COMPLETED,
42 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
43 CAPTIVE_PORTAL_NO_RESPONSE,
44 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
45 CAPTIVE_PORTAL_DETECTED,
46 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
47 UNUSED_CAPTIVE_PORTAL_EVENT,
48 };
49
50 // Scores/weights which will be constant through all the SSL error types.
51 static const float kServerWeight = 0.5f;
52 static const float kClientWeight = 0.5f;
53
28 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) { 54 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) {
29 if (overridable) { 55 if (overridable) {
30 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event, 56 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event,
31 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 57 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
32 } else { 58 } else {
33 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event, 59 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event,
34 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 60 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
35 } 61 }
36 } 62 }
37 63
64 void RecordCaptivePortalEventStats(SSLBlockingPageCaptivePortal event) {
65 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captiveportal",
felt 2014/07/18 23:53:42 interstitial.ssl.captive_portal I think would be i
radhikabhar 2014/07/23 21:41:28 Done.
66 event,
67 UNUSED_CAPTIVE_PORTAL_EVENT);
68 }
69
38 } // namespace 70 } // namespace
39 71
40 SSLErrorClassification::SSLErrorClassification( 72 SSLErrorClassification::SSLErrorClassification(
73 content::WebContents& web_contents,
41 base::Time current_time, 74 base::Time current_time,
42 const net::X509Certificate& cert) 75 const net::X509Certificate& cert)
43 : current_time_(current_time), 76 : web_contents_(web_contents),
44 cert_(cert) { } 77 current_time_(current_time),
78 cert_(cert),
79 captive_portal_detection_enabled_(false),
80 captive_portal_probe_completed_(false),
81 captive_portal_no_response_(false),
82 captive_portal_detected_(false) {
83 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
84 Profile* profile = Profile::FromBrowserContext(
85 web_contents_.GetBrowserContext());
86 CaptivePortalService* captive_portal_service =
87 CaptivePortalServiceFactory::GetForProfile(profile);
88 captive_portal_detection_enabled_ = captive_portal_service ->enabled();
89 captive_portal_service ->DetectCaptivePortal();
90 registrar_.Add(this,
91 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
92 content::Source<Profile>(profile));
93 #endif
94 }
45 95
46 SSLErrorClassification::~SSLErrorClassification() { } 96 SSLErrorClassification::~SSLErrorClassification() { }
47 97
48 float SSLErrorClassification::InvalidDateSeverityScore() const { 98 float SSLErrorClassification::InvalidDateSeverityScore() const{
49 // Client-side characterisitics. Check whether the system's clock is wrong or 99 // Client-side characteristics. Check whether or not the system's clock is
50 // not and whether the user has encountered this error before or not. 100 // wrong and whether or not the user has already encountered this error
101 // before.
51 float severity_date_score = 0.0f; 102 float severity_date_score = 0.0f;
52 103
53 static const float kClientWeight = 0.5f; 104 static const float kCertificateExpiredWeight = 0.3f;
105 static const float kNotYetValidWeight = 0.2f;
106
54 static const float kSystemClockWeight = 0.75f; 107 static const float kSystemClockWeight = 0.75f;
55 static const float kSystemClockWrongWeight = 0.1f; 108 static const float kSystemClockWrongWeight = 0.1f;
56 static const float kSystemClockRightWeight = 1.0f; 109 static const float kSystemClockRightWeight = 1.0f;
57 110
58 static const float kServerWeight = 0.5f;
59 static const float kCertificateExpiredWeight = 0.3f;
60 static const float kNotYetValidWeight = 0.2f;
61
62 if (IsUserClockInThePast(current_time_) || 111 if (IsUserClockInThePast(current_time_) ||
63 IsUserClockInTheFuture(current_time_)) { 112 IsUserClockInTheFuture(current_time_)) {
64 severity_date_score = kClientWeight * kSystemClockWeight * 113 severity_date_score += kClientWeight * kSystemClockWeight *
65 kSystemClockWrongWeight; 114 kSystemClockWrongWeight;
66 } else { 115 } else {
67 severity_date_score = kClientWeight * kSystemClockWeight * 116 severity_date_score += kClientWeight * kSystemClockWeight *
68 kSystemClockRightWeight; 117 kSystemClockRightWeight;
69 } 118 }
70 // TODO(radhikabhar): (crbug.com/393262) Check website settings. 119 // TODO(radhikabhar): (crbug.com/393262) Check website settings.
71 120
72 // Server-side characteristics. Check whether the certificate has expired or 121 // Server-side characteristics. Check whether the certificate has expired or
73 // is not yet valid. If the certificate has expired then factor the time which 122 // is not yet valid. If the certificate has expired then factor the time which
74 // has passed since expiry. 123 // has passed since expiry.
75 if (cert_.HasExpired()) { 124 if (cert_.HasExpired()) {
76 severity_date_score += kServerWeight * kCertificateExpiredWeight * 125 severity_date_score += kServerWeight * kCertificateExpiredWeight *
77 CalculateScoreTimePassedSinceExpiry(); 126 CalculateScoreTimePassedSinceExpiry();
78 } 127 }
79 if (current_time_ < cert_.valid_start()) 128 if (current_time_ < cert_.valid_start())
80 severity_date_score += kServerWeight * kNotYetValidWeight; 129 severity_date_score += kServerWeight * kNotYetValidWeight;
81 return severity_date_score; 130 return severity_date_score;
82 } 131 }
83 132
133 void SSLErrorClassification::RecordUMAStatistics(bool overridable) {
134 if (IsUserClockInThePast(base::Time::NowFromSystemTime()))
135 RecordSSLInterstitialCause(overridable, CLOCK_PAST);
136 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime()))
137 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE);
138 }
139
140 void SSLErrorClassification::RecordUMAStatisticsCaptivePortals(
141 bool overridable) {
142 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
143 if (captive_portal_detection_enabled_)
144 RecordCaptivePortalEventStats(
145 overridable ?
146 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE :
147 CAPTIVE_PORTAL_DETECTION_ENABLED);
148 if (captive_portal_probe_completed_)
149 RecordCaptivePortalEventStats(
150 overridable ?
151 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE :
152 CAPTIVE_PORTAL_PROBE_COMPLETED);
153 // Log only one of portal detected and no response results.
154 if (captive_portal_detected_)
155 RecordCaptivePortalEventStats(
156 overridable ?
157 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE :
158 CAPTIVE_PORTAL_DETECTED);
159 else if (captive_portal_no_response_)
160 RecordCaptivePortalEventStats(
161 overridable ?
162 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE :
163 CAPTIVE_PORTAL_NO_RESPONSE);
164 #endif
165 }
166
167
84 base::TimeDelta SSLErrorClassification::TimePassedSinceExpiry() const { 168 base::TimeDelta SSLErrorClassification::TimePassedSinceExpiry() const {
85 base::TimeDelta delta = current_time_ - cert_.valid_expiry(); 169 base::TimeDelta delta = current_time_ - cert_.valid_expiry();
86 return delta; 170 return delta;
87 } 171 }
88 172
89 float SSLErrorClassification::CalculateScoreTimePassedSinceExpiry() const { 173 float SSLErrorClassification::CalculateScoreTimePassedSinceExpiry() const {
90 base::TimeDelta delta = TimePassedSinceExpiry(); 174 base::TimeDelta delta = TimePassedSinceExpiry();
91 int64 time_passed = delta.InDays(); 175 int64 time_passed = delta.InDays();
92 const int64 kHighThreshold = 7; 176 const int64 kHighThreshold = 7;
93 const int64 kLowThreshold = 4; 177 const int64 kLowThreshold = 4;
94 static const float kHighThresholdWeight = 0.4f; 178 static const float kHighThresholdWeight = 0.4f;
95 static const float kMediumThresholdWeight = 0.3f; 179 static const float kMediumThresholdWeight = 0.3f;
96 static const float kLowThresholdWeight = 0.2f; 180 static const float kLowThresholdWeight = 0.2f;
97 if (time_passed >= kHighThreshold) 181 if (time_passed >= kHighThreshold)
98 return kHighThresholdWeight; 182 return kHighThresholdWeight;
99 else if (time_passed >= kLowThreshold) 183 else if (time_passed >= kLowThreshold)
100 return kMediumThresholdWeight; 184 return kMediumThresholdWeight;
101 else 185 else
102 return kLowThresholdWeight; 186 return kLowThresholdWeight;
103 } 187 }
104 188
189 float SSLErrorClassification::CalculateScoreEnvironments() const {
190 static const float kWifiWeight = 0.7f;
191 static const float kCellularWeight = 0.7f;
192 static const float kHotspotWeight = 0.2f;
193 static const float kEthernetWeight = 0.7f;
194 static const float kOtherWeight = 0.7f;
195 net::NetworkChangeNotifier::ConnectionType type =
196 net::NetworkChangeNotifier::GetConnectionType();
197 if (type == net::NetworkChangeNotifier::CONNECTION_WIFI)
198 return kWifiWeight;
199 if (type == net::NetworkChangeNotifier::CONNECTION_2G ||
200 type == net::NetworkChangeNotifier::CONNECTION_3G ||
201 type == net::NetworkChangeNotifier::CONNECTION_4G)
meacer 2014/07/19 00:06:45 Multiline ifs should have braces {}
radhikabhar 2014/07/23 21:41:28 Done.
202 return kCellularWeight;
203 if (type == net::NetworkChangeNotifier::CONNECTION_ETHERNET)
204 return kEthernetWeight;
205 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
206 // Assume if captive portals are detected then the user is connected using a
207 // hot spot.
208 if (captive_portal_detected_)
209 return kHotspotWeight;
210 #endif
211 return kOtherWeight;
212 }
213
105 bool SSLErrorClassification::IsUserClockInThePast(base::Time time_now) { 214 bool SSLErrorClassification::IsUserClockInThePast(base::Time time_now) {
106 base::Time build_time = base::GetBuildTime(); 215 base::Time build_time = base::GetBuildTime();
107 if (time_now < build_time - base::TimeDelta::FromDays(2)) 216 if (time_now < build_time - base::TimeDelta::FromDays(2))
108 return true; 217 return true;
109 return false; 218 return false;
110 } 219 }
111 220
112 bool SSLErrorClassification::IsUserClockInTheFuture(base::Time time_now) { 221 bool SSLErrorClassification::IsUserClockInTheFuture(base::Time time_now) {
113 base::Time build_time = base::GetBuildTime(); 222 base::Time build_time = base::GetBuildTime();
114 if (time_now > build_time + base::TimeDelta::FromDays(365)) 223 if (time_now > build_time + base::TimeDelta::FromDays(365))
115 return true; 224 return true;
116 return false; 225 return false;
117 } 226 }
118 227
119 void SSLErrorClassification::RecordUMAStatistics(bool overridable) { 228 void SSLErrorClassification::Observe(
120 if (IsUserClockInThePast(base::Time::NowFromSystemTime())) 229 int type,
121 RecordSSLInterstitialCause(overridable, CLOCK_PAST); 230 const content::NotificationSource& source,
122 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime())) 231 const content::NotificationDetails& details) {
123 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); 232 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
233 // When detection is disabled, captive portal service always sends
234 // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
235 if (!captive_portal_detection_enabled_)
236 return;
237 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
238 captive_portal_probe_completed_ = true;
239 CaptivePortalService::Results* results =
240 content::Details<CaptivePortalService::Results>(
241 details).ptr();
242 // If a captive portal was detected at any point when the interstitial was
243 // displayed, assume that the interstitial was caused by a captive portal.
244 // Example scenario:
245 // 1- Interstitial displayed and captive portal detected, setting the flag.
246 // 2- Captive portal detection automatically opens portal login page.
247 // 3- User logs in on the portal login page.
248 // A notification will be received here for RESULT_INTERNET_CONNECTED. Make
249 // sure we don't clear the captive protal flag, since the interstitial was
250 // potentially caused by the captive portal.
251 captive_portal_detected_ = captive_portal_detected_ ||
252 (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
253 // Also keep track of non-HTTP portals and error cases.
254 captive_portal_no_response_ = captive_portal_no_response_ ||
255 (results->result == captive_portal::RESULT_NO_RESPONSE);
256 }
257 #endif
124 } 258 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698