1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/net/network_portal_detector_impl.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <algorithm> 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram.h" 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/strings/stringprintf.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chromeos/dbus/shill_profile_client.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/login/login_state.h" 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chromeos/network/network_event_log.h" 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chromeos/network/network_state.h" 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chromeos/network/network_state_handler.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/notification_service.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/content_switches.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/http/http_status_code.h" 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using base::StringPrintf; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using captive_portal::CaptivePortalDetector; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos { 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Delay before portal detection caused by changes in proxy settings. 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kProxyChangeDelaySec = 1; 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Maximum number of reports from captive portal detector about 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// offline state in a row before notification is sent to observers. 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kMaxOfflineResultsBeforeReport = 3; 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Delay before portal detection attempt after !ONLINE -> !ONLINE 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// transition. 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kShortInitialDelayBetweenAttemptsMs = 600; 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Maximum timeout before portal detection attempts after !ONLINE -> 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// !ONLINE transition. 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kShortMaximumDelayBetweenAttemptsMs = 2 * 60 * 1000; 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Delay before portal detection attempt after !ONLINE -> ONLINE 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// transition. 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kLongInitialDelayBetweenAttemptsMs = 30 * 1000; 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Maximum timeout before portal detection attempts after !ONLINE -> 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// ONLINE transition. 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kLongMaximumDelayBetweenAttemptsMs = 5 * 60 * 1000; 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const NetworkState* DefaultNetwork() { 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NetworkHandler::Get()->network_state_handler()->DefaultNetwork(); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool InSession() { 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return LoginState::IsInitialized() && LoginState::Get()->IsUserLoggedIn(); 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordDetectionResult(NetworkPortalDetector::CaptivePortalStatus status) { 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (InSession()) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION( 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kSessionDetectionResultHistogram, 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status, 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION( 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kOobeDetectionResultHistogram, 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status, 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordDetectionDuration(const base::TimeDelta& duration) { 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (InSession()) { 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_MEDIUM_TIMES( 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kSessionDetectionDurationHistogram, 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch duration); 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_MEDIUM_TIMES( 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kOobeDetectionDurationHistogram, duration); 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordDiscrepancyWithShill( 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const NetworkState* network, 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const NetworkPortalDetector::CaptivePortalStatus status) { 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (InSession()) { 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (network->connection_state() == shill::kStateOnline) { 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_ENUMERATION( 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kSessionShillOnlineHistogram, 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch status, 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (network->connection_state() == shill::kStatePortal) { 100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_ENUMERATION( 101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kSessionShillPortalHistogram, 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch status, 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (network->connection_state() == shill::kStateOffline) { 105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_ENUMERATION( 106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kSessionShillOfflineHistogram, 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch status, 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (network->connection_state() == shill::kStateOnline) { 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_ENUMERATION( 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kOobeShillOnlineHistogram, 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch status, 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (network->connection_state() == shill::kStatePortal) { 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_ENUMERATION( 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kOobeShillPortalHistogram, 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch status, 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (network->connection_state() == shill::kStateOffline) { 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_ENUMERATION( 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetectorImpl::kOobeShillOfflineHistogram, 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch status, 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid RecordPortalToOnlineTransition(const base::TimeDelta& duration) { 131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (InSession()) { 132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch UMA_HISTOGRAM_LONG_TIMES( 133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch NetworkPortalDetectorImpl::kSessionPortalToOnlineHistogram, 134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch duration); 135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch UMA_HISTOGRAM_LONG_TIMES( 137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch NetworkPortalDetectorImpl::kOobePortalToOnlineHistogram, 138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch duration); 139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// NetworkPortalDetectorImpl::DetectionAttemptCompletedLogState 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 147116680a4aac90f2aa7413d9095a592090648e557Ben MurdochNetworkPortalDetectorImpl::DetectionAttemptCompletedReport:: 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DetectionAttemptCompletedReport() 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : result(captive_portal::RESULT_COUNT), response_code(-1) { 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 152116680a4aac90f2aa7413d9095a592090648e557Ben MurdochNetworkPortalDetectorImpl::DetectionAttemptCompletedReport:: 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DetectionAttemptCompletedReport(const std::string network_name, 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string network_id, 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch captive_portal::CaptivePortalResult result, 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int response_code) 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : network_name(network_name), 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch network_id(network_id), 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result(result), 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch response_code(response_code) { 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkPortalDetectorImpl::DetectionAttemptCompletedReport::Report() 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const { 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // TODO (ygorshenin@): remove VLOG as soon as NET_LOG_EVENT will be dumped on 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // a disk, crbug.com/293739. 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(1) << "Detection attempt completed: " 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "name=" << network_name << ", " 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "id=" << network_id << ", " 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "result=" << captive_portal::CaptivePortalResultToString(result) 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << ", " 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "response_code=" << response_code; 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NET_LOG_EVENT(StringPrintf( 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "Portal detection completed: network_id=%s, result=%s, " 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "response_code=%d", 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_id.c_str(), 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) captive_portal::CaptivePortalResultToString(result).c_str(), 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) response_code), 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_name); 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool NetworkPortalDetectorImpl::DetectionAttemptCompletedReport::Equals( 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const DetectionAttemptCompletedReport& o) const { 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return network_name == o.network_name && network_id == o.network_id && 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result == o.result && response_code == o.response_code; 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// NetworkPortalDetectorImpl, public: 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kOobeDetectionResultHistogram[] = 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "CaptivePortal.OOBE.DetectionResult"; 193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kOobeDetectionDurationHistogram[] = 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "CaptivePortal.OOBE.DetectionDuration"; 195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kOobeShillOnlineHistogram[] = 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "CaptivePortal.OOBE.DiscrepancyWithShill_Online"; 197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kOobeShillPortalHistogram[] = 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool"; 199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kOobeShillOfflineHistogram[] = 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "CaptivePortal.OOBE.DiscrepancyWithShill_Offline"; 201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char NetworkPortalDetectorImpl::kOobePortalToOnlineHistogram[] = 202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "CaptivePortal.OOBE.PortalToOnlineTransition"; 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kSessionDetectionResultHistogram[] = 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "CaptivePortal.Session.DetectionResult"; 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kSessionDetectionDurationHistogram[] = 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "CaptivePortal.Session.DetectionDuration"; 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kSessionShillOnlineHistogram[] = 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "CaptivePortal.Session.DiscrepancyWithShill_Online"; 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kSessionShillPortalHistogram[] = 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "CaptivePortal.Session.DiscrepancyWithShill_RestrictedPool"; 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char NetworkPortalDetectorImpl::kSessionShillOfflineHistogram[] = 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "CaptivePortal.Session.DiscrepancyWithShill_Offline"; 214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char NetworkPortalDetectorImpl::kSessionPortalToOnlineHistogram[] = 215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch "CaptivePortal.Session.PortalToOnlineTransition"; 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkPortalDetectorImpl::Initialize( 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::URLRequestContextGetter* url_context) { 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (NetworkPortalDetector::set_for_testing()) 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(!NetworkPortalDetector::network_portal_detector()) 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << "NetworkPortalDetector was initialized twice."; 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType)) 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch set_network_portal_detector(new NetworkPortalDetectorStubImpl()); 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch set_network_portal_detector(new NetworkPortalDetectorImpl(url_context)); 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NetworkPortalDetectorImpl::NetworkPortalDetectorImpl( 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const scoped_refptr<net::URLRequestContextGetter>& request_context) 2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : state_(STATE_IDLE), 2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) test_url_(CaptivePortalDetector::kDefaultURL), 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enabled_(false), 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) strategy_(PortalDetectorStrategy::CreateById( 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN, this)), 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_detection_result_(CAPTIVE_PORTAL_STATUS_UNKNOWN), 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) same_detection_result_count_(0), 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) no_response_result_count_(0), 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_(this) { 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) captive_portal_detector_.reset(new CaptivePortalDetector(request_context)); 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.Add(this, 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome::NOTIFICATION_LOGIN_PROXY_CHANGED, 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::NotificationService::AllSources()); 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.Add(this, 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome::NOTIFICATION_AUTH_SUPPLIED, 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::NotificationService::AllSources()); 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registrar_.Add(this, 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome::NOTIFICATION_AUTH_CANCELLED, 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::NotificationService::AllSources()); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE); 254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) StartDetectionIfIdle(); 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() { 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_task_.Cancel(); 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_timeout_.Cancel(); 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) captive_portal_detector_->Cancel(); 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) captive_portal_detector_.reset(); 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) observers_.Clear(); 2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (NetworkHandler::IsInitialized()) { 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NetworkHandler::Get()->network_state_handler()->RemoveObserver(this, 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE); 2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkPortalDetectorImpl::AddObserver(Observer* observer) { 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (observer && !observers_.HasObserver(observer)) 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) observers_.AddObserver(observer); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkPortalDetectorImpl::AddAndFireObserver(Observer* observer) { 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!observer) 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AddObserver(observer); 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CaptivePortalState portal_state; 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const NetworkState* network = DefaultNetwork(); 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (network) 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch portal_state = GetCaptivePortalState(network->guid()); 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) observer->OnPortalDetectionCompleted(network, portal_state); 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkPortalDetectorImpl::RemoveObserver(Observer* observer) { 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (observer) 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) observers_.RemoveObserver(observer); 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool NetworkPortalDetectorImpl::IsEnabled() { return enabled_; } 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkPortalDetectorImpl::Enable(bool start_detection) { 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (enabled_) 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(is_idle()); 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enabled_ = true; 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const NetworkState* network = DefaultNetwork(); 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!start_detection || !network) 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NET_LOG_EVENT(StringPrintf("Starting detection attempt: network_id=%s", 31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network->guid().c_str()), 31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network->name()); 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch portal_state_map_.erase(network->guid()); 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartDetection(); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NetworkPortalDetectorImpl::CaptivePortalState 317116680a4aac90f2aa7413d9095a592090648e557Ben MurdochNetworkPortalDetectorImpl::GetCaptivePortalState(const std::string& guid) { 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CaptivePortalStateMap::const_iterator it = portal_state_map_.find(guid); 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (it == portal_state_map_.end()) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return CaptivePortalState(); 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return it->second; 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NetworkPortalDetectorImpl::StartDetectionIfIdle() { 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!is_idle()) 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartDetection(); 32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void NetworkPortalDetectorImpl::SetStrategy( 333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PortalDetectorStrategy::StrategyId id) { 334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (id == strategy_->Id()) 335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strategy_ = PortalDetectorStrategy::CreateById(id, this).Pass(); 337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) StopDetection(); 338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) StartDetectionIfIdle(); 339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NetworkPortalDetectorImpl::DefaultNetworkChanged( 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const NetworkState* default_network) { 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!default_network) { 34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NET_LOG_EVENT("Default network changed", "None"); 34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) default_network_name_.clear(); 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopDetection(); 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CaptivePortalState state; 353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) state.status = CAPTIVE_PORTAL_STATUS_OFFLINE; 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnDetectionCompleted(NULL, state); 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) default_network_name_ = default_network->name(); 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool network_changed = (default_network_id_ != default_network->guid()); 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default_network_id_ = default_network->guid(); 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool connection_state_changed = 364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (default_connection_state_ != default_network->connection_state()); 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default_connection_state_ = default_network->connection_state(); 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NET_LOG_EVENT(StringPrintf( 36803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "Default network changed: network_id=%s, state=%s, " 36903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "changed=%d, state_changed=%d", 37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_network_id_.c_str(), 37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_connection_state_.c_str(), 37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_changed, 37303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) connection_state_changed), 37403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_network_name_); 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (network_changed || connection_state_changed) 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopDetection(); 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (is_idle() && NetworkState::StateIsConnected(default_connection_state_)) { 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Initiate Captive Portal detection if network's captive 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // portal state is unknown (e.g. for freshly created networks), 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // offline or if network connection state was changed. 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CaptivePortalState state = GetCaptivePortalState(default_network->guid()); 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN || 385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state.status == CAPTIVE_PORTAL_STATUS_OFFLINE || 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (!network_changed && connection_state_changed)) { 387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScheduleAttempt(base::TimeDelta()); 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int NetworkPortalDetectorImpl::NoResponseResultCount() { 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return no_response_result_count_; 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() { 397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return attempt_start_time_; 398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() { 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (time_ticks_for_testing_.is_null()) 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return base::TimeTicks::Now(); 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return time_ticks_for_testing_; 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// NetworkPortalDetectorImpl, private: 40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::StartDetection() { 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(is_idle()); 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ResetStrategyAndCounters(); 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) detection_start_time_ = GetCurrentTimeTicks(); 415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScheduleAttempt(base::TimeDelta()); 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::StopDetection() { 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_task_.Cancel(); 420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_timeout_.Cancel(); 421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) captive_portal_detector_->Cancel(); 422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state_ = STATE_IDLE; 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ResetStrategyAndCounters(); 424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) { 4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(is_idle()); 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!IsEnabled()) 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_task_.Cancel(); 433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_timeout_.Cancel(); 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state_ = STATE_PORTAL_CHECK_PENDING; 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) next_attempt_delay_ = std::max(delay, strategy_->GetDelayTillNextAttempt()); 437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt, 438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr())); 43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, attempt_task_.callback(), next_attempt_delay_); 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::StartAttempt() { 444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(is_portal_check_pending()); 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state_ = STATE_CHECKING_FOR_PORTAL; 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attempt_start_time_ = GetCurrentTimeTicks(); 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) captive_portal_detector_->DetectCaptivePortal( 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) test_url_, 451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&NetworkPortalDetectorImpl::OnAttemptCompleted, 452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr())); 453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_timeout_.Reset( 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&NetworkPortalDetectorImpl::OnAttemptTimeout, 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr())); 456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) attempt_timeout_.callback(), 460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) strategy_->GetNextAttemptTimeout()); 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::OnAttemptTimeout() { 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(is_checking_for_portal()); 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NET_LOG_ERROR(StringPrintf("Portal detection timeout: network_id=%s", 46803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_network_id_.c_str()), 46903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_network_name_); 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) captive_portal_detector_->Cancel(); 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptivePortalDetector::Results results; 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) results.result = captive_portal::RESULT_NO_RESPONSE; 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnAttemptCompleted(results); 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::OnAttemptCompleted( 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CaptivePortalDetector::Results& results) { 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(CalledOnValidThread()); 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(is_checking_for_portal()); 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) captive_portal::CaptivePortalResult result = results.result; 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int response_code = results.response_code; 484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const NetworkState* network = DefaultNetwork(); 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If using a fake profile client, also fake being behind a captive portal 488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // if the default network is in portal state. 489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (result != captive_portal::RESULT_NO_RESPONSE && 490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() && 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) network && network->connection_state() == shill::kStatePortal) { 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL; 493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) response_code = 200; 494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DetectionAttemptCompletedReport attempt_completed_report( 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_network_name_, default_network_id_, result, response_code); 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!attempt_completed_report_.Equals(attempt_completed_report)) { 4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) attempt_completed_report_ = attempt_completed_report; 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) attempt_completed_report_.Report(); 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) state_ = STATE_IDLE; 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) attempt_timeout_.Cancel(); 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptivePortalState state; 507c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch state.response_code = response_code; 508e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch state.time = GetCurrentTimeTicks(); 509c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch switch (result) { 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case captive_portal::RESULT_NO_RESPONSE: 5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { 512010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED; 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (network && 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (network->connection_state() == shill::kStatePortal)) { 515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Take into account shill's detection results. 516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.status = CAPTIVE_PORTAL_STATUS_OFFLINE; 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case captive_portal::RESULT_INTERNET_CONNECTED: 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state.status = CAPTIVE_PORTAL_STATUS_ONLINE; 523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default: 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (last_detection_result_ != state.status) { 5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_detection_result_ = state.status; 5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) same_detection_result_count_ = 1; 5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::BackoffEntry::Policy policy = strategy_->policy(); 5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (state.status == CAPTIVE_PORTAL_STATUS_ONLINE) { 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy.initial_delay_ms = kLongInitialDelayBetweenAttemptsMs; 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy.maximum_backoff_ms = kLongMaximumDelayBetweenAttemptsMs; 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy.initial_delay_ms = kShortInitialDelayBetweenAttemptsMs; 5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) policy.maximum_backoff_ms = kShortMaximumDelayBetweenAttemptsMs; 5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strategy_->SetPolicyAndReset(policy); 5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++same_detection_result_count_; 5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strategy_->OnDetectionCompleted(); 5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result == captive_portal::RESULT_NO_RESPONSE) 5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++no_response_result_count_; 5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) no_response_result_count_ = 0; 5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (state.status != CAPTIVE_PORTAL_STATUS_OFFLINE || 5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) same_detection_result_count_ >= kMaxOfflineResultsBeforeReport) { 5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnDetectionCompleted(network, state); 5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ScheduleAttempt(results.retry_after_delta); 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkPortalDetectorImpl::Observe( 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int type, 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::NotificationSource& source, 563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::NotificationDetails& details) { 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || 565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) type == chrome::NOTIFICATION_AUTH_SUPPLIED || 566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) type == chrome::NOTIFICATION_AUTH_CANCELLED) { 56703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NET_LOG_EVENT( 56803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "Restarting portal detection due to proxy change", 56903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_network_name_.empty() ? "None" : default_network_name_); 570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopDetection(); 571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec)); 572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::OnDetectionCompleted( 57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const NetworkState* network, 577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CaptivePortalState& state) { 57890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!network) { 579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NotifyDetectionCompleted(network, state); 58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 58290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptivePortalStateMap::const_iterator it = 584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch portal_state_map_.find(network->guid()); 585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it == portal_state_map_.end() || it->second.status != state.status || 586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->second.response_code != state.response_code) { 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Record detection duration iff detection result differs from the 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // previous one for this network. The reason is to record all stats 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // only when network changes it's state. 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordDetectionStats(network, state.status); 591e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (it != portal_state_map_.end() && 592e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch it->second.status == CAPTIVE_PORTAL_STATUS_PORTAL && 593e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch state.status == CAPTIVE_PORTAL_STATUS_ONLINE) { 594e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch RecordPortalToOnlineTransition(state.time - it->second.time); 595e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch portal_state_map_[network->guid()] = state; 598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 599a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NotifyDetectionCompleted(network, state); 600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 602a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkPortalDetectorImpl::NotifyDetectionCompleted( 60390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const NetworkState* network, 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CaptivePortalState& state) { 605a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FOR_EACH_OBSERVER( 606a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Observer, observers_, OnPortalDetectionCompleted(network, state)); 607a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notification_controller_.OnPortalDetectionCompleted(network, state); 608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool NetworkPortalDetectorImpl::AttemptTimeoutIsCancelledForTesting() const { 611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return attempt_timeout_.IsCancelled(); 61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NetworkPortalDetectorImpl::RecordDetectionStats( 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const NetworkState* network, 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CaptivePortalStatus status) { 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Don't record stats for offline state. 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!network) 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 621effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!detection_start_time_.is_null()) 622effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordDetectionDuration(GetCurrentTimeTicks() - detection_start_time_); 623effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordDetectionResult(status); 624effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (status) { 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN: 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE: 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (network->connection_state() == shill::kStateOnline || 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) network->connection_state() == shill::kStatePortal) { 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordDiscrepancyWithShill(network, status); 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE: 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (network->connection_state() != shill::kStateOnline) 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordDiscrepancyWithShill(network, status); 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL: 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (network->connection_state() != shill::kStatePortal) 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordDiscrepancyWithShill(network, status); 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED: 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (network->connection_state() != shill::kStateOnline) 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordDiscrepancyWithShill(network, status); 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT: 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void NetworkPortalDetectorImpl::ResetStrategyAndCounters() { 6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_detection_result_ = CAPTIVE_PORTAL_STATUS_UNKNOWN; 6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) same_detection_result_count_ = 0; 6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) no_response_result_count_ = 0; 6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strategy_->Reset(); 6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace chromeos 661