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";
36 #define TRR_PREF_PREFIX "network.trr."
37 #define TRR_PREF(x) TRR_PREF_PREFIX x
39 namespace mozilla::net
{
41 StaticRefPtr
<nsIThread
> sTRRBackgroundThread
;
42 static Atomic
<TRRService
*> sTRRServicePtr
;
44 static Atomic
<size_t, Relaxed
> sDomainIndex(0);
45 static Atomic
<size_t, Relaxed
> sCurrentTRRModeIndex(0);
47 constexpr nsLiteralCString kTRRDomains
[3][7] = {
50 // When mode is 0, the provider key has no postfix.
52 "mozilla.cloudflare-dns.com"_ns
,
53 "firefox.dns.nextdns.io"_ns
,
54 "private.canadianshield.cira.ca"_ns
,
55 "doh.xfinity.com"_ns
, // Steered clients
56 "dns.shaw.ca"_ns
, // Steered clients
57 "dooh.cloudflare-dns.com"_ns
, // DNS over Oblivious HTTP
61 "mozilla.cloudflare-dns.com_2"_ns
,
62 "firefox.dns.nextdns.io_2"_ns
,
63 "private.canadianshield.cira.ca_2"_ns
,
64 "doh.xfinity.com_2"_ns
, // Steered clients
65 "dns.shaw.ca_2"_ns
, // Steered clients
66 "dooh.cloudflare-dns.com_2"_ns
, // DNS over Oblivious HTTP
70 "mozilla.cloudflare-dns.com_3"_ns
,
71 "firefox.dns.nextdns.io_3"_ns
,
72 "private.canadianshield.cira.ca_3"_ns
,
73 "doh.xfinity.com_3"_ns
, // Steered clients
74 "dns.shaw.ca_3"_ns
, // Steered clients
75 "dooh.cloudflare-dns.com_3"_ns
, // DNS over Oblivious HTTP
81 void TRRService::SetCurrentTRRMode(nsIDNSService::ResolverMode aMode
) {
82 // A table to map ResolverMode to the row of kTRRDomains.
83 // When the aMode is 2, we use kTRRDomains[1] as provider keys. When aMode is
84 // 3, we use kTRRDomains[2]. Otherwise, we kTRRDomains[0] is used.
85 static const uint32_t index
[] = {0, 0, 1, 2, 0, 0};
86 if (aMode
> nsIDNSService::MODE_TRROFF
) {
87 aMode
= nsIDNSService::MODE_TRROFF
;
89 sCurrentTRRModeIndex
= index
[static_cast<size_t>(aMode
)];
93 void TRRService::SetProviderDomain(const nsACString
& aTRRDomain
) {
95 for (size_t i
= 1; i
< std::size(kTRRDomains
[0]); i
++) {
96 if (aTRRDomain
.Equals(kTRRDomains
[0][i
])) {
104 const nsCString
& TRRService::ProviderKey() {
105 return kTRRDomains
[sCurrentTRRModeIndex
][sDomainIndex
];
108 NS_IMPL_ISUPPORTS_INHERITED(TRRService
, TRRServiceBase
, nsIObserver
,
109 nsISupportsWeakReference
)
111 NS_IMPL_ADDREF_USING_AGGREGATOR(TRRService::ConfirmationContext
, OwningObject())
112 NS_IMPL_RELEASE_USING_AGGREGATOR(TRRService::ConfirmationContext
,
114 NS_IMPL_QUERY_INTERFACE(TRRService::ConfirmationContext
, nsITimerCallback
,
117 TRRService::TRRService() : mLock("TRRService", this) {
118 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
122 TRRService
* TRRService::Get() { return sTRRServicePtr
; }
125 void TRRService::AddObserver(nsIObserver
* aObserver
,
126 nsIObserverService
* aObserverService
) {
127 nsCOMPtr
<nsIObserverService
> observerService
;
128 if (aObserverService
) {
129 observerService
= aObserverService
;
131 observerService
= mozilla::services::GetObserverService();
134 if (observerService
) {
135 observerService
->AddObserver(aObserver
, NS_CAPTIVE_PORTAL_CONNECTIVITY
,
137 observerService
->AddObserver(aObserver
, kOpenCaptivePortalLoginEvent
, true);
138 observerService
->AddObserver(aObserver
, kClearPrivateData
, true);
139 observerService
->AddObserver(aObserver
, kPurge
, true);
140 observerService
->AddObserver(aObserver
, NS_NETWORK_LINK_TOPIC
, true);
141 observerService
->AddObserver(aObserver
, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC
,
143 observerService
->AddObserver(aObserver
, "xpcom-shutdown-threads", true);
148 bool TRRService::CheckCaptivePortalIsPassed() {
150 nsCOMPtr
<nsICaptivePortalService
> captivePortalService
=
151 do_GetService(NS_CAPTIVEPORTAL_CID
);
152 if (captivePortalService
) {
153 int32_t captiveState
;
154 MOZ_ALWAYS_SUCCEEDS(captivePortalService
->GetState(&captiveState
));
156 if ((captiveState
== nsICaptivePortalService::UNLOCKED_PORTAL
) ||
157 (captiveState
== nsICaptivePortalService::NOT_CAPTIVE
)) {
160 LOG(("TRRService::Init mCaptiveState=%d mCaptiveIsPassed=%d\n",
161 captiveState
, (int)result
));
167 static void EventTelemetryPrefChanged(const char* aPref
, void* aData
) {
168 Telemetry::SetEventRecordingEnabled(
170 StaticPrefs::network_trr_confirmation_telemetry_enabled());
173 nsresult
TRRService::Init() {
174 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
182 nsCOMPtr
<nsIPrefBranch
> prefBranch
;
183 GetPrefBranch(getter_AddRefs(prefBranch
));
185 prefBranch
->AddObserver(TRR_PREF_PREFIX
, this, true);
186 prefBranch
->AddObserver(kRolloutURIPref
, this, true);
187 prefBranch
->AddObserver(kRolloutModePref
, this, true);
190 sTRRServicePtr
= this;
193 mConfirmation
.HandleEvent(ConfirmationEvent::Init
);
195 if (XRE_IsParentProcess()) {
196 mCaptiveIsPassed
= CheckCaptivePortalIsPassed();
198 mParentalControlEnabled
= GetParentalControlEnabledInternal();
200 mLinkService
= do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID
);
202 nsTArray
<nsCString
> suffixList
;
203 mLinkService
->GetDnsSuffixList(suffixList
);
204 RebuildSuffixList(std::move(suffixList
));
207 nsCOMPtr
<nsIThread
> thread
;
209 NS_NewNamedThread("TRR Background", getter_AddRefs(thread
)))) {
210 NS_WARNING("NS_NewNamedThread failed!");
211 return NS_ERROR_FAILURE
;
214 sTRRBackgroundThread
= thread
;
217 Preferences::RegisterCallbackAndCall(
218 EventTelemetryPrefChanged
,
219 "network.trr.confirmation_telemetry_enabled"_ns
);
221 LOG(("Initialized TRRService\n"));
226 bool TRRService::GetParentalControlEnabledInternal() {
227 nsCOMPtr
<nsIParentalControlsService
> pc
=
228 do_CreateInstance("@mozilla.org/parental-controls-service;1");
231 pc
->GetParentalControlsEnabled(&result
);
232 LOG(("TRRService::GetParentalControlEnabledInternal=%d\n", result
));
239 void TRRService::SetDetectedTrrURI(const nsACString
& aURI
) {
240 LOG(("SetDetectedTrrURI(%s", nsPromiseFlatCString(aURI
).get()));
241 // If the user has set a custom URI then we don't want to override that.
242 // If the URI is set via doh-rollout.uri, mURIPref will be empty
243 // (see TRRServiceBase::OnTRRURIChange)
244 if (!mURIPref
.IsEmpty()) {
245 LOG(("Already has user value. Not setting URI"));
249 if (StaticPrefs::network_trr_use_ohttp()) {
250 LOG(("No autodetection when using OHTTP"));
254 mURISetByDetection
= MaybeSetPrivateURI(aURI
);
257 bool TRRService::Enabled(nsIRequest::TRRMode aRequestMode
) {
258 if (mMode
== nsIDNSService::MODE_TRROFF
||
259 aRequestMode
== nsIRequest::TRR_DISABLED_MODE
) {
260 LOG(("TRR service not enabled - off or disabled"));
264 // If already confirmed, service is enabled.
265 if (mConfirmation
.State() == CONFIRM_OK
||
266 aRequestMode
== nsIRequest::TRR_ONLY_MODE
) {
267 LOG(("TRR service enabled - confirmed or trr_only request"));
271 // If this is a TRR_FIRST request but the resolver has a different mode,
272 // just go ahead and let it try to use TRR.
273 if (aRequestMode
== nsIRequest::TRR_FIRST_MODE
&&
274 mMode
!= nsIDNSService::MODE_TRRFIRST
) {
275 LOG(("TRR service enabled - trr_first request"));
279 // In TRR_ONLY_MODE / confirmationNS == "skip" we don't try to confirm.
280 if (mConfirmation
.State() == CONFIRM_DISABLED
) {
281 LOG(("TRRService service enabled - confirmation is disabled"));
285 LOG(("TRRService::Enabled mConfirmation.mState=%d mCaptiveIsPassed=%d\n",
286 mConfirmation
.State(), (int)mCaptiveIsPassed
));
288 if (StaticPrefs::network_trr_wait_for_confirmation()) {
289 return mConfirmation
.State() == CONFIRM_OK
;
292 if (StaticPrefs::network_trr_attempt_when_retrying_confirmation()) {
293 return mConfirmation
.State() == CONFIRM_OK
||
294 mConfirmation
.State() == CONFIRM_TRYING_OK
||
295 mConfirmation
.State() == CONFIRM_TRYING_FAILED
;
298 return mConfirmation
.State() == CONFIRM_OK
||
299 mConfirmation
.State() == CONFIRM_TRYING_OK
;
302 void TRRService::GetPrefBranch(nsIPrefBranch
** result
) {
303 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
305 CallGetService(NS_PREFSERVICE_CONTRACTID
, result
);
308 bool TRRService::MaybeSetPrivateURI(const nsACString
& aURI
) {
309 bool clearCache
= false;
310 nsAutoCString
newURI(aURI
);
311 LOG(("MaybeSetPrivateURI(%s)", newURI
.get()));
313 ProcessURITemplate(newURI
);
315 MutexSingleWriterAutoLock
lock(mLock
);
316 if (mPrivateURI
.Equals(newURI
)) {
320 if (!mPrivateURI
.IsEmpty()) {
321 LOG(("TRRService clearing blocklist because of change in uri service\n"));
322 auto bl
= mTRRBLStorage
.Lock();
329 nsCOMPtr
<nsIURI
> url
;
330 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(url
), newURI
))) {
334 SetProviderDomain(host
);
336 mPrivateURI
= newURI
;
338 // Notify the content processes of the new TRR
340 dom::ContentParent::AllProcesses(dom::ContentParent::eLive
)) {
341 PNeckoParent
* neckoParent
=
342 SingleManagedOrNull(cp
->ManagedPNeckoParent());
346 Unused
<< neckoParent
->SendSetTRRDomain(host
);
349 AsyncCreateTRRConnectionInfo(mPrivateURI
);
351 // The URI has changed. We should trigger a new confirmation immediately.
352 // We must do this here because the URI could also change because of
354 mConfirmationTriggered
=
355 mConfirmation
.HandleEvent(ConfirmationEvent::URIChange
, lock
);
358 // Clear the cache because we changed the URI
363 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
365 obs
->NotifyObservers(nullptr, NS_NETWORK_TRR_URI_CHANGED_TOPIC
, nullptr);
370 nsresult
TRRService::ReadPrefs(const char* name
) {
371 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
373 // Whenever a pref change occurs that would cause us to clear the cache
374 // we set this to true then do it at the end of the method.
375 bool clearEntireCache
= false;
377 if (!name
|| !strcmp(name
, TRR_PREF("mode")) ||
378 !strcmp(name
, kRolloutModePref
)) {
379 nsIDNSService::ResolverMode prevMode
= Mode();
382 // When the TRR service gets disabled we should purge the TRR cache to
383 // make sure we don't use any of the cached entries on a network where
384 // they are invalid - for example after turning on a VPN.
385 if (TRR_DISABLED(Mode()) && !TRR_DISABLED(prevMode
)) {
386 clearEntireCache
= true;
389 if (!name
|| !strcmp(name
, TRR_PREF("uri")) ||
390 !strcmp(name
, TRR_PREF("default_provider_uri")) ||
391 !strcmp(name
, kRolloutURIPref
) || !strcmp(name
, TRR_PREF("ohttp.uri")) ||
392 !strcmp(name
, TRR_PREF("use_ohttp"))) {
395 if (!name
|| !strcmp(name
, TRR_PREF("credentials"))) {
396 MutexSingleWriterAutoLock
lock(mLock
);
397 Preferences::GetCString(TRR_PREF("credentials"), mPrivateCred
);
399 if (!name
|| !strcmp(name
, TRR_PREF("confirmationNS"))) {
400 MutexSingleWriterAutoLock
lock(mLock
);
401 Preferences::GetCString(TRR_PREF("confirmationNS"), mConfirmationNS
);
402 LOG(("confirmationNS = %s", mConfirmationNS
.get()));
404 if (!name
|| !strcmp(name
, TRR_PREF("bootstrapAddr"))) {
405 MutexSingleWriterAutoLock
lock(mLock
);
406 Preferences::GetCString(TRR_PREF("bootstrapAddr"), mBootstrapAddr
);
407 clearEntireCache
= true;
409 if (!name
|| !strcmp(name
, TRR_PREF("excluded-domains")) ||
410 !strcmp(name
, TRR_PREF("builtin-excluded-domains"))) {
411 MutexSingleWriterAutoLock
lock(mLock
);
412 mExcludedDomains
.Clear();
414 auto parseExcludedDomains
= [this](const char* aPrefName
) {
415 nsAutoCString excludedDomains
;
416 mLock
.AssertCurrentThreadOwns();
417 Preferences::GetCString(aPrefName
, excludedDomains
);
418 if (excludedDomains
.IsEmpty()) {
422 for (const nsACString
& tokenSubstring
:
423 nsCCharSeparatedTokenizerTemplate
<
424 NS_IsAsciiWhitespace
, nsTokenizerFlags::SeparatorOptional
>(
425 excludedDomains
, ',')
427 nsCString token
{tokenSubstring
};
428 LOG(("TRRService::ReadPrefs %s host:[%s]\n", aPrefName
, token
.get()));
429 mExcludedDomains
.Insert(token
);
433 parseExcludedDomains(TRR_PREF("excluded-domains"));
434 parseExcludedDomains(TRR_PREF("builtin-excluded-domains"));
435 clearEntireCache
= true;
438 // if name is null, then we're just now initializing. In that case we don't
439 // need to clear the cache.
440 if (name
&& clearEntireCache
) {
447 void TRRService::ClearEntireCache() {
448 if (!StaticPrefs::network_trr_clear_cache_on_pref_change()) {
451 nsCOMPtr
<nsIDNSService
> dns
= do_GetService(NS_DNSSERVICE_CONTRACTID
);
455 dns
->ClearCache(true);
458 void TRRService::AddEtcHosts(const nsTArray
<nsCString
>& aArray
) {
459 MutexSingleWriterAutoLock
lock(mLock
);
460 for (const auto& item
: aArray
) {
461 LOG(("Adding %s from /etc/hosts to excluded domains", item
.get()));
462 mEtcHostsDomains
.Insert(item
);
466 void TRRService::ReadEtcHostsFile() {
467 if (!XRE_IsParentProcess()) {
471 DoReadEtcHostsFile([](const nsTArray
<nsCString
>* aArray
) -> bool {
472 RefPtr
<TRRService
> service(sTRRServicePtr
);
473 if (service
&& aArray
) {
474 service
->AddEtcHosts(*aArray
);
480 void TRRService::GetURI(nsACString
& result
) {
481 MutexSingleWriterAutoLock
lock(mLock
);
482 result
= mPrivateURI
;
485 nsresult
TRRService::GetCredentials(nsCString
& result
) {
486 MutexSingleWriterAutoLock
lock(mLock
);
487 result
= mPrivateCred
;
491 uint32_t TRRService::GetRequestTimeout() {
492 if (mMode
== nsIDNSService::MODE_TRRONLY
) {
493 return StaticPrefs::network_trr_request_timeout_mode_trronly_ms();
496 if (StaticPrefs::network_trr_strict_native_fallback()) {
497 return StaticPrefs::network_trr_strict_fallback_request_timeout_ms();
500 return StaticPrefs::network_trr_request_timeout_ms();
503 nsresult
TRRService::Start() {
504 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
506 return NS_ERROR_NOT_INITIALIZED
;
511 TRRService::~TRRService() {
512 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
513 LOG(("Exiting TRRService\n"));
516 nsresult
TRRService::DispatchTRRRequest(TRR
* aTrrRequest
) {
517 return DispatchTRRRequestInternal(aTrrRequest
, true);
520 nsresult
TRRService::DispatchTRRRequestInternal(TRR
* aTrrRequest
,
522 NS_ENSURE_ARG_POINTER(aTrrRequest
);
524 nsCOMPtr
<nsIThread
> thread
= MainThreadOrTRRThread(aWithLock
);
526 return NS_ERROR_FAILURE
;
529 RefPtr
<TRR
> trr
= aTrrRequest
;
530 return thread
->Dispatch(trr
.forget());
533 already_AddRefed
<nsIThread
> TRRService::MainThreadOrTRRThread(bool aWithLock
) {
534 if (!StaticPrefs::network_trr_fetch_off_main_thread() ||
535 XRE_IsSocketProcess() || mDontUseTRRThread
) {
536 return do_GetMainThread();
539 nsCOMPtr
<nsIThread
> thread
= aWithLock
? TRRThread() : TRRThread_locked();
540 return thread
.forget();
543 already_AddRefed
<nsIThread
> TRRService::TRRThread() {
544 MutexSingleWriterAutoLock
lock(mLock
);
545 return TRRThread_locked();
548 already_AddRefed
<nsIThread
> TRRService::TRRThread_locked() {
549 RefPtr
<nsIThread
> thread
= sTRRBackgroundThread
;
550 return thread
.forget();
553 bool TRRService::IsOnTRRThread() {
554 nsCOMPtr
<nsIThread
> thread
;
556 MutexSingleWriterAutoLock
lock(mLock
);
557 thread
= sTRRBackgroundThread
;
563 return thread
->IsOnCurrentThread();
567 TRRService::Observe(nsISupports
* aSubject
, const char* aTopic
,
568 const char16_t
* aData
) {
569 MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
570 LOG(("TRR::Observe() topic=%s\n", aTopic
));
571 if (!strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
)) {
572 // Reset the state of whether a confirmation is triggered, so we can check
573 // if we create a new one after ReadPrefs().
574 mConfirmationTriggered
= false;
575 ReadPrefs(NS_ConvertUTF16toUTF8(aData
).get());
577 MutexSingleWriterAutoLock
lock(mLock
);
578 mConfirmation
.RecordEvent("pref-change", lock
);
581 // We should only trigger a new confirmation if reading the prefs didn't
582 // already trigger one.
583 if (!mConfirmationTriggered
) {
584 mConfirmation
.HandleEvent(ConfirmationEvent::PrefChange
);
586 } else if (!strcmp(aTopic
, kOpenCaptivePortalLoginEvent
)) {
587 // We are in a captive portal
588 LOG(("TRRservice in captive portal\n"));
589 mCaptiveIsPassed
= false;
590 mConfirmation
.SetCaptivePortalStatus(
591 nsICaptivePortalService::LOCKED_PORTAL
);
592 } else if (!strcmp(aTopic
, NS_CAPTIVE_PORTAL_CONNECTIVITY
)) {
593 nsAutoCString data
= NS_ConvertUTF16toUTF8(aData
);
594 LOG(("TRRservice captive portal was %s\n", data
.get()));
595 nsCOMPtr
<nsICaptivePortalService
> cps
= do_QueryInterface(aSubject
);
597 mConfirmation
.SetCaptivePortalStatus(cps
->State());
600 // If we were previously in a captive portal, this event means we will
601 // need to trigger confirmation again. Otherwise it's just a periodical
602 // captive-portal check that completed and we don't need to react to it.
603 if (!mCaptiveIsPassed
) {
604 mConfirmation
.HandleEvent(ConfirmationEvent::CaptivePortalConnectivity
);
607 mCaptiveIsPassed
= true;
608 } else if (!strcmp(aTopic
, kClearPrivateData
) || !strcmp(aTopic
, kPurge
)) {
609 // flush the TRR blocklist
610 auto bl
= mTRRBLStorage
.Lock();
612 } else if (!strcmp(aTopic
, NS_DNS_SUFFIX_LIST_UPDATED_TOPIC
) ||
613 !strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
)) {
614 // nsINetworkLinkService is only available on parent process.
615 if (XRE_IsParentProcess()) {
616 nsCOMPtr
<nsINetworkLinkService
> link
= do_QueryInterface(aSubject
);
617 // The network link service notification normally passes itself as the
618 // subject, but some unit tests will sometimes pass a null subject.
620 nsTArray
<nsCString
> suffixList
;
621 link
->GetDnsSuffixList(suffixList
);
622 RebuildSuffixList(std::move(suffixList
));
626 if (!strcmp(aTopic
, NS_NETWORK_LINK_TOPIC
)) {
627 if (NS_ConvertUTF16toUTF8(aData
).EqualsLiteral(
628 NS_NETWORK_LINK_DATA_DOWN
)) {
629 MutexSingleWriterAutoLock
lock(mLock
);
630 mConfirmation
.RecordEvent("network-change", lock
);
633 if (mURISetByDetection
) {
634 // If the URI was set via SetDetectedTrrURI we need to restore it to the
635 // default pref when a network link change occurs.
639 if (NS_ConvertUTF16toUTF8(aData
).EqualsLiteral(NS_NETWORK_LINK_DATA_UP
)) {
640 mConfirmation
.HandleEvent(ConfirmationEvent::NetworkUp
);
643 } else if (!strcmp(aTopic
, "xpcom-shutdown-threads")) {
645 // If a confirmation is still in progress we record the event.
646 // Since there should be no more confirmations after this, the shutdown
647 // reason would not really be recorded in telemetry.
649 MutexSingleWriterAutoLock
lock(mLock
);
650 mConfirmation
.RecordEvent("shutdown", lock
);
653 if (sTRRBackgroundThread
) {
654 nsCOMPtr
<nsIThread
> thread
;
655 thread
= sTRRBackgroundThread
.get();
656 sTRRBackgroundThread
= nullptr;
657 MOZ_ALWAYS_SUCCEEDS(thread
->Shutdown());
658 sTRRServicePtr
= nullptr;
664 void TRRService::RebuildSuffixList(nsTArray
<nsCString
>&& aSuffixList
) {
665 if (!StaticPrefs::network_trr_split_horizon_mitigations() || mShutdown
) {
669 MutexSingleWriterAutoLock
lock(mLock
);
670 mDNSSuffixDomains
.Clear();
671 for (const auto& item
: aSuffixList
) {
672 LOG(("TRRService adding %s to suffix list", item
.get()));
673 mDNSSuffixDomains
.Insert(item
);
677 void TRRService::ConfirmationContext::SetState(
678 enum ConfirmationState aNewState
) {
681 enum ConfirmationState state
= mState
;
682 if (XRE_IsParentProcess()) {
683 NS_DispatchToMainThread(NS_NewRunnableFunction(
684 "TRRService::ConfirmationContextNotify", [state
] {
685 if (nsCOMPtr
<nsIObserverService
> obs
=
686 mozilla::services::GetObserverService()) {
688 [](enum ConfirmationState aState
) -> const char16_t
* {
691 return u
"CONFIRM_OFF";
692 case CONFIRM_TRYING_OK
:
693 return u
"CONFIRM_TRYING_OK";
695 return u
"CONFIRM_OK";
697 return u
"CONFIRM_FAILED";
698 case CONFIRM_TRYING_FAILED
:
699 return u
"CONFIRM_TRYING_FAILED";
700 case CONFIRM_DISABLED
:
701 return u
"CONFIRM_DISABLED";
703 MOZ_ASSERT_UNREACHABLE();
707 obs
->NotifyObservers(nullptr, "network:trr-confirmation",
713 if (XRE_IsParentProcess()) {
717 MOZ_ASSERT(XRE_IsSocketProcess());
718 MOZ_ASSERT(NS_IsMainThread());
720 TRRServiceChild
* child
= TRRServiceChild::GetSingleton();
721 if (child
&& child
->CanSend()) {
722 LOG(("TRRService::SendSetConfirmationState"));
723 Unused
<< child
->SendSetConfirmationState(mState
);
727 bool TRRService::ConfirmationContext::HandleEvent(ConfirmationEvent aEvent
) {
728 MutexSingleWriterAutoLock
lock(OwningObject()->mLock
);
729 return HandleEvent(aEvent
, lock
);
732 // We're protected by service->mLock
733 bool TRRService::ConfirmationContext::HandleEvent(
734 ConfirmationEvent aEvent
, const MutexSingleWriterAutoLock
&) {
735 auto prevAddr
= TaskAddr();
736 TRRService
* service
= OwningObject();
737 service
->mLock
.AssertCurrentThreadOwns();
738 nsIDNSService::ResolverMode mode
= service
->Mode();
740 auto resetConfirmation
= [&]() {
741 service
->mLock
.AssertCurrentThreadOwns();
743 nsCOMPtr
<nsITimer
> timer
= std::move(mTimer
);
748 mRetryInterval
= StaticPrefs::network_trr_retry_timeout_ms();
751 if (TRR_DISABLED(mode
)) {
752 LOG(("TRR is disabled. mConfirmation.mState -> CONFIRM_OFF"));
753 SetState(CONFIRM_OFF
);
757 if (mode
== nsIDNSService::MODE_TRRONLY
) {
758 LOG(("TRR_ONLY_MODE. mConfirmation.mState -> CONFIRM_DISABLED"));
759 SetState(CONFIRM_DISABLED
);
763 if (service
->mConfirmationNS
.Equals("skip"_ns
)) {
765 "mConfirmationNS == skip. mConfirmation.mState -> CONFIRM_DISABLED"));
766 SetState(CONFIRM_DISABLED
);
770 // The next call to maybeConfirm will transition to CONFIRM_TRYING_OK
771 LOG(("mConfirmation.mState -> CONFIRM_OK"));
772 SetState(CONFIRM_OK
);
775 auto maybeConfirm
= [&](const char* aReason
) {
776 service
->mLock
.AssertCurrentThreadOwns();
777 if (TRR_DISABLED(mode
) || mState
== CONFIRM_DISABLED
|| mTask
) {
779 ("TRRService:MaybeConfirm(%s) mode=%d, mTask=%p "
781 aReason
, (int)mode
, (void*)mTask
, (int)mState
));
785 MOZ_ASSERT(mode
!= nsIDNSService::MODE_TRRONLY
,
786 "Confirmation should be disabled");
787 MOZ_ASSERT(!service
->mConfirmationNS
.Equals("skip"),
788 "Confirmation should be disabled");
790 LOG(("maybeConfirm(%s) starting confirmation test %s %s\n", aReason
,
791 service
->mPrivateURI
.get(), service
->mConfirmationNS
.get()));
793 MOZ_ASSERT(mState
== CONFIRM_OK
|| mState
== CONFIRM_FAILED
);
795 if (mState
== CONFIRM_FAILED
) {
796 LOG(("mConfirmation.mState -> CONFIRM_TRYING_FAILED"));
797 SetState(CONFIRM_TRYING_FAILED
);
799 LOG(("mConfirmation.mState -> CONFIRM_TRYING_OK"));
800 SetState(CONFIRM_TRYING_OK
);
803 nsCOMPtr
<nsITimer
> timer
= std::move(mTimer
);
808 MOZ_ASSERT(mode
== nsIDNSService::MODE_TRRFIRST
,
809 "Should only confirm in TRR first mode");
810 // Set aUseFreshConnection if TRR lookups are retried.
811 mTask
= new TRR(service
, service
->mConfirmationNS
, TRRTYPE_NS
, ""_ns
, false,
812 StaticPrefs::network_trr_retry_on_recoverable_errors());
813 mTask
->SetTimeout(StaticPrefs::network_trr_confirmation_timeout_ms());
814 mTask
->SetPurpose(TRR::Confirmation
);
816 if (service
->mLinkService
) {
817 service
->mLinkService
->GetNetworkID(mNetworkId
);
820 if (mFirstRequestTime
.IsNull()) {
821 mFirstRequestTime
= TimeStamp::Now();
823 if (mTrigger
.IsEmpty()) {
824 mTrigger
.Assign(aReason
);
827 LOG(("Dispatching confirmation task: %p", mTask
.get()));
828 service
->DispatchTRRRequestInternal(mTask
, false);
832 case ConfirmationEvent::Init
:
834 maybeConfirm("context-init");
836 case ConfirmationEvent::PrefChange
:
838 maybeConfirm("pref-change");
840 case ConfirmationEvent::ConfirmationRetry
:
841 MOZ_ASSERT(mState
== CONFIRM_FAILED
);
842 if (mState
== CONFIRM_FAILED
) {
843 maybeConfirm("confirmation-retry");
846 case ConfirmationEvent::FailedLookups
:
847 MOZ_ASSERT(mState
== CONFIRM_OK
);
848 mTrigger
.Assign("failed-lookups");
849 mFailedLookups
= nsDependentCSubstring(
850 mFailureReasons
, mTRRFailures
% ConfirmationContext::RESULTS_SIZE
);
851 maybeConfirm("failed-lookups");
853 case ConfirmationEvent::RetryTRR
:
854 MOZ_ASSERT(mState
== CONFIRM_OK
);
855 maybeConfirm("retry-trr");
857 case ConfirmationEvent::URIChange
:
859 maybeConfirm("uri-change");
861 case ConfirmationEvent::CaptivePortalConnectivity
:
862 // If we area already confirmed then we're fine.
863 // If there is a confirmation in progress, likely it started before
864 // we had full connectivity, so it may be hanging. We reset and try again.
865 if (mState
== CONFIRM_FAILED
|| mState
== CONFIRM_TRYING_FAILED
||
866 mState
== CONFIRM_TRYING_OK
) {
868 maybeConfirm("cp-connectivity");
871 case ConfirmationEvent::NetworkUp
:
872 if (mState
!= CONFIRM_OK
) {
874 maybeConfirm("network-up");
877 case ConfirmationEvent::ConfirmOK
:
878 SetState(CONFIRM_OK
);
881 case ConfirmationEvent::ConfirmFail
:
882 MOZ_ASSERT(mState
== CONFIRM_TRYING_OK
||
883 mState
== CONFIRM_TRYING_FAILED
);
884 SetState(CONFIRM_FAILED
);
886 // retry failed NS confirmation
888 NS_NewTimerWithCallback(getter_AddRefs(mTimer
), this, mRetryInterval
,
889 nsITimer::TYPE_ONE_SHOT
);
890 if (mRetryInterval
< 64000) {
891 // double the interval up to this point
896 MOZ_ASSERT_UNREACHABLE("Unexpected ConfirmationEvent");
899 return prevAddr
!= TaskAddr();
902 bool TRRService::MaybeBootstrap(const nsACString
& aPossible
,
903 nsACString
& aResult
) {
904 MutexSingleWriterAutoLock
lock(mLock
);
905 if (mMode
== nsIDNSService::MODE_TRROFF
|| mBootstrapAddr
.IsEmpty()) {
909 nsCOMPtr
<nsIURI
> url
;
911 NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID
)
912 .Apply(&nsIStandardURLMutator::Init
, nsIStandardURL::URLTYPE_STANDARD
,
913 443, mPrivateURI
, nullptr, nullptr, nullptr)
916 LOG(("TRRService::MaybeBootstrap failed to create URI!\n"));
922 if (!aPossible
.Equals(host
)) {
925 LOG(("TRRService::MaybeBootstrap: use %s instead of %s\n",
926 mBootstrapAddr
.get(), host
.get()));
927 aResult
= mBootstrapAddr
;
931 bool TRRService::IsDomainBlocked(const nsACString
& aHost
,
932 const nsACString
& aOriginSuffix
,
933 bool aPrivateBrowsing
) {
934 auto bl
= mTRRBLStorage
.Lock();
939 // use a unified casing for the hashkey
940 nsAutoCString
hashkey(aHost
+ aOriginSuffix
);
941 if (auto val
= bl
->Lookup(hashkey
)) {
943 *val
+ int32_t(StaticPrefs::network_trr_temp_blocklist_duration_sec());
944 int32_t expire
= NowInSeconds();
945 if (until
> expire
) {
946 LOG(("Host [%s] is TRR blocklisted\n", nsCString(aHost
).get()));
950 // the blocklisted entry has expired
956 // When running in TRR-only mode, the blocklist is not used and it will also
957 // try resolving the localhost / .local names.
958 bool TRRService::IsTemporarilyBlocked(const nsACString
& aHost
,
959 const nsACString
& aOriginSuffix
,
960 bool aPrivateBrowsing
,
961 bool aParentsToo
) // false if domain
963 if (!StaticPrefs::network_trr_temp_blocklist()) {
964 LOG(("TRRService::IsTemporarilyBlocked temp blocklist disabled by pref"));
968 if (mMode
== nsIDNSService::MODE_TRRONLY
) {
969 return false; // might as well try
972 LOG(("Checking if host [%s] is blocklisted", aHost
.BeginReading()));
974 int32_t dot
= aHost
.FindChar('.');
975 if ((dot
== kNotFound
) && aParentsToo
) {
976 // Only if a full host name. Domains can be dotless to be able to
977 // blocklist entire TLDs
981 if (IsDomainBlocked(aHost
, aOriginSuffix
, aPrivateBrowsing
)) {
985 nsDependentCSubstring domain
= Substring(aHost
, 0);
986 while (dot
!= kNotFound
) {
988 domain
.Rebind(domain
, dot
, domain
.Length() - dot
);
990 if (IsDomainBlocked(domain
, aOriginSuffix
, aPrivateBrowsing
)) {
994 dot
= domain
.FindChar('.');
1000 bool TRRService::IsExcludedFromTRR(const nsACString
& aHost
) {
1001 // This method may be called off the main thread. We need to lock so
1002 // mExcludedDomains and mDNSSuffixDomains don't change while this code
1004 MutexSingleWriterAutoLock
lock(mLock
);
1006 return IsExcludedFromTRR_unlocked(aHost
);
1009 bool TRRService::IsExcludedFromTRR_unlocked(const nsACString
& aHost
) {
1010 mLock
.AssertOnWritingThreadOrHeld();
1013 // iteratively check the sub-domain of |aHost|
1014 while (dot
< static_cast<int32_t>(aHost
.Length())) {
1015 nsDependentCSubstring subdomain
=
1016 Substring(aHost
, dot
, aHost
.Length() - dot
);
1018 if (mExcludedDomains
.Contains(subdomain
)) {
1019 LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR via pref\n",
1020 subdomain
.BeginReading(), aHost
.BeginReading()));
1023 if (mDNSSuffixDomains
.Contains(subdomain
)) {
1024 LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR via pref\n",
1025 subdomain
.BeginReading(), aHost
.BeginReading()));
1028 if (mEtcHostsDomains
.Contains(subdomain
)) {
1029 LOG(("Subdomain [%s] of host [%s] Is Excluded From TRR by /etc/hosts\n",
1030 subdomain
.BeginReading(), aHost
.BeginReading()));
1034 dot
= aHost
.FindChar('.', dot
+ 1);
1035 if (dot
== kNotFound
) {
1044 void TRRService::AddToBlocklist(const nsACString
& aHost
,
1045 const nsACString
& aOriginSuffix
,
1046 bool privateBrowsing
, bool aParentsToo
) {
1047 if (!StaticPrefs::network_trr_temp_blocklist()) {
1048 LOG(("TRRService::AddToBlocklist temp blocklist disabled by pref"));
1052 LOG(("TRR blocklist %s\n", nsCString(aHost
).get()));
1053 nsAutoCString
hashkey(aHost
+ aOriginSuffix
);
1055 // this overwrites any existing entry
1057 auto bl
= mTRRBLStorage
.Lock();
1058 bl
->InsertOrUpdate(hashkey
, NowInSeconds());
1061 // See bug 1700405. Some test expects 15 trr consecutive failures, but the NS
1062 // check against the base domain is successful. So, we skip this NS check when
1063 // the pref said so in order to pass the test reliably.
1064 if (aParentsToo
&& !StaticPrefs::network_trr_skip_check_for_blocked_host()) {
1065 // when given a full host name, verify its domain as well
1066 int32_t dot
= aHost
.FindChar('.');
1067 if (dot
!= kNotFound
) {
1068 // this has a domain to be checked
1070 nsDependentCSubstring domain
=
1071 Substring(aHost
, dot
, aHost
.Length() - dot
);
1072 nsAutoCString
check(domain
);
1073 if (IsTemporarilyBlocked(check
, aOriginSuffix
, privateBrowsing
, false)) {
1074 // the domain part is already blocklisted, no need to add this entry
1077 // verify 'check' over TRR
1078 LOG(("TRR: verify if '%s' resolves as NS\n", check
.get()));
1080 // check if there's an NS entry for this name
1081 RefPtr
<TRR
> trr
= new TRR(this, check
, TRRTYPE_NS
, aOriginSuffix
,
1082 privateBrowsing
, false);
1083 trr
->SetPurpose(TRR::Blocklist
);
1084 DispatchTRRRequest(trr
);
1090 TRRService::ConfirmationContext::Notify(nsITimer
* aTimer
) {
1091 MutexSingleWriterAutoLock
lock(OwningObject()->mLock
);
1092 if (aTimer
== mTimer
) {
1093 HandleEvent(ConfirmationEvent::ConfirmationRetry
, lock
);
1100 TRRService::ConfirmationContext::GetName(nsACString
& aName
) {
1101 aName
.AssignLiteral("TRRService::ConfirmationContext");
1105 static char StatusToChar(nsresult aLookupStatus
, nsresult aChannelStatus
) {
1106 // If the resolution fails in the TRR channel then we'll have a failed
1107 // aChannelStatus. Otherwise, we parse the response - if it's not a valid DNS
1108 // packet or doesn't contain the correct responses aLookupStatus will be a
1110 if (aChannelStatus
== NS_OK
) {
1111 // Return + if confirmation was OK, or - if confirmation failed
1112 return aLookupStatus
== NS_OK
? '+' : '-';
1115 if (nsCOMPtr
<nsIIOService
> ios
= do_GetIOService()) {
1116 bool hasConnectiviy
= true;
1117 ios
->GetConnectivity(&hasConnectiviy
);
1118 if (!hasConnectiviy
) {
1119 // Browser has no active network interfaces = is offline.
1124 switch (aChannelStatus
) {
1125 case NS_ERROR_NET_TIMEOUT_EXTERNAL
:
1126 // TRR timeout expired
1128 case NS_ERROR_UNKNOWN_HOST
:
1129 // TRRServiceChannel failed to due to unresolved host
1135 // The error is a network error
1136 if (NS_ERROR_GET_MODULE(aChannelStatus
) == NS_ERROR_MODULE_NETWORK
) {
1140 // Some other kind of failure.
1144 void TRRService::RetryTRRConfirm() {
1145 if (mConfirmation
.State() == CONFIRM_OK
) {
1146 LOG(("TRRService::RetryTRRConfirm triggering confirmation"));
1147 mConfirmation
.HandleEvent(ConfirmationEvent::RetryTRR
);
1151 void TRRService::RecordTRRStatus(TRR
* aTrrRequest
) {
1152 MOZ_ASSERT_IF(XRE_IsParentProcess(), NS_IsMainThread() || IsOnTRRThread());
1153 MOZ_ASSERT_IF(XRE_IsSocketProcess(), NS_IsMainThread());
1155 nsresult channelStatus
= aTrrRequest
->ChannelStatus();
1157 Telemetry::AccumulateCategoricalKeyed(
1158 ProviderKey(), NS_SUCCEEDED(channelStatus
)
1159 ? Telemetry::LABELS_DNS_TRR_SUCCESS3::Fine
1160 : (channelStatus
== NS_ERROR_NET_TIMEOUT_EXTERNAL
1161 ? Telemetry::LABELS_DNS_TRR_SUCCESS3::Timeout
1162 : Telemetry::LABELS_DNS_TRR_SUCCESS3::Bad
));
1164 mConfirmation
.RecordTRRStatus(aTrrRequest
);
1167 void TRRService::ConfirmationContext::RecordTRRStatus(TRR
* aTrrRequest
) {
1168 nsresult channelStatus
= aTrrRequest
->ChannelStatus();
1170 if (OwningObject()->Mode() == nsIDNSService::MODE_TRRONLY
) {
1171 mLastConfirmationSkipReason
= aTrrRequest
->SkipReason();
1172 mLastConfirmationStatus
= channelStatus
;
1175 if (NS_SUCCEEDED(channelStatus
)) {
1176 LOG(("TRRService::RecordTRRStatus channel success"));
1181 if (OwningObject()->Mode() != nsIDNSService::MODE_TRRFIRST
) {
1185 // only count failures while in OK state
1186 if (State() != CONFIRM_OK
) {
1190 // When TRR retry is enabled, nsHostResolver will trigger Confirmation
1191 // immediately upon a lookup failure, so nothing to be done here.
1192 // nsHostResolver can assess the success of the lookup considering all the
1193 // involved results (A, AAAA) so we let it tell us when to re-Confirm.
1194 if (StaticPrefs::network_trr_retry_on_recoverable_errors()) {
1195 LOG(("TRRService not counting failures when retry is enabled"));
1199 mFailureReasons
[mTRRFailures
% ConfirmationContext::RESULTS_SIZE
] =
1200 StatusToChar(NS_OK
, channelStatus
);
1201 uint32_t fails
= ++mTRRFailures
;
1202 LOG(("TRRService::RecordTRRStatus fails=%u", fails
));
1204 if (fails
>= StaticPrefs::network_trr_max_fails()) {
1205 LOG(("TRRService had %u failures in a row\n", fails
));
1206 // When several failures occur we trigger a confirmation causing
1207 // us to transition into the CONFIRM_TRYING_OK state.
1208 // Only after the confirmation fails do we finally go into CONFIRM_FAILED
1209 // and start skipping TRR.
1211 // Trigger a confirmation immediately.
1212 // If it fails, it will fire off a timer to start retrying again.
1213 HandleEvent(ConfirmationEvent::FailedLookups
);
1217 void TRRService::ConfirmationContext::RecordEvent(
1218 const char* aReason
, const MutexSingleWriterAutoLock
&) {
1219 // Reset the confirmation context attributes
1220 // Only resets the attributes that we keep for telemetry purposes.
1221 auto reset
= [&]() {
1223 mNetworkId
.Truncate();
1224 mFirstRequestTime
= TimeStamp();
1225 mContextChangeReason
.Assign(aReason
);
1226 mTrigger
.Truncate();
1227 mFailedLookups
.Truncate();
1229 mRetryInterval
= StaticPrefs::network_trr_retry_timeout_ms();
1232 if (mAttemptCount
== 0) {
1233 // XXX: resetting everything might not be the best thing here, even if the
1234 // context changes, because there might still be a confirmation pending.
1235 // But cancelling and retrying that confirmation might just make the whole
1236 // confirmation longer for no reason.
1241 Telemetry::EventID eventType
=
1242 Telemetry::EventID::NetworkDns_Trrconfirmation_Context
;
1244 nsAutoCString results
;
1245 static_assert(RESULTS_SIZE
< 64);
1247 // mResults is a circular buffer ending at mAttemptCount
1248 if (mAttemptCount
<= RESULTS_SIZE
) {
1249 // We have fewer attempts than the size of the buffer, so all of the
1250 // results are in the buffer.
1251 results
.Append(nsDependentCSubstring(mResults
, mAttemptCount
));
1253 // More attempts than the buffer size.
1254 // That means past RESULTS_SIZE attempts in order are
1255 // [posInResults .. end-of-buffer) + [start-of-buffer .. posInResults)
1256 uint32_t posInResults
= mAttemptCount
% RESULTS_SIZE
;
1258 results
.Append(nsDependentCSubstring(mResults
+ posInResults
,
1259 RESULTS_SIZE
- posInResults
));
1260 results
.Append(nsDependentCSubstring(mResults
, posInResults
));
1263 auto extra
= Some
<nsTArray
<mozilla::Telemetry::EventExtraEntry
>>({
1264 Telemetry::EventExtraEntry
{"trigger"_ns
, mTrigger
},
1265 Telemetry::EventExtraEntry
{"contextReason"_ns
, mContextChangeReason
},
1266 Telemetry::EventExtraEntry
{"attemptCount"_ns
,
1267 nsPrintfCString("%u", mAttemptCount
)},
1268 Telemetry::EventExtraEntry
{"results"_ns
, results
},
1269 Telemetry::EventExtraEntry
{
1273 !mFirstRequestTime
.IsNull()
1274 ? (TimeStamp::Now() - mFirstRequestTime
).ToMilliseconds()
1276 Telemetry::EventExtraEntry
{"networkID"_ns
, mNetworkId
},
1277 Telemetry::EventExtraEntry
{"captivePortal"_ns
,
1278 nsPrintfCString("%i", mCaptivePortalStatus
)},
1281 if (mTrigger
.Equals("failed-lookups"_ns
)) {
1282 extra
.ref().AppendElement(
1283 Telemetry::EventExtraEntry
{"failedLookups"_ns
, mFailedLookups
});
1286 enum ConfirmationState state
= mState
;
1287 Telemetry::RecordEvent(eventType
, mozilla::Some(nsPrintfCString("%u", state
)),
1293 void TRRService::ConfirmationContext::RequestCompleted(
1294 nsresult aLookupStatus
, nsresult aChannelStatus
) {
1295 mResults
[mAttemptCount
% RESULTS_SIZE
] =
1296 StatusToChar(aLookupStatus
, aChannelStatus
);
1300 void TRRService::ConfirmationContext::CompleteConfirmation(nsresult aStatus
,
1303 MutexSingleWriterAutoLock
lock(OwningObject()->mLock
);
1304 // Ignore confirmations that dont match the pending task.
1305 if (mTask
!= aTRRRequest
) {
1308 MOZ_ASSERT(State() == CONFIRM_TRYING_OK
||
1309 State() == CONFIRM_TRYING_FAILED
);
1310 if (State() != CONFIRM_TRYING_OK
&& State() != CONFIRM_TRYING_FAILED
) {
1314 RequestCompleted(aStatus
, aTRRRequest
->ChannelStatus());
1315 mLastConfirmationSkipReason
= aTRRRequest
->SkipReason();
1316 mLastConfirmationStatus
= aTRRRequest
->ChannelStatus();
1319 if (NS_SUCCEEDED(aStatus
)) {
1320 HandleEvent(ConfirmationEvent::ConfirmOK
, lock
);
1322 HandleEvent(ConfirmationEvent::ConfirmFail
, lock
);
1325 if (State() == CONFIRM_OK
) {
1326 // Record event and start new confirmation context
1327 RecordEvent("success", lock
);
1329 LOG(("TRRService finishing confirmation test %s %d %X\n",
1330 OwningObject()->mPrivateURI
.get(), State(), (unsigned int)aStatus
));
1333 if (State() == CONFIRM_OK
) {
1334 // A fresh confirmation means previous blocked entries might not
1335 // be valid anymore.
1336 auto bl
= OwningObject()->mTRRBLStorage
.Lock();
1339 MOZ_ASSERT(State() == CONFIRM_FAILED
);
1342 Telemetry::Accumulate(Telemetry::DNS_TRR_NS_VERFIFIED3
,
1343 TRRService::ProviderKey(), (State() == CONFIRM_OK
));
1346 AHostResolver::LookupStatus
TRRService::CompleteLookup(
1347 nsHostRecord
* rec
, nsresult status
, AddrInfo
* aNewRRSet
, bool pb
,
1348 const nsACString
& aOriginSuffix
, TRRSkippedReason aReason
,
1350 // this is an NS check for the TRR blocklist or confirmationNS check
1352 MOZ_ASSERT_IF(XRE_IsParentProcess(), NS_IsMainThread() || IsOnTRRThread());
1353 MOZ_ASSERT_IF(XRE_IsSocketProcess(), NS_IsMainThread());
1356 RefPtr
<AddrInfo
> newRRSet(aNewRRSet
);
1357 MOZ_ASSERT(newRRSet
&& newRRSet
->TRRType() == TRRTYPE_NS
);
1359 if (aTRRRequest
->Purpose() == TRR::Confirmation
) {
1360 mConfirmation
.CompleteConfirmation(status
, aTRRRequest
);
1364 if (aTRRRequest
->Purpose() == TRR::Blocklist
) {
1365 if (NS_SUCCEEDED(status
)) {
1366 LOG(("TRR verified %s to be fine!\n", newRRSet
->Hostname().get()));
1368 LOG(("TRR says %s doesn't resolve as NS!\n", newRRSet
->Hostname().get()));
1369 AddToBlocklist(newRRSet
->Hostname(), aOriginSuffix
, pb
, false);
1374 MOZ_ASSERT_UNREACHABLE(
1375 "TRRService::CompleteLookup called for unexpected request");
1379 AHostResolver::LookupStatus
TRRService::CompleteLookupByType(
1380 nsHostRecord
*, nsresult
, mozilla::net::TypeRecordResultType
& aResult
,
1381 mozilla::net::TRRSkippedReason aReason
, uint32_t aTtl
, bool aPb
) {
1385 NS_IMETHODIMP
TRRService::OnProxyConfigChanged() {
1386 LOG(("TRRService::OnProxyConfigChanged"));
1390 AsyncCreateTRRConnectionInfo(uri
);
1395 void TRRService::InitTRRConnectionInfo() {
1396 if (XRE_IsParentProcess()) {
1397 TRRServiceBase::InitTRRConnectionInfo();
1401 MOZ_ASSERT(XRE_IsSocketProcess());
1402 MOZ_ASSERT(NS_IsMainThread());
1404 TRRServiceChild
* child
= TRRServiceChild::GetSingleton();
1405 if (child
&& child
->CanSend()) {
1406 LOG(("TRRService::SendInitTRRConnectionInfo"));
1407 Unused
<< child
->SendInitTRRConnectionInfo();
1411 } // namespace mozilla::net