This source file includes following definitions.
- SslNetErrorMayImplyCaptivePortal
 
- weak_factory_
 
- OnLoadStart
 
- OnLoadCommitted
 
- OnAbort
 
- OnRedirect
 
- OnCaptivePortalResults
 
- OnSSLCertError
 
- OnSlowSSLConnect
 
- SetState
 
- ReloadTabIfNeeded
 
- ReloadTab
 
- MaybeOpenCaptivePortalLoginTab
 
- CheckForCaptivePortal
 
#include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/captive_portal/captive_portal_service.h"
#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "net/base/net_errors.h"
namespace captive_portal {
namespace {
const int kDefaultSlowSSLTimeSeconds = 30;
bool SslNetErrorMayImplyCaptivePortal(int error) {
  
  if (error == net::ERR_CONNECTION_TIMED_OUT)
    return true;
  
  
  
  if (error == net::ERR_SSL_PROTOCOL_ERROR)
    return true;
  return false;
}
}  
CaptivePortalTabReloader::CaptivePortalTabReloader(
    Profile* profile,
    content::WebContents* web_contents,
    const OpenLoginTabCallback& open_login_tab_callback)
    : profile_(profile),
      web_contents_(web_contents),
      state_(STATE_NONE),
      provisional_main_frame_load_(false),
      ssl_url_in_redirect_chain_(false),
      slow_ssl_load_time_(
          base::TimeDelta::FromSeconds(kDefaultSlowSSLTimeSeconds)),
      open_login_tab_callback_(open_login_tab_callback),
      weak_factory_(this) {
}
CaptivePortalTabReloader::~CaptivePortalTabReloader() {
}
void CaptivePortalTabReloader::OnLoadStart(bool is_ssl) {
  provisional_main_frame_load_ = true;
  ssl_url_in_redirect_chain_ = is_ssl;
  SetState(STATE_NONE);
  
  
  
  
  if (is_ssl)
    SetState(STATE_TIMER_RUNNING);
}
void CaptivePortalTabReloader::OnLoadCommitted(int net_error) {
  provisional_main_frame_load_ = false;
  ssl_url_in_redirect_chain_ = false;
  if (state_ == STATE_NONE)
    return;
  
  
  if (!SslNetErrorMayImplyCaptivePortal(net_error)) {
    
    
    
    SetState(STATE_NONE);
    return;
  }
  
  
  if (state_ == STATE_TIMER_RUNNING) {
    OnSlowSSLConnect();
    return;
  }
  
  
  if (state_ == STATE_NEEDS_RELOAD) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&CaptivePortalTabReloader::ReloadTabIfNeeded,
                   weak_factory_.GetWeakPtr()));
  }
}
void CaptivePortalTabReloader::OnAbort() {
  provisional_main_frame_load_ = false;
  ssl_url_in_redirect_chain_ = false;
  SetState(STATE_NONE);
}
void CaptivePortalTabReloader::OnRedirect(bool is_ssl) {
  SetState(STATE_NONE);
  if (!is_ssl)
    return;
  
  
  
  if (!ssl_url_in_redirect_chain_)
    SetState(STATE_TIMER_RUNNING);
  ssl_url_in_redirect_chain_ = true;
}
void CaptivePortalTabReloader::OnCaptivePortalResults(
    Result previous_result,
    Result result) {
  if (result == RESULT_BEHIND_CAPTIVE_PORTAL) {
    if (state_ == STATE_MAYBE_BROKEN_BY_PORTAL) {
      SetState(STATE_BROKEN_BY_PORTAL);
      MaybeOpenCaptivePortalLoginTab();
    }
    return;
  }
  switch (state_) {
    case STATE_MAYBE_BROKEN_BY_PORTAL:
    case STATE_TIMER_RUNNING:
      
      
      
      
      
      
      if (previous_result == RESULT_BEHIND_CAPTIVE_PORTAL) {
        SetState(STATE_NEEDS_RELOAD);
        return;
      }
      SetState(STATE_NONE);
      return;
    case STATE_BROKEN_BY_PORTAL:
      
      
      
      SetState(STATE_NEEDS_RELOAD);
      return;
    case STATE_NEEDS_RELOAD:
    case STATE_NONE:
      
      
      
      return;
    default:
      NOTREACHED();
  }
}
void CaptivePortalTabReloader::OnSSLCertError(const net::SSLInfo& ssl_info) {
  
  
  
  
  if (state_ == STATE_TIMER_RUNNING)
    SetState(STATE_MAYBE_BROKEN_BY_PORTAL);
}
void CaptivePortalTabReloader::OnSlowSSLConnect() {
  SetState(STATE_MAYBE_BROKEN_BY_PORTAL);
}
void CaptivePortalTabReloader::SetState(State new_state) {
  
  if (state_ == STATE_TIMER_RUNNING) {
    slow_ssl_load_timer_.Stop();
  } else {
    DCHECK(!slow_ssl_load_timer_.IsRunning());
  }
  
  switch (state_) {
    case STATE_NONE:
      DCHECK(new_state == STATE_NONE ||
             new_state == STATE_TIMER_RUNNING);
      break;
    case STATE_TIMER_RUNNING:
      DCHECK(new_state == STATE_NONE ||
             new_state == STATE_MAYBE_BROKEN_BY_PORTAL ||
             new_state == STATE_NEEDS_RELOAD);
      break;
    case STATE_MAYBE_BROKEN_BY_PORTAL:
      DCHECK(new_state == STATE_NONE ||
             new_state == STATE_BROKEN_BY_PORTAL ||
             new_state == STATE_NEEDS_RELOAD);
      break;
    case STATE_BROKEN_BY_PORTAL:
      DCHECK(new_state == STATE_NONE ||
             new_state == STATE_NEEDS_RELOAD);
      break;
    case STATE_NEEDS_RELOAD:
      DCHECK_EQ(STATE_NONE, new_state);
      break;
    default:
      NOTREACHED();
      break;
  };
  state_ = new_state;
  switch (state_) {
    case STATE_TIMER_RUNNING:
      slow_ssl_load_timer_.Start(
          FROM_HERE,
          slow_ssl_load_time_,
          this,
          &CaptivePortalTabReloader::OnSlowSSLConnect);
      break;
    case STATE_MAYBE_BROKEN_BY_PORTAL:
      CheckForCaptivePortal();
      break;
    case STATE_NEEDS_RELOAD:
      
      ReloadTabIfNeeded();
      break;
    default:
      break;
  }
}
void CaptivePortalTabReloader::ReloadTabIfNeeded() {
  
  if (state_ != STATE_NEEDS_RELOAD)
    return;
  
  
  
  if (provisional_main_frame_load_ &&
      !content::InterstitialPage::GetInterstitialPage(web_contents_)) {
    return;
  }
  SetState(STATE_NONE);
  ReloadTab();
}
void CaptivePortalTabReloader::ReloadTab() {
  content::NavigationController* controller = &web_contents_->GetController();
  if (!controller->GetActiveEntry()->GetHasPostData())
    controller->Reload(true);
}
void CaptivePortalTabReloader::MaybeOpenCaptivePortalLoginTab() {
  open_login_tab_callback_.Run();
}
void CaptivePortalTabReloader::CheckForCaptivePortal() {
  CaptivePortalService* service =
      CaptivePortalServiceFactory::GetForProfile(profile_);
  if (service)
    service->DetectCaptivePortal();
}
}