summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net
diff options
context:
space:
mode:
authorttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-20 03:51:30 +0000
committerttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-20 03:51:30 +0000
commitd99867df5eca85690b93e574d98b297f0dd818ce (patch)
treeb5505c53f2eef63c4c35cb399282040034bf6cf2 /chrome/browser/net
parent70ca7775fe7edbe3973e3507c6ca00d26e4df5dc (diff)
downloadchromium_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.cc16
-rw-r--r--chrome/browser/net/dns_probe_service.cc48
-rw-r--r--chrome/browser/net/dns_probe_service.h4
-rw-r--r--chrome/browser/net/net_error_tab_helper.cc88
-rw-r--r--chrome/browser/net/net_error_tab_helper.h17
-rw-r--r--chrome/browser/net/net_error_tab_helper_unittest.cc20
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_;
};