Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / netwerk / base / nsDNSPrefetch.cpp
blob4c5a3a0fd6711317aab6333b5c3ed1f7988be46b
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"
7 #include "nsCOMPtr.h"
8 #include "nsString.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"
16 #include "nsIURI.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;
26 return NS_OK;
29 nsresult nsDNSPrefetch::Shutdown() {
30 sDNSService = nullptr;
31 return NS_OK;
34 nsDNSPrefetch::nsDNSPrefetch(nsIURI* aURI,
35 mozilla::OriginAttributes& aOriginAttributes,
36 nsIRequest::TRRMode aTRRMode,
37 nsIDNSListener* aListener, bool storeTiming)
38 : mOriginAttributes(aOriginAttributes),
39 mStoreTiming(storeTiming),
40 mTRRMode(aTRRMode),
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),
50 mStoreTiming(false),
51 mTRRMode(aTRRMode),
52 mListener(nullptr) {
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);
90 namespace {
92 class HTTPSRRListener final : public nsIDNSListener {
93 public:
94 NS_DECL_THREADSAFE_ISUPPORTS
95 NS_DECL_NSIDNSLISTENER
97 explicit HTTPSRRListener(
98 std::function<void(nsIDNSHTTPSSVCRecord*)>&& aCallback)
99 : mResultCallback(std::move(aCallback)) {}
101 private:
102 ~HTTPSRRListener() = default;
103 std::function<void(nsIDNSHTTPSSVCRecord*)> mResultCallback;
106 NS_IMPL_ISUPPORTS(HTTPSRRListener, nsIDNSListener)
108 NS_IMETHODIMP
109 HTTPSRRListener::OnLookupComplete(nsICancelable* aRequest, nsIDNSRecord* aRec,
110 nsresult aStatus) {
111 if (NS_FAILED(aStatus)) {
112 mResultCallback(nullptr);
113 return NS_OK;
116 nsCOMPtr<nsIDNSHTTPSSVCRecord> httpsRecord = do_QueryInterface(aRec);
117 mResultCallback(httpsRecord);
118 return NS_OK;
121 }; // namespace
123 nsresult nsDNSPrefetch::FetchHTTPSSVC(
124 bool aRefreshDNS, bool aPrefetch,
125 std::function<void(nsIDNSHTTPSSVCRecord*)>&& aCallback) {
126 if (!sDNSService) {
127 return NS_ERROR_NOT_AVAILABLE;
130 nsCOMPtr<nsIEventTarget> target = mozilla::GetCurrentSerialEventTarget();
131 nsIDNSService::DNSFlags flags = nsIDNSService::GetFlagsFromTRRMode(mTRRMode);
132 if (aRefreshDNS) {
133 flags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
135 if (aPrefetch) {
136 flags |= nsIDNSService::RESOLVE_SPECULATE;
139 nsCOMPtr<nsICancelable> tmpOutstanding;
140 nsCOMPtr<nsIDNSListener> listener = new HTTPSRRListener(std::move(aCallback));
141 nsCOMPtr<nsIDNSAdditionalInfo> info;
142 if (mPort != -1) {
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)
152 NS_IMETHODIMP
153 nsDNSPrefetch::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
154 nsresult status) {
155 if (mStoreTiming) {
156 mEndTimestamp = mozilla::TimeStamp::Now();
158 nsCOMPtr<nsIDNSListener> listener = do_QueryReferent(mListener);
159 if (listener) {
160 listener->OnLookupComplete(request, rec, status);
163 return NS_OK;