| 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 |