1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 "nsCharSeparatedTokenizer.h"
7 #include "nsComponentManagerUtils.h"
8 #include "nsDirectoryServiceUtils.h"
9 #include "nsHttpConnectionInfo.h"
10 #include "nsICaptivePortalService.h"
12 #include "nsIParentalControlsService.h"
13 #include "nsINetworkLinkService.h"
14 #include "nsIObserverService.h"
15 #include "nsIOService.h"
16 #include "nsNetUtil.h"
17 #include "nsStandardURL.h"
19 #include "TRRService.h"
21 #include "mozilla/Preferences.h"
22 #include "mozilla/StaticPrefs_network.h"
23 #include "mozilla/Telemetry.h"
24 #include "mozilla/TelemetryComms.h"
25 #include "mozilla/Tokenizer.h"
26 #include "mozilla/dom/ContentParent.h"
27 #include "mozilla/net/NeckoParent.h"
28 #include "mozilla/net/TRRServiceChild.h"
29 // Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
30 #include "DNSLogging.h"
32 static const char kOpenCaptivePortalLoginEvent
[] = "captive-portal-login";
33 static const char kClearPrivateData
[] = "clear-private-data";
34 static const char kPurge
[] = "browser:purge-session-history";
35 static const char kDisableIpv6Pref
[] = "network.dns.disableIPv6";
37 #define TRR_PREF_PREFIX "network.trr."
38 #define TRR_PREF(x) TRR_PREF_PREFIX x
40 namespace mozilla::net
{
42 StaticRefPtr
<nsIThread
> sTRRBackgroundThread
;
43 static Atomic
<TRRService
*> sTRRServicePtr
;
45 static Atomic
<size_t, Relaxed
> sDomainIndex(0);
46 static Atomic
<size_t, Relaxed
> sCurrentTRRModeIndex(0);
48 constexpr nsLiteralCString kTRRDomains
[3][7] = {
51 // When mode is 0, the provider key has no postfix.
53 "mozilla.cloudflare-dns.com"_ns
,
54 "firefox.dns.nextdns.io"_ns
,
55 "private.canadianshield.cira.ca"_ns
,
56 "doh.xfinity.com"_ns
, // Steered clients
57 "dns.shaw.ca"_ns
, // Steered clients
58 "dooh.cloudflare-dns.com"_ns
, // DNS over Oblivious HTTP
62 "mozilla.cloudflare-dns.com_2"_ns
,
63 "firefox.dns.nextdns.io_2"_ns
,
64 "private.canadianshield.cira.ca_2"_ns
,
65 "doh.xfinity.com_2"_ns
, // Steered clients
66 "dns.shaw.ca_2"_ns
, // Steered clients
67 "dooh.cloudflare-dns.com_2"_ns
, // DNS over Oblivious HTTP
71 "mozilla.cloudflare-dns.com_3"_ns
,
72 "firefox.dns.nextdns.io_3"_ns
,
73 "private.canadianshield.cira.ca_3"_ns
,
74 "doh.xfinity.com_3"_ns
, // Steered clients
75 "dns.shaw.ca_3"_ns
, // Steered clients
76 "dooh.cloudflare-dns.com_3"_ns
, // DNS over Oblivious HTTP
82 void TRRService::SetCurrentTRRMode(nsIDNSService::ResolverMode aMode
) {
83 // A table to map ResolverMode to the row of kTRRDomains.
84 // When the aMode is 2, we use kTRRDomains[1] as provider keys. When aMode is
85 // 3, we use kTRRDomains[2]. Otherwise, we kTRRDomains[0] is used.
86 static const uint32_t index
[] = {0, 0, 1, 2, 0, 0};
87 if (aMode
> nsIDNSService::MODE_TRROFF
) {
88 aMode
= nsIDNSService::MODE_TRROFF
;
90 sCurrentTRRModeIndex
= index
[static_cast<size_t>(aMode
)];
94 void TRRService::SetProviderDomain(const nsACString
& aTRRDomain
) {
96 for (size_t i
= 1; i
< std::size(kTRRDomains
[0]); i
++) {
97 if (aTRRDomain
.Equals(kTRRDomains
[0][i
])) {
105 const nsCString
& TRRService::ProviderKey() {
106 return kTRRDomains
[sCurrentTRRModeIndex
][sDomainIndex
];
109 NS_IMPL_ISUPPORTS_INHERITED(TRRService
, TRRServiceBase
, nsIObserver
,
110 nsISupportsWeakReference
)
112 NS_IMPL_ADDREF_USING_AGGREGATOR(TRRService::ConfirmationContext
, OwningObject())
113 NS_IMPL_RELEASE_USING_AGGREGATOR(TRRService::ConfirmationContext
,
115 NS_IMPL_QUERY_INTERFACE(TRRService::ConfirmationContext
, nsITimerCallback
,
118 TRRService::TRRService() : mLock("TRRService", this) {
119 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
123 TRRService
* TRRService::Get() { return sTRRServicePtr
; }
126 void TRRService::AddObserver(nsIObserver
* aObserver
,
127 nsIObserverService
* aObserverService
) {
128 nsCOMPtr
<nsIObserverService
> observerService
;
129 if (aObserverService
) {
130 observerService
= aObserverService
;
132 observerService
= mozilla::services::GetObserverService();
135 if (observerService
) {
136 observerService
->AddObserver(aObserver
, NS_CAPTIVE_PORTAL_CONNECTIVITY
,
138 observerService
->AddObserver(aObserver
, kOpenCaptivePortalLoginEvent
, true);
139 observerService
->AddObserver(aObserver
, kClearPrivateData
, true);
140 observerService
->AddObserver(aObserver
, kPurge
, true);
141 observerService
->AddObserver(aObserver
, NS_NETWORK_LINK_TOPIC
, true);
142 observerService
->AddObserver(aObserver
, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC
,
144 observerService
->AddObserver(aObserver
, "xpcom-shutdown-threads", true);
149 bool TRRService::CheckCaptivePortalIsPassed() {
151 nsCOMPtr
<nsICaptivePortalService
> captivePortalService
=
152 do_GetService(NS_CAPTIVEPORTAL_CID
);
153 if (captivePortalService
) {
154 int32_t captiveState
;
155 MOZ_ALWAYS_SUCCEEDS(captivePortalService
->GetState(&captiveState
));
157 if ((captiveState
== nsICaptivePortalService::UNLOCKED_PORTAL
) ||
158 (captiveState
== nsICaptivePortalService::NOT_CAPTIVE
)) {
161 LOG(("TRRService::Init mCaptiveState=%d mCaptiveIsPassed=%d\n",
162 captiveState
, (int)result
));
168 static void EventTelemetryPrefChanged(const char* aPref
, void* aData
) {
169 Telemetry::SetEventRecordingEnabled(
171 StaticPrefs::network_trr_confirmation_telemetry_enabled());
174 nsresult
TRRService::Init() {
175 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
183 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
184 GetPrefBranch(getter_AddRefs(prefBranch
));
186 prefBranch
->AddObserver(TRR_PREF_PREFIX
, this, true);
187 prefBranch
->AddObserver(kDisableIpv6Pref
, this, true);
188 prefBranch
->AddObserver(kRolloutURIPref
, this, true);
189 prefBranch
->AddObserver(kRolloutModePref
, this, true);
192 sTRRServicePtr
= this;
195 mConfirmation
.HandleEvent(ConfirmationEvent::Init
);
197 if (XRE_IsParentProcess()) {
198 mCaptiveIsPassed
= CheckCaptivePortalIsPassed();
200 mParentalControlEnabled
= GetParentalControlEnabledInternal();
202 mLinkService
= do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID
);
204 nsTArray
<nsCString
> suffixList
;
205 mLinkService
->GetDnsSuffixList(suffixList
);
206 RebuildSuffixList(std::move(suffixList
));
209 nsCOMPtr
<nsIThread
> thread
;
211 NS_NewNamedThread("TRR Background", getter_AddRefs(thread
)))) {
212 NS_WARNING("NS_NewNamedThread failed!");
213 return NS_ERROR_FAILURE
;
216 sTRRBackgroundThread
= thread
;
219 Preferences::RegisterCallbackAndCall(
220 EventTelemetryPrefChanged
,
221 "network.trr.confirmation_telemetry_enabled"_ns
);
223 LOG(("Initialized TRRService\n"));
228 bool TRRService::GetParentalControlEnabledInternal() {
229 nsCOMPtr
<nsIParentalControlsService
> pc
=
230 do_CreateInstance("@mozilla.org/parental-controls-service;1");
233 pc
->GetParentalControlsEnabled(&result
);
234 LOG(("TRRService::GetParentalControlEnabledInternal=%d\n", result
));
241 void TRRService::SetDetectedTrrURI(const nsACString
& aURI
) {
242 LOG(("SetDetectedTrrURI(%s", nsPromiseFlatCString(aURI
).get()));
243 // If the user has set a custom URI then we don't want to override that.
244 // If the URI is set via doh-rollout.uri, mURIPref will be empty
245 // (see TRRServiceBase::OnTRRURIChange)
246 if (!mURIPref
.IsEmpty()) {
247 LOG(("Already has user value. Not setting URI"));
251 if (StaticPrefs::network_trr_use_ohttp()) {
252 LOG(("No autodetection when using OHTTP"));
256 mURISetByDetection
= MaybeSetPrivateURI(aURI
);
259 bool TRRService::Enabled(nsIRequest::TRRMode aRequestMode
) {
260 if (mMode
== nsIDNSService::MODE_TRROFF
||
261 aRequestMode
== nsIRequest::TRR_DISABLED_MODE
) {
262 LOG(("TRR service not enabled - off or disabled"));
266 // If already confirmed, service is enabled.
267 if (mConfirmation
.State() == CONFIRM_OK
||
268 aRequestMode
== nsIRequest::TRR_ONLY_MODE
) {
269 LOG(("TRR service enabled - confirmed or trr_only request"));
273 // If this is a TRR_FIRST request but the resolver has a different mode,
274 // just go ahead and let it try to use TRR.
275 if (aRequestMode
== nsIRequest::TRR_FIRST_MODE
&&
276 mMode
!= nsIDNSService::MODE_TRRFIRST
) {
277 LOG(("TRR service enabled - trr_first request"));
281 // In TRR_ONLY_MODE / confirmationNS == "skip" we don't try to confirm.
282 if (mConfirmation
.State() == CONFIRM_DISABLED
) {
283 LOG(("TRRService service enabled - confirmation is disabled"));
287 LOG(("TRRService::Enabled mConfirmation.mState=%d mCaptiveIsPassed=%d\n",
288 mConfirmation
.State(), (int)mCaptiveIsPassed
));
290 if (StaticPrefs::network_trr_wait_for_confirmation()) {
291 return mConfirmation
.State() == CONFIRM_OK
;
294 if (StaticPrefs::network_trr_attempt_when_retrying_confirmation()) {
295 return mConfirmation
.State() == CONFIRM_OK
||
296 mConfirmation
.State() == CONFIRM_TRYING_OK
||
297 mConfirmation
.State() == CONFIRM_TRYING_FAILED
;
300 return mConfirmation
.State() == CONFIRM_OK
||
301 mConfirmation
.State() == CONFIRM_TRYING_OK
;
304 void TRRService::GetPrefBranch(nsIPrefBranch
** result
) {
305 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
307 CallGetService(NS_PREFSERVICE_CONTRACTID
, result
);
310 bool TRRService::MaybeSetPrivateURI(const nsACString
& aURI
) {
311 bool clearCache
= false;
312 nsAutoCString
newURI(aURI
);
313 LOG(("MaybeSetPrivateURI(%s)", newURI
.get()));
315 ProcessURITemplate(newURI
);
317 MutexSingleWriterAutoLock
lock(mLock
);
318 if (mPrivateURI
.Equals(newURI
)) {
322 if (!mPrivateURI
.IsEmpty()) {
323 LOG(("TRRService clearing blocklist because of change in uri service\n"));
324 auto bl
= mTRRBLStorage
.Lock();
331 nsCOMPtr
<nsIURI
> url
;
332 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(url
), newURI
))) {
336 SetProviderDomain(host
);
338 mPrivateURI
= newURI
;
340 // Notify the content processes of the new TRR
342 dom::ContentParent::AllProcesses(dom::ContentParent::eLive
)) {
343 PNeckoParent
* neckoParent
=
344 SingleManagedOrNull(cp
->ManagedPNeckoParent());
348 Unused
<< neckoParent
->SendSetTRRDomain(host
);
351 AsyncCreateTRRConnectionInfo(mPrivateURI
);
353 // The URI has changed. We should trigger a new confirmation immediately.
354 // We must do this here because the URI could also change because of
356 mConfirmationTriggered
=
357 mConfirmation
.HandleEvent(ConfirmationEvent::URIChange
, lock
);
360 // Clear the cache because we changed the URI
365 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
367 obs
->NotifyObservers(nullptr, NS_NETWORK_TRR_URI_CHANGED_TOPIC
, nullptr);
372 nsresult
TRRService::ReadPrefs(const char* name
) {
373 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
375 // Whenever a pref change occurs that would cause us to clear the cache
376 // we set this to true then do it at the end of the method.
377 bool clearEntireCache
= false;
379 if (!name
|| !strcmp(name
, TRR_PREF("mode")) ||
380 !strcmp(name
, kRolloutModePref
)) {
381 nsIDNSService::ResolverMode prevMode
= Mode();
384 // When the TRR service gets disabled we should purge the TRR cache to
385 // make sure we don't use any of the cached entries on a network where
386 // they are invalid - for example after turning on a VPN.
387 if (TRR_DISABLED(Mode()) && !TRR_DISABLED(prevMode
)) {
388 clearEntireCache
= true;
391 if (!name
|| !strcmp(name
, TRR_PREF("uri")) ||
392 !strcmp(name
, TRR_PREF("default_provider_uri")) ||
393 !strcmp(name
, kRolloutURIPref
) || !strcmp(name
, TRR_PREF("ohttp.uri")) ||
394 !strcmp(name
, TRR_PREF("use_ohttp"))) {
397 if (!name
|| !strcmp(name
, TRR_PREF("credentials"))) {
398 MutexSingleWriterAutoLock
lock(mLock
);
399 Preferences::GetCString(TRR_PREF("credentials"), mPrivateCred
);
401 if (!name
|| !strcmp(name
, TRR_PREF("confirmationNS"))) {
402 MutexSingleWriterAutoLock
lock(mLock
);
403 Preferences::GetCString(TRR_PREF("confirmationNS"), mConfirmationNS
);
404 LOG(("confirmationNS = %s", mConfirmationNS
.get()));
406 if (!name
|| !strcmp(name
, TRR_PREF("bootstrapAddr"))) {
407 MutexSingleWriterAutoLock
lock(mLock
);
408 Preferences::GetCString(TRR_PREF("bootstrapAddr"), mBootstrapAddr
);
409 clearEntireCache
= true;
411 if (!name
|| !strcmp(name
, kDisableIpv6Pref
)) {
413 if (NS_SUCCEEDED(Preferences::GetBool(kDisableIpv6Pref
, &tmp
))) {
417 if (!name
|| !strcmp(name
, TRR_PREF("excluded-domains")) ||
418 !strcmp(name
, TRR_PREF("builtin-excluded-domains"))) {
419 MutexSingleWriterAutoLock
lock(mLock
);
420 mExcludedDomains
.Clear();
422 auto parseExcludedDomains
= [this](const char* aPrefName
) {
423 nsAutoCString excludedDomains
;
424 mLock
.AssertCurrentThreadOwns();
425 Preferences::GetCString(aPrefName
, excludedDomains
);
426 if (excludedDomains
.IsEmpty()) {
430 for (const nsACString
& tokenSubstring
:
431 nsCCharSeparatedTokenizerTemplate
<
432 NS_IsAsciiWhitespace
, nsTokenizerFlags::SeparatorOptional
>(
433 excludedDomains
, ',')
435 nsCString token
{tokenSubstring
};
436 LOG(("TRRService::ReadPrefs %s host:[%s]\n", aPrefName
, token
.get()));
437 mExcludedDomains
.Insert(token
);
441 parseExcludedDomains(TRR_PREF("excluded-domains"));
442 parseExcludedDomains(TRR_PREF("builtin-excluded-domains"));
443 clearEntireCache
= true;
446 // if name is null, then we're just now initializing. In that case we don't
447 // need to clear the cache.
448 if (name
&& clearEntireCache
) {
455 void TRRService::ClearEntireCache() {
456 if (!StaticPrefs::network_trr_clear_cache_on_pref_change()) {
459 nsCOMPtr
<nsIDNSService
> dns
= do_GetService(NS_DNSSERVICE_CONTRACTID
);
463 dns
->ClearCache(true);
466 void TRRService::AddEtcHosts(const nsTArray
<nsCString
>& aArray
) {
467 MutexSingleWriterAutoLock
lock(mLock
);
468 for (const auto& item
: aArray
) {
469 LOG(("Adding %s from /etc/hosts to excluded domains", item
.get()));
470 mEtcHostsDomains
.Insert(item
);
474 void TRRService::ReadEtcHostsFile() {
475 if (!XRE_IsParentProcess()) {
479 DoReadEtcHostsFile([](const nsTArray
<nsCString
>* aArray
) -> bool {
480 RefPtr
<TRRService
> service(sTRRServicePtr
);
481 if (service
&& aArray
) {
482 service
->AddEtcHosts(*aArray
);
488 void TRRService::GetURI(nsACString
& result
) {
489 MutexSingleWriterAutoLock
lock(mLock
);
490 result
= mPrivateURI
;
493 nsresult
TRRService::GetCredentials(nsCString
& result
) {
494 MutexSingleWriterAutoLock
lock(mLock
);
495 result
= mPrivateCred
;
499 uint32_t TRRService::GetRequestTimeout() {
500 if (mMode
== nsIDNSService::MODE_TRRONLY
) {
501 return StaticPrefs::network_trr_request_timeout_mode_trronly_ms();
504 if (StaticPrefs::network_trr_strict_native_fallback()) {
505 return StaticPrefs::network_trr_strict_fallback_request_timeout_ms();
508 return StaticPrefs::network_trr_request_timeout_ms();
511 nsresult
TRRService::Start() {
512 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
514 return NS_ERROR_NOT_INITIALIZED
;
519 TRRService::~TRRService() {
520 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
521 LOG(("Exiting TRRService\n"));
524 nsresult
TRRService::DispatchTRRRequest(TRR
* aTrrRequest
) {
525 return DispatchTRRRequestInternal(aTrrRequest
, true);
528 nsresult
TRRService::DispatchTRRRequestInternal(TRR
* aTrrRequest
,
530 NS_ENSURE_ARG_POINTER(aTrrRequest
);
532 nsCOMPtr
<nsIThread
> thread
= MainThreadOrTRRThread(aWithLock
);
534 return NS_ERROR_FAILURE
;
537 RefPtr
<TRR
> trr
= aTrrRequest
;
538 return thread
->Dispatch(trr
.forget());
541 already_AddRefed
<nsIThread
> TRRService::MainThreadOrTRRThread(bool aWithLock
) {
542 if (!StaticPrefs::network_trr_fetch_off_main_thread() ||
543 XRE_IsSocketProcess() || mDontUseTRRThread
) {
544 return do_GetMainThread();
547 nsCOMPtr
<nsIThread
> thread
= aWithLock
? TRRThread() : TRRThread_locked();
548 return thread
.forget();
551 already_AddRefed
<nsIThread
> TRRService::TRRThread() {
552 MutexSingleWriterAutoLock
lock(mLock
);
553 return TRRThread_locked();
556 already_AddRefed
<nsIThread
> TRRService::TRRThread_locked() {
557 RefPtr
<nsIThread
> thread
= sTRRBackgroundThread
;
558 return thread
.forget();
561 bool TRRService::IsOnTRRThread() {
562 nsCOMPtr
<nsIThread
> thread
;
564 MutexSingleWriterAutoLock
lock(mLock
);
565 thread
= sTRRBackgroundThread
;
571 return thread
->IsOnCurrentThread();
575 TRRService::Observe(nsISupports
* aSubject
, const char* aTopic
,
576 const char16_t
* aData
) {
577 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
578 LOG(("TRR::Observe() topic=%s\n", aTopic
));
579 if (!strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
)) {
580 // Reset the state of whether a confirmation is triggered, so we can check
581 // if we create a new one after ReadPrefs().
582 mConfirmationTriggered
= false;
583 ReadPrefs(NS_ConvertUTF16toUTF8(aData
).get());
585 MutexSingleWriterAutoLock
lock(mLock
);
586 mConfirmation
.RecordEvent("pref-change", lock
);
589 // We should only trigger a new confirmation if reading the prefs didn't
590 // already trigger one.
591 if (!mConfirmationTriggered
) {
592 mConfirmation
.HandleEvent(ConfirmationEvent::PrefChange
);
594 } else if (!strcmp(aTopic
, kOpenCaptivePortalLoginEvent
)) {
595 // We are in a captive portal
596 LOG(("TRRservice in captive portal\n"));
597 mCaptiveIsPassed
= false;
598 mConfirmation
.SetCaptivePortalStatus(
599 nsICaptivePortalService::LOCKED_PORTAL
);
600 } else if (!strcmp(aTopic
, NS_CAPTIVE_PORTAL_CONNECTIVITY
)) {
601 nsAutoCString data
= NS_ConvertUTF16toUTF8(aData
);
602 LOG(("TRRservice captive portal was %s\n", data
.get()));
603 nsCOMPtr
<nsICaptivePortalService
> cps
= do_QueryInterface(aSubject
);
605 mConfirmation
.SetCaptivePortalStatus(cps
->State());
608 // If we were previously in a captive portal, this event means we will
609 // need to trigger confirmation again. Otherwise it's just a periodical
610 // captive-portal check that completed and we don't need to react to it.
611 if (!mCaptiveIsPassed
) {
612 mConfirmation
.HandleEvent(ConfirmationEvent::CaptivePortalConnectivity
);
615 mCaptiveIsPassed
= true;
616 } else if (!strcmp(aTopic
, kClearPrivateData
) || !strcmp(aTopic
, kPurge
)) {
617 // flush the TRR blocklist
618 auto bl
= mTRRBLStorage
.Lock();
620 } else if (!strcmp(aTopic
, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC
) ||
621 !strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
)) {
622 // nsINetworkLinkService is only available on parent process.
623 if (XRE_IsParentProcess()) {
624 nsCOMPtr
<nsINetworkLinkService
> link
= do_QueryInterface(aSubject
);
625 // The network link service notification normally passes itself as the
626 // subject, but some unit tests will sometimes pass a null subject.
628 nsTArray
<nsCString
> suffixList
;
629 link
->GetDnsSuffixList(suffixList
);
630 RebuildSuffixList(std::move(suffixList
));
634 if (!strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
)) {
635 if (NS_ConvertUTF16toUTF8(aData
).EqualsLiteral(
636 NS_NETWORK_LINK_DATA_DOWN
)) {
637 MutexSingleWriterAutoLock
lock(mLock
);
638 mConfirmation
.RecordEvent("network-change", lock
);
641 if (mURISetByDetection
) {
642 // If the URI was set via SetDetectedTrrURI we need to restore it to the
643 // default pref when a network link change occurs.
647 if (NS_ConvertUTF16toUTF8(aData
).EqualsLiteral(NS_NETWORK_LINK_DATA_UP
)) {
648 mConfirmation
.HandleEvent(ConfirmationEvent::NetworkUp
);
651 } else if (!strcmp(aTopic
, "xpcom-shutdown-threads")) {
653 // If a confirmation is still in progress we record the event.
654 // Since there should be no more confirmations after this, the shutdown
655 // reason would not really be recorded in telemetry.
657 MutexSingleWriterAutoLock
lock(mLock
);
658 mConfirmation
.RecordEvent("shutdown", lock
);
661 if (sTRRBackgroundThread
) {
662 nsCOMPtr
<nsIThread
> thread
;
663 thread
= sTRRBackgroundThread
.get();
664 sTRRBackgroundThread
= nullptr;
665 MOZ_ALWAYS_SUCCEEDS(thread
->Shutdown());
666 sTRRServicePtr
= nullptr;
672 void TRRService::RebuildSuffixList(nsTArray
<nsCString
>&& aSuffixList
) {
673 if (!StaticPrefs::network_trr_split_horizon_mitigations() || mShutdown
) {
677 MutexSingleWriterAutoLock
lock(mLock
);
678 mDNSSuffixDomains
.Clear();
679 for (const auto& item
: aSuffixList
) {
680 LOG(("TRRService adding %s to suffix list", item
.get()));
681 mDNSSuffixDomains
.Insert(item
);
685 void TRRService::ConfirmationContext::SetState(
686 enum ConfirmationState aNewState
) {
689 enum ConfirmationState state
= mState
;
690 if (XRE_IsParentProcess()) {
691 NS_DispatchToMainThread(NS_NewRunnableFunction(
692 "TRRService::ConfirmationContextNotify", [state
] {
693 if (nsCOMPtr
<nsIObserverService
> obs
=
694 mozilla::services::GetObserverService()) {
696 [](enum ConfirmationState aState
) -> const char16_t
* {
699 return u
"CONFIRM_OFF";
700 case CONFIRM_TRYING_OK
:
701 return u
"CONFIRM_TRYING_OK";
703 return u
"CONFIRM_OK";
705 return u
"CONFIRM_FAILED";
706 case CONFIRM_TRYING_FAILED
:
707 return u
"CONFIRM_TRYING_FAILED";
708 case CONFIRM_DISABLED
:
709 return u
"CONFIRM_DISABLED";
711 MOZ_ASSERT_UNREACHABLE();
715 obs
->NotifyObservers(nullptr, "network:trr-confirmation",
721 if (XRE_IsParentProcess()) {
725 MOZ_ASSERT(XRE_IsSocketProcess());
726 MOZ_ASSERT(NS_IsMainThread());
728 TRRServiceChild
* child
= TRRServiceChild::GetSingleton();
729 if (child
&& child
->CanSend()) {
730 LOG(("TRRService::SendSetConfirmationState"));
731 Unused
<< child
->SendSetConfirmationState(mState
);
735 bool TRRService::ConfirmationContext::HandleEvent(ConfirmationEvent aEvent
) {
736 MutexSingleWriterAutoLock
lock(OwningObject()->mLock
);
737 return HandleEvent(aEvent
, lock
);
740 // We're protected by service->mLock
741 bool TRRService::ConfirmationContext::HandleEvent(
742 ConfirmationEvent aEvent
, const MutexSingleWriterAutoLock
&) {
743 auto prevAddr
= TaskAddr();
744 TRRService
* service
= OwningObject();
745 service
->mLock
.AssertCurrentThreadOwns();
746 nsIDNSService::ResolverMode mode
= service
->Mode();
748 auto resetConfirmation
= [&]() {
749 service
->mLock
.AssertCurrentThreadOwns();
751 nsCOMPtr
<nsITimer
> timer
= std::move(mTimer
);
756 mRetryInterval
= StaticPrefs::network_trr_retry_timeout_ms();
759 if (TRR_DISABLED(mode
)) {
760 LOG(("TRR is disabled. mConfirmation.mState -> CONFIRM_OFF"));
761 SetState(CONFIRM_OFF
);
765 if (mode
== nsIDNSService::MODE_TRRONLY
) {
766 LOG(("TRR_ONLY_MODE. mConfirmation.mState -> CONFIRM_DISABLED"));
767 SetState(CONFIRM_DISABLED
);
771 if (service
->mConfirmationNS
.Equals("skip"_ns
)) {
773 "mConfirmationNS == skip. mConfirmation.mState -> CONFIRM_DISABLED"));
774 SetState(CONFIRM_DISABLED
);
778 // The next call to maybeConfirm will transition to CONFIRM_TRYING_OK
779 LOG(("mConfirmation.mState -> CONFIRM_OK"));
780 SetState(CONFIRM_OK
);
783 auto maybeConfirm
= [&](const char* aReason
) {
784 service
->mLock
.AssertCurrentThreadOwns();
785 if (TRR_DISABLED(mode
) || mState
== CONFIRM_DISABLED
|| mTask
) {
787 ("TRRService:MaybeConfirm(%s) mode=%d, mTask=%p "
789 aReason
, (int)mode
, (void*)mTask
, (int)mState
));
793 MOZ_ASSERT(mode
!= nsIDNSService::MODE_TRRONLY
,
794 "Confirmation should be disabled");
795 MOZ_ASSERT(!service
->mConfirmationNS
.Equals("skip"),
796 "Confirmation should be disabled");
798 LOG(("maybeConfirm(%s) starting confirmation test %s %s\n", aReason
,
799 service
->mPrivateURI
.get(), service
->mConfirmationNS
.get()));
801 MOZ_ASSERT(mState
== CONFIRM_OK
|| mState
== CONFIRM_FAILED
);
803 if (mState
== CONFIRM_FAILED
) {
804 LOG(("mConfirmation.mState -> CONFIRM_TRYING_FAILED"));
805 SetState(CONFIRM_TRYING_FAILED
);
807 LOG(("mConfirmation.mState -> CONFIRM_TRYING_OK"));
808 SetState(CONFIRM_TRYING_OK
);
811 nsCOMPtr
<nsITimer
> timer
= std::move(mTimer
);
816 MOZ_ASSERT(mode
== nsIDNSService::MODE_TRRFIRST
,
817 "Should only confirm in TRR first mode");
818 // Set aUseFreshConnection if TRR lookups are retried.
819 mTask
= new TRR(service
, service
->mConfirmationNS
, TRRTYPE_NS
, ""_ns
, false,
820 StaticPrefs::network_trr_retry_on_recoverable_errors());
821 mTask
->SetTimeout(StaticPrefs::network_trr_confirmation_timeout_ms());
822 mTask
->SetPurpose(TRR::Confirmation
);
824 if (service
->mLinkService
) {
825 service
->mLinkService
->GetNetworkID(mNetworkId
);
828 if (mFirstRequestTime
.IsNull()) {
829 mFirstRequestTime
= TimeStamp::Now();
831 if (mTrigger
.IsEmpty()) {
832 mTrigger
.Assign(aReason
);
835 LOG(("Dispatching confirmation task: %p", mTask
.get()));
836 service
->DispatchTRRRequestInternal(mTask
, false);
840 case ConfirmationEvent::Init
:
842 maybeConfirm("context-init");
844 case ConfirmationEvent::PrefChange
:
846 maybeConfirm("pref-change");
848 case ConfirmationEvent::ConfirmationRetry
:
849 MOZ_ASSERT(mState
== CONFIRM_FAILED
);
850 if (mState
== CONFIRM_FAILED
) {
851 maybeConfirm("confirmation-retry");
854 case ConfirmationEvent::FailedLookups
:
855 MOZ_ASSERT(mState
== CONFIRM_OK
);
856 mTrigger
.Assign("failed-lookups");
857 mFailedLookups
= nsDependentCSubstring(
858 mFailureReasons
, mTRRFailures
% ConfirmationContext::RESULTS_SIZE
);
859 maybeConfirm("failed-lookups");
861 case ConfirmationEvent::RetryTRR
:
862 MOZ_ASSERT(mState
== CONFIRM_OK
);
863 maybeConfirm("retry-trr");
865 case ConfirmationEvent::URIChange
:
867 maybeConfirm("uri-change");
869 case ConfirmationEvent::CaptivePortalConnectivity
:
870 // If we area already confirmed then we're fine.
871 // If there is a confirmation in progress, likely it started before
872 // we had full connectivity, so it may be hanging. We reset and try again.
873 if (mState
== CONFIRM_FAILED
|| mState
== CONFIRM_TRYING_FAILED
||
874 mState
== CONFIRM_TRYING_OK
) {
876 maybeConfirm("cp-connectivity");
879 case ConfirmationEvent::NetworkUp
:
880 if (mState
!= CONFIRM_OK
) {
882 maybeConfirm("network-up");
885 case ConfirmationEvent::ConfirmOK
:
886 SetState(CONFIRM_OK
);
889 case ConfirmationEvent::ConfirmFail
:
890 MOZ_ASSERT(mState
== CONFIRM_TRYING_OK
||
891 mState
== CONFIRM_TRYING_FAILED
);
892 SetState(CONFIRM_FAILED
);
894 // retry failed NS confirmation
896 NS_NewTimerWithCallback(getter_AddRefs(mTimer
), this, mRetryInterval
,
897 nsITimer::TYPE_ONE_SHOT
);
898 if (mRetryInterval
< 64000) {
899 // double the interval up to this point
904 MOZ_ASSERT_UNREACHABLE("Unexpected ConfirmationEvent");
907 return prevAddr
!= TaskAddr();
910 bool TRRService::MaybeBootstrap(const nsACString
& aPossible
,
911 nsACString
& aResult
) {
912 MutexSingleWriterAutoLock
lock(mLock
);
913 if (mMode
== nsIDNSService::MODE_TRROFF
|| mBootstrapAddr
.IsEmpty()) {
917 nsCOMPtr
<nsIURI
> url
;
919 NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID
)
920 .Apply(&nsIStandardURLMutator::Init
, nsIStandardURL::URLTYPE_STANDARD
,
921 443, mPrivateURI
, nullptr, nullptr, nullptr)
924 LOG(("TRRService::MaybeBootstrap failed to create URI!\n"));
930 if (!aPossible
.Equals(host
)) {
933 LOG(("TRRService::MaybeBootstrap: use %s instead of %s\n",
934 mBootstrapAddr
.get(), host
.get()));
935 aResult
= mBootstrapAddr
;
939 bool TRRService::IsDomainBlocked(const nsACString
& aHost
,
940 const nsACString
& aOriginSuffix
,
941 bool aPrivateBrowsing
) {
942 auto bl
= mTRRBLStorage
.Lock();
947 // use a unified casing for the hashkey
948 nsAutoCString
hashkey(aHost
+ aOriginSuffix
);
949 if (auto val
= bl
->Lookup(hashkey
)) {
951 *val
+ int32_t(StaticPrefs::network_trr_temp_blocklist_duration_sec());
952 int32_t expire
= NowInSeconds();
953 if (until
> expire
) {
954 LOG(("Host [%s] is TRR blocklisted\n", nsCString(aHost
).get()));
958 // the blocklisted entry has expired
964 // When running in TRR-only mode, the blocklist is not used and it will also
965 // try resolving the localhost / .local names.
966 bool TRRService::IsTemporarilyBlocked(const nsACString
& aHost
,
967 const nsACString
& aOriginSuffix
,
968 bool aPrivateBrowsing
,
969 bool aParentsToo
) // false if domain
971 if (!StaticPrefs::network_trr_temp_blocklist()) {
972 LOG(("TRRService::IsTemporarilyBlocked temp blocklist disabled by pref"));
976 if (mMode
== nsIDNSService::MODE_TRRONLY
) {
977 return false; // might as well try
980 LOG(("Checking if host [%s] is blocklisted", aHost
.BeginReading()));
982 int32_t dot
= aHost
.FindChar('.');
983 if ((dot
== kNotFound
) && aParentsToo
) {
984 // Only if a full host name. Domains can be dotless to be able to
985 // blocklist entire TLDs
989 if (IsDomainBlocked(aHost
, aOriginSuffix
, aPrivateBrowsing
)) {
993 nsDependentCSubstring domain
= Substring(aHost
, 0);
994 while (dot
!= kNotFound
) {
996 domain
.Rebind(domain
, dot
, domain
.Length() - dot
);
998 if (IsDomainBlocked(domain
, aOriginSuffix
, aPrivateBrowsing
)) {
1002 dot
= domain
.FindChar('.');
1008 bool TRRService::IsExcludedFromTRR(const nsACString
& aHost
) {
1009 // This method may be called off the main thread. We need to lock so
1010 // mExcludedDomains and mDNSSuffixDomains don't change while this code
1012 MutexSingleWriterAutoLock
lock(mLock
);
1014 return IsExcludedFromTRR_unlocked(aHost
);
1017 bool TRRService::IsExcludedFromTRR_unlocked(const nsACString
& aHost
) {
1018 mLock
.AssertOnWritingThreadOrHeld();
1021 // iteratively check the sub-domain of |aHost|
1022 while (dot
< static_cast<int32_t>(aHost
.Length())) {
1023 nsDependentCSubstring subdomain
=
1024 Substring(aHost
, dot
, aHost
.Length() - dot
);
1026 if (mExcludedDomains
.Contains(subdomain
)) {
1027 LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR via pref\n",
1028 subdomain
.BeginReading(), aHost
.BeginReading()));
1031 if (mDNSSuffixDomains
.Contains(subdomain
)) {
1032 LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR via pref\n",
1033 subdomain
.BeginReading(), aHost
.BeginReading()));
1036 if (mEtcHostsDomains
.Contains(subdomain
)) {
1037 LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR by /etc/hosts\n",
1038 subdomain
.BeginReading(), aHost
.BeginReading()));
1042 dot
= aHost
.FindChar('.', dot
+ 1);
1043 if (dot
== kNotFound
) {
1052 void TRRService::AddToBlocklist(const nsACString
& aHost
,
1053 const nsACString
& aOriginSuffix
,
1054 bool privateBrowsing
, bool aParentsToo
) {
1055 if (!StaticPrefs::network_trr_temp_blocklist()) {
1056 LOG(("TRRService::AddToBlocklist temp blocklist disabled by pref"));
1060 LOG(("TRR blocklist %s\n", nsCString(aHost
).get()));
1061 nsAutoCString
hashkey(aHost
+ aOriginSuffix
);
1063 // this overwrites any existing entry
1065 auto bl
= mTRRBLStorage
.Lock();
1066 bl
->InsertOrUpdate(hashkey
, NowInSeconds());
1069 // See bug 1700405. Some test expects 15 trr consecutive failures, but the NS
1070 // check against the base domain is successful. So, we skip this NS check when
1071 // the pref said so in order to pass the test reliably.
1072 if (aParentsToo
&& !StaticPrefs::network_trr_skip_check_for_blocked_host()) {
1073 // when given a full host name, verify its domain as well
1074 int32_t dot
= aHost
.FindChar('.');
1075 if (dot
!= kNotFound
) {
1076 // this has a domain to be checked
1078 nsDependentCSubstring domain
=
1079 Substring(aHost
, dot
, aHost
.Length() - dot
);
1080 nsAutoCString
check(domain
);
1081 if (IsTemporarilyBlocked(check
, aOriginSuffix
, privateBrowsing
, false)) {
1082 // the domain part is already blocklisted, no need to add this entry
1085 // verify 'check' over TRR
1086 LOG(("TRR: verify if '%s' resolves as NS\n", check
.get()));
1088 // check if there's an NS entry for this name
1089 RefPtr
<TRR
> trr
= new TRR(this, check
, TRRTYPE_NS
, aOriginSuffix
,
1090 privateBrowsing
, false);
1091 trr
->SetPurpose(TRR::Blocklist
);
1092 DispatchTRRRequest(trr
);
1098 TRRService::ConfirmationContext::Notify(nsITimer
* aTimer
) {
1099 MutexSingleWriterAutoLock
lock(OwningObject()->mLock
);
1100 if (aTimer
== mTimer
) {
1101 HandleEvent(ConfirmationEvent::ConfirmationRetry
, lock
);
1108 TRRService::ConfirmationContext::GetName(nsACString
& aName
) {
1109 aName
.AssignLiteral("TRRService::ConfirmationContext");
1113 static char StatusToChar(nsresult aLookupStatus
, nsresult aChannelStatus
) {
1114 // If the resolution fails in the TRR channel then we'll have a failed
1115 // aChannelStatus. Otherwise, we parse the response - if it's not a valid DNS
1116 // packet or doesn't contain the correct responses aLookupStatus will be a
1118 if (aChannelStatus
== NS_OK
) {
1119 // Return + if confirmation was OK, or - if confirmation failed
1120 return aLookupStatus
== NS_OK
? '+' : '-';
1123 if (nsCOMPtr
<nsIIOService
> ios
= do_GetIOService()) {
1124 bool hasConnectiviy
= true;
1125 ios
->GetConnectivity(&hasConnectiviy
);
1126 if (!hasConnectiviy
) {
1127 // Browser has no active network interfaces = is offline.
1132 switch (aChannelStatus
) {
1133 case NS_ERROR_NET_TIMEOUT_EXTERNAL
:
1134 // TRR timeout expired
1136 case NS_ERROR_UNKNOWN_HOST
:
1137 // TRRServiceChannel failed to due to unresolved host
1143 // The error is a network error
1144 if (NS_ERROR_GET_MODULE(aChannelStatus
) == NS_ERROR_MODULE_NETWORK
) {
1148 // Some other kind of failure.
1152 void TRRService::RetryTRRConfirm() {
1153 if (mConfirmation
.State() == CONFIRM_OK
) {
1154 LOG(("TRRService::RetryTRRConfirm triggering confirmation"));
1155 mConfirmation
.HandleEvent(ConfirmationEvent::RetryTRR
);
1159 void TRRService::RecordTRRStatus(TRR
* aTrrRequest
) {
1160 MOZ_ASSERT_IF(XRE_IsParentProcess(), NS_IsMainThread() || IsOnTRRThread());
1161 MOZ_ASSERT_IF(XRE_IsSocketProcess(), NS_IsMainThread());
1163 nsresult channelStatus
= aTrrRequest
->ChannelStatus();
1165 Telemetry::AccumulateCategoricalKeyed(
1166 ProviderKey(), NS_SUCCEEDED(channelStatus
)
1167 ? Telemetry::LABELS_DNS_TRR_SUCCESS3::Fine
1168 : (channelStatus
== NS_ERROR_NET_TIMEOUT_EXTERNAL
1169 ? Telemetry::LABELS_DNS_TRR_SUCCESS3::Timeout
1170 : Telemetry::LABELS_DNS_TRR_SUCCESS3::Bad
));
1172 mConfirmation
.RecordTRRStatus(aTrrRequest
);
1175 void TRRService::ConfirmationContext::RecordTRRStatus(TRR
* aTrrRequest
) {
1176 nsresult channelStatus
= aTrrRequest
->ChannelStatus();
1178 if (OwningObject()->Mode() == nsIDNSService::MODE_TRRONLY
) {
1179 mLastConfirmationSkipReason
= aTrrRequest
->SkipReason();
1180 mLastConfirmationStatus
= channelStatus
;
1183 if (NS_SUCCEEDED(channelStatus
)) {
1184 LOG(("TRRService::RecordTRRStatus channel success"));
1189 if (OwningObject()->Mode() != nsIDNSService::MODE_TRRFIRST
) {
1193 // only count failures while in OK state
1194 if (State() != CONFIRM_OK
) {
1198 // When TRR retry is enabled, nsHostResolver will trigger Confirmation
1199 // immediately upon a lookup failure, so nothing to be done here.
1200 // nsHostResolver can assess the success of the lookup considering all the
1201 // involved results (A, AAAA) so we let it tell us when to re-Confirm.
1202 if (StaticPrefs::network_trr_retry_on_recoverable_errors()) {
1203 LOG(("TRRService not counting failures when retry is enabled"));
1207 mFailureReasons
[mTRRFailures
% ConfirmationContext::RESULTS_SIZE
] =
1208 StatusToChar(NS_OK
, channelStatus
);
1209 uint32_t fails
= ++mTRRFailures
;
1210 LOG(("TRRService::RecordTRRStatus fails=%u", fails
));
1212 if (fails
>= StaticPrefs::network_trr_max_fails()) {
1213 LOG(("TRRService had %u failures in a row\n", fails
));
1214 // When several failures occur we trigger a confirmation causing
1215 // us to transition into the CONFIRM_TRYING_OK state.
1216 // Only after the confirmation fails do we finally go into CONFIRM_FAILED
1217 // and start skipping TRR.
1219 // Trigger a confirmation immediately.
1220 // If it fails, it will fire off a timer to start retrying again.
1221 HandleEvent(ConfirmationEvent::FailedLookups
);
1225 void TRRService::ConfirmationContext::RecordEvent(
1226 const char* aReason
, const MutexSingleWriterAutoLock
&) {
1227 // Reset the confirmation context attributes
1228 // Only resets the attributes that we keep for telemetry purposes.
1229 auto reset
= [&]() {
1231 mNetworkId
.Truncate();
1232 mFirstRequestTime
= TimeStamp();
1233 mContextChangeReason
.Assign(aReason
);
1234 mTrigger
.Truncate();
1235 mFailedLookups
.Truncate();
1237 mRetryInterval
= StaticPrefs::network_trr_retry_timeout_ms();
1240 if (mAttemptCount
== 0) {
1241 // XXX: resetting everything might not be the best thing here, even if the
1242 // context changes, because there might still be a confirmation pending.
1243 // But cancelling and retrying that confirmation might just make the whole
1244 // confirmation longer for no reason.
1249 Telemetry::EventID eventType
=
1250 Telemetry::EventID::NetworkDns_Trrconfirmation_Context
;
1252 nsAutoCString results
;
1253 static_assert(RESULTS_SIZE
< 64);
1255 // mResults is a circular buffer ending at mAttemptCount
1256 if (mAttemptCount
<= RESULTS_SIZE
) {
1257 // We have fewer attempts than the size of the buffer, so all of the
1258 // results are in the buffer.
1259 results
.Append(nsDependentCSubstring(mResults
, mAttemptCount
));
1261 // More attempts than the buffer size.
1262 // That means past RESULTS_SIZE attempts in order are
1263 // [posInResults .. end-of-buffer) + [start-of-buffer .. posInResults)
1264 uint32_t posInResults
= mAttemptCount
% RESULTS_SIZE
;
1266 results
.Append(nsDependentCSubstring(mResults
+ posInResults
,
1267 RESULTS_SIZE
- posInResults
));
1268 results
.Append(nsDependentCSubstring(mResults
, posInResults
));
1271 auto extra
= Some
<nsTArray
<mozilla::Telemetry::EventExtraEntry
>>({
1272 Telemetry::EventExtraEntry
{"trigger"_ns
, mTrigger
},
1273 Telemetry::EventExtraEntry
{"contextReason"_ns
, mContextChangeReason
},
1274 Telemetry::EventExtraEntry
{"attemptCount"_ns
,
1275 nsPrintfCString("%u", mAttemptCount
)},
1276 Telemetry::EventExtraEntry
{"results"_ns
, results
},
1277 Telemetry::EventExtraEntry
{
1281 !mFirstRequestTime
.IsNull()
1282 ? (TimeStamp::Now() - mFirstRequestTime
).ToMilliseconds()
1284 Telemetry::EventExtraEntry
{"networkID"_ns
, mNetworkId
},
1285 Telemetry::EventExtraEntry
{"captivePortal"_ns
,
1286 nsPrintfCString("%i", mCaptivePortalStatus
)},
1289 if (mTrigger
.Equals("failed-lookups"_ns
)) {
1290 extra
.ref().AppendElement(
1291 Telemetry::EventExtraEntry
{"failedLookups"_ns
, mFailedLookups
});
1294 enum ConfirmationState state
= mState
;
1295 Telemetry::RecordEvent(eventType
, mozilla::Some(nsPrintfCString("%u", state
)),
1301 void TRRService::ConfirmationContext::RequestCompleted(
1302 nsresult aLookupStatus
, nsresult aChannelStatus
) {
1303 mResults
[mAttemptCount
% RESULTS_SIZE
] =
1304 StatusToChar(aLookupStatus
, aChannelStatus
);
1308 void TRRService::ConfirmationContext::CompleteConfirmation(nsresult aStatus
,
1311 MutexSingleWriterAutoLock
lock(OwningObject()->mLock
);
1312 // Ignore confirmations that dont match the pending task.
1313 if (mTask
!= aTRRRequest
) {
1316 MOZ_ASSERT(State() == CONFIRM_TRYING_OK
||
1317 State() == CONFIRM_TRYING_FAILED
);
1318 if (State() != CONFIRM_TRYING_OK
&& State() != CONFIRM_TRYING_FAILED
) {
1322 RequestCompleted(aStatus
, aTRRRequest
->ChannelStatus());
1323 mLastConfirmationSkipReason
= aTRRRequest
->SkipReason();
1324 mLastConfirmationStatus
= aTRRRequest
->ChannelStatus();
1327 if (NS_SUCCEEDED(aStatus
)) {
1328 HandleEvent(ConfirmationEvent::ConfirmOK
, lock
);
1330 HandleEvent(ConfirmationEvent::ConfirmFail
, lock
);
1333 if (State() == CONFIRM_OK
) {
1334 // Record event and start new confirmation context
1335 RecordEvent("success", lock
);
1337 LOG(("TRRService finishing confirmation test %s %d %X\n",
1338 OwningObject()->mPrivateURI
.get(), State(), (unsigned int)aStatus
));
1341 if (State() == CONFIRM_OK
) {
1342 // A fresh confirmation means previous blocked entries might not
1343 // be valid anymore.
1344 auto bl
= OwningObject()->mTRRBLStorage
.Lock();
1347 MOZ_ASSERT(State() == CONFIRM_FAILED
);
1350 Telemetry::Accumulate(Telemetry::DNS_TRR_NS_VERFIFIED3
,
1351 TRRService::ProviderKey(), (State() == CONFIRM_OK
));
1354 AHostResolver::LookupStatus
TRRService::CompleteLookup(
1355 nsHostRecord
* rec
, nsresult status
, AddrInfo
* aNewRRSet
, bool pb
,
1356 const nsACString
& aOriginSuffix
, TRRSkippedReason aReason
,
1358 // this is an NS check for the TRR blocklist or confirmationNS check
1360 MOZ_ASSERT_IF(XRE_IsParentProcess(), NS_IsMainThread() || IsOnTRRThread());
1361 MOZ_ASSERT_IF(XRE_IsSocketProcess(), NS_IsMainThread());
1364 RefPtr
<AddrInfo
> newRRSet(aNewRRSet
);
1365 MOZ_ASSERT(newRRSet
&& newRRSet
->TRRType() == TRRTYPE_NS
);
1367 if (aTRRRequest
->Purpose() == TRR::Confirmation
) {
1368 mConfirmation
.CompleteConfirmation(status
, aTRRRequest
);
1372 if (aTRRRequest
->Purpose() == TRR::Blocklist
) {
1373 if (NS_SUCCEEDED(status
)) {
1374 LOG(("TRR verified %s to be fine!\n", newRRSet
->Hostname().get()));
1376 LOG(("TRR says %s doesn't resolve as NS!\n", newRRSet
->Hostname().get()));
1377 AddToBlocklist(newRRSet
->Hostname(), aOriginSuffix
, pb
, false);
1382 MOZ_ASSERT_UNREACHABLE(
1383 "TRRService::CompleteLookup called for unexpected request");
1387 AHostResolver::LookupStatus
TRRService::CompleteLookupByType(
1388 nsHostRecord
*, nsresult
, mozilla::net::TypeRecordResultType
& aResult
,
1389 uint32_t aTtl
, bool aPb
) {
1393 NS_IMETHODIMP
TRRService::OnProxyConfigChanged() {
1394 LOG(("TRRService::OnProxyConfigChanged"));
1398 AsyncCreateTRRConnectionInfo(uri
);
1403 void TRRService::InitTRRConnectionInfo() {
1404 if (XRE_IsParentProcess()) {
1405 TRRServiceBase::InitTRRConnectionInfo();
1409 MOZ_ASSERT(XRE_IsSocketProcess());
1410 MOZ_ASSERT(NS_IsMainThread());
1412 TRRServiceChild
* child
= TRRServiceChild::GetSingleton();
1413 if (child
&& child
->CanSend()) {
1414 LOG(("TRRService::SendInitTRRConnectionInfo"));
1415 Unused
<< child
->SendInitTRRConnectionInfo();
1419 } // namespace mozilla::net