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();
}
}