15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/dns_probe_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/field_trial.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_client.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_config_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_protocol.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::FieldTrialList;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::StringToInt;
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing chrome_common_net::DnsProbeStatus;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::DnsClient;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::DnsConfig;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::IPAddressNumber;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::IPEndPoint;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::ParseIPLiteralToNumber;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::NetworkChangeNotifier;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_browser_net {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// How long the DnsProbeService will cache the probe result for.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// If it's older than this and we get a probe request, the service expires it
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and starts a new probe.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxResultAgeMs = 5000;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The public DNS servers used by the DnsProbeService to verify internet
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// connectivity.
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kGooglePublicDns1[] = "8.8.8.8";
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kGooglePublicDns2[] = "8.8.4.4";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber dns_ip_number;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool rv = ParseIPLiteralToNumber(dns_ip_literal, &dns_ip_number);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rv);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPEndPoint(dns_ip_number, net::dns_protocol::kDefaultPort);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDnsProbeStatus EvaluateResults(DnsProbeRunner::Result system_result,
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                               DnsProbeRunner::Result public_result) {
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the system DNS is working, assume the domain doesn't exist.
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (system_result == DnsProbeRunner::CORRECT)
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If the system DNS is unknown (e.g. on Android), but the public server is
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // reachable, assume the domain doesn't exist.
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (system_result == DnsProbeRunner::UNKNOWN &&
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      public_result == DnsProbeRunner::CORRECT) {
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN;
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the system DNS is not working but another public server is, assume the
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // DNS config is bad (or perhaps the DNS servers are down or broken).
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (public_result == DnsProbeRunner::CORRECT)
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the system DNS is not working and another public server is unreachable,
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // assume the internet connection is down (note that system DNS may be a
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // router on the LAN, so it may be reachable but returning errors.)
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (public_result == DnsProbeRunner::UNREACHABLE)
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Otherwise: the system DNS is not working and another public server is
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // responding but with errors or incorrect results.  This is an awkward case;
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // an invasive captive portal or a restrictive firewall may be intercepting
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // or rewriting DNS traffic, or the public server may itself be failing or
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // down.
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistogramProbe(DnsProbeStatus status, base::TimeDelta elapsed) {
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(chrome_common_net::DnsProbeStatusIsFinished(status));
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("DnsProbe.ProbeResult", status,
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            chrome_common_net::DNS_PROBE_MAX);
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UMA_HISTOGRAM_MEDIUM_TIMES("DnsProbe.ProbeDuration", elapsed);
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DnsProbeService::DnsProbeService()
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : state_(STATE_NO_RESULT) {
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NetworkChangeNotifier::AddDNSObserver(this);
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SetSystemClientToCurrentConfig();
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SetPublicClientToGooglePublicDns();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DnsProbeService::~DnsProbeService() {
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NetworkChangeNotifier::RemoveDNSObserver(this);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::ProbeDns(const DnsProbeService::ProbeCallback& callback) {
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  pending_callbacks_.push_back(callback);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (CachedResultIsExpired())
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ClearCachedResult();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case STATE_NO_RESULT:
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StartProbes();
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case STATE_RESULT_CACHED:
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CallCallbacks();
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case STATE_PROBE_RUNNING:
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // Do nothing; probe is already running, and will call the callback.
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::OnDNSChanged() {
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ClearCachedResult();
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SetSystemClientToCurrentConfig();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::SetSystemClientForTesting(
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<DnsClient> system_client) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_runner_.SetClient(system_client.Pass());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::SetPublicClientForTesting(
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<DnsClient> public_client) {
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_runner_.SetClient(public_client.Pass());
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::ClearCachedResultForTesting() {
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ClearCachedResult();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::SetSystemClientToCurrentConfig() {
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DnsConfig system_config;
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NetworkChangeNotifier::GetDnsConfig(&system_config);
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_config.search.clear();
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_config.attempts = 1;
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_config.randomize_ports = false;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<DnsClient> system_client(DnsClient::CreateClient(NULL));
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_client->SetConfig(system_config);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_runner_.SetClient(system_client.Pass());
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::SetPublicClientToGooglePublicDns() {
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DnsConfig public_config;
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_config.nameservers.push_back(MakeDnsEndPoint(kGooglePublicDns1));
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_config.nameservers.push_back(MakeDnsEndPoint(kGooglePublicDns2));
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_config.attempts = 1;
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_config.randomize_ports = false;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<DnsClient> public_client(DnsClient::CreateClient(NULL));
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_client->SetConfig(public_config);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_runner_.SetClient(public_client.Pass());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::StartProbes() {
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(STATE_NO_RESULT, state_);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!system_runner_.IsRunning());
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!public_runner_.IsRunning());
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const base::Closure callback = base::Bind(&DnsProbeService::OnProbeComplete,
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                            base::Unretained(this));
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  system_runner_.RunProbe(callback);
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  public_runner_.RunProbe(callback);
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  probe_start_time_ = base::Time::Now();
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  state_ = STATE_PROBE_RUNNING;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(system_runner_.IsRunning());
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(public_runner_.IsRunning());
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::OnProbeComplete() {
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(STATE_PROBE_RUNNING, state_);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (system_runner_.IsRunning() || public_runner_.IsRunning())
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  cached_result_ = EvaluateResults(system_runner_.result(),
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                   public_runner_.result());
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  state_ = STATE_RESULT_CACHED;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  HistogramProbe(cached_result_, base::Time::Now() - probe_start_time_);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CallCallbacks();
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DnsProbeService::CallCallbacks() {
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(STATE_RESULT_CACHED, state_);
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(chrome_common_net::DnsProbeStatusIsFinished(cached_result_));
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!pending_callbacks_.empty());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::vector<ProbeCallback> callbacks;
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  callbacks.swap(pending_callbacks_);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (std::vector<ProbeCallback>::const_iterator i = callbacks.begin();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != callbacks.end(); ++i) {
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    i->Run(cached_result_);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DnsProbeService::ClearCachedResult() {
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state_ == STATE_RESULT_CACHED) {
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    state_ = STATE_NO_RESULT;
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    cached_result_ = chrome_common_net::DNS_PROBE_MAX;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool DnsProbeService::CachedResultIsExpired() const {
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state_ != STATE_RESULT_CACHED)
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kMaxResultAge =
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxResultAgeMs);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::Time::Now() - probe_start_time_ > kMaxResultAge;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace chrome_browser_net
227