OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/captive_portal/captive_portal_service.h" | 5 #include "chrome/browser/captive_portal/captive_portal_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/prefs/pref_service.h" | 12 #include "base/prefs/pref_service.h" |
13 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
14 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/common/pref_names.h" | 15 #include "chrome/common/pref_names.h" |
| 16 #include "components/captive_portal/captive_portal_types.h" |
16 #include "content/public/browser/notification_service.h" | 17 #include "content/public/browser/notification_service.h" |
17 | 18 |
18 #if defined(OS_MACOSX) | 19 #if defined(OS_MACOSX) |
19 #include "base/mac/mac_util.h" | 20 #include "base/mac/mac_util.h" |
20 #endif | 21 #endif |
21 | 22 |
22 #if defined(OS_WIN) | 23 #if defined(OS_WIN) |
23 #include "base/win/windows_version.h" | 24 #include "base/win/windows_version.h" |
24 #endif | 25 #endif |
25 | 26 |
26 namespace captive_portal { | 27 using captive_portal::CaptivePortalResult; |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 // Make sure this enum is in sync with CaptivePortalDetectionResult enum | 31 // Make sure this enum is in sync with CaptivePortalDetectionResult enum |
31 // in histograms.xml. This enum is append-only, don't modify existing values. | 32 // in histograms.xml. This enum is append-only, don't modify existing values. |
32 enum CaptivePortalDetectionResult { | 33 enum CaptivePortalDetectionResult { |
33 // There's a confirmed connection to the Internet. | 34 // There's a confirmed connection to the Internet. |
34 DETECTION_RESULT_INTERNET_CONNECTED, | 35 DETECTION_RESULT_INTERNET_CONNECTED, |
35 // Received a network or HTTP error, or a non-HTTP response. | 36 // Received a network or HTTP error, or a non-HTTP response. |
36 DETECTION_RESULT_NO_RESPONSE, | 37 DETECTION_RESULT_NO_RESPONSE, |
37 // Encountered a captive portal with a non-HTTPS landing URL. | 38 // Encountered a captive portal with a non-HTTPS landing URL. |
38 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL, | 39 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL, |
39 // Received a network or HTTP error with an HTTPS landing URL. | 40 // Received a network or HTTP error with an HTTPS landing URL. |
40 DETECTION_RESULT_NO_RESPONSE_HTTPS_LANDING_URL, | 41 DETECTION_RESULT_NO_RESPONSE_HTTPS_LANDING_URL, |
41 // Encountered a captive portal with an HTTPS landing URL. | 42 // Encountered a captive portal with an HTTPS landing URL. |
42 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL, | 43 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL, |
43 DETECTION_RESULT_COUNT | 44 DETECTION_RESULT_COUNT |
44 }; | 45 }; |
45 | 46 |
46 // Records histograms relating to how often captive portal detection attempts | 47 // Records histograms relating to how often captive portal detection attempts |
47 // ended with |result| in a row, and for how long |result| was the last result | 48 // ended with |result| in a row, and for how long |result| was the last result |
48 // of a detection attempt. Recorded both on quit and on a new Result. | 49 // of a detection attempt. Recorded both on quit and on a new Result. |
49 // | 50 // |
50 // |repeat_count| may be 0 if there were no captive portal checks during | 51 // |repeat_count| may be 0 if there were no captive portal checks during |
51 // a session. | 52 // a session. |
52 // | 53 // |
53 // |result_duration| is the time between when a captive portal check first | 54 // |result_duration| is the time between when a captive portal check first |
54 // returned |result| and when a check returned a different result, or when the | 55 // returned |result| and when a check returned a different result, or when the |
55 // CaptivePortalService was shut down. | 56 // CaptivePortalService was shut down. |
56 void RecordRepeatHistograms(Result result, | 57 void RecordRepeatHistograms(CaptivePortalResult result, |
57 int repeat_count, | 58 int repeat_count, |
58 base::TimeDelta result_duration) { | 59 base::TimeDelta result_duration) { |
59 // Histogram macros can't be used with variable names, since they cache | 60 // Histogram macros can't be used with variable names, since they cache |
60 // pointers, so have to use the histogram functions directly. | 61 // pointers, so have to use the histogram functions directly. |
61 | 62 |
62 // Record number of times the last result was received in a row. | 63 // Record number of times the last result was received in a row. |
63 base::HistogramBase* result_repeated_histogram = | 64 base::HistogramBase* result_repeated_histogram = |
64 base::Histogram::FactoryGet( | 65 base::Histogram::FactoryGet( |
65 "CaptivePortal.ResultRepeated." + | 66 "CaptivePortal.ResultRepeated." + CaptivePortalResultToString(result), |
66 CaptivePortalDetector::CaptivePortalResultToString(result), | |
67 1, // min | 67 1, // min |
68 100, // max | 68 100, // max |
69 100, // bucket_count | 69 100, // bucket_count |
70 base::Histogram::kUmaTargetedHistogramFlag); | 70 base::Histogram::kUmaTargetedHistogramFlag); |
71 result_repeated_histogram->Add(repeat_count); | 71 result_repeated_histogram->Add(repeat_count); |
72 | 72 |
73 if (repeat_count == 0) | 73 if (repeat_count == 0) |
74 return; | 74 return; |
75 | 75 |
76 // Time between first request that returned |result| and now. | 76 // Time between first request that returned |result| and now. |
77 base::HistogramBase* result_duration_histogram = | 77 base::HistogramBase* result_duration_histogram = |
78 base::Histogram::FactoryTimeGet( | 78 base::Histogram::FactoryTimeGet( |
79 "CaptivePortal.ResultDuration." + | 79 "CaptivePortal.ResultDuration." + CaptivePortalResultToString(result), |
80 CaptivePortalDetector::CaptivePortalResultToString(result), | |
81 base::TimeDelta::FromSeconds(1), // min | 80 base::TimeDelta::FromSeconds(1), // min |
82 base::TimeDelta::FromHours(1), // max | 81 base::TimeDelta::FromHours(1), // max |
83 50, // bucket_count | 82 50, // bucket_count |
84 base::Histogram::kUmaTargetedHistogramFlag); | 83 base::Histogram::kUmaTargetedHistogramFlag); |
85 result_duration_histogram->AddTime(result_duration); | 84 result_duration_histogram->AddTime(result_duration); |
86 } | 85 } |
87 | 86 |
88 int GetHistogramEntryForDetectionResult( | 87 int GetHistogramEntryForDetectionResult( |
89 const CaptivePortalDetector::Results& results) { | 88 const captive_portal::CaptivePortalDetector::Results& results) { |
90 bool is_https = results.landing_url.SchemeIs("https"); | 89 bool is_https = results.landing_url.SchemeIs("https"); |
91 switch (results.result) { | 90 switch (results.result) { |
92 case RESULT_INTERNET_CONNECTED: | 91 case captive_portal::RESULT_INTERNET_CONNECTED: |
93 return DETECTION_RESULT_INTERNET_CONNECTED; | 92 return DETECTION_RESULT_INTERNET_CONNECTED; |
94 case RESULT_NO_RESPONSE: | 93 case captive_portal::RESULT_NO_RESPONSE: |
95 return is_https ? | 94 return is_https ? |
96 DETECTION_RESULT_NO_RESPONSE_HTTPS_LANDING_URL : | 95 DETECTION_RESULT_NO_RESPONSE_HTTPS_LANDING_URL : |
97 DETECTION_RESULT_NO_RESPONSE; | 96 DETECTION_RESULT_NO_RESPONSE; |
98 case RESULT_BEHIND_CAPTIVE_PORTAL: | 97 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: |
99 return is_https ? | 98 return is_https ? |
100 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL : | 99 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL : |
101 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL; | 100 DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL; |
102 default: | 101 default: |
103 NOTREACHED(); | 102 NOTREACHED(); |
104 return -1; | 103 return -1; |
105 } | 104 } |
106 } | 105 } |
107 | 106 |
108 bool ShouldDeferToNativeCaptivePortalDetection() { | 107 bool ShouldDeferToNativeCaptivePortalDetection() { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 backoff_policy.entry_lifetime_ms = -1; | 166 backoff_policy.entry_lifetime_ms = -1; |
168 | 167 |
169 backoff_policy.always_use_initial_delay = true; | 168 backoff_policy.always_use_initial_delay = true; |
170 } | 169 } |
171 | 170 |
172 CaptivePortalService::CaptivePortalService(Profile* profile) | 171 CaptivePortalService::CaptivePortalService(Profile* profile) |
173 : profile_(profile), | 172 : profile_(profile), |
174 state_(STATE_IDLE), | 173 state_(STATE_IDLE), |
175 captive_portal_detector_(profile->GetRequestContext()), | 174 captive_portal_detector_(profile->GetRequestContext()), |
176 enabled_(false), | 175 enabled_(false), |
177 last_detection_result_(RESULT_INTERNET_CONNECTED), | 176 last_detection_result_(captive_portal::RESULT_INTERNET_CONNECTED), |
178 num_checks_with_same_result_(0), | 177 num_checks_with_same_result_(0), |
179 test_url_(CaptivePortalDetector::kDefaultURL) { | 178 test_url_(captive_portal::CaptivePortalDetector::kDefaultURL) { |
180 // The order matters here: | 179 // The order matters here: |
181 // |resolve_errors_with_web_service_| must be initialized and |backoff_entry_| | 180 // |resolve_errors_with_web_service_| must be initialized and |backoff_entry_| |
182 // created before the call to UpdateEnabledState. | 181 // created before the call to UpdateEnabledState. |
183 resolve_errors_with_web_service_.Init( | 182 resolve_errors_with_web_service_.Init( |
184 prefs::kAlternateErrorPagesEnabled, | 183 prefs::kAlternateErrorPagesEnabled, |
185 profile_->GetPrefs(), | 184 profile_->GetPrefs(), |
186 base::Bind(&CaptivePortalService::UpdateEnabledState, | 185 base::Bind(&CaptivePortalService::UpdateEnabledState, |
187 base::Unretained(this))); | 186 base::Unretained(this))); |
188 ResetBackoffEntry(last_detection_result_); | 187 ResetBackoffEntry(last_detection_result_); |
189 | 188 |
(...skipping 26 matching lines...) Expand all Loading... |
216 DCHECK(state_ == STATE_TIMER_RUNNING || state_ == STATE_IDLE); | 215 DCHECK(state_ == STATE_TIMER_RUNNING || state_ == STATE_IDLE); |
217 DCHECK(!TimerRunning()); | 216 DCHECK(!TimerRunning()); |
218 | 217 |
219 state_ = STATE_CHECKING_FOR_PORTAL; | 218 state_ = STATE_CHECKING_FOR_PORTAL; |
220 | 219 |
221 // When not enabled, just claim there's an Internet connection. | 220 // When not enabled, just claim there's an Internet connection. |
222 if (!enabled_) { | 221 if (!enabled_) { |
223 // Count this as a success, so the backoff entry won't apply exponential | 222 // Count this as a success, so the backoff entry won't apply exponential |
224 // backoff, but will apply the standard delay. | 223 // backoff, but will apply the standard delay. |
225 backoff_entry_->InformOfRequest(true); | 224 backoff_entry_->InformOfRequest(true); |
226 OnResult(RESULT_INTERNET_CONNECTED); | 225 OnResult(captive_portal::RESULT_INTERNET_CONNECTED); |
227 return; | 226 return; |
228 } | 227 } |
229 | 228 |
230 captive_portal_detector_.DetectCaptivePortal( | 229 captive_portal_detector_.DetectCaptivePortal( |
231 test_url_, base::Bind( | 230 test_url_, base::Bind( |
232 &CaptivePortalService::OnPortalDetectionCompleted, | 231 &CaptivePortalService::OnPortalDetectionCompleted, |
233 base::Unretained(this))); | 232 base::Unretained(this))); |
234 } | 233 } |
235 | 234 |
236 void CaptivePortalService::OnPortalDetectionCompleted( | 235 void CaptivePortalService::OnPortalDetectionCompleted( |
237 const CaptivePortalDetector::Results& results) { | 236 const captive_portal::CaptivePortalDetector::Results& results) { |
238 DCHECK(CalledOnValidThread()); | 237 DCHECK(CalledOnValidThread()); |
239 DCHECK_EQ(STATE_CHECKING_FOR_PORTAL, state_); | 238 DCHECK_EQ(STATE_CHECKING_FOR_PORTAL, state_); |
240 DCHECK(!TimerRunning()); | 239 DCHECK(!TimerRunning()); |
241 DCHECK(enabled_); | 240 DCHECK(enabled_); |
242 | 241 |
243 Result result = results.result; | 242 CaptivePortalResult result = results.result; |
244 const base::TimeDelta& retry_after_delta = results.retry_after_delta; | 243 const base::TimeDelta& retry_after_delta = results.retry_after_delta; |
245 base::TimeTicks now = GetCurrentTimeTicks(); | 244 base::TimeTicks now = GetCurrentTimeTicks(); |
246 | 245 |
247 // Record histograms. | 246 // Record histograms. |
248 UMA_HISTOGRAM_ENUMERATION("CaptivePortal.DetectResult", | 247 UMA_HISTOGRAM_ENUMERATION("CaptivePortal.DetectResult", |
249 GetHistogramEntryForDetectionResult(results), | 248 GetHistogramEntryForDetectionResult(results), |
250 DETECTION_RESULT_COUNT); | 249 DETECTION_RESULT_COUNT); |
251 | 250 |
252 // If this isn't the first captive portal result, record stats. | 251 // If this isn't the first captive portal result, record stats. |
253 if (!last_check_time_.is_null()) { | 252 if (!last_check_time_.is_null()) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 void CaptivePortalService::Shutdown() { | 294 void CaptivePortalService::Shutdown() { |
296 DCHECK(CalledOnValidThread()); | 295 DCHECK(CalledOnValidThread()); |
297 if (enabled_) { | 296 if (enabled_) { |
298 RecordRepeatHistograms( | 297 RecordRepeatHistograms( |
299 last_detection_result_, | 298 last_detection_result_, |
300 num_checks_with_same_result_, | 299 num_checks_with_same_result_, |
301 GetCurrentTimeTicks() - first_check_time_with_same_result_); | 300 GetCurrentTimeTicks() - first_check_time_with_same_result_); |
302 } | 301 } |
303 } | 302 } |
304 | 303 |
305 void CaptivePortalService::OnResult(Result result) { | 304 void CaptivePortalService::OnResult(CaptivePortalResult result) { |
306 DCHECK_EQ(STATE_CHECKING_FOR_PORTAL, state_); | 305 DCHECK_EQ(STATE_CHECKING_FOR_PORTAL, state_); |
307 state_ = STATE_IDLE; | 306 state_ = STATE_IDLE; |
308 | 307 |
309 Results results; | 308 Results results; |
310 results.previous_result = last_detection_result_; | 309 results.previous_result = last_detection_result_; |
311 results.result = result; | 310 results.result = result; |
312 last_detection_result_ = result; | 311 last_detection_result_ = result; |
313 | 312 |
314 content::NotificationService::current()->Notify( | 313 content::NotificationService::current()->Notify( |
315 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, | 314 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, |
316 content::Source<Profile>(profile_), | 315 content::Source<Profile>(profile_), |
317 content::Details<Results>(&results)); | 316 content::Details<Results>(&results)); |
318 } | 317 } |
319 | 318 |
320 void CaptivePortalService::ResetBackoffEntry(Result result) { | 319 void CaptivePortalService::ResetBackoffEntry(CaptivePortalResult result) { |
321 if (!enabled_ || result == RESULT_BEHIND_CAPTIVE_PORTAL) { | 320 if (!enabled_ || result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL) { |
322 // Use the shorter time when the captive portal service is not enabled, or | 321 // Use the shorter time when the captive portal service is not enabled, or |
323 // behind a captive portal. | 322 // behind a captive portal. |
324 recheck_policy_.backoff_policy.initial_delay_ms = | 323 recheck_policy_.backoff_policy.initial_delay_ms = |
325 recheck_policy_.initial_backoff_portal_ms; | 324 recheck_policy_.initial_backoff_portal_ms; |
326 } else { | 325 } else { |
327 recheck_policy_.backoff_policy.initial_delay_ms = | 326 recheck_policy_.backoff_policy.initial_delay_ms = |
328 recheck_policy_.initial_backoff_no_portal_ms; | 327 recheck_policy_.initial_backoff_no_portal_ms; |
329 } | 328 } |
330 | 329 |
331 backoff_entry_.reset(new RecheckBackoffEntry(this)); | 330 backoff_entry_.reset(new RecheckBackoffEntry(this)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 return time_ticks_for_testing_; | 371 return time_ticks_for_testing_; |
373 } | 372 } |
374 | 373 |
375 bool CaptivePortalService::DetectionInProgress() const { | 374 bool CaptivePortalService::DetectionInProgress() const { |
376 return state_ == STATE_CHECKING_FOR_PORTAL; | 375 return state_ == STATE_CHECKING_FOR_PORTAL; |
377 } | 376 } |
378 | 377 |
379 bool CaptivePortalService::TimerRunning() const { | 378 bool CaptivePortalService::TimerRunning() const { |
380 return check_captive_portal_timer_.IsRunning(); | 379 return check_captive_portal_timer_.IsRunning(); |
381 } | 380 } |
382 | |
383 } // namespace captive_portal | |
OLD | NEW |