| 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
|
|
|