Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / net / dns_probe_service.cc
blob38b79041382109fdcae18b684a76bc58f2fca825
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/net/dns_probe_service.h"
7 #include "base/metrics/field_trial.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "net/base/ip_endpoint.h"
11 #include "net/base/net_util.h"
12 #include "net/dns/dns_client.h"
13 #include "net/dns/dns_config_service.h"
14 #include "net/dns/dns_protocol.h"
16 using base::FieldTrialList;
17 using base::StringToInt;
18 using chrome_common_net::DnsProbeStatus;
19 using net::DnsClient;
20 using net::DnsConfig;
21 using net::IPAddressNumber;
22 using net::ParseIPLiteralToNumber;
23 using net::NetworkChangeNotifier;
25 namespace chrome_browser_net {
27 namespace {
29 // How long the DnsProbeService will cache the probe result for.
30 // If it's older than this and we get a probe request, the service expires it
31 // and starts a new probe.
32 const int kMaxResultAgeMs = 5000;
34 // The public DNS servers used by the DnsProbeService to verify internet
35 // connectivity.
36 const char kGooglePublicDns1[] = "8.8.8.8";
37 const char kGooglePublicDns2[] = "8.8.4.4";
39 net::IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) {
40 IPAddressNumber dns_ip_number;
41 bool rv = ParseIPLiteralToNumber(dns_ip_literal, &dns_ip_number);
42 DCHECK(rv);
43 return net::IPEndPoint(dns_ip_number, net::dns_protocol::kDefaultPort);
46 DnsProbeStatus EvaluateResults(DnsProbeRunner::Result system_result,
47 DnsProbeRunner::Result public_result) {
48 // If the system DNS is working, assume the domain doesn't exist.
49 if (system_result == DnsProbeRunner::CORRECT)
50 return chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN;
52 // If the system DNS is unknown (e.g. on Android), but the public server is
53 // reachable, assume the domain doesn't exist.
54 if (system_result == DnsProbeRunner::UNKNOWN &&
55 public_result == DnsProbeRunner::CORRECT) {
56 return chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN;
59 // If the system DNS is not working but another public server is, assume the
60 // DNS config is bad (or perhaps the DNS servers are down or broken).
61 if (public_result == DnsProbeRunner::CORRECT)
62 return chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG;
64 // If the system DNS is not working and another public server is unreachable,
65 // assume the internet connection is down (note that system DNS may be a
66 // router on the LAN, so it may be reachable but returning errors.)
67 if (public_result == DnsProbeRunner::UNREACHABLE)
68 return chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET;
70 // Otherwise: the system DNS is not working and another public server is
71 // responding but with errors or incorrect results. This is an awkward case;
72 // an invasive captive portal or a restrictive firewall may be intercepting
73 // or rewriting DNS traffic, or the public server may itself be failing or
74 // down.
75 return chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE;
78 void HistogramProbe(DnsProbeStatus status, base::TimeDelta elapsed) {
79 DCHECK(chrome_common_net::DnsProbeStatusIsFinished(status));
81 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ProbeResult", status,
82 chrome_common_net::DNS_PROBE_MAX);
83 UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.ProbeDuration", elapsed);
86 } // namespace
88 DnsProbeService::DnsProbeService()
89 : state_(STATE_NO_RESULT) {
90 NetworkChangeNotifier::AddDNSObserver(this);
91 SetSystemClientToCurrentConfig();
92 SetPublicClientToGooglePublicDns();
95 DnsProbeService::~DnsProbeService() {
96 NetworkChangeNotifier::RemoveDNSObserver(this);
99 void DnsProbeService::ProbeDns(const DnsProbeService::ProbeCallback& callback) {
100 pending_callbacks_.push_back(callback);
102 if (CachedResultIsExpired())
103 ClearCachedResult();
105 switch (state_) {
106 case STATE_NO_RESULT:
107 StartProbes();
108 break;
109 case STATE_RESULT_CACHED:
110 CallCallbacks();
111 break;
112 case STATE_PROBE_RUNNING:
113 // Do nothing; probe is already running, and will call the callback.
114 break;
118 void DnsProbeService::OnDNSChanged() {
119 ClearCachedResult();
120 SetSystemClientToCurrentConfig();
123 void DnsProbeService::SetSystemClientForTesting(
124 scoped_ptr<DnsClient> system_client) {
125 system_runner_.SetClient(system_client.Pass());
128 void DnsProbeService::SetPublicClientForTesting(
129 scoped_ptr<DnsClient> public_client) {
130 public_runner_.SetClient(public_client.Pass());
133 void DnsProbeService::ClearCachedResultForTesting() {
134 ClearCachedResult();
137 void DnsProbeService::SetSystemClientToCurrentConfig() {
138 DnsConfig system_config;
139 NetworkChangeNotifier::GetDnsConfig(&system_config);
140 system_config.search.clear();
141 system_config.attempts = 1;
142 system_config.randomize_ports = false;
144 scoped_ptr<DnsClient> system_client(DnsClient::CreateClient(NULL));
145 system_client->SetConfig(system_config);
147 system_runner_.SetClient(system_client.Pass());
150 void DnsProbeService::SetPublicClientToGooglePublicDns() {
151 DnsConfig public_config;
152 public_config.nameservers.push_back(MakeDnsEndPoint(kGooglePublicDns1));
153 public_config.nameservers.push_back(MakeDnsEndPoint(kGooglePublicDns2));
154 public_config.attempts = 1;
155 public_config.randomize_ports = false;
157 scoped_ptr<DnsClient> public_client(DnsClient::CreateClient(NULL));
158 public_client->SetConfig(public_config);
160 public_runner_.SetClient(public_client.Pass());
163 void DnsProbeService::StartProbes() {
164 DCHECK_EQ(STATE_NO_RESULT, state_);
166 DCHECK(!system_runner_.IsRunning());
167 DCHECK(!public_runner_.IsRunning());
169 const base::Closure callback = base::Bind(&DnsProbeService::OnProbeComplete,
170 base::Unretained(this));
171 system_runner_.RunProbe(callback);
172 public_runner_.RunProbe(callback);
173 probe_start_time_ = base::Time::Now();
174 state_ = STATE_PROBE_RUNNING;
176 DCHECK(system_runner_.IsRunning());
177 DCHECK(public_runner_.IsRunning());
180 void DnsProbeService::OnProbeComplete() {
181 DCHECK_EQ(STATE_PROBE_RUNNING, state_);
183 if (system_runner_.IsRunning() || public_runner_.IsRunning())
184 return;
186 cached_result_ = EvaluateResults(system_runner_.result(),
187 public_runner_.result());
188 state_ = STATE_RESULT_CACHED;
190 HistogramProbe(cached_result_, base::Time::Now() - probe_start_time_);
192 CallCallbacks();
195 void DnsProbeService::CallCallbacks() {
196 DCHECK_EQ(STATE_RESULT_CACHED, state_);
197 DCHECK(chrome_common_net::DnsProbeStatusIsFinished(cached_result_));
198 DCHECK(!pending_callbacks_.empty());
200 std::vector<ProbeCallback> callbacks;
201 callbacks.swap(pending_callbacks_);
203 for (std::vector<ProbeCallback>::const_iterator i = callbacks.begin();
204 i != callbacks.end(); ++i) {
205 i->Run(cached_result_);
209 void DnsProbeService::ClearCachedResult() {
210 if (state_ == STATE_RESULT_CACHED) {
211 state_ = STATE_NO_RESULT;
212 cached_result_ = chrome_common_net::DNS_PROBE_MAX;
216 bool DnsProbeService::CachedResultIsExpired() const {
217 if (state_ != STATE_RESULT_CACHED)
218 return false;
220 const base::TimeDelta kMaxResultAge =
221 base::TimeDelta::FromMilliseconds(kMaxResultAgeMs);
222 return base::Time::Now() - probe_start_time_ > kMaxResultAge;
225 } // namespace chrome_browser_net