1 /* -*- Mode: C++; tab-width: 4; 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 "nsDNSPrefetch.h"
9 #include "nsThreadUtils.h"
11 #include "nsIDNSAdditionalInfo.h"
12 #include "nsIDNSListener.h"
13 #include "nsIDNSService.h"
14 #include "nsIDNSByTypeRecord.h"
15 #include "nsICancelable.h"
17 #include "mozilla/Atomics.h"
18 #include "mozilla/Preferences.h"
20 static mozilla::StaticRefPtr
<nsIDNSService
> sDNSService
;
22 nsresult
nsDNSPrefetch::Initialize(nsIDNSService
* aDNSService
) {
23 MOZ_ASSERT(NS_IsMainThread());
25 sDNSService
= aDNSService
;
29 nsresult
nsDNSPrefetch::Shutdown() {
30 sDNSService
= nullptr;
34 nsDNSPrefetch::nsDNSPrefetch(nsIURI
* aURI
,
35 mozilla::OriginAttributes
& aOriginAttributes
,
36 nsIRequest::TRRMode aTRRMode
,
37 nsIDNSListener
* aListener
, bool storeTiming
)
38 : mOriginAttributes(aOriginAttributes
),
39 mStoreTiming(storeTiming
),
41 mListener(do_GetWeakReference(aListener
)) {
42 aURI
->GetAsciiHost(mHostname
);
43 aURI
->GetPort(&mPort
);
46 nsDNSPrefetch::nsDNSPrefetch(nsIURI
* aURI
,
47 mozilla::OriginAttributes
& aOriginAttributes
,
48 nsIRequest::TRRMode aTRRMode
)
49 : mOriginAttributes(aOriginAttributes
),
53 aURI
->GetAsciiHost(mHostname
);
56 nsresult
nsDNSPrefetch::Prefetch(nsIDNSService::DNSFlags flags
) {
57 if (mHostname
.IsEmpty()) return NS_ERROR_NOT_AVAILABLE
;
59 if (!sDNSService
) return NS_ERROR_NOT_AVAILABLE
;
61 nsCOMPtr
<nsICancelable
> tmpOutstanding
;
63 if (mStoreTiming
) mStartTimestamp
= mozilla::TimeStamp::Now();
64 // If AsyncResolve fails, for example because prefetching is disabled,
65 // then our timing will be useless. However, in such a case,
66 // mEndTimestamp will be a null timestamp and callers should check
67 // TimingsValid() before using the timing.
68 nsCOMPtr
<nsIEventTarget
> target
= mozilla::GetCurrentSerialEventTarget();
70 flags
|= nsIDNSService::GetFlagsFromTRRMode(mTRRMode
);
72 return sDNSService
->AsyncResolveNative(
73 mHostname
, nsIDNSService::RESOLVE_TYPE_DEFAULT
,
74 flags
| nsIDNSService::RESOLVE_SPECULATE
, nullptr, this, target
,
75 mOriginAttributes
, getter_AddRefs(tmpOutstanding
));
78 nsresult
nsDNSPrefetch::PrefetchLow(nsIDNSService::DNSFlags aFlags
) {
79 return Prefetch(nsIDNSService::RESOLVE_PRIORITY_LOW
| aFlags
);
82 nsresult
nsDNSPrefetch::PrefetchMedium(nsIDNSService::DNSFlags aFlags
) {
83 return Prefetch(nsIDNSService::RESOLVE_PRIORITY_MEDIUM
| aFlags
);
86 nsresult
nsDNSPrefetch::PrefetchHigh(nsIDNSService::DNSFlags aFlags
) {
87 return Prefetch(aFlags
);
92 class HTTPSRRListener final
: public nsIDNSListener
{
94 NS_DECL_THREADSAFE_ISUPPORTS
95 NS_DECL_NSIDNSLISTENER
97 explicit HTTPSRRListener(
98 std::function
<void(nsIDNSHTTPSSVCRecord
*)>&& aCallback
)
99 : mResultCallback(std::move(aCallback
)) {}
102 ~HTTPSRRListener() = default;
103 std::function
<void(nsIDNSHTTPSSVCRecord
*)> mResultCallback
;
106 NS_IMPL_ISUPPORTS(HTTPSRRListener
, nsIDNSListener
)
109 HTTPSRRListener::OnLookupComplete(nsICancelable
* aRequest
, nsIDNSRecord
* aRec
,
111 if (NS_FAILED(aStatus
)) {
112 mResultCallback(nullptr);
116 nsCOMPtr
<nsIDNSHTTPSSVCRecord
> httpsRecord
= do_QueryInterface(aRec
);
117 mResultCallback(httpsRecord
);
123 nsresult
nsDNSPrefetch::FetchHTTPSSVC(
124 bool aRefreshDNS
, bool aPrefetch
,
125 std::function
<void(nsIDNSHTTPSSVCRecord
*)>&& aCallback
) {
127 return NS_ERROR_NOT_AVAILABLE
;
130 nsCOMPtr
<nsIEventTarget
> target
= mozilla::GetCurrentSerialEventTarget();
131 nsIDNSService::DNSFlags flags
= nsIDNSService::GetFlagsFromTRRMode(mTRRMode
);
133 flags
|= nsIDNSService::RESOLVE_BYPASS_CACHE
;
136 flags
|= nsIDNSService::RESOLVE_SPECULATE
;
139 nsCOMPtr
<nsICancelable
> tmpOutstanding
;
140 nsCOMPtr
<nsIDNSListener
> listener
= new HTTPSRRListener(std::move(aCallback
));
141 nsCOMPtr
<nsIDNSAdditionalInfo
> info
;
143 sDNSService
->NewAdditionalInfo(""_ns
, mPort
, getter_AddRefs(info
));
145 return sDNSService
->AsyncResolveNative(
146 mHostname
, nsIDNSService::RESOLVE_TYPE_HTTPSSVC
, flags
, info
, listener
,
147 target
, mOriginAttributes
, getter_AddRefs(tmpOutstanding
));
150 NS_IMPL_ISUPPORTS(nsDNSPrefetch
, nsIDNSListener
)
153 nsDNSPrefetch::OnLookupComplete(nsICancelable
* request
, nsIDNSRecord
* rec
,
156 mEndTimestamp
= mozilla::TimeStamp::Now();
158 nsCOMPtr
<nsIDNSListener
> listener
= do_QueryReferent(mListener
);
160 listener
->OnLookupComplete(request
, rec
, status
);