This source file includes following definitions.
- IsDnsError
- OnDnsProbeFinishedOnIOThread
- StartDnsProbeOnIOThread
- set_state_for_testing
- DidStartProvisionalLoadForFrame
- DidCommitProvisionalLoadForFrame
- DidFailProvisionalLoad
- dns_probe_status_
- OnMainFrameDnsError
- StartDnsProbe
- OnDnsProbeFinished
- InitializePref
- ProbesAllowed
- SendInfo
#include "chrome/browser/net/net_error_tab_helper.h"
#include "base/bind.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/dns_probe_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/net/net_error_info.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "net/base/net_errors.h"
using chrome_common_net::DnsProbeStatus;
using chrome_common_net::DnsProbeStatusToString;
using content::BrowserContext;
using content::BrowserThread;
using content::PageTransition;
using content::RenderViewHost;
using content::WebContents;
using content::WebContentsObserver;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(chrome_browser_net::NetErrorTabHelper);
namespace chrome_browser_net {
namespace {
static NetErrorTabHelper::TestingState testing_state_ =
NetErrorTabHelper::TESTING_DEFAULT;
bool IsDnsError(int net_error) {
return net_error == net::ERR_NAME_NOT_RESOLVED ||
net_error == net::ERR_NAME_RESOLUTION_FAILED;
}
void OnDnsProbeFinishedOnIOThread(
const base::Callback<void(DnsProbeStatus)>& callback,
DnsProbeStatus result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(callback, result));
}
void StartDnsProbeOnIOThread(
const base::Callback<void(DnsProbeStatus)>& callback,
IOThread* io_thread) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DnsProbeService* probe_service =
io_thread->globals()->dns_probe_service.get();
probe_service->ProbeDns(base::Bind(&OnDnsProbeFinishedOnIOThread, callback));
}
}
NetErrorTabHelper::~NetErrorTabHelper() {
}
void NetErrorTabHelper::set_state_for_testing(TestingState state) {
testing_state_ = state;
}
void NetErrorTabHelper::DidStartProvisionalLoadForFrame(
int64 frame_id,
int64 parent_frame_id,
bool is_main_frame,
const GURL& validated_url,
bool is_error_page,
bool is_iframe_srcdoc,
RenderViewHost* render_view_host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!is_main_frame)
return;
is_error_page_ = is_error_page;
}
void NetErrorTabHelper::DidCommitProvisionalLoadForFrame(
int64 frame_id,
const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
RenderViewHost* render_view_host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!is_main_frame)
return;
if (is_error_page_ && dns_error_active_) {
dns_error_page_committed_ = true;
DVLOG(1) << "Committed error page; resending status.";
SendInfo();
} else {
dns_error_active_ = false;
dns_error_page_committed_ = false;
}
}
void NetErrorTabHelper::DidFailProvisionalLoad(
int64 frame_id,
const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& validated_url,
int error_code,
const base::string16& error_description,
RenderViewHost* render_view_host) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!is_main_frame)
return;
if (IsDnsError(error_code)) {
dns_error_active_ = true;
OnMainFrameDnsError();
}
}
NetErrorTabHelper::NetErrorTabHelper(WebContents* contents)
: WebContentsObserver(contents),
weak_factory_(this),
is_error_page_(false),
dns_error_active_(false),
dns_error_page_committed_(false),
dns_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (contents)
InitializePref(contents);
}
void NetErrorTabHelper::OnMainFrameDnsError() {
if (ProbesAllowed()) {
if (dns_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) {
StartDnsProbe();
dns_probe_status_ = chrome_common_net::DNS_PROBE_STARTED;
}
} else {
dns_probe_status_ = chrome_common_net::DNS_PROBE_NOT_RUN;
}
}
void NetErrorTabHelper::StartDnsProbe() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(dns_error_active_);
DCHECK_NE(chrome_common_net::DNS_PROBE_STARTED, dns_probe_status_);
DVLOG(1) << "Starting DNS probe.";
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&StartDnsProbeOnIOThread,
base::Bind(&NetErrorTabHelper::OnDnsProbeFinished,
weak_factory_.GetWeakPtr()),
g_browser_process->io_thread()));
}
void NetErrorTabHelper::OnDnsProbeFinished(DnsProbeStatus result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(chrome_common_net::DNS_PROBE_STARTED, dns_probe_status_);
DCHECK(chrome_common_net::DnsProbeStatusIsFinished(result));
DVLOG(1) << "Finished DNS probe with result "
<< DnsProbeStatusToString(result) << ".";
dns_probe_status_ = result;
if (dns_error_page_committed_)
SendInfo();
}
void NetErrorTabHelper::InitializePref(WebContents* contents) {
DCHECK(contents);
BrowserContext* browser_context = contents->GetBrowserContext();
Profile* profile = Profile::FromBrowserContext(browser_context);
resolve_errors_with_web_service_.Init(
prefs::kAlternateErrorPagesEnabled,
profile->GetPrefs());
}
bool NetErrorTabHelper::ProbesAllowed() const {
if (testing_state_ != TESTING_DEFAULT)
return testing_state_ == TESTING_FORCE_ENABLED;
return *resolve_errors_with_web_service_;
}
void NetErrorTabHelper::SendInfo() {
DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, dns_probe_status_);
DCHECK(dns_error_page_committed_);
DVLOG(1) << "Sending status " << DnsProbeStatusToString(dns_probe_status_);
content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
rfh->Send(new ChromeViewMsg_NetErrorInfo(rfh->GetRoutingID(),
dns_probe_status_));
if (!dns_probe_status_snoop_callback_.is_null())
dns_probe_status_snoop_callback_.Run(dns_probe_status_);
}
}