Index: chrome/browser/net/dns_probe_service.cc |
diff --git a/chrome/browser/net/dns_probe_service.cc b/chrome/browser/net/dns_probe_service.cc |
index 8a0e9f073e973e6581e7c11a1924c5d5760cf34c..31cc65c697ccbe8c0efec330fce154d29fec06ce 100644 |
--- a/chrome/browser/net/dns_probe_service.cc |
+++ b/chrome/browser/net/dns_probe_service.cc |
@@ -7,17 +7,18 @@ |
#include "base/metrics/field_trial.h" |
#include "base/metrics/histogram.h" |
#include "base/strings/string_number_conversions.h" |
-#include "chrome/browser/net/dns_probe_job.h" |
+#include "chrome/browser/net/dns_probe_runner.h" |
#include "chrome/common/net/net_error_info.h" |
#include "net/base/ip_endpoint.h" |
#include "net/base/net_util.h" |
+#include "net/base/network_change_notifier.h" |
#include "net/dns/dns_client.h" |
#include "net/dns/dns_config_service.h" |
#include "net/dns/dns_protocol.h" |
using base::FieldTrialList; |
using base::StringToInt; |
-using chrome_common_net::DnsProbeResult; |
+using chrome_common_net::DnsProbeStatus; |
using net::DnsClient; |
using net::DnsConfig; |
using net::IPAddressNumber; |
@@ -25,8 +26,6 @@ using net::IPEndPoint; |
using net::ParseIPLiteralToNumber; |
using net::NetworkChangeNotifier; |
-namespace chrome_browser_net { |
- |
namespace { |
// How long the DnsProbeService will cache the probe result for. |
@@ -62,34 +61,25 @@ int GetAttemptsFromFieldTrial() { |
return attempts; |
} |
-bool IsLocalhost(const IPAddressNumber& ip) { |
- return (ip.size() == net::kIPv4AddressSize) |
- && (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1); |
-} |
- |
-// The maximum number of nameservers counted in histograms. |
-const int kNameserverCountMax = 10; |
- |
} // namespace |
DnsProbeService::DnsProbeService() |
- : system_result_(DnsProbeJob::SERVERS_UNKNOWN), |
- public_result_(DnsProbeJob::SERVERS_UNKNOWN), |
- state_(STATE_NO_RESULTS), |
- result_(chrome_common_net::DNS_PROBE_UNKNOWN), |
- dns_attempts_(GetAttemptsFromFieldTrial()) { |
- NetworkChangeNotifier::AddIPAddressObserver(this); |
+ : state_(STATE_NO_RESULTS), |
+ system_result_(DnsProbeRunner::UNKNOWN), |
+ public_result_(DnsProbeRunner::UNKNOWN), |
+ result_(chrome_common_net::DNS_PROBE_MAX) { |
+ NetworkChangeNotifier::AddDNSObserver(this); |
} |
DnsProbeService::~DnsProbeService() { |
- NetworkChangeNotifier::RemoveIPAddressObserver(this); |
+ NetworkChangeNotifier::RemoveDNSObserver(this); |
} |
-void DnsProbeService::ProbeDns(const DnsProbeService::CallbackType& callback) { |
- callbacks_.push_back(callback); |
+void DnsProbeService::ProbeDns(const DnsProbeService::ProbeCallback& callback) { |
+ pending_callbacks_.push_back(callback); |
if (state_ == STATE_RESULTS_CACHED && ResultsExpired()) |
- ExpireResults(); |
+ ExpireResult(); |
switch (state_) { |
case STATE_NO_RESULTS: |
@@ -104,63 +94,41 @@ void DnsProbeService::ProbeDns(const DnsProbeService::CallbackType& callback) { |
} |
} |
-scoped_ptr<DnsProbeJob> DnsProbeService::CreateSystemProbeJob( |
- const DnsProbeJob::CallbackType& job_callback) { |
- DnsConfig system_config; |
- GetSystemDnsConfig(&system_config); |
- return CreateProbeJob(system_config, job_callback); |
+void DnsProbeService::ExpireResultForTesting() { |
+ ExpireResult(); |
} |
-scoped_ptr<DnsProbeJob> DnsProbeService::CreatePublicProbeJob( |
- const DnsProbeJob::CallbackType& job_callback) { |
- DnsConfig public_config; |
- GetPublicDnsConfig(&public_config); |
- return CreateProbeJob(public_config, job_callback); |
+DnsProbeRunner* DnsProbeService::GetProbeRunnerForTesting() { |
+ return &probe_runner_; |
} |
-void DnsProbeService::OnIPAddressChanged() { |
- if (state_ == STATE_RESULTS_CACHED) |
- ExpireResults(); |
+void DnsProbeService::OnDNSChanged() { |
+ ExpireResult(); |
} |
-void DnsProbeService::ExpireResults() { |
- DCHECK_EQ(STATE_RESULTS_CACHED, state_); |
- |
- state_ = STATE_NO_RESULTS; |
- result_ = chrome_common_net::DNS_PROBE_UNKNOWN; |
+void DnsProbeService::ExpireResult() { |
+ if (state_ == STATE_RESULTS_CACHED) { |
+ state_ = STATE_NO_RESULTS; |
+ result_ = chrome_common_net::DNS_PROBE_MAX; |
+ } |
} |
void DnsProbeService::StartProbes() { |
DCHECK_NE(STATE_PROBE_RUNNING, state_); |
- DCHECK(!system_job_.get()); |
- DCHECK(!public_job_.get()); |
- |
- DnsProbeJob::CallbackType job_callback = |
- base::Bind(&DnsProbeService::OnProbeJobComplete, |
- base::Unretained(this)); |
- |
- // TODO(ttuttle): Do we want to keep explicit flags for "job done"? |
- // Or maybe DnsProbeJob should have a "finished" flag? |
- system_result_ = DnsProbeJob::SERVERS_UNKNOWN; |
- public_result_ = DnsProbeJob::SERVERS_UNKNOWN; |
- |
- system_job_ = CreateSystemProbeJob(job_callback); |
- public_job_ = CreatePublicProbeJob(job_callback); |
- |
- // If we can't create one or both jobs, fail the probe immediately. |
- if (!system_job_.get() || !public_job_.get()) { |
- system_job_.reset(); |
- public_job_.reset(); |
- state_ = STATE_RESULTS_CACHED; |
- // TODO(ttuttle): Should this be BAD_CONFIG? Currently I think it only |
- // happens when the system DnsConfig has no servers. |
- result_ = chrome_common_net::DNS_PROBE_UNKNOWN; |
- CallCallbacks(); |
- return; |
- } |
+ |
+ const DnsProbeRunner::ProbeCallback probe_callback = |
+ base::Bind(&DnsProbeService::OnProbeComplete, base::Unretained(this)); |
+ |
+ system_done_ = false; |
+ public_done_ = false; |
+ system_result_ = DnsProbeRunner::UNKNOWN; |
+ public_result_ = DnsProbeRunner::UNKNOWN; |
state_ = STATE_PROBE_RUNNING; |
probe_start_time_ = base::Time::Now(); |
+ |
+ probe_runner_.RunProbe(DnsProbeRunner::SYSTEM, probe_callback); |
+ probe_runner_.RunProbe(DnsProbeRunner::PUBLIC, probe_callback); |
} |
void DnsProbeService::OnProbesComplete() { |
@@ -174,171 +142,121 @@ void DnsProbeService::OnProbesComplete() { |
CallCallbacks(); |
} |
+// TODO(ttuttle): Make sure we're not changing result histogram mappings going |
+// from DnsProbeJob to DnsProbeRunner. |
void DnsProbeService::HistogramProbes() const { |
- const DnsProbeResult kMaxResult = chrome_common_net::DNS_PROBE_MAX; |
+ const DnsProbeStatus kMaxStatus = chrome_common_net::DNS_PROBE_MAX; |
DCHECK_EQ(STATE_RESULTS_CACHED, state_); |
- DCHECK_NE(kMaxResult, result_); |
+ DCHECK(chrome_common_net::DnsProbeStatusIsFinished(result_)); |
base::TimeDelta elapsed = base::Time::Now() - probe_start_time_; |
- UMA_HISTOGRAM_ENUMERATION("DnsProbe.Probe.Result", result_, kMaxResult); |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.Elapsed", elapsed); |
+ UMA_HISTOGRAM_ENUMERATION("DnsProbe.Status", result_, kMaxStatus); |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed", elapsed); |
if (NetworkChangeNotifier::IsOffline()) { |
- UMA_HISTOGRAM_ENUMERATION("DnsProbe.Probe.NcnOffline.Result", |
- result_, kMaxResult); |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.NcnOffline.Elapsed", elapsed); |
+ UMA_HISTOGRAM_ENUMERATION("DnsProbe.Status_NcnOffline", |
+ result_, kMaxStatus); |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed_NcnOffline", elapsed); |
} else { |
- UMA_HISTOGRAM_ENUMERATION("DnsProbe.Probe.NcnOnline.Result", |
- result_, kMaxResult); |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.NcnOnline.Elapsed", elapsed); |
+ UMA_HISTOGRAM_ENUMERATION("DnsProbe.Status_NcnOnline", |
+ result_, kMaxStatus); |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed_NcnOnline", elapsed); |
} |
switch (result_) { |
- case chrome_common_net::DNS_PROBE_UNKNOWN: |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.ResultUnknown.Elapsed", |
+ case chrome_common_net::DNS_PROBE_FINISHED_UNKNOWN: |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed_Unknown", |
elapsed); |
break; |
- case chrome_common_net::DNS_PROBE_NO_INTERNET: |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.ResultNoInternet.Elapsed", |
+ case chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET: |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed_NoInternet", |
elapsed); |
break; |
- case chrome_common_net::DNS_PROBE_BAD_CONFIG: |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.ResultBadConfig.Elapsed", |
+ case chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG: |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed_BadConfig", |
elapsed); |
- |
- // Histogram some extra data to see why BAD_CONFIG is happening. |
- UMA_HISTOGRAM_ENUMERATION( |
- "DnsProbe.Probe.ResultBadConfig.SystemJobResult", |
- system_result_, |
- DnsProbeJob::MAX_RESULT); |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "DnsProbe.Probe.ResultBadConfig.SystemNameserverCount", |
- system_nameserver_count_, |
- 0, kNameserverCountMax, kNameserverCountMax + 1); |
- UMA_HISTOGRAM_BOOLEAN( |
- "DnsProbe.Probe.ResultBadConfig.SystemIsLocalhost", |
- system_is_localhost_); |
break; |
- case chrome_common_net::DNS_PROBE_NXDOMAIN: |
- UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Probe.ResultNxdomain.Elapsed", |
+ case chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN: |
+ UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.Elapsed_Nxdomain", |
elapsed); |
break; |
+ |
+ // These aren't actually results. |
+ case chrome_common_net::DNS_PROBE_POSSIBLE: |
+ case chrome_common_net::DNS_PROBE_NOT_RUN: |
+ case chrome_common_net::DNS_PROBE_STARTED: |
case chrome_common_net::DNS_PROBE_MAX: |
NOTREACHED(); |
break; |
} |
} |
-DnsProbeResult DnsProbeService::EvaluateResults() const { |
- DCHECK_NE(DnsProbeJob::SERVERS_UNKNOWN, system_result_); |
- DCHECK_NE(DnsProbeJob::SERVERS_UNKNOWN, public_result_); |
+DnsProbeStatus DnsProbeService::EvaluateResults() const { |
+ DCHECK_NE(DnsProbeRunner::UNKNOWN, system_result_); |
+ DCHECK_NE(DnsProbeRunner::UNKNOWN, public_result_); |
// If the system DNS is working, assume the domain doesn't exist. |
- if (system_result_ == DnsProbeJob::SERVERS_CORRECT) |
- return chrome_common_net::DNS_PROBE_NXDOMAIN; |
+ if (system_result_ == DnsProbeRunner::CORRECT) |
+ return chrome_common_net::DNS_PROBE_FINISHED_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 chrome_common_net::DNS_PROBE_BAD_CONFIG; |
+ if (public_result_ == DnsProbeRunner::CORRECT) |
+ return chrome_common_net::DNS_PROBE_FINISHED_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 chrome_common_net::DNS_PROBE_NO_INTERNET; |
+ if (public_result_ == DnsProbeRunner::UNREACHABLE) |
+ return chrome_common_net::DNS_PROBE_FINISHED_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 chrome_common_net::DNS_PROBE_UNKNOWN; |
+ return chrome_common_net::DNS_PROBE_FINISHED_UNKNOWN; |
} |
void DnsProbeService::CallCallbacks() { |
DCHECK_EQ(STATE_RESULTS_CACHED, state_); |
- DCHECK(!callbacks_.empty()); |
+ DCHECK(chrome_common_net::DnsProbeStatusIsFinished(result_)); |
+ DCHECK(!pending_callbacks_.empty()); |
- std::vector<CallbackType> callbacks = callbacks_; |
- callbacks_.clear(); |
+ std::vector<ProbeCallback> callbacks = pending_callbacks_; |
+ pending_callbacks_.clear(); |
- for (std::vector<CallbackType>::const_iterator i = callbacks.begin(); |
+ for (std::vector<ProbeCallback>::const_iterator i = callbacks.begin(); |
i != callbacks.end(); ++i) { |
i->Run(result_); |
} |
} |
-scoped_ptr<DnsProbeJob> DnsProbeService::CreateProbeJob( |
- const DnsConfig& dns_config, |
- const DnsProbeJob::CallbackType& job_callback) { |
- if (!dns_config.IsValid()) |
- return scoped_ptr<DnsProbeJob>(NULL); |
- |
- scoped_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL)); |
- dns_client->SetConfig(dns_config); |
- return DnsProbeJob::CreateJob(dns_client.Pass(), job_callback, NULL); |
-} |
- |
-void DnsProbeService::OnProbeJobComplete(DnsProbeJob* job, |
- DnsProbeJob::Result result) { |
+void DnsProbeService::OnProbeComplete(DnsProbeRunner::Type type, |
+ DnsProbeRunner::Result result) { |
DCHECK_EQ(STATE_PROBE_RUNNING, state_); |
- if (job == system_job_.get()) { |
+ switch (type) { |
+ case DnsProbeRunner::SYSTEM: |
+ DCHECK(!system_done_); |
system_result_ = result; |
- system_job_.reset(); |
- } else if (job == public_job_.get()) { |
+ system_done_ = true; |
+ break; |
+ case DnsProbeRunner::PUBLIC: |
+ DCHECK(!public_done_); |
public_result_ = result; |
- public_job_.reset(); |
- } else { |
- NOTREACHED(); |
- return; |
+ public_done_ = true; |
} |
- if (system_result_ != DnsProbeJob::SERVERS_UNKNOWN && |
- public_result_ != DnsProbeJob::SERVERS_UNKNOWN) { |
+ if (system_done_ && public_done_) { |
OnProbesComplete(); |
} |
} |
-void DnsProbeService::GetSystemDnsConfig(DnsConfig* config) { |
- NetworkChangeNotifier::GetDnsConfig(config); |
- |
- // DNS probes don't need or want the suffix search list populated |
- config->search.clear(); |
- |
- if (dns_attempts_ != kAttemptsUseDefault) |
- config->attempts = dns_attempts_; |
- |
- // Take notes in case the config turns out to be bad, so we can histogram |
- // some useful data. |
- system_nameserver_count_ = config->nameservers.size(); |
- system_is_localhost_ = (system_nameserver_count_ == 1) |
- && IsLocalhost(config->nameservers[0].address()); |
- |
- // Disable port randomization. |
- config->randomize_ports = false; |
-} |
- |
-void DnsProbeService::GetPublicDnsConfig(DnsConfig* config) { |
- *config = DnsConfig(); |
- |
- config->nameservers.push_back(MakeDnsEndPoint(kPublicDnsPrimary)); |
- config->nameservers.push_back(MakeDnsEndPoint(kPublicDnsSecondary)); |
- |
- if (dns_attempts_ != kAttemptsUseDefault) |
- config->attempts = dns_attempts_; |
- |
- // Disable port randomization. |
- config->randomize_ports = false; |
-} |
- |
bool DnsProbeService::ResultsExpired() { |
const base::TimeDelta kMaxResultAge = |
base::TimeDelta::FromMilliseconds(kMaxResultAgeMs); |
return base::Time::Now() - probe_start_time_ > kMaxResultAge; |
} |
- |
-} // namespace chrome_browser_net |