netwerk/dns/ChildDNSService.cpp

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

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

mercurial