/src/mozilla-central/netwerk/base/nsDNSPrefetch.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
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/. */ |
5 | | |
6 | | #include "nsDNSPrefetch.h" |
7 | | #include "nsCOMPtr.h" |
8 | | #include "nsString.h" |
9 | | #include "nsThreadUtils.h" |
10 | | |
11 | | #include "nsIDNSListener.h" |
12 | | #include "nsIDNSService.h" |
13 | | #include "nsICancelable.h" |
14 | | #include "nsIURI.h" |
15 | | #include "mozilla/Preferences.h" |
16 | | |
17 | | static nsIDNSService *sDNSService = nullptr; |
18 | | static bool sESNIEnabled = false; |
19 | | |
20 | | nsresult |
21 | | nsDNSPrefetch::Initialize(nsIDNSService *aDNSService) |
22 | 3 | { |
23 | 3 | NS_IF_RELEASE(sDNSService); |
24 | 3 | sDNSService = aDNSService; |
25 | 3 | NS_IF_ADDREF(sDNSService); |
26 | 3 | mozilla::Preferences::AddBoolVarCache(&sESNIEnabled, "network.security.esni.enabled"); |
27 | 3 | return NS_OK; |
28 | 3 | } |
29 | | |
30 | | nsresult |
31 | | nsDNSPrefetch::Shutdown() |
32 | 0 | { |
33 | 0 | NS_IF_RELEASE(sDNSService); |
34 | 0 | return NS_OK; |
35 | 0 | } |
36 | | |
37 | | nsDNSPrefetch::nsDNSPrefetch(nsIURI *aURI, |
38 | | mozilla::OriginAttributes& aOriginAttributes, |
39 | | nsIDNSListener *aListener, |
40 | | bool storeTiming) |
41 | | : mOriginAttributes(aOriginAttributes) |
42 | | , mStoreTiming(storeTiming) |
43 | | , mListener(do_GetWeakReference(aListener)) |
44 | 0 | { |
45 | 0 | aURI->GetAsciiHost(mHostname); |
46 | 0 | mIsHttps = false; |
47 | 0 | aURI->SchemeIs("https", &mIsHttps); |
48 | 0 | } |
49 | | |
50 | | nsresult |
51 | | nsDNSPrefetch::Prefetch(uint16_t flags) |
52 | 0 | { |
53 | 0 | // This can work properly only if this call is on the main thread. |
54 | 0 | // Curenlty we use nsDNSPrefetch only in nsHttpChannel which will call |
55 | 0 | // PrefetchHigh() from the main thread. Let's add assertion to catch |
56 | 0 | // if things change. |
57 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Expecting DNS callback on main thread."); |
58 | 0 |
|
59 | 0 | if (mHostname.IsEmpty()) |
60 | 0 | return NS_ERROR_NOT_AVAILABLE; |
61 | 0 | |
62 | 0 | if (!sDNSService) |
63 | 0 | return NS_ERROR_NOT_AVAILABLE; |
64 | 0 | |
65 | 0 | nsCOMPtr<nsICancelable> tmpOutstanding; |
66 | 0 |
|
67 | 0 | if (mStoreTiming) |
68 | 0 | mStartTimestamp = mozilla::TimeStamp::Now(); |
69 | 0 | // If AsyncResolve fails, for example because prefetching is disabled, |
70 | 0 | // then our timing will be useless. However, in such a case, |
71 | 0 | // mEndTimestamp will be a null timestamp and callers should check |
72 | 0 | // TimingsValid() before using the timing. |
73 | 0 | nsCOMPtr<nsIEventTarget> main = mozilla::GetMainThreadEventTarget(); |
74 | 0 |
|
75 | 0 | nsresult rv = sDNSService->AsyncResolveNative(mHostname, |
76 | 0 | flags | nsIDNSService::RESOLVE_SPECULATE, |
77 | 0 | this, main, mOriginAttributes, |
78 | 0 | getter_AddRefs(tmpOutstanding)); |
79 | 0 | if (NS_FAILED(rv)) { |
80 | 0 | return rv; |
81 | 0 | } |
82 | 0 | |
83 | 0 | // Fetch esni keys if needed. |
84 | 0 | if (sESNIEnabled && mIsHttps) { |
85 | 0 | nsAutoCString esniHost; |
86 | 0 | esniHost.Append("_esni."); |
87 | 0 | esniHost.Append(mHostname); |
88 | 0 | sDNSService->AsyncResolveByTypeNative(esniHost, nsIDNSService::RESOLVE_TYPE_TXT, |
89 | 0 | flags | nsIDNSService::RESOLVE_SPECULATE, |
90 | 0 | this, main, mOriginAttributes, |
91 | 0 | getter_AddRefs(tmpOutstanding)); |
92 | 0 | } |
93 | 0 | return NS_OK; |
94 | 0 | } |
95 | | |
96 | | nsresult |
97 | | nsDNSPrefetch::PrefetchLow(bool refreshDNS) |
98 | 0 | { |
99 | 0 | return Prefetch(nsIDNSService::RESOLVE_PRIORITY_LOW | |
100 | 0 | (refreshDNS ? nsIDNSService::RESOLVE_BYPASS_CACHE : 0)); |
101 | 0 | } |
102 | | |
103 | | nsresult |
104 | | nsDNSPrefetch::PrefetchMedium(bool refreshDNS) |
105 | 0 | { |
106 | 0 | return Prefetch(nsIDNSService::RESOLVE_PRIORITY_MEDIUM | |
107 | 0 | (refreshDNS ? nsIDNSService::RESOLVE_BYPASS_CACHE : 0)); |
108 | 0 | } |
109 | | |
110 | | nsresult |
111 | | nsDNSPrefetch::PrefetchHigh(bool refreshDNS) |
112 | 0 | { |
113 | 0 | return Prefetch(refreshDNS ? |
114 | 0 | nsIDNSService::RESOLVE_BYPASS_CACHE : 0); |
115 | 0 | } |
116 | | |
117 | | NS_IMPL_ISUPPORTS(nsDNSPrefetch, nsIDNSListener) |
118 | | |
119 | | NS_IMETHODIMP |
120 | | nsDNSPrefetch::OnLookupComplete(nsICancelable *request, |
121 | | nsIDNSRecord *rec, |
122 | | nsresult status) |
123 | 0 | { |
124 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Expecting DNS callback on main thread."); |
125 | 0 |
|
126 | 0 | if (mStoreTiming) { |
127 | 0 | mEndTimestamp = mozilla::TimeStamp::Now(); |
128 | 0 | } |
129 | 0 | nsCOMPtr<nsIDNSListener> listener = do_QueryReferent(mListener); |
130 | 0 | if (listener) { |
131 | 0 | listener->OnLookupComplete(request, rec, status); |
132 | 0 | } |
133 | 0 | return NS_OK; |
134 | 0 | } |
135 | | |
136 | | NS_IMETHODIMP |
137 | | nsDNSPrefetch::OnLookupByTypeComplete(nsICancelable *request, |
138 | | nsIDNSByTypeRecord *res, |
139 | | nsresult status) |
140 | 0 | { |
141 | 0 | MOZ_ASSERT(NS_IsMainThread(), "Expecting DNS callback on main thread."); |
142 | 0 |
|
143 | 0 | if (mStoreTiming) { |
144 | 0 | mEndTimestamp = mozilla::TimeStamp::Now(); |
145 | 0 | } |
146 | 0 | nsCOMPtr<nsIDNSListener> listener = do_QueryReferent(mListener); |
147 | 0 | if (listener) { |
148 | 0 | listener->OnLookupByTypeComplete(request, res, status); |
149 | 0 | } |
150 | 0 | return NS_OK; |
151 | 0 | } |