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

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: Rebase. 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 VLOG(1) << "DefaultNetworkChanged: " 343 VLOG(1) << "DefaultNetworkChanged: "
338 << "name=" << default_network_name_ << ", " 344 << "name=" << default_network_name_ << ", "
339 << "id=" << default_network_id_ << ", " 345 << "id=" << default_network_id_ << ", "
340 << "state=" << default_connection_state_ << ", " 346 << "state=" << default_connection_state_ << ", "
341 << "changed=" << network_changed << ", " 347 << "changed=" << network_changed << ", "
342 << "state_changed=" << connection_state_changed; 348 << "state_changed=" << connection_state_changed;
343 349
344 if (network_changed || connection_state_changed) 350 if (network_changed || connection_state_changed)
345 StopDetection(); 351 StopDetection();
346 352
347 if (CanPerformAttempt() && 353 if (is_idle() && NetworkState::StateIsConnected(default_connection_state_)) {
348 NetworkState::StateIsConnected(default_connection_state_)) {
349 // Initiate Captive Portal detection if network's captive 354 // Initiate Captive Portal detection if network's captive
350 // portal state is unknown (e.g. for freshly created networks), 355 // portal state is unknown (e.g. for freshly created networks),
351 // offline or if network connection state was changed. 356 // offline or if network connection state was changed.
352 CaptivePortalState state = GetCaptivePortalState(default_network->guid()); 357 CaptivePortalState state = GetCaptivePortalState(default_network->guid());
353 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN || 358 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN ||
354 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE || 359 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE ||
355 (!network_changed && connection_state_changed)) { 360 (!network_changed && connection_state_changed)) {
356 ScheduleAttempt(base::TimeDelta()); 361 ScheduleAttempt(base::TimeDelta());
357 } 362 }
358 } 363 }
359 } 364 }
360 365
361 int NetworkPortalDetectorImpl::AttemptCount() { return attempt_count_; } 366 int NetworkPortalDetectorImpl::NoResponseResultCount() {
367 return no_response_result_count_;
368 }
362 369
363 base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() { 370 base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() {
364 return attempt_start_time_; 371 return attempt_start_time_;
365 } 372 }
366 373
367 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() { 374 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() {
368 if (time_ticks_for_testing_.is_null()) 375 if (time_ticks_for_testing_.is_null())
369 return base::TimeTicks::Now(); 376 return base::TimeTicks::Now();
370 return time_ticks_for_testing_; 377 return time_ticks_for_testing_;
371 } 378 }
372 379
373 380
374 //////////////////////////////////////////////////////////////////////////////// 381 ////////////////////////////////////////////////////////////////////////////////
375 // NetworkPortalDetectorImpl, private: 382 // NetworkPortalDetectorImpl, private:
376 383
377 void NetworkPortalDetectorImpl::StartDetection() { 384 void NetworkPortalDetectorImpl::StartDetection() {
378 attempt_count_ = 0; 385 DCHECK(is_idle());
379 DCHECK(CanPerformAttempt()); 386
387 ResetStrategyAndCounters();
380 detection_start_time_ = GetCurrentTimeTicks(); 388 detection_start_time_ = GetCurrentTimeTicks();
381 ScheduleAttempt(base::TimeDelta()); 389 ScheduleAttempt(base::TimeDelta());
382 } 390 }
383 391
384 void NetworkPortalDetectorImpl::StopDetection() { 392 void NetworkPortalDetectorImpl::StopDetection() {
385 attempt_task_.Cancel(); 393 attempt_task_.Cancel();
386 attempt_timeout_.Cancel(); 394 attempt_timeout_.Cancel();
387 captive_portal_detector_->Cancel(); 395 captive_portal_detector_->Cancel();
388 state_ = STATE_IDLE; 396 state_ = STATE_IDLE;
389 attempt_count_ = 0; 397 ResetStrategyAndCounters();
390 }
391
392 bool NetworkPortalDetectorImpl::CanPerformAttempt() const {
393 return is_idle() && strategy_->CanPerformAttempt();
394 } 398 }
395 399
396 void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) { 400 void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) {
397 DCHECK(CanPerformAttempt()); 401 DCHECK(is_idle());
398 402
399 if (!IsEnabled()) 403 if (!IsEnabled())
400 return; 404 return;
401 405
402 attempt_task_.Cancel(); 406 attempt_task_.Cancel();
403 attempt_timeout_.Cancel(); 407 attempt_timeout_.Cancel();
404 state_ = STATE_PORTAL_CHECK_PENDING; 408 state_ = STATE_PORTAL_CHECK_PENDING;
405 409
406 next_attempt_delay_ = std::max(delay, strategy_->GetDelayTillNextAttempt()); 410 next_attempt_delay_ = std::max(delay, strategy_->GetDelayTillNextAttempt());
407 attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt, 411 attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt,
(...skipping 30 matching lines...) Expand all
438 << "id=" << default_network_id_; 442 << "id=" << default_network_id_;
439 443
440 captive_portal_detector_->Cancel(); 444 captive_portal_detector_->Cancel();
441 CaptivePortalDetector::Results results; 445 CaptivePortalDetector::Results results;
442 results.result = captive_portal::RESULT_NO_RESPONSE; 446 results.result = captive_portal::RESULT_NO_RESPONSE;
443 OnAttemptCompleted(results); 447 OnAttemptCompleted(results);
444 } 448 }
445 449
446 void NetworkPortalDetectorImpl::OnAttemptCompleted( 450 void NetworkPortalDetectorImpl::OnAttemptCompleted(
447 const CaptivePortalDetector::Results& results) { 451 const CaptivePortalDetector::Results& results) {
452 DCHECK(CalledOnValidThread());
453 DCHECK(is_checking_for_portal());
454
448 captive_portal::CaptivePortalResult result = results.result; 455 captive_portal::CaptivePortalResult result = results.result;
449 int response_code = results.response_code; 456 int response_code = results.response_code;
450 457
451 DCHECK(CalledOnValidThread());
452 DCHECK(is_checking_for_portal());
453
454 DetectionAttemptCompletedReport attempt_completed_report(
455 default_network_name_,
456 default_network_id_,
457 results.result,
458 results.response_code);
459 if (!attempt_completed_report_.Equals(attempt_completed_report)) {
460 attempt_completed_report_ = attempt_completed_report;
461 attempt_completed_report_.Report();
462 }
463
464 state_ = STATE_IDLE;
465 attempt_timeout_.Cancel();
466 ++attempt_count_;
467
468 const NetworkState* network = DefaultNetwork(); 458 const NetworkState* network = DefaultNetwork();
469 459
470 // If using a fake profile client, also fake being behind a captive portal 460 // If using a fake profile client, also fake being behind a captive portal
471 // if the default network is in portal state. 461 // if the default network is in portal state.
472 if (result != captive_portal::RESULT_NO_RESPONSE && 462 if (result != captive_portal::RESULT_NO_RESPONSE &&
473 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() && 463 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() &&
474 network && network->connection_state() == shill::kStatePortal) { 464 network && network->connection_state() == shill::kStatePortal) {
475 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL; 465 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
476 response_code = 200; 466 response_code = 200;
477 } 467 }
478 468
469 DetectionAttemptCompletedReport attempt_completed_report(
470 default_network_name_, default_network_id_, result, response_code);
471 if (!attempt_completed_report_.Equals(attempt_completed_report)) {
472 attempt_completed_report_ = attempt_completed_report;
473 attempt_completed_report_.Report();
474 }
475
476 state_ = STATE_IDLE;
477 attempt_timeout_.Cancel();
478
479 CaptivePortalState state; 479 CaptivePortalState state;
480 state.response_code = response_code; 480 state.response_code = response_code;
481 state.time = GetCurrentTimeTicks(); 481 state.time = GetCurrentTimeTicks();
482 switch (result) { 482 switch (result) {
483 case captive_portal::RESULT_NO_RESPONSE: 483 case captive_portal::RESULT_NO_RESPONSE:
484 if (CanPerformAttempt()) { 484 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
485 ScheduleAttempt(results.retry_after_delta);
486 return;
487 } else if (state.response_code ==
488 net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
489 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED; 485 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
490 } else if (network && 486 } else if (network &&
491 (network->connection_state() == shill::kStatePortal)) { 487 (network->connection_state() == shill::kStatePortal)) {
492 // Take into account shill's detection results. 488 // Take into account shill's detection results.
493 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 489 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
494 LOG(WARNING) << "Network name=" << network->name() << ", "
495 << "id=" << network->guid() << " "
496 << "is marked as "
497 << CaptivePortalStatusString(state.status) << " "
498 << "despite the fact that CaptivePortalDetector "
499 << "received no response";
500 } else { 490 } else {
501 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE; 491 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
502 } 492 }
503 break; 493 break;
504 case captive_portal::RESULT_INTERNET_CONNECTED: 494 case captive_portal::RESULT_INTERNET_CONNECTED:
505 state.status = CAPTIVE_PORTAL_STATUS_ONLINE; 495 state.status = CAPTIVE_PORTAL_STATUS_ONLINE;
506 break; 496 break;
507 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: 497 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL:
508 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 498 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
509 break; 499 break;
510 default: 500 default:
511 break; 501 break;
512 } 502 }
513 503
514 OnDetectionCompleted(network, state); 504 if (last_detection_result_ != state.status) {
515 if (CanPerformAttempt() && strategy_->CanPerformAttemptAfterDetection()) 505 last_detection_result_ = state.status;
516 ScheduleAttempt(base::TimeDelta()); 506 same_detection_result_count_ = 1;
507 strategy_->Reset();
508 } else {
509 ++same_detection_result_count_;
510 }
511 strategy_->OnDetectionCompleted();
512
513 if (result == captive_portal::RESULT_NO_RESPONSE)
514 ++no_response_result_count_;
515 else
516 no_response_result_count_ = 0;
517
518 if (state.status != CAPTIVE_PORTAL_STATUS_OFFLINE ||
519 same_detection_result_count_ >= kMaxOfflineResultsBeforeReport) {
520 OnDetectionCompleted(network, state);
521 }
522 ScheduleAttempt(results.retry_after_delta);
517 } 523 }
518 524
519 void NetworkPortalDetectorImpl::Observe( 525 void NetworkPortalDetectorImpl::Observe(
520 int type, 526 int type,
521 const content::NotificationSource& source, 527 const content::NotificationSource& source,
522 const content::NotificationDetails& details) { 528 const content::NotificationDetails& details) {
523 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || 529 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED ||
524 type == chrome::NOTIFICATION_AUTH_SUPPLIED || 530 type == chrome::NOTIFICATION_AUTH_SUPPLIED ||
525 type == chrome::NOTIFICATION_AUTH_CANCELLED) { 531 type == chrome::NOTIFICATION_AUTH_CANCELLED) {
526 VLOG(1) << "Restarting portal detection due to proxy change."; 532 VLOG(1) << "Restarting portal detection due to proxy change.";
527 attempt_count_ = 0;
528 if (is_portal_check_pending())
529 return;
530 StopDetection(); 533 StopDetection();
531 ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec)); 534 ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec));
532 } 535 }
533 } 536 }
534 537
535 void NetworkPortalDetectorImpl::OnDetectionCompleted( 538 void NetworkPortalDetectorImpl::OnDetectionCompleted(
536 const NetworkState* network, 539 const NetworkState* network,
537 const CaptivePortalState& state) { 540 const CaptivePortalState& state) {
538 if (!network) { 541 if (!network) {
539 NotifyDetectionCompleted(network, state); 542 NotifyDetectionCompleted(network, state);
540 return; 543 return;
541 } 544 }
542 545
543 CaptivePortalStateMap::const_iterator it = 546 CaptivePortalStateMap::const_iterator it =
544 portal_state_map_.find(network->guid()); 547 portal_state_map_.find(network->guid());
545 if (it == portal_state_map_.end() || it->second.status != state.status || 548 if (it == portal_state_map_.end() || it->second.status != state.status ||
546 it->second.response_code != state.response_code) { 549 it->second.response_code != state.response_code) {
547 VLOG(1) << "Updating Chrome Captive Portal state: "
548 << "name=" << network->name() << ", "
549 << "id=" << network->guid() << ", "
550 << "status=" << CaptivePortalStatusString(state.status) << ", "
551 << "response_code=" << state.response_code;
552
553 // Record detection duration iff detection result differs from the 550 // Record detection duration iff detection result differs from the
554 // previous one for this network. The reason is to record all stats 551 // previous one for this network. The reason is to record all stats
555 // only when network changes it's state. 552 // only when network changes it's state.
556 RecordDetectionStats(network, state.status); 553 RecordDetectionStats(network, state.status);
557 if (it != portal_state_map_.end() && 554 if (it != portal_state_map_.end() &&
558 it->second.status == CAPTIVE_PORTAL_STATUS_PORTAL && 555 it->second.status == CAPTIVE_PORTAL_STATUS_PORTAL &&
559 state.status == CAPTIVE_PORTAL_STATUS_ONLINE) { 556 state.status == CAPTIVE_PORTAL_STATUS_ONLINE) {
560 RecordPortalToOnlineTransition(state.time - it->second.time); 557 RecordPortalToOnlineTransition(state.time - it->second.time);
561 } 558 }
562 559
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED: 606 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
610 if (network->connection_state() != shill::kStateOnline) 607 if (network->connection_state() != shill::kStateOnline)
611 RecordDiscrepancyWithShill(network, status); 608 RecordDiscrepancyWithShill(network, status);
612 break; 609 break;
613 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT: 610 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
614 NOTREACHED(); 611 NOTREACHED();
615 break; 612 break;
616 } 613 }
617 } 614 }
618 615
616 void NetworkPortalDetectorImpl::ResetStrategyAndCounters() {
617 last_detection_result_ = CAPTIVE_PORTAL_STATUS_UNKNOWN;
618 same_detection_result_count_ = 0;
619 no_response_result_count_ = 0;
620 strategy_->Reset();
621 }
622
619 } // namespace chromeos 623 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698