| 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/chromeos/net/network_portal_detector.h" | 5 #include "chrome/browser/chromeos/net/network_portal_detector.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" |
| 10 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 11 #include "chrome/browser/chromeos/cros/cros_library.h" | 12 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 12 #include "chrome/common/chrome_switches.h" | 13 #include "chrome/common/chrome_switches.h" |
| 13 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
| 14 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 16 #include "ui/base/l10n/l10n_util.h" |
| 16 | 17 |
| 17 using captive_portal::CaptivePortalDetector; | 18 using captive_portal::CaptivePortalDetector; |
| 18 | 19 |
| 19 namespace chromeos { | 20 namespace chromeos { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 24 // Maximum number of portal detections for the same active network |
| 25 // after network change. |
| 26 const int kMaxRequestAttempts = 3; |
| 27 |
| 28 // Minimum timeout between consecutive portal checks for the same |
| 29 // network. |
| 30 const int kMinTimeBetweenAttemptsSec = 3; |
| 31 |
| 32 // Timeout for a portal check. |
| 33 const int kRequestTimeoutSec = 10; |
| 34 |
| 23 std::string CaptivePortalStateString( | 35 std::string CaptivePortalStateString( |
| 24 NetworkPortalDetector::CaptivePortalState state) { | 36 NetworkPortalDetector::CaptivePortalState state) { |
| 25 switch (state) { | 37 switch (state) { |
| 26 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_UNKNOWN: | 38 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_UNKNOWN: |
| 27 return l10n_util::GetStringUTF8( | 39 return l10n_util::GetStringUTF8( |
| 28 IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_UNKNOWN); | 40 IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_UNKNOWN); |
| 29 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_OFFLINE: | 41 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_OFFLINE: |
| 30 return l10n_util::GetStringUTF8( | 42 return l10n_util::GetStringUTF8( |
| 31 IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_OFFLINE); | 43 IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_OFFLINE); |
| 32 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_ONLINE: | 44 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_ONLINE: |
| 33 return l10n_util::GetStringUTF8(IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_ONLINE); | 45 return l10n_util::GetStringUTF8(IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_ONLINE); |
| 34 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_PORTAL: | 46 case NetworkPortalDetector::CAPTIVE_PORTAL_STATE_PORTAL: |
| 35 return l10n_util::GetStringUTF8(IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_PORTAL); | 47 return l10n_util::GetStringUTF8(IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_PORTAL); |
| 36 } | 48 } |
| 37 return l10n_util::GetStringUTF8( | 49 return l10n_util::GetStringUTF8( |
| 38 IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_UNRECOGNIZED); | 50 IDS_CHROMEOS_CAPTIVE_PORTAL_STATE_UNRECOGNIZED); |
| 39 } | 51 } |
| 40 | 52 |
| 41 NetworkPortalDetector* g_network_portal_detector = NULL; | 53 NetworkPortalDetector* g_network_portal_detector = NULL; |
| 42 | 54 |
| 43 } // namespace | 55 } // namespace |
| 44 | 56 |
| 45 NetworkPortalDetector::NetworkPortalDetector( | 57 NetworkPortalDetector::NetworkPortalDetector( |
| 46 const scoped_refptr<net::URLRequestContextGetter>& request_context) | 58 const scoped_refptr<net::URLRequestContextGetter>& request_context) |
| 47 : test_url_(CaptivePortalDetector::kDefaultURL) { | 59 : test_url_(CaptivePortalDetector::kDefaultURL), |
| 60 weak_ptr_factory_(this), |
| 61 attempt_count_(0), |
| 62 min_time_between_attempts_( |
| 63 base::TimeDelta::FromSeconds(kMinTimeBetweenAttemptsSec)), |
| 64 request_timeout_(base::TimeDelta::FromSeconds(kRequestTimeoutSec)) { |
| 48 captive_portal_detector_.reset( | 65 captive_portal_detector_.reset( |
| 49 new CaptivePortalDetector(request_context)); | 66 new CaptivePortalDetector(request_context)); |
| 50 } | 67 } |
| 51 | 68 |
| 52 NetworkPortalDetector::~NetworkPortalDetector() { | 69 NetworkPortalDetector::~NetworkPortalDetector() { |
| 53 } | 70 } |
| 54 | 71 |
| 55 void NetworkPortalDetector::Init() { | 72 void NetworkPortalDetector::Init() { |
| 56 DCHECK(CalledOnValidThread()); | 73 DCHECK(CalledOnValidThread()); |
| 57 | 74 |
| 58 state_ = STATE_IDLE; | 75 state_ = STATE_IDLE; |
| 59 chromeos::NetworkLibrary* network_library = | 76 chromeos::NetworkLibrary* network_library = |
| 60 chromeos::CrosLibrary::Get()->GetNetworkLibrary(); | 77 chromeos::CrosLibrary::Get()->GetNetworkLibrary(); |
| 61 network_library->AddNetworkManagerObserver(this); | 78 network_library->AddNetworkManagerObserver(this); |
| 62 } | 79 } |
| 63 | 80 |
| 64 void NetworkPortalDetector::Shutdown() { | 81 void NetworkPortalDetector::Shutdown() { |
| 65 DCHECK(CalledOnValidThread()); | 82 DCHECK(CalledOnValidThread()); |
| 66 | 83 |
| 84 detection_task_.Cancel(); |
| 85 detection_timeout_.Cancel(); |
| 86 |
| 67 captive_portal_detector_->Cancel(); | 87 captive_portal_detector_->Cancel(); |
| 68 captive_portal_detector_.reset(); | 88 captive_portal_detector_.reset(); |
| 69 observers_.Clear(); | 89 observers_.Clear(); |
| 70 chromeos::NetworkLibrary* network_library = | 90 chromeos::NetworkLibrary* network_library = |
| 71 chromeos::CrosLibrary::Get()->GetNetworkLibrary(); | 91 chromeos::CrosLibrary::Get()->GetNetworkLibrary(); |
| 72 network_library->RemoveNetworkManagerObserver(this); | 92 network_library->RemoveNetworkManagerObserver(this); |
| 73 } | 93 } |
| 74 | 94 |
| 75 void NetworkPortalDetector::AddObserver(Observer* observer) { | 95 void NetworkPortalDetector::AddObserver(Observer* observer) { |
| 76 DCHECK(CalledOnValidThread()); | 96 DCHECK(CalledOnValidThread()); |
| 97 |
| 77 if (!observers_.HasObserver(observer)) | 98 if (!observers_.HasObserver(observer)) |
| 78 observers_.AddObserver(observer); | 99 observers_.AddObserver(observer); |
| 79 } | 100 } |
| 80 | 101 |
| 81 void NetworkPortalDetector::RemoveObserver(Observer* observer) { | 102 void NetworkPortalDetector::RemoveObserver(Observer* observer) { |
| 82 DCHECK(CalledOnValidThread()); | 103 DCHECK(CalledOnValidThread()); |
| 104 |
| 83 observers_.RemoveObserver(observer); | 105 observers_.RemoveObserver(observer); |
| 84 } | 106 } |
| 85 | 107 |
| 86 NetworkPortalDetector::CaptivePortalState | 108 NetworkPortalDetector::CaptivePortalState |
| 87 NetworkPortalDetector::GetCaptivePortalState(const Network* network) { | 109 NetworkPortalDetector::GetCaptivePortalState(const Network* network) { |
| 110 DCHECK(CalledOnValidThread()); |
| 111 |
| 88 if (!network) | 112 if (!network) |
| 89 return CAPTIVE_PORTAL_STATE_UNKNOWN; | 113 return CAPTIVE_PORTAL_STATE_UNKNOWN; |
| 90 CaptivePortalStateMap::const_iterator it = | 114 CaptivePortalStateMap::const_iterator it = |
| 91 captive_portal_state_map_.find(network->unique_id()); | 115 captive_portal_state_map_.find(network->unique_id()); |
| 92 if (it == captive_portal_state_map_.end()) | 116 if (it == captive_portal_state_map_.end()) |
| 93 return CAPTIVE_PORTAL_STATE_UNKNOWN; | 117 return CAPTIVE_PORTAL_STATE_UNKNOWN; |
| 94 return it->second; | 118 return it->second; |
| 95 } | 119 } |
| 96 | 120 |
| 97 void NetworkPortalDetector::OnNetworkManagerChanged(NetworkLibrary* cros) { | 121 void NetworkPortalDetector::OnNetworkManagerChanged(NetworkLibrary* cros) { |
| 98 DCHECK(CalledOnValidThread()); | 122 DCHECK(CalledOnValidThread()); |
| 99 | 123 |
| 100 // Suppose that if there are no active network, then unique id is | 124 // Suppose that if there are no active network, then unique id is |
| 101 // empty and connection state is unknown. | 125 // empty and connection state is unknown. |
| 102 std::string new_active_network_id; | 126 std::string new_active_network_id; |
| 103 ConnectionState connection_state = STATE_UNKNOWN; | 127 ConnectionState connection_state = STATE_UNKNOWN; |
| 104 const Network* active_network = cros->active_network(); | 128 const Network* active_network = cros->active_network(); |
| 105 if (active_network) { | 129 if (active_network) { |
| 106 new_active_network_id = active_network->unique_id(); | 130 new_active_network_id = active_network->unique_id(); |
| 107 connection_state = active_network->connection_state(); | 131 connection_state = active_network->connection_state(); |
| 108 } | 132 } |
| 109 | 133 |
| 110 if (active_network_id_ != new_active_network_id) { | 134 if (active_network_id_ != new_active_network_id) { |
| 111 active_network_id_ = new_active_network_id; | 135 active_network_id_ = new_active_network_id; |
| 112 if (IsCheckingForPortal()) { | 136 attempt_count_ = 0; |
| 113 // Network is changed, so detection results will be incorrect. | 137 if (IsPortalCheckPending()) { |
| 114 state_ = STATE_CHECKING_FOR_PORTAL_NETWORK_CHANGED; | 138 detection_task_.Cancel(); |
| 115 } else if (Network::IsConnectedState(connection_state)) { | 139 detection_timeout_.Cancel(); |
| 116 // Start captive portal detection, if possible. | 140 } else if (IsCheckingForPortal()) { |
| 117 DetectCaptivePortal(); | 141 captive_portal_detector_->Cancel(); |
| 118 } | 142 } |
| 119 } else if (!IsCheckingForPortal() && | 143 state_ = STATE_IDLE; |
| 120 Network::IsConnectedState(connection_state)) { | 144 } |
| 145 if (!IsCheckingForPortal() && !IsPortalCheckPending() && |
| 146 Network::IsConnectedState(connection_state) && |
| 147 attempt_count_ < kMaxRequestAttempts) { |
| 121 DCHECK(active_network); | 148 DCHECK(active_network); |
| 149 |
| 122 // Initiate Captive Portal detection only if network's captive | 150 // Initiate Captive Portal detection only if network's captive |
| 123 // portal state is unknown (e.g. for freshly created networks) or offline. | 151 // portal state is unknown (e.g. for freshly created networks) or |
| 152 // offline. |
| 124 CaptivePortalState state = GetCaptivePortalState(active_network); | 153 CaptivePortalState state = GetCaptivePortalState(active_network); |
| 125 if (state == CAPTIVE_PORTAL_STATE_UNKNOWN || | 154 if (state == CAPTIVE_PORTAL_STATE_UNKNOWN || |
| 126 state == CAPTIVE_PORTAL_STATE_OFFLINE) { | 155 state == CAPTIVE_PORTAL_STATE_OFFLINE) { |
| 127 DetectCaptivePortal(); | 156 DetectCaptivePortal(base::TimeDelta()); |
| 128 } | 157 } |
| 129 } | 158 } |
| 130 } | 159 } |
| 131 | 160 |
| 132 // static | 161 // static |
| 133 NetworkPortalDetector* NetworkPortalDetector::CreateInstance() { | 162 NetworkPortalDetector* NetworkPortalDetector::CreateInstance() { |
| 134 DCHECK(!g_network_portal_detector); | 163 DCHECK(!g_network_portal_detector); |
| 135 g_network_portal_detector = new NetworkPortalDetector( | 164 g_network_portal_detector = new NetworkPortalDetector( |
| 136 g_browser_process->system_request_context()); | 165 g_browser_process->system_request_context()); |
| 137 return g_network_portal_detector; | 166 return g_network_portal_detector; |
| 138 } | 167 } |
| 139 | 168 |
| 140 // static | 169 // static |
| 141 NetworkPortalDetector* NetworkPortalDetector::GetInstance() { | 170 NetworkPortalDetector* NetworkPortalDetector::GetInstance() { |
| 142 if (!g_network_portal_detector) | 171 if (!g_network_portal_detector) |
| 143 return CreateInstance(); | 172 return CreateInstance(); |
| 144 return g_network_portal_detector; | 173 return g_network_portal_detector; |
| 145 } | 174 } |
| 146 | 175 |
| 147 // static | 176 // static |
| 148 bool NetworkPortalDetector::IsEnabled() { | 177 bool NetworkPortalDetector::IsEnabled() { |
| 149 return !CommandLine::ForCurrentProcess()->HasSwitch( | 178 return !CommandLine::ForCurrentProcess()->HasSwitch( |
| 150 switches::kDisableChromeCaptivePortalDetector); | 179 switches::kDisableChromeCaptivePortalDetector); |
| 151 } | 180 } |
| 152 | 181 |
| 153 void NetworkPortalDetector::DetectCaptivePortal() { | 182 void NetworkPortalDetector::DetectCaptivePortal(const base::TimeDelta& delay) { |
| 183 DCHECK(!IsPortalCheckPending()); |
| 184 DCHECK(!IsCheckingForPortal()); |
| 185 DCHECK(attempt_count_ < kMaxRequestAttempts); |
| 186 |
| 187 detection_task_.Cancel(); |
| 188 detection_timeout_.Cancel(); |
| 189 state_ = STATE_PORTAL_CHECK_PENDING; |
| 190 |
| 191 next_attempt_delay_ = delay; |
| 192 if (attempt_count_ > 0) { |
| 193 base::TimeTicks now = GetCurrentTimeTicks(); |
| 194 base::TimeDelta elapsed_time; |
| 195 if (now > attempt_start_time_) |
| 196 elapsed_time = now - attempt_start_time_; |
| 197 if (elapsed_time < min_time_between_attempts_ && |
| 198 min_time_between_attempts_ - elapsed_time > next_attempt_delay_) { |
| 199 next_attempt_delay_ = min_time_between_attempts_ - elapsed_time; |
| 200 } |
| 201 } |
| 202 detection_task_.Reset( |
| 203 base::Bind(&NetworkPortalDetector::DetectCaptivePortalTask, |
| 204 weak_ptr_factory_.GetWeakPtr())); |
| 205 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 206 detection_task_.callback(), |
| 207 next_attempt_delay_); |
| 208 } |
| 209 |
| 210 void NetworkPortalDetector::DetectCaptivePortalTask() { |
| 211 DCHECK(IsPortalCheckPending()); |
| 212 |
| 154 state_ = STATE_CHECKING_FOR_PORTAL; | 213 state_ = STATE_CHECKING_FOR_PORTAL; |
| 214 |
| 215 ++attempt_count_; |
| 216 attempt_start_time_ = GetCurrentTimeTicks(); |
| 217 |
| 218 VLOG(1) << "Portal detection started: " |
| 219 << "network=" << active_network_id_ << ", " |
| 220 << "attempt=" << attempt_count_ << " of " << kMaxRequestAttempts; |
| 221 |
| 155 captive_portal_detector_->DetectCaptivePortal( | 222 captive_portal_detector_->DetectCaptivePortal( |
| 156 test_url_, | 223 test_url_, |
| 157 base::Bind(&NetworkPortalDetector::OnPortalDetectionCompleted, | 224 base::Bind(&NetworkPortalDetector::OnPortalDetectionCompleted, |
| 158 base::Unretained(this))); | 225 weak_ptr_factory_.GetWeakPtr())); |
| 226 detection_timeout_.Reset( |
| 227 base::Bind(&NetworkPortalDetector::PortalDetectionTimeout, |
| 228 weak_ptr_factory_.GetWeakPtr())); |
| 229 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 230 detection_timeout_.callback(), |
| 231 request_timeout_); |
| 232 } |
| 233 |
| 234 void NetworkPortalDetector::PortalDetectionTimeout() { |
| 235 DCHECK(CalledOnValidThread()); |
| 236 DCHECK(IsCheckingForPortal()); |
| 237 |
| 238 VLOG(1) << "Portal detection timeout: network=" << active_network_id_; |
| 239 |
| 240 captive_portal_detector_->Cancel(); |
| 241 CaptivePortalDetector::Results results; |
| 242 results.result = captive_portal::RESULT_NO_RESPONSE; |
| 243 OnPortalDetectionCompleted(results); |
| 159 } | 244 } |
| 160 | 245 |
| 161 void NetworkPortalDetector::OnPortalDetectionCompleted( | 246 void NetworkPortalDetector::OnPortalDetectionCompleted( |
| 162 const CaptivePortalDetector::Results& results) { | 247 const CaptivePortalDetector::Results& results) { |
| 163 DCHECK(CalledOnValidThread()); | 248 DCHECK(CalledOnValidThread()); |
| 249 DCHECK(IsCheckingForPortal()); |
| 164 | 250 |
| 165 DCHECK(IsCheckingForPortal()); | 251 VLOG(1) << "Portal detection completed: " |
| 252 << "network=" << active_network_id_ << ", " |
| 253 << "result=" << CaptivePortalDetector::CaptivePortalResultToString( |
| 254 results.result); |
| 255 |
| 256 state_ = STATE_IDLE; |
| 257 detection_timeout_.Cancel(); |
| 166 | 258 |
| 167 NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); | 259 NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); |
| 168 const Network* active_network = cros->active_network(); | 260 const Network* active_network = cros->active_network(); |
| 169 if (!active_network) | 261 if (!active_network) |
| 170 return; | 262 return; |
| 171 | 263 |
| 172 if (state_ == STATE_CHECKING_FOR_PORTAL_NETWORK_CHANGED) { | |
| 173 // Can't use detection results, because network was changed. So | |
| 174 // retry portal detection for the active network or, if possible. | |
| 175 if (Network::IsConnectedState(active_network->connection_state()) && | |
| 176 GetCaptivePortalState(active_network) == | |
| 177 CAPTIVE_PORTAL_STATE_UNKNOWN) { | |
| 178 DetectCaptivePortal(); | |
| 179 } | |
| 180 return; | |
| 181 } | |
| 182 | |
| 183 state_ = STATE_IDLE; | |
| 184 | |
| 185 switch (results.result) { | 264 switch (results.result) { |
| 186 case captive_portal::RESULT_NO_RESPONSE: | 265 case captive_portal::RESULT_NO_RESPONSE: |
| 187 SetCaptivePortalState(active_network, CAPTIVE_PORTAL_STATE_OFFLINE); | 266 if (attempt_count_ >= kMaxRequestAttempts) |
| 267 SetCaptivePortalState(active_network, CAPTIVE_PORTAL_STATE_OFFLINE); |
| 268 else |
| 269 DetectCaptivePortal(results.retry_after_delta); |
| 188 break; | 270 break; |
| 189 case captive_portal::RESULT_INTERNET_CONNECTED: | 271 case captive_portal::RESULT_INTERNET_CONNECTED: |
| 190 SetCaptivePortalState(active_network, CAPTIVE_PORTAL_STATE_ONLINE); | 272 SetCaptivePortalState(active_network, CAPTIVE_PORTAL_STATE_ONLINE); |
| 191 break; | 273 break; |
| 192 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: | 274 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: |
| 193 SetCaptivePortalState(active_network, CAPTIVE_PORTAL_STATE_PORTAL); | 275 SetCaptivePortalState(active_network, CAPTIVE_PORTAL_STATE_PORTAL); |
| 194 break; | 276 break; |
| 195 default: | 277 default: |
| 196 break; | 278 break; |
| 197 } | 279 } |
| 198 } | 280 } |
| 199 | 281 |
| 282 bool NetworkPortalDetector::IsPortalCheckPending() const { |
| 283 return state_ == STATE_PORTAL_CHECK_PENDING; |
| 284 } |
| 285 |
| 200 bool NetworkPortalDetector::IsCheckingForPortal() const { | 286 bool NetworkPortalDetector::IsCheckingForPortal() const { |
| 201 return state_ == STATE_CHECKING_FOR_PORTAL || | 287 return state_ == STATE_CHECKING_FOR_PORTAL; |
| 202 state_ == STATE_CHECKING_FOR_PORTAL_NETWORK_CHANGED; | |
| 203 } | 288 } |
| 204 | 289 |
| 205 void NetworkPortalDetector::SetCaptivePortalState(const Network* network, | 290 void NetworkPortalDetector::SetCaptivePortalState(const Network* network, |
| 206 CaptivePortalState state) { | 291 CaptivePortalState state) { |
| 207 DCHECK(network); | 292 DCHECK(network); |
| 293 |
| 208 CaptivePortalStateMap::const_iterator it = | 294 CaptivePortalStateMap::const_iterator it = |
| 209 captive_portal_state_map_.find(network->unique_id()); | 295 captive_portal_state_map_.find(network->unique_id()); |
| 210 if (it == captive_portal_state_map_.end() || | 296 if (it == captive_portal_state_map_.end() || |
| 211 it->second != state) { | 297 it->second != state) { |
| 212 VLOG(2) << "Updating Chrome Captive Portal state: " | 298 VLOG(1) << "Updating Chrome Captive Portal state: " |
| 213 << "network=" << network->unique_id() << ", " | 299 << "network=" << network->unique_id() << ", " |
| 214 << "state=" << CaptivePortalStateString(state); | 300 << "state=" << CaptivePortalStateString(state); |
| 215 captive_portal_state_map_[network->unique_id()] = state; | 301 captive_portal_state_map_[network->unique_id()] = state; |
| 216 NotifyPortalStateChanged(network, state); | 302 NotifyPortalStateChanged(network, state); |
| 217 } | 303 } |
| 218 } | 304 } |
| 219 | 305 |
| 220 void NetworkPortalDetector::NotifyPortalStateChanged(const Network* network, | 306 void NetworkPortalDetector::NotifyPortalStateChanged(const Network* network, |
| 221 CaptivePortalState state) { | 307 CaptivePortalState state) { |
| 222 FOR_EACH_OBSERVER(Observer, observers_, OnPortalStateChanged(network, state)); | 308 FOR_EACH_OBSERVER(Observer, observers_, OnPortalStateChanged(network, state)); |
| 223 } | 309 } |
| 224 | 310 |
| 311 base::TimeTicks NetworkPortalDetector::GetCurrentTimeTicks() const { |
| 312 if (time_ticks_for_testing_.is_null()) |
| 313 return base::TimeTicks::Now(); |
| 314 else |
| 315 return time_ticks_for_testing_; |
| 316 } |
| 317 |
| 225 } // namespace chromeos | 318 } // namespace chromeos |
| OLD | NEW |