• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/dns/host_resolver_manager.h"
6 
7 #include <cmath>
8 #include <cstdint>
9 #include <iterator>
10 #include <limits>
11 #include <memory>
12 #include <numeric>
13 #include <set>
14 #include <string>
15 #include <tuple>
16 #include <unordered_set>
17 #include <utility>
18 #include <vector>
19 
20 #include "base/check_op.h"
21 #include "base/compiler_specific.h"
22 #include "base/containers/circular_deque.h"
23 #include "base/containers/contains.h"
24 #include "base/containers/cxx20_erase.h"
25 #include "base/containers/flat_set.h"
26 #include "base/containers/linked_list.h"
27 #include "base/debug/debugger.h"
28 #include "base/feature_list.h"
29 #include "base/functional/bind.h"
30 #include "base/functional/callback.h"
31 #include "base/functional/callback_helpers.h"
32 #include "base/functional/identity.h"
33 #include "base/logging.h"
34 #include "base/memory/ptr_util.h"
35 #include "base/memory/raw_ptr.h"
36 #include "base/memory/safe_ref.h"
37 #include "base/memory/weak_ptr.h"
38 #include "base/metrics/field_trial.h"
39 #include "base/metrics/field_trial_params.h"
40 #include "base/metrics/histogram_functions.h"
41 #include "base/metrics/histogram_macros.h"
42 #include "base/no_destructor.h"
43 #include "base/numerics/safe_conversions.h"
44 #include "base/observer_list.h"
45 #include "base/ranges/algorithm.h"
46 #include "base/sequence_checker.h"
47 #include "base/strings/strcat.h"
48 #include "base/strings/string_number_conversions.h"
49 #include "base/strings/string_piece.h"
50 #include "base/strings/string_split.h"
51 #include "base/strings/string_util.h"
52 #include "base/strings/stringprintf.h"
53 #include "base/strings/utf_string_conversions.h"
54 #include "base/task/sequenced_task_runner.h"
55 #include "base/task/single_thread_task_runner.h"
56 #include "base/task/thread_pool.h"
57 #include "base/threading/scoped_blocking_call.h"
58 #include "base/time/default_tick_clock.h"
59 #include "base/time/time.h"
60 #include "base/types/optional_util.h"
61 #include "base/values.h"
62 #include "build/build_config.h"
63 #include "net/base/address_family.h"
64 #include "net/base/address_list.h"
65 #include "net/base/completion_once_callback.h"
66 #include "net/base/features.h"
67 #include "net/base/host_port_pair.h"
68 #include "net/base/ip_address.h"
69 #include "net/base/ip_endpoint.h"
70 #include "net/base/net_errors.h"
71 #include "net/base/network_anonymization_key.h"
72 #include "net/base/network_interfaces.h"
73 #include "net/base/prioritized_dispatcher.h"
74 #include "net/base/request_priority.h"
75 #include "net/base/trace_constants.h"
76 #include "net/base/tracing.h"
77 #include "net/base/url_util.h"
78 #include "net/dns/address_sorter.h"
79 #include "net/dns/dns_alias_utility.h"
80 #include "net/dns/dns_client.h"
81 #include "net/dns/dns_names_util.h"
82 #include "net/dns/dns_response.h"
83 #include "net/dns/dns_response_result_extractor.h"
84 #include "net/dns/dns_transaction.h"
85 #include "net/dns/dns_util.h"
86 #include "net/dns/host_cache.h"
87 #include "net/dns/host_resolver_mdns_listener_impl.h"
88 #include "net/dns/host_resolver_mdns_task.h"
89 #include "net/dns/host_resolver_nat64_task.h"
90 #include "net/dns/host_resolver_proc.h"
91 #include "net/dns/host_resolver_system_task.h"
92 #include "net/dns/httpssvc_metrics.h"
93 #include "net/dns/mdns_client.h"
94 #include "net/dns/public/dns_protocol.h"
95 #include "net/dns/public/dns_query_type.h"
96 #include "net/dns/public/host_resolver_results.h"
97 #include "net/dns/public/resolve_error_info.h"
98 #include "net/dns/public/secure_dns_mode.h"
99 #include "net/dns/public/secure_dns_policy.h"
100 #include "net/dns/public/util.h"
101 #include "net/dns/record_parsed.h"
102 #include "net/dns/resolve_context.h"
103 #include "net/dns/test_dns_config_service.h"
104 #include "net/http/http_network_session.h"
105 #include "net/log/net_log.h"
106 #include "net/log/net_log_capture_mode.h"
107 #include "net/log/net_log_event_type.h"
108 #include "net/log/net_log_source.h"
109 #include "net/log/net_log_source_type.h"
110 #include "net/log/net_log_with_source.h"
111 #include "net/socket/client_socket_factory.h"
112 #include "net/url_request/url_request_context.h"
113 #include "third_party/abseil-cpp/absl/types/optional.h"
114 #include "third_party/abseil-cpp/absl/types/variant.h"
115 #include "url/scheme_host_port.h"
116 #include "url/url_constants.h"
117 
118 #if BUILDFLAG(ENABLE_MDNS)
119 #include "net/dns/mdns_client_impl.h"
120 #endif
121 
122 #if BUILDFLAG(IS_WIN)
123 #include <Winsock2.h>
124 #include "net/base/winsock_init.h"
125 #endif
126 
127 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
128 #include <net/if.h>
129 #include "net/base/sys_addrinfo.h"
130 #if BUILDFLAG(IS_ANDROID)
131 #include "base/android/build_info.h"
132 #include "net/android/network_library.h"
133 #else  // !BUILDFLAG(IS_ANDROID)
134 #include <ifaddrs.h>
135 #endif  // BUILDFLAG(IS_ANDROID)
136 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
137 
138 namespace net {
139 
140 namespace {
141 
142 // Limit the size of hostnames that will be resolved to combat issues in
143 // some platform's resolvers.
144 const size_t kMaxHostLength = 4096;
145 
146 // Default TTL for successful resolutions with HostResolverSystemTask.
147 const unsigned kCacheEntryTTLSeconds = 60;
148 
149 // Default TTL for unsuccessful resolutions with HostResolverSystemTask.
150 const unsigned kNegativeCacheEntryTTLSeconds = 0;
151 
152 // Minimum TTL for successful resolutions with DnsTask.
153 const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds;
154 
155 // Time between IPv6 probes, i.e. for how long results of each IPv6 probe are
156 // cached.
157 const int kIPv6ProbePeriodMs = 1000;
158 
159 // Google DNS address used for IPv6 probes.
160 const uint8_t kIPv6ProbeAddress[] = {0x20, 0x01, 0x48, 0x60, 0x48, 0x60,
161                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162                                      0x00, 0x00, 0x88, 0x88};
163 
164 // ICANN uses this localhost address to indicate a name collision.
165 //
166 // The policy in Chromium is to fail host resolving if it resolves to
167 // this special address.
168 //
169 // Not however that IP literals are exempt from this policy, so it is still
170 // possible to navigate to http://127.0.53.53/ directly.
171 //
172 // For more details: https://www.icann.org/news/announcement-2-2014-08-01-en
173 const uint8_t kIcanNameCollisionIp[] = {127, 0, 53, 53};
174 
ContainsIcannNameCollisionIp(const std::vector<IPEndPoint> & endpoints)175 bool ContainsIcannNameCollisionIp(const std::vector<IPEndPoint>& endpoints) {
176   for (const auto& endpoint : endpoints) {
177     const IPAddress& addr = endpoint.address();
178     if (addr.IsIPv4() && IPAddressStartsWith(addr, kIcanNameCollisionIp)) {
179       return true;
180     }
181   }
182   return false;
183 }
184 
185 // True if |hostname| ends with either ".local" or ".local.".
ResemblesMulticastDNSName(base::StringPiece hostname)186 bool ResemblesMulticastDNSName(base::StringPiece hostname) {
187   return base::EndsWith(hostname, ".local") ||
188          base::EndsWith(hostname, ".local.");
189 }
190 
ConfigureAsyncDnsNoFallbackFieldTrial()191 bool ConfigureAsyncDnsNoFallbackFieldTrial() {
192   const bool kDefault = false;
193 
194   // Configure the AsyncDns field trial as follows:
195   // groups AsyncDnsNoFallbackA and AsyncDnsNoFallbackB: return true,
196   // groups AsyncDnsA and AsyncDnsB: return false,
197   // groups SystemDnsA and SystemDnsB: return false,
198   // otherwise (trial absent): return default.
199   std::string group_name = base::FieldTrialList::FindFullName("AsyncDns");
200   if (!group_name.empty()) {
201     return base::StartsWith(group_name, "AsyncDnsNoFallback",
202                             base::CompareCase::INSENSITIVE_ASCII);
203   }
204   return kDefault;
205 }
206 
207 // Returns true if NAT64 can be used in place of an IPv4 address during host
208 // resolution.
MayUseNAT64ForIPv4Literal(HostResolverFlags flags,HostResolverSource source,const IPAddress & ip_address)209 bool MayUseNAT64ForIPv4Literal(HostResolverFlags flags,
210                                HostResolverSource source,
211                                const IPAddress& ip_address) {
212   return !(flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) &&
213          ip_address.IsValid() && ip_address.IsIPv4() &&
214          base::FeatureList::IsEnabled(features::kUseNAT64ForIPv4Literal) &&
215          (source != HostResolverSource::LOCAL_ONLY);
216 }
217 
218 //-----------------------------------------------------------------------------
219 
220 // Returns true if it can determine that only loopback addresses are configured.
221 // i.e. if only 127.0.0.1 and ::1 are routable.
222 // Also returns false if it cannot determine this.
HaveOnlyLoopbackAddresses()223 bool HaveOnlyLoopbackAddresses() {
224   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
225                                                 base::BlockingType::WILL_BLOCK);
226 #if BUILDFLAG(IS_WIN)
227   // TODO(wtc): implement with the GetAdaptersAddresses function.
228   NOTIMPLEMENTED();
229   return false;
230 #elif BUILDFLAG(IS_ANDROID)
231   return android::HaveOnlyLoopbackAddresses();
232 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
233   struct ifaddrs* interface_addr = nullptr;
234   int rv = getifaddrs(&interface_addr);
235   if (rv != 0) {
236     DVPLOG(1) << "getifaddrs() failed";
237     return false;
238   }
239 
240   bool result = true;
241   for (struct ifaddrs* interface = interface_addr; interface != nullptr;
242        interface = interface->ifa_next) {
243     if (!(IFF_UP & interface->ifa_flags))
244       continue;
245     if (IFF_LOOPBACK & interface->ifa_flags)
246       continue;
247     const struct sockaddr* addr = interface->ifa_addr;
248     if (!addr)
249       continue;
250     if (addr->sa_family == AF_INET6) {
251       // Safe cast since this is AF_INET6.
252       const struct sockaddr_in6* addr_in6 =
253           reinterpret_cast<const struct sockaddr_in6*>(addr);
254       const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
255       if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr))
256         continue;
257     }
258     if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET)
259       continue;
260 
261     result = false;
262     break;
263   }
264   freeifaddrs(interface_addr);
265   return result;
266 #endif  // defined(various platforms)
267 }
268 
269 // Creates NetLog parameters when the DnsTask failed.
NetLogDnsTaskFailedParams(int net_error,absl::optional<DnsQueryType> failed_transaction_type,absl::optional<base::TimeDelta> ttl,const HostCache::Entry * saved_results)270 base::Value::Dict NetLogDnsTaskFailedParams(
271     int net_error,
272     absl::optional<DnsQueryType> failed_transaction_type,
273     absl::optional<base::TimeDelta> ttl,
274     const HostCache::Entry* saved_results) {
275   base::Value::Dict dict;
276   if (failed_transaction_type) {
277     dict.Set("dns_query_type", kDnsQueryTypes.at(*failed_transaction_type));
278   }
279   if (ttl)
280     dict.Set("error_ttl_sec",
281              base::saturated_cast<int>(ttl.value().InSeconds()));
282   dict.Set("net_error", net_error);
283   if (saved_results)
284     dict.Set("saved_results", saved_results->NetLogParams());
285   return dict;
286 }
287 
NetLogDnsTaskExtractionFailureParams(DnsResponseResultExtractor::ExtractionError extraction_error,DnsQueryType dns_query_type,const HostCache::Entry & results)288 base::Value::Dict NetLogDnsTaskExtractionFailureParams(
289     DnsResponseResultExtractor::ExtractionError extraction_error,
290     DnsQueryType dns_query_type,
291     const HostCache::Entry& results) {
292   base::Value::Dict dict;
293   dict.Set("extraction_error", base::strict_cast<int>(extraction_error));
294   dict.Set("dns_query_type", kDnsQueryTypes.at(dns_query_type));
295   dict.Set("results", results.NetLogParams());
296   return dict;
297 }
298 
299 // Creates NetLog parameters for HOST_RESOLVER_MANAGER_JOB_ATTACH/DETACH events.
NetLogJobAttachParams(const NetLogSource & source,RequestPriority priority)300 base::Value::Dict NetLogJobAttachParams(const NetLogSource& source,
301                                         RequestPriority priority) {
302   base::Value::Dict dict;
303   source.AddToEventParameters(dict);
304   dict.Set("priority", RequestPriorityToString(priority));
305   return dict;
306 }
307 
NetLogIPv6AvailableParams(bool ipv6_available,bool cached)308 base::Value::Dict NetLogIPv6AvailableParams(bool ipv6_available, bool cached) {
309   base::Value::Dict dict;
310   dict.Set("ipv6_available", ipv6_available);
311   dict.Set("cached", cached);
312   return dict;
313 }
314 
315 // The logging routines are defined here because some requests are resolved
316 // without a Request object.
317 
318 //-----------------------------------------------------------------------------
319 
320 // Maximum of 64 concurrent resolver calls (excluding retries).
321 // Between 2010 and 2020, the limit was set to 6 because of a report of a broken
322 // home router that would fail in the presence of more simultaneous queries.
323 // In 2020, we conducted an experiment to see if this kind of router was still
324 // present on the Internet, and found no evidence of any remaining issues, so
325 // we increased the limit to 64 at that time.
326 const size_t kDefaultMaxSystemTasks = 64u;
327 
GetDispatcherLimits(const HostResolver::ManagerOptions & options)328 PrioritizedDispatcher::Limits GetDispatcherLimits(
329     const HostResolver::ManagerOptions& options) {
330   PrioritizedDispatcher::Limits limits(NUM_PRIORITIES,
331                                        options.max_concurrent_resolves);
332 
333   // If not using default, do not use the field trial.
334   if (limits.total_jobs != HostResolver::ManagerOptions::kDefaultParallelism)
335     return limits;
336 
337   // Default, without trial is no reserved slots.
338   limits.total_jobs = kDefaultMaxSystemTasks;
339 
340   // Parallelism is determined by the field trial.
341   std::string group =
342       base::FieldTrialList::FindFullName("HostResolverDispatch");
343 
344   if (group.empty())
345     return limits;
346 
347   // The format of the group name is a list of non-negative integers separated
348   // by ':'. Each of the elements in the list corresponds to an element in
349   // |reserved_slots|, except the last one which is the |total_jobs|.
350   std::vector<base::StringPiece> group_parts = base::SplitStringPiece(
351       group, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
352   if (group_parts.size() != NUM_PRIORITIES + 1) {
353     NOTREACHED();
354     return limits;
355   }
356 
357   std::vector<size_t> parsed(group_parts.size());
358   for (size_t i = 0; i < group_parts.size(); ++i) {
359     if (!base::StringToSizeT(group_parts[i], &parsed[i])) {
360       NOTREACHED();
361       return limits;
362     }
363   }
364 
365   const size_t total_jobs = parsed.back();
366   parsed.pop_back();
367 
368   const size_t total_reserved_slots =
369       std::accumulate(parsed.begin(), parsed.end(), 0u);
370 
371   // There must be some unreserved slots available for the all priorities.
372   if (total_reserved_slots > total_jobs ||
373       (total_reserved_slots == total_jobs && parsed[MINIMUM_PRIORITY] == 0)) {
374     NOTREACHED();
375     return limits;
376   }
377 
378   limits.total_jobs = total_jobs;
379   limits.reserved_slots = parsed;
380   return limits;
381 }
382 
383 // Keeps track of the highest priority.
384 class PriorityTracker {
385  public:
PriorityTracker(RequestPriority initial_priority)386   explicit PriorityTracker(RequestPriority initial_priority)
387       : highest_priority_(initial_priority) {}
388 
highest_priority() const389   RequestPriority highest_priority() const { return highest_priority_; }
390 
total_count() const391   size_t total_count() const { return total_count_; }
392 
Add(RequestPriority req_priority)393   void Add(RequestPriority req_priority) {
394     ++total_count_;
395     ++counts_[req_priority];
396     if (highest_priority_ < req_priority)
397       highest_priority_ = req_priority;
398   }
399 
Remove(RequestPriority req_priority)400   void Remove(RequestPriority req_priority) {
401     DCHECK_GT(total_count_, 0u);
402     DCHECK_GT(counts_[req_priority], 0u);
403     --total_count_;
404     --counts_[req_priority];
405     size_t i;
406     for (i = highest_priority_; i > MINIMUM_PRIORITY && !counts_[i]; --i) {
407     }
408     highest_priority_ = static_cast<RequestPriority>(i);
409 
410     // In absence of requests, default to MINIMUM_PRIORITY.
411     if (total_count_ == 0)
412       DCHECK_EQ(MINIMUM_PRIORITY, highest_priority_);
413   }
414 
415  private:
416   RequestPriority highest_priority_;
417   size_t total_count_ = 0;
418   size_t counts_[NUM_PRIORITIES] = {};
419 };
420 
NetLogResults(const HostCache::Entry & results)421 base::Value::Dict NetLogResults(const HostCache::Entry& results) {
422   base::Value::Dict dict;
423   dict.Set("results", results.NetLogParams());
424   return dict;
425 }
426 
ToLogStringValue(const absl::variant<url::SchemeHostPort,std::string> & host)427 base::Value ToLogStringValue(
428     const absl::variant<url::SchemeHostPort, std::string>& host) {
429   if (absl::holds_alternative<url::SchemeHostPort>(host)) {
430     return base::Value(absl::get<url::SchemeHostPort>(host).Serialize());
431   }
432 
433   return base::Value(absl::get<std::string>(host));
434 }
435 
436 // Returns empty string if `host` has no known scheme.
GetScheme(const absl::variant<url::SchemeHostPort,std::string> & host)437 base::StringPiece GetScheme(
438     const absl::variant<url::SchemeHostPort, std::string>& host) {
439   if (absl::holds_alternative<url::SchemeHostPort>(host))
440     return absl::get<url::SchemeHostPort>(host).scheme();
441 
442   return base::StringPiece();
443 }
444 
GetHostname(const absl::variant<url::SchemeHostPort,std::string> & host)445 base::StringPiece GetHostname(
446     const absl::variant<url::SchemeHostPort, std::string>& host) {
447   if (absl::holds_alternative<url::SchemeHostPort>(host)) {
448     base::StringPiece hostname = absl::get<url::SchemeHostPort>(host).host();
449     if (hostname.size() >= 2 && hostname.front() == '[' &&
450         hostname.back() == ']') {
451       hostname = hostname.substr(1, hostname.size() - 2);
452     }
453     return hostname;
454   }
455 
456   return absl::get<std::string>(host);
457 }
458 
459 // Only use scheme/port in JobKey if `https_svcb_options_enabled` is true
460 // (or the query is explicitly for HTTPS). Otherwise DNS will not give different
461 // results for the same hostname.
CreateHostForJobKey(const HostResolver::Host & input,DnsQueryType query_type,bool https_svcb_options_enabled)462 absl::variant<url::SchemeHostPort, std::string> CreateHostForJobKey(
463     const HostResolver::Host& input,
464     DnsQueryType query_type,
465     bool https_svcb_options_enabled) {
466   if ((https_svcb_options_enabled || query_type == DnsQueryType::HTTPS) &&
467       input.HasScheme()) {
468     return input.AsSchemeHostPort();
469   }
470 
471   return std::string(input.GetHostnameWithoutBrackets());
472 }
473 
CreateFakeEmptyResponse(base::StringPiece hostname,DnsQueryType query_type)474 DnsResponse CreateFakeEmptyResponse(base::StringPiece hostname,
475                                     DnsQueryType query_type) {
476   absl::optional<std::vector<uint8_t>> qname =
477       dns_names_util::DottedNameToNetwork(
478           hostname, /*require_valid_internet_hostname=*/true);
479   CHECK(qname.has_value());
480   return DnsResponse::CreateEmptyNoDataResponse(
481       /*id=*/0u, /*is_authoritative=*/true, qname.value(),
482       DnsQueryTypeToQtype(query_type));
483 }
484 
FilterAddresses(std::vector<IPEndPoint> addresses,DnsQueryTypeSet query_types)485 std::vector<IPEndPoint> FilterAddresses(std::vector<IPEndPoint> addresses,
486                                         DnsQueryTypeSet query_types) {
487   DCHECK(!query_types.Has(DnsQueryType::UNSPECIFIED));
488   DCHECK(!query_types.Empty());
489 
490   const AddressFamily want_family =
491       HostResolver::DnsQueryTypeSetToAddressFamily(query_types);
492 
493   if (want_family == ADDRESS_FAMILY_UNSPECIFIED)
494     return addresses;
495 
496   // Keep only the endpoints that match `want_family`.
497   addresses.erase(
498       base::ranges::remove_if(
499           addresses,
500           [want_family](AddressFamily family) { return family != want_family; },
501           &IPEndPoint::GetFamily),
502       addresses.end());
503   return addresses;
504 }
505 
RecordResolveTimeDiffForBucket(const char * histogram_variant,const char * histogram_bucket,base::TimeDelta diff)506 void RecordResolveTimeDiffForBucket(const char* histogram_variant,
507                                     const char* histogram_bucket,
508                                     base::TimeDelta diff) {
509   base::UmaHistogramTimes(
510       base::StrCat({"Net.Dns.ResolveTimeDiff.", histogram_variant,
511                     ".FirstRecord", histogram_bucket}),
512       diff);
513 }
514 
RecordResolveTimeDiff(const char * histogram_variant,base::TimeTicks start_time,base::TimeTicks first_record_end_time,base::TimeTicks second_record_end_time)515 void RecordResolveTimeDiff(const char* histogram_variant,
516                            base::TimeTicks start_time,
517                            base::TimeTicks first_record_end_time,
518                            base::TimeTicks second_record_end_time) {
519   CHECK_LE(start_time, first_record_end_time);
520   CHECK_LE(first_record_end_time, second_record_end_time);
521   base::TimeDelta first_elapsed = first_record_end_time - start_time;
522   base::TimeDelta diff = second_record_end_time - first_record_end_time;
523 
524   if (first_elapsed < base::Milliseconds(10)) {
525     RecordResolveTimeDiffForBucket(histogram_variant, "FasterThan10ms", diff);
526   } else if (first_elapsed < base::Milliseconds(25)) {
527     RecordResolveTimeDiffForBucket(histogram_variant, "10msTo25ms", diff);
528   } else if (first_elapsed < base::Milliseconds(50)) {
529     RecordResolveTimeDiffForBucket(histogram_variant, "25msTo50ms", diff);
530   } else if (first_elapsed < base::Milliseconds(100)) {
531     RecordResolveTimeDiffForBucket(histogram_variant, "50msTo100ms", diff);
532   } else if (first_elapsed < base::Milliseconds(250)) {
533     RecordResolveTimeDiffForBucket(histogram_variant, "100msTo250ms", diff);
534   } else if (first_elapsed < base::Milliseconds(500)) {
535     RecordResolveTimeDiffForBucket(histogram_variant, "250msTo500ms", diff);
536   } else if (first_elapsed < base::Seconds(1)) {
537     RecordResolveTimeDiffForBucket(histogram_variant, "500msTo1s", diff);
538   } else {
539     RecordResolveTimeDiffForBucket(histogram_variant, "SlowerThan1s", diff);
540   }
541 }
542 
543 }  // namespace
544 
545 //-----------------------------------------------------------------------------
546 
ResolveLocalHostname(base::StringPiece host,std::vector<IPEndPoint> * address_list)547 bool ResolveLocalHostname(base::StringPiece host,
548                           std::vector<IPEndPoint>* address_list) {
549   address_list->clear();
550   if (!IsLocalHostname(host))
551     return false;
552 
553   address_list->emplace_back(IPAddress::IPv6Localhost(), 0);
554   address_list->emplace_back(IPAddress::IPv4Localhost(), 0);
555 
556   return true;
557 }
558 
559 struct HostResolverManager::JobKey {
JobKeynet::HostResolverManager::JobKey560   explicit JobKey(ResolveContext* resolve_context)
561       : resolve_context(resolve_context->AsSafeRef()) {}
562 
operator <net::HostResolverManager::JobKey563   bool operator<(const JobKey& other) const {
564     return std::forward_as_tuple(query_types.ToEnumBitmask(), flags, source,
565                                  secure_dns_mode, &*resolve_context, host,
566                                  network_anonymization_key) <
567            std::forward_as_tuple(other.query_types.ToEnumBitmask(), other.flags,
568                                  other.source, other.secure_dns_mode,
569                                  &*other.resolve_context, other.host,
570                                  other.network_anonymization_key);
571   }
572 
operator ==net::HostResolverManager::JobKey573   bool operator==(const JobKey& other) const {
574     return !(*this < other || other < *this);
575   }
576 
577   absl::variant<url::SchemeHostPort, std::string> host;
578   NetworkAnonymizationKey network_anonymization_key;
579   DnsQueryTypeSet query_types;
580   HostResolverFlags flags;
581   HostResolverSource source;
582   SecureDnsMode secure_dns_mode;
583   base::SafeRef<ResolveContext> resolve_context;
584 
ToCacheKeynet::HostResolverManager::JobKey585   HostCache::Key ToCacheKey(bool secure) const {
586     if (query_types.Size() != 1) {
587       // This function will produce identical cache keys for `JobKey` structs
588       // that differ only in their (non-singleton) `query_types` fields. When we
589       // enable new query types, this behavior could lead to subtle bugs. That
590       // is why the following DCHECK restricts the allowable query types.
591       DCHECK(Difference(query_types,
592                         DnsQueryTypeSet(DnsQueryType::A, DnsQueryType::AAAA,
593                                         DnsQueryType::HTTPS))
594                  .Empty());
595     }
596     const DnsQueryType query_type_for_key = query_types.Size() == 1
597                                                 ? *query_types.begin()
598                                                 : DnsQueryType::UNSPECIFIED;
599     HostCache::Key key(host, query_type_for_key, flags, source,
600                        network_anonymization_key);
601     key.secure = secure;
602     return key;
603   }
604 
GetTargetNetworknet::HostResolverManager::JobKey605   handles::NetworkHandle GetTargetNetwork() const {
606     return resolve_context->GetTargetNetwork();
607   }
608 };
609 
610 // Holds the callback and request parameters for an outstanding request.
611 //
612 // The RequestImpl is owned by the end user of host resolution. Deletion prior
613 // to the request having completed means the request was cancelled by the
614 // caller.
615 //
616 // Both the RequestImpl and its associated Job hold non-owning pointers to each
617 // other. Care must be taken to clear the corresponding pointer when
618 // cancellation is initiated by the Job (OnJobCancelled) vs by the end user
619 // (~RequestImpl).
620 class HostResolverManager::RequestImpl
621     : public HostResolver::ResolveHostRequest,
622       public base::LinkNode<HostResolverManager::RequestImpl> {
623  public:
RequestImpl(NetLogWithSource source_net_log,HostResolver::Host request_host,NetworkAnonymizationKey network_anonymization_key,absl::optional<ResolveHostParameters> optional_parameters,base::WeakPtr<ResolveContext> resolve_context,HostCache * host_cache,base::WeakPtr<HostResolverManager> resolver,const base::TickClock * tick_clock)624   RequestImpl(NetLogWithSource source_net_log,
625               HostResolver::Host request_host,
626               NetworkAnonymizationKey network_anonymization_key,
627               absl::optional<ResolveHostParameters> optional_parameters,
628               base::WeakPtr<ResolveContext> resolve_context,
629               HostCache* host_cache,
630               base::WeakPtr<HostResolverManager> resolver,
631               const base::TickClock* tick_clock)
632       : source_net_log_(std::move(source_net_log)),
633         request_host_(std::move(request_host)),
634         network_anonymization_key_(
635             NetworkAnonymizationKey::IsPartitioningEnabled()
636                 ? std::move(network_anonymization_key)
637                 : NetworkAnonymizationKey()),
638         parameters_(optional_parameters ? std::move(optional_parameters).value()
639                                         : ResolveHostParameters()),
640         resolve_context_(std::move(resolve_context)),
641         host_cache_(host_cache),
642         host_resolver_flags_(
643             HostResolver::ParametersToHostResolverFlags(parameters_)),
644         priority_(parameters_.initial_priority),
645         job_key_(JobKey(resolve_context_.get())),
646         resolver_(std::move(resolver)),
647         tick_clock_(tick_clock) {}
648 
649   RequestImpl(const RequestImpl&) = delete;
650   RequestImpl& operator=(const RequestImpl&) = delete;
651 
652   ~RequestImpl() override;
653 
Start(CompletionOnceCallback callback)654   int Start(CompletionOnceCallback callback) override {
655     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
656     DCHECK(callback);
657     // Start() may only be called once per request.
658     CHECK(!job_.has_value());
659     DCHECK(!complete_);
660     DCHECK(!callback_);
661     // Parent HostResolver must still be alive to call Start().
662     DCHECK(resolver_);
663 
664     if (!resolve_context_) {
665       complete_ = true;
666       resolver_.reset();
667       set_error_info(ERR_CONTEXT_SHUT_DOWN, false);
668       return ERR_NAME_NOT_RESOLVED;
669     }
670 
671     LogStartRequest();
672 
673     next_state_ = STATE_IPV6_REACHABILITY;
674     callback_ = std::move(callback);
675 
676     int rv = OK;
677     rv = DoLoop(rv);
678     return rv;
679   }
680 
DoLoop(int rv)681   int DoLoop(int rv) {
682     do {
683       ResolveState state = next_state_;
684       next_state_ = STATE_NONE;
685       switch (state) {
686         case STATE_IPV6_REACHABILITY:
687           rv = DoIPv6Reachability();
688           break;
689         case STATE_GET_PARAMETERS:
690           DCHECK_EQ(OK, rv);
691           rv = DoGetParameters();
692           break;
693         case STATE_GET_PARAMETERS_COMPLETE:
694           rv = DoGetParametersComplete(rv);
695           break;
696         case STATE_RESOLVE_LOCALLY:
697           rv = DoResolveLocally();
698           break;
699         case STATE_START_JOB:
700           rv = DoStartJob();
701           break;
702         case STATE_FINISH_REQUEST:
703           rv = DoFinishRequest(rv);
704           break;
705         default:
706           NOTREACHED() << "next_state_: " << next_state_;
707           break;
708       }
709     } while (next_state_ != STATE_NONE && rv != ERR_IO_PENDING);
710 
711     return rv;
712   }
713 
OnIOComplete(int rv)714   void OnIOComplete(int rv) {
715     rv = DoLoop(rv);
716     if (rv != ERR_IO_PENDING && !callback_.is_null()) {
717       std::move(callback_).Run(rv);
718     }
719   }
720 
DoIPv6Reachability()721   int DoIPv6Reachability() {
722     next_state_ = STATE_GET_PARAMETERS;
723     // If a single reachability probe has not been completed, and the latest
724     // probe will return asynchronously, return ERR_NAME_NOT_RESOLVED when the
725     // request source is LOCAL_ONLY. This is due to LOCAL_ONLY requiring a
726     // synchronous response, so it cannot wait on an async probe result and
727     // cannot make assumptions about reachability.
728     if (parameters_.source == HostResolverSource::LOCAL_ONLY) {
729       int rv = resolver_->StartIPv6ReachabilityCheck(
730           source_net_log_, base::DoNothingAs<void(int)>());
731       if (rv == ERR_IO_PENDING) {
732         next_state_ = STATE_FINISH_REQUEST;
733         return ERR_NAME_NOT_RESOLVED;
734       }
735       return OK;
736     }
737     return resolver_->StartIPv6ReachabilityCheck(
738         source_net_log_, base::BindOnce(&RequestImpl::OnIOComplete,
739                                         weak_ptr_factory_.GetWeakPtr()));
740   }
741 
DoGetParameters()742   int DoGetParameters() {
743     job_key_.host =
744         CreateHostForJobKey(request_host_, parameters_.dns_query_type,
745                             resolver_->https_svcb_options_.enable);
746     job_key_.network_anonymization_key = network_anonymization_key_;
747     job_key_.source = parameters_.source;
748 
749     bool is_ip = ip_address_.AssignFromIPLiteral(GetHostname(job_key_.host));
750 
751     resolver_->GetEffectiveParametersForRequest(
752         job_key_.host, parameters_.dns_query_type, host_resolver_flags_,
753         parameters_.secure_dns_policy, is_ip, source_net_log_,
754         &job_key_.query_types, &job_key_.flags, &job_key_.secure_dns_mode);
755 
756     // A reachability probe to determine if the network is only reachable on
757     // IPv6 will be scheduled if the parameters are met for using NAT64 in place
758     // of an IPv4 address.
759     if (MayUseNAT64ForIPv4Literal(job_key_.flags, parameters_.source,
760                                   ip_address_) &&
761         resolver_->last_ipv6_probe_result_) {
762       next_state_ = STATE_GET_PARAMETERS_COMPLETE;
763       return resolver_->StartGloballyReachableCheck(
764           ip_address_, source_net_log_,
765           base::BindOnce(&RequestImpl::OnIOComplete,
766                          weak_ptr_factory_.GetWeakPtr()));
767     }
768     next_state_ = STATE_RESOLVE_LOCALLY;
769     return OK;
770   }
771 
DoGetParametersComplete(int rv)772   int DoGetParametersComplete(int rv) {
773     next_state_ = STATE_RESOLVE_LOCALLY;
774     only_ipv6_reachable_ = (rv == ERR_FAILED) ? true : false;
775     return OK;
776   }
777 
DoResolveLocally()778   int DoResolveLocally() {
779     absl::optional<HostCache::EntryStaleness> stale_info;
780     HostCache::Entry results = resolver_->ResolveLocally(
781         only_ipv6_reachable_, job_key_, ip_address_, parameters_.cache_usage,
782         parameters_.secure_dns_policy, parameters_.source, source_net_log_,
783         host_cache_, &tasks_, &stale_info);
784     if (results.error() != ERR_DNS_CACHE_MISS ||
785         parameters_.source == HostResolverSource::LOCAL_ONLY ||
786         tasks_.empty()) {
787       if (results.error() == OK && !parameters_.is_speculative) {
788         set_results(results.CopyWithDefaultPort(request_host_.GetPort()));
789       }
790       if (stale_info && !parameters_.is_speculative) {
791         set_stale_info(std::move(stale_info).value());
792       }
793       next_state_ = STATE_FINISH_REQUEST;
794       return results.error();
795     }
796     next_state_ = STATE_START_JOB;
797     return OK;
798   }
799 
DoStartJob()800   int DoStartJob() {
801     resolver_->CreateAndStartJob(std::move(job_key_), std::move(tasks_), this);
802     DCHECK(!complete_);
803     resolver_.reset();
804     return ERR_IO_PENDING;
805   }
806 
DoFinishRequest(int rv)807   int DoFinishRequest(int rv) {
808     CHECK(!job_.has_value());
809     complete_ = true;
810     set_error_info(rv, /*is_secure_network_error=*/false);
811     rv = HostResolver::SquashErrorCode(rv);
812     LogFinishRequest(rv, /*async_completion=*/false);
813     return rv;
814   }
815 
GetAddressResults() const816   const AddressList* GetAddressResults() const override {
817     DCHECK(complete_);
818     return base::OptionalToPtr(legacy_address_results_);
819   }
820 
GetEndpointResults() const821   const std::vector<HostResolverEndpointResult>* GetEndpointResults()
822       const override {
823     DCHECK(complete_);
824     return base::OptionalToPtr(endpoint_results_);
825   }
826 
GetTextResults() const827   const absl::optional<std::vector<std::string>>& GetTextResults()
828       const override {
829     DCHECK(complete_);
830     static const base::NoDestructor<absl::optional<std::vector<std::string>>>
831         nullopt_result;
832     return results_ ? results_.value().text_records() : *nullopt_result;
833   }
834 
GetHostnameResults() const835   const absl::optional<std::vector<HostPortPair>>& GetHostnameResults()
836       const override {
837     DCHECK(complete_);
838     static const base::NoDestructor<absl::optional<std::vector<HostPortPair>>>
839         nullopt_result;
840     return results_ ? results_.value().hostnames() : *nullopt_result;
841   }
842 
GetDnsAliasResults() const843   const std::set<std::string>* GetDnsAliasResults() const override {
844     DCHECK(complete_);
845 
846     // If `include_canonical_name` param was true, should only ever have at most
847     // a single alias, representing the expected "canonical name".
848 #if DCHECK_IS_ON()
849     if (parameters().include_canonical_name && fixed_up_dns_alias_results_) {
850       DCHECK_LE(fixed_up_dns_alias_results_->size(), 1u);
851       if (GetAddressResults()) {
852         std::set<std::string> address_list_aliases_set(
853             GetAddressResults()->dns_aliases().begin(),
854             GetAddressResults()->dns_aliases().end());
855         DCHECK(address_list_aliases_set == fixed_up_dns_alias_results_.value());
856       }
857     }
858 #endif  // DCHECK_IS_ON()
859 
860     return base::OptionalToPtr(fixed_up_dns_alias_results_);
861   }
862 
GetExperimentalResultsForTesting() const863   const std::vector<bool>* GetExperimentalResultsForTesting() const override {
864     DCHECK(complete_);
865     return results_ ? results_.value().https_record_compatibility() : nullptr;
866   }
867 
GetResolveErrorInfo() const868   net::ResolveErrorInfo GetResolveErrorInfo() const override {
869     DCHECK(complete_);
870     return error_info_;
871   }
872 
GetStaleInfo() const873   const absl::optional<HostCache::EntryStaleness>& GetStaleInfo()
874       const override {
875     DCHECK(complete_);
876     return stale_info_;
877   }
878 
879   void ChangeRequestPriority(RequestPriority priority) override;
880 
set_results(HostCache::Entry results)881   void set_results(HostCache::Entry results) {
882     // Should only be called at most once and before request is marked
883     // completed.
884     DCHECK(!complete_);
885     DCHECK(!results_);
886     DCHECK(!parameters_.is_speculative);
887 
888     results_ = std::move(results);
889     FixUpEndpointAndAliasResults();
890   }
891 
set_error_info(int error,bool is_secure_network_error)892   void set_error_info(int error, bool is_secure_network_error) {
893     error_info_ = ResolveErrorInfo(error, is_secure_network_error);
894   }
895 
set_stale_info(HostCache::EntryStaleness stale_info)896   void set_stale_info(HostCache::EntryStaleness stale_info) {
897     // Should only be called at most once and before request is marked
898     // completed.
899     DCHECK(!complete_);
900     DCHECK(!stale_info_);
901     DCHECK(!parameters_.is_speculative);
902 
903     stale_info_ = std::move(stale_info);
904   }
905 
AssignJob(base::SafeRef<Job> job)906   void AssignJob(base::SafeRef<Job> job) {
907     CHECK(!job_.has_value());
908     job_ = std::move(job);
909   }
910 
HasJob() const911   bool HasJob() const { return job_.has_value(); }
912 
913   // Gets the Job's key. Crashes if no Job has been assigned.
914   const JobKey& GetJobKey() const;
915 
916   // Unassigns the Job without calling completion callback.
917   void OnJobCancelled(const JobKey& key);
918 
919   // Cleans up Job assignment, marks request completed, and calls the completion
920   // callback. |is_secure_network_error| indicates whether |error| came from a
921   // secure DNS lookup.
922   void OnJobCompleted(const JobKey& job_key,
923                       int error,
924                       bool is_secure_network_error);
925 
926   // NetLog for the source, passed in HostResolver::Resolve.
source_net_log()927   const NetLogWithSource& source_net_log() { return source_net_log_; }
928 
request_host() const929   const HostResolver::Host& request_host() const { return request_host_; }
930 
network_anonymization_key() const931   const NetworkAnonymizationKey& network_anonymization_key() const {
932     return network_anonymization_key_;
933   }
934 
parameters() const935   const ResolveHostParameters& parameters() const { return parameters_; }
936 
resolve_context() const937   ResolveContext* resolve_context() const { return resolve_context_.get(); }
938 
host_cache() const939   HostCache* host_cache() const { return host_cache_; }
940 
host_resolver_flags() const941   HostResolverFlags host_resolver_flags() const { return host_resolver_flags_; }
942 
priority() const943   RequestPriority priority() const { return priority_; }
set_priority(RequestPriority priority)944   void set_priority(RequestPriority priority) { priority_ = priority; }
945 
complete() const946   bool complete() const { return complete_; }
947 
948  private:
949   enum ResolveState {
950     STATE_IPV6_REACHABILITY,
951     STATE_GET_PARAMETERS,
952     STATE_GET_PARAMETERS_COMPLETE,
953     STATE_RESOLVE_LOCALLY,
954     STATE_START_JOB,
955     STATE_FINISH_REQUEST,
956     STATE_NONE,
957   };
958 
FixUpEndpointAndAliasResults()959   void FixUpEndpointAndAliasResults() {
960     DCHECK(results_.has_value());
961     DCHECK(!legacy_address_results_.has_value());
962     DCHECK(!endpoint_results_.has_value());
963     DCHECK(!fixed_up_dns_alias_results_.has_value());
964 
965     endpoint_results_ = results_.value().GetEndpoints();
966     if (endpoint_results_.has_value()) {
967       DCHECK(results_.value().aliases());
968       fixed_up_dns_alias_results_ = *results_.value().aliases();
969 
970       // Skip fixups for `include_canonical_name` requests. Just use the
971       // canonical name exactly as it was received from the system resolver.
972       if (parameters().include_canonical_name) {
973         DCHECK_LE(fixed_up_dns_alias_results_.value().size(), 1u);
974       } else {
975         fixed_up_dns_alias_results_ = dns_alias_utility::FixUpDnsAliases(
976             fixed_up_dns_alias_results_.value());
977       }
978 
979       legacy_address_results_ = HostResolver::EndpointResultToAddressList(
980           endpoint_results_.value(), fixed_up_dns_alias_results_.value());
981     }
982   }
983 
984   // Logging and metrics for when a request has just been started.
LogStartRequest()985   void LogStartRequest() {
986     DCHECK(request_time_.is_null());
987     request_time_ = tick_clock_->NowTicks();
988 
989     source_net_log_.BeginEvent(
990         NetLogEventType::HOST_RESOLVER_MANAGER_REQUEST, [this] {
991           base::Value::Dict dict;
992           dict.Set("host", request_host_.ToString());
993           dict.Set("dns_query_type",
994                    kDnsQueryTypes.at(parameters_.dns_query_type));
995           dict.Set("allow_cached_response",
996                    parameters_.cache_usage !=
997                        ResolveHostParameters::CacheUsage::DISALLOWED);
998           dict.Set("is_speculative", parameters_.is_speculative);
999           dict.Set("network_anonymization_key",
1000                    network_anonymization_key_.ToDebugString());
1001           dict.Set("secure_dns_policy",
1002                    base::strict_cast<int>(parameters_.secure_dns_policy));
1003           return dict;
1004         });
1005   }
1006 
1007   // Logging and metrics for when a request has just completed (before its
1008   // callback is run).
LogFinishRequest(int net_error,bool async_completion)1009   void LogFinishRequest(int net_error, bool async_completion) {
1010     source_net_log_.EndEventWithNetErrorCode(
1011         NetLogEventType::HOST_RESOLVER_MANAGER_REQUEST, net_error);
1012 
1013     if (!parameters_.is_speculative) {
1014       DCHECK(!request_time_.is_null());
1015       base::TimeDelta duration = tick_clock_->NowTicks() - request_time_;
1016 
1017       UMA_HISTOGRAM_MEDIUM_TIMES("Net.DNS.Request.TotalTime", duration);
1018       if (async_completion)
1019         UMA_HISTOGRAM_MEDIUM_TIMES("Net.DNS.Request.TotalTimeAsync", duration);
1020     }
1021   }
1022 
1023   // Logs when a request has been cancelled.
LogCancelRequest()1024   void LogCancelRequest() {
1025     source_net_log_.AddEvent(NetLogEventType::CANCELLED);
1026     source_net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_REQUEST);
1027   }
1028 
1029   const NetLogWithSource source_net_log_;
1030 
1031   const HostResolver::Host request_host_;
1032   const NetworkAnonymizationKey network_anonymization_key_;
1033   ResolveHostParameters parameters_;
1034   base::WeakPtr<ResolveContext> resolve_context_;
1035   const raw_ptr<HostCache, DanglingUntriaged> host_cache_;
1036   const HostResolverFlags host_resolver_flags_;
1037 
1038   RequestPriority priority_;
1039 
1040   ResolveState next_state_;
1041   JobKey job_key_;
1042   IPAddress ip_address_;
1043 
1044   std::deque<TaskType> tasks_;
1045   // The resolve job that this request is dependent on.
1046   absl::optional<base::SafeRef<Job>> job_;
1047   base::WeakPtr<HostResolverManager> resolver_ = nullptr;
1048 
1049   // The user's callback to invoke when the request completes.
1050   CompletionOnceCallback callback_;
1051 
1052   bool complete_ = false;
1053   bool only_ipv6_reachable_ = false;
1054   absl::optional<HostCache::Entry> results_;
1055   absl::optional<HostCache::EntryStaleness> stale_info_;
1056   absl::optional<AddressList> legacy_address_results_;
1057   absl::optional<std::vector<HostResolverEndpointResult>> endpoint_results_;
1058   absl::optional<std::set<std::string>> fixed_up_dns_alias_results_;
1059   ResolveErrorInfo error_info_;
1060 
1061   const raw_ptr<const base::TickClock> tick_clock_;
1062   base::TimeTicks request_time_;
1063 
1064   SEQUENCE_CHECKER(sequence_checker_);
1065 
1066   base::WeakPtrFactory<RequestImpl> weak_ptr_factory_{this};
1067 };
1068 
1069 class HostResolverManager::ProbeRequestImpl
1070     : public HostResolver::ProbeRequest,
1071       public ResolveContext::DohStatusObserver {
1072  public:
ProbeRequestImpl(base::WeakPtr<ResolveContext> context,base::WeakPtr<HostResolverManager> resolver)1073   ProbeRequestImpl(base::WeakPtr<ResolveContext> context,
1074                    base::WeakPtr<HostResolverManager> resolver)
1075       : context_(std::move(context)), resolver_(std::move(resolver)) {}
1076 
1077   ProbeRequestImpl(const ProbeRequestImpl&) = delete;
1078   ProbeRequestImpl& operator=(const ProbeRequestImpl&) = delete;
1079 
~ProbeRequestImpl()1080   ~ProbeRequestImpl() override {
1081     // Ensure that observers are deregistered to avoid wasting memory.
1082     if (context_)
1083       context_->UnregisterDohStatusObserver(this);
1084   }
1085 
Start()1086   int Start() override {
1087     DCHECK(resolver_);
1088     DCHECK(!runner_);
1089 
1090     if (!context_)
1091       return ERR_CONTEXT_SHUT_DOWN;
1092 
1093     context_->RegisterDohStatusObserver(this);
1094 
1095     StartRunner(false /* network_change */);
1096     return ERR_IO_PENDING;
1097   }
1098 
1099   // ResolveContext::DohStatusObserver
OnSessionChanged()1100   void OnSessionChanged() override { CancelRunner(); }
1101 
OnDohServerUnavailable(bool network_change)1102   void OnDohServerUnavailable(bool network_change) override {
1103     // Start the runner asynchronously, as this may trigger reentrant calls into
1104     // HostResolverManager, which are not allowed during notification handling.
1105     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
1106         FROM_HERE,
1107         base::BindOnce(&ProbeRequestImpl::StartRunner,
1108                        weak_ptr_factory_.GetWeakPtr(), network_change));
1109   }
1110 
1111  private:
StartRunner(bool network_change)1112   void StartRunner(bool network_change) {
1113     DCHECK(resolver_);
1114     DCHECK(!resolver_->invalidation_in_progress_);
1115 
1116     if (!context_)
1117       return;  // Reachable if the context ends before a posted task runs.
1118 
1119     if (!runner_)
1120       runner_ = resolver_->CreateDohProbeRunner(context_.get());
1121     if (runner_)
1122       runner_->Start(network_change);
1123   }
1124 
CancelRunner()1125   void CancelRunner() {
1126     runner_.reset();
1127 
1128     // Cancel any asynchronous StartRunner() calls.
1129     weak_ptr_factory_.InvalidateWeakPtrs();
1130   }
1131 
1132   base::WeakPtr<ResolveContext> context_;
1133 
1134   std::unique_ptr<DnsProbeRunner> runner_;
1135   base::WeakPtr<HostResolverManager> resolver_;
1136 
1137   base::WeakPtrFactory<ProbeRequestImpl> weak_ptr_factory_{this};
1138 };
1139 
1140 //-----------------------------------------------------------------------------
1141 
1142 // Resolves the hostname using DnsTransaction, which is a full implementation of
1143 // a DNS stub resolver. One DnsTransaction is created for each resolution
1144 // needed, which for AF_UNSPEC resolutions includes both A and AAAA. The
1145 // transactions are scheduled separately and started separately.
1146 //
1147 // TODO(szym): This could be moved to separate source file as well.
1148 class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
1149  public:
1150   class Delegate {
1151    public:
1152     virtual void OnDnsTaskComplete(base::TimeTicks start_time,
1153                                    bool allow_fallback,
1154                                    HostCache::Entry results,
1155                                    bool secure) = 0;
1156 
1157     // Called when one or more transactions complete or get cancelled, but only
1158     // if more transactions are needed. If no more transactions are needed,
1159     // expect `OnDnsTaskComplete()` to be called instead.
1160     virtual void OnIntermediateTransactionsComplete() = 0;
1161 
1162     virtual RequestPriority priority() const = 0;
1163 
1164     virtual void AddTransactionTimeQueued(base::TimeDelta time_queued) = 0;
1165 
1166    protected:
1167     Delegate() = default;
1168     virtual ~Delegate() = default;
1169   };
1170 
DnsTask(DnsClient * client,absl::variant<url::SchemeHostPort,std::string> host,DnsQueryTypeSet query_types,ResolveContext * resolve_context,bool secure,SecureDnsMode secure_dns_mode,Delegate * delegate,const NetLogWithSource & job_net_log,const base::TickClock * tick_clock,bool fallback_available,const HostResolver::HttpsSvcbOptions & https_svcb_options)1171   DnsTask(DnsClient* client,
1172           absl::variant<url::SchemeHostPort, std::string> host,
1173           DnsQueryTypeSet query_types,
1174           ResolveContext* resolve_context,
1175           bool secure,
1176           SecureDnsMode secure_dns_mode,
1177           Delegate* delegate,
1178           const NetLogWithSource& job_net_log,
1179           const base::TickClock* tick_clock,
1180           bool fallback_available,
1181           const HostResolver::HttpsSvcbOptions& https_svcb_options)
1182       : client_(client),
1183         host_(std::move(host)),
1184         resolve_context_(resolve_context->AsSafeRef()),
1185         secure_(secure),
1186         secure_dns_mode_(secure_dns_mode),
1187         delegate_(delegate),
1188         net_log_(job_net_log),
1189         tick_clock_(tick_clock),
1190         task_start_time_(tick_clock_->NowTicks()),
1191         fallback_available_(fallback_available),
1192         https_svcb_options_(https_svcb_options) {
1193     DCHECK(client_);
1194     DCHECK(delegate_);
1195 
1196     if (!secure_) {
1197       DCHECK(client_->CanUseInsecureDnsTransactions());
1198     }
1199 
1200     PushTransactionsNeeded(MaybeDisableAdditionalQueries(query_types));
1201   }
1202 
1203   DnsTask(const DnsTask&) = delete;
1204   DnsTask& operator=(const DnsTask&) = delete;
1205 
num_additional_transactions_needed() const1206   int num_additional_transactions_needed() const {
1207     return base::checked_cast<int>(transactions_needed_.size());
1208   }
1209 
num_transactions_in_progress() const1210   int num_transactions_in_progress() const {
1211     return base::checked_cast<int>(transactions_in_progress_.size());
1212   }
1213 
secure() const1214   bool secure() const { return secure_; }
1215 
StartNextTransaction()1216   void StartNextTransaction() {
1217     DCHECK_GE(num_additional_transactions_needed(), 1);
1218 
1219     if (!any_transaction_started_) {
1220       net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK,
1221                           [&] { return NetLogDnsTaskCreationParams(); });
1222     }
1223     any_transaction_started_ = true;
1224 
1225     TransactionInfo transaction_info = std::move(transactions_needed_.front());
1226     transactions_needed_.pop_front();
1227 
1228     DCHECK(IsAddressType(transaction_info.type) || secure_ ||
1229            client_->CanQueryAdditionalTypesViaInsecureDns());
1230 
1231     // Record how long this transaction has been waiting to be created.
1232     base::TimeDelta time_queued = tick_clock_->NowTicks() - task_start_time_;
1233     UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.JobQueueTime.PerTransaction",
1234                                  time_queued);
1235     delegate_->AddTransactionTimeQueued(time_queued);
1236 
1237     CreateAndStartTransaction(std::move(transaction_info));
1238   }
1239 
1240  private:
1241   enum class TransactionErrorBehavior {
1242     // Errors lead to task fallback (immediately unless another pending/started
1243     // transaction has the `kFatalOrEmpty` behavior).
1244     kFallback,
1245 
1246     // Transaction errors are treated as if a NOERROR response were received,
1247     // allowing task success if other transactions complete successfully.
1248     kSynthesizeEmpty,
1249 
1250     // Transaction errors are potentially fatal (determined by
1251     // `OnTransactionComplete` and often its helper
1252     // `IsFatalTransactionFailure()`) for the entire Job and may disallow
1253     // fallback. Otherwise, same as `kSynthesizeEmpty`.
1254     // TODO(crbug.com/1264933): Implement the fatality behavior.
1255     kFatalOrEmpty,
1256   };
1257 
1258   struct TransactionInfo {
TransactionInfonet::HostResolverManager::DnsTask::TransactionInfo1259     explicit TransactionInfo(DnsQueryType type,
1260                              TransactionErrorBehavior error_behavior =
1261                                  TransactionErrorBehavior::kFallback)
1262         : type(type), error_behavior(error_behavior) {}
1263     TransactionInfo(TransactionInfo&&) = default;
1264     TransactionInfo& operator=(TransactionInfo&&) = default;
1265 
operator <net::HostResolverManager::DnsTask::TransactionInfo1266     bool operator<(const TransactionInfo& other) const {
1267       return std::tie(type, error_behavior, transaction) <
1268              std::tie(other.type, other.error_behavior, other.transaction);
1269     }
1270 
1271     DnsQueryType type;
1272     TransactionErrorBehavior error_behavior;
1273     std::unique_ptr<DnsTransaction> transaction;
1274   };
1275 
NetLogDnsTaskCreationParams()1276   base::Value::Dict NetLogDnsTaskCreationParams() {
1277     base::Value::Dict dict;
1278     dict.Set("secure", secure());
1279 
1280     base::Value::List transactions_needed_value;
1281     for (const TransactionInfo& info : transactions_needed_) {
1282       base::Value::Dict transaction_dict;
1283       transaction_dict.Set("dns_query_type", kDnsQueryTypes.at(info.type));
1284       transactions_needed_value.Append(std::move(transaction_dict));
1285     }
1286     dict.Set("transactions_needed", std::move(transactions_needed_value));
1287 
1288     return dict;
1289   }
1290 
NetLogDnsTaskTimeoutParams()1291   base::Value::Dict NetLogDnsTaskTimeoutParams() {
1292     base::Value::Dict dict;
1293 
1294     if (!transactions_in_progress_.empty()) {
1295       base::Value::List list;
1296       for (const TransactionInfo& info : transactions_in_progress_) {
1297         base::Value::Dict transaction_dict;
1298         transaction_dict.Set("dns_query_type", kDnsQueryTypes.at(info.type));
1299         list.Append(std::move(transaction_dict));
1300       }
1301       dict.Set("started_transactions", std::move(list));
1302     }
1303 
1304     if (!transactions_needed_.empty()) {
1305       base::Value::List list;
1306       for (const TransactionInfo& info : transactions_needed_) {
1307         base::Value::Dict transaction_dict;
1308         transaction_dict.Set("dns_query_type", kDnsQueryTypes.at(info.type));
1309         list.Append(std::move(transaction_dict));
1310       }
1311       dict.Set("queued_transactions", std::move(list));
1312     }
1313 
1314     return dict;
1315   }
1316 
MaybeDisableAdditionalQueries(DnsQueryTypeSet types)1317   DnsQueryTypeSet MaybeDisableAdditionalQueries(DnsQueryTypeSet types) {
1318     DCHECK(!types.Empty());
1319     DCHECK(!types.Has(DnsQueryType::UNSPECIFIED));
1320 
1321     // No-op if the caller explicitly requested this one query type.
1322     if (types.Size() == 1)
1323       return types;
1324 
1325     if (types.Has(DnsQueryType::HTTPS)) {
1326       if (!secure_ && !client_->CanQueryAdditionalTypesViaInsecureDns()) {
1327         types.Remove(DnsQueryType::HTTPS);
1328       } else {
1329         DCHECK(!httpssvc_metrics_);
1330         httpssvc_metrics_.emplace(secure_);
1331       }
1332     }
1333     DCHECK(!types.Empty());
1334     return types;
1335   }
1336 
PushTransactionsNeeded(DnsQueryTypeSet query_types)1337   void PushTransactionsNeeded(DnsQueryTypeSet query_types) {
1338     DCHECK(transactions_needed_.empty());
1339 
1340     if (query_types.Has(DnsQueryType::HTTPS) &&
1341         features::kUseDnsHttpsSvcbEnforceSecureResponse.Get() && secure_) {
1342       query_types.Remove(DnsQueryType::HTTPS);
1343       transactions_needed_.emplace_back(
1344           DnsQueryType::HTTPS, TransactionErrorBehavior::kFatalOrEmpty);
1345     }
1346 
1347     // Give AAAA/A queries a head start by pushing them to the queue first.
1348     constexpr DnsQueryType kHighPriorityQueries[] = {DnsQueryType::AAAA,
1349                                                      DnsQueryType::A};
1350     for (DnsQueryType high_priority_query : kHighPriorityQueries) {
1351       if (query_types.Has(high_priority_query)) {
1352         query_types.Remove(high_priority_query);
1353         transactions_needed_.emplace_back(high_priority_query);
1354       }
1355     }
1356     for (DnsQueryType remaining_query : query_types) {
1357       if (remaining_query == DnsQueryType::HTTPS) {
1358         // Ignore errors for these types. In most cases treating them normally
1359         // would only result in fallback to resolution without querying the
1360         // type. Instead, synthesize empty results.
1361         transactions_needed_.emplace_back(
1362             remaining_query, TransactionErrorBehavior::kSynthesizeEmpty);
1363       } else {
1364         transactions_needed_.emplace_back(remaining_query);
1365       }
1366     }
1367   }
1368 
CreateAndStartTransaction(TransactionInfo transaction_info)1369   void CreateAndStartTransaction(TransactionInfo transaction_info) {
1370     DCHECK(!transaction_info.transaction);
1371     DCHECK_NE(DnsQueryType::UNSPECIFIED, transaction_info.type);
1372 
1373     std::string transaction_hostname(GetHostname(host_));
1374 
1375     // For HTTPS, prepend "_<port>._https." for any non-default port.
1376     uint16_t request_port = 0;
1377     if (transaction_info.type == DnsQueryType::HTTPS &&
1378         absl::holds_alternative<url::SchemeHostPort>(host_)) {
1379       const auto& scheme_host_port = absl::get<url::SchemeHostPort>(host_);
1380       transaction_hostname =
1381           dns_util::GetNameForHttpsQuery(scheme_host_port, &request_port);
1382     }
1383 
1384     transaction_info.transaction =
1385         client_->GetTransactionFactory()->CreateTransaction(
1386             std::move(transaction_hostname),
1387             DnsQueryTypeToQtype(transaction_info.type), net_log_, secure_,
1388             secure_dns_mode_, &*resolve_context_,
1389             fallback_available_ /* fast_timeout */);
1390     transaction_info.transaction->SetRequestPriority(delegate_->priority());
1391 
1392     auto transaction_info_it =
1393         transactions_in_progress_.insert(std::move(transaction_info)).first;
1394 
1395     // Safe to pass `transaction_info_it` because it is only modified/removed
1396     // after async completion of this call or by destruction (which cancels the
1397     // transaction and prevents callback because it owns the `DnsTransaction`
1398     // object).
1399     transaction_info_it->transaction->Start(base::BindOnce(
1400         &DnsTask::OnDnsTransactionComplete, base::Unretained(this),
1401         transaction_info_it, request_port));
1402   }
1403 
OnTimeout()1404   void OnTimeout() {
1405     net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK_TIMEOUT,
1406                       [&] { return NetLogDnsTaskTimeoutParams(); });
1407 
1408     for (const TransactionInfo& transaction : transactions_in_progress_) {
1409       base::TimeDelta elapsed_time = tick_clock_->NowTicks() - task_start_time_;
1410 
1411       switch (transaction.type) {
1412         case DnsQueryType::HTTPS:
1413           DCHECK(!secure_ ||
1414                  !features::kUseDnsHttpsSvcbEnforceSecureResponse.Get());
1415           if (httpssvc_metrics_) {
1416             // Don't record provider ID for timeouts. It is not precisely known
1417             // at this level which provider is actually to blame for the
1418             // timeout, and breaking metrics out by provider is no longer
1419             // important for current experimentation goals.
1420             httpssvc_metrics_->SaveForHttps(HttpssvcDnsRcode::kTimedOut,
1421                                             /*condensed_records=*/{},
1422                                             elapsed_time);
1423           }
1424           break;
1425         default:
1426           // The timeout timer is only started when all other transactions have
1427           // completed.
1428           NOTREACHED();
1429       }
1430     }
1431 
1432     transactions_needed_.clear();
1433     transactions_in_progress_.clear();
1434 
1435     OnTransactionsFinished();
1436   }
1437 
1438   // Called on completion of a `DnsTransaction`, but not necessarily completion
1439   // of all work for the individual transaction in this task (see
1440   // `OnTransactionsFinished()`).
OnDnsTransactionComplete(std::set<TransactionInfo>::iterator transaction_info_it,uint16_t request_port,int net_error,const DnsResponse * response)1441   void OnDnsTransactionComplete(
1442       std::set<TransactionInfo>::iterator transaction_info_it,
1443       uint16_t request_port,
1444       int net_error,
1445       const DnsResponse* response) {
1446     DCHECK(transaction_info_it != transactions_in_progress_.end());
1447     DCHECK(transactions_in_progress_.find(*transaction_info_it) !=
1448            transactions_in_progress_.end());
1449 
1450     // Pull the TransactionInfo out of `transactions_in_progress_` now, so it
1451     // and its underlying DnsTransaction will be deleted on completion of
1452     // OnTransactionComplete. Note: Once control leaves OnTransactionComplete,
1453     // there's no further need for the transaction object. On the other hand,
1454     // since it owns `*response`, it should stay around while
1455     // OnTransactionComplete executes.
1456     TransactionInfo transaction_info = std::move(
1457         transactions_in_progress_.extract(transaction_info_it).value());
1458 
1459     const base::TimeTicks now = tick_clock_->NowTicks();
1460     base::TimeDelta elapsed_time = now - task_start_time_;
1461     enum HttpssvcDnsRcode rcode_for_httpssvc = HttpssvcDnsRcode::kNoError;
1462     if (httpssvc_metrics_) {
1463       if (net_error == ERR_DNS_TIMED_OUT) {
1464         rcode_for_httpssvc = HttpssvcDnsRcode::kTimedOut;
1465       } else if (net_error == ERR_NAME_NOT_RESOLVED) {
1466         rcode_for_httpssvc = HttpssvcDnsRcode::kNoError;
1467       } else if (response == nullptr) {
1468         rcode_for_httpssvc = HttpssvcDnsRcode::kMissingDnsResponse;
1469       } else {
1470         rcode_for_httpssvc =
1471             TranslateDnsRcodeForHttpssvcExperiment(response->rcode());
1472       }
1473     }
1474 
1475     // Handle network errors. Note that for NXDOMAIN, DnsTransaction returns
1476     // ERR_NAME_NOT_RESOLVED, so that is not a network error if received with a
1477     // valid response.
1478     bool fatal_error =
1479         IsFatalTransactionFailure(net_error, transaction_info, response);
1480     absl::optional<DnsResponse> fake_response;
1481     if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
1482                              response->IsValid())) {
1483       if (transaction_info.error_behavior ==
1484               TransactionErrorBehavior::kFallback ||
1485           fatal_error) {
1486         // Fail task (or maybe Job) completely on network failure.
1487         OnFailure(net_error, /*allow_fallback=*/!fatal_error,
1488                   /*ttl=*/absl::nullopt, transaction_info.type);
1489         return;
1490       } else {
1491         DCHECK((transaction_info.error_behavior ==
1492                     TransactionErrorBehavior::kFatalOrEmpty &&
1493                 !fatal_error) ||
1494                transaction_info.error_behavior ==
1495                    TransactionErrorBehavior::kSynthesizeEmpty);
1496         // For non-fatal failures, synthesize an empty response.
1497         fake_response =
1498             CreateFakeEmptyResponse(GetHostname(host_), transaction_info.type);
1499         response = &fake_response.value();
1500       }
1501     }
1502 
1503     HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
1504     DnsResponseResultExtractor extractor(response);
1505     DnsResponseResultExtractor::ExtractionError extraction_error =
1506         extractor.ExtractDnsResults(transaction_info.type,
1507                                     /*original_domain_name=*/GetHostname(host_),
1508                                     request_port, &results);
1509     DCHECK_NE(extraction_error,
1510               DnsResponseResultExtractor::ExtractionError::kUnexpected);
1511 
1512     if (results.error() != OK && results.error() != ERR_NAME_NOT_RESOLVED) {
1513       net_log_.AddEvent(
1514           NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK_EXTRACTION_FAILURE,
1515           [&] {
1516             return NetLogDnsTaskExtractionFailureParams(
1517                 extraction_error, transaction_info.type, results);
1518           });
1519       if (transaction_info.error_behavior ==
1520               TransactionErrorBehavior::kFatalOrEmpty ||
1521           transaction_info.error_behavior ==
1522               TransactionErrorBehavior::kSynthesizeEmpty) {
1523         // No extraction errors are currently considered fatal, otherwise, there
1524         // would need to be a call to some sort of
1525         // IsFatalTransactionExtractionError() function.
1526         DCHECK(!fatal_error);
1527         results = DnsResponseResultExtractor::CreateEmptyResult(
1528             transaction_info.type);
1529       } else {
1530         OnFailure(results.error(), /*allow_fallback=*/true,
1531                   results.GetOptionalTtl(), transaction_info.type);
1532         return;
1533       }
1534     }
1535 
1536     if (httpssvc_metrics_) {
1537       if (transaction_info.type == DnsQueryType::HTTPS) {
1538         const std::vector<bool>* record_compatibility =
1539             results.https_record_compatibility();
1540         CHECK(record_compatibility);
1541         httpssvc_metrics_->SaveForHttps(rcode_for_httpssvc,
1542                                         *record_compatibility, elapsed_time);
1543       } else {
1544         httpssvc_metrics_->SaveForAddressQuery(elapsed_time,
1545                                                rcode_for_httpssvc);
1546       }
1547     }
1548 
1549     // Trigger HTTP->HTTPS upgrade if an HTTPS record is received for an "http"
1550     // or "ws" request.
1551     if (transaction_info.type == DnsQueryType::HTTPS &&
1552         ShouldTriggerHttpToHttpsUpgrade(results)) {
1553       // Disallow fallback. Otherwise DNS could be reattempted without HTTPS
1554       // queries, and that would hide this error instead of triggering upgrade.
1555       OnFailure(ERR_DNS_NAME_HTTPS_ONLY, /*allow_fallback=*/false,
1556                 results.GetOptionalTtl(), transaction_info.type);
1557       return;
1558     }
1559 
1560     HideMetadataResultsIfNotDesired(results);
1561 
1562     switch (transaction_info.type) {
1563       case DnsQueryType::A:
1564         a_record_end_time_ = now;
1565         if (!aaaa_record_end_time_.is_null()) {
1566           RecordResolveTimeDiff("AAAABeforeA", task_start_time_,
1567                                 aaaa_record_end_time_, a_record_end_time_);
1568         }
1569         break;
1570       case DnsQueryType::AAAA:
1571         aaaa_record_end_time_ = now;
1572         if (!a_record_end_time_.is_null()) {
1573           RecordResolveTimeDiff("ABeforeAAAA", task_start_time_,
1574                                 a_record_end_time_, aaaa_record_end_time_);
1575         }
1576         break;
1577       case DnsQueryType::HTTPS: {
1578         base::TimeTicks first_address_end_time =
1579             std::min(a_record_end_time_, aaaa_record_end_time_);
1580         if (!first_address_end_time.is_null()) {
1581           RecordResolveTimeDiff("AddressRecordBeforeHTTPS", task_start_time_,
1582                                 first_address_end_time, now);
1583         }
1584         break;
1585       }
1586       default:
1587         break;
1588     }
1589 
1590     // Merge results with saved results from previous transactions.
1591     if (saved_results_) {
1592       // If saved result is a deferred failure, try again to complete with that
1593       // failure.
1594       if (saved_results_is_failure_) {
1595         OnFailure(saved_results_.value().error(), /*allow_fallback=*/true,
1596                   saved_results_.value().GetOptionalTtl());
1597         return;
1598       }
1599 
1600       switch (transaction_info.type) {
1601         case DnsQueryType::A:
1602           // Canonical names from A results have lower priority than those
1603           // from AAAA results, so merge to the back.
1604           results = HostCache::Entry::MergeEntries(
1605               std::move(saved_results_).value(), std::move(results));
1606           break;
1607         case DnsQueryType::AAAA:
1608           // Canonical names from AAAA results take priority over those
1609           // from A results, so merge to the front.
1610           results = HostCache::Entry::MergeEntries(
1611               std::move(results), std::move(saved_results_).value());
1612           break;
1613         case DnsQueryType::HTTPS:
1614           // No particular importance to order.
1615           results = HostCache::Entry::MergeEntries(
1616               std::move(results), std::move(saved_results_).value());
1617           break;
1618         default:
1619           // Only expect address query types with multiple transactions.
1620           NOTREACHED();
1621       }
1622     }
1623 
1624     saved_results_ = std::move(results);
1625     OnTransactionsFinished();
1626   }
1627 
IsFatalTransactionFailure(int transaction_error,const TransactionInfo & transaction_info,const DnsResponse * response)1628   bool IsFatalTransactionFailure(int transaction_error,
1629                                  const TransactionInfo& transaction_info,
1630                                  const DnsResponse* response) {
1631     if (transaction_info.type != DnsQueryType::HTTPS) {
1632       DCHECK(transaction_info.error_behavior !=
1633              TransactionErrorBehavior::kFatalOrEmpty);
1634       return false;
1635     }
1636 
1637     // These values are logged to UMA. Entries should not be renumbered and
1638     // numeric values should never be reused. Please keep in sync with
1639     // "DNS.SvcbHttpsTransactionError" in
1640     // src/tools/metrics/histograms/enums.xml.
1641     enum class HttpsTransactionError {
1642       kNoError = 0,
1643       kInsecureError = 1,
1644       kNonFatalError = 2,
1645       kFatalErrorDisabled = 3,
1646       kFatalErrorEnabled = 4,
1647       kMaxValue = kFatalErrorEnabled
1648     } error;
1649 
1650     if (transaction_error == OK ||
1651         (transaction_error == ERR_NAME_NOT_RESOLVED && response &&
1652          response->IsValid())) {
1653       error = HttpsTransactionError::kNoError;
1654     } else if (!secure_) {
1655       // HTTPS failures are never fatal via insecure DNS.
1656       DCHECK(transaction_info.error_behavior !=
1657              TransactionErrorBehavior::kFatalOrEmpty);
1658       error = HttpsTransactionError::kInsecureError;
1659     } else if (transaction_error == ERR_DNS_SERVER_FAILED && response &&
1660                response->rcode() != dns_protocol::kRcodeSERVFAIL) {
1661       // For server failures, only SERVFAIL is fatal.
1662       error = HttpsTransactionError::kNonFatalError;
1663     } else if (features::kUseDnsHttpsSvcbEnforceSecureResponse.Get()) {
1664       DCHECK(transaction_info.error_behavior ==
1665              TransactionErrorBehavior::kFatalOrEmpty);
1666       error = HttpsTransactionError::kFatalErrorEnabled;
1667     } else {
1668       DCHECK(transaction_info.error_behavior !=
1669              TransactionErrorBehavior::kFatalOrEmpty);
1670       error = HttpsTransactionError::kFatalErrorDisabled;
1671     }
1672 
1673     UMA_HISTOGRAM_ENUMERATION("Net.DNS.DnsTask.SvcbHttpsTransactionError",
1674                               error);
1675     return error == HttpsTransactionError::kFatalErrorEnabled;
1676   }
1677 
1678   // Called on processing for one or more individual transaction being
1679   // completed/cancelled. Processes overall results if all transactions are
1680   // finished.
OnTransactionsFinished()1681   void OnTransactionsFinished() {
1682     if (!transactions_in_progress_.empty() || !transactions_needed_.empty()) {
1683       delegate_->OnIntermediateTransactionsComplete();
1684       MaybeStartTimeoutTimer();
1685       return;
1686     }
1687 
1688     DCHECK(saved_results_.has_value());
1689     HostCache::Entry results = std::move(*saved_results_);
1690 
1691     timeout_timer_.Stop();
1692 
1693     absl::optional<std::vector<IPEndPoint>> ip_endpoints;
1694     ip_endpoints = base::OptionalFromPtr(results.ip_endpoints());
1695 
1696     if (ip_endpoints.has_value()) {
1697       // If there are multiple addresses, and at least one is IPv6, need to
1698       // sort them.
1699       bool at_least_one_ipv6_address = base::ranges::any_of(
1700           ip_endpoints.value(),
1701           [](auto& e) { return e.GetFamily() == ADDRESS_FAMILY_IPV6; });
1702 
1703       if (at_least_one_ipv6_address) {
1704         // Sort addresses if needed.  Sort could complete synchronously.
1705         client_->GetAddressSorter()->Sort(
1706             ip_endpoints.value(),
1707             base::BindOnce(&DnsTask::OnSortComplete, AsWeakPtr(),
1708                            tick_clock_->NowTicks(), std::move(results),
1709                            secure_));
1710         return;
1711       }
1712     }
1713     OnSuccess(std::move(results));
1714   }
1715 
OnSortComplete(base::TimeTicks sort_start_time,HostCache::Entry results,bool secure,bool success,std::vector<IPEndPoint> sorted)1716   void OnSortComplete(base::TimeTicks sort_start_time,
1717                       HostCache::Entry results,
1718                       bool secure,
1719                       bool success,
1720                       std::vector<IPEndPoint> sorted) {
1721     DCHECK(results.ip_endpoints());
1722     results.set_ip_endpoints(std::move(sorted));
1723 
1724     if (!success) {
1725       OnFailure(ERR_DNS_SORT_ERROR, /*allow_fallback=*/true,
1726                 results.GetOptionalTtl());
1727       return;
1728     }
1729 
1730     // AddressSorter prunes unusable destinations.
1731     if ((!results.ip_endpoints() || results.ip_endpoints()->empty()) &&
1732         results.text_records().value_or(std::vector<std::string>()).empty() &&
1733         results.hostnames().value_or(std::vector<HostPortPair>()).empty()) {
1734       LOG(WARNING) << "Address list empty after RFC3484 sort";
1735       OnFailure(ERR_NAME_NOT_RESOLVED, /*allow_fallback=*/true,
1736                 results.GetOptionalTtl());
1737       return;
1738     }
1739 
1740     OnSuccess(std::move(results));
1741   }
1742 
AnyPotentiallyFatalTransactionsRemain()1743   bool AnyPotentiallyFatalTransactionsRemain() {
1744     auto is_fatal_or_empty_error = [](TransactionErrorBehavior behavior) {
1745       return behavior == TransactionErrorBehavior::kFatalOrEmpty;
1746     };
1747 
1748     return base::ranges::any_of(transactions_needed_, is_fatal_or_empty_error,
1749                                 &TransactionInfo::error_behavior) ||
1750            base::ranges::any_of(transactions_in_progress_,
1751                                 is_fatal_or_empty_error,
1752                                 &TransactionInfo::error_behavior);
1753   }
1754 
CancelNonFatalTransactions()1755   void CancelNonFatalTransactions() {
1756     auto has_non_fatal_or_empty_error = [](const TransactionInfo& info) {
1757       return info.error_behavior != TransactionErrorBehavior::kFatalOrEmpty;
1758     };
1759 
1760     base::EraseIf(transactions_needed_, has_non_fatal_or_empty_error);
1761     base::EraseIf(transactions_in_progress_, has_non_fatal_or_empty_error);
1762   }
1763 
OnFailure(int net_error,bool allow_fallback,absl::optional<base::TimeDelta> ttl=absl::nullopt,absl::optional<DnsQueryType> failed_transaction_type=absl::nullopt)1764   void OnFailure(
1765       int net_error,
1766       bool allow_fallback,
1767       absl::optional<base::TimeDelta> ttl = absl::nullopt,
1768       absl::optional<DnsQueryType> failed_transaction_type = absl::nullopt) {
1769     if (httpssvc_metrics_ && failed_transaction_type.has_value() &&
1770         IsAddressType(failed_transaction_type.value())) {
1771       httpssvc_metrics_->SaveAddressQueryFailure();
1772     }
1773 
1774     DCHECK_NE(OK, net_error);
1775     HostCache::Entry results(net_error, HostCache::Entry::SOURCE_UNKNOWN, ttl);
1776 
1777     // On non-fatal errors, if any potentially fatal transactions remain, need
1778     // to defer ending the task in case any of those remaining transactions end
1779     // with a fatal failure.
1780     if (allow_fallback && AnyPotentiallyFatalTransactionsRemain()) {
1781       saved_results_ = std::move(results);
1782       saved_results_is_failure_ = true;
1783 
1784       CancelNonFatalTransactions();
1785       OnTransactionsFinished();
1786       return;
1787     }
1788 
1789     net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK, [&] {
1790       return NetLogDnsTaskFailedParams(net_error, failed_transaction_type, ttl,
1791                                        base::OptionalToPtr(saved_results_));
1792     });
1793 
1794     // Expect this to result in destroying `this` and thus cancelling any
1795     // remaining transactions.
1796     delegate_->OnDnsTaskComplete(task_start_time_, allow_fallback,
1797                                  std::move(results), secure_);
1798   }
1799 
OnSuccess(HostCache::Entry results)1800   void OnSuccess(HostCache::Entry results) {
1801     net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK,
1802                       [&] { return NetLogResults(results); });
1803     delegate_->OnDnsTaskComplete(task_start_time_, /*allow_fallback=*/true,
1804                                  std::move(results), secure_);
1805   }
1806 
1807   // Returns whether any transactions left to finish are of a transaction type
1808   // in `types`. Used for logging and starting the timeout timer (see
1809   // MaybeStartTimeoutTimer()).
AnyOfTypeTransactionsRemain(std::initializer_list<DnsQueryType> types) const1810   bool AnyOfTypeTransactionsRemain(
1811       std::initializer_list<DnsQueryType> types) const {
1812     // Should only be called if some transactions are still running or waiting
1813     // to run.
1814     DCHECK(!transactions_needed_.empty() || !transactions_in_progress_.empty());
1815 
1816     // Check running transactions.
1817     if (base::ranges::find_first_of(transactions_in_progress_, types,
1818                                     /*pred=*/{},
1819                                     /*proj1=*/&TransactionInfo::type) !=
1820         transactions_in_progress_.end()) {
1821       return true;
1822     }
1823 
1824     // Check queued transactions, in case it ever becomes possible to get here
1825     // without the transactions being started first.
1826     return base::ranges::find_first_of(transactions_needed_, types, /*pred=*/{},
1827                                        /*proj1=*/&TransactionInfo::type) !=
1828            transactions_needed_.end();
1829   }
1830 
MaybeStartTimeoutTimer()1831   void MaybeStartTimeoutTimer() {
1832     // Should only be called if some transactions are still running or waiting
1833     // to run.
1834     DCHECK(!transactions_in_progress_.empty() || !transactions_needed_.empty());
1835 
1836     // Timer already running.
1837     if (timeout_timer_.IsRunning())
1838       return;
1839 
1840     // Always wait for address transactions.
1841     if (AnyOfTypeTransactionsRemain({DnsQueryType::A, DnsQueryType::AAAA}))
1842       return;
1843 
1844     base::TimeDelta timeout_max;
1845     int extra_time_percent = 0;
1846     base::TimeDelta timeout_min;
1847 
1848     if (AnyOfTypeTransactionsRemain({DnsQueryType::HTTPS})) {
1849       DCHECK(https_svcb_options_.enable);
1850 
1851       if (secure_) {
1852         timeout_max = https_svcb_options_.secure_extra_time_max;
1853         extra_time_percent = https_svcb_options_.secure_extra_time_percent;
1854         timeout_min = https_svcb_options_.secure_extra_time_min;
1855       } else {
1856         timeout_max = https_svcb_options_.insecure_extra_time_max;
1857         extra_time_percent = https_svcb_options_.insecure_extra_time_percent;
1858         timeout_min = https_svcb_options_.insecure_extra_time_min;
1859       }
1860 
1861       // Skip timeout for secure requests if the timeout would be a fatal
1862       // failure.
1863       if (secure_ && features::kUseDnsHttpsSvcbEnforceSecureResponse.Get()) {
1864         timeout_max = base::TimeDelta();
1865         extra_time_percent = 0;
1866         timeout_min = base::TimeDelta();
1867       }
1868     } else {
1869       // Unhandled supplemental type.
1870       NOTREACHED();
1871     }
1872 
1873     base::TimeDelta timeout;
1874     if (extra_time_percent > 0) {
1875       base::TimeDelta total_time_for_other_transactions =
1876           tick_clock_->NowTicks() - task_start_time_;
1877       timeout = total_time_for_other_transactions * extra_time_percent / 100;
1878       // Use at least 1ms to ensure timeout doesn't occur immediately in tests.
1879       timeout = std::max(timeout, base::Milliseconds(1));
1880 
1881       if (!timeout_max.is_zero())
1882         timeout = std::min(timeout, timeout_max);
1883       if (!timeout_min.is_zero())
1884         timeout = std::max(timeout, timeout_min);
1885     } else {
1886       // If no relative timeout, use a non-zero min/max as timeout. If both are
1887       // non-zero, that's not very sensible, but arbitrarily take the higher
1888       // timeout.
1889       timeout = std::max(timeout_min, timeout_max);
1890     }
1891 
1892     if (!timeout.is_zero())
1893       timeout_timer_.Start(
1894           FROM_HERE, timeout,
1895           base::BindOnce(&DnsTask::OnTimeout, base::Unretained(this)));
1896   }
1897 
ShouldTriggerHttpToHttpsUpgrade(const HostCache::Entry & results)1898   bool ShouldTriggerHttpToHttpsUpgrade(const HostCache::Entry& results) {
1899     // Upgrade if at least one HTTPS record was compatible, and the host uses an
1900     // upgradable scheme.
1901     return results.https_record_compatibility() &&
1902            base::ranges::any_of(*results.https_record_compatibility(),
1903                                 base::identity()) &&
1904            (GetScheme(host_) == url::kHttpScheme ||
1905             GetScheme(host_) == url::kWsScheme);
1906   }
1907 
1908   // Only keep metadata results (from HTTPS records) for appropriate schemes.
1909   // This is needed to ensure metadata isn't included in results if the current
1910   // Feature setup allows querying HTTPS for http:// or ws:// but doesn't enable
1911   // scheme upgrade to error out on finding an HTTPS record.
1912   //
1913   // TODO(crbug.com/1206455): Remove once all requests that query HTTPS will
1914   // either allow metadata results or error out.
HideMetadataResultsIfNotDesired(HostCache::Entry & results)1915   void HideMetadataResultsIfNotDesired(HostCache::Entry& results) {
1916     if (GetScheme(host_) == url::kHttpsScheme ||
1917         GetScheme(host_) == url::kWssScheme) {
1918       return;
1919     }
1920 
1921     results.ClearMetadatas();
1922   }
1923 
1924   const raw_ptr<DnsClient> client_;
1925 
1926   absl::variant<url::SchemeHostPort, std::string> host_;
1927 
1928   base::SafeRef<ResolveContext> resolve_context_;
1929 
1930   // Whether lookups in this DnsTask should occur using DoH or plaintext.
1931   const bool secure_;
1932   const SecureDnsMode secure_dns_mode_;
1933 
1934   // The listener to the results of this DnsTask.
1935   const raw_ptr<Delegate> delegate_;
1936   const NetLogWithSource net_log_;
1937 
1938   bool any_transaction_started_ = false;
1939   base::circular_deque<TransactionInfo> transactions_needed_;
1940   // Active transactions have iterators pointing to their entry in this set, so
1941   // individual entries should not be modified or removed until completion or
1942   // cancellation of the transaction.
1943   std::set<TransactionInfo> transactions_in_progress_;
1944 
1945   // For histograms.
1946   base::TimeTicks a_record_end_time_;
1947   base::TimeTicks aaaa_record_end_time_;
1948 
1949   absl::optional<HostCache::Entry> saved_results_;
1950   bool saved_results_is_failure_ = false;
1951 
1952   const raw_ptr<const base::TickClock> tick_clock_;
1953   base::TimeTicks task_start_time_;
1954 
1955   absl::optional<HttpssvcMetrics> httpssvc_metrics_;
1956 
1957   // Timer for task timeout. Generally started after completion of address
1958   // transactions to allow aborting experimental or supplemental transactions.
1959   base::OneShotTimer timeout_timer_;
1960 
1961   // If true, there are still significant fallback options available if this
1962   // task completes unsuccessfully. Used as a signal that underlying
1963   // transactions should timeout more quickly.
1964   bool fallback_available_;
1965 
1966   const HostResolver::HttpsSvcbOptions https_svcb_options_;
1967 };
1968 
1969 //-----------------------------------------------------------------------------
1970 
1971 // Aggregates all Requests for the same Key. Dispatched via
1972 // PrioritizedDispatcher.
1973 class HostResolverManager::Job : public PrioritizedDispatcher::Job,
1974                                  public HostResolverManager::DnsTask::Delegate {
1975  public:
1976   // Creates new job for |key| where |request_net_log| is bound to the
1977   // request that spawned it.
Job(const base::WeakPtr<HostResolverManager> & resolver,JobKey key,ResolveHostParameters::CacheUsage cache_usage,HostCache * host_cache,std::deque<TaskType> tasks,RequestPriority priority,const NetLogWithSource & source_net_log,const base::TickClock * tick_clock,const HostResolver::HttpsSvcbOptions & https_svcb_options)1978   Job(const base::WeakPtr<HostResolverManager>& resolver,
1979       JobKey key,
1980       ResolveHostParameters::CacheUsage cache_usage,
1981       HostCache* host_cache,
1982       std::deque<TaskType> tasks,
1983       RequestPriority priority,
1984       const NetLogWithSource& source_net_log,
1985       const base::TickClock* tick_clock,
1986       const HostResolver::HttpsSvcbOptions& https_svcb_options)
1987       : resolver_(resolver),
1988         key_(std::move(key)),
1989         cache_usage_(cache_usage),
1990         host_cache_(host_cache),
1991         tasks_(tasks),
1992         priority_tracker_(priority),
1993         tick_clock_(tick_clock),
1994         https_svcb_options_(https_svcb_options),
1995         net_log_(
1996             NetLogWithSource::Make(source_net_log.net_log(),
1997                                    NetLogSourceType::HOST_RESOLVER_IMPL_JOB)) {
1998     source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_CREATE_JOB);
1999 
2000     net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB, [&] {
2001       return NetLogJobCreationParams(source_net_log.source());
2002     });
2003   }
2004 
~Job()2005   ~Job() override {
2006     bool was_queued = is_queued();
2007     bool was_running = is_running();
2008     // Clean up now for nice NetLog.
2009     Finish();
2010     if (was_running) {
2011       // This Job was destroyed while still in flight.
2012       net_log_.EndEventWithNetErrorCode(
2013           NetLogEventType::HOST_RESOLVER_MANAGER_JOB, ERR_ABORTED);
2014     } else if (was_queued) {
2015       // Job was cancelled before it could run.
2016       // TODO(szym): is there any benefit in having this distinction?
2017       net_log_.AddEvent(NetLogEventType::CANCELLED);
2018       net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB);
2019     }
2020     // else CompleteRequests logged EndEvent.
2021     while (!requests_.empty()) {
2022       // Log any remaining Requests as cancelled.
2023       RequestImpl* req = requests_.head()->value();
2024       req->RemoveFromList();
2025       CHECK(key_ == req->GetJobKey());
2026       req->OnJobCancelled(key_);
2027     }
2028   }
2029 
2030   // Add this job to the dispatcher.  If "at_head" is true, adds at the front
2031   // of the queue.
Schedule(bool at_head)2032   void Schedule(bool at_head) {
2033     DCHECK(!is_queued());
2034     PrioritizedDispatcher::Handle handle;
2035     DCHECK(dispatched_);
2036     if (!at_head) {
2037       handle = resolver_->dispatcher_->Add(this, priority());
2038     } else {
2039       handle = resolver_->dispatcher_->AddAtHead(this, priority());
2040     }
2041     // The dispatcher could have started |this| in the above call to Add, which
2042     // could have called Schedule again. In that case |handle| will be null,
2043     // but |handle_| may have been set by the other nested call to Schedule.
2044     if (!handle.is_null()) {
2045       DCHECK(handle_.is_null());
2046       handle_ = handle;
2047     }
2048   }
2049 
AddRequest(RequestImpl * request)2050   void AddRequest(RequestImpl* request) {
2051     // Job currently assumes a 1:1 correspondence between ResolveContext and
2052     // HostCache. Since the ResolveContext is part of the JobKey, any request
2053     // added to any existing Job should share the same HostCache.
2054     DCHECK_EQ(host_cache_, request->host_cache());
2055     // TODO(crbug.com/1206799): Check equality of whole host once Jobs are
2056     // separated by scheme/port.
2057     DCHECK_EQ(GetHostname(key_.host),
2058               request->request_host().GetHostnameWithoutBrackets());
2059 
2060     request->AssignJob(weak_ptr_factory_.GetSafeRef());
2061 
2062     priority_tracker_.Add(request->priority());
2063 
2064     request->source_net_log().AddEventReferencingSource(
2065         NetLogEventType::HOST_RESOLVER_MANAGER_JOB_ATTACH, net_log_.source());
2066 
2067     net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB_REQUEST_ATTACH,
2068                       [&] {
2069                         return NetLogJobAttachParams(
2070                             request->source_net_log().source(), priority());
2071                       });
2072 
2073     if (!request->parameters().is_speculative)
2074       had_non_speculative_request_ = true;
2075 
2076     requests_.Append(request);
2077 
2078     UpdatePriority();
2079   }
2080 
ChangeRequestPriority(RequestImpl * req,RequestPriority priority)2081   void ChangeRequestPriority(RequestImpl* req, RequestPriority priority) {
2082     // TODO(crbug.com/1206799): Check equality of whole host once Jobs are
2083     // separated by scheme/port.
2084     DCHECK_EQ(GetHostname(key_.host),
2085               req->request_host().GetHostnameWithoutBrackets());
2086 
2087     priority_tracker_.Remove(req->priority());
2088     req->set_priority(priority);
2089     priority_tracker_.Add(req->priority());
2090     UpdatePriority();
2091   }
2092 
2093   // Detach cancelled request. If it was the last active Request, also finishes
2094   // this Job.
CancelRequest(RequestImpl * request)2095   void CancelRequest(RequestImpl* request) {
2096     // TODO(crbug.com/1206799): Check equality of whole host once Jobs are
2097     // separated by scheme/port.
2098     DCHECK_EQ(GetHostname(key_.host),
2099               request->request_host().GetHostnameWithoutBrackets());
2100     DCHECK(!requests_.empty());
2101 
2102     priority_tracker_.Remove(request->priority());
2103     net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB_REQUEST_DETACH,
2104                       [&] {
2105                         return NetLogJobAttachParams(
2106                             request->source_net_log().source(), priority());
2107                       });
2108 
2109     if (num_active_requests() > 0) {
2110       UpdatePriority();
2111       request->RemoveFromList();
2112     } else {
2113       // If we were called from a Request's callback within CompleteRequests,
2114       // that Request could not have been cancelled, so num_active_requests()
2115       // could not be 0. Therefore, we are not in CompleteRequests().
2116       CompleteRequestsWithError(ERR_DNS_REQUEST_CANCELLED,
2117                                 /*task_type=*/absl::nullopt);
2118     }
2119   }
2120 
2121   // Called from AbortJobsWithoutTargetNetwork(). Completes all requests and
2122   // destroys the job. This currently assumes the abort is due to a network
2123   // change.
2124   // TODO This should not delete |this|.
Abort()2125   void Abort() {
2126     CompleteRequestsWithError(ERR_NETWORK_CHANGED, /*task_type=*/absl::nullopt);
2127   }
2128 
2129   // Gets a closure that will abort an insecure DnsTask (see
2130   // AbortInsecureDnsTask()) iff |this| is still valid. Useful if aborting a
2131   // list of Jobs as some may be cancelled while aborting others.
GetAbortInsecureDnsTaskClosure(int error,bool fallback_only)2132   base::OnceClosure GetAbortInsecureDnsTaskClosure(int error,
2133                                                    bool fallback_only) {
2134     return base::BindOnce(&Job::AbortInsecureDnsTask,
2135                           weak_ptr_factory_.GetWeakPtr(), error, fallback_only);
2136   }
2137 
2138   // Aborts or removes any current/future insecure DnsTasks if a
2139   // HostResolverSystemTask is available for fallback. If no fallback is
2140   // available and |fallback_only| is false, a job that is currently running an
2141   // insecure DnsTask will be completed with |error|.
AbortInsecureDnsTask(int error,bool fallback_only)2142   void AbortInsecureDnsTask(int error, bool fallback_only) {
2143     bool has_system_fallback = base::Contains(tasks_, TaskType::SYSTEM);
2144     if (has_system_fallback) {
2145       for (auto it = tasks_.begin(); it != tasks_.end();) {
2146         if (*it == TaskType::DNS)
2147           it = tasks_.erase(it);
2148         else
2149           ++it;
2150       }
2151     }
2152 
2153     if (dns_task_ && !dns_task_->secure()) {
2154       if (has_system_fallback) {
2155         KillDnsTask();
2156         dns_task_error_ = OK;
2157         RunNextTask();
2158       } else if (!fallback_only) {
2159         CompleteRequestsWithError(error, /*task_type=*/absl::nullopt);
2160       }
2161     }
2162   }
2163 
2164   // Called by HostResolverManager when this job is evicted due to queue
2165   // overflow. Completes all requests and destroys the job. The job could have
2166   // waiting requests that will receive completion callbacks, so cleanup
2167   // asynchronously to avoid reentrancy.
OnEvicted()2168   void OnEvicted() {
2169     DCHECK(!is_running());
2170     DCHECK(is_queued());
2171     handle_.Reset();
2172 
2173     net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB_EVICTED);
2174 
2175     // This signals to CompleteRequests that parts of this job never ran.
2176     // Job must be saved in |resolver_| to be completed asynchronously.
2177     // Otherwise the job will be destroyed with requests silently cancelled
2178     // before completion runs.
2179     DCHECK(self_iterator_);
2180     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
2181         FROM_HERE, base::BindOnce(&Job::CompleteRequestsWithError,
2182                                   weak_ptr_factory_.GetWeakPtr(),
2183                                   ERR_HOST_RESOLVER_QUEUE_TOO_LARGE,
2184                                   /*task_type=*/absl::nullopt));
2185   }
2186 
2187   // Attempts to serve the job from HOSTS. Returns true if succeeded and
2188   // this Job was destroyed.
ServeFromHosts()2189   bool ServeFromHosts() {
2190     DCHECK_GT(num_active_requests(), 0u);
2191     absl::optional<HostCache::Entry> results = resolver_->ServeFromHosts(
2192         GetHostname(key_.host), key_.query_types,
2193         key_.flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6, tasks_);
2194     if (results) {
2195       // This will destroy the Job.
2196       CompleteRequests(results.value(), base::TimeDelta(),
2197                        true /* allow_cache */, true /* secure */,
2198                        TaskType::HOSTS);
2199       return true;
2200     }
2201     return false;
2202   }
2203 
OnAddedToJobMap(JobMap::iterator iterator)2204   void OnAddedToJobMap(JobMap::iterator iterator) {
2205     DCHECK(!self_iterator_);
2206     DCHECK(iterator != resolver_->jobs_.end());
2207     self_iterator_ = iterator;
2208   }
2209 
OnRemovedFromJobMap()2210   void OnRemovedFromJobMap() {
2211     DCHECK(self_iterator_);
2212     self_iterator_ = absl::nullopt;
2213   }
2214 
RunNextTask()2215   void RunNextTask() {
2216     // If there are no tasks left to try, cache any stored results and complete
2217     // the request with the last stored result. All stored results should be
2218     // errors.
2219     if (tasks_.empty()) {
2220       // If there are no stored results, complete with an error.
2221       if (completion_results_.size() == 0) {
2222         CompleteRequestsWithError(ERR_NAME_NOT_RESOLVED,
2223                                   /*task_type=*/absl::nullopt);
2224         return;
2225       }
2226 
2227       // Cache all but the last result here. The last result will be cached
2228       // as part of CompleteRequests.
2229       for (size_t i = 0; i < completion_results_.size() - 1; ++i) {
2230         const auto& result = completion_results_[i];
2231         DCHECK_NE(OK, result.entry.error());
2232         MaybeCacheResult(result.entry, result.ttl, result.secure);
2233       }
2234       const auto& last_result = completion_results_.back();
2235       DCHECK_NE(OK, last_result.entry.error());
2236       CompleteRequests(
2237           last_result.entry, last_result.ttl, true /* allow_cache */,
2238           last_result.secure,
2239           last_result.secure ? TaskType::SECURE_DNS : TaskType::DNS);
2240       return;
2241     }
2242 
2243     TaskType next_task = tasks_.front();
2244 
2245     // Schedule insecure DnsTasks and HostResolverSystemTasks with the
2246     // dispatcher.
2247     if (!dispatched_ &&
2248         (next_task == TaskType::DNS || next_task == TaskType::SYSTEM ||
2249          next_task == TaskType::MDNS)) {
2250       dispatched_ = true;
2251       job_running_ = false;
2252       Schedule(false);
2253       DCHECK(is_running() || is_queued());
2254 
2255       // Check for queue overflow.
2256       PrioritizedDispatcher& dispatcher = *resolver_->dispatcher_;
2257       if (dispatcher.num_queued_jobs() > resolver_->max_queued_jobs_) {
2258         Job* evicted = static_cast<Job*>(dispatcher.EvictOldestLowest());
2259         DCHECK(evicted);
2260         evicted->OnEvicted();
2261       }
2262       return;
2263     }
2264 
2265     if (start_time_ == base::TimeTicks()) {
2266       net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_JOB_STARTED);
2267       start_time_ = tick_clock_->NowTicks();
2268     }
2269     tasks_.pop_front();
2270     job_running_ = true;
2271 
2272     switch (next_task) {
2273       case TaskType::SYSTEM:
2274         StartSystemTask();
2275         break;
2276       case TaskType::DNS:
2277         StartDnsTask(false /* secure */);
2278         break;
2279       case TaskType::SECURE_DNS:
2280         StartDnsTask(true /* secure */);
2281         break;
2282       case TaskType::MDNS:
2283         StartMdnsTask();
2284         break;
2285       case TaskType::INSECURE_CACHE_LOOKUP:
2286         InsecureCacheLookup();
2287         break;
2288       case TaskType::NAT64:
2289         StartNat64Task();
2290         break;
2291       case TaskType::SECURE_CACHE_LOOKUP:
2292       case TaskType::CACHE_LOOKUP:
2293       case TaskType::CONFIG_PRESET:
2294       case TaskType::HOSTS:
2295         // These task types should have been handled synchronously in
2296         // ResolveLocally() prior to Job creation.
2297         NOTREACHED();
2298         break;
2299     }
2300   }
2301 
key() const2302   const JobKey& key() const { return key_; }
2303 
is_queued() const2304   bool is_queued() const { return !handle_.is_null(); }
2305 
is_running() const2306   bool is_running() const { return job_running_; }
2307 
HasTargetNetwork() const2308   bool HasTargetNetwork() const {
2309     return key_.GetTargetNetwork() != handles::kInvalidNetworkHandle;
2310   }
2311 
2312  private:
NetLogJobCreationParams(const NetLogSource & source)2313   base::Value::Dict NetLogJobCreationParams(const NetLogSource& source) {
2314     base::Value::Dict dict;
2315     source.AddToEventParameters(dict);
2316     dict.Set("host", ToLogStringValue(key_.host));
2317     base::Value::List query_types_list;
2318     for (DnsQueryType query_type : key_.query_types)
2319       query_types_list.Append(kDnsQueryTypes.at(query_type));
2320     dict.Set("dns_query_types", std::move(query_types_list));
2321     dict.Set("secure_dns_mode", base::strict_cast<int>(key_.secure_dns_mode));
2322     dict.Set("network_anonymization_key",
2323              key_.network_anonymization_key.ToDebugString());
2324     return dict;
2325   }
2326 
Finish()2327   void Finish() {
2328     if (is_running()) {
2329       // Clean up but don't run any callbacks.
2330       system_task_ = nullptr;
2331       KillDnsTask();
2332       mdns_task_ = nullptr;
2333       job_running_ = false;
2334 
2335       if (dispatched_) {
2336         // Job should only ever occupy one slot after any tasks that may have
2337         // required additional slots, e.g. DnsTask, have been killed, and
2338         // additional slots are expected to be vacated as part of killing the
2339         // task.
2340         DCHECK_EQ(1, num_occupied_job_slots_);
2341         if (resolver_)
2342           resolver_->dispatcher_->OnJobFinished();
2343         num_occupied_job_slots_ = 0;
2344       }
2345     } else if (is_queued()) {
2346       DCHECK(dispatched_);
2347       if (resolver_)
2348         resolver_->dispatcher_->Cancel(handle_);
2349       handle_.Reset();
2350     }
2351   }
2352 
KillDnsTask()2353   void KillDnsTask() {
2354     if (dns_task_) {
2355       if (dispatched_) {
2356         while (num_occupied_job_slots_ > 1 || is_queued()) {
2357           ReduceByOneJobSlot();
2358         }
2359       }
2360       dns_task_.reset();
2361     }
2362   }
2363 
2364   // Reduce the number of job slots occupied and queued in the dispatcher by
2365   // one. If the next Job slot is queued in the dispatcher, cancels the queued
2366   // job. Otherwise, the next Job has been started by the PrioritizedDispatcher,
2367   // so signals it is complete.
ReduceByOneJobSlot()2368   void ReduceByOneJobSlot() {
2369     DCHECK_GE(num_occupied_job_slots_, 1);
2370     DCHECK(dispatched_);
2371     if (is_queued()) {
2372       if (resolver_)
2373         resolver_->dispatcher_->Cancel(handle_);
2374       handle_.Reset();
2375     } else if (num_occupied_job_slots_ > 1) {
2376       if (resolver_)
2377         resolver_->dispatcher_->OnJobFinished();
2378       --num_occupied_job_slots_;
2379     } else {
2380       NOTREACHED();
2381     }
2382   }
2383 
UpdatePriority()2384   void UpdatePriority() {
2385     if (is_queued())
2386       handle_ = resolver_->dispatcher_->ChangePriority(handle_, priority());
2387   }
2388 
2389   // PrioritizedDispatcher::Job:
Start()2390   void Start() override {
2391     handle_.Reset();
2392     ++num_occupied_job_slots_;
2393 
2394     if (num_occupied_job_slots_ >= 2) {
2395       if (!dns_task_) {
2396         resolver_->dispatcher_->OnJobFinished();
2397         return;
2398       }
2399       StartNextDnsTransaction();
2400       DCHECK_EQ(num_occupied_job_slots_,
2401                 dns_task_->num_transactions_in_progress());
2402       if (dns_task_->num_additional_transactions_needed() >= 1) {
2403         Schedule(true);
2404       }
2405       return;
2406     }
2407 
2408     DCHECK(!is_running());
2409     DCHECK(!tasks_.empty());
2410     RunNextTask();
2411     // Caution: Job::Start must not complete synchronously.
2412   }
2413 
2414   // TODO(szym): Since DnsTransaction does not consume threads, we can increase
2415   // the limits on |dispatcher_|. But in order to keep the number of
2416   // ThreadPool threads low, we will need to use an "inner"
2417   // PrioritizedDispatcher with tighter limits.
StartSystemTask()2418   void StartSystemTask() {
2419     DCHECK(dispatched_);
2420     DCHECK_EQ(1, num_occupied_job_slots_);
2421     DCHECK(HasAddressType(key_.query_types));
2422 
2423     system_task_ = HostResolverSystemTask::Create(
2424         std::string(GetHostname(key_.host)),
2425         HostResolver::DnsQueryTypeSetToAddressFamily(key_.query_types),
2426         key_.flags, resolver_->host_resolver_system_params_, net_log_,
2427         key_.GetTargetNetwork());
2428 
2429     // Start() could be called from within Resolve(), hence it must NOT directly
2430     // call OnSystemTaskComplete, for example, on synchronous failure.
2431     system_task_->Start(base::BindOnce(&Job::OnSystemTaskComplete,
2432                                        base::Unretained(this),
2433                                        tick_clock_->NowTicks()));
2434   }
2435 
2436   // Called by HostResolverSystemTask when it completes.
OnSystemTaskComplete(base::TimeTicks start_time,const AddressList & addr_list,int,int net_error)2437   void OnSystemTaskComplete(base::TimeTicks start_time,
2438                             const AddressList& addr_list,
2439                             int /*os_error*/,
2440                             int net_error) {
2441     DCHECK(system_task_);
2442 
2443     base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
2444     if (net_error == OK)
2445       UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.SystemTask.SuccessTime", duration);
2446     else
2447       UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.SystemTask.FailureTime", duration);
2448 
2449     if (dns_task_error_ != OK && net_error == OK) {
2450       // This HostResolverSystemTask was a fallback resolution after a failed
2451       // insecure DnsTask.
2452       resolver_->OnFallbackResolve(dns_task_error_);
2453     }
2454 
2455     if (ContainsIcannNameCollisionIp(addr_list.endpoints()))
2456       net_error = ERR_ICANN_NAME_COLLISION;
2457 
2458     base::TimeDelta ttl = base::Seconds(kNegativeCacheEntryTTLSeconds);
2459     if (net_error == OK)
2460       ttl = base::Seconds(kCacheEntryTTLSeconds);
2461 
2462     auto aliases = std::set<std::string>(addr_list.dns_aliases().begin(),
2463                                          addr_list.dns_aliases().end());
2464 
2465     // Source unknown because the system resolver could have gotten it from a
2466     // hosts file, its own cache, a DNS lookup or somewhere else.
2467     // Don't store the |ttl| in cache since it's not obtained from the server.
2468     CompleteRequests(
2469         HostCache::Entry(
2470             net_error,
2471             net_error == OK ? addr_list.endpoints() : std::vector<IPEndPoint>(),
2472             std::move(aliases), HostCache::Entry::SOURCE_UNKNOWN),
2473         ttl, /*allow_cache=*/true, /*secure=*/false, TaskType::SYSTEM);
2474   }
2475 
InsecureCacheLookup()2476   void InsecureCacheLookup() {
2477     // Insecure cache lookups for requests allowing stale results should have
2478     // occurred prior to Job creation.
2479     DCHECK(cache_usage_ != ResolveHostParameters::CacheUsage::STALE_ALLOWED);
2480     absl::optional<HostCache::EntryStaleness> stale_info;
2481     absl::optional<HostCache::Entry> resolved = resolver_->MaybeServeFromCache(
2482         host_cache_, key_.ToCacheKey(/*secure=*/false), cache_usage_,
2483         false /* ignore_secure */, net_log_, &stale_info);
2484 
2485     if (resolved) {
2486       DCHECK(stale_info);
2487       DCHECK(!stale_info.value().is_stale());
2488       CompleteRequestsWithoutCache(resolved.value(), std::move(stale_info),
2489                                    TaskType::INSECURE_CACHE_LOOKUP);
2490     } else {
2491       RunNextTask();
2492     }
2493   }
2494 
StartDnsTask(bool secure)2495   void StartDnsTask(bool secure) {
2496     DCHECK_EQ(secure, !dispatched_);
2497     DCHECK_EQ(dispatched_ ? 1 : 0, num_occupied_job_slots_);
2498     DCHECK(!resolver_->ShouldForceSystemResolverDueToTestOverride());
2499     // Need to create the task even if we're going to post a failure instead of
2500     // running it, as a "started" job needs a task to be properly cleaned up.
2501     dns_task_ = std::make_unique<DnsTask>(
2502         resolver_->dns_client_.get(), key_.host, key_.query_types,
2503         &*key_.resolve_context, secure, key_.secure_dns_mode, this, net_log_,
2504         tick_clock_, !tasks_.empty() /* fallback_available */,
2505         https_svcb_options_);
2506     dns_task_->StartNextTransaction();
2507     // Schedule a second transaction, if needed. DoH queries can bypass the
2508     // dispatcher and start all of their transactions immediately.
2509     if (secure) {
2510       while (dns_task_->num_additional_transactions_needed() >= 1)
2511         dns_task_->StartNextTransaction();
2512       DCHECK_EQ(dns_task_->num_additional_transactions_needed(), 0);
2513     } else if (dns_task_->num_additional_transactions_needed() >= 1) {
2514       Schedule(true);
2515     }
2516   }
2517 
StartNextDnsTransaction()2518   void StartNextDnsTransaction() {
2519     DCHECK(dns_task_);
2520     DCHECK_EQ(dns_task_->secure(), !dispatched_);
2521     DCHECK(!dispatched_ || num_occupied_job_slots_ ==
2522                                dns_task_->num_transactions_in_progress() + 1);
2523     DCHECK_GE(dns_task_->num_additional_transactions_needed(), 1);
2524     dns_task_->StartNextTransaction();
2525   }
2526 
2527   // Called if DnsTask fails. It is posted from StartDnsTask, so Job may be
2528   // deleted before this callback. In this case dns_task is deleted as well,
2529   // so we use it as indicator whether Job is still valid.
OnDnsTaskFailure(const base::WeakPtr<DnsTask> & dns_task,base::TimeDelta duration,bool allow_fallback,const HostCache::Entry & failure_results,bool secure)2530   void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task,
2531                         base::TimeDelta duration,
2532                         bool allow_fallback,
2533                         const HostCache::Entry& failure_results,
2534                         bool secure) {
2535     DCHECK_NE(OK, failure_results.error());
2536 
2537     if (key_.secure_dns_mode == SecureDnsMode::kSecure) {
2538       DCHECK(secure);
2539       UMA_HISTOGRAM_LONG_TIMES_100(
2540           "Net.DNS.SecureDnsTask.DnsModeSecure.FailureTime", duration);
2541     } else if (key_.secure_dns_mode == SecureDnsMode::kAutomatic && secure) {
2542       UMA_HISTOGRAM_LONG_TIMES_100(
2543           "Net.DNS.SecureDnsTask.DnsModeAutomatic.FailureTime", duration);
2544     } else {
2545       UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.InsecureDnsTask.FailureTime",
2546                                    duration);
2547     }
2548 
2549     if (!dns_task)
2550       return;
2551 
2552     UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.JobQueueTime.Failure",
2553                                  total_transaction_time_queued_);
2554 
2555     // If one of the fallback tasks doesn't complete the request, store a result
2556     // to use during request completion.
2557     base::TimeDelta ttl =
2558         failure_results.has_ttl() ? failure_results.ttl() : base::Seconds(0);
2559     completion_results_.push_back({failure_results, ttl, secure});
2560 
2561     dns_task_error_ = failure_results.error();
2562     KillDnsTask();
2563 
2564     if (!allow_fallback)
2565       tasks_.clear();
2566 
2567     RunNextTask();
2568   }
2569 
2570   // HostResolverManager::DnsTask::Delegate implementation:
2571 
OnDnsTaskComplete(base::TimeTicks start_time,bool allow_fallback,HostCache::Entry results,bool secure)2572   void OnDnsTaskComplete(base::TimeTicks start_time,
2573                          bool allow_fallback,
2574                          HostCache::Entry results,
2575                          bool secure) override {
2576     DCHECK(dns_task_);
2577 
2578     // Tasks containing address queries are only considered successful overall
2579     // if they find address results. However, DnsTask may claim success if any
2580     // transaction, e.g. a supplemental HTTPS transaction, finds results.
2581     DCHECK(!key_.query_types.Has(DnsQueryType::UNSPECIFIED));
2582     if (HasAddressType(key_.query_types) && results.error() == OK &&
2583         (!results.ip_endpoints() || results.ip_endpoints()->empty())) {
2584       results.set_error(ERR_NAME_NOT_RESOLVED);
2585     }
2586 
2587     base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
2588     if (results.error() != OK) {
2589       OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, allow_fallback,
2590                        results, secure);
2591       return;
2592     }
2593 
2594     UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.SuccessTime", duration);
2595 
2596     UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.JobQueueTime.Success",
2597                                  total_transaction_time_queued_);
2598 
2599     // Reset the insecure DNS failure counter if an insecure DnsTask completed
2600     // successfully.
2601     if (!secure)
2602       resolver_->dns_client_->ClearInsecureFallbackFailures();
2603 
2604     base::TimeDelta bounded_ttl =
2605         std::max(results.ttl(), base::Seconds(kMinimumTTLSeconds));
2606 
2607     if ((results.ip_endpoints() &&
2608          ContainsIcannNameCollisionIp(*results.ip_endpoints()))) {
2609       CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION,
2610                                 secure ? TaskType::SECURE_DNS : TaskType::DNS);
2611       return;
2612     }
2613 
2614     CompleteRequests(results, bounded_ttl, true /* allow_cache */, secure,
2615                      secure ? TaskType::SECURE_DNS : TaskType::DNS);
2616   }
2617 
OnIntermediateTransactionsComplete()2618   void OnIntermediateTransactionsComplete() override {
2619     if (dispatched_) {
2620       DCHECK_GE(num_occupied_job_slots_,
2621                 dns_task_->num_transactions_in_progress());
2622       int unused_slots =
2623           num_occupied_job_slots_ - dns_task_->num_transactions_in_progress();
2624 
2625       // Reuse vacated slots for any remaining transactions.
2626       while (unused_slots > 0 &&
2627              dns_task_->num_additional_transactions_needed() > 0) {
2628         dns_task_->StartNextTransaction();
2629         --unused_slots;
2630       }
2631 
2632       // If all remaining transactions found a slot, no more needed from the
2633       // dispatcher.
2634       if (is_queued() && dns_task_->num_additional_transactions_needed() == 0) {
2635         resolver_->dispatcher_->Cancel(handle_);
2636         handle_.Reset();
2637       }
2638 
2639       // Relinquish any remaining extra slots.
2640       while (unused_slots > 0) {
2641         ReduceByOneJobSlot();
2642         --unused_slots;
2643       }
2644     } else if (dns_task_->num_additional_transactions_needed() >= 1) {
2645       dns_task_->StartNextTransaction();
2646     }
2647   }
2648 
AddTransactionTimeQueued(base::TimeDelta time_queued)2649   void AddTransactionTimeQueued(base::TimeDelta time_queued) override {
2650     total_transaction_time_queued_ += time_queued;
2651   }
2652 
StartMdnsTask()2653   void StartMdnsTask() {
2654     // No flags are supported for MDNS except
2655     // HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6 (which is not actually an
2656     // input flag).
2657     DCHECK_EQ(0, key_.flags & ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6);
2658 
2659     MDnsClient* client = nullptr;
2660     int rv = resolver_->GetOrCreateMdnsClient(&client);
2661     mdns_task_ = std::make_unique<HostResolverMdnsTask>(
2662         client, std::string{GetHostname(key_.host)}, key_.query_types);
2663 
2664     if (rv == OK) {
2665       mdns_task_->Start(
2666           base::BindOnce(&Job::OnMdnsTaskComplete, base::Unretained(this)));
2667     } else {
2668       // Could not create an mDNS client. Since we cannot complete synchronously
2669       // from here, post a failure without starting the task.
2670       base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
2671           FROM_HERE, base::BindOnce(&Job::OnMdnsImmediateFailure,
2672                                     weak_ptr_factory_.GetWeakPtr(), rv));
2673     }
2674   }
2675 
OnMdnsTaskComplete()2676   void OnMdnsTaskComplete() {
2677     DCHECK(mdns_task_);
2678     // TODO(crbug.com/846423): Consider adding MDNS-specific logging.
2679 
2680     HostCache::Entry results = mdns_task_->GetResults();
2681 
2682     if ((results.ip_endpoints() &&
2683          ContainsIcannNameCollisionIp(*results.ip_endpoints()))) {
2684       CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION, TaskType::MDNS);
2685       return;
2686     }
2687     // MDNS uses a separate cache, so skip saving result to cache.
2688     // TODO(crbug.com/926300): Consider merging caches.
2689     CompleteRequestsWithoutCache(results, absl::nullopt /* stale_info */,
2690                                  TaskType::MDNS);
2691   }
2692 
OnMdnsImmediateFailure(int rv)2693   void OnMdnsImmediateFailure(int rv) {
2694     DCHECK(mdns_task_);
2695     DCHECK_NE(OK, rv);
2696 
2697     CompleteRequestsWithError(rv, TaskType::MDNS);
2698   }
2699 
StartNat64Task()2700   void StartNat64Task() {
2701     DCHECK(!nat64_task_);
2702     RequestImpl* req = requests_.head()->value();
2703     nat64_task_ = std::make_unique<HostResolverNat64Task>(
2704         std::string{GetHostname(key_.host)}, req->network_anonymization_key(),
2705         req->source_net_log(), req->resolve_context(), req->host_cache(),
2706         resolver_);
2707     nat64_task_->Start(base::BindOnce(&Job::OnNat64TaskComplete,
2708                                       weak_ptr_factory_.GetWeakPtr()));
2709   }
2710 
OnNat64TaskComplete()2711   void OnNat64TaskComplete() {
2712     DCHECK(nat64_task_);
2713     HostCache::Entry results = nat64_task_->GetResults();
2714     CompleteRequestsWithoutCache(results, absl::nullopt /* stale_info */,
2715                                  TaskType::NAT64);
2716   }
2717 
RecordJobHistograms(const HostCache::Entry & results,absl::optional<TaskType> task_type)2718   void RecordJobHistograms(const HostCache::Entry& results,
2719                            absl::optional<TaskType> task_type) {
2720     int error = results.error();
2721     // Used in UMA_HISTOGRAM_ENUMERATION. Do not renumber entries or reuse
2722     // deprecated values.
2723     enum Category {
2724       RESOLVE_SUCCESS = 0,
2725       RESOLVE_FAIL = 1,
2726       RESOLVE_SPECULATIVE_SUCCESS = 2,
2727       RESOLVE_SPECULATIVE_FAIL = 3,
2728       RESOLVE_ABORT = 4,
2729       RESOLVE_SPECULATIVE_ABORT = 5,
2730       RESOLVE_MAX,  // Bounding value.
2731     };
2732     Category category = RESOLVE_MAX;  // Illegal value for later DCHECK only.
2733 
2734     base::TimeDelta duration = tick_clock_->NowTicks() - start_time_;
2735     if (error == OK) {
2736       if (had_non_speculative_request_) {
2737         category = RESOLVE_SUCCESS;
2738         UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime", duration);
2739       } else {
2740         category = RESOLVE_SPECULATIVE_SUCCESS;
2741       }
2742     } else if (error == ERR_NETWORK_CHANGED ||
2743                error == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) {
2744       category = had_non_speculative_request_ ? RESOLVE_ABORT
2745                                               : RESOLVE_SPECULATIVE_ABORT;
2746     } else {
2747       if (had_non_speculative_request_) {
2748         category = RESOLVE_FAIL;
2749         UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime", duration);
2750       } else {
2751         category = RESOLVE_SPECULATIVE_FAIL;
2752       }
2753     }
2754     DCHECK_LT(static_cast<int>(category),
2755               static_cast<int>(RESOLVE_MAX));  // Be sure it was set.
2756     UMA_HISTOGRAM_ENUMERATION("Net.DNS.ResolveCategory", category, RESOLVE_MAX);
2757 
2758     if (category == RESOLVE_FAIL ||
2759         (start_time_ != base::TimeTicks() && category == RESOLVE_ABORT)) {
2760       if (duration < base::Milliseconds(10))
2761         base::UmaHistogramSparse("Net.DNS.ResolveError.Fast", std::abs(error));
2762       else
2763         base::UmaHistogramSparse("Net.DNS.ResolveError.Slow", std::abs(error));
2764     }
2765 
2766     if (had_non_speculative_request_) {
2767       UmaHistogramMediumTimes(
2768           base::StringPrintf(
2769               "Net.DNS.SecureDnsMode.%s.ResolveTime",
2770               SecureDnsModeToString(key_.secure_dns_mode).c_str()),
2771           duration);
2772     }
2773 
2774     if (error == OK) {
2775       DCHECK(task_type.has_value());
2776       // Record, for HTTPS-capable queries to a host known to serve HTTPS
2777       // records, whether the HTTPS record was successfully received.
2778       if (key_.query_types.Has(DnsQueryType::HTTPS) &&
2779           // Skip http- and ws-schemed hosts. Although they query HTTPS records,
2780           // successful queries are reported as errors, which would skew the
2781           // metrics.
2782           (GetScheme(key_.host) == url::kHttpsScheme ||
2783            GetScheme(key_.host) == url::kWssScheme) &&
2784           IsGoogleHostWithAlpnH3(GetHostname(key_.host))) {
2785         bool has_metadata =
2786             results.GetMetadatas() && !results.GetMetadatas()->empty();
2787         base::UmaHistogramExactLinear(
2788             "Net.DNS.H3SupportedGoogleHost.TaskTypeMetadataAvailability2",
2789             static_cast<int>(task_type.value()) * 2 + (has_metadata ? 1 : 0),
2790             (static_cast<int>(TaskType::kMaxValue) + 1) * 2);
2791       }
2792     }
2793   }
2794 
MaybeCacheResult(const HostCache::Entry & results,base::TimeDelta ttl,bool secure)2795   void MaybeCacheResult(const HostCache::Entry& results,
2796                         base::TimeDelta ttl,
2797                         bool secure) {
2798     // If the request did not complete, don't cache it.
2799     if (!results.did_complete())
2800       return;
2801     resolver_->CacheResult(host_cache_, key_.ToCacheKey(secure), results, ttl);
2802   }
2803 
2804   // Performs Job's last rites. Completes all Requests. Deletes this.
2805   //
2806   // If not |allow_cache|, result will not be stored in the host cache, even if
2807   // result would otherwise allow doing so. Update the key to reflect |secure|,
2808   // which indicates whether or not the result was obtained securely.
CompleteRequests(const HostCache::Entry & results,base::TimeDelta ttl,bool allow_cache,bool secure,absl::optional<TaskType> task_type)2809   void CompleteRequests(const HostCache::Entry& results,
2810                         base::TimeDelta ttl,
2811                         bool allow_cache,
2812                         bool secure,
2813                         absl::optional<TaskType> task_type) {
2814     CHECK(resolver_.get());
2815 
2816     // This job must be removed from resolver's |jobs_| now to make room for a
2817     // new job with the same key in case one of the OnComplete callbacks decides
2818     // to spawn one. Consequently, if the job was owned by |jobs_|, the job
2819     // deletes itself when CompleteRequests is done.
2820     std::unique_ptr<Job> self_deleter;
2821     if (self_iterator_)
2822       self_deleter = resolver_->RemoveJob(self_iterator_.value());
2823 
2824     Finish();
2825 
2826     if (results.error() == ERR_DNS_REQUEST_CANCELLED) {
2827       net_log_.AddEvent(NetLogEventType::CANCELLED);
2828       net_log_.EndEventWithNetErrorCode(
2829           NetLogEventType::HOST_RESOLVER_MANAGER_JOB, OK);
2830       return;
2831     }
2832 
2833     net_log_.EndEventWithNetErrorCode(
2834         NetLogEventType::HOST_RESOLVER_MANAGER_JOB, results.error());
2835 
2836     // Handle all caching before completing requests as completing requests may
2837     // start new requests that rely on cached results.
2838     if (allow_cache)
2839       MaybeCacheResult(results, ttl, secure);
2840 
2841     RecordJobHistograms(results, task_type);
2842 
2843     // Complete all of the requests that were attached to the job and
2844     // detach them.
2845     while (!requests_.empty()) {
2846       RequestImpl* req = requests_.head()->value();
2847       req->RemoveFromList();
2848       CHECK(key_ == req->GetJobKey());
2849 
2850       if (results.error() == OK && !req->parameters().is_speculative) {
2851         req->set_results(
2852             results.CopyWithDefaultPort(req->request_host().GetPort()));
2853       }
2854       req->OnJobCompleted(
2855           key_, results.error(),
2856           /*is_secure_network_error=*/secure && results.error() != OK);
2857 
2858       // Check if the resolver was destroyed as a result of running the
2859       // callback. If it was, we could continue, but we choose to bail.
2860       if (!resolver_.get())
2861         return;
2862     }
2863 
2864     // TODO(crbug.com/1200908): Call StartBootstrapFollowup() if any of the
2865     // requests have the Bootstrap policy.  Note: A naive implementation could
2866     // cause an infinite loop if the bootstrap result has TTL=0.
2867   }
2868 
CompleteRequestsWithoutCache(const HostCache::Entry & results,absl::optional<HostCache::EntryStaleness> stale_info,TaskType task_type)2869   void CompleteRequestsWithoutCache(
2870       const HostCache::Entry& results,
2871       absl::optional<HostCache::EntryStaleness> stale_info,
2872       TaskType task_type) {
2873     // Record the stale_info for all non-speculative requests, if it exists.
2874     if (stale_info) {
2875       for (auto* node = requests_.head(); node != requests_.end();
2876            node = node->next()) {
2877         if (!node->value()->parameters().is_speculative)
2878           node->value()->set_stale_info(stale_info.value());
2879       }
2880     }
2881     CompleteRequests(results, base::TimeDelta(), false /* allow_cache */,
2882                      false /* secure */, task_type);
2883   }
2884 
2885   // Convenience wrapper for CompleteRequests in case of failure.
CompleteRequestsWithError(int net_error,absl::optional<TaskType> task_type)2886   void CompleteRequestsWithError(int net_error,
2887                                  absl::optional<TaskType> task_type) {
2888     DCHECK_NE(OK, net_error);
2889     CompleteRequests(
2890         HostCache::Entry(net_error, HostCache::Entry::SOURCE_UNKNOWN),
2891         base::TimeDelta(), true /* allow_cache */, false /* secure */,
2892         task_type);
2893   }
2894 
priority() const2895   RequestPriority priority() const override {
2896     return priority_tracker_.highest_priority();
2897   }
2898 
2899   // Number of non-canceled requests in |requests_|.
num_active_requests() const2900   size_t num_active_requests() const { return priority_tracker_.total_count(); }
2901 
2902   base::WeakPtr<HostResolverManager> resolver_;
2903 
2904   const JobKey key_;
2905   const ResolveHostParameters::CacheUsage cache_usage_;
2906   // TODO(crbug.com/969847): Consider allowing requests within a single Job to
2907   // have different HostCaches.
2908   const raw_ptr<HostCache> host_cache_;
2909 
2910   struct CompletionResult {
2911     const HostCache::Entry entry;
2912     base::TimeDelta ttl;
2913     bool secure;
2914   };
2915 
2916   // Results to use in last-ditch attempt to complete request.
2917   std::vector<CompletionResult> completion_results_;
2918 
2919   // The sequence of tasks to run in this Job. Tasks may be aborted and removed
2920   // from the sequence, but otherwise the tasks will run in order until a
2921   // successful result is found.
2922   std::deque<TaskType> tasks_;
2923 
2924   // Whether the job is running.
2925   bool job_running_ = false;
2926 
2927   // Tracks the highest priority across |requests_|.
2928   PriorityTracker priority_tracker_;
2929 
2930   bool had_non_speculative_request_ = false;
2931 
2932   // Number of slots occupied by this Job in |dispatcher_|. Should be 0 when
2933   // the job is not registered with any dispatcher.
2934   int num_occupied_job_slots_ = 0;
2935 
2936   // True once this Job has been sent to `resolver_->dispatcher_`.
2937   bool dispatched_ = false;
2938 
2939   // Result of DnsTask.
2940   int dns_task_error_ = OK;
2941 
2942   raw_ptr<const base::TickClock> tick_clock_;
2943   base::TimeTicks start_time_;
2944 
2945   HostResolver::HttpsSvcbOptions https_svcb_options_;
2946 
2947   NetLogWithSource net_log_;
2948 
2949   // Resolves the host using the system DNS resolver, which can be overridden
2950   // for tests.
2951   std::unique_ptr<HostResolverSystemTask> system_task_;
2952 
2953   // Resolves the host using a DnsTransaction.
2954   std::unique_ptr<DnsTask> dns_task_;
2955 
2956   // Resolves the host using MDnsClient.
2957   std::unique_ptr<HostResolverMdnsTask> mdns_task_;
2958 
2959   // Perform NAT64 address synthesis to a given IPv4 literal.
2960   std::unique_ptr<HostResolverNat64Task> nat64_task_;
2961 
2962   // All Requests waiting for the result of this Job. Some can be canceled.
2963   base::LinkedList<RequestImpl> requests_;
2964 
2965   // A handle used for |dispatcher_|.
2966   PrioritizedDispatcher::Handle handle_;
2967 
2968   // Iterator to |this| in the JobMap. |nullopt| if not owned by the JobMap.
2969   absl::optional<JobMap::iterator> self_iterator_;
2970 
2971   base::TimeDelta total_transaction_time_queued_;
2972 
2973   base::WeakPtrFactory<Job> weak_ptr_factory_{this};
2974 };
2975 
2976 //-----------------------------------------------------------------------------
2977 
HostResolverManager(const HostResolver::ManagerOptions & options,SystemDnsConfigChangeNotifier * system_dns_config_notifier,NetLog * net_log)2978 HostResolverManager::HostResolverManager(
2979     const HostResolver::ManagerOptions& options,
2980     SystemDnsConfigChangeNotifier* system_dns_config_notifier,
2981     NetLog* net_log)
2982     : HostResolverManager(PassKey(),
2983                           options,
2984                           system_dns_config_notifier,
2985                           handles::kInvalidNetworkHandle,
2986                           net_log) {}
2987 
HostResolverManager(base::PassKey<HostResolverManager>,const HostResolver::ManagerOptions & options,SystemDnsConfigChangeNotifier * system_dns_config_notifier,handles::NetworkHandle target_network,NetLog * net_log)2988 HostResolverManager::HostResolverManager(
2989     base::PassKey<HostResolverManager>,
2990     const HostResolver::ManagerOptions& options,
2991     SystemDnsConfigChangeNotifier* system_dns_config_notifier,
2992     handles::NetworkHandle target_network,
2993     NetLog* net_log)
2994     : host_resolver_system_params_(nullptr, options.max_system_retry_attempts),
2995       net_log_(net_log),
2996       system_dns_config_notifier_(system_dns_config_notifier),
2997       target_network_(target_network),
2998       check_ipv6_on_wifi_(options.check_ipv6_on_wifi),
2999       tick_clock_(base::DefaultTickClock::GetInstance()),
3000       https_svcb_options_(
3001           options.https_svcb_options
3002               ? *options.https_svcb_options
3003               : HostResolver::HttpsSvcbOptions::FromFeatures()) {
3004   PrioritizedDispatcher::Limits job_limits = GetDispatcherLimits(options);
3005   dispatcher_ = std::make_unique<PrioritizedDispatcher>(job_limits);
3006   max_queued_jobs_ = job_limits.total_jobs * 100u;
3007 
3008   DCHECK_GE(dispatcher_->num_priorities(), static_cast<size_t>(NUM_PRIORITIES));
3009 
3010 #if BUILDFLAG(IS_WIN)
3011   EnsureWinsockInit();
3012 #endif
3013 #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)) || \
3014     BUILDFLAG(IS_FUCHSIA)
3015   RunLoopbackProbeJob();
3016 #endif
3017   // Network-bound HostResolverManagers don't need to act on network changes.
3018   if (!IsBoundToNetwork()) {
3019     NetworkChangeNotifier::AddIPAddressObserver(this);
3020     NetworkChangeNotifier::AddConnectionTypeObserver(this);
3021   }
3022   if (system_dns_config_notifier_)
3023     system_dns_config_notifier_->AddObserver(this);
3024   EnsureSystemHostResolverCallReady();
3025 
3026   auto connection_type =
3027       IsBoundToNetwork()
3028           ? NetworkChangeNotifier::GetNetworkConnectionType(target_network)
3029           : NetworkChangeNotifier::GetConnectionType();
3030   UpdateConnectionType(connection_type);
3031 
3032 #if defined(ENABLE_BUILT_IN_DNS)
3033   dns_client_ = DnsClient::CreateClient(net_log_);
3034   dns_client_->SetInsecureEnabled(
3035       options.insecure_dns_client_enabled,
3036       options.additional_types_via_insecure_dns_enabled);
3037   dns_client_->SetConfigOverrides(options.dns_config_overrides);
3038 #else
3039   DCHECK(options.dns_config_overrides == DnsConfigOverrides());
3040 #endif
3041 
3042   allow_fallback_to_systemtask_ = !ConfigureAsyncDnsNoFallbackFieldTrial();
3043 }
3044 
~HostResolverManager()3045 HostResolverManager::~HostResolverManager() {
3046   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3047   // Prevent the dispatcher from starting new jobs.
3048   dispatcher_->SetLimitsToZero();
3049   // It's now safe for Jobs to call KillDnsTask on destruction, because
3050   // OnJobComplete will not start any new jobs.
3051   jobs_.clear();
3052 
3053   if (target_network_ == handles::kInvalidNetworkHandle) {
3054     NetworkChangeNotifier::RemoveIPAddressObserver(this);
3055     NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
3056   }
3057   if (system_dns_config_notifier_)
3058     system_dns_config_notifier_->RemoveObserver(this);
3059 }
3060 
3061 // static
3062 std::unique_ptr<HostResolverManager>
CreateNetworkBoundHostResolverManager(const HostResolver::ManagerOptions & options,handles::NetworkHandle target_network,NetLog * net_log)3063 HostResolverManager::CreateNetworkBoundHostResolverManager(
3064     const HostResolver::ManagerOptions& options,
3065     handles::NetworkHandle target_network,
3066     NetLog* net_log) {
3067 #if BUILDFLAG(IS_ANDROID)
3068   DCHECK(NetworkChangeNotifier::AreNetworkHandlesSupported());
3069   return std::make_unique<HostResolverManager>(
3070       PassKey(), options, nullptr /* system_dns_config_notifier */,
3071       target_network, net_log);
3072 #else   // !BUILDFLAG(IS_ANDROID)
3073   NOTIMPLEMENTED();
3074   return nullptr;
3075 #endif  // BUILDFLAG(IS_ANDROID)
3076 }
3077 
3078 std::unique_ptr<HostResolver::ResolveHostRequest>
CreateRequest(absl::variant<url::SchemeHostPort,HostPortPair> host,NetworkAnonymizationKey network_anonymization_key,NetLogWithSource net_log,absl::optional<ResolveHostParameters> optional_parameters,ResolveContext * resolve_context,HostCache * host_cache)3079 HostResolverManager::CreateRequest(
3080     absl::variant<url::SchemeHostPort, HostPortPair> host,
3081     NetworkAnonymizationKey network_anonymization_key,
3082     NetLogWithSource net_log,
3083     absl::optional<ResolveHostParameters> optional_parameters,
3084     ResolveContext* resolve_context,
3085     HostCache* host_cache) {
3086   return CreateRequest(HostResolver::Host(std::move(host)),
3087                        std::move(network_anonymization_key), std::move(net_log),
3088                        std::move(optional_parameters), resolve_context,
3089                        host_cache);
3090 }
3091 
3092 std::unique_ptr<HostResolver::ResolveHostRequest>
CreateRequest(HostResolver::Host host,NetworkAnonymizationKey network_anonymization_key,NetLogWithSource net_log,absl::optional<ResolveHostParameters> optional_parameters,ResolveContext * resolve_context,HostCache * host_cache)3093 HostResolverManager::CreateRequest(
3094     HostResolver::Host host,
3095     NetworkAnonymizationKey network_anonymization_key,
3096     NetLogWithSource net_log,
3097     absl::optional<ResolveHostParameters> optional_parameters,
3098     ResolveContext* resolve_context,
3099     HostCache* host_cache) {
3100   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3101   DCHECK(!invalidation_in_progress_);
3102 
3103   DCHECK_EQ(resolve_context->GetTargetNetwork(), target_network_);
3104   // ResolveContexts must register (via RegisterResolveContext()) before use to
3105   // ensure cached data is invalidated on network and configuration changes.
3106   DCHECK(registered_contexts_.HasObserver(resolve_context));
3107 
3108   return std::make_unique<RequestImpl>(
3109       std::move(net_log), std::move(host), std::move(network_anonymization_key),
3110       std::move(optional_parameters), resolve_context->GetWeakPtr(), host_cache,
3111       weak_ptr_factory_.GetWeakPtr(), tick_clock_);
3112 }
3113 
3114 std::unique_ptr<HostResolver::ProbeRequest>
CreateDohProbeRequest(ResolveContext * context)3115 HostResolverManager::CreateDohProbeRequest(ResolveContext* context) {
3116   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3117 
3118   return std::make_unique<ProbeRequestImpl>(context->GetWeakPtr(),
3119                                             weak_ptr_factory_.GetWeakPtr());
3120 }
3121 
3122 std::unique_ptr<HostResolver::MdnsListener>
CreateMdnsListener(const HostPortPair & host,DnsQueryType query_type)3123 HostResolverManager::CreateMdnsListener(const HostPortPair& host,
3124                                         DnsQueryType query_type) {
3125   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3126   DCHECK_NE(DnsQueryType::UNSPECIFIED, query_type);
3127 
3128   auto listener =
3129       std::make_unique<HostResolverMdnsListenerImpl>(host, query_type);
3130 
3131   MDnsClient* client;
3132   int rv = GetOrCreateMdnsClient(&client);
3133 
3134   if (rv == OK) {
3135     std::unique_ptr<net::MDnsListener> inner_listener = client->CreateListener(
3136         DnsQueryTypeToQtype(query_type), host.host(), listener.get());
3137     listener->set_inner_listener(std::move(inner_listener));
3138   } else {
3139     listener->set_initialization_error(rv);
3140   }
3141   return listener;
3142 }
3143 
SetInsecureDnsClientEnabled(bool enabled,bool additional_dns_types_enabled)3144 void HostResolverManager::SetInsecureDnsClientEnabled(
3145     bool enabled,
3146     bool additional_dns_types_enabled) {
3147   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3148 
3149   if (!dns_client_)
3150     return;
3151 
3152   bool enabled_before = dns_client_->CanUseInsecureDnsTransactions();
3153   bool additional_types_before =
3154       enabled_before && dns_client_->CanQueryAdditionalTypesViaInsecureDns();
3155   dns_client_->SetInsecureEnabled(enabled, additional_dns_types_enabled);
3156 
3157   // Abort current tasks if `CanUseInsecureDnsTransactions()` changes or if
3158   // insecure transactions are enabled and
3159   // `CanQueryAdditionalTypesViaInsecureDns()` changes. Changes to allowing
3160   // additional types don't matter if insecure transactions are completely
3161   // disabled.
3162   if (dns_client_->CanUseInsecureDnsTransactions() != enabled_before ||
3163       (dns_client_->CanUseInsecureDnsTransactions() &&
3164        dns_client_->CanQueryAdditionalTypesViaInsecureDns() !=
3165            additional_types_before)) {
3166     AbortInsecureDnsTasks(ERR_NETWORK_CHANGED, false /* fallback_only */);
3167   }
3168 }
3169 
GetDnsConfigAsValue() const3170 base::Value::Dict HostResolverManager::GetDnsConfigAsValue() const {
3171   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3172   return dns_client_ ? dns_client_->GetDnsConfigAsValueForNetLog()
3173                      : base::Value::Dict();
3174 }
3175 
SetDnsConfigOverrides(DnsConfigOverrides overrides)3176 void HostResolverManager::SetDnsConfigOverrides(DnsConfigOverrides overrides) {
3177   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
3178 
3179   if (!dns_client_ && overrides == DnsConfigOverrides())
3180     return;
3181 
3182   // Not allowed to set overrides if compiled without DnsClient.
3183   DCHECK(dns_client_);
3184 
3185   bool transactions_allowed_before =
3186       dns_client_->CanUseSecureDnsTransactions() ||
3187       dns_client_->CanUseInsecureDnsTransactions();
3188   bool changed = dns_client_->SetConfigOverrides(std::move(overrides));
3189 
3190   if (changed) {
3191     NetworkChangeNotifier::TriggerNonSystemDnsChange();
3192 
3193     // Only invalidate cache if new overrides have resulted in a config change.
3194     InvalidateCaches();
3195 
3196     // Need to update jobs iff transactions were previously allowed because
3197     // in-progress jobs may be running using a now-invalid configuration.
3198     if (transactions_allowed_before) {
3199       UpdateJobsForChangedConfig();
3200     }
3201   }
3202 }
3203 
RegisterResolveContext(ResolveContext * context)3204 void HostResolverManager::RegisterResolveContext(ResolveContext* context) {
3205   registered_contexts_.AddObserver(context);
3206   context->InvalidateCachesAndPerSessionData(
3207       dns_client_ ? dns_client_->GetCurrentSession() : nullptr,
3208       false /* network_change */);
3209 }
3210 
DeregisterResolveContext(const ResolveContext * context)3211 void HostResolverManager::DeregisterResolveContext(
3212     const ResolveContext* context) {
3213   registered_contexts_.RemoveObserver(context);
3214 
3215   // Destroy Jobs when their context is closed.
3216   RemoveAllJobs(context);
3217 }
3218 
SetTickClockForTesting(const base::TickClock * tick_clock)3219 void HostResolverManager::SetTickClockForTesting(
3220     const base::TickClock* tick_clock) {
3221   tick_clock_ = tick_clock;
3222 }
3223 
SetMaxQueuedJobsForTesting(size_t value)3224 void HostResolverManager::SetMaxQueuedJobsForTesting(size_t value) {
3225   DCHECK_EQ(0u, dispatcher_->num_queued_jobs());
3226   DCHECK_GE(value, 0u);
3227   max_queued_jobs_ = value;
3228 }
3229 
SetHaveOnlyLoopbackAddresses(bool result)3230 void HostResolverManager::SetHaveOnlyLoopbackAddresses(bool result) {
3231   if (result) {
3232     additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
3233   } else {
3234     additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY;
3235   }
3236 }
3237 
SetMdnsSocketFactoryForTesting(std::unique_ptr<MDnsSocketFactory> socket_factory)3238 void HostResolverManager::SetMdnsSocketFactoryForTesting(
3239     std::unique_ptr<MDnsSocketFactory> socket_factory) {
3240   DCHECK(!mdns_client_);
3241   mdns_socket_factory_ = std::move(socket_factory);
3242 }
3243 
SetMdnsClientForTesting(std::unique_ptr<MDnsClient> client)3244 void HostResolverManager::SetMdnsClientForTesting(
3245     std::unique_ptr<MDnsClient> client) {
3246   mdns_client_ = std::move(client);
3247 }
3248 
SetDnsClientForTesting(std::unique_ptr<DnsClient> dns_client)3249 void HostResolverManager::SetDnsClientForTesting(
3250     std::unique_ptr<DnsClient> dns_client) {
3251   DCHECK(dns_client);
3252   if (dns_client_) {
3253     if (!dns_client->GetSystemConfigForTesting())
3254       dns_client->SetSystemConfig(dns_client_->GetSystemConfigForTesting());
3255     dns_client->SetConfigOverrides(dns_client_->GetConfigOverridesForTesting());
3256   }
3257   dns_client_ = std::move(dns_client);
3258   // Inform `registered_contexts_` of the new `DnsClient`.
3259   InvalidateCaches();
3260 }
3261 
SetLastIPv6ProbeResultForTesting(bool last_ipv6_probe_result)3262 void HostResolverManager::SetLastIPv6ProbeResultForTesting(
3263     bool last_ipv6_probe_result) {
3264   SetLastIPv6ProbeResult(last_ipv6_probe_result);
3265 }
3266 
3267 // static
IsLocalTask(TaskType task)3268 bool HostResolverManager::IsLocalTask(TaskType task) {
3269   switch (task) {
3270     case TaskType::SECURE_CACHE_LOOKUP:
3271     case TaskType::INSECURE_CACHE_LOOKUP:
3272     case TaskType::CACHE_LOOKUP:
3273     case TaskType::CONFIG_PRESET:
3274     case TaskType::HOSTS:
3275       return true;
3276     default:
3277       return false;
3278   }
3279 }
3280 
ResolveLocally(bool only_ipv6_reachable,const JobKey & job_key,const IPAddress & ip_address,ResolveHostParameters::CacheUsage cache_usage,SecureDnsPolicy secure_dns_policy,HostResolverSource source,const NetLogWithSource & source_net_log,HostCache * cache,std::deque<TaskType> * out_tasks,absl::optional<HostCache::EntryStaleness> * out_stale_info)3281 HostCache::Entry HostResolverManager::ResolveLocally(
3282     bool only_ipv6_reachable,
3283     const JobKey& job_key,
3284     const IPAddress& ip_address,
3285     ResolveHostParameters::CacheUsage cache_usage,
3286     SecureDnsPolicy secure_dns_policy,
3287     HostResolverSource source,
3288     const NetLogWithSource& source_net_log,
3289     HostCache* cache,
3290     std::deque<TaskType>* out_tasks,
3291     absl::optional<HostCache::EntryStaleness>* out_stale_info) {
3292   DCHECK(out_stale_info);
3293   *out_stale_info = absl::nullopt;
3294 
3295   CreateTaskSequence(job_key, cache_usage, secure_dns_policy, out_tasks);
3296 
3297   if (!ip_address.IsValid()) {
3298     // Check that the caller supplied a valid hostname to resolve. For
3299     // MULTICAST_DNS, we are less restrictive.
3300     // TODO(ericorth): Control validation based on an explicit flag rather
3301     // than implicitly based on |source|.
3302     const bool is_valid_hostname =
3303         job_key.source == HostResolverSource::MULTICAST_DNS
3304             ? dns_names_util::IsValidDnsName(GetHostname(job_key.host))
3305             : IsCanonicalizedHostCompliant(GetHostname(job_key.host));
3306     if (!is_valid_hostname) {
3307       return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
3308                               HostCache::Entry::SOURCE_UNKNOWN);
3309     }
3310   }
3311 
3312   bool resolve_canonname = job_key.flags & HOST_RESOLVER_CANONNAME;
3313   bool default_family_due_to_no_ipv6 =
3314       job_key.flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
3315 
3316   // The result of |getaddrinfo| for empty hosts is inconsistent across systems.
3317   // On Windows it gives the default interface's address, whereas on Linux it
3318   // gives an error. We will make it fail on all platforms for consistency.
3319   if (GetHostname(job_key.host).empty() ||
3320       GetHostname(job_key.host).size() > kMaxHostLength) {
3321     return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
3322                             HostCache::Entry::SOURCE_UNKNOWN);
3323   }
3324 
3325   if (ip_address.IsValid()) {
3326     // Use NAT64Task for IPv4 literal when the network is IPv6 only.
3327     if (MayUseNAT64ForIPv4Literal(job_key.flags, source, ip_address) &&
3328         only_ipv6_reachable) {
3329       out_tasks->push_front(TaskType::NAT64);
3330       return HostCache::Entry(ERR_DNS_CACHE_MISS,
3331                               HostCache::Entry::SOURCE_UNKNOWN);
3332     }
3333 
3334     return ResolveAsIP(job_key.query_types, resolve_canonname, ip_address);
3335   }
3336 
3337   // Special-case localhost names, as per the recommendations in
3338   // https://tools.ietf.org/html/draft-west-let-localhost-be-localhost.
3339   absl::optional<HostCache::Entry> resolved =
3340       ServeLocalhost(GetHostname(job_key.host), job_key.query_types,
3341                      default_family_due_to_no_ipv6);
3342   if (resolved)
3343     return resolved.value();
3344 
3345   // Do initial cache lookups.
3346   while (!out_tasks->empty() && IsLocalTask(out_tasks->front())) {
3347     TaskType task = out_tasks->front();
3348     out_tasks->pop_front();
3349     if (task == TaskType::SECURE_CACHE_LOOKUP ||
3350         task == TaskType::INSECURE_CACHE_LOOKUP ||
3351         task == TaskType::CACHE_LOOKUP) {
3352       bool secure = task == TaskType::SECURE_CACHE_LOOKUP;
3353       HostCache::Key key = job_key.ToCacheKey(secure);
3354 
3355       bool ignore_secure = task == TaskType::CACHE_LOOKUP;
3356       resolved = MaybeServeFromCache(cache, key, cache_usage, ignore_secure,
3357                                      source_net_log, out_stale_info);
3358       if (resolved) {
3359         // |MaybeServeFromCache()| will update |*out_stale_info| as needed.
3360         DCHECK(out_stale_info->has_value());
3361         source_net_log.AddEvent(
3362             NetLogEventType::HOST_RESOLVER_MANAGER_CACHE_HIT,
3363             [&] { return NetLogResults(resolved.value()); });
3364 
3365         // TODO(crbug.com/1200908): Call StartBootstrapFollowup() if the Secure
3366         // DNS Policy is kBootstrap and the result is not secure.  Note: A naive
3367         // implementation could cause an infinite loop if |resolved| always
3368         // expires or is evicted before the followup runs.
3369         return resolved.value();
3370       }
3371       DCHECK(!out_stale_info->has_value());
3372     } else if (task == TaskType::CONFIG_PRESET) {
3373       resolved = MaybeReadFromConfig(job_key);
3374       if (resolved) {
3375         source_net_log.AddEvent(
3376             NetLogEventType::HOST_RESOLVER_MANAGER_CONFIG_PRESET_MATCH,
3377             [&] { return NetLogResults(resolved.value()); });
3378         StartBootstrapFollowup(job_key, cache, source_net_log);
3379         return resolved.value();
3380       }
3381     } else if (task == TaskType::HOSTS) {
3382       resolved = ServeFromHosts(GetHostname(job_key.host), job_key.query_types,
3383                                 default_family_due_to_no_ipv6, *out_tasks);
3384       if (resolved) {
3385         source_net_log.AddEvent(
3386             NetLogEventType::HOST_RESOLVER_MANAGER_HOSTS_HIT,
3387             [&] { return NetLogResults(resolved.value()); });
3388         return resolved.value();
3389       }
3390     } else {
3391       NOTREACHED();
3392     }
3393   }
3394 
3395   return HostCache::Entry(ERR_DNS_CACHE_MISS, HostCache::Entry::SOURCE_UNKNOWN);
3396 }
3397 
CreateAndStartJob(JobKey key,std::deque<TaskType> tasks,RequestImpl * request)3398 void HostResolverManager::CreateAndStartJob(JobKey key,
3399                                             std::deque<TaskType> tasks,
3400                                             RequestImpl* request) {
3401   DCHECK(!tasks.empty());
3402 
3403   auto jobit = jobs_.find(key);
3404   Job* job;
3405   if (jobit == jobs_.end()) {
3406     job = AddJobWithoutRequest(key, request->parameters().cache_usage,
3407                                request->host_cache(), std::move(tasks),
3408                                request->priority(), request->source_net_log());
3409     job->AddRequest(request);
3410     job->RunNextTask();
3411   } else {
3412     job = jobit->second.get();
3413     job->AddRequest(request);
3414   }
3415 }
3416 
AddJobWithoutRequest(JobKey key,ResolveHostParameters::CacheUsage cache_usage,HostCache * host_cache,std::deque<TaskType> tasks,RequestPriority priority,const NetLogWithSource & source_net_log)3417 HostResolverManager::Job* HostResolverManager::AddJobWithoutRequest(
3418     JobKey key,
3419     ResolveHostParameters::CacheUsage cache_usage,
3420     HostCache* host_cache,
3421     std::deque<TaskType> tasks,
3422     RequestPriority priority,
3423     const NetLogWithSource& source_net_log) {
3424   auto new_job =
3425       std::make_unique<Job>(weak_ptr_factory_.GetWeakPtr(), key, cache_usage,
3426                             host_cache, std::move(tasks), priority,
3427                             source_net_log, tick_clock_, https_svcb_options_);
3428   auto insert_result = jobs_.emplace(std::move(key), std::move(new_job));
3429   auto& iterator = insert_result.first;
3430   bool is_new = insert_result.second;
3431   DCHECK(is_new);
3432   auto& job = iterator->second;
3433   job->OnAddedToJobMap(iterator);
3434   return job.get();
3435 }
3436 
ResolveAsIP(DnsQueryTypeSet query_types,bool resolve_canonname,const IPAddress & ip_address)3437 HostCache::Entry HostResolverManager::ResolveAsIP(DnsQueryTypeSet query_types,
3438                                                   bool resolve_canonname,
3439                                                   const IPAddress& ip_address) {
3440   DCHECK(ip_address.IsValid());
3441   DCHECK(!query_types.Has(DnsQueryType::UNSPECIFIED));
3442 
3443   // IP literals cannot resolve unless the query type is an address query that
3444   // allows addresses with the same address family as the literal. E.g., don't
3445   // return IPv6 addresses for IPv4 queries or anything for a non-address query.
3446   AddressFamily family = GetAddressFamily(ip_address);
3447   if (!query_types.Has(AddressFamilyToDnsQueryType(family))) {
3448     return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
3449                             HostCache::Entry::SOURCE_UNKNOWN);
3450   }
3451 
3452   std::set<std::string> aliases;
3453   if (resolve_canonname) {
3454     aliases = {ip_address.ToString()};
3455   }
3456   return HostCache::Entry(OK, {IPEndPoint(ip_address, 0)}, std::move(aliases),
3457                           HostCache::Entry::SOURCE_UNKNOWN);
3458 }
3459 
MaybeServeFromCache(HostCache * cache,const HostCache::Key & key,ResolveHostParameters::CacheUsage cache_usage,bool ignore_secure,const NetLogWithSource & source_net_log,absl::optional<HostCache::EntryStaleness> * out_stale_info)3460 absl::optional<HostCache::Entry> HostResolverManager::MaybeServeFromCache(
3461     HostCache* cache,
3462     const HostCache::Key& key,
3463     ResolveHostParameters::CacheUsage cache_usage,
3464     bool ignore_secure,
3465     const NetLogWithSource& source_net_log,
3466     absl::optional<HostCache::EntryStaleness>* out_stale_info) {
3467   DCHECK(out_stale_info);
3468   *out_stale_info = absl::nullopt;
3469 
3470   if (!cache)
3471     return absl::nullopt;
3472 
3473   if (cache_usage == ResolveHostParameters::CacheUsage::DISALLOWED)
3474     return absl::nullopt;
3475 
3476   // Local-only requests search the cache for non-local-only results.
3477   HostCache::Key effective_key = key;
3478   if (effective_key.host_resolver_source == HostResolverSource::LOCAL_ONLY)
3479     effective_key.host_resolver_source = HostResolverSource::ANY;
3480 
3481   const std::pair<const HostCache::Key, HostCache::Entry>* cache_result;
3482   HostCache::EntryStaleness staleness;
3483   if (cache_usage == ResolveHostParameters::CacheUsage::STALE_ALLOWED) {
3484     cache_result = cache->LookupStale(effective_key, tick_clock_->NowTicks(),
3485                                       &staleness, ignore_secure);
3486   } else {
3487     DCHECK(cache_usage == ResolveHostParameters::CacheUsage::ALLOWED);
3488     cache_result =
3489         cache->Lookup(effective_key, tick_clock_->NowTicks(), ignore_secure);
3490     staleness = HostCache::kNotStale;
3491   }
3492   if (cache_result) {
3493     *out_stale_info = std::move(staleness);
3494     source_net_log.AddEvent(
3495         NetLogEventType::HOST_RESOLVER_MANAGER_CACHE_HIT,
3496         [&] { return NetLogResults(cache_result->second); });
3497     return cache_result->second;
3498   }
3499   return absl::nullopt;
3500 }
3501 
MaybeReadFromConfig(const JobKey & key)3502 absl::optional<HostCache::Entry> HostResolverManager::MaybeReadFromConfig(
3503     const JobKey& key) {
3504   DCHECK(HasAddressType(key.query_types));
3505   if (!absl::holds_alternative<url::SchemeHostPort>(key.host))
3506     return absl::nullopt;
3507   absl::optional<std::vector<IPEndPoint>> preset_addrs =
3508       dns_client_->GetPresetAddrs(absl::get<url::SchemeHostPort>(key.host));
3509   if (!preset_addrs)
3510     return absl::nullopt;
3511 
3512   std::vector<IPEndPoint> filtered_addresses =
3513       FilterAddresses(std::move(*preset_addrs), key.query_types);
3514   if (filtered_addresses.empty())
3515     return absl::nullopt;
3516 
3517   return HostCache::Entry(OK, std::move(filtered_addresses), /*aliases=*/{},
3518                           HostCache::Entry::SOURCE_CONFIG);
3519 }
3520 
StartBootstrapFollowup(JobKey key,HostCache * host_cache,const NetLogWithSource & source_net_log)3521 void HostResolverManager::StartBootstrapFollowup(
3522     JobKey key,
3523     HostCache* host_cache,
3524     const NetLogWithSource& source_net_log) {
3525   DCHECK_EQ(SecureDnsMode::kOff, key.secure_dns_mode);
3526   DCHECK(host_cache);
3527 
3528   key.secure_dns_mode = SecureDnsMode::kSecure;
3529   if (jobs_.count(key) != 0)
3530     return;
3531 
3532   Job* job = AddJobWithoutRequest(
3533       key, ResolveHostParameters::CacheUsage::ALLOWED, host_cache,
3534       {TaskType::SECURE_DNS}, RequestPriority::LOW, source_net_log);
3535   job->RunNextTask();
3536 }
3537 
ServeFromHosts(base::StringPiece hostname,DnsQueryTypeSet query_types,bool default_family_due_to_no_ipv6,const std::deque<TaskType> & tasks)3538 absl::optional<HostCache::Entry> HostResolverManager::ServeFromHosts(
3539     base::StringPiece hostname,
3540     DnsQueryTypeSet query_types,
3541     bool default_family_due_to_no_ipv6,
3542     const std::deque<TaskType>& tasks) {
3543   DCHECK(!query_types.Has(DnsQueryType::UNSPECIFIED));
3544   // Don't attempt a HOSTS lookup if there is no DnsConfig or the HOSTS lookup
3545   // is going to be done next as part of a system lookup.
3546   if (!dns_client_ || !HasAddressType(query_types) ||
3547       (!tasks.empty() && tasks.front() == TaskType::SYSTEM))
3548     return absl::nullopt;
3549   const DnsHosts* hosts = dns_client_->GetHosts();
3550 
3551   if (!hosts || hosts->empty())
3552     return absl::nullopt;
3553 
3554   // HOSTS lookups are case-insensitive.
3555   std::string effective_hostname = base::ToLowerASCII(hostname);
3556 
3557   // If |address_family| is ADDRESS_FAMILY_UNSPECIFIED other implementations
3558   // (glibc and c-ares) return the first matching line. We have more
3559   // flexibility, but lose implicit ordering.
3560   // We prefer IPv6 because "happy eyeballs" will fall back to IPv4 if
3561   // necessary.
3562   std::vector<IPEndPoint> addresses;
3563   if (query_types.Has(DnsQueryType::AAAA)) {
3564     auto it = hosts->find(DnsHostsKey(effective_hostname, ADDRESS_FAMILY_IPV6));
3565     if (it != hosts->end()) {
3566       addresses.emplace_back(it->second, 0);
3567     }
3568   }
3569 
3570   if (query_types.Has(DnsQueryType::A)) {
3571     auto it = hosts->find(DnsHostsKey(effective_hostname, ADDRESS_FAMILY_IPV4));
3572     if (it != hosts->end()) {
3573       addresses.emplace_back(it->second, 0);
3574     }
3575   }
3576 
3577   // If got only loopback addresses and the family was restricted, resolve
3578   // again, without restrictions. See SystemHostResolverCall for rationale.
3579   if (default_family_due_to_no_ipv6 &&
3580       base::ranges::all_of(addresses, &IPAddress::IsIPv4,
3581                            &IPEndPoint::address) &&
3582       base::ranges::all_of(addresses, &IPAddress::IsLoopback,
3583                            &IPEndPoint::address)) {
3584     query_types.Put(DnsQueryType::AAAA);
3585     return ServeFromHosts(hostname, query_types, false, tasks);
3586   }
3587 
3588   if (addresses.empty())
3589     return absl::nullopt;
3590 
3591   return HostCache::Entry(OK, std::move(addresses),
3592                           /*aliases=*/{}, HostCache::Entry::SOURCE_HOSTS);
3593 }
3594 
ServeLocalhost(base::StringPiece hostname,DnsQueryTypeSet query_types,bool default_family_due_to_no_ipv6)3595 absl::optional<HostCache::Entry> HostResolverManager::ServeLocalhost(
3596     base::StringPiece hostname,
3597     DnsQueryTypeSet query_types,
3598     bool default_family_due_to_no_ipv6) {
3599   DCHECK(!query_types.Has(DnsQueryType::UNSPECIFIED));
3600 
3601   std::vector<IPEndPoint> resolved_addresses;
3602   if (!HasAddressType(query_types) ||
3603       !ResolveLocalHostname(hostname, &resolved_addresses)) {
3604     return absl::nullopt;
3605   }
3606 
3607   if (default_family_due_to_no_ipv6 && query_types.Has(DnsQueryType::A) &&
3608       !query_types.Has(DnsQueryType::AAAA)) {
3609     // The caller disabled the AAAA query due to lack of detected IPv6 support.
3610     // (See SystemHostResolverCall for rationale).
3611     query_types.Put(DnsQueryType::AAAA);
3612   }
3613   std::vector<IPEndPoint> filtered_addresses =
3614       FilterAddresses(std::move(resolved_addresses), query_types);
3615   return HostCache::Entry(OK, std::move(filtered_addresses), /*aliases=*/{},
3616                           HostCache::Entry::SOURCE_UNKNOWN);
3617 }
3618 
CacheResult(HostCache * cache,const HostCache::Key & key,const HostCache::Entry & entry,base::TimeDelta ttl)3619 void HostResolverManager::CacheResult(HostCache* cache,
3620                                       const HostCache::Key& key,
3621                                       const HostCache::Entry& entry,
3622                                       base::TimeDelta ttl) {
3623   // Don't cache an error unless it has a positive TTL.
3624   if (cache && (entry.error() == OK || ttl.is_positive()))
3625     cache->Set(key, entry, tick_clock_->NowTicks(), ttl);
3626 }
3627 
RemoveJob(JobMap::iterator job_it)3628 std::unique_ptr<HostResolverManager::Job> HostResolverManager::RemoveJob(
3629     JobMap::iterator job_it) {
3630   DCHECK(job_it != jobs_.end());
3631   DCHECK(job_it->second);
3632   DCHECK_EQ(1u, jobs_.count(job_it->first));
3633 
3634   std::unique_ptr<Job> job;
3635   job_it->second.swap(job);
3636   jobs_.erase(job_it);
3637   job->OnRemovedFromJobMap();
3638 
3639   return job;
3640 }
3641 
GetEffectiveSecureDnsMode(SecureDnsPolicy secure_dns_policy)3642 SecureDnsMode HostResolverManager::GetEffectiveSecureDnsMode(
3643     SecureDnsPolicy secure_dns_policy) {
3644   // Use switch() instead of if() to ensure that all policies are handled.
3645   switch (secure_dns_policy) {
3646     case SecureDnsPolicy::kDisable:
3647     case SecureDnsPolicy::kBootstrap:
3648       return SecureDnsMode::kOff;
3649     case SecureDnsPolicy::kAllow:
3650       break;
3651   }
3652 
3653   const DnsConfig* config =
3654       dns_client_ ? dns_client_->GetEffectiveConfig() : nullptr;
3655 
3656   SecureDnsMode secure_dns_mode = SecureDnsMode::kOff;
3657   if (config) {
3658     secure_dns_mode = config->secure_dns_mode;
3659   }
3660   return secure_dns_mode;
3661 }
3662 
ShouldForceSystemResolverDueToTestOverride() const3663 bool HostResolverManager::ShouldForceSystemResolverDueToTestOverride() const {
3664   // If tests have provided a catch-all DNS block and then disabled it, check
3665   // that we are not at risk of sending queries beyond the local network.
3666   if (HostResolverProc::GetDefault() && system_resolver_disabled_for_testing_) {
3667     DCHECK(dns_client_);
3668     DCHECK(dns_client_->GetEffectiveConfig());
3669     DCHECK(base::ranges::none_of(dns_client_->GetEffectiveConfig()->nameservers,
3670                                  &IPAddress::IsPubliclyRoutable,
3671                                  &IPEndPoint::address))
3672         << "Test could query a publicly-routable address.";
3673   }
3674   return !host_resolver_system_params_.resolver_proc &&
3675          HostResolverProc::GetDefault() &&
3676          !system_resolver_disabled_for_testing_;
3677 }
3678 
PushDnsTasks(bool system_task_allowed,SecureDnsMode secure_dns_mode,bool insecure_tasks_allowed,bool allow_cache,bool prioritize_local_lookups,ResolveContext * resolve_context,std::deque<TaskType> * out_tasks)3679 void HostResolverManager::PushDnsTasks(bool system_task_allowed,
3680                                        SecureDnsMode secure_dns_mode,
3681                                        bool insecure_tasks_allowed,
3682                                        bool allow_cache,
3683                                        bool prioritize_local_lookups,
3684                                        ResolveContext* resolve_context,
3685                                        std::deque<TaskType>* out_tasks) {
3686   DCHECK(dns_client_);
3687   DCHECK(dns_client_->GetEffectiveConfig());
3688 
3689   // If a catch-all DNS block has been set for unit tests, we shouldn't send
3690   // DnsTasks. It is still necessary to call this method, however, so that the
3691   // correct cache tasks for the secure dns mode are added.
3692   const bool dns_tasks_allowed = !ShouldForceSystemResolverDueToTestOverride();
3693   // Upgrade the insecure DnsTask depending on the secure dns mode.
3694   switch (secure_dns_mode) {
3695     case SecureDnsMode::kSecure:
3696       DCHECK(!allow_cache ||
3697              out_tasks->front() == TaskType::SECURE_CACHE_LOOKUP);
3698       // Policy misconfiguration can put us in secure DNS mode without any DoH
3699       // servers to query. See https://crbug.com/1326526.
3700       if (dns_tasks_allowed && dns_client_->CanUseSecureDnsTransactions())
3701         out_tasks->push_back(TaskType::SECURE_DNS);
3702       break;
3703     case SecureDnsMode::kAutomatic:
3704       DCHECK(!allow_cache || out_tasks->front() == TaskType::CACHE_LOOKUP);
3705       if (dns_client_->FallbackFromSecureTransactionPreferred(
3706               resolve_context)) {
3707         // Don't run a secure DnsTask if there are no available DoH servers.
3708         if (dns_tasks_allowed && insecure_tasks_allowed)
3709           out_tasks->push_back(TaskType::DNS);
3710       } else if (prioritize_local_lookups) {
3711         // If local lookups are prioritized, the cache should be checked for
3712         // both secure and insecure results prior to running a secure DnsTask.
3713         // The task sequence should already contain the appropriate cache task.
3714         if (dns_tasks_allowed) {
3715           out_tasks->push_back(TaskType::SECURE_DNS);
3716           if (insecure_tasks_allowed)
3717             out_tasks->push_back(TaskType::DNS);
3718         }
3719       } else {
3720         if (allow_cache) {
3721           // Remove the initial cache lookup task so that the secure and
3722           // insecure lookups can be separated.
3723           out_tasks->pop_front();
3724           out_tasks->push_back(TaskType::SECURE_CACHE_LOOKUP);
3725         }
3726         if (dns_tasks_allowed)
3727           out_tasks->push_back(TaskType::SECURE_DNS);
3728         if (allow_cache)
3729           out_tasks->push_back(TaskType::INSECURE_CACHE_LOOKUP);
3730         if (dns_tasks_allowed && insecure_tasks_allowed)
3731           out_tasks->push_back(TaskType::DNS);
3732       }
3733       break;
3734     case SecureDnsMode::kOff:
3735       DCHECK(!allow_cache || IsLocalTask(out_tasks->front()));
3736       if (dns_tasks_allowed && insecure_tasks_allowed)
3737         out_tasks->push_back(TaskType::DNS);
3738       break;
3739     default:
3740       NOTREACHED();
3741       break;
3742   }
3743 
3744   constexpr TaskType kWantTasks[] = {TaskType::DNS, TaskType::SECURE_DNS};
3745   const bool no_dns_or_secure_tasks =
3746       base::ranges::find_first_of(*out_tasks, kWantTasks) == out_tasks->end();
3747   // The system resolver can be used as a fallback for a non-existent or
3748   // failing DnsTask if allowed by the request parameters.
3749   if (system_task_allowed &&
3750       (no_dns_or_secure_tasks || allow_fallback_to_systemtask_))
3751     out_tasks->push_back(TaskType::SYSTEM);
3752 }
3753 
CreateTaskSequence(const JobKey & job_key,ResolveHostParameters::CacheUsage cache_usage,SecureDnsPolicy secure_dns_policy,std::deque<TaskType> * out_tasks)3754 void HostResolverManager::CreateTaskSequence(
3755     const JobKey& job_key,
3756     ResolveHostParameters::CacheUsage cache_usage,
3757     SecureDnsPolicy secure_dns_policy,
3758     std::deque<TaskType>* out_tasks) {
3759   DCHECK(out_tasks->empty());
3760 
3761   // A cache lookup should generally be performed first. For jobs involving a
3762   // DnsTask, this task may be replaced.
3763   bool allow_cache =
3764       cache_usage != ResolveHostParameters::CacheUsage::DISALLOWED;
3765   if (secure_dns_policy == SecureDnsPolicy::kBootstrap) {
3766     DCHECK_EQ(SecureDnsMode::kOff, job_key.secure_dns_mode);
3767     if (allow_cache)
3768       out_tasks->push_front(TaskType::INSECURE_CACHE_LOOKUP);
3769     out_tasks->push_front(TaskType::CONFIG_PRESET);
3770     if (allow_cache)
3771       out_tasks->push_front(TaskType::SECURE_CACHE_LOOKUP);
3772   } else if (allow_cache) {
3773     if (job_key.secure_dns_mode == SecureDnsMode::kSecure) {
3774       out_tasks->push_front(TaskType::SECURE_CACHE_LOOKUP);
3775     } else {
3776       out_tasks->push_front(TaskType::CACHE_LOOKUP);
3777     }
3778   }
3779   out_tasks->push_back(TaskType::HOSTS);
3780 
3781   // Determine what type of task a future Job should start.
3782   bool prioritize_local_lookups =
3783       cache_usage ==
3784       HostResolver::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
3785 
3786   const bool has_address_type = HasAddressType(job_key.query_types);
3787 
3788   switch (job_key.source) {
3789     case HostResolverSource::ANY:
3790       // Force address queries with canonname to use HostResolverSystemTask to
3791       // counter poor CNAME support in DnsTask. See https://crbug.com/872665
3792       //
3793       // Otherwise, default to DnsTask (with allowed fallback to
3794       // HostResolverSystemTask for address queries). But if hostname appears to
3795       // be an MDNS name (ends in *.local), go with HostResolverSystemTask for
3796       // address queries and MdnsTask for non- address queries.
3797       if ((job_key.flags & HOST_RESOLVER_CANONNAME) && has_address_type) {
3798         out_tasks->push_back(TaskType::SYSTEM);
3799       } else if (!ResemblesMulticastDNSName(GetHostname(job_key.host))) {
3800         bool system_task_allowed =
3801             has_address_type &&
3802             job_key.secure_dns_mode != SecureDnsMode::kSecure;
3803         if (dns_client_ && dns_client_->GetEffectiveConfig()) {
3804           bool insecure_allowed =
3805               dns_client_->CanUseInsecureDnsTransactions() &&
3806               !dns_client_->FallbackFromInsecureTransactionPreferred() &&
3807               (has_address_type ||
3808                dns_client_->CanQueryAdditionalTypesViaInsecureDns());
3809           PushDnsTasks(system_task_allowed, job_key.secure_dns_mode,
3810                        insecure_allowed, allow_cache, prioritize_local_lookups,
3811                        &*job_key.resolve_context, out_tasks);
3812         } else if (system_task_allowed) {
3813           out_tasks->push_back(TaskType::SYSTEM);
3814         }
3815       } else if (has_address_type) {
3816         // For *.local address queries, try the system resolver even if the
3817         // secure dns mode is SECURE. Public recursive resolvers aren't expected
3818         // to handle these queries.
3819         out_tasks->push_back(TaskType::SYSTEM);
3820       } else {
3821         out_tasks->push_back(TaskType::MDNS);
3822       }
3823       break;
3824     case HostResolverSource::SYSTEM:
3825       out_tasks->push_back(TaskType::SYSTEM);
3826       break;
3827     case HostResolverSource::DNS:
3828       if (dns_client_ && dns_client_->GetEffectiveConfig()) {
3829         bool insecure_allowed =
3830             dns_client_->CanUseInsecureDnsTransactions() &&
3831             (has_address_type ||
3832              dns_client_->CanQueryAdditionalTypesViaInsecureDns());
3833         PushDnsTasks(false /* system_task_allowed */, job_key.secure_dns_mode,
3834                      insecure_allowed, allow_cache, prioritize_local_lookups,
3835                      &*job_key.resolve_context, out_tasks);
3836       }
3837       break;
3838     case HostResolverSource::MULTICAST_DNS:
3839       out_tasks->push_back(TaskType::MDNS);
3840       break;
3841     case HostResolverSource::LOCAL_ONLY:
3842       // If no external source allowed, a job should not be created or started
3843       break;
3844   }
3845 
3846   // `HOST_RESOLVER_CANONNAME` is only supported through system resolution.
3847   if (job_key.flags & HOST_RESOLVER_CANONNAME) {
3848     DCHECK(base::ranges::find(*out_tasks, TaskType::DNS) == out_tasks->end());
3849     DCHECK(base::ranges::find(*out_tasks, TaskType::MDNS) == out_tasks->end());
3850   }
3851 }
3852 
GetEffectiveParametersForRequest(const absl::variant<url::SchemeHostPort,std::string> & host,DnsQueryType dns_query_type,HostResolverFlags flags,SecureDnsPolicy secure_dns_policy,bool is_ip,const NetLogWithSource & net_log,DnsQueryTypeSet * out_effective_types,HostResolverFlags * out_effective_flags,SecureDnsMode * out_effective_secure_dns_mode)3853 void HostResolverManager::GetEffectiveParametersForRequest(
3854     const absl::variant<url::SchemeHostPort, std::string>& host,
3855     DnsQueryType dns_query_type,
3856     HostResolverFlags flags,
3857     SecureDnsPolicy secure_dns_policy,
3858     bool is_ip,
3859     const NetLogWithSource& net_log,
3860     DnsQueryTypeSet* out_effective_types,
3861     HostResolverFlags* out_effective_flags,
3862     SecureDnsMode* out_effective_secure_dns_mode) {
3863   const SecureDnsMode secure_dns_mode =
3864       GetEffectiveSecureDnsMode(secure_dns_policy);
3865 
3866   *out_effective_secure_dns_mode = secure_dns_mode;
3867   *out_effective_flags = flags | additional_resolver_flags_;
3868 
3869   if (dns_query_type != DnsQueryType::UNSPECIFIED) {
3870     *out_effective_types = dns_query_type;
3871     return;
3872   }
3873 
3874   DnsQueryTypeSet effective_types(DnsQueryType::A, DnsQueryType::AAAA);
3875 
3876   // Disable AAAA queries when we cannot do anything with the results.
3877   bool use_local_ipv6 = true;
3878   if (dns_client_) {
3879     const DnsConfig* config = dns_client_->GetEffectiveConfig();
3880     if (config)
3881       use_local_ipv6 = config->use_local_ipv6;
3882   }
3883   // When resolving IPv4 literals, there's no need to probe for IPv6. When
3884   // resolving IPv6 literals, there's no benefit to artificially limiting our
3885   // resolution based on a probe. Prior logic ensures that this is an automatic
3886   // query, so the code requesting the resolution should be amenable to
3887   // receiving an IPv6 resolution.
3888   if (!use_local_ipv6 && !is_ip && !last_ipv6_probe_result_) {
3889     *out_effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
3890     effective_types.Remove(DnsQueryType::AAAA);
3891   }
3892 
3893   // Optimistically enable feature-controlled queries. These queries may be
3894   // skipped at a later point.
3895 
3896   // `https_svcb_options_.enable` has precedence, so if enabled, ignore any
3897   // other related features.
3898   if (https_svcb_options_.enable) {
3899     static const char* const kSchemesForHttpsQuery[] = {
3900         url::kHttpScheme, url::kHttpsScheme, url::kWsScheme, url::kWssScheme};
3901     if (base::Contains(kSchemesForHttpsQuery, GetScheme(host)))
3902       effective_types.Put(DnsQueryType::HTTPS);
3903   }
3904 
3905   *out_effective_types = effective_types;
3906 }
3907 
3908 namespace {
3909 
RequestWillUseWiFi(handles::NetworkHandle network)3910 bool RequestWillUseWiFi(handles::NetworkHandle network) {
3911   NetworkChangeNotifier::ConnectionType connection_type;
3912   if (network == handles::kInvalidNetworkHandle)
3913     connection_type = NetworkChangeNotifier::GetConnectionType();
3914   else
3915     connection_type = NetworkChangeNotifier::GetNetworkConnectionType(network);
3916 
3917   return connection_type == NetworkChangeNotifier::CONNECTION_WIFI;
3918 }
3919 
3920 }  // namespace
3921 
FinishIPv6ReachabilityCheck(CompletionOnceCallback callback,int rv)3922 void HostResolverManager::FinishIPv6ReachabilityCheck(
3923     CompletionOnceCallback callback,
3924     int rv) {
3925   SetLastIPv6ProbeResult((rv == OK) ? true : false);
3926   std::move(callback).Run(OK);
3927   if (!ipv6_request_callbacks_.empty()) {
3928     std::vector<CompletionOnceCallback> tmp_request_callbacks;
3929     ipv6_request_callbacks_.swap(tmp_request_callbacks);
3930     for (auto& request_callback : tmp_request_callbacks) {
3931       std::move(request_callback).Run(OK);
3932     }
3933   }
3934 }
3935 
StartIPv6ReachabilityCheck(const NetLogWithSource & net_log,CompletionOnceCallback callback)3936 int HostResolverManager::StartIPv6ReachabilityCheck(
3937     const NetLogWithSource& net_log,
3938     CompletionOnceCallback callback) {
3939   // Don't bother checking if the request will use WiFi and IPv6 is assumed to
3940   // not work on WiFi.
3941   if (!check_ipv6_on_wifi_ && RequestWillUseWiFi(target_network_)) {
3942     probing_ipv6_ = false;
3943     last_ipv6_probe_result_ = false;
3944     last_ipv6_probe_time_ = base::TimeTicks();
3945     return OK;
3946   }
3947 
3948   if (probing_ipv6_) {
3949     ipv6_request_callbacks_.push_back(std::move(callback));
3950     return ERR_IO_PENDING;
3951   }
3952   // Cache the result for kIPv6ProbePeriodMs (measured from after
3953   // StartGloballyReachableCheck() completes).
3954   int rv = OK;
3955   bool cached = true;
3956   if (last_ipv6_probe_time_.is_null() ||
3957       (tick_clock_->NowTicks() - last_ipv6_probe_time_).InMilliseconds() >
3958           kIPv6ProbePeriodMs) {
3959     probing_ipv6_ = true;
3960     rv = StartGloballyReachableCheck(
3961         IPAddress(kIPv6ProbeAddress), net_log,
3962         base::BindOnce(&HostResolverManager::FinishIPv6ReachabilityCheck,
3963                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
3964     if (rv != ERR_IO_PENDING) {
3965       SetLastIPv6ProbeResult((rv == OK) ? true : false);
3966       rv = OK;
3967     }
3968     cached = false;
3969   }
3970   net_log.AddEvent(
3971       NetLogEventType::HOST_RESOLVER_MANAGER_IPV6_REACHABILITY_CHECK, [&] {
3972         return NetLogIPv6AvailableParams(last_ipv6_probe_result_, cached);
3973       });
3974   return rv;
3975 }
3976 
SetLastIPv6ProbeResult(bool last_ipv6_probe_result)3977 void HostResolverManager::SetLastIPv6ProbeResult(bool last_ipv6_probe_result) {
3978   probing_ipv6_ = false;
3979   last_ipv6_probe_result_ = last_ipv6_probe_result;
3980   last_ipv6_probe_time_ = tick_clock_->NowTicks();
3981 }
3982 
StartGloballyReachableCheck(const IPAddress & dest,const NetLogWithSource & net_log,CompletionOnceCallback callback)3983 int HostResolverManager::StartGloballyReachableCheck(
3984     const IPAddress& dest,
3985     const NetLogWithSource& net_log,
3986     CompletionOnceCallback callback) {
3987   std::unique_ptr<DatagramClientSocket> probing_socket =
3988       ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
3989           DatagramSocket::DEFAULT_BIND, net_log.net_log(), net_log.source());
3990   DatagramClientSocket* probing_socket_ptr = probing_socket.get();
3991   auto refcounted_socket = base::MakeRefCounted<
3992       base::RefCountedData<std::unique_ptr<DatagramClientSocket>>>(
3993       std::move(probing_socket));
3994   int rv = probing_socket_ptr->ConnectAsync(
3995       IPEndPoint(dest, 53),
3996       base::BindOnce(&HostResolverManager::RunFinishGloballyReachableCheck,
3997                      weak_ptr_factory_.GetWeakPtr(), refcounted_socket,
3998                      std::move(callback)));
3999   if (rv != ERR_IO_PENDING) {
4000     rv = FinishGloballyReachableCheck(probing_socket_ptr, rv) ? OK : ERR_FAILED;
4001   }
4002   return rv;
4003 }
4004 
FinishGloballyReachableCheck(DatagramClientSocket * socket,int rv)4005 bool HostResolverManager::FinishGloballyReachableCheck(
4006     DatagramClientSocket* socket,
4007     int rv) {
4008   if (rv != OK) {
4009     return false;
4010   }
4011   IPEndPoint endpoint;
4012   rv = socket->GetLocalAddress(&endpoint);
4013 
4014   if (rv != OK) {
4015     return false;
4016   }
4017   const IPAddress& address = endpoint.address();
4018 
4019   if (address.IsLinkLocal()) {
4020     return false;
4021   }
4022 
4023   if (address.IsIPv6()) {
4024     const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
4025     if (IPAddressStartsWith(address, kTeredoPrefix)) {
4026       return false;
4027     }
4028   }
4029 
4030   return true;
4031 }
4032 
RunFinishGloballyReachableCheck(scoped_refptr<base::RefCountedData<std::unique_ptr<DatagramClientSocket>>> socket,CompletionOnceCallback callback,int rv)4033 void HostResolverManager::RunFinishGloballyReachableCheck(
4034     scoped_refptr<base::RefCountedData<std::unique_ptr<DatagramClientSocket>>>
4035         socket,
4036     CompletionOnceCallback callback,
4037     int rv) {
4038   bool is_reachable = FinishGloballyReachableCheck(socket->data.get(), rv);
4039   std::move(callback).Run(is_reachable ? OK : ERR_FAILED);
4040 }
4041 
RunLoopbackProbeJob()4042 void HostResolverManager::RunLoopbackProbeJob() {
4043   // Run this asynchronously as it can take 40-100ms and should not block
4044   // initialization.
4045   base::ThreadPool::PostTaskAndReplyWithResult(
4046       FROM_HERE,
4047       {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
4048       base::BindOnce(&HaveOnlyLoopbackAddresses),
4049       base::BindOnce(&HostResolverManager::SetHaveOnlyLoopbackAddresses,
4050                      weak_ptr_factory_.GetWeakPtr()));
4051 }
4052 
RemoveAllJobs(const ResolveContext * context)4053 void HostResolverManager::RemoveAllJobs(const ResolveContext* context) {
4054   for (auto it = jobs_.begin(); it != jobs_.end();) {
4055     const JobKey& key = it->first;
4056     if (&*key.resolve_context == context) {
4057       RemoveJob(it++);
4058     } else {
4059       ++it;
4060     }
4061   }
4062 }
4063 
AbortJobsWithoutTargetNetwork(bool in_progress_only)4064 void HostResolverManager::AbortJobsWithoutTargetNetwork(bool in_progress_only) {
4065   // In Abort, a Request callback could spawn new Jobs with matching keys, so
4066   // first collect and remove all running jobs from `jobs_`.
4067   std::vector<std::unique_ptr<Job>> jobs_to_abort;
4068   for (auto it = jobs_.begin(); it != jobs_.end();) {
4069     Job* job = it->second.get();
4070     if (!job->HasTargetNetwork() && (!in_progress_only || job->is_running())) {
4071       jobs_to_abort.push_back(RemoveJob(it++));
4072     } else {
4073       ++it;
4074     }
4075   }
4076 
4077   // Pause the dispatcher so it won't start any new dispatcher jobs while
4078   // aborting the old ones.  This is needed so that it won't start the second
4079   // DnsTransaction for a job in `jobs_to_abort` if the DnsConfig just became
4080   // invalid.
4081   PrioritizedDispatcher::Limits limits = dispatcher_->GetLimits();
4082   dispatcher_->SetLimits(
4083       PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
4084 
4085   // Life check to bail once `this` is deleted.
4086   base::WeakPtr<HostResolverManager> self = weak_ptr_factory_.GetWeakPtr();
4087 
4088   // Then Abort them.
4089   for (size_t i = 0; self.get() && i < jobs_to_abort.size(); ++i) {
4090     jobs_to_abort[i]->Abort();
4091   }
4092 
4093   if (self)
4094     dispatcher_->SetLimits(limits);
4095 }
4096 
AbortInsecureDnsTasks(int error,bool fallback_only)4097 void HostResolverManager::AbortInsecureDnsTasks(int error, bool fallback_only) {
4098   // Aborting jobs potentially modifies |jobs_| and may even delete some jobs.
4099   // Create safe closures of all current jobs.
4100   std::vector<base::OnceClosure> job_abort_closures;
4101   for (auto& job : jobs_) {
4102     job_abort_closures.push_back(
4103         job.second->GetAbortInsecureDnsTaskClosure(error, fallback_only));
4104   }
4105 
4106   // Pause the dispatcher so it won't start any new dispatcher jobs while
4107   // aborting the old ones.  This is needed so that it won't start the second
4108   // DnsTransaction for a job if the DnsConfig just changed.
4109   PrioritizedDispatcher::Limits limits = dispatcher_->GetLimits();
4110   dispatcher_->SetLimits(
4111       PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
4112 
4113   for (base::OnceClosure& closure : job_abort_closures)
4114     std::move(closure).Run();
4115 
4116   dispatcher_->SetLimits(limits);
4117 }
4118 
4119 // TODO(crbug.com/995984): Consider removing this and its usage.
TryServingAllJobsFromHosts()4120 void HostResolverManager::TryServingAllJobsFromHosts() {
4121   if (!dns_client_ || !dns_client_->GetEffectiveConfig())
4122     return;
4123 
4124   // TODO(szym): Do not do this if nsswitch.conf instructs not to.
4125   // http://crbug.com/117655
4126 
4127   // Life check to bail once |this| is deleted.
4128   base::WeakPtr<HostResolverManager> self = weak_ptr_factory_.GetWeakPtr();
4129 
4130   for (auto it = jobs_.begin(); self.get() && it != jobs_.end();) {
4131     Job* job = it->second.get();
4132     ++it;
4133     // This could remove |job| from |jobs_|, but iterator will remain valid.
4134     job->ServeFromHosts();
4135   }
4136 }
4137 
OnIPAddressChanged()4138 void HostResolverManager::OnIPAddressChanged() {
4139   DCHECK(!IsBoundToNetwork());
4140   last_ipv6_probe_time_ = base::TimeTicks();
4141   // Abandon all ProbeJobs.
4142   probe_weak_ptr_factory_.InvalidateWeakPtrs();
4143   InvalidateCaches();
4144 #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)) || \
4145     BUILDFLAG(IS_FUCHSIA)
4146   RunLoopbackProbeJob();
4147 #endif
4148   AbortJobsWithoutTargetNetwork(true /* in_progress_only */);
4149   // `this` may be deleted inside AbortJobsWithoutTargetNetwork().
4150 }
4151 
OnConnectionTypeChanged(NetworkChangeNotifier::ConnectionType type)4152 void HostResolverManager::OnConnectionTypeChanged(
4153     NetworkChangeNotifier::ConnectionType type) {
4154   DCHECK(!IsBoundToNetwork());
4155   UpdateConnectionType(type);
4156 }
4157 
OnSystemDnsConfigChanged(absl::optional<DnsConfig> config)4158 void HostResolverManager::OnSystemDnsConfigChanged(
4159     absl::optional<DnsConfig> config) {
4160   DCHECK(!IsBoundToNetwork());
4161   // If tests have provided a catch-all DNS block and then disabled it, check
4162   // that we are not at risk of sending queries beyond the local network.
4163   if (HostResolverProc::GetDefault() && system_resolver_disabled_for_testing_ &&
4164       config.has_value()) {
4165     DCHECK(base::ranges::none_of(config->nameservers,
4166                                  &IPAddress::IsPubliclyRoutable,
4167                                  &IPEndPoint::address))
4168         << "Test could query a publicly-routable address.";
4169   }
4170 
4171   bool changed = false;
4172   bool transactions_allowed_before = false;
4173   if (dns_client_) {
4174     transactions_allowed_before = dns_client_->CanUseSecureDnsTransactions() ||
4175                                   dns_client_->CanUseInsecureDnsTransactions();
4176     changed = dns_client_->SetSystemConfig(std::move(config));
4177   }
4178 
4179   // Always invalidate cache, even if no change is seen.
4180   InvalidateCaches();
4181 
4182   if (changed) {
4183     // Need to update jobs iff transactions were previously allowed because
4184     // in-progress jobs may be running using a now-invalid configuration.
4185     if (transactions_allowed_before)
4186       UpdateJobsForChangedConfig();
4187   }
4188 }
4189 
UpdateJobsForChangedConfig()4190 void HostResolverManager::UpdateJobsForChangedConfig() {
4191   // Life check to bail once `this` is deleted.
4192   base::WeakPtr<HostResolverManager> self = weak_ptr_factory_.GetWeakPtr();
4193 
4194   // Existing jobs that were set up using the nameservers and secure dns mode
4195   // from the original config need to be aborted (does not apply to jobs
4196   // targeting a specific network).
4197   AbortJobsWithoutTargetNetwork(false /* in_progress_only */);
4198 
4199   // `this` may be deleted inside AbortJobsWithoutTargetNetwork().
4200   if (self.get())
4201     TryServingAllJobsFromHosts();
4202 }
4203 
OnFallbackResolve(int dns_task_error)4204 void HostResolverManager::OnFallbackResolve(int dns_task_error) {
4205   DCHECK(dns_client_);
4206   DCHECK_NE(OK, dns_task_error);
4207 
4208   // Nothing to do if DnsTask is already not preferred.
4209   if (dns_client_->FallbackFromInsecureTransactionPreferred())
4210     return;
4211 
4212   dns_client_->IncrementInsecureFallbackFailures();
4213 
4214   // If DnsClient became not preferred, fallback all fallback-allowed insecure
4215   // DnsTasks to HostResolverSystemTasks.
4216   if (dns_client_->FallbackFromInsecureTransactionPreferred())
4217     AbortInsecureDnsTasks(ERR_FAILED, true /* fallback_only */);
4218 }
4219 
GetOrCreateMdnsClient(MDnsClient ** out_client)4220 int HostResolverManager::GetOrCreateMdnsClient(MDnsClient** out_client) {
4221 #if BUILDFLAG(ENABLE_MDNS)
4222   if (!mdns_client_) {
4223     if (!mdns_socket_factory_)
4224       mdns_socket_factory_ = std::make_unique<MDnsSocketFactoryImpl>(net_log_);
4225     mdns_client_ = MDnsClient::CreateDefault();
4226   }
4227 
4228   int rv = OK;
4229   if (!mdns_client_->IsListening())
4230     rv = mdns_client_->StartListening(mdns_socket_factory_.get());
4231 
4232   DCHECK_NE(ERR_IO_PENDING, rv);
4233   DCHECK(rv != OK || mdns_client_->IsListening());
4234   if (rv == OK)
4235     *out_client = mdns_client_.get();
4236   return rv;
4237 #else
4238   // Should not request MDNS resoltuion unless MDNS is enabled.
4239   NOTREACHED();
4240   return ERR_UNEXPECTED;
4241 #endif
4242 }
4243 
InvalidateCaches(bool network_change)4244 void HostResolverManager::InvalidateCaches(bool network_change) {
4245   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
4246   DCHECK(!invalidation_in_progress_);
4247 
4248 #if DCHECK_IS_ON()
4249   base::WeakPtr<HostResolverManager> self_ptr = weak_ptr_factory_.GetWeakPtr();
4250   size_t num_jobs = jobs_.size();
4251 #endif
4252 
4253   invalidation_in_progress_ = true;
4254   for (auto& context : registered_contexts_) {
4255     context.InvalidateCachesAndPerSessionData(
4256         dns_client_ ? dns_client_->GetCurrentSession() : nullptr,
4257         network_change);
4258   }
4259   invalidation_in_progress_ = false;
4260 
4261 #if DCHECK_IS_ON()
4262   // Sanity checks that invalidation does not have reentrancy issues.
4263   DCHECK(self_ptr);
4264   DCHECK_EQ(num_jobs, jobs_.size());
4265 #endif
4266 }
4267 
UpdateConnectionType(NetworkChangeNotifier::ConnectionType type)4268 void HostResolverManager::UpdateConnectionType(
4269     NetworkChangeNotifier::ConnectionType type) {
4270   host_resolver_system_params_.unresponsive_delay =
4271       GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
4272           "DnsUnresponsiveDelayMsByConnectionType",
4273           HostResolverSystemTask::Params::kDnsDefaultUnresponsiveDelay, type);
4274 
4275   // Note that NetworkChangeNotifier always sends a CONNECTION_NONE notification
4276   // before non-NONE notifications. This check therefore just ensures each
4277   // connection change notification is handled once and has nothing to do with
4278   // whether the change is to offline or online.
4279   if (type == NetworkChangeNotifier::CONNECTION_NONE && dns_client_) {
4280     dns_client_->ReplaceCurrentSession();
4281     InvalidateCaches(true /* network_change */);
4282   }
4283 }
4284 
CreateDohProbeRunner(ResolveContext * resolve_context)4285 std::unique_ptr<DnsProbeRunner> HostResolverManager::CreateDohProbeRunner(
4286     ResolveContext* resolve_context) {
4287   DCHECK(resolve_context);
4288   DCHECK(registered_contexts_.HasObserver(resolve_context));
4289   if (!dns_client_ || !dns_client_->CanUseSecureDnsTransactions()) {
4290     return nullptr;
4291   }
4292 
4293   return dns_client_->GetTransactionFactory()->CreateDohProbeRunner(
4294       resolve_context);
4295 }
4296 
~RequestImpl()4297 HostResolverManager::RequestImpl::~RequestImpl() {
4298   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
4299   if (!job_.has_value())
4300     return;
4301 
4302   job_.value()->CancelRequest(this);
4303   LogCancelRequest();
4304 }
4305 
ChangeRequestPriority(RequestPriority priority)4306 void HostResolverManager::RequestImpl::ChangeRequestPriority(
4307     RequestPriority priority) {
4308   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
4309   if (!job_.has_value()) {
4310     priority_ = priority;
4311     return;
4312   }
4313   job_.value()->ChangeRequestPriority(this, priority);
4314 }
4315 
GetJobKey() const4316 const HostResolverManager::JobKey& HostResolverManager::RequestImpl::GetJobKey()
4317     const {
4318   CHECK(job_.has_value());
4319   return job_.value()->key();
4320 }
4321 
OnJobCancelled(const JobKey & job_key)4322 void HostResolverManager::RequestImpl::OnJobCancelled(const JobKey& job_key) {
4323   CHECK(job_.has_value());
4324   CHECK(job_key == job_.value()->key());
4325   job_.reset();
4326   DCHECK(!complete_);
4327   DCHECK(callback_);
4328   callback_.Reset();
4329 
4330   // No results should be set.
4331   DCHECK(!results_);
4332 
4333   LogCancelRequest();
4334 }
4335 
OnJobCompleted(const JobKey & job_key,int error,bool is_secure_network_error)4336 void HostResolverManager::RequestImpl::OnJobCompleted(
4337     const JobKey& job_key,
4338     int error,
4339     bool is_secure_network_error) {
4340   set_error_info(error, is_secure_network_error);
4341 
4342   CHECK(job_.has_value());
4343   CHECK(job_key == job_.value()->key());
4344   job_.reset();
4345 
4346   DCHECK(!complete_);
4347   complete_ = true;
4348 
4349   LogFinishRequest(error, true /* async_completion */);
4350 
4351   DCHECK(callback_);
4352   std::move(callback_).Run(HostResolver::SquashErrorCode(error));
4353 }
4354 
4355 }  // namespace net
4356