summaryrefslogtreecommitdiff
path: root/chromium/net/dns/host_resolver_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/dns/host_resolver_manager.cc')
-rw-r--r--chromium/net/dns/host_resolver_manager.cc394
1 files changed, 196 insertions, 198 deletions
diff --git a/chromium/net/dns/host_resolver_manager.cc b/chromium/net/dns/host_resolver_manager.cc
index 87bc925b8a0..82347fd6bf8 100644
--- a/chromium/net/dns/host_resolver_manager.cc
+++ b/chromium/net/dns/host_resolver_manager.cc
@@ -82,6 +82,7 @@
#include "net/dns/host_resolver_mdns_listener_impl.h"
#include "net/dns/host_resolver_mdns_task.h"
#include "net/dns/host_resolver_proc.h"
+#include "net/dns/httpssvc_metrics.h"
#include "net/dns/mdns_client.h"
#include "net/dns/public/dns_protocol.h"
#include "net/dns/public/resolve_error_info.h"
@@ -499,7 +500,8 @@ class HostResolverManager::RequestImpl
const base::Optional<ResolveHostParameters>& optional_parameters,
ResolveContext* resolve_context,
HostCache* host_cache,
- base::WeakPtr<HostResolverManager> resolver)
+ base::WeakPtr<HostResolverManager> resolver,
+ const base::TickClock* tick_clock)
: source_net_log_(source_net_log),
request_host_(request_host),
network_isolation_key_(
@@ -516,7 +518,8 @@ class HostResolverManager::RequestImpl
priority_(parameters_.initial_priority),
job_(nullptr),
resolver_(resolver),
- complete_(false) {}
+ complete_(false),
+ tick_clock_(tick_clock) {}
~RequestImpl() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -544,7 +547,7 @@ class HostResolverManager::RequestImpl
} else {
DCHECK(!job_);
complete_ = true;
- LogFinishRequest(rv);
+ LogFinishRequest(rv, false /* async_completion */);
}
resolver_ = nullptr;
@@ -573,10 +576,12 @@ class HostResolverManager::RequestImpl
return results_ ? results_.value().hostnames() : *nullopt_result;
}
- const base::Optional<EsniContent>& GetEsniResults() const override {
+ const base::Optional<std::vector<bool>>& GetIntegrityResultsForTesting()
+ const override {
DCHECK(complete_);
- static const base::NoDestructor<base::Optional<EsniContent>> nullopt_result;
- return results_ ? results_.value().esni_data() : *nullopt_result;
+ static const base::NoDestructor<base::Optional<std::vector<bool>>>
+ nullopt_result;
+ return results_ ? results_.value().integrity_data() : *nullopt_result;
}
net::ResolveErrorInfo GetResolveErrorInfo() const override {
@@ -649,7 +654,7 @@ class HostResolverManager::RequestImpl
DCHECK(!complete_);
complete_ = true;
- LogFinishRequest(error);
+ LogFinishRequest(error, true /* async_completion */);
DCHECK(callback_);
std::move(callback_).Run(HostResolver::SquashErrorCode(error));
@@ -679,19 +684,12 @@ class HostResolverManager::RequestImpl
bool complete() const { return complete_; }
- base::TimeTicks request_time() const {
- DCHECK(!request_time_.is_null());
- return request_time_;
- }
- void set_request_time(base::TimeTicks request_time) {
- DCHECK(request_time_.is_null());
- DCHECK(!request_time.is_null());
- request_time_ = request_time;
- }
-
private:
- // Logs when a request has just been started.
+ // Logging and metrics for when a request has just been started.
void LogStartRequest() {
+ DCHECK(request_time_.is_null());
+ request_time_ = tick_clock_->NowTicks();
+
source_net_log_.BeginEvent(
NetLogEventType::HOST_RESOLVER_IMPL_REQUEST, [this] {
base::Value dict(base::Value::Type::DICTIONARY);
@@ -708,10 +706,20 @@ class HostResolverManager::RequestImpl
});
}
- // Logs when a request has just completed (before its callback is run).
- void LogFinishRequest(int net_error) {
+ // Logging and metrics for when a request has just completed (before its
+ // callback is run).
+ void LogFinishRequest(int net_error, bool async_completion) {
source_net_log_.EndEventWithNetErrorCode(
NetLogEventType::HOST_RESOLVER_IMPL_REQUEST, net_error);
+
+ if (!parameters_.is_speculative) {
+ DCHECK(!request_time_.is_null());
+ base::TimeDelta duration = tick_clock_->NowTicks() - request_time_;
+
+ UMA_HISTOGRAM_MEDIUM_TIMES("Net.DNS.Request.TotalTime", duration);
+ if (async_completion)
+ UMA_HISTOGRAM_MEDIUM_TIMES("Net.DNS.Request.TotalTimeAsync", duration);
+ }
}
// Logs when a request has been cancelled.
@@ -744,6 +752,7 @@ class HostResolverManager::RequestImpl
base::Optional<HostCache::EntryStaleness> stale_info_;
ResolveErrorInfo error_info_;
+ const base::TickClock* const tick_clock_;
base::TimeTicks request_time_;
SEQUENCE_CHECKER(sequence_checker_);
@@ -1107,9 +1116,21 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
transactions_needed_.push(DnsQueryType::A);
transactions_needed_.push(DnsQueryType::AAAA);
- if (secure_ &&
- base::FeatureList::IsEnabled(features::kRequestEsniDnsRecords)) {
- transactions_needed_.push(DnsQueryType::ESNI);
+ // Queue up an INTEGRITY query if we are allowed to.
+ const bool is_httpssvc_experiment_domain =
+ httpssvc_domain_cache_.IsExperimental(hostname);
+ const bool is_httpssvc_control_domain =
+ httpssvc_domain_cache_.IsControl(hostname);
+ if (base::FeatureList::IsEnabled(features::kDnsHttpssvc) &&
+ features::kDnsHttpssvcUseIntegrity.Get() &&
+ (secure_ || features::kDnsHttpssvcEnableQueryOverInsecure.Get()) &&
+ (is_httpssvc_experiment_domain || is_httpssvc_control_domain)) {
+ // We should not be configured to query HTTPSSVC *and* INTEGRITY.
+ DCHECK(!features::kDnsHttpssvcUseHttpssvc.Get());
+
+ httpssvc_metrics_.emplace(
+ is_httpssvc_experiment_domain /* expect_intact */);
+ transactions_needed_.push(DnsQueryType::INTEGRITY);
}
}
num_needed_transactions_ = transactions_needed_.size();
@@ -1170,15 +1191,25 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
return trans;
}
- void OnEsniTransactionTimeout() {
- // Currently, the ESNI transaction timer only gets started
- // when all non-ESNI transactions have completed.
- DCHECK(TaskIsCompleteOrOnlyEsniTransactionsRemain());
+ void OnExperimentalQueryTimeout(uint16_t qtype,
+ base::Optional<std::string> doh_provider_id) {
+ // The experimental query timer is only started when all other transactions
+ // have completed.
+ DCHECK(TaskIsCompleteOrOnlyQtypeTransactionsRemain(qtype));
num_completed_transactions_ += transactions_started_.size();
DCHECK(num_completed_transactions_ == num_needed_transactions());
transactions_started_.clear();
+ if (qtype == dns_protocol::kExperimentalTypeIntegrity) {
+ DCHECK(httpssvc_metrics_);
+
+ // Record that this INTEGRITY query timed out in the metrics.
+ base::TimeDelta elapsed_time = tick_clock_->NowTicks() - task_start_time_;
+ httpssvc_metrics_->SaveForIntegrity(
+ doh_provider_id, HttpssvcDnsRcode::kTimedOut, {}, elapsed_time);
+ }
+
ProcessResultsOnCompletion();
}
@@ -1186,7 +1217,8 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
DnsQueryType dns_query_type,
DnsTransaction* transaction,
int net_error,
- const DnsResponse* response) {
+ const DnsResponse* response,
+ base::Optional<std::string> doh_provider_id) {
DCHECK(transaction);
// Once control leaves OnTransactionComplete, there's no further
@@ -1202,10 +1234,30 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
transactions_started_.erase(it);
}
+ base::TimeDelta elapsed_time = tick_clock_->NowTicks() - task_start_time_;
+ enum HttpssvcDnsRcode rcode_for_httpssvc = HttpssvcDnsRcode::kNoError;
+ if (httpssvc_metrics_) {
+ if (net_error == ERR_DNS_TIMED_OUT) {
+ rcode_for_httpssvc = HttpssvcDnsRcode::kTimedOut;
+ } else if (net_error == ERR_NAME_NOT_RESOLVED) {
+ rcode_for_httpssvc = HttpssvcDnsRcode::kNoError;
+ } else if (response == nullptr) {
+ rcode_for_httpssvc = HttpssvcDnsRcode::kMissingDnsResponse;
+ } else {
+ rcode_for_httpssvc =
+ TranslateDnsRcodeForHttpssvcExperiment(response->rcode());
+ }
+ }
+
if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
response->IsValid())) {
- OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt);
- return;
+ if (dns_query_type == DnsQueryType::INTEGRITY) {
+ // Do not allow an INTEGRITY query to fail the whole DnsTask.
+ response = nullptr;
+ } else {
+ OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt);
+ return;
+ }
}
DnsResponse::Result parse_result = DnsResponse::DNS_PARSE_RESULT_MAX;
@@ -1228,8 +1280,9 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
case DnsQueryType::SRV:
parse_result = ParseServiceDnsResponse(response, &results);
break;
- case DnsQueryType::ESNI:
- parse_result = ParseEsniDnsResponse(response, &results);
+ case DnsQueryType::INTEGRITY:
+ // Parse the INTEGRITY records, condensing them into a vector<bool>.
+ parse_result = ParseIntegrityDnsResponse(response, &results);
break;
}
DCHECK_LT(parse_result, DnsResponse::DNS_PARSE_RESULT_MAX);
@@ -1239,6 +1292,21 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
return;
}
+ if (httpssvc_metrics_) {
+ if (dns_query_type != DnsQueryType::INTEGRITY) {
+ httpssvc_metrics_->SaveForNonIntegrity(doh_provider_id, elapsed_time,
+ rcode_for_httpssvc);
+ } else {
+ const base::Optional<std::vector<bool>>& condensed =
+ results.integrity_data();
+ CHECK(condensed.has_value());
+ // INTEGRITY queries can time out the normal way (here), or when the
+ // experimental query timer runs out (OnExperimentalQueryTimeout).
+ httpssvc_metrics_->SaveForIntegrity(doh_provider_id, rcode_for_httpssvc,
+ *condensed, elapsed_time);
+ }
+ }
+
// Merge results with saved results from previous transactions.
if (saved_results_) {
DCHECK_LE(2, num_needed_transactions());
@@ -1257,10 +1325,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
results = HostCache::Entry::MergeEntries(
std::move(results), std::move(saved_results_).value());
break;
- case DnsQueryType::ESNI:
- // It doesn't matter whether the ESNI record is the "front"
- // or the "back" argument to the merge, since the logic for
- // merging addresses from ESNI records is the same in each case.
+ case DnsQueryType::INTEGRITY:
results = HostCache::Entry::MergeEntries(
std::move(results), std::move(saved_results_).value());
break;
@@ -1277,13 +1342,16 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
++num_completed_transactions_;
if (num_completed_transactions_ < num_needed_transactions()) {
delegate_->OnIntermediateTransactionComplete();
- MaybeStartEsniTimer();
+ // If the experimental query times out, blame the provider that gave the
+ // last A/AAAA result. If we were being 100% correct, we would blame the
+ // provider associated with the experimental query.
+ MaybeStartExperimentalQueryTimer(doh_provider_id);
return;
}
- // Since all transactions are complete, in particular, all ESNI transactions
- // are complete (if any were started).
- esni_cancellation_timer_.Stop();
+ // Since all transactions are complete, in particular, all experimental
+ // transactions are complete (if any were started).
+ experimental_query_cancellation_timer_.Stop();
ProcessResultsOnCompletion();
}
@@ -1296,20 +1364,13 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
// If there are multiple addresses, and at least one is IPv6, need to
// sort them.
- // When there are no ESNI keys in the record, IPv6 addresses are always
- // put before IPv4 ones, so it's sufficient to just check the family of
- // the first address.
- // When there are ESNI keys, there could be ESNI-equipped
- // IPv4 addresses preceding the first IPv6 address, so it's necessary to
- // scan the list.
bool at_least_one_ipv6_address =
results.addresses() && !results.addresses().value().empty() &&
(results.addresses().value()[0].GetFamily() == ADDRESS_FAMILY_IPV6 ||
- (results.esni_data() &&
- std::any_of(results.addresses().value().begin(),
- results.addresses().value().end(), [](auto& e) {
- return e.GetFamily() == ADDRESS_FAMILY_IPV6;
- })));
+ std::any_of(results.addresses().value().begin(),
+ results.addresses().value().end(), [](auto& e) {
+ return e.GetFamily() == ADDRESS_FAMILY_IPV6;
+ }));
if (at_least_one_ipv6_address) {
// Sort addresses if needed. Sort could complete synchronously.
@@ -1326,6 +1387,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
DnsResponse::Result ParseAddressDnsResponse(const DnsResponse* response,
HostCache::Entry* out_results) {
+ DCHECK(response);
AddressList addresses;
base::TimeDelta ttl;
DnsResponse::Result parse_result =
@@ -1346,6 +1408,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
DnsResponse::Result ParseTxtDnsResponse(const DnsResponse* response,
HostCache::Entry* out_results) {
+ DCHECK(response);
std::vector<std::unique_ptr<const RecordParsed>> records;
base::Optional<base::TimeDelta> response_ttl;
DnsResponse::Result parse_result = ParseAndFilterResponseRecords(
@@ -1371,6 +1434,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
DnsResponse::Result ParsePointerDnsResponse(const DnsResponse* response,
HostCache::Entry* out_results) {
+ DCHECK(response);
std::vector<std::unique_ptr<const RecordParsed>> records;
base::Optional<base::TimeDelta> response_ttl;
DnsResponse::Result parse_result = ParseAndFilterResponseRecords(
@@ -1399,6 +1463,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
DnsResponse::Result ParseServiceDnsResponse(const DnsResponse* response,
HostCache::Entry* out_results) {
+ DCHECK(response);
std::vector<std::unique_ptr<const RecordParsed>> records;
base::Optional<base::TimeDelta> response_ttl;
DnsResponse::Result parse_result = ParseAndFilterResponseRecords(
@@ -1428,55 +1493,39 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
return DnsResponse::DNS_PARSE_OK;
}
- DnsResponse::Result ParseEsniDnsResponse(const DnsResponse* response,
- HostCache::Entry* out_results) {
- std::vector<std::unique_ptr<const RecordParsed>> records;
+ DnsResponse::Result ParseIntegrityDnsResponse(const DnsResponse* response,
+ HostCache::Entry* out_results) {
base::Optional<base::TimeDelta> response_ttl;
+ const HostCache::Entry default_entry(
+ OK, std::vector<bool>(), HostCache::Entry::SOURCE_DNS, response_ttl);
+
+ if (response == nullptr) {
+ *out_results = default_entry;
+ return DnsResponse::Result::DNS_PARSE_OK;
+ }
+
+ std::vector<std::unique_ptr<const RecordParsed>> records;
DnsResponse::Result parse_result = ParseAndFilterResponseRecords(
- response, dns_protocol::kExperimentalTypeEsniDraft4, &records,
+ response, dns_protocol::kExperimentalTypeIntegrity, &records,
&response_ttl);
if (parse_result != DnsResponse::DNS_PARSE_OK) {
- *out_results = GetMalformedResponseResult();
- return parse_result;
+ *out_results = default_entry;
+ return DnsResponse::Result::DNS_PARSE_OK;
}
- // Glom the ESNI response records into a single EsniContent;
- // this also dedups keys and (key, address) associations.
- EsniContent content;
+ // Condense results into a list of booleans. We do not cache the results,
+ // but this enables us to write some unit tests.
+ std::vector<bool> condensed_results;
for (const auto& record : records) {
- const EsniRecordRdata& rdata = *record->rdata<EsniRecordRdata>();
-
- for (const IPAddress& address : rdata.addresses())
- content.AddKeyForAddress(address, rdata.esni_keys());
- }
-
- // As a first pass, deliberately ignore ESNI records with no addresses
- // included. Later, the implementation can be extended to handle "at-large"
- // ESNI keys not specifically associated with collections of addresses.
- // (We're declining the "...clients MAY initiate..." choice in ESNI draft 4,
- // Section 4.2.2 Step 2.)
- if (content.keys_for_addresses().empty()) {
- *out_results =
- HostCache::Entry(ERR_NAME_NOT_RESOLVED, EsniContent(),
- HostCache::Entry::SOURCE_DNS, response_ttl);
- } else {
- AddressList addresses, ipv4_addresses_temporary;
- addresses.set_canonical_name(hostname_);
- for (const auto& kv : content.keys_for_addresses())
- (kv.first.IsIPv6() ? addresses : ipv4_addresses_temporary)
- .push_back(IPEndPoint(kv.first, 0));
- addresses.insert(addresses.end(), ipv4_addresses_temporary.begin(),
- ipv4_addresses_temporary.end());
-
- // Store the addresses separately from the ESNI key-address
- // associations, so that the addresses can be merged later with
- // addresses from A and AAAA records.
- *out_results = HostCache::Entry(
- OK, std::move(content), HostCache::Entry::SOURCE_DNS, response_ttl);
- out_results->set_addresses(std::move(addresses));
+ const IntegrityRecordRdata& rdata =
+ *record->rdata<IntegrityRecordRdata>();
+ condensed_results.push_back(rdata.IsIntact());
}
+ *out_results = HostCache::Entry(OK, std::move(condensed_results),
+ HostCache::Entry::SOURCE_DNS, response_ttl);
+ DCHECK_EQ(parse_result, DnsResponse::DNS_PARSE_OK);
return parse_result;
}
@@ -1605,6 +1654,9 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
void OnFailure(int net_error,
DnsResponse::Result parse_result,
base::Optional<base::TimeDelta> ttl) {
+ if (httpssvc_metrics_)
+ httpssvc_metrics_->SaveNonIntegrityFailure();
+
DCHECK_NE(OK, net_error);
HostCache::Entry results(net_error, HostCache::Entry::SOURCE_UNKNOWN);
@@ -1636,52 +1688,57 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
delegate_->OnDnsTaskComplete(task_start_time_, results, secure_);
}
- // Returns whether all transactions left to execute are of transaction
- // type ESNI. (In particular, this is the case if all transactions are
- // complete.)
- // Used for logging and starting the ESNI transaction timer (see
- // MaybeStartEsniTimer).
- bool TaskIsCompleteOrOnlyEsniTransactionsRemain() const {
- // Since DoH runs all transactions concurrently and
- // DnsQueryType::UNSPECIFIED-with-ESNI tasks are only run using DoH,
- // this method only needs to check the transactions in transactions_started_
- // because transactions_needed_ is empty from the time the first
- // transaction is started.
+ // Returns whether all transactions left to execute are of transaction type
+ // |qtype|. (In particular, this is the case if all transactions are
+ // complete.) Used for logging and starting the experimental query timer (see
+ // MaybeStartExperimentalQueryTimer).
+ bool TaskIsCompleteOrOnlyQtypeTransactionsRemain(uint16_t qtype) const {
+ // Since DoH runs all transactions concurrently and experimental types are
+ // only queried over DoH, this method only needs to check the transactions
+ // in transactions_started_ because transactions_needed_ is empty from the
+ // time the first transaction is started.
DCHECK(transactions_needed_.empty());
return std::all_of(
transactions_started_.begin(), transactions_started_.end(),
[&](const std::unique_ptr<DnsTransaction>& p) {
DCHECK(p);
- return p->GetType() == dns_protocol::kExperimentalTypeEsniDraft4;
+ return p->GetType() == qtype;
});
}
- // If ESNI transactions are being executed as part of this task
- // and all transactions except the ESNI transactions have finished, and the
- // ESNI transactions have not finished, starts a timer after which to abort
- // the ESNI transactions.
- //
- // This timer has duration equal to the shorter of two parameterized values:
- // - a fixed, absolute duration
- // - a relative duration (as a proportion of the total time taken for
- // the task's other transactions).
- void MaybeStartEsniTimer() {
+
+ void MaybeStartExperimentalQueryTimer(
+ base::Optional<std::string> doh_provider_id) {
DCHECK(!transactions_started_.empty());
- DCHECK(saved_results_);
- if (!esni_cancellation_timer_.IsRunning() &&
- TaskIsCompleteOrOnlyEsniTransactionsRemain()) {
- base::TimeDelta total_time_taken_for_other_transactions =
+
+ // Abort if neither HTTPSSVC nor INTEGRITY querying is enabled.
+ if (!base::FeatureList::IsEnabled(features::kDnsHttpssvc) ||
+ (!features::kDnsHttpssvcUseIntegrity.Get() &&
+ !features::kDnsHttpssvcUseHttpssvc.Get())) {
+ return;
+ }
+
+ if (!experimental_query_cancellation_timer_.IsRunning() &&
+ TaskIsCompleteOrOnlyQtypeTransactionsRemain(
+ dns_protocol::kExperimentalTypeIntegrity)) {
+ const base::TimeDelta kExtraTimeAbsolute =
+ features::dns_httpssvc_experiment::GetExtraTimeAbsolute();
+ const int kExtraTimePercent =
+ features::kDnsHttpssvcExtraTimePercent.Get();
+
+ base::TimeDelta total_time_for_other_transactions =
tick_clock_->NowTicks() - task_start_time_;
+ base::TimeDelta relative_timeout =
+ total_time_for_other_transactions * kExtraTimePercent / 100;
- esni_cancellation_timer_.Start(
- FROM_HERE,
- std::min(
- features::EsniDnsMaxAbsoluteAdditionalWait(),
- total_time_taken_for_other_transactions *
- (0.01 *
- features::kEsniDnsMaxRelativeAdditionalWaitPercent.Get())),
- this, &DnsTask::OnEsniTransactionTimeout);
+ base::TimeDelta timeout = std::min(kExtraTimeAbsolute, relative_timeout);
+
+ experimental_query_cancellation_timer_.Start(
+ FROM_HERE, timeout,
+ base::BindOnce(
+ &DnsTask::OnExperimentalQueryTimeout, base::Unretained(this),
+ dns_protocol::kExperimentalTypeIntegrity, doh_provider_id));
}
}
@@ -1711,16 +1768,12 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
const base::TickClock* tick_clock_;
base::TimeTicks task_start_time_;
- // In order to histogram the relative end-to-end elapsed times of
- // a task's ESNI and non-ESNI transactions, store the end-to-end time
- // elapsed from task start to the end of the task's ESNI transaction
- // (if any) and its final non-ESNI transaction.
- base::TimeDelta esni_elapsed_for_logging_;
- base::TimeDelta non_esni_elapsed_for_logging_;
+ HttpssvcExperimentDomainCache httpssvc_domain_cache_;
+ base::Optional<HttpssvcMetrics> httpssvc_metrics_;
- // Timer for early abort of ESNI transactions. See comments describing
- // the timeout parameters in net/base/features.h.
- base::OneShotTimer esni_cancellation_timer_;
+ // Timer for early abort of experimental queries. See comments describing the
+ // timeout parameters in net/base/features.h.
+ base::OneShotTimer experimental_query_cancellation_timer_;
DISALLOW_COPY_AND_ASSIGN(DnsTask);
};
@@ -2396,7 +2449,7 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
query_types.push_back(query_type_);
}
- MDnsClient* client;
+ MDnsClient* client = nullptr;
int rv = resolver_->GetOrCreateMdnsClient(&client);
mdns_task_ =
std::make_unique<HostResolverMdnsTask>(client, hostname_, query_types);
@@ -2454,23 +2507,6 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
if (had_non_speculative_request_) {
category = RESOLVE_SUCCESS;
UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime", duration);
- switch (query_type_) {
- case DnsQueryType::A:
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV4",
- duration);
- break;
- case DnsQueryType::AAAA:
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV6",
- duration);
- break;
- case DnsQueryType::UNSPECIFIED:
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.UNSPEC",
- duration);
- break;
- default:
- // No histogram for other query types.
- break;
- }
} else {
category = RESOLVE_SPECULATIVE_SUCCESS;
}
@@ -2482,23 +2518,6 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
if (had_non_speculative_request_) {
category = RESOLVE_FAIL;
UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime", duration);
- switch (query_type_) {
- case DnsQueryType::A:
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV4",
- duration);
- break;
- case DnsQueryType::AAAA:
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV6",
- duration);
- break;
- case DnsQueryType::UNSPECIFIED:
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.UNSPEC",
- duration);
- break;
- default:
- // No histogram for other query types.
- break;
- }
} else {
category = RESOLVE_SPECULATIVE_FAIL;
}
@@ -2514,6 +2533,13 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
else
base::UmaHistogramSparse("Net.DNS.ResolveError.Slow", std::abs(error));
}
+
+ if (had_non_speculative_request_) {
+ UmaHistogramMediumTimes(
+ base::StringPrintf("Net.DNS.SecureDnsMode.%s.ResolveTime",
+ SecureDnsModeToString(secure_dns_mode_).c_str()),
+ duration);
+ }
}
void MaybeCacheResult(const HostCache::Entry& results,
@@ -2587,13 +2613,7 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
RequestImpl* req = requests_.head()->value();
req->RemoveFromList();
DCHECK_EQ(this, req->job());
- // Update the net log and notify registered observers.
- if (results.did_complete()) {
- // Record effective total time from creation to completion.
- resolver_->RecordTotalTime(
- req->parameters().is_speculative, false /* from_cache */,
- secure_dns_mode_, tick_clock_->NowTicks() - req->request_time());
- }
+
if (results.error() == OK && !req->parameters().is_speculative) {
req->set_results(
results.CopyWithDefaultPort(req->request_host().port()));
@@ -2808,7 +2828,7 @@ HostResolverManager::CreateRequest(
return std::make_unique<RequestImpl>(
net_log, host, network_isolation_key, optional_parameters,
- resolve_context, host_cache, weak_ptr_factory_.GetWeakPtr());
+ resolve_context, host_cache, weak_ptr_factory_.GetWeakPtr(), tick_clock_);
}
std::unique_ptr<HostResolverManager::CancellableProbeRequest>
@@ -2971,8 +2991,6 @@ int HostResolverManager::Resolve(RequestImpl* request) {
ResolveHostParameters::CacheUsage::ALLOWED);
DCHECK(!invalidation_in_progress_);
- request->set_request_time(tick_clock_->NowTicks());
-
DnsQueryType effective_query_type;
HostResolverFlags effective_host_resolver_flags;
DnsConfig::SecureDnsMode effective_secure_dns_mode;
@@ -2996,8 +3014,6 @@ int HostResolverManager::Resolve(RequestImpl* request) {
}
if (stale_info && !request->parameters().is_speculative)
request->set_stale_info(std::move(stale_info).value());
- RecordTotalTime(request->parameters().is_speculative, true /* from_cache */,
- effective_secure_dns_mode, base::TimeDelta());
request->set_error_info(results.error(),
false /* is_secure_network_error */);
return HostResolver::SquashErrorCode(results.error());
@@ -3317,24 +3333,6 @@ void HostResolverManager::CacheResult(HostCache* cache,
cache->Set(key, entry, tick_clock_->NowTicks(), ttl);
}
-// Record time from Request creation until a valid DNS response.
-void HostResolverManager::RecordTotalTime(
- bool speculative,
- bool from_cache,
- DnsConfig::SecureDnsMode secure_dns_mode,
- base::TimeDelta duration) const {
- if (!speculative) {
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTime", duration);
- UmaHistogramMediumTimes(
- base::StringPrintf("Net.DNS.SecureDnsMode.%s.TotalTime",
- SecureDnsModeToString(secure_dns_mode).c_str()),
- duration);
-
- if (!from_cache)
- UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTimeNotCached", duration);
- }
-}
-
std::unique_ptr<HostResolverManager::Job> HostResolverManager::RemoveJob(
JobMap::iterator job_it) {
DCHECK(job_it != jobs_.end());