1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/host_resolver_impl.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <Winsock2.h>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_POSIX)
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <netdb.h>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <cmath>
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <deque>
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h"
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/debug/debugger.h"
20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/debug/stack_trace.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/field_trial.h"
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/stl_util-inl.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h"
273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/worker_pool.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h"
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/address_list.h"
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/address_list_net_log_param.h"
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/host_port_pair.h"
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/host_resolver_proc.h"
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_log.h"
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/winsock_init.h"
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// We use a separate histogram name for each platform to facilitate the
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// display of error codes by their symbolic name (since each platform has
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// different mappings).
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst char kOSErrorsForGetAddrinfoHistogramName[] =
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if defined(OS_WIN)
52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "Net.OSErrorsForGetAddrinfo_Win";
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#elif defined(OS_MACOSX)
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "Net.OSErrorsForGetAddrinfo_Mac";
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#elif defined(OS_LINUX)
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "Net.OSErrorsForGetAddrinfo_Linux";
57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#else
58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "Net.OSErrorsForGetAddrinfo";
59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHostCache* CreateDefaultCache() {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const size_t kMaxHostCacheEntries = 100;
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HostCache* cache = new HostCache(
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      kMaxHostCacheEntries,
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta::FromMinutes(1),
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::TimeDelta::FromSeconds(0));  // Disable caching of failed DNS.
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return cache;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // anonymous namespace
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                       HostResolverProc* resolver_proc,
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       NetLog* net_log) {
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Maximum of 8 concurrent resolver threads.
78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Some routers (or resolvers) appear to start to provide host-not-found if
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // too many simultaneous resolutions are pending.  This number needs to be
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // further optimized, but 8 is what FF currently does.
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  static const size_t kDefaultMaxJobs = 8u;
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (max_concurrent_resolves == HostResolver::kDefaultParallelism)
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    max_concurrent_resolves = kDefaultMaxJobs;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HostResolverImpl* resolver =
87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new HostResolverImpl(resolver_proc, CreateDefaultCache(),
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           max_concurrent_resolves, net_log);
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90dd0e069b1c2e5079f99024c4d54c7d06ef81d11bIain Merrick  return resolver;
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int ResolveAddrInfo(HostResolverProc* resolver_proc,
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           const std::string& host,
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           AddressFamily address_family,
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           HostResolverFlags host_resolver_flags,
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           AddressList* out,
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           int* os_error) {
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (resolver_proc) {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Use the custom procedure.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return resolver_proc->Resolve(host, address_family,
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  host_resolver_flags, out, os_error);
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Use the system procedure (getaddrinfo).
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return SystemHostResolverProc(host, address_family,
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  host_resolver_flags, out, os_error);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Extra parameters to attach to the NetLog when the resolve failed.
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HostResolveFailedParams : public NetLog::EventParameters {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostResolveFailedParams(int net_error, int os_error)
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : net_error_(net_error),
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        os_error_(os_error) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual Value* ToValue() const {
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue* dict = new DictionaryValue();
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetInteger("net_error", net_error_);
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (os_error_) {
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      dict->SetInteger("os_error", os_error_);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      dict->SetString("os_error_string", gai_strerror(os_error_));
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_WIN)
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Map the error code to a human-readable string.
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LPWSTR error_string = NULL;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               FORMAT_MESSAGE_FROM_SYSTEM,
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               0,  // Use the internal message table.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               os_error_,
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               0,  // Use default language.
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               (LPWSTR)&error_string,
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               0,  // Buffer size.
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               0);  // Arguments (unused).
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      dict->SetString("os_error_string", WideToUTF8(error_string));
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LocalFree(error_string);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return dict;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int net_error_;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int os_error_;
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Parameters representing the information in a RequestInfo object, along with
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the associated NetLog::Source.
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass RequestInfoParameters : public NetLog::EventParameters {
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  RequestInfoParameters(const HostResolver::RequestInfo& info,
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        const NetLog::Source& source)
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : info_(info), source_(source) {}
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual Value* ToValue() const {
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DictionaryValue* dict = new DictionaryValue();
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetString("host", info_.host_port_pair().ToString());
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetInteger("address_family",
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                     static_cast<int>(info_.address_family()));
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetBoolean("allow_cached_response", info_.allow_cached_response());
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    dict->SetBoolean("only_use_cached_response",
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                     info_.only_use_cached_response());
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetBoolean("is_speculative", info_.is_speculative());
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetInteger("priority", info_.priority());
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (source_.is_valid())
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      dict->Set("source_dependency", source_.ToValue());
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return dict;
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HostResolver::RequestInfo info_;
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const NetLog::Source source_;
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Parameters associated with the creation of a HostResolverImpl::Job.
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass JobCreationParameters : public NetLog::EventParameters {
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  JobCreationParameters(const std::string& host, const NetLog::Source& source)
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : host_(host), source_(source) {}
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual Value* ToValue() const {
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DictionaryValue* dict = new DictionaryValue();
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->SetString("host", host_);
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->Set("source_dependency", source_.ToValue());
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return dict;
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const std::string host_;
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const NetLog::Source source_;
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Gets a list of the likely error codes that getaddrinfo() can return
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (non-exhaustive). These are the error codes that we will track via
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a histogram.
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<int> GetAllGetAddrinfoOSErrors() {
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int os_errors[] = {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
20400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#ifndef ANDROID
20500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // "obsoleted ..." see bionic/libc/include/netdb.h
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_ADDRFAMILY,
20700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#endif
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_AGAIN,
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_BADFLAGS,
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_FAIL,
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_FAMILY,
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_MEMORY,
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_NODATA,
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_NONAME,
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_SERVICE,
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_SOCKTYPE,
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EAI_SYSTEM,
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_WIN)
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSA_NOT_ENOUGH_MEMORY,
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSAEAFNOSUPPORT,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSAEINVAL,
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSAESOCKTNOSUPPORT,
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSAHOST_NOT_FOUND,
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSANO_DATA,
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSANO_RECOVERY,
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSANOTINITIALISED,
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSATRY_AGAIN,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WSATYPE_NOT_FOUND,
230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // The following are not in doc, but might be to appearing in results :-(.
231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    WSA_INVALID_HANDLE,
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Histogram enumerations require positive numbers.
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<int> errors;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < arraysize(os_errors); ++i) {
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    errors.push_back(std::abs(os_errors[i]));
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Also add N+1 for each error, so the bucket that contains our expected
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // error is of size 1. That way if we get unexpected error codes, they
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // won't fall into the same buckets as the expected ones.
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    errors.push_back(std::abs(os_errors[i]) + 1);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return errors;
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HostResolverImpl::Request {
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Request(const BoundNetLog& source_net_log,
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          const BoundNetLog& request_net_log,
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          int id,
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          const RequestInfo& info,
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          CompletionCallback* callback,
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          AddressList* addresses)
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : source_net_log_(source_net_log),
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        request_net_log_(request_net_log),
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        id_(id),
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        info_(info),
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        job_(NULL),
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        callback_(callback),
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        addresses_(addresses) {
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Mark the request as cancelled.
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void MarkAsCancelled() {
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    job_ = NULL;
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    callback_ = NULL;
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    addresses_ = NULL;
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool was_cancelled() const {
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return callback_ == NULL;
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void set_job(Job* job) {
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(job != NULL);
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Identify which job the request is waiting on.
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    job_ = job;
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnComplete(int error, const AddressList& addrlist) {
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (error == OK)
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      addresses_->SetFrom(addrlist, port());
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CompletionCallback* callback = callback_;
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MarkAsCancelled();
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    callback->Run(error);
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int port() const {
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return info_.port();
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Job* job() const {
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return job_;
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const BoundNetLog& source_net_log() {
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return source_net_log_;
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const BoundNetLog& request_net_log() {
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return request_net_log_;
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int id() const {
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return id_;
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const RequestInfo& info() const {
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return info_;
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BoundNetLog source_net_log_;
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BoundNetLog request_net_log_;
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Unique ID for this request. Used by observers to identify requests.
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int id_;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The request info that started the request.
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RequestInfo info_;
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The resolve job (running in worker pool) that this request is dependent on.
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Job* job_;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The user's callback to invoke when the request completes.
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallback* callback_;
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The address list to save result into.
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddressList* addresses_;
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(Request);
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick//------------------------------------------------------------------------------
338731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
339731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Provide a common macro to simplify code and readability. We must use a
340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// macros as the underlying HISTOGRAM macro creates static varibles.
341731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \
342731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromHours(1), 100)
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class represents a request to the worker pool for a "getaddrinfo()"
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// call.
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HostResolverImpl::Job
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public base::RefCountedThreadSafe<HostResolverImpl::Job> {
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Job(int id,
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HostResolverImpl* resolver,
3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const Key& key,
3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const BoundNetLog& source_net_log,
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NetLog* net_log)
3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     : id_(id),
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       key_(key),
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       resolver_(resolver),
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       origin_loop_(MessageLoop::current()),
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       resolver_proc_(resolver->effective_resolver_proc()),
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       error_(OK),
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       os_error_(0),
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       had_non_speculative_request_(false),
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       net_log_(BoundNetLog::Make(net_log,
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) {
364513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    net_log_.BeginEvent(
365513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
366513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        make_scoped_refptr(
367513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch            new JobCreationParameters(key.hostname, source_net_log.source())));
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Attaches a request to this job. The job takes ownership of |req| and will
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // take care to delete it.
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void AddRequest(Request* req) {
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    req->request_net_log().BeginEvent(
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH,
375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        make_scoped_refptr(new NetLogSourceParameter(
376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch            "source_dependency", net_log_.source())));
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    req->set_job(this);
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    requests_.push_back(req);
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!req->info().is_speculative())
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      had_non_speculative_request_ = true;
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called from origin loop.
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Start() {
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    start_time_ = base::TimeTicks::Now();
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Dispatch the job to a worker thread.
3903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    if (!base::WorkerPool::PostTask(FROM_HERE,
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            NewRunnableMethod(this, &Job::DoLookup), true)) {
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Since we could be running within Resolve() right now, we can't just
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // call OnLookupComplete().  Instead we must wait until Resolve() has
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // returned (IO_PENDING).
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      error_ = ERR_UNEXPECTED;
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      MessageLoop::current()->PostTask(
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          FROM_HERE, NewRunnableMethod(this, &Job::OnLookupComplete));
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Cancels the current job. Callable from origin thread.
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Cancel() {
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HostResolver* resolver = resolver_;
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    resolver_ = NULL;
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Mark the job as cancelled, so when worker thread completes it will
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // not try to post completion to origin loop.
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock locked(origin_loop_lock_);
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      origin_loop_ = NULL;
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // End here to prevent issues when a Job outlives the HostResolver that
4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // spawned it.
4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL);
4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We will call HostResolverImpl::CancelRequest(Request*) on each one
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // in order to notify any observers.
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (RequestsList::const_iterator it = requests_.begin();
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         it != requests_.end(); ++it) {
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      HostResolverImpl::Request* req = *it;
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!req->was_cancelled())
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        resolver->CancelRequest(req);
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called from origin thread.
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool was_cancelled() const {
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return resolver_ == NULL;
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called from origin thread.
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const Key& key() const {
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return key_;
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int id() const {
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return id_;
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::TimeTicks start_time() const {
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return start_time_;
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called from origin thread.
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const RequestsList& requests() const {
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return requests_;
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns the first request attached to the job.
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const Request* initial_request() const {
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK_EQ(origin_loop_, MessageLoop::current());
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!requests_.empty());
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return requests_[0];
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns true if |req_info| can be fulfilled by this job.
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool CanServiceRequest(const RequestInfo& req_info) const {
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return key_ == resolver_->GetEffectiveKeyForRequest(req_info);
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class base::RefCountedThreadSafe<HostResolverImpl::Job>;
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~Job() {
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Free the requests attached to this job.
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    STLDeleteElements(&requests_);
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WARNING: This code runs inside a worker pool. The shutdown code cannot
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // wait for it to finish, so we must be very careful here about using other
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // objects (like MessageLoops, Singletons, etc). During shutdown these objects
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // may no longer exist.
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void DoLookup() {
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Running on the worker thread
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    error_ = ResolveAddrInfo(resolver_proc_,
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             key_.hostname,
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             key_.address_family,
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             key_.host_resolver_flags,
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &results_,
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &os_error_);
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The origin loop could go away while we are trying to post to it, so we
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // need to call its PostTask method inside a lock.  See ~HostResolver.
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
49072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock locked(origin_loop_lock_);
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (origin_loop_) {
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        origin_loop_->PostTask(FROM_HERE,
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               NewRunnableMethod(this, &Job::OnLookupComplete));
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Callback for when DoLookup() completes (runs on origin thread).
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnLookupComplete() {
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Should be running on origin loop.
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(eroman): this is being hit by URLRequestTest.CancelTest*,
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // because MessageLoop::current() == NULL.
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //DCHECK_EQ(origin_loop_, MessageLoop::current());
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(error_ || results_.head());
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
506731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Ideally the following code would be part of host_resolver_proc.cc,
507731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // however it isn't safe to call NetworkChangeNotifier from worker
508731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // threads. So we do it here on the IO thread instead.
509731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (error_ != OK && NetworkChangeNotifier::IsOffline())
510731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      error_ = ERR_INTERNET_DISCONNECTED;
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
512731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RecordPerformanceHistograms();
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (was_cancelled())
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return;
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<NetLog::EventParameters> params;
5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (error_ != OK) {
5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      params = new HostResolveFailedParams(error_, os_error_);
5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      params = new AddressListNetLogParam(results_);
5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // End here to prevent issues when a Job outlives the HostResolver that
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // spawned it.
5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, params);
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!requests_.empty());
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     // Use the port number of the first request.
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (error_ == OK)
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      results_.SetPort(requests_[0]->port());
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resolver_->OnJobComplete(this, error_, os_error_, results_);
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
537731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void RecordPerformanceHistograms() const {
538731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    enum Category {  // Used in HISTOGRAM_ENUMERATION.
539731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RESOLVE_SUCCESS,
540731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RESOLVE_FAIL,
541731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RESOLVE_SPECULATIVE_SUCCESS,
542731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RESOLVE_SPECULATIVE_FAIL,
543731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      RESOLVE_MAX,  // Bounding value.
544731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    };
545731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int category = RESOLVE_MAX;  // Illegal value for later DCHECK only.
546731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
547731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
548731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (error_ == OK) {
549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (had_non_speculative_request_) {
550731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        category = RESOLVE_SUCCESS;
551731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        DNS_HISTOGRAM("DNS.ResolveSuccess", duration);
552731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      } else {
553731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        category = RESOLVE_SPECULATIVE_SUCCESS;
554731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        DNS_HISTOGRAM("DNS.ResolveSpeculativeSuccess", duration);
555731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
556731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    } else {
557731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (had_non_speculative_request_) {
558731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        category = RESOLVE_FAIL;
559731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        DNS_HISTOGRAM("DNS.ResolveFail", duration);
560731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      } else {
561731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        category = RESOLVE_SPECULATIVE_FAIL;
562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        DNS_HISTOGRAM("DNS.ResolveSpeculativeFail", duration);
563731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
564731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName,
565731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                       std::abs(os_error_),
566731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                       GetAllGetAddrinfoOSErrors());
567731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
568731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DCHECK_LT(category, static_cast<int>(RESOLVE_MAX));  // Be sure it was set.
569731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX);
571731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
572731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    static bool show_speculative_experiment_histograms =
573731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        base::FieldTrialList::Find("DnsImpact") &&
574731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        !base::FieldTrialList::Find("DnsImpact")->group_name().empty();
575731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (show_speculative_experiment_histograms) {
576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      UMA_HISTOGRAM_ENUMERATION(
577731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          base::FieldTrial::MakeName("DNS.ResolveCategory", "DnsImpact"),
578731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          category, RESOLVE_MAX);
579731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (RESOLVE_SUCCESS == category) {
580731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess",
581731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                 "DnsImpact"), duration);
582731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
583731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
584731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    static bool show_parallelism_experiment_histograms =
585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        base::FieldTrialList::Find("DnsParallelism") &&
586731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        !base::FieldTrialList::Find("DnsParallelism")->group_name().empty();
587731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (show_parallelism_experiment_histograms) {
588731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      UMA_HISTOGRAM_ENUMERATION(
589731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          base::FieldTrial::MakeName("DNS.ResolveCategory", "DnsParallelism"),
590731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          category, RESOLVE_MAX);
591731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (RESOLVE_SUCCESS == category) {
592731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess",
593731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                 "DnsParallelism"), duration);
594731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
595731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
596731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
597731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
598731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
599731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Immutable. Can be read from either thread,
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int id_;
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Set on the origin thread, read on the worker thread.
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Key key_;
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Only used on the origin thread (where Resolve was called).
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HostResolverImpl* resolver_;
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RequestsList requests_;  // The requests waiting on this job.
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Used to post ourselves onto the origin thread.
61172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::Lock origin_loop_lock_;
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop* origin_loop_;
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Hold an owning reference to the HostResolverProc that we are going to use.
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This may not be the current resolver procedure by the time we call
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // reference ensures that it remains valid until we are done.
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<HostResolverProc> resolver_proc_;
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Assigned on the worker thread, read on the origin thread.
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int error_;
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int os_error_;
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // True if a non-speculative request was ever attached to this job
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (regardless of whether or not it was later cancelled.
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This boolean is used for histogramming the duration of jobs used to
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // service non-speculative requests.
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool had_non_speculative_request_;
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddressList results_;
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The time when the job was started.
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::TimeTicks start_time_;
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BoundNetLog net_log_;
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(Job);
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class represents a request to the worker pool for a "probe for IPv6
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// support" call.
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HostResolverImpl::IPv6ProbeJob
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> {
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit IPv6ProbeJob(HostResolverImpl* resolver)
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : resolver_(resolver),
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        origin_loop_(MessageLoop::current()) {
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!was_cancelled());
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Start() {
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (was_cancelled())
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(IsOnOriginThread());
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const bool kIsSlow = true;
6583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::WorkerPool::PostTask(
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FROM_HERE, NewRunnableMethod(this, &IPv6ProbeJob::DoProbe), kIsSlow);
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancels the current job.
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Cancel() {
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (was_cancelled())
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(IsOnOriginThread());
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resolver_ = NULL;  // Read/write ONLY on origin thread.
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    {
66972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock locked(origin_loop_lock_);
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Origin loop may be destroyed before we can use it!
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      origin_loop_ = NULL;  // Write ONLY on origin thread.
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob>;
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~IPv6ProbeJob() {
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Should be run on |orgin_thread_|, but that may not be well defined now.
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_cancelled() const {
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!resolver_ || !origin_loop_) {
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DCHECK(!resolver_);
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DCHECK(!origin_loop_);
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Run on worker thread.
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void DoProbe() {
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Do actual testing on this thread, as it takes 40-100ms.
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           : ADDRESS_FAMILY_IPV4;
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Task* reply = NewRunnableMethod(this, &IPv6ProbeJob::OnProbeComplete,
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    family);
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The origin loop could go away while we are trying to post to it, so we
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // need to call its PostTask method inside a lock.  See ~HostResolver.
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    {
70372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock locked(origin_loop_lock_);
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (origin_loop_) {
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        origin_loop_->PostTask(FROM_HERE, reply);
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We didn't post, so delete the reply.
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete reply;
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Callback for when DoProbe() completes (runs on origin thread).
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnProbeComplete(AddressFamily address_family) {
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (was_cancelled())
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(IsOnOriginThread());
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resolver_->IPv6ProbeSetDefaultAddressFamily(address_family);
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IsOnOriginThread() const {
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return !MessageLoop::current() || origin_loop_ == MessageLoop::current();
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Used/set only on origin thread.
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HostResolverImpl* resolver_;
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Used to post ourselves onto the origin thread.
73072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::Lock origin_loop_lock_;
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop* origin_loop_;
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob);
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//-----------------------------------------------------------------------------
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We rely on the priority enum values being sequential having starting at 0,
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and increasing for lower priorities.
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(HIGHEST == 0u &&
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               LOWEST > HIGHEST &&
7423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               IDLE > LOWEST &&
7433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               NUM_PRIORITIES > IDLE,
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               priority_indexes_incompatible);
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// JobPool contains all the information relating to queued requests, including
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the limits on how many jobs are allowed to be used for this category of
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// requests.
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HostResolverImpl::JobPool {
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  JobPool(size_t max_outstanding_jobs, size_t max_pending_requests)
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : num_outstanding_jobs_(0u) {
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetConstraints(max_outstanding_jobs, max_pending_requests);
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~JobPool() {
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Free the pending requests.
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0; i < arraysize(pending_requests_); ++i)
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      STLDeleteElements(&pending_requests_[i]);
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Sets the constraints for this pool. See SetPoolConstraints() for the
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // specific meaning of these parameters.
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetConstraints(size_t max_outstanding_jobs,
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      size_t max_pending_requests) {
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CHECK_NE(max_outstanding_jobs, 0u);
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_outstanding_jobs_ = max_outstanding_jobs;
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_pending_requests_ = max_pending_requests;
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns the number of pending requests enqueued to this pool.
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A pending request is one waiting to be attached to a job.
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t GetNumPendingRequests() const {
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    size_t total = 0u;
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0u; i < arraysize(pending_requests_); ++i)
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      total += pending_requests_[i].size();
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return total;
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool HasPendingRequests() const {
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GetNumPendingRequests() > 0u;
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Enqueues a request to this pool. As a result of enqueing this request,
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the queue may have reached its maximum size. In this case, a request is
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // evicted from the queue, and returned. Otherwise returns NULL. The caller
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // is responsible for freeing the evicted request.
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Request* InsertPendingRequest(Request* req) {
7893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    req->request_net_log().BeginEvent(
7903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE,
7913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NULL);
7923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PendingRequestsQueue& q = pending_requests_[req->info().priority()];
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    q.push_back(req);
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If the queue is too big, kick out the lowest priority oldest request.
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (GetNumPendingRequests() > max_pending_requests_) {
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Iterate over the queues from lowest priority to highest priority.
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      for (int i = static_cast<int>(arraysize(pending_requests_)) - 1;
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott           i >= 0; --i) {
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        PendingRequestsQueue& q = pending_requests_[i];
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (!q.empty()) {
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          Request* req = q.front();
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          q.pop_front();
8053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          req->request_net_log().AddEvent(
8063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE_EVICTED, NULL);
8073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          req->request_net_log().EndEvent(
8083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL);
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return req;
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Erases |req| from this container. Caller is responsible for freeing
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |req| afterwards.
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void RemovePendingRequest(Request* req) {
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PendingRequestsQueue& q = pending_requests_[req->info().priority()];
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PendingRequestsQueue::iterator it = std::find(q.begin(), q.end(), req);
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(it != q.end());
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    q.erase(it);
8243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    req->request_net_log().EndEvent(
8253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL);
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Removes and returns the highest priority pending request.
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Request* RemoveTopPendingRequest() {
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(HasPendingRequests());
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0u; i < arraysize(pending_requests_); ++i) {
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PendingRequestsQueue& q = pending_requests_[i];
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!q.empty()) {
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Request* req = q.front();
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        q.pop_front();
8373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        req->request_net_log().EndEvent(
8383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL);
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return req;
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Keeps track of a job that was just added/removed, and belongs to this pool.
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void AdjustNumOutstandingJobs(int offset) {
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(offset == 1 || (offset == -1 && num_outstanding_jobs_ > 0u));
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    num_outstanding_jobs_ += offset;
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void ResetNumOutstandingJobs() {
8543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    num_outstanding_jobs_ = 0;
8553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
8563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if a new job can be created for this pool.
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool CanCreateJob() const {
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return num_outstanding_jobs_ + 1u <= max_outstanding_jobs_;
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Removes any pending requests from the queue which are for the
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // same (hostname / effective address-family) as |job|, and attaches them to
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |job|.
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void MoveRequestsToJob(Job* job) {
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0u; i < arraysize(pending_requests_); ++i) {
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PendingRequestsQueue& q = pending_requests_[i];
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PendingRequestsQueue::iterator req_it = q.begin();
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      while (req_it != q.end()) {
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Request* req = *req_it;
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (job->CanServiceRequest(req->info())) {
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          // Job takes ownership of |req|.
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          job->AddRequest(req);
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          req_it = q.erase(req_it);
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          ++req_it;
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::deque<Request*> PendingRequestsQueue;
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Maximum number of concurrent jobs allowed to be started for requests
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // belonging to this pool.
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t max_outstanding_jobs_;
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The current number of running jobs that were started for requests
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // belonging to this pool.
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t num_outstanding_jobs_;
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The maximum number of requests we allow to be waiting on a job,
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // for this pool.
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t max_pending_requests_;
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The requests which are waiting to be started for this pool.
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PendingRequestsQueue pending_requests_[NUM_PRIORITIES];
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHostResolverImpl::HostResolverImpl(
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HostResolverProc* resolver_proc,
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HostCache* cache,
9063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    size_t max_jobs,
9073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NetLog* net_log)
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : cache_(cache),
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      max_jobs_(max_jobs),
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_request_id_(0),
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_job_id_(0),
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      resolver_proc_(resolver_proc),
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      default_address_family_(ADDRESS_FAMILY_UNSPECIFIED),
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      shutdown_(false),
9153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ipv6_probe_monitoring_(false),
9163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      additional_resolver_flags_(0),
9173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net_log_(net_log) {
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(max_jobs, 0u);
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // It is cumbersome to expose all of the constraints in the constructor,
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // so we choose some defaults, which users can override later.
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  job_pools_[POOL_NORMAL] = new JobPool(max_jobs, 100u * max_jobs);
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EnsureWinsockInit();
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
9273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_LINUX)
9283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (HaveOnlyLoopbackAddresses())
9293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
9303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
931dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NetworkChangeNotifier::AddIPAddressObserver(this);
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHostResolverImpl::~HostResolverImpl() {
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Cancel the outstanding jobs. Those jobs may contain several attached
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // requests, which will also be cancelled.
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DiscardIPv6ProbeJob();
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CancelAllJobs();
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // In case we are being deleted during the processing of a callback.
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cur_completing_job_)
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cur_completing_job_->Cancel();
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
945dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NetworkChangeNotifier::RemoveIPAddressObserver(this);
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Delete the job pools.
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0u; i < arraysize(job_pools_); ++i)
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete job_pools_[i];
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HostResolverImpl::ProbeIPv6Support() {
95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(CalledOnValidThread());
95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!ipv6_probe_monitoring_);
95572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ipv6_probe_monitoring_ = true;
95672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  OnIPAddressChanged();  // Give initial setup call.
95772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
95872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
95972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HostResolverImpl::SetPoolConstraints(JobPoolIndex pool_index,
96072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                          size_t max_outstanding_jobs,
96172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                          size_t max_pending_requests) {
96272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(CalledOnValidThread());
96372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK_GE(pool_index, 0);
96472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK_LT(pool_index, POOL_COUNT);
96572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(jobs_.empty()) << "Can only set constraints during setup";
96672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  JobPool* pool = job_pools_[pool_index];
96772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  pool->SetConstraints(max_outstanding_jobs, max_pending_requests);
96872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
96972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HostResolverImpl::Resolve(const RequestInfo& info,
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              AddressList* addresses,
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              CompletionCallback* callback,
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              RequestHandle* out_req,
9743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              const BoundNetLog& source_net_log) {
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (shutdown_)
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_UNEXPECTED;
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Choose a unique ID number for observers to see.
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int request_id = next_request_id_++;
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make a log item for the request.
9843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BoundNetLog request_net_log = BoundNetLog::Make(net_log_,
9853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST);
9863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the net log and notify registered observers.
9883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnStartRequest(source_net_log, request_net_log, request_id, info);
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Build a key that identifies the request in the cache and in the
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // outstanding jobs map.
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Key key = GetEffectiveKeyForRequest(info);
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Check for IP literal.
9953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  IPAddressNumber ip_number;
9963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (ParseIPLiteralToNumber(info.hostname(), &ip_number)) {
9973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_EQ(key.host_resolver_flags &
9983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                  ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY |
9993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6),
10003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              0) << " Unhandled flag";
10013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool ipv6_disabled = default_address_family_ == ADDRESS_FAMILY_IPV4 &&
10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        !ipv6_probe_monitoring_;
10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int net_error = OK;
10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (ip_number.size() == 16 && ipv6_disabled) {
10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net_error = ERR_NAME_NOT_RESOLVED;
10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
10073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      AddressList result(ip_number, info.port(),
10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         (key.host_resolver_flags & HOST_RESOLVER_CANONNAME));
10093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      *addresses = result;
10103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
10113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Update the net log and notify registered observers.
10123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    OnFinishRequest(source_net_log, request_net_log, request_id, info,
10133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    net_error, 0  /* os_error (unknown since from cache) */);
10143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return net_error;
10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
10163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If we have an unexpired cache entry, use it.
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (info.allow_cached_response() && cache_.get()) {
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const HostCache::Entry* cache_entry = cache_->Lookup(
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        key, base::TimeTicks::Now());
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (cache_entry) {
10223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL);
1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int net_error = cache_entry->error;
1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (net_error == OK)
1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        addresses->SetFrom(cache_entry->addrlist, info.port());
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Update the net log and notify registered observers.
10283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      OnFinishRequest(source_net_log, request_net_log, request_id, info,
10293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      net_error,
10303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      0  /* os_error (unknown since from cache) */);
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net_error;
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1036dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (info.only_use_cached_response()) {  // Not allowed to do a real lookup.
1037dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OnFinishRequest(source_net_log,
1038dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    request_net_log,
1039dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    request_id,
1040dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    info,
1041dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    ERR_NAME_NOT_RESOLVED,
1042dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    0);
1043dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_NAME_NOT_RESOLVED;
1044dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1045dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If no callback was specified, do a synchronous resolution.
1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!callback) {
1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AddressList addrlist;
1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int os_error = 0;
1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int error = ResolveAddrInfo(
1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        effective_resolver_proc(), key.hostname, key.address_family,
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        key.host_resolver_flags, &addrlist, &os_error);
1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (error == OK) {
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      addrlist.SetPort(info.port());
1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *addresses = addrlist;
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Write to cache.
1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (cache_.get())
1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cache_->Set(key, error, addrlist, base::TimeTicks::Now());
1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Update the net log and notify registered observers.
10633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    OnFinishRequest(source_net_log, request_net_log, request_id, info, error,
10643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    os_error);
1065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return error;
1067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Create a handle for this request, and pass it back to the user if they
1070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // asked for it (out_req != NULL).
10713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Request* req = new Request(source_net_log, request_net_log, request_id, info,
10723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             callback, addresses);
1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (out_req)
1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *out_req = reinterpret_cast<RequestHandle>(req);
1075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Next we need to attach our request to a "job". This job is responsible for
1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // calling "getaddrinfo(hostname)" on a worker thread.
1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<Job> job;
1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If there is already an outstanding job to resolve |key|, use
1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // it. This prevents starting concurrent resolves for the same hostname.
1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  job = FindOutstandingJob(key);
1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (job) {
1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    job->AddRequest(req);
1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    JobPool* pool = GetPoolForRequest(req);
1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (CanCreateJobForPool(*pool)) {
1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CreateAndStartJob(req);
1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return EnqueueRequest(pool, req);
1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Completion happens during OnJobComplete(Job*).
1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See OnJobComplete(Job*) for why it is important not to clean out
1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cancelled requests from Job::requests_.
1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::CancelRequest(RequestHandle req_handle) {
1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (shutdown_) {
1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(eroman): temp hack for: http://crbug.com/18373
1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Because we destroy outstanding requests during Shutdown(),
1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // |req_handle| is already cancelled.
1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Called HostResolverImpl::CancelRequest() after Shutdown().";
1107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    base::debug::StackTrace().PrintBacktrace();
1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Request* req = reinterpret_cast<Request*>(req_handle);
1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(req);
1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<Request> request_deleter;  // Frees at end of function.
1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!req->job()) {
1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If the request was not attached to a job yet, it must have been
1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // enqueued into a pool. Remove it from that pool's queue.
1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Otherwise if it was attached to a job, the job is responsible for
1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // deleting it.
1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    JobPool* pool = GetPoolForRequest(req);
1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pool->RemovePendingRequest(req);
1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_deleter.reset(req);
11233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
11243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    req->request_net_log().EndEvent(
11253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, NULL);
1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // NULL out the fields of req, to mark it as cancelled.
1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  req->MarkAsCancelled();
11303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnCancelRequest(req->source_net_log(), req->request_net_log(), req->id(),
11313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                  req->info());
1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::AddObserver(HostResolver::Observer* observer) {
1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  observers_.push_back(observer);
1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) {
1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
1141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ObserversList::iterator it =
1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      std::find(observers_.begin(), observers_.end(), observer);
1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Observer must exist.
1145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(it != observers_.end());
1146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  observers_.erase(it);
1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) {
1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ipv6_probe_monitoring_ = false;
1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DiscardIPv6ProbeJob();
1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  default_address_family_ = address_family;
1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1157731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickAddressFamily HostResolverImpl::GetDefaultAddressFamily() const {
1158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return default_address_family_;
1159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
116121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenHostResolverImpl* HostResolverImpl::GetAsHostResolverImpl() {
116221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return this;
116321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
116421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::Shutdown() {
1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Cancel the outstanding jobs.
11693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CancelAllJobs();
1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DiscardIPv6ProbeJob();
11713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  shutdown_ = true;
1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::AddOutstandingJob(Job* job) {
1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<Job>& found_job = jobs_[job->key()];
1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!found_job);
1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_job = job;
1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  JobPool* pool = GetPoolForRequest(job->initial_request());
1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pool->AdjustNumOutstandingJobs(1);
1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHostResolverImpl::Job* HostResolverImpl::FindOutstandingJob(const Key& key) {
1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  JobMap::iterator it = jobs_.find(key);
1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != jobs_.end())
1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return it->second;
1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;
1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::RemoveOutstandingJob(Job* job) {
1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  JobMap::iterator it = jobs_.find(job->key());
1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(it != jobs_.end());
1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(it->second.get(), job);
1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  jobs_.erase(it);
1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  JobPool* pool = GetPoolForRequest(job->initial_request());
1198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pool->AdjustNumOutstandingJobs(-1);
1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::OnJobComplete(Job* job,
1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     int net_error,
1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     int os_error,
1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     const AddressList& addrlist) {
1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RemoveOutstandingJob(job);
1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write result to the cache.
1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cache_.get())
1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cache_->Set(job->key(), net_error, addrlist, base::TimeTicks::Now());
1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnJobCompleteInternal(job, net_error, os_error, addrlist);
12123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
12133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::AbortJob(Job* job) {
12153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnJobCompleteInternal(job, ERR_ABORTED, 0 /* no os_error */, AddressList());
12163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
12173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::OnJobCompleteInternal(
12193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Job* job,
12203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int net_error,
12213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int os_error,
12223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const AddressList& addrlist) {
1223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Make a note that we are executing within OnJobComplete() in case the
1224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // HostResolver is deleted by a callback invocation.
1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!cur_completing_job_);
1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cur_completing_job_ = job;
1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Try to start any queued requests now that a job-slot has freed up.
1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProcessQueuedRequests();
1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Complete all of the requests that were attached to the job.
1232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (RequestsList::const_iterator it = job->requests().begin();
1233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != job->requests().end(); ++it) {
1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Request* req = *it;
1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!req->was_cancelled()) {
1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK_EQ(job, req->job());
12373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      req->request_net_log().EndEvent(
12383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, NULL);
1239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Update the net log and notify registered observers.
12413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      OnFinishRequest(req->source_net_log(), req->request_net_log(), req->id(),
12423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      req->info(), net_error, os_error);
1243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      req->OnComplete(net_error, addrlist);
1245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Check if the job was cancelled as a result of running the callback.
1247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // (Meaning that |this| was deleted).
1248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (job->was_cancelled())
1249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
1250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cur_completing_job_ = NULL;
1254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::OnStartRequest(const BoundNetLog& source_net_log,
12573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      const BoundNetLog& request_net_log,
1258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      int request_id,
1259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      const RequestInfo& info) {
12603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  source_net_log.BeginEvent(
12613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NetLog::TYPE_HOST_RESOLVER_IMPL,
1262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      make_scoped_refptr(new NetLogSourceParameter(
1263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          "source_dependency", request_net_log.source())));
12643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_net_log.BeginEvent(
12663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST,
1267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      make_scoped_refptr(new RequestInfoParameters(
1268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          info, source_net_log.source())));
1269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Notify the observers of the start.
1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!observers_.empty()) {
1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (ObserversList::iterator it = observers_.begin();
1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         it != observers_.end(); ++it) {
1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      (*it)->OnStartResolution(request_id, info);
1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::OnFinishRequest(const BoundNetLog& source_net_log,
12803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       const BoundNetLog& request_net_log,
1281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       int request_id,
1282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       const RequestInfo& info,
1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       int net_error,
12843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       int os_error) {
1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_resolved = net_error == OK;
1286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Notify the observers of the completion.
1288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!observers_.empty()) {
1289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (ObserversList::iterator it = observers_.begin();
1290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         it != observers_.end(); ++it) {
1291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      (*it)->OnFinishResolutionWithStatus(request_id, was_resolved, info);
1292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Log some extra parameters on failure for synchronous requests.
1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<NetLog::EventParameters> params;
12973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!was_resolved) {
12983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    params = new HostResolveFailedParams(net_error, os_error);
12993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params);
13023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
1303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::OnCancelRequest(const BoundNetLog& source_net_log,
13063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       const BoundNetLog& request_net_log,
1307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       int request_id,
1308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       const RequestInfo& info) {
13093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL);
1310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Notify the observers of the cancellation.
1312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!observers_.empty()) {
1313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (ObserversList::iterator it = observers_.begin();
1314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         it != observers_.end(); ++it) {
1315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      (*it)->OnCancelResolution(request_id, info);
1316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL);
13203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
1321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HostResolverImpl::DiscardIPv6ProbeJob() {
1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ipv6_probe_job_.get()) {
1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ipv6_probe_job_->Cancel();
1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ipv6_probe_job_ = NULL;
1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HostResolverImpl::IPv6ProbeSetDefaultAddressFamily(
1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddressFamily address_family) {
1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED ||
1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         address_family == ADDRESS_FAMILY_IPV4);
1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (default_address_family_ != address_family) {
1335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    VLOG(1) << "IPv6Probe forced AddressFamily setting to "
1336731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ?
1337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4");
1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  default_address_family_ = address_family;
1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Drop reference since the job has called us back.
1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DiscardIPv6ProbeJob();
1342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HostResolverImpl::CanCreateJobForPool(const JobPool& pool) const {
1345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_LE(jobs_.size(), max_jobs_);
1346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We can't create another job if it would exceed the global total.
1348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (jobs_.size() + 1 > max_jobs_)
1349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check whether the pool's constraints are met.
1352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return pool.CanCreateJob();
1353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
135572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
135672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenHostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest(
135772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const Request* req) {
135872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return POOL_NORMAL;
135972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
136072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HostResolverImpl::ProcessQueuedRequests() {
1362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Find the highest priority request that can be scheduled.
1363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Request* top_req = NULL;
1364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(job_pools_); ++i) {
1365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    JobPool* pool = job_pools_[i];
1366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (pool->HasPendingRequests() && CanCreateJobForPool(*pool)) {
1367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      top_req = pool->RemoveTopPendingRequest();
1368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!top_req)
1373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<Job> job(CreateAndStartJob(top_req));
1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Search for any other pending request which can piggy-back off this job.
1378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t pool_i = 0; pool_i < POOL_COUNT; ++pool_i) {
1379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    JobPool* pool = job_pools_[pool_i];
1380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pool->MoveRequestsToJob(job);
1381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const RequestInfo& info) const {
13863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostResolverFlags effective_flags =
13873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      info.host_resolver_flags() | additional_resolver_flags_;
1388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddressFamily effective_address_family = info.address_family();
13893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED &&
13903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) {
1391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    effective_address_family = default_address_family_;
13923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (ipv6_probe_monitoring_)
13933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
13943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
13953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return Key(info.hostname(), effective_address_family, effective_flags);
1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHostResolverImpl::Job* HostResolverImpl::CreateAndStartJob(Request* req) {
1399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(CanCreateJobForPool(*GetPoolForRequest(req)));
1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Key key = GetEffectiveKeyForRequest(req->info());
14013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  req->request_net_log().AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB,
14033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  NULL);
14043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1405513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<Job> job(new Job(next_job_id_++, this, key,
1406513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   req->request_net_log(), net_log_));
1407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  job->AddRequest(req);
1408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddOutstandingJob(job);
1409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  job->Start();
14103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return job.get();
1412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HostResolverImpl::EnqueueRequest(JobPool* pool, Request* req) {
1415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<Request> req_evicted_from_queue(
1416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pool->InsertPendingRequest(req));
1417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the queue has become too large, we need to kick something out.
1419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (req_evicted_from_queue.get()) {
1420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Request* r = req_evicted_from_queue.get();
1421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int error = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
1422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    OnFinishRequest(r->source_net_log(), r->request_net_log(), r->id(),
14243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    r->info(), error,
14253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    0  /* os_error (not applicable) */);
1426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (r == req)
1428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return error;
1429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    r->OnComplete(error, AddressList());
1431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
1434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::CancelAllJobs() {
14373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  JobMap jobs;
14383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  jobs.swap(jobs_);
14393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (JobMap::iterator it = jobs.begin(); it != jobs.end(); ++it)
14403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    it->second->Cancel();
14413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
14423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HostResolverImpl::AbortAllInProgressJobs() {
14443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (size_t i = 0; i < arraysize(job_pools_); ++i)
14453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    job_pools_[i]->ResetNumOutstandingJobs();
14463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  JobMap jobs;
14473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  jobs.swap(jobs_);
14483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (JobMap::iterator it = jobs.begin(); it != jobs.end(); ++it) {
14493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    AbortJob(it->second);
14503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    it->second->Cancel();
14513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
14523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
14533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
145472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HostResolverImpl::OnIPAddressChanged() {
145572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (cache_.get())
145672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cache_->clear();
145772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ipv6_probe_monitoring_) {
145872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(!shutdown_);
145972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (shutdown_)
146072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return;
146172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DiscardIPv6ProbeJob();
146272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ipv6_probe_job_ = new IPv6ProbeJob(this);
146372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ipv6_probe_job_->Start();
146472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
146572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_LINUX)
146672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (HaveOnlyLoopbackAddresses()) {
146772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
146872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
146972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY;
147072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
147172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
147272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  AbortAllInProgressJobs();
147372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // |this| may be deleted inside AbortAllInProgressJobs().
147472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
147572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
1477