Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / netwerk / dns / TRRService.h
blobeb4f6e9ae75256117de5cc2e26d1bb8cf2f7ad5b
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 #ifndef TRRService_h_
7 #define TRRService_h_
9 #include "mozilla/DataMutex.h"
10 #include "nsHostResolver.h"
11 #include "nsIObserver.h"
12 #include "nsITimer.h"
13 #include "nsWeakReference.h"
14 #include "TRRServiceBase.h"
15 #include "nsICaptivePortalService.h"
16 #include "nsTHashSet.h"
17 #include "TRR.h"
19 class nsDNSService;
20 class nsIPrefBranch;
21 class nsINetworkLinkService;
22 class nsIObserverService;
24 namespace mozilla {
25 namespace net {
27 class TRRServiceChild;
28 class TRRServiceParent;
30 class TRRService : public TRRServiceBase,
31 public nsIObserver,
32 public nsSupportsWeakReference,
33 public AHostResolver,
34 public SingleWriterLockOwner {
35 public:
36 NS_DECL_ISUPPORTS_INHERITED
37 NS_DECL_NSIOBSERVER
38 NS_DECL_NSIPROXYCONFIGCHANGEDCALLBACK
40 TRRService();
41 static TRRService* Get();
43 bool OnWritingThread() const override { return NS_IsMainThread(); }
45 nsresult Init(bool aNativeHTTPSQueryEnabled);
46 nsresult Start();
47 bool Enabled(nsIRequest::TRRMode aRequestMode = nsIRequest::TRR_DEFAULT_MODE);
48 bool IsConfirmed() { return mConfirmation.State() == CONFIRM_OK; }
49 uint32_t ConfirmationState() { return mConfirmation.State(); }
51 void GetURI(nsACString& result) override;
52 nsresult GetCredentials(nsCString& result);
53 uint32_t GetRequestTimeout();
54 void RetryTRRConfirm();
56 LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*,
57 bool pb, const nsACString& aOriginSuffix,
58 TRRSkippedReason aReason,
59 TRR* aTrrRequest) override;
60 LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
61 mozilla::net::TypeRecordResultType&,
62 TRRSkippedReason, uint32_t,
63 bool pb) override;
64 void AddToBlocklist(const nsACString& host, const nsACString& originSuffix,
65 bool privateBrowsing, bool aParentsToo);
66 bool IsTemporarilyBlocked(const nsACString& aHost,
67 const nsACString& aOriginSuffix,
68 bool aPrivateBrowsing, bool aParentsToo);
69 bool IsExcludedFromTRR(const nsACString& aHost);
71 bool MaybeBootstrap(const nsACString& possible, nsACString& result);
72 void RecordTRRStatus(TRR* aTrrRequest);
73 bool ParentalControlEnabled() const { return mParentalControlEnabled; }
75 nsresult DispatchTRRRequest(TRR* aTrrRequest);
76 already_AddRefed<nsIThread> TRRThread();
77 bool IsOnTRRThread();
79 bool IsUsingAutoDetectedURL() { return mURISetByDetection; }
81 void SetHeuristicDetectionResult(TRRSkippedReason aValue) {
82 mHeuristicDetectionValue = aValue;
84 TRRSkippedReason GetHeuristicDetectionResult() {
85 return mHeuristicDetectionValue;
88 nsresult LastConfirmationStatus() {
89 return mConfirmation.LastConfirmationStatus();
91 TRRSkippedReason LastConfirmationSkipReason() {
92 return mConfirmation.LastConfirmationSkipReason();
95 // Returns a reference to a static string identifying the current DoH server
96 // If the DoH server is not one of the built-in ones it will return "(other)"
97 static const nsCString& ProviderKey();
98 static void SetProviderDomain(const nsACString& aTRRDomain);
99 // Only called when TRR mode changed.
100 static void SetCurrentTRRMode(nsIDNSService::ResolverMode aMode);
102 void InitTRRConnectionInfo() override;
104 void DontUseTRRThread() { mDontUseTRRThread = true; }
106 private:
107 virtual ~TRRService();
109 friend class TRRServiceChild;
110 friend class TRRServiceParent;
111 static void AddObserver(nsIObserver* aObserver,
112 nsIObserverService* aObserverService = nullptr);
113 static bool CheckCaptivePortalIsPassed();
114 static bool GetParentalControlsEnabledInternal();
115 // Exposed for testing purposes only
116 static bool ReloadParentalControlsEnabled();
118 static bool CheckPlatformDNSStatus(nsINetworkLinkService* aLinkService);
120 nsresult ReadPrefs(const char* name);
121 void GetPrefBranch(nsIPrefBranch** result);
122 friend class ::nsDNSService;
123 void SetDetectedTrrURI(const nsACString& aURI);
125 bool IsDomainBlocked(const nsACString& aHost, const nsACString& aOriginSuffix,
126 bool aPrivateBrowsing);
127 bool IsExcludedFromTRR_unlocked(const nsACString& aHost);
129 void RebuildSuffixList(nsTArray<nsCString>&& aSuffixList);
131 nsresult DispatchTRRRequestInternal(TRR* aTrrRequest, bool aWithLock);
132 already_AddRefed<nsIThread> TRRThread_locked();
133 already_AddRefed<nsIThread> MainThreadOrTRRThread(bool aWithLock = true);
135 // This method will process the URI and try to set mPrivateURI to that value.
136 // Will return true if performed the change (if the value was different)
137 // or false if mPrivateURI already had that value.
138 bool MaybeSetPrivateURI(const nsACString& aURI) override;
139 void ClearEntireCache();
141 virtual void ReadEtcHostsFile() override;
142 void AddEtcHosts(const nsTArray<nsCString>&);
144 bool mInitialized{false};
145 MutexSingleWriter mLock;
147 nsCString mPrivateCred; // main thread only
148 nsCString mConfirmationNS MOZ_GUARDED_BY(mLock){"example.com"_ns};
149 nsCString mBootstrapAddr MOZ_GUARDED_BY(mLock);
151 Atomic<bool, Relaxed> mCaptiveIsPassed{
152 false}; // set when captive portal check is passed
153 Atomic<bool, Relaxed> mShutdown{false};
154 Atomic<bool, Relaxed> mDontUseTRRThread{false};
156 // TRR Blocklist storage
157 // mTRRBLStorage is only modified on the main thread, but we query whether it
158 // is initialized or not off the main thread as well. Therefore we need to
159 // lock while creating it and while accessing it off the main thread.
160 DataMutex<nsTHashMap<nsCStringHashKey, int32_t>> mTRRBLStorage{
161 "DataMutex::TRRBlocklist"};
163 // A set of domains that we should not use TRR for.
164 nsTHashSet<nsCString> mExcludedDomains MOZ_GUARDED_BY(mLock);
165 nsTHashSet<nsCString> mDNSSuffixDomains MOZ_GUARDED_BY(mLock);
166 nsTHashSet<nsCString> mEtcHostsDomains MOZ_GUARDED_BY(mLock);
168 // The result of the TRR heuristic detection
169 TRRSkippedReason mHeuristicDetectionValue = nsITRRSkipReason::TRR_UNSET;
171 enum class ConfirmationEvent {
172 Init,
173 PrefChange,
174 ConfirmationRetry,
175 FailedLookups,
176 RetryTRR,
177 URIChange,
178 CaptivePortalConnectivity,
179 NetworkUp,
180 ConfirmOK,
181 ConfirmFail,
184 // (FailedLookups/RetryTRR/URIChange/NetworkUp)
185 // +---------------------------+
186 // +-----------+ | |
187 // | (Init) | +------v---------+ +-+--+
188 // | | TRR turned on | | (ConfirmOK) | |
189 // | OFF +---------------> TRY-OK +---------------> OK |
190 // | | (PrefChange) | | | |
191 // +-----^-----+ +^-^----+--------+ +-^--+
192 // | (PrefChange/CP) | | | |
193 // TRR + +------------------+ | | |
194 // off | | +----+ |(ConfirmFail) |(ConfirmOK)
195 // (Pref)| | | | |
196 // +---------+-+ | | |
197 // | | (CPConn) | +-------v--------+ +-+---------+
198 // | ANY-STATE | (NetworkUp)| | | timer | |
199 // | | (URIChange)+-+ FAIL +---------------> TRY-FAIL |
200 // +-----+-----+ | | (Confirmation | |
201 // | +------^---------+ Retry) +------+----+
202 // | (PrefChange) | |
203 // | TRR_ONLY mode or +--------------------------------+
204 // | confirmationNS = skip (ConfirmFail)
205 // +-----v-----+
206 // | |
207 // | DISABLED |
208 // | |
209 // +-----------+
211 enum ConfirmationState {
212 CONFIRM_OFF = 0,
213 CONFIRM_TRYING_OK = 1,
214 CONFIRM_OK = 2,
215 CONFIRM_FAILED = 3,
216 CONFIRM_TRYING_FAILED = 4,
217 CONFIRM_DISABLED = 5,
220 class ConfirmationContext final : public nsITimerCallback, public nsINamed {
221 NS_DECL_ISUPPORTS_INHERITED
222 NS_DECL_NSITIMERCALLBACK
223 NS_DECL_NSINAMED
225 private:
226 static const size_t RESULTS_SIZE = 32;
228 RefPtr<TRR> mTask;
229 nsCOMPtr<nsITimer> mTimer;
230 uint32_t mRetryInterval = 125; // milliseconds until retry
231 // The number of TRR requests that failed in a row.
232 Atomic<uint32_t, Relaxed> mTRRFailures{0};
234 // This buffer holds consecutive TRR failures reported by calling
235 // RecordTRRStatus(). It is only meant for reporting event telemetry.
236 char mFailureReasons[RESULTS_SIZE] = {0};
238 // The number of confirmation retries.
239 uint32_t mAttemptCount = 0;
241 // The results of past confirmation attempts.
242 // This is circular buffer ending at mAttemptCount.
243 char mResults[RESULTS_SIZE] = {0};
245 // Time when first confirmation started. Needed so we can
246 // record the time from start to confirmed.
247 TimeStamp mFirstRequestTime;
248 // The network ID at the start of the last confirmation attempt
249 nsCString mNetworkId;
250 // Captive portal status at the time of recording.
251 int32_t mCaptivePortalStatus = nsICaptivePortalService::UNKNOWN;
253 // The reason the confirmation context changed.
254 nsCString mContextChangeReason;
256 // What triggered the confirmation
257 nsCString mTrigger;
259 // String representation of consecutive failed lookups that triggered
260 // confirmation.
261 nsCString mFailedLookups;
263 Atomic<TRRSkippedReason, Relaxed> mLastConfirmationSkipReason{
264 nsITRRSkipReason::TRR_UNSET};
265 Atomic<nsresult, Relaxed> mLastConfirmationStatus{NS_OK};
267 void SetState(enum ConfirmationState aNewState);
269 public:
270 // Called when a confirmation completes successfully or when the
271 // confirmation context changes.
272 void RecordEvent(const char* aReason, const MutexSingleWriterAutoLock&);
274 // Called when a confirmation request is completed. The status is recorded
275 // in the results.
276 void RequestCompleted(nsresult aLookupStatus, nsresult aChannelStatus);
278 enum ConfirmationState State() { return mState; }
280 void CompleteConfirmation(nsresult aStatus, TRR* aTrrRequest);
282 void RecordTRRStatus(TRR* aTrrRequest);
284 // Returns true when handling the event caused a new confirmation task to be
285 // dispatched.
286 bool HandleEvent(ConfirmationEvent aEvent);
287 bool HandleEvent(ConfirmationEvent aEvent,
288 const MutexSingleWriterAutoLock&);
290 void SetCaptivePortalStatus(int32_t aStatus) {
291 mCaptivePortalStatus = aStatus;
294 TRRSkippedReason LastConfirmationSkipReason() {
295 return mLastConfirmationSkipReason;
297 nsresult LastConfirmationStatus() { return mLastConfirmationStatus; }
299 uintptr_t TaskAddr() { return uintptr_t(mTask.get()); }
301 private:
302 // Since the ConfirmationContext is embedded in the TRRService object
303 // we can easily get a pointer to the TRRService. ConfirmationContext
304 // delegates AddRef/Release calls to the owning object since they are
305 // guaranteed to have the same lifetime.
306 TRRService* OwningObject() {
307 return reinterpret_cast<TRRService*>(
308 reinterpret_cast<uint8_t*>(this) -
309 offsetof(TRRService, mConfirmation) -
310 offsetof(ConfirmationWrapper, mConfirmation));
313 Atomic<enum ConfirmationState, Relaxed> mState{CONFIRM_OFF};
315 // TRRService needs to be a friend class because it needs to access the
316 // destructor.
317 friend class TRRService;
318 ~ConfirmationContext() = default;
321 // Because TRRService needs to be a friend class to ConfirmationContext that
322 // means it can access member variables. In order to properly separate logic
323 // and prevent direct access to its member variables we embed it in a wrapper
324 // class.
325 class ConfirmationWrapper {
326 public:
327 // Called when a confirmation completes successfully or when the
328 // confirmation context changes.
329 void RecordEvent(const char* aReason,
330 const MutexSingleWriterAutoLock& aLock) {
331 mConfirmation.RecordEvent(aReason, aLock);
334 // Called when a confirmation request is completed. The status is recorded
335 // in the results.
336 void RequestCompleted(nsresult aLookupStatus, nsresult aChannelStatus) {
337 mConfirmation.RequestCompleted(aLookupStatus, aChannelStatus);
340 enum ConfirmationState State() { return mConfirmation.State(); }
342 void CompleteConfirmation(nsresult aStatus, TRR* aTrrRequest) {
343 mConfirmation.CompleteConfirmation(aStatus, aTrrRequest);
346 void RecordTRRStatus(TRR* aTrrRequest) {
347 mConfirmation.RecordTRRStatus(aTrrRequest);
350 bool HandleEvent(ConfirmationEvent aEvent) {
351 return mConfirmation.HandleEvent(aEvent);
354 bool HandleEvent(ConfirmationEvent aEvent,
355 const MutexSingleWriterAutoLock& lock) {
356 return mConfirmation.HandleEvent(aEvent, lock);
359 void SetCaptivePortalStatus(int32_t aStatus) {
360 mConfirmation.SetCaptivePortalStatus(aStatus);
363 TRRSkippedReason LastConfirmationSkipReason() {
364 return mConfirmation.LastConfirmationSkipReason();
366 nsresult LastConfirmationStatus() {
367 return mConfirmation.LastConfirmationStatus();
370 private:
371 friend TRRService* ConfirmationContext::OwningObject();
372 ConfirmationContext mConfirmation;
375 ConfirmationWrapper mConfirmation;
377 bool mParentalControlEnabled{false};
378 // This is used to track whether a confirmation was triggered by a URI change,
379 // so we don't trigger another one just because other prefs have changed.
380 bool mConfirmationTriggered{false};
381 nsCOMPtr<nsINetworkLinkService> mLinkService;
384 } // namespace net
385 } // namespace mozilla
387 #endif // TRRService_h_