diff options
author | ttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-20 03:51:30 +0000 |
---|---|---|
committer | ttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-20 03:51:30 +0000 |
commit | d99867df5eca85690b93e574d98b297f0dd818ce (patch) | |
tree | b5505c53f2eef63c4c35cb399282040034bf6cf2 /chrome/browser/net | |
parent | 70ca7775fe7edbe3973e3507c6ca00d26e4df5dc (diff) | |
download | chromium_src-d99867df5eca85690b93e574d98b297f0dd818ce.zip chromium_src-d99867df5eca85690b93e574d98b297f0dd818ce.tar.gz chromium_src-d99867df5eca85690b93e574d98b297f0dd818ce.tar.bz2 |
Glue browser-side DNS probing together. We should detect DNS errors on main frame loads, run probes, and get the results, but they won't show error pages yet.
BUG=156415
TEST=extended NetErrorTabHelper test
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=168650
Review URL: https://chromiumcodereview.appspot.com/11363157
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168716 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/net')
-rw-r--r-- | chrome/browser/net/dns_probe_job.cc | 16 | ||||
-rw-r--r-- | chrome/browser/net/dns_probe_service.cc | 48 | ||||
-rw-r--r-- | chrome/browser/net/dns_probe_service.h | 4 | ||||
-rw-r--r-- | chrome/browser/net/net_error_tab_helper.cc | 88 | ||||
-rw-r--r-- | chrome/browser/net/net_error_tab_helper.h | 17 | ||||
-rw-r--r-- | chrome/browser/net/net_error_tab_helper_unittest.cc | 20 |
6 files changed, 154 insertions, 39 deletions
diff --git a/chrome/browser/net/dns_probe_job.cc b/chrome/browser/net/dns_probe_job.cc index 3e5328f..6f57b5a 100644 --- a/chrome/browser/net/dns_probe_job.cc +++ b/chrome/browser/net/dns_probe_job.cc @@ -101,7 +101,6 @@ DnsProbeJobImpl::DnsProbeJobImpl(scoped_ptr<DnsClient> dns_client, } DnsProbeJobImpl::~DnsProbeJobImpl() { - // TODO(ttuttle): Cleanup? (Transactions stop themselves on destruction.) } scoped_ptr<DnsTransaction> DnsProbeJobImpl::CreateTransaction( @@ -146,19 +145,14 @@ DnsProbeJobImpl::QueryResult DnsProbeJobImpl::EvaluateGoodResponse( DnsProbeJobImpl::QueryResult DnsProbeJobImpl::EvaluateBadResponse( int net_error, const DnsResponse* response) { + if (net_error == net::ERR_NAME_NOT_RESOLVED) // NXDOMAIN maps to this + return QUERY_CORRECT; + + // TODO(ttuttle): Examine net_error a little more closely to see whether + // it's a DNS error or a network error. if (net_error != net::OK) return QUERY_NET_ERROR; - AddressList addr_list; - TimeDelta ttl; - DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); - - if (result != DnsResponse::DNS_PARSE_OK) - return QUERY_DNS_ERROR; - - if (addr_list.empty()) - return QUERY_CORRECT; - return QUERY_INCORRECT; } diff --git a/chrome/browser/net/dns_probe_service.cc b/chrome/browser/net/dns_probe_service.cc index 0d006c3..7b43a4a 100644 --- a/chrome/browser/net/dns_probe_service.cc +++ b/chrome/browser/net/dns_probe_service.cc @@ -23,8 +23,8 @@ namespace chrome_browser_net { namespace { -const char* kPublicDnsPrimary = "8.8.8.8"; -const char* kPublicDnsSecondary = "8.8.4.4"; +const char kPublicDnsPrimary[] = "8.8.8.8"; +const char kPublicDnsSecondary[] = "8.8.4.4"; IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) { IPAddressNumber dns_ip_number; @@ -33,7 +33,9 @@ IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) { return IPEndPoint(dns_ip_number, net::dns_protocol::kDefaultPort); } -} +const int kMaxResultAgeMs = 5000; + +} // namespace DnsProbeService::DnsProbeService() : system_result_(DnsProbeJob::SERVERS_UNKNOWN), @@ -48,7 +50,8 @@ DnsProbeService::~DnsProbeService() { void DnsProbeService::ProbeDns(const DnsProbeService::CallbackType& callback) { callbacks_.push_back(callback); - // TODO(ttuttle): Check for cache expiration. + if (state_ == STATE_RESULTS_CACHED && ResultsExpired()) + ExpireResults(); switch (state_) { case STATE_NO_RESULTS: @@ -102,18 +105,45 @@ void DnsProbeService::StartProbes() { public_job_ = CreatePublicProbeJob(job_callback); state_ = STATE_PROBE_RUNNING; + last_probe_time_ = base::Time::Now(); } void DnsProbeService::OnProbesComplete() { DCHECK_EQ(STATE_PROBE_RUNNING, state_); state_ = STATE_RESULTS_CACHED; - // TODO(ttuttle): Calculate result. - result_ = PROBE_NXDOMAIN; + result_ = EvaluateResults(); CallCallbacks(); } +DnsProbeService::Result DnsProbeService::EvaluateResults() { + DCHECK_NE(DnsProbeJob::SERVERS_UNKNOWN, system_result_); + DCHECK_NE(DnsProbeJob::SERVERS_UNKNOWN, public_result_); + + // If the system DNS is working, assume the domain doesn't exist. + if (system_result_ == DnsProbeJob::SERVERS_CORRECT) + return PROBE_NXDOMAIN; + + // If the system DNS is not working but another public server is, assume the + // DNS config is bad (or perhaps the DNS servers are down or broken). + if (public_result_ == DnsProbeJob::SERVERS_CORRECT) + return PROBE_BAD_CONFIG; + + // If the system DNS is not working and another public server is unreachable, + // assume the internet connection is down (note that system DNS may be a + // router on the LAN, so it may be reachable but returning errors.) + if (public_result_ == DnsProbeJob::SERVERS_UNREACHABLE) + return PROBE_NO_INTERNET; + + // Otherwise: the system DNS is not working and another public server is + // responding but with errors or incorrect results. This is an awkward case; + // an invasive captive portal or a restrictive firewall may be intercepting + // or rewriting DNS traffic, or the public server may itself be failing or + // down. + return PROBE_UNKNOWN; +} + void DnsProbeService::CallCallbacks() { DCHECK_EQ(STATE_RESULTS_CACHED, state_); DCHECK(!callbacks_.empty()); @@ -167,4 +197,10 @@ void DnsProbeService::GetPublicDnsConfig(DnsConfig* config) { config->nameservers.push_back(MakeDnsEndPoint(kPublicDnsSecondary)); } +bool DnsProbeService::ResultsExpired() { + const base::TimeDelta kMaxResultAge = + base::TimeDelta::FromMilliseconds(kMaxResultAgeMs); + return base::Time::Now() - last_probe_time_ > kMaxResultAge; +} + } // namespace chrome_browser_net diff --git a/chrome/browser/net/dns_probe_service.h b/chrome/browser/net/dns_probe_service.h index 206344d..8aeb3b7 100644 --- a/chrome/browser/net/dns_probe_service.h +++ b/chrome/browser/net/dns_probe_service.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/time.h" #include "chrome/browser/net/dns_probe_job.h" namespace net { @@ -48,6 +49,7 @@ class DnsProbeService { void CallCallbacks(); void OnProbeJobComplete(DnsProbeJob* job, DnsProbeJob::Result result); + Result EvaluateResults(); // These are expected to be overridden by tests to return mock jobs. virtual scoped_ptr<DnsProbeJob> CreateSystemProbeJob( @@ -60,6 +62,7 @@ class DnsProbeService { const DnsProbeJob::CallbackType& job_callback); void GetSystemDnsConfig(net::DnsConfig* config); void GetPublicDnsConfig(net::DnsConfig* config); + bool ResultsExpired(); scoped_ptr<DnsProbeJob> system_job_; scoped_ptr<DnsProbeJob> public_job_; @@ -68,6 +71,7 @@ class DnsProbeService { std::vector<CallbackType> callbacks_; State state_; Result result_; + base::Time last_probe_time_; DISALLOW_COPY_AND_ASSIGN(DnsProbeService); }; diff --git a/chrome/browser/net/net_error_tab_helper.cc b/chrome/browser/net/net_error_tab_helper.cc index fa0c781..c6d0481 100644 --- a/chrome/browser/net/net_error_tab_helper.cc +++ b/chrome/browser/net/net_error_tab_helper.cc @@ -4,8 +4,15 @@ #include "chrome/browser/net/net_error_tab_helper.h" +#include "base/bind.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/io_thread.h" +#include "chrome/browser/net/dns_probe_service.h" +#include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" +using content::BrowserThread; + DEFINE_WEB_CONTENTS_USER_DATA_KEY(chrome_browser_net::NetErrorTabHelper) namespace chrome_browser_net { @@ -15,14 +22,40 @@ namespace { // Returns whether |net_error| is a DNS-related error (and therefore whether // the tab helper should start a DNS probe after receiving it.) bool IsDnsError(int net_error) { - return net_error == net::ERR_NAME_NOT_RESOLVED; + return net_error == net::ERR_NAME_NOT_RESOLVED || + net_error == net::ERR_NAME_RESOLUTION_FAILED; +} + +void DnsProbeCallback( + base::WeakPtr<NetErrorTabHelper> tab_helper, + DnsProbeService::Result result) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&NetErrorTabHelper::OnDnsProbeFinished, + tab_helper, + result)); +} + +void StartDnsProbe( + base::WeakPtr<NetErrorTabHelper> tab_helper, + IOThread* io_thread) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + DnsProbeService* probe_service = + io_thread->globals()->dns_probe_service.get(); + probe_service->ProbeDns(base::Bind(&DnsProbeCallback, tab_helper)); } } // namespace NetErrorTabHelper::NetErrorTabHelper(content::WebContents* contents) : content::WebContentsObserver(contents), - dns_probe_running_(false) { + dns_probe_running_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); } NetErrorTabHelper::~NetErrorTabHelper() { @@ -35,25 +68,48 @@ void NetErrorTabHelper::DidFailProvisionalLoad( int error_code, const string16& error_description, content::RenderViewHost* render_view_host) { - // If the error wasn't a DNS-related error, a DNS probe won't return any - // useful information, so don't run one. - // - // If the load wasn't a main frame load, there's nowhere to put an error - // page, so don't bother running a probe. (The probes are intended to give - // more useful troubleshooting ideas on DNS error pages.) - // - // If the tab helper has already started a probe, don't start another; it - // will use the result from the first one. - if (IsDnsError(error_code) && is_main_frame && !dns_probe_running_) - StartDnsProbe(); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // Consider running a DNS probe if a main frame load fails with a DNS error + if (is_main_frame && IsDnsError(error_code)) + OnMainFrameDnsError(); } -void NetErrorTabHelper::StartDnsProbe() { - DCHECK(!dns_probe_running_); +void NetErrorTabHelper::OnMainFrameDnsError() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // Don't start a probe if one is running already or we're not allowed to. + if (dns_probe_running_ || !DnsProbesAllowedByPref()) + return; - // TODO(ttuttle): Start probe. + PostStartDnsProbeTask(); set_dns_probe_running(true); } +void NetErrorTabHelper::OnDnsProbeFinished( + DnsProbeService::Result result) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(dns_probe_running_); + + // TODO(ttuttle): Notify renderer of probe results. + + set_dns_probe_running(false); +} + +void NetErrorTabHelper::PostStartDnsProbeTask() { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&StartDnsProbe, + weak_factory_.GetWeakPtr(), + g_browser_process->io_thread())); +} + +bool NetErrorTabHelper::DnsProbesAllowedByPref() const { + // TODO(ttuttle): Actually check the pref. + // TODO(ttuttle): Disable on browser_tests and maybe on mobile. + return false; +} + } // namespace chrome_browser_net diff --git a/chrome/browser/net/net_error_tab_helper.h b/chrome/browser/net/net_error_tab_helper.h index bc64bc1..4793bab 100644 --- a/chrome/browser/net/net_error_tab_helper.h +++ b/chrome/browser/net/net_error_tab_helper.h @@ -6,6 +6,9 @@ #define CHROME_BROWSER_NET_NET_ERROR_TAB_HELPER_H_ #include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/net/dns_probe_service.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -29,6 +32,8 @@ class NetErrorTabHelper const string16& error_description, content::RenderViewHost* render_view_host) OVERRIDE; + void OnDnsProbeFinished(DnsProbeService::Result result); + protected: friend class content::WebContentsUserData<NetErrorTabHelper>; @@ -36,17 +41,25 @@ class NetErrorTabHelper // attached to. explicit NetErrorTabHelper(content::WebContents* contents); - // Starts a DNS probe. - virtual void StartDnsProbe(); + // Posts a task to the IO thread that will start a DNS probe. + virtual void PostStartDnsProbeTask(); + + // Checks if the "Use web service to resolve navigation errors" preference is + // enabled on the profile. + virtual bool DnsProbesAllowedByPref() const; bool dns_probe_running() { return dns_probe_running_; } void set_dns_probe_running(bool running) { dns_probe_running_ = running; } private: + void OnMainFrameDnsError(); + // Whether the tab helper has started a DNS probe that has not yet returned // a result. bool dns_probe_running_; + base::WeakPtrFactory<NetErrorTabHelper> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(NetErrorTabHelper); }; diff --git a/chrome/browser/net/net_error_tab_helper_unittest.cc b/chrome/browser/net/net_error_tab_helper_unittest.cc index 22196fe..86372f4 100644 --- a/chrome/browser/net/net_error_tab_helper_unittest.cc +++ b/chrome/browser/net/net_error_tab_helper_unittest.cc @@ -4,11 +4,18 @@ #include "chrome/browser/net/net_error_tab_helper.h" +#include "base/message_loop.h" +#include "base/run_loop.h" #include "chrome/browser/net/dns_probe_service.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/test_browser_thread.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" +using content::BrowserThread; +using content::TestBrowserThread; + namespace chrome_browser_net { namespace { @@ -18,13 +25,14 @@ class TestNetErrorTabHelper : public NetErrorTabHelper { TestNetErrorTabHelper() : NetErrorTabHelper(NULL), probe_start_count_(0) { } - virtual void StartDnsProbe() { + virtual void PostStartDnsProbeTask() OVERRIDE { ++probe_start_count_; - NetErrorTabHelper::StartDnsProbe(); } + virtual bool DnsProbesAllowedByPref() const OVERRIDE { return true; } + void SimulateProbeResult(DnsProbeService::Result result) { - set_dns_probe_running(false); + OnDnsProbeFinished(result); } bool dns_probe_running() { return NetErrorTabHelper::dns_probe_running(); } @@ -36,7 +44,8 @@ class TestNetErrorTabHelper : public NetErrorTabHelper { class NetErrorTabHelperTest : public testing::Test { public: - NetErrorTabHelperTest() { } + NetErrorTabHelperTest() + : ui_thread_(BrowserThread::UI, &message_loop_) { } protected: void SimulateFailure(bool is_main_frame, int error_code) { @@ -52,6 +61,9 @@ class NetErrorTabHelperTest : public testing::Test { NULL /* render_view_host */); } + MessageLoop message_loop_; + TestBrowserThread ui_thread_; + TestNetErrorTabHelper tab_helper_; }; |