1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/dns/ChildDNSService.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,231 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "mozilla/net/ChildDNSService.h" 1.9 +#include "nsIDNSListener.h" 1.10 +#include "nsNetUtil.h" 1.11 +#include "nsIThread.h" 1.12 +#include "nsThreadUtils.h" 1.13 +#include "nsIXPConnect.h" 1.14 +#include "nsIPrefService.h" 1.15 +#include "nsIProtocolProxyService.h" 1.16 +#include "mozilla/net/NeckoChild.h" 1.17 +#include "mozilla/net/DNSRequestChild.h" 1.18 +#include "mozilla/net/DNSListenerProxy.h" 1.19 + 1.20 +namespace mozilla { 1.21 +namespace net { 1.22 + 1.23 +//----------------------------------------------------------------------------- 1.24 +// ChildDNSService 1.25 +//----------------------------------------------------------------------------- 1.26 + 1.27 +static ChildDNSService *gChildDNSService; 1.28 +static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch"; 1.29 + 1.30 +ChildDNSService* ChildDNSService::GetSingleton() 1.31 +{ 1.32 + MOZ_ASSERT(IsNeckoChild()); 1.33 + 1.34 + if (!gChildDNSService) { 1.35 + gChildDNSService = new ChildDNSService(); 1.36 + } 1.37 + 1.38 + NS_ADDREF(gChildDNSService); 1.39 + return gChildDNSService; 1.40 +} 1.41 + 1.42 +NS_IMPL_ISUPPORTS(ChildDNSService, 1.43 + nsIDNSService, 1.44 + nsPIDNSService, 1.45 + nsIObserver) 1.46 + 1.47 +ChildDNSService::ChildDNSService() 1.48 + : mFirstTime(true) 1.49 + , mOffline(false) 1.50 +{ 1.51 + MOZ_ASSERT(IsNeckoChild()); 1.52 +} 1.53 + 1.54 +ChildDNSService::~ChildDNSService() 1.55 +{ 1.56 + 1.57 +} 1.58 + 1.59 +//----------------------------------------------------------------------------- 1.60 +// ChildDNSService::nsIDNSService 1.61 +//----------------------------------------------------------------------------- 1.62 + 1.63 +NS_IMETHODIMP 1.64 +ChildDNSService::AsyncResolve(const nsACString &hostname, 1.65 + uint32_t flags, 1.66 + nsIDNSListener *listener, 1.67 + nsIEventTarget *target_, 1.68 + nsICancelable **result) 1.69 +{ 1.70 + NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE); 1.71 + 1.72 + if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) { 1.73 + return NS_ERROR_DNS_LOOKUP_QUEUE_FULL; 1.74 + } 1.75 + 1.76 + // Support apps being 'offline' even if parent is not: avoids DNS traffic by 1.77 + // apps that have been told they are offline. 1.78 + if (mOffline) { 1.79 + flags |= RESOLVE_OFFLINE; 1.80 + } 1.81 + 1.82 + // make sure JS callers get notification on the main thread 1.83 + nsCOMPtr<nsIEventTarget> target = target_; 1.84 + nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener); 1.85 + if (wrappedListener && !target) { 1.86 + nsCOMPtr<nsIThread> mainThread; 1.87 + NS_GetMainThread(getter_AddRefs(mainThread)); 1.88 + target = do_QueryInterface(mainThread); 1.89 + } 1.90 + if (target) { 1.91 + // Guarantee listener freed on main thread. Not sure we need this in child 1.92 + // (or in parent in nsDNSService.cpp) but doesn't hurt. 1.93 + listener = new DNSListenerProxy(listener, target); 1.94 + } 1.95 + 1.96 + nsRefPtr<DNSRequestChild> childReq = 1.97 + new DNSRequestChild(nsCString(hostname), flags, listener, target); 1.98 + 1.99 + childReq->StartRequest(); 1.100 + 1.101 + childReq.forget(result); 1.102 + return NS_OK; 1.103 +} 1.104 + 1.105 +NS_IMETHODIMP 1.106 +ChildDNSService::CancelAsyncResolve(const nsACString &aHostname, 1.107 + uint32_t aFlags, 1.108 + nsIDNSListener *aListener, 1.109 + nsresult aReason) 1.110 +{ 1.111 + if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE)) { 1.112 + return NS_ERROR_DNS_LOOKUP_QUEUE_FULL; 1.113 + } 1.114 + 1.115 + // TODO: keep a hashtable of pending requests, so we can obey cancel semantics 1.116 + // (call OnLookupComplete with aReason). Also possible we could send IPDL to 1.117 + // parent to cancel. 1.118 + return NS_ERROR_NOT_AVAILABLE; 1.119 +} 1.120 + 1.121 +NS_IMETHODIMP 1.122 +ChildDNSService::Resolve(const nsACString &hostname, 1.123 + uint32_t flags, 1.124 + nsIDNSRecord **result) 1.125 +{ 1.126 + // not planning to ever support this, since sync IPDL is evil. 1.127 + return NS_ERROR_NOT_AVAILABLE; 1.128 +} 1.129 + 1.130 +NS_IMETHODIMP 1.131 +ChildDNSService::GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *args) 1.132 +{ 1.133 + // Only used by networking dashboard, so may not ever need this in child. 1.134 + // (and would provide a way to spy on what hosts other apps are connecting to, 1.135 + // unless we start keeping per-app DNS caches). 1.136 + return NS_ERROR_NOT_AVAILABLE; 1.137 +} 1.138 + 1.139 +NS_IMETHODIMP 1.140 +ChildDNSService::GetMyHostName(nsACString &result) 1.141 +{ 1.142 + // TODO: get value from parent during PNecko construction? 1.143 + return NS_ERROR_NOT_AVAILABLE; 1.144 +} 1.145 + 1.146 +//----------------------------------------------------------------------------- 1.147 +// ChildDNSService::nsPIDNSService 1.148 +//----------------------------------------------------------------------------- 1.149 + 1.150 +nsresult 1.151 +ChildDNSService::Init() 1.152 +{ 1.153 + // Disable prefetching either by explicit preference or if a manual proxy 1.154 + // is configured 1.155 + bool disablePrefetch = false; 1.156 + int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT; 1.157 + 1.158 + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); 1.159 + prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch); 1.160 + if (prefs) { 1.161 + prefs->GetIntPref("network.proxy.type", &proxyType); 1.162 + prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch); 1.163 + } 1.164 + 1.165 + if (mFirstTime) { 1.166 + mFirstTime = false; 1.167 + if (prefs) { 1.168 + prefs->AddObserver(kPrefNameDisablePrefetch, this, false); 1.169 + 1.170 + // Monitor these to see if there is a change in proxy configuration 1.171 + // If a manual proxy is in use, disable prefetch implicitly 1.172 + prefs->AddObserver("network.proxy.type", this, false); 1.173 + } 1.174 + } 1.175 + 1.176 + mDisablePrefetch = disablePrefetch || 1.177 + (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL); 1.178 + 1.179 + return NS_OK; 1.180 +} 1.181 + 1.182 +nsresult 1.183 +ChildDNSService::Shutdown() 1.184 +{ 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +NS_IMETHODIMP 1.189 +ChildDNSService::GetPrefetchEnabled(bool *outVal) 1.190 +{ 1.191 + *outVal = !mDisablePrefetch; 1.192 + return NS_OK; 1.193 +} 1.194 + 1.195 +NS_IMETHODIMP 1.196 +ChildDNSService::SetPrefetchEnabled(bool inVal) 1.197 +{ 1.198 + mDisablePrefetch = !inVal; 1.199 + return NS_OK; 1.200 +} 1.201 + 1.202 +NS_IMETHODIMP 1.203 +ChildDNSService::GetOffline(bool* aResult) 1.204 +{ 1.205 + *aResult = mOffline; 1.206 + return NS_OK; 1.207 +} 1.208 + 1.209 +NS_IMETHODIMP 1.210 +ChildDNSService::SetOffline(bool value) 1.211 +{ 1.212 + mOffline = value; 1.213 + return NS_OK; 1.214 +} 1.215 + 1.216 +//----------------------------------------------------------------------------- 1.217 +// ChildDNSService::nsIObserver 1.218 +//----------------------------------------------------------------------------- 1.219 + 1.220 +NS_IMETHODIMP 1.221 +ChildDNSService::Observe(nsISupports *subject, const char *topic, 1.222 + const char16_t *data) 1.223 +{ 1.224 + // we are only getting called if a preference has changed. 1.225 + NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0, 1.226 + "unexpected observe call"); 1.227 + 1.228 + // Reread prefs 1.229 + Init(); 1.230 + return NS_OK; 1.231 +} 1.232 + 1.233 +} // namespace net 1.234 +} // namespace mozilla