Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / netwerk / dns / nsHostRecord.cpp
blob54a602058a289b9940c29fee47dfc5d9bd22e5e8
1 /* vim:set ts=4 sw=2 sts=2 et cin: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsHostRecord.h"
7 #include "TRRQuery.h"
8 // Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
9 #include "DNSLogging.h"
10 #include "mozilla/StaticPrefs_network.h"
11 #include "mozilla/Telemetry.h"
12 #include "mozilla/ThreadSafety.h"
13 #include "TRRService.h"
15 //----------------------------------------------------------------------------
16 // this macro filters out any flags that are not used when constructing the
17 // host key. the significant flags are those that would affect the resulting
18 // host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
19 #define RES_KEY_FLAGS(_f) \
20 ((_f) & \
21 (nsIDNSService::RESOLVE_CANONICAL_NAME | \
22 nsIDNSService::RESOLVE_DISABLE_TRR | \
23 nsIDNSService::RESOLVE_TRR_MODE_MASK | nsIDNSService::RESOLVE_IP_HINT))
25 #define IS_ADDR_TYPE(_type) ((_type) == nsIDNSService::RESOLVE_TYPE_DEFAULT)
26 #define IS_OTHER_TYPE(_type) ((_type) != nsIDNSService::RESOLVE_TYPE_DEFAULT)
28 //----------------------------------------------------------------------------
30 using namespace mozilla;
31 using namespace mozilla::net;
33 nsHostKey::nsHostKey(const nsACString& aHost, const nsACString& aTrrServer,
34 uint16_t aType, nsIDNSService::DNSFlags aFlags,
35 uint16_t aAf, bool aPb, const nsACString& aOriginsuffix)
36 : host(aHost),
37 mTrrServer(aTrrServer),
38 type(aType),
39 flags(aFlags),
40 af(aAf),
41 pb(aPb),
42 originSuffix(aOriginsuffix) {}
44 nsHostKey::nsHostKey(const nsHostKey& other)
45 : host(other.host),
46 mTrrServer(other.mTrrServer),
47 type(other.type),
48 flags(other.flags),
49 af(other.af),
50 pb(other.pb),
51 originSuffix(other.originSuffix) {}
53 bool nsHostKey::operator==(const nsHostKey& other) const {
54 return host == other.host && mTrrServer == other.mTrrServer &&
55 type == other.type &&
56 RES_KEY_FLAGS(flags) == RES_KEY_FLAGS(other.flags) && af == other.af &&
57 originSuffix == other.originSuffix;
60 PLDHashNumber nsHostKey::Hash() const {
61 return AddToHash(HashString(host.get()), HashString(mTrrServer.get()), type,
62 RES_KEY_FLAGS(flags), af, HashString(originSuffix.get()));
65 size_t nsHostKey::SizeOfExcludingThis(
66 mozilla::MallocSizeOf mallocSizeOf) const {
67 size_t n = 0;
68 n += host.SizeOfExcludingThisIfUnshared(mallocSizeOf);
69 n += mTrrServer.SizeOfExcludingThisIfUnshared(mallocSizeOf);
70 n += originSuffix.SizeOfExcludingThisIfUnshared(mallocSizeOf);
71 return n;
74 //----------------------------------------------------------------------------
75 // nsHostRecord
76 //----------------------------------------------------------------------------
78 NS_IMPL_ISUPPORTS0(nsHostRecord)
80 nsHostRecord::nsHostRecord(const nsHostKey& key)
81 : nsHostKey(key), mTRRQuery("nsHostRecord.mTRRQuery") {}
83 void nsHostRecord::Invalidate() { mDoomed = true; }
85 void nsHostRecord::Cancel() {
86 RefPtr<TRRQuery> query;
88 auto lock = mTRRQuery.Lock();
89 query.swap(lock.ref());
92 if (query) {
93 query->Cancel(NS_ERROR_ABORT);
97 nsHostRecord::ExpirationStatus nsHostRecord::CheckExpiration(
98 const mozilla::TimeStamp& now) const {
99 if (!mGraceStart.IsNull() && now >= mGraceStart && !mValidEnd.IsNull() &&
100 now < mValidEnd) {
101 return nsHostRecord::EXP_GRACE;
103 if (!mValidEnd.IsNull() && now < mValidEnd) {
104 return nsHostRecord::EXP_VALID;
107 return nsHostRecord::EXP_EXPIRED;
110 void nsHostRecord::SetExpiration(const mozilla::TimeStamp& now,
111 unsigned int valid, unsigned int grace) {
112 mValidStart = now;
113 if ((valid + grace) < 60) {
114 grace = 60 - valid;
115 LOG(("SetExpiration: artificially bumped grace to %d\n", grace));
117 mGraceStart = now + TimeDuration::FromSeconds(valid);
118 mValidEnd = now + TimeDuration::FromSeconds(valid + grace);
119 mTtl = valid;
122 void nsHostRecord::CopyExpirationTimesAndFlagsFrom(
123 const nsHostRecord* aFromHostRecord) {
124 // This is used to copy information from a cache entry to a record. All
125 // information necessary for HasUsableRecord needs to be copied.
126 mValidStart = aFromHostRecord->mValidStart;
127 mValidEnd = aFromHostRecord->mValidEnd;
128 mGraceStart = aFromHostRecord->mGraceStart;
129 mDoomed = aFromHostRecord->mDoomed;
130 mTtl = uint32_t(aFromHostRecord->mTtl);
133 bool nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now,
134 nsIDNSService::DNSFlags queryFlags) const {
135 if (mDoomed) {
136 return false;
139 return HasUsableResultInternal(now, queryFlags);
142 //----------------------------------------------------------------------------
143 // AddrHostRecord
144 //----------------------------------------------------------------------------
146 static size_t SizeOfResolveHostCallbackListExcludingHead(
147 const mozilla::LinkedList<RefPtr<nsResolveHostCallback>>& aCallbacks,
148 MallocSizeOf mallocSizeOf) {
149 size_t n = aCallbacks.sizeOfExcludingThis(mallocSizeOf);
151 for (const nsResolveHostCallback* t = aCallbacks.getFirst(); t;
152 t = t->getNext()) {
153 n += t->SizeOfIncludingThis(mallocSizeOf);
156 return n;
159 NS_IMPL_ISUPPORTS_INHERITED(AddrHostRecord, nsHostRecord, AddrHostRecord)
161 AddrHostRecord::AddrHostRecord(const nsHostKey& key) : nsHostRecord(key) {}
163 AddrHostRecord::~AddrHostRecord() {
164 mCallbacks.clear();
165 Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mUnusableCount);
168 bool AddrHostRecord::Blocklisted(const NetAddr* aQuery) {
169 addr_info_lock.AssertCurrentThreadOwns();
170 LOG(("Checking unusable list for host [%s], host record [%p].\n", host.get(),
171 this));
173 // skip the string conversion for the common case of no blocklist
174 if (!mUnusableItems.Length()) {
175 return false;
178 char buf[kIPv6CStrBufSize];
179 if (!aQuery->ToStringBuffer(buf, sizeof(buf))) {
180 return false;
182 nsDependentCString strQuery(buf);
184 for (uint32_t i = 0; i < mUnusableItems.Length(); i++) {
185 if (mUnusableItems.ElementAt(i).Equals(strQuery)) {
186 LOG(("Address [%s] is blocklisted for host [%s].\n", buf, host.get()));
187 return true;
191 return false;
194 void AddrHostRecord::ReportUnusable(const NetAddr* aAddress) {
195 addr_info_lock.AssertCurrentThreadOwns();
196 LOG(
197 ("Adding address to blocklist for host [%s], host record [%p]."
198 "used trr=%d\n",
199 host.get(), this, mTRRSuccess));
201 ++mUnusableCount;
203 char buf[kIPv6CStrBufSize];
204 if (aAddress->ToStringBuffer(buf, sizeof(buf))) {
205 LOG(
206 ("Successfully adding address [%s] to blocklist for host "
207 "[%s].\n",
208 buf, host.get()));
209 mUnusableItems.AppendElement(nsCString(buf));
213 void AddrHostRecord::ResetBlocklist() {
214 addr_info_lock.AssertCurrentThreadOwns();
215 LOG(("Resetting blocklist for host [%s], host record [%p].\n", host.get(),
216 this));
217 mUnusableItems.Clear();
220 size_t AddrHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
221 size_t n = mallocSizeOf(this);
223 n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
224 n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
226 n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
227 n += mallocSizeOf(addr.get());
229 n += mUnusableItems.ShallowSizeOfExcludingThis(mallocSizeOf);
230 for (size_t i = 0; i < mUnusableItems.Length(); i++) {
231 n += mUnusableItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
233 return n;
236 bool AddrHostRecord::HasUsableResultInternal(
237 const mozilla::TimeStamp& now, nsIDNSService::DNSFlags queryFlags) const {
238 // don't use cached negative results for high priority queries.
239 if (negative && IsHighPriority(queryFlags)) {
240 return false;
243 if (CheckExpiration(now) == EXP_EXPIRED) {
244 return false;
247 if (negative) {
248 return true;
251 return addr_info || addr;
254 // Returns true if the entry can be removed, or false if it should be left.
255 // Sets ResolveAgain true for entries being resolved right now.
256 bool AddrHostRecord::RemoveOrRefresh(bool aTrrToo) {
257 // no need to flush TRRed names, they're not resolved "locally"
258 MutexAutoLock lock(addr_info_lock);
259 if (addr_info && !aTrrToo && addr_info->IsTRR()) {
260 return false;
262 if (LoadNative()) {
263 if (!onQueue()) {
264 // The request has been passed to the OS resolver. The resultant DNS
265 // record should be considered stale and not trusted; set a flag to
266 // ensure it is called again.
267 StoreResolveAgain(true);
269 // if onQueue is true, the host entry is already added to the cache
270 // but is still pending to get resolved: just leave it in hash.
271 return false;
273 // Already resolved; not in a pending state; remove from cache
274 return true;
277 void AddrHostRecord::NotifyRetryingTrr() {
278 MOZ_ASSERT(mFirstTRRSkippedReason ==
279 mozilla::net::TRRSkippedReason::TRR_UNSET);
281 // Save the skip reason of our first attempt for recording telemetry later.
282 mFirstTRRSkippedReason = mTRRSkippedReason;
283 mTRRSkippedReason = mozilla::net::TRRSkippedReason::TRR_UNSET;
286 void AddrHostRecord::ResolveComplete() {
287 if (LoadNativeUsed()) {
288 if (mNativeSuccess) {
289 uint32_t millis = static_cast<uint32_t>(mNativeDuration.ToMilliseconds());
290 Telemetry::Accumulate(Telemetry::DNS_NATIVE_LOOKUP_TIME, millis);
292 AccumulateCategoricalKeyed(
293 TRRService::ProviderKey(),
294 mNativeSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osOK
295 : Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::osFail);
298 if (mResolverType == DNSResolverType::TRR) {
299 if (mTRRSuccess) {
300 MOZ_DIAGNOSTIC_ASSERT(mTRRSkippedReason ==
301 mozilla::net::TRRSkippedReason::TRR_OK);
302 uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
303 Telemetry::Accumulate(Telemetry::DNS_TRR_LOOKUP_TIME3,
304 TRRService::ProviderKey(), millis);
306 AccumulateCategoricalKeyed(
307 TRRService::ProviderKey(),
308 mTRRSuccess ? Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrOK
309 : Telemetry::LABELS_DNS_LOOKUP_DISPOSITION3::trrFail);
312 if (nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST ||
313 nsHostResolver::Mode() == nsIDNSService::MODE_TRRONLY) {
314 MOZ_ASSERT(mTRRSkippedReason != mozilla::net::TRRSkippedReason::TRR_UNSET);
316 Telemetry::Accumulate(Telemetry::TRR_SKIP_REASON_TRR_FIRST2,
317 TRRService::ProviderKey(),
318 static_cast<uint32_t>(mTRRSkippedReason));
319 if (!mTRRSuccess && LoadNativeUsed()) {
320 Telemetry::Accumulate(
321 mNativeSuccess ? Telemetry::TRR_SKIP_REASON_NATIVE_SUCCESS
322 : Telemetry::TRR_SKIP_REASON_NATIVE_FAILED,
323 TRRService::ProviderKey(), static_cast<uint32_t>(mTRRSkippedReason));
326 if (IsRelevantTRRSkipReason(mTRRSkippedReason)) {
327 Telemetry::Accumulate(Telemetry::TRR_RELEVANT_SKIP_REASON_TRR_FIRST,
328 TRRService::ProviderKey(),
329 static_cast<uint32_t>(mTRRSkippedReason));
331 if (!mTRRSuccess && LoadNativeUsed()) {
332 Telemetry::Accumulate(
333 mNativeSuccess ? Telemetry::TRR_RELEVANT_SKIP_REASON_NATIVE_SUCCESS
334 : Telemetry::TRR_RELEVANT_SKIP_REASON_NATIVE_FAILED,
335 TRRService::ProviderKey(),
336 static_cast<uint32_t>(mTRRSkippedReason));
340 if (StaticPrefs::network_trr_retry_on_recoverable_errors() &&
341 nsHostResolver::Mode() == nsIDNSService::MODE_TRRFIRST) {
342 nsAutoCString telemetryKey(TRRService::ProviderKey());
344 if (mFirstTRRSkippedReason != mozilla::net::TRRSkippedReason::TRR_UNSET) {
345 telemetryKey.AppendLiteral("|");
346 telemetryKey.AppendInt(static_cast<uint32_t>(mFirstTRRSkippedReason));
348 Telemetry::Accumulate(mTRRSuccess
349 ? Telemetry::TRR_SKIP_REASON_RETRY_SUCCESS
350 : Telemetry::TRR_SKIP_REASON_RETRY_FAILED,
351 TRRService::ProviderKey(),
352 static_cast<uint32_t>(mFirstTRRSkippedReason));
355 Telemetry::Accumulate(Telemetry::TRR_SKIP_REASON_STRICT_MODE,
356 telemetryKey,
357 static_cast<uint32_t>(mTRRSkippedReason));
359 if (mTRRSuccess) {
360 Telemetry::Accumulate(Telemetry::TRR_ATTEMPT_COUNT,
361 TRRService::ProviderKey(), mTrrAttempts);
366 if (mEffectiveTRRMode == nsIRequest::TRR_FIRST_MODE) {
367 if (flags & nsIDNSService::RESOLVE_DISABLE_TRR) {
368 // TRR is disabled on request, which is a next-level back-off method.
369 Telemetry::Accumulate(Telemetry::DNS_TRR_DISABLED3,
370 TRRService::ProviderKey(), mNativeSuccess);
371 } else {
372 if (mTRRSuccess) {
373 AccumulateCategoricalKeyed(TRRService::ProviderKey(),
374 Telemetry::LABELS_DNS_TRR_FIRST4::TRR);
375 } else if (mNativeSuccess) {
376 if (mResolverType == DNSResolverType::TRR) {
377 AccumulateCategoricalKeyed(
378 TRRService::ProviderKey(),
379 Telemetry::LABELS_DNS_TRR_FIRST4::NativeAfterTRR);
380 } else {
381 AccumulateCategoricalKeyed(TRRService::ProviderKey(),
382 Telemetry::LABELS_DNS_TRR_FIRST4::Native);
384 } else {
385 AccumulateCategoricalKeyed(
386 TRRService::ProviderKey(),
387 Telemetry::LABELS_DNS_TRR_FIRST4::BothFailed);
392 switch (mEffectiveTRRMode) {
393 case nsIRequest::TRR_DISABLED_MODE:
394 AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::nativeOnly);
395 break;
396 case nsIRequest::TRR_FIRST_MODE:
397 AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrFirst);
398 break;
399 case nsIRequest::TRR_ONLY_MODE:
400 AccumulateCategorical(Telemetry::LABELS_DNS_LOOKUP_ALGORITHM::trrOnly);
401 break;
402 case nsIRequest::TRR_DEFAULT_MODE:
403 MOZ_ASSERT_UNREACHABLE("We should not have a default value here");
404 break;
407 if (mResolverType == DNSResolverType::TRR && !mTRRSuccess && mNativeSuccess &&
408 !LoadGetTtl() && TRRService::Get()) {
409 TRRService::Get()->AddToBlocklist(nsCString(host), originSuffix, pb, true);
413 AddrHostRecord::DnsPriority AddrHostRecord::GetPriority(
414 nsIDNSService::DNSFlags aFlags) {
415 if (IsHighPriority(aFlags)) {
416 return AddrHostRecord::DNS_PRIORITY_HIGH;
418 if (IsMediumPriority(aFlags)) {
419 return AddrHostRecord::DNS_PRIORITY_MEDIUM;
422 return AddrHostRecord::DNS_PRIORITY_LOW;
425 nsresult AddrHostRecord::GetTtl(uint32_t* aResult) {
426 NS_ENSURE_ARG(aResult);
427 *aResult = mTtl;
428 return NS_OK;
431 //----------------------------------------------------------------------------
432 // TypeHostRecord
433 //----------------------------------------------------------------------------
435 NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
436 nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
438 TypeHostRecord::TypeHostRecord(const nsHostKey& key)
439 : nsHostRecord(key), DNSHTTPSSVCRecordBase(key.host) {}
441 TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
443 bool TypeHostRecord::HasUsableResultInternal(
444 const mozilla::TimeStamp& now, nsIDNSService::DNSFlags queryFlags) const {
445 if (CheckExpiration(now) == EXP_EXPIRED) {
446 return false;
449 if (negative) {
450 return true;
453 MOZ_PUSH_IGNORE_THREAD_SAFETY
454 // To avoid locking in a const method
455 return !mResults.is<Nothing>();
456 MOZ_POP_THREAD_SAFETY
459 bool TypeHostRecord::RefreshForNegativeResponse() const { return false; }
461 NS_IMETHODIMP TypeHostRecord::GetRecords(CopyableTArray<nsCString>& aRecords) {
462 // deep copy
463 MutexAutoLock lock(mResultsLock);
465 if (!mResults.is<TypeRecordTxt>()) {
466 return NS_ERROR_NOT_AVAILABLE;
468 aRecords = mResults.as<CopyableTArray<nsCString>>();
469 return NS_OK;
472 NS_IMETHODIMP TypeHostRecord::GetRecordsAsOneString(nsACString& aRecords) {
473 // deep copy
474 MutexAutoLock lock(mResultsLock);
476 if (!mResults.is<TypeRecordTxt>()) {
477 return NS_ERROR_NOT_AVAILABLE;
479 auto& results = mResults.as<CopyableTArray<nsCString>>();
480 for (uint32_t i = 0; i < results.Length(); i++) {
481 aRecords.Append(results[i]);
483 return NS_OK;
486 size_t TypeHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
487 size_t n = mallocSizeOf(this);
489 n += nsHostKey::SizeOfExcludingThis(mallocSizeOf);
490 n += SizeOfResolveHostCallbackListExcludingHead(mCallbacks, mallocSizeOf);
492 return n;
495 uint32_t TypeHostRecord::GetType() {
496 MutexAutoLock lock(mResultsLock);
498 return mResults.match(
499 [](TypeRecordEmpty&) {
500 MOZ_ASSERT(false, "This should never be the case");
501 return nsIDNSService::RESOLVE_TYPE_DEFAULT;
503 [](TypeRecordTxt&) { return nsIDNSService::RESOLVE_TYPE_TXT; },
504 [](TypeRecordHTTPSSVC&) { return nsIDNSService::RESOLVE_TYPE_HTTPSSVC; });
507 TypeRecordResultType TypeHostRecord::GetResults() {
508 MutexAutoLock lock(mResultsLock);
509 return mResults;
512 NS_IMETHODIMP
513 TypeHostRecord::GetRecords(nsTArray<RefPtr<nsISVCBRecord>>& aRecords) {
514 MutexAutoLock lock(mResultsLock);
515 if (!mResults.is<TypeRecordHTTPSSVC>()) {
516 return NS_ERROR_NOT_AVAILABLE;
519 auto& results = mResults.as<TypeRecordHTTPSSVC>();
521 for (const SVCB& r : results) {
522 RefPtr<nsISVCBRecord> rec = new mozilla::net::SVCBRecord(r);
523 aRecords.AppendElement(rec);
526 return NS_OK;
529 NS_IMETHODIMP
530 TypeHostRecord::GetServiceModeRecord(bool aNoHttp2, bool aNoHttp3,
531 nsISVCBRecord** aRecord) {
532 return GetServiceModeRecordWithCname(aNoHttp2, aNoHttp3, ""_ns, aRecord);
535 NS_IMETHODIMP
536 TypeHostRecord::GetServiceModeRecordWithCname(bool aNoHttp2, bool aNoHttp3,
537 const nsACString& aCname,
538 nsISVCBRecord** aRecord) {
539 MutexAutoLock lock(mResultsLock);
540 if (!mResults.is<TypeRecordHTTPSSVC>()) {
541 return NS_ERROR_NOT_AVAILABLE;
544 auto& results = mResults.as<TypeRecordHTTPSSVC>();
545 nsCOMPtr<nsISVCBRecord> result = GetServiceModeRecordInternal(
546 aNoHttp2, aNoHttp3, results, mAllRecordsExcluded, true, aCname);
547 if (!result) {
548 return NS_ERROR_NOT_AVAILABLE;
551 result.forget(aRecord);
552 return NS_OK;
555 NS_IMETHODIMP
556 TypeHostRecord::IsTRR(bool* aResult) {
557 *aResult = (mResolverType == DNSResolverType::TRR);
558 return NS_OK;
561 NS_IMETHODIMP
562 TypeHostRecord::GetAllRecordsWithEchConfig(
563 bool aNoHttp2, bool aNoHttp3, const nsACString& aCname,
564 bool* aAllRecordsHaveEchConfig, bool* aAllRecordsInH3ExcludedList,
565 nsTArray<RefPtr<nsISVCBRecord>>& aResult) {
566 MutexAutoLock lock(mResultsLock);
567 if (!mResults.is<TypeRecordHTTPSSVC>()) {
568 return NS_ERROR_NOT_AVAILABLE;
571 auto& records = mResults.as<TypeRecordHTTPSSVC>();
572 GetAllRecordsWithEchConfigInternal(aNoHttp2, aNoHttp3, aCname, records,
573 aAllRecordsHaveEchConfig,
574 aAllRecordsInH3ExcludedList, aResult);
575 return NS_OK;
578 NS_IMETHODIMP
579 TypeHostRecord::GetHasIPAddresses(bool* aResult) {
580 NS_ENSURE_ARG(aResult);
581 MutexAutoLock lock(mResultsLock);
583 if (!mResults.is<TypeRecordHTTPSSVC>()) {
584 return NS_ERROR_NOT_AVAILABLE;
587 auto& results = mResults.as<TypeRecordHTTPSSVC>();
588 *aResult = HasIPAddressesInternal(results);
589 return NS_OK;
592 NS_IMETHODIMP
593 TypeHostRecord::GetAllRecordsExcluded(bool* aResult) {
594 NS_ENSURE_ARG(aResult);
595 MutexAutoLock lock(mResultsLock);
597 if (!mResults.is<TypeRecordHTTPSSVC>()) {
598 return NS_ERROR_NOT_AVAILABLE;
601 *aResult = mAllRecordsExcluded;
602 return NS_OK;
605 NS_IMETHODIMP
606 TypeHostRecord::GetTtl(uint32_t* aResult) {
607 NS_ENSURE_ARG(aResult);
608 *aResult = mTtl;
609 return NS_OK;
612 void TypeHostRecord::ResolveComplete() {
613 if (IsRelevantTRRSkipReason(mTRRSkippedReason)) {
614 Telemetry::Accumulate(
615 Telemetry::TRR_RELEVANT_SKIP_REASON_TRR_FIRST_TYPE_REC,
616 TRRService::ProviderKey(), static_cast<uint32_t>(mTRRSkippedReason));
619 uint32_t millis = static_cast<uint32_t>(mTrrDuration.ToMilliseconds());
620 if (mTRRSuccess) {
621 Telemetry::Accumulate(Telemetry::DNS_BY_TYPE_SUCCEEDED_LOOKUP_TIME, millis);
622 } else {
623 Telemetry::Accumulate(Telemetry::DNS_BY_TYPE_FAILED_LOOKUP_TIME, millis);