Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/net/ChildDNSService.h"
6 #include "nsIDNSListener.h"
7 #include "nsNetUtil.h"
8 #include "nsIThread.h"
9 #include "nsThreadUtils.h"
10 #include "nsIXPConnect.h"
11 #include "nsIPrefService.h"
12 #include "nsIProtocolProxyService.h"
13 #include "mozilla/net/NeckoChild.h"
14 #include "mozilla/net/DNSRequestChild.h"
15 #include "mozilla/net/DNSListenerProxy.h"
17 namespace mozilla {
18 namespace net {
20 //-----------------------------------------------------------------------------
21 // ChildDNSService
22 //-----------------------------------------------------------------------------
24 static ChildDNSService *gChildDNSService;
25 static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch";
27 ChildDNSService* ChildDNSService::GetSingleton()
28 {
29 MOZ_ASSERT(IsNeckoChild());
31 if (!gChildDNSService) {
32 gChildDNSService = new ChildDNSService();
33 }
35 NS_ADDREF(gChildDNSService);
36 return gChildDNSService;
37 }
39 NS_IMPL_ISUPPORTS(ChildDNSService,
40 nsIDNSService,
41 nsPIDNSService,
42 nsIObserver)
44 ChildDNSService::ChildDNSService()
45 : mFirstTime(true)
46 , mOffline(false)
47 {
48 MOZ_ASSERT(IsNeckoChild());
49 }
51 ChildDNSService::~ChildDNSService()
52 {
54 }
56 //-----------------------------------------------------------------------------
57 // ChildDNSService::nsIDNSService
58 //-----------------------------------------------------------------------------
60 NS_IMETHODIMP
61 ChildDNSService::AsyncResolve(const nsACString &hostname,
62 uint32_t flags,
63 nsIDNSListener *listener,
64 nsIEventTarget *target_,
65 nsICancelable **result)
66 {
67 NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
69 if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) {
70 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
71 }
73 // Support apps being 'offline' even if parent is not: avoids DNS traffic by
74 // apps that have been told they are offline.
75 if (mOffline) {
76 flags |= RESOLVE_OFFLINE;
77 }
79 // make sure JS callers get notification on the main thread
80 nsCOMPtr<nsIEventTarget> target = target_;
81 nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
82 if (wrappedListener && !target) {
83 nsCOMPtr<nsIThread> mainThread;
84 NS_GetMainThread(getter_AddRefs(mainThread));
85 target = do_QueryInterface(mainThread);
86 }
87 if (target) {
88 // Guarantee listener freed on main thread. Not sure we need this in child
89 // (or in parent in nsDNSService.cpp) but doesn't hurt.
90 listener = new DNSListenerProxy(listener, target);
91 }
93 nsRefPtr<DNSRequestChild> childReq =
94 new DNSRequestChild(nsCString(hostname), flags, listener, target);
96 childReq->StartRequest();
98 childReq.forget(result);
99 return NS_OK;
100 }
102 NS_IMETHODIMP
103 ChildDNSService::CancelAsyncResolve(const nsACString &aHostname,
104 uint32_t aFlags,
105 nsIDNSListener *aListener,
106 nsresult aReason)
107 {
108 if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE)) {
109 return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
110 }
112 // TODO: keep a hashtable of pending requests, so we can obey cancel semantics
113 // (call OnLookupComplete with aReason). Also possible we could send IPDL to
114 // parent to cancel.
115 return NS_ERROR_NOT_AVAILABLE;
116 }
118 NS_IMETHODIMP
119 ChildDNSService::Resolve(const nsACString &hostname,
120 uint32_t flags,
121 nsIDNSRecord **result)
122 {
123 // not planning to ever support this, since sync IPDL is evil.
124 return NS_ERROR_NOT_AVAILABLE;
125 }
127 NS_IMETHODIMP
128 ChildDNSService::GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *args)
129 {
130 // Only used by networking dashboard, so may not ever need this in child.
131 // (and would provide a way to spy on what hosts other apps are connecting to,
132 // unless we start keeping per-app DNS caches).
133 return NS_ERROR_NOT_AVAILABLE;
134 }
136 NS_IMETHODIMP
137 ChildDNSService::GetMyHostName(nsACString &result)
138 {
139 // TODO: get value from parent during PNecko construction?
140 return NS_ERROR_NOT_AVAILABLE;
141 }
143 //-----------------------------------------------------------------------------
144 // ChildDNSService::nsPIDNSService
145 //-----------------------------------------------------------------------------
147 nsresult
148 ChildDNSService::Init()
149 {
150 // Disable prefetching either by explicit preference or if a manual proxy
151 // is configured
152 bool disablePrefetch = false;
153 int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
155 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
156 prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch);
157 if (prefs) {
158 prefs->GetIntPref("network.proxy.type", &proxyType);
159 prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch);
160 }
162 if (mFirstTime) {
163 mFirstTime = false;
164 if (prefs) {
165 prefs->AddObserver(kPrefNameDisablePrefetch, this, false);
167 // Monitor these to see if there is a change in proxy configuration
168 // If a manual proxy is in use, disable prefetch implicitly
169 prefs->AddObserver("network.proxy.type", this, false);
170 }
171 }
173 mDisablePrefetch = disablePrefetch ||
174 (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
176 return NS_OK;
177 }
179 nsresult
180 ChildDNSService::Shutdown()
181 {
182 return NS_OK;
183 }
185 NS_IMETHODIMP
186 ChildDNSService::GetPrefetchEnabled(bool *outVal)
187 {
188 *outVal = !mDisablePrefetch;
189 return NS_OK;
190 }
192 NS_IMETHODIMP
193 ChildDNSService::SetPrefetchEnabled(bool inVal)
194 {
195 mDisablePrefetch = !inVal;
196 return NS_OK;
197 }
199 NS_IMETHODIMP
200 ChildDNSService::GetOffline(bool* aResult)
201 {
202 *aResult = mOffline;
203 return NS_OK;
204 }
206 NS_IMETHODIMP
207 ChildDNSService::SetOffline(bool value)
208 {
209 mOffline = value;
210 return NS_OK;
211 }
213 //-----------------------------------------------------------------------------
214 // ChildDNSService::nsIObserver
215 //-----------------------------------------------------------------------------
217 NS_IMETHODIMP
218 ChildDNSService::Observe(nsISupports *subject, const char *topic,
219 const char16_t *data)
220 {
221 // we are only getting called if a preference has changed.
222 NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
223 "unexpected observe call");
225 // Reread prefs
226 Init();
227 return NS_OK;
228 }
230 } // namespace net
231 } // namespace mozilla