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

Side by Side Diff: chrome/browser/chromeos/net/network_portal_detector.cc

Issue 12260003: Implemented lazy portal detection. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "base/message_loop.h"
(...skipping 20 matching lines...) Expand all
31 // Minimum timeout between consecutive portal checks for the same 31 // Minimum timeout between consecutive portal checks for the same
32 // network. 32 // network.
33 const int kMinTimeBetweenAttemptsSec = 3; 33 const int kMinTimeBetweenAttemptsSec = 3;
34 34
35 // Timeout for a portal check. 35 // Timeout for a portal check.
36 const int kRequestTimeoutSec = 10; 36 const int kRequestTimeoutSec = 10;
37 37
38 // Delay before portal detection caused by changes in proxy settings. 38 // Delay before portal detection caused by changes in proxy settings.
39 const int kProxyChangeDelayMs = 500; 39 const int kProxyChangeDelayMs = 500;
40 40
41 // Delay between consecutive portal checks for a network in lazy mode.
42 // TODO (ygorshenin@): use exponential backoff or normally distributed
43 // random variable instead of this.
44 const int kLazyCheckIntervalSec = 30;
45
41 std::string CaptivePortalStatusString( 46 std::string CaptivePortalStatusString(
42 NetworkPortalDetector::CaptivePortalStatus status) { 47 NetworkPortalDetector::CaptivePortalStatus status) {
43 switch (status) { 48 switch (status) {
44 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN: 49 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
45 return l10n_util::GetStringUTF8( 50 return l10n_util::GetStringUTF8(
46 IDS_CHROMEOS_CAPTIVE_PORTAL_STATUS_UNKNOWN); 51 IDS_CHROMEOS_CAPTIVE_PORTAL_STATUS_UNKNOWN);
47 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE: 52 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
48 return l10n_util::GetStringUTF8( 53 return l10n_util::GetStringUTF8(
49 IDS_CHROMEOS_CAPTIVE_PORTAL_STATUS_OFFLINE); 54 IDS_CHROMEOS_CAPTIVE_PORTAL_STATUS_OFFLINE);
50 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE: 55 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
(...skipping 15 matching lines...) Expand all
66 NetworkPortalDetector* g_network_portal_detector = NULL; 71 NetworkPortalDetector* g_network_portal_detector = NULL;
67 72
68 } // namespace 73 } // namespace
69 74
70 NetworkPortalDetector::NetworkPortalDetector( 75 NetworkPortalDetector::NetworkPortalDetector(
71 const scoped_refptr<net::URLRequestContextGetter>& request_context) 76 const scoped_refptr<net::URLRequestContextGetter>& request_context)
72 : active_connection_state_(STATE_UNKNOWN), 77 : active_connection_state_(STATE_UNKNOWN),
73 test_url_(CaptivePortalDetector::kDefaultURL), 78 test_url_(CaptivePortalDetector::kDefaultURL),
74 weak_ptr_factory_(this), 79 weak_ptr_factory_(this),
75 attempt_count_(0), 80 attempt_count_(0),
81 lazy_detection_enabled_(false),
82 lazy_check_interval_(base::TimeDelta::FromSeconds(kLazyCheckIntervalSec)),
76 min_time_between_attempts_( 83 min_time_between_attempts_(
77 base::TimeDelta::FromSeconds(kMinTimeBetweenAttemptsSec)), 84 base::TimeDelta::FromSeconds(kMinTimeBetweenAttemptsSec)),
78 request_timeout_(base::TimeDelta::FromSeconds(kRequestTimeoutSec)) { 85 request_timeout_(base::TimeDelta::FromSeconds(kRequestTimeoutSec)) {
79 captive_portal_detector_.reset(new CaptivePortalDetector(request_context)); 86 captive_portal_detector_.reset(new CaptivePortalDetector(request_context));
80 87
81 registrar_.Add(this, 88 registrar_.Add(this,
82 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED, 89 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
83 content::NotificationService::AllSources()); 90 content::NotificationService::AllSources());
84 registrar_.Add(this, 91 registrar_.Add(this,
85 chrome::NOTIFICATION_AUTH_SUPPLIED, 92 chrome::NOTIFICATION_AUTH_SUPPLIED,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 active_service_path_ = active_network->service_path(); 170 active_service_path_ = active_network->service_path();
164 cros->AddNetworkObserver(active_service_path_, this); 171 cros->AddNetworkObserver(active_service_path_, this);
165 } 172 }
166 173
167 bool connection_state_changed = 174 bool connection_state_changed =
168 (active_connection_state_ != active_network->connection_state()); 175 (active_connection_state_ != active_network->connection_state());
169 active_connection_state_ = active_network->connection_state(); 176 active_connection_state_ = active_network->connection_state();
170 177
171 if (network_changed || connection_state_changed) { 178 if (network_changed || connection_state_changed) {
172 attempt_count_ = 0; 179 attempt_count_ = 0;
173 if (IsPortalCheckPending()) { 180 CancelPortalDetection();
174 detection_task_.Cancel();
175 detection_timeout_.Cancel();
176 } else if (IsCheckingForPortal()) {
177 captive_portal_detector_->Cancel();
178 }
179 state_ = STATE_IDLE;
180 } 181 }
181 182
182 if (!IsCheckingForPortal() && !IsPortalCheckPending() && 183 if (!IsCheckingForPortal() && !IsPortalCheckPending() &&
183 Network::IsConnectedState(active_connection_state_) && 184 Network::IsConnectedState(active_connection_state_) &&
184 attempt_count_ < kMaxRequestAttempts) { 185 (attempt_count_ < kMaxRequestAttempts || lazy_detection_enabled_)) {
185 DCHECK(active_network); 186 DCHECK(active_network);
186 187
187 // Initiate Captive Portal detection if network's captive 188 // Initiate Captive Portal detection if network's captive
188 // portal state is unknown (e.g. for freshly created networks), 189 // portal state is unknown (e.g. for freshly created networks),
189 // offline or if network connection state was changed. 190 // offline or if network connection state was changed.
190 CaptivePortalState state = GetCaptivePortalState(active_network); 191 CaptivePortalState state = GetCaptivePortalState(active_network);
191 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN || 192 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN ||
192 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE || 193 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE ||
193 (!network_changed && connection_state_changed)) { 194 (!network_changed && connection_state_changed)) {
194 DetectCaptivePortal(base::TimeDelta()); 195 DetectCaptivePortal(base::TimeDelta());
195 } 196 }
196 } 197 }
197 } 198 }
198 199
199 void NetworkPortalDetector::OnNetworkChanged(chromeos::NetworkLibrary* cros, 200 void NetworkPortalDetector::OnNetworkChanged(chromeos::NetworkLibrary* cros,
200 const chromeos::Network* network) { 201 const chromeos::Network* network) {
201 DCHECK(CalledOnValidThread()); 202 DCHECK(CalledOnValidThread());
202 OnNetworkManagerChanged(cros); 203 OnNetworkManagerChanged(cros);
203 } 204 }
204 205
206 void NetworkPortalDetector::EnableLazyDetection() {
207 if (lazy_detection_enabled_)
208 return;
209 VLOG(1) << "Lazy detection mode enabled";
210 lazy_detection_enabled_ = true;
211 if (!IsPortalCheckPending() && !IsCheckingForPortal())
212 DetectCaptivePortal(base::TimeDelta());
213 }
214
215 void NetworkPortalDetector::DisableLazyDetection() {
216 if (!lazy_detection_enabled_)
217 return;
218 VLOG(1) << "Lazy detection mode disabled";
219 if (attempt_count_ == kMaxRequestAttempts)
220 CancelPortalDetection();
221 lazy_detection_enabled_ = false;
222 }
223
205 // static 224 // static
206 NetworkPortalDetector* NetworkPortalDetector::CreateInstance() { 225 NetworkPortalDetector* NetworkPortalDetector::CreateInstance() {
207 DCHECK(!g_network_portal_detector); 226 DCHECK(!g_network_portal_detector);
208 g_network_portal_detector = new NetworkPortalDetector( 227 g_network_portal_detector = new NetworkPortalDetector(
209 g_browser_process->system_request_context()); 228 g_browser_process->system_request_context());
210 return g_network_portal_detector; 229 return g_network_portal_detector;
211 } 230 }
212 231
213 // static 232 // static
214 NetworkPortalDetector* NetworkPortalDetector::GetInstance() { 233 NetworkPortalDetector* NetworkPortalDetector::GetInstance() {
215 if (!g_network_portal_detector) 234 if (!g_network_portal_detector)
216 return CreateInstance(); 235 return CreateInstance();
217 return g_network_portal_detector; 236 return g_network_portal_detector;
218 } 237 }
219 238
220 // static 239 // static
221 bool NetworkPortalDetector::IsEnabled() { 240 bool NetworkPortalDetector::IsEnabled() {
222 return !CommandLine::ForCurrentProcess()->HasSwitch( 241 return !CommandLine::ForCurrentProcess()->HasSwitch(
223 switches::kDisableChromeCaptivePortalDetector); 242 switches::kDisableChromeCaptivePortalDetector);
224 } 243 }
225 244
226 void NetworkPortalDetector::DetectCaptivePortal(const base::TimeDelta& delay) { 245 void NetworkPortalDetector::DetectCaptivePortal(const base::TimeDelta& delay) {
227 DCHECK(!IsPortalCheckPending()); 246 DCHECK(!IsPortalCheckPending());
228 DCHECK(!IsCheckingForPortal()); 247 DCHECK(!IsCheckingForPortal());
229 DCHECK(attempt_count_ < kMaxRequestAttempts); 248 DCHECK(attempt_count_ < kMaxRequestAttempts || lazy_detection_enabled_);
230 249
231 detection_task_.Cancel(); 250 detection_task_.Cancel();
232 detection_timeout_.Cancel(); 251 detection_timeout_.Cancel();
233 state_ = STATE_PORTAL_CHECK_PENDING; 252 state_ = STATE_PORTAL_CHECK_PENDING;
234 253
235 next_attempt_delay_ = delay; 254 next_attempt_delay_ = delay;
236 if (attempt_count_ > 0) { 255 if (attempt_count_ > 0) {
237 base::TimeTicks now = GetCurrentTimeTicks(); 256 base::TimeTicks now = GetCurrentTimeTicks();
238 base::TimeDelta elapsed_time; 257 base::TimeDelta elapsed_time;
258
259 base::TimeDelta delay_between_attempts = min_time_between_attempts_;
260 if (attempt_count_ == kMaxRequestAttempts) {
261 DCHECK(lazy_detection_enabled_);
262 delay_between_attempts = lazy_check_interval_;
263 }
239 if (now > attempt_start_time_) 264 if (now > attempt_start_time_)
240 elapsed_time = now - attempt_start_time_; 265 elapsed_time = now - attempt_start_time_;
241 if (elapsed_time < min_time_between_attempts_ && 266 if (elapsed_time < delay_between_attempts &&
242 min_time_between_attempts_ - elapsed_time > next_attempt_delay_) { 267 delay_between_attempts - elapsed_time > next_attempt_delay_) {
243 next_attempt_delay_ = min_time_between_attempts_ - elapsed_time; 268 next_attempt_delay_ = delay_between_attempts - elapsed_time;
244 } 269 }
245 } else { 270 } else {
246 detection_start_time_ = GetCurrentTimeTicks(); 271 detection_start_time_ = GetCurrentTimeTicks();
247 } 272 }
248 detection_task_.Reset( 273 detection_task_.Reset(
249 base::Bind(&NetworkPortalDetector::DetectCaptivePortalTask, 274 base::Bind(&NetworkPortalDetector::DetectCaptivePortalTask,
250 weak_ptr_factory_.GetWeakPtr())); 275 weak_ptr_factory_.GetWeakPtr()));
251 MessageLoop::current()->PostDelayedTask(FROM_HERE, 276 MessageLoop::current()->PostDelayedTask(FROM_HERE,
252 detection_task_.callback(), 277 detection_task_.callback(),
253 next_attempt_delay_); 278 next_attempt_delay_);
254 } 279 }
255 280
256 void NetworkPortalDetector::DetectCaptivePortalTask() { 281 void NetworkPortalDetector::DetectCaptivePortalTask() {
257 DCHECK(IsPortalCheckPending()); 282 DCHECK(IsPortalCheckPending());
258 283
259 state_ = STATE_CHECKING_FOR_PORTAL; 284 state_ = STATE_CHECKING_FOR_PORTAL;
260 285
261 ++attempt_count_;
262 attempt_start_time_ = GetCurrentTimeTicks(); 286 attempt_start_time_ = GetCurrentTimeTicks();
263 287
264 VLOG(1) << "Portal detection started: network=" << active_network_id_ << ", " 288 if (attempt_count_ < kMaxRequestAttempts) {
265 << "attempt=" << attempt_count_ << " of " << kMaxRequestAttempts; 289 ++attempt_count_;
290 VLOG(1) << "Portal detection started: "
291 << "network=" << active_network_id_ << ", "
292 << "attempt=" << attempt_count_ << " of " << kMaxRequestAttempts;
293 } else {
294 DCHECK(lazy_detection_enabled_);
295 VLOG(1) << "Lazy portal detection attempt started";
296 }
266 297
267 captive_portal_detector_->DetectCaptivePortal( 298 captive_portal_detector_->DetectCaptivePortal(
268 test_url_, 299 test_url_,
269 base::Bind(&NetworkPortalDetector::OnPortalDetectionCompleted, 300 base::Bind(&NetworkPortalDetector::OnPortalDetectionCompleted,
270 weak_ptr_factory_.GetWeakPtr())); 301 weak_ptr_factory_.GetWeakPtr()));
271 detection_timeout_.Reset( 302 detection_timeout_.Reset(
272 base::Bind(&NetworkPortalDetector::PortalDetectionTimeout, 303 base::Bind(&NetworkPortalDetector::PortalDetectionTimeout,
273 weak_ptr_factory_.GetWeakPtr())); 304 weak_ptr_factory_.GetWeakPtr()));
274 MessageLoop::current()->PostDelayedTask(FROM_HERE, 305 MessageLoop::current()->PostDelayedTask(FROM_HERE,
275 detection_timeout_.callback(), 306 detection_timeout_.callback(),
276 request_timeout_); 307 request_timeout_);
277 } 308 }
278 309
279 void NetworkPortalDetector::PortalDetectionTimeout() { 310 void NetworkPortalDetector::PortalDetectionTimeout() {
280 DCHECK(CalledOnValidThread()); 311 DCHECK(CalledOnValidThread());
281 DCHECK(IsCheckingForPortal()); 312 DCHECK(IsCheckingForPortal());
282 313
283 VLOG(1) << "Portal detection timeout: network=" << active_network_id_; 314 VLOG(1) << "Portal detection timeout: network=" << active_network_id_;
284 315
285 captive_portal_detector_->Cancel(); 316 captive_portal_detector_->Cancel();
286 CaptivePortalDetector::Results results; 317 CaptivePortalDetector::Results results;
287 results.result = captive_portal::RESULT_NO_RESPONSE; 318 results.result = captive_portal::RESULT_NO_RESPONSE;
288 OnPortalDetectionCompleted(results); 319 OnPortalDetectionCompleted(results);
289 } 320 }
290 321
322 void NetworkPortalDetector::CancelPortalDetection() {
323 if (IsPortalCheckPending()) {
324 detection_task_.Cancel();
Nikita (slow) 2013/02/13 15:12:20 nit: Alignment.
Nikita (slow) 2013/02/13 17:26:31 Done.
325 detection_timeout_.Cancel();
326 } else if (IsCheckingForPortal()) {
327 captive_portal_detector_->Cancel();
328 }
329 state_ = STATE_IDLE;
330 }
331
291 void NetworkPortalDetector::OnPortalDetectionCompleted( 332 void NetworkPortalDetector::OnPortalDetectionCompleted(
292 const CaptivePortalDetector::Results& results) { 333 const CaptivePortalDetector::Results& results) {
293 DCHECK(CalledOnValidThread()); 334 DCHECK(CalledOnValidThread());
294 DCHECK(IsCheckingForPortal()); 335 DCHECK(IsCheckingForPortal());
295 336
296 VLOG(1) << "Portal detection completed: " 337 VLOG(1) << "Portal detection completed: "
297 << "network=" << active_network_id_ << ", " 338 << "network=" << active_network_id_ << ", "
298 << "result=" << CaptivePortalDetector::CaptivePortalResultToString( 339 << "result=" << CaptivePortalDetector::CaptivePortalResultToString(
299 results.result) << ", " 340 results.result) << ", "
300 << "response_code=" << results.response_code; 341 << "response_code=" << results.response_code;
301 342
302 state_ = STATE_IDLE; 343 state_ = STATE_IDLE;
303 detection_timeout_.Cancel(); 344 detection_timeout_.Cancel();
304 345
305 NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); 346 NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
306 const Network* active_network = cros->active_network(); 347 const Network* active_network = cros->active_network();
307 if (!active_network) 348 if (!active_network) {
349 TryLazyDetection();
308 return; 350 return;
351 }
309 352
310 CaptivePortalState state; 353 CaptivePortalState state;
311 state.response_code = results.response_code; 354 state.response_code = results.response_code;
312 switch (results.result) { 355 switch (results.result) {
313 case captive_portal::RESULT_NO_RESPONSE: 356 case captive_portal::RESULT_NO_RESPONSE:
314 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { 357 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
315 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED; 358 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
316 SetCaptivePortalState(active_network, state); 359 SetCaptivePortalState(active_network, state);
317 } else if (attempt_count_ >= kMaxRequestAttempts) { 360 } else if (attempt_count_ >= kMaxRequestAttempts) {
318 // Take into account shill's detection results. 361 // Take into account shill's detection results.
(...skipping 16 matching lines...) Expand all
335 state.status = CAPTIVE_PORTAL_STATUS_ONLINE; 378 state.status = CAPTIVE_PORTAL_STATUS_ONLINE;
336 SetCaptivePortalState(active_network, state); 379 SetCaptivePortalState(active_network, state);
337 break; 380 break;
338 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: 381 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL:
339 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 382 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
340 SetCaptivePortalState(active_network, state); 383 SetCaptivePortalState(active_network, state);
341 break; 384 break;
342 default: 385 default:
343 break; 386 break;
344 } 387 }
388
389 TryLazyDetection();
345 } 390 }
391
392 void NetworkPortalDetector::TryLazyDetection() {
393 if (!IsPortalCheckPending() && !IsCheckingForPortal() &&
394 lazy_detection_enabled_) {
395 attempt_count_ = kMaxRequestAttempts;
396 DetectCaptivePortal(base::TimeDelta());
397 }
398 }
399
346 void NetworkPortalDetector::Observe( 400 void NetworkPortalDetector::Observe(
347 int type, 401 int type,
348 const content::NotificationSource& source, 402 const content::NotificationSource& source,
349 const content::NotificationDetails& details) { 403 const content::NotificationDetails& details) {
350 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || 404 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED ||
351 type == chrome::NOTIFICATION_AUTH_SUPPLIED || 405 type == chrome::NOTIFICATION_AUTH_SUPPLIED ||
352 type == chrome::NOTIFICATION_AUTH_CANCELLED) { 406 type == chrome::NOTIFICATION_AUTH_CANCELLED) {
353 if (!IsCheckingForPortal() && !IsPortalCheckPending()) { 407 if (!IsCheckingForPortal() && !IsPortalCheckPending()) {
354 attempt_count_ = 0; 408 attempt_count_ = 0;
355 DetectCaptivePortal( 409 DetectCaptivePortal(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 451 }
398 452
399 base::TimeTicks NetworkPortalDetector::GetCurrentTimeTicks() const { 453 base::TimeTicks NetworkPortalDetector::GetCurrentTimeTicks() const {
400 if (time_ticks_for_testing_.is_null()) 454 if (time_ticks_for_testing_.is_null())
401 return base::TimeTicks::Now(); 455 return base::TimeTicks::Now();
402 else 456 else
403 return time_ticks_for_testing_; 457 return time_ticks_for_testing_;
404 } 458 }
405 459
406 } // namespace chromeos 460 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/net/network_portal_detector.h ('k') | chrome/browser/chromeos/net/network_portal_detector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698