Coerce more canonicalname resolves to use ProcTask

DnsClient doesn't handle cannonname very well (see
https://crbug.com/872665), so some logic was added a while back to force
ProcTask for such cases by setting HostResolverSource::SYSTEM when the
HOST_RESOLVER_CANONNAME flag is set. But this didn't affect the newer
HostResolver::CreateRequest() API, as that has callers directly set the
source and doesn't directly use ProcTask flags.

Bug: 872665
Change-Id: I709959911ec299118369f1f995ea5802df7a92f9
Reviewed-on: https://chromium-review.googlesource.com/c/1418350
Reviewed-by: Asanka Herath <asanka@chromium.org>
Commit-Queue: Eric Orth <ericorth@chromium.org>
Cr-Commit-Position: refs/heads/master@{#623815}
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 813a246..fc570e7 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -1740,11 +1740,17 @@
 
     switch (key_.host_resolver_source) {
       case HostResolverSource::ANY:
-        // Default to DnsTask (with allowed fallback to ProcTask for address
-        // queries). But if hostname appears to be an MDNS name (ends in
+        // Force address queries with canonname to use ProcTask to counter poor
+        // CNAME support in DnsTask. See https://crbug.com/872665
+        //
+        // Otherwise, default to DnsTask (with allowed fallback to ProcTask for
+        // address queries). But if hostname appears to be an MDNS name (ends in
         // *.local), go with ProcTask for address queries and MdnsTask for non-
         // address queries.
-        if (!ResemblesMulticastDNSName(key_.hostname)) {
+        if ((key_.host_resolver_flags & HOST_RESOLVER_CANONNAME) &&
+            IsAddressType(key_.dns_query_type)) {
+          StartProcTask();
+        } else if (!ResemblesMulticastDNSName(key_.hostname)) {
           StartDnsTask(IsAddressType(
               key_.dns_query_type) /* allow_fallback_resolution */);
         } else if (IsAddressType(key_.dns_query_type)) {
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc
index cc08987..4abc892 100644
--- a/net/dns/host_resolver_impl_unittest.cc
+++ b/net/dns/host_resolver_impl_unittest.cc
@@ -5923,6 +5923,7 @@
 
   HostResolver::ResolveHostParameters params;
   params.include_canonical_name = true;
+  params.source = HostResolverSource::DNS;
   ResolveHostResponseHelper response(resolver_->CreateRequest(
       HostPortPair("alias", 80), NetLogWithSource(), params));
   ASSERT_THAT(response.result_error(), IsOk());
@@ -5944,6 +5945,7 @@
 
   HostResolver::ResolveHostParameters params;
   params.include_canonical_name = true;
+  params.source = HostResolverSource::DNS;
   ResolveHostResponseHelper response(resolver_->CreateRequest(
       HostPortPair("alias", 80), NetLogWithSource(), params));
   ASSERT_FALSE(response.complete());
@@ -5965,6 +5967,7 @@
   HostResolver::ResolveHostParameters params;
   params.dns_query_type = DnsQueryType::A;
   params.include_canonical_name = true;
+  params.source = HostResolverSource::DNS;
   ResolveHostResponseHelper response(resolver_->CreateRequest(
       HostPortPair("alias", 80), NetLogWithSource(), params));
   ASSERT_THAT(response.result_error(), IsOk());
@@ -5972,6 +5975,29 @@
             "correct");
 }
 
+// Test that without specifying source, a request that would otherwise be
+// handled by DNS is sent to the system resolver if cannonname is requested.
+TEST_F(HostResolverImplDnsTest, CanonicalNameForcesProc) {
+  // Disable fallback to ensure system resolver is used directly, not via
+  // fallback.
+  set_allow_fallback_to_proctask(false);
+
+  proc_->AddRuleForAllFamilies("nx_succeed", "192.168.1.102",
+                               HOST_RESOLVER_CANONNAME, "canonical");
+  proc_->SignalMultiple(1u);
+
+  ChangeDnsConfig(CreateValidDnsConfig());
+
+  HostResolver::ResolveHostParameters params;
+  params.include_canonical_name = true;
+  ResolveHostResponseHelper response(resolver_->CreateRequest(
+      HostPortPair("nx_succeed", 80), NetLogWithSource(), params));
+  ASSERT_THAT(response.result_error(), IsOk());
+
+  EXPECT_EQ(response.request()->GetAddressResults().value().canonical_name(),
+            "canonical");
+}
+
 TEST_F(HostResolverImplTest, ResolveLocalHostname) {
   AddressList addresses;