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

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

Issue 385553002: BackoffEntry is used to compute timeouts between consecutive captive portal checks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 5 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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_impl.h" 5 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 15 matching lines...) Expand all
26 26
27 using captive_portal::CaptivePortalDetector; 27 using captive_portal::CaptivePortalDetector;
28 28
29 namespace chromeos { 29 namespace chromeos {
30 30
31 namespace { 31 namespace {
32 32
33 // Delay before portal detection caused by changes in proxy settings. 33 // Delay before portal detection caused by changes in proxy settings.
34 const int kProxyChangeDelaySec = 1; 34 const int kProxyChangeDelaySec = 1;
35 35
36 // Maximum number of reports from captive portal detector about
37 // offline state in a row before notification is sent to observers.
38 const int kMaxOfflineResultsBeforeReport = 3;
39
36 const NetworkState* DefaultNetwork() { 40 const NetworkState* DefaultNetwork() {
37 return NetworkHandler::Get()->network_state_handler()->DefaultNetwork(); 41 return NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
38 } 42 }
39 43
40 bool InSession() { 44 bool InSession() {
41 return LoginState::IsInitialized() && LoginState::Get()->IsUserLoggedIn(); 45 return LoginState::IsInitialized() && LoginState::Get()->IsUserLoggedIn();
42 } 46 }
43 47
44 void RecordDetectionResult(NetworkPortalDetector::CaptivePortalStatus status) { 48 void RecordDetectionResult(NetworkPortalDetector::CaptivePortalStatus status) {
45 if (InSession()) { 49 if (InSession()) {
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 set_network_portal_detector(new NetworkPortalDetectorStubImpl()); 199 set_network_portal_detector(new NetworkPortalDetectorStubImpl());
196 else 200 else
197 set_network_portal_detector(new NetworkPortalDetectorImpl(url_context)); 201 set_network_portal_detector(new NetworkPortalDetectorImpl(url_context));
198 } 202 }
199 203
200 NetworkPortalDetectorImpl::NetworkPortalDetectorImpl( 204 NetworkPortalDetectorImpl::NetworkPortalDetectorImpl(
201 const scoped_refptr<net::URLRequestContextGetter>& request_context) 205 const scoped_refptr<net::URLRequestContextGetter>& request_context)
202 : state_(STATE_IDLE), 206 : state_(STATE_IDLE),
203 test_url_(CaptivePortalDetector::kDefaultURL), 207 test_url_(CaptivePortalDetector::kDefaultURL),
204 enabled_(false), 208 enabled_(false),
205 attempt_count_(0),
206 strategy_(PortalDetectorStrategy::CreateById( 209 strategy_(PortalDetectorStrategy::CreateById(
207 PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN)), 210 PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN)),
211 last_detection_result_(CAPTIVE_PORTAL_STATUS_UNKNOWN),
212 same_detection_result_count_(0),
213 no_response_result_count_(0),
208 weak_factory_(this) { 214 weak_factory_(this) {
209 captive_portal_detector_.reset(new CaptivePortalDetector(request_context)); 215 captive_portal_detector_.reset(new CaptivePortalDetector(request_context));
210 strategy_->set_delegate(this); 216 strategy_->set_delegate(this);
211 217
212 registrar_.Add(this, 218 registrar_.Add(this,
213 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED, 219 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
214 content::NotificationService::AllSources()); 220 content::NotificationService::AllSources());
215 registrar_.Add(this, 221 registrar_.Add(this,
216 chrome::NOTIFICATION_AUTH_SUPPLIED, 222 chrome::NOTIFICATION_AUTH_SUPPLIED,
217 content::NotificationService::AllSources()); 223 content::NotificationService::AllSources());
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 bool network_changed = (default_service_path_ != default_network->path()); 335 bool network_changed = (default_service_path_ != default_network->path());
330 default_service_path_ = default_network->path(); 336 default_service_path_ = default_network->path();
331 337
332 bool connection_state_changed = 338 bool connection_state_changed =
333 (default_connection_state_ != default_network->connection_state()); 339 (default_connection_state_ != default_network->connection_state());
334 default_connection_state_ = default_network->connection_state(); 340 default_connection_state_ = default_network->connection_state();
335 341
336 if (network_changed || connection_state_changed) 342 if (network_changed || connection_state_changed)
337 StopDetection(); 343 StopDetection();
338 344
339 if (CanPerformAttempt() && 345 if (is_idle() && NetworkState::StateIsConnected(default_connection_state_)) {
340 NetworkState::StateIsConnected(default_connection_state_)) {
341 // Initiate Captive Portal detection if network's captive 346 // Initiate Captive Portal detection if network's captive
342 // portal state is unknown (e.g. for freshly created networks), 347 // portal state is unknown (e.g. for freshly created networks),
343 // offline or if network connection state was changed. 348 // offline or if network connection state was changed.
344 CaptivePortalState state = GetCaptivePortalState(default_network->path()); 349 CaptivePortalState state = GetCaptivePortalState(default_network->path());
345 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN || 350 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN ||
346 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE || 351 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE ||
347 (!network_changed && connection_state_changed)) { 352 (!network_changed && connection_state_changed)) {
348 ScheduleAttempt(base::TimeDelta()); 353 ScheduleAttempt(base::TimeDelta());
349 } 354 }
350 } 355 }
351 } 356 }
352 357
353 int NetworkPortalDetectorImpl::AttemptCount() { return attempt_count_; } 358 uint64 NetworkPortalDetectorImpl::NoResponseResultCount() {
359 return no_response_result_count_;
360 }
354 361
355 base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() { 362 base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() {
356 return attempt_start_time_; 363 return attempt_start_time_;
357 } 364 }
358 365
359 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() { 366 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() {
360 if (time_ticks_for_testing_.is_null()) 367 if (time_ticks_for_testing_.is_null())
361 return base::TimeTicks::Now(); 368 return base::TimeTicks::Now();
362 return time_ticks_for_testing_; 369 return time_ticks_for_testing_;
363 } 370 }
364 371
365 372
366 //////////////////////////////////////////////////////////////////////////////// 373 ////////////////////////////////////////////////////////////////////////////////
367 // NetworkPortalDetectorImpl, private: 374 // NetworkPortalDetectorImpl, private:
368 375
369 void NetworkPortalDetectorImpl::StartDetection() { 376 void NetworkPortalDetectorImpl::StartDetection() {
370 attempt_count_ = 0; 377 DCHECK(is_idle());
371 DCHECK(CanPerformAttempt()); 378
379 ResetStrategyAndCounters();
372 detection_start_time_ = GetCurrentTimeTicks(); 380 detection_start_time_ = GetCurrentTimeTicks();
373 ScheduleAttempt(base::TimeDelta()); 381 ScheduleAttempt(base::TimeDelta());
374 } 382 }
375 383
376 void NetworkPortalDetectorImpl::StopDetection() { 384 void NetworkPortalDetectorImpl::StopDetection() {
377 attempt_task_.Cancel(); 385 attempt_task_.Cancel();
378 attempt_timeout_.Cancel(); 386 attempt_timeout_.Cancel();
379 captive_portal_detector_->Cancel(); 387 captive_portal_detector_->Cancel();
380 state_ = STATE_IDLE; 388 state_ = STATE_IDLE;
381 attempt_count_ = 0; 389 ResetStrategyAndCounters();
382 }
383
384 bool NetworkPortalDetectorImpl::CanPerformAttempt() const {
385 return is_idle() && strategy_->CanPerformAttempt();
386 } 390 }
387 391
388 void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) { 392 void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) {
389 DCHECK(CanPerformAttempt()); 393 DCHECK(is_idle());
390 394
391 if (!IsEnabled()) 395 if (!IsEnabled())
392 return; 396 return;
393 397
394 attempt_task_.Cancel(); 398 attempt_task_.Cancel();
395 attempt_timeout_.Cancel(); 399 attempt_timeout_.Cancel();
396 state_ = STATE_PORTAL_CHECK_PENDING; 400 state_ = STATE_PORTAL_CHECK_PENDING;
397 401
398 next_attempt_delay_ = std::max(delay, strategy_->GetDelayTillNextAttempt()); 402 next_attempt_delay_ = std::max(delay, strategy_->GetDelayTillNextAttempt());
399 attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt, 403 attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt,
(...skipping 30 matching lines...) Expand all
430 << "id=" << default_network_id_; 434 << "id=" << default_network_id_;
431 435
432 captive_portal_detector_->Cancel(); 436 captive_portal_detector_->Cancel();
433 CaptivePortalDetector::Results results; 437 CaptivePortalDetector::Results results;
434 results.result = captive_portal::RESULT_NO_RESPONSE; 438 results.result = captive_portal::RESULT_NO_RESPONSE;
435 OnAttemptCompleted(results); 439 OnAttemptCompleted(results);
436 } 440 }
437 441
438 void NetworkPortalDetectorImpl::OnAttemptCompleted( 442 void NetworkPortalDetectorImpl::OnAttemptCompleted(
439 const CaptivePortalDetector::Results& results) { 443 const CaptivePortalDetector::Results& results) {
444 DCHECK(CalledOnValidThread());
445 DCHECK(is_checking_for_portal());
446
440 captive_portal::CaptivePortalResult result = results.result; 447 captive_portal::CaptivePortalResult result = results.result;
441 int response_code = results.response_code; 448 int response_code = results.response_code;
442 449
443 DCHECK(CalledOnValidThread());
444 DCHECK(is_checking_for_portal());
445
446 DetectionAttemptCompletedReport attempt_completed_report(
447 default_network_name_,
448 default_network_id_,
449 results.result,
450 results.response_code);
451 if (!attempt_completed_report_.Equals(attempt_completed_report)) {
452 attempt_completed_report_ = attempt_completed_report;
453 attempt_completed_report_.Report();
454 }
455
456 state_ = STATE_IDLE;
457 attempt_timeout_.Cancel();
458 ++attempt_count_;
459
460 const NetworkState* network = DefaultNetwork(); 450 const NetworkState* network = DefaultNetwork();
461 451
462 // If using a fake profile client, also fake being behind a captive portal 452 // If using a fake profile client, also fake being behind a captive portal
463 // if the default network is in portal state. 453 // if the default network is in portal state.
464 if (result != captive_portal::RESULT_NO_RESPONSE && 454 if (result != captive_portal::RESULT_NO_RESPONSE &&
465 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() && 455 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() &&
466 network && network->connection_state() == shill::kStatePortal) { 456 network && network->connection_state() == shill::kStatePortal) {
467 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL; 457 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
468 response_code = 200; 458 response_code = 200;
469 } 459 }
470 460
461 DetectionAttemptCompletedReport attempt_completed_report(
462 default_network_name_, default_network_id_, result, response_code);
463 if (!attempt_completed_report_.Equals(attempt_completed_report)) {
464 attempt_completed_report_ = attempt_completed_report;
465 attempt_completed_report_.Report();
466 }
467
468 state_ = STATE_IDLE;
469 attempt_timeout_.Cancel();
470
471 CaptivePortalState state; 471 CaptivePortalState state;
472 state.response_code = response_code; 472 state.response_code = response_code;
473 state.time = GetCurrentTimeTicks(); 473 state.time = GetCurrentTimeTicks();
474 switch (result) { 474 switch (result) {
475 case captive_portal::RESULT_NO_RESPONSE: 475 case captive_portal::RESULT_NO_RESPONSE:
476 if (CanPerformAttempt()) { 476 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
477 ScheduleAttempt(results.retry_after_delta);
478 return;
479 } else if (state.response_code ==
480 net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
481 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED; 477 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
482 } else if (network && 478 } else if (network &&
483 (network->connection_state() == shill::kStatePortal)) { 479 (network->connection_state() == shill::kStatePortal)) {
484 // Take into account shill's detection results. 480 // Take into account shill's detection results.
485 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 481 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
486 LOG(WARNING) << "Network name=" << network->name() << ", "
487 << "id=" << network->guid() << " "
488 << "is marked as "
489 << CaptivePortalStatusString(state.status) << " "
490 << "despite the fact that CaptivePortalDetector "
491 << "received no response";
492 } else { 482 } else {
493 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE; 483 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
494 } 484 }
495 break; 485 break;
496 case captive_portal::RESULT_INTERNET_CONNECTED: 486 case captive_portal::RESULT_INTERNET_CONNECTED:
497 state.status = CAPTIVE_PORTAL_STATUS_ONLINE; 487 state.status = CAPTIVE_PORTAL_STATUS_ONLINE;
498 break; 488 break;
499 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: 489 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL:
500 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 490 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
501 break; 491 break;
502 default: 492 default:
503 break; 493 break;
504 } 494 }
505 495
506 OnDetectionCompleted(network, state); 496 if (last_detection_result_ != state.status) {
507 if (CanPerformAttempt() && strategy_->CanPerformAttemptAfterDetection()) 497 last_detection_result_ = state.status;
508 ScheduleAttempt(base::TimeDelta()); 498 same_detection_result_count_ = 1;
499 strategy_->Reset();
500 } else {
501 ++same_detection_result_count_;
502 }
503 strategy_->OnDetectionCompleted();
504
505 if (result == captive_portal::RESULT_NO_RESPONSE)
506 ++no_response_result_count_;
507 else
508 no_response_result_count_ = 0;
509
510 if (state.status != CAPTIVE_PORTAL_STATUS_OFFLINE ||
511 same_detection_result_count_ >=
512 static_cast<uint64>(kMaxOfflineResultsBeforeReport)) {
513 OnDetectionCompleted(network, state);
514 }
515 ScheduleAttempt(results.retry_after_delta);
509 } 516 }
510 517
511 void NetworkPortalDetectorImpl::Observe( 518 void NetworkPortalDetectorImpl::Observe(
512 int type, 519 int type,
513 const content::NotificationSource& source, 520 const content::NotificationSource& source,
514 const content::NotificationDetails& details) { 521 const content::NotificationDetails& details) {
515 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || 522 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED ||
516 type == chrome::NOTIFICATION_AUTH_SUPPLIED || 523 type == chrome::NOTIFICATION_AUTH_SUPPLIED ||
517 type == chrome::NOTIFICATION_AUTH_CANCELLED) { 524 type == chrome::NOTIFICATION_AUTH_CANCELLED) {
518 VLOG(1) << "Restarting portal detection due to proxy change."; 525 VLOG(1) << "Restarting portal detection due to proxy change.";
519 attempt_count_ = 0;
520 if (is_portal_check_pending())
521 return;
522 StopDetection(); 526 StopDetection();
523 ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec)); 527 ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec));
524 } 528 }
525 } 529 }
526 530
527 void NetworkPortalDetectorImpl::OnDetectionCompleted( 531 void NetworkPortalDetectorImpl::OnDetectionCompleted(
528 const NetworkState* network, 532 const NetworkState* network,
529 const CaptivePortalState& state) { 533 const CaptivePortalState& state) {
530 if (!network) { 534 if (!network) {
531 NotifyDetectionCompleted(network, state); 535 NotifyDetectionCompleted(network, state);
532 return; 536 return;
533 } 537 }
534 538
535 CaptivePortalStateMap::const_iterator it = 539 CaptivePortalStateMap::const_iterator it =
536 portal_state_map_.find(network->path()); 540 portal_state_map_.find(network->path());
537 if (it == portal_state_map_.end() || it->second.status != state.status || 541 if (it == portal_state_map_.end() || it->second.status != state.status ||
538 it->second.response_code != state.response_code) { 542 it->second.response_code != state.response_code) {
539 VLOG(1) << "Updating Chrome Captive Portal state: "
540 << "name=" << network->name() << ", "
541 << "id=" << network->guid() << ", "
542 << "status=" << CaptivePortalStatusString(state.status) << ", "
543 << "response_code=" << state.response_code;
544
545 // Record detection duration iff detection result differs from the 543 // Record detection duration iff detection result differs from the
546 // previous one for this network. The reason is to record all stats 544 // previous one for this network. The reason is to record all stats
547 // only when network changes it's state. 545 // only when network changes it's state.
548 RecordDetectionStats(network, state.status); 546 RecordDetectionStats(network, state.status);
549 if (it != portal_state_map_.end() && 547 if (it != portal_state_map_.end() &&
550 it->second.status == CAPTIVE_PORTAL_STATUS_PORTAL && 548 it->second.status == CAPTIVE_PORTAL_STATUS_PORTAL &&
551 state.status == CAPTIVE_PORTAL_STATUS_ONLINE) { 549 state.status == CAPTIVE_PORTAL_STATUS_ONLINE) {
552 RecordPortalToOnlineTransition(state.time - it->second.time); 550 RecordPortalToOnlineTransition(state.time - it->second.time);
553 } 551 }
554 552
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED: 599 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
602 if (network->connection_state() != shill::kStateOnline) 600 if (network->connection_state() != shill::kStateOnline)
603 RecordDiscrepancyWithShill(network, status); 601 RecordDiscrepancyWithShill(network, status);
604 break; 602 break;
605 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT: 603 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
606 NOTREACHED(); 604 NOTREACHED();
607 break; 605 break;
608 } 606 }
609 } 607 }
610 608
609 void NetworkPortalDetectorImpl::ResetStrategyAndCounters() {
610 last_detection_result_ = CAPTIVE_PORTAL_STATUS_UNKNOWN;
611 same_detection_result_count_ = 0;
612 no_response_result_count_ = 0;
613 strategy_->Reset();
614 }
615
611 } // namespace chromeos 616 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698