blob: 3126f603a4bf4a8305c2c755289f514594149f63 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/captive_portal/content/captive_portal_tab_helper.h"
#include "base/debug/dump_without_crashing.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "components/captive_portal/content/captive_portal_login_detector.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "net/ssl/ssl_info.h"
namespace captive_portal {
CaptivePortalTabHelper::CaptivePortalTabHelper(
content::WebContents* web_contents,
CaptivePortalService* captive_portal_service,
const CaptivePortalTabReloader::OpenLoginTabCallback&
open_login_tab_callback)
: content::WebContentsObserver(web_contents),
content::WebContentsUserData<CaptivePortalTabHelper>(*web_contents),
tab_reloader_(new CaptivePortalTabReloader(captive_portal_service,
web_contents,
open_login_tab_callback)),
login_detector_(new CaptivePortalLoginDetector(captive_portal_service)),
is_captive_portal_window_(false),
subscription_(captive_portal_service->RegisterCallback(
base::BindRepeating(&CaptivePortalTabHelper::Observe,
base::Unretained(this)))) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
CaptivePortalTabHelper::~CaptivePortalTabHelper() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
void CaptivePortalTabHelper::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!navigation_handle->IsInPrimaryMainFrame() ||
navigation_handle->IsSameDocument()) {
return;
}
// TODO(clamy): The root cause behind crbug.com/704892 is known.
// Remove this code if it is never reached until ~ 2017-July-20.
if (navigation_handle == navigation_handle_)
base::debug::DumpWithoutCrashing();
bool was_tracking_navigation = !!navigation_handle_;
navigation_handle_ = navigation_handle;
// Always track the latest navigation. If a navigation was already tracked,
// and it committed (either the navigation proper or an error page), it is
// safe to start tracking the new navigation. Otherwise simulate an abort
// before reporting the start of the new navigation.
if (was_tracking_navigation)
tab_reloader_->OnAbort();
tab_reloader_->OnLoadStart(
navigation_handle->GetURL().SchemeIsCryptographic());
}
void CaptivePortalTabHelper::DidRedirectNavigation(
content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (navigation_handle != navigation_handle_)
return;
DCHECK(navigation_handle->IsInPrimaryMainFrame());
tab_reloader_->OnRedirect(
navigation_handle->GetURL().SchemeIsCryptographic());
}
void CaptivePortalTabHelper::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Exclude non-primary frame and subframe navigations.
if (!navigation_handle->IsInPrimaryMainFrame())
return;
// Exclude same-document navigations and aborted navigations that were not
// being tracked.
if (navigation_handle_ != navigation_handle &&
(!navigation_handle->HasCommitted() ||
navigation_handle->IsSameDocument())) {
return;
}
bool need_to_simulate_start = navigation_handle_ != navigation_handle;
bool need_to_simulate_previous_abort =
need_to_simulate_start && !!navigation_handle_;
navigation_handle_ = nullptr;
if (need_to_simulate_previous_abort)
tab_reloader_->OnAbort();
if (need_to_simulate_start) {
tab_reloader_->OnLoadStart(
navigation_handle->GetURL().SchemeIsCryptographic());
}
if (navigation_handle->HasCommitted()) {
tab_reloader_->OnLoadCommitted(navigation_handle->GetNetErrorCode(),
navigation_handle->GetResolveErrorInfo());
} else {
tab_reloader_->OnAbort();
}
}
void CaptivePortalTabHelper::DidStopLoading() {
login_detector_->OnStoppedLoading();
}
void CaptivePortalTabHelper::Observe(
const CaptivePortalService::Results& results) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
OnCaptivePortalResults(results.previous_result, results.result);
}
void CaptivePortalTabHelper::OnSSLCertError(const net::SSLInfo& ssl_info) {
tab_reloader_->OnSSLCertError(ssl_info);
}
bool CaptivePortalTabHelper::IsLoginTab() const {
return login_detector_->is_login_tab();
}
void CaptivePortalTabHelper::OnCaptivePortalResults(
CaptivePortalResult previous_result,
CaptivePortalResult result) {
tab_reloader_->OnCaptivePortalResults(previous_result, result);
login_detector_->OnCaptivePortalResults(previous_result, result);
}
void CaptivePortalTabHelper::SetIsLoginTab() {
login_detector_->SetIsLoginTab();
}
void CaptivePortalTabHelper::SetTabReloaderForTest(
CaptivePortalTabReloader* tab_reloader) {
tab_reloader_.reset(tab_reloader);
}
CaptivePortalTabReloader* CaptivePortalTabHelper::GetTabReloaderForTest() {
return tab_reloader_.get();
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(CaptivePortalTabHelper);
} // namespace captive_portal