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