1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/base/src/nsPACMan.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,234 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef nsPACMan_h__ 1.11 +#define nsPACMan_h__ 1.12 + 1.13 +#include "nsIStreamLoader.h" 1.14 +#include "nsIInterfaceRequestor.h" 1.15 +#include "nsIChannelEventSink.h" 1.16 +#include "ProxyAutoConfig.h" 1.17 +#include "nsThreadUtils.h" 1.18 +#include "nsIURI.h" 1.19 +#include "nsCOMPtr.h" 1.20 +#include "nsString.h" 1.21 +#include "mozilla/Attributes.h" 1.22 +#include "mozilla/LinkedList.h" 1.23 +#include "nsAutoPtr.h" 1.24 +#include "mozilla/TimeStamp.h" 1.25 +#include "prlog.h" 1.26 + 1.27 +class nsPACMan; 1.28 +class nsISystemProxySettings; 1.29 +class nsIThread; 1.30 +class WaitForThreadShutdown; 1.31 + 1.32 +/** 1.33 + * This class defines a callback interface used by AsyncGetProxyForChannel. 1.34 + */ 1.35 +class NS_NO_VTABLE nsPACManCallback : public nsISupports 1.36 +{ 1.37 +public: 1.38 + /** 1.39 + * This method is invoked on the same thread that called AsyncGetProxyForChannel. 1.40 + * 1.41 + * @param status 1.42 + * This parameter indicates whether or not the PAC query succeeded. 1.43 + * @param pacString 1.44 + * This parameter holds the value of the PAC string. It is empty when 1.45 + * status is a failure code. 1.46 + * @param newPACURL 1.47 + * This parameter holds the URL of a new PAC file that should be loaded 1.48 + * before the query is evaluated again. At least one of pacString and 1.49 + * newPACURL should be 0 length. 1.50 + */ 1.51 + virtual void OnQueryComplete(nsresult status, 1.52 + const nsCString &pacString, 1.53 + const nsCString &newPACURL) = 0; 1.54 +}; 1.55 + 1.56 +class PendingPACQuery MOZ_FINAL : public nsRunnable, 1.57 + public mozilla::LinkedListElement<PendingPACQuery> 1.58 +{ 1.59 +public: 1.60 + PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, 1.61 + nsPACManCallback *callback, bool mainThreadResponse); 1.62 + 1.63 + // can be called from either thread 1.64 + void Complete(nsresult status, const nsCString &pacString); 1.65 + void UseAlternatePACFile(const nsCString &pacURL); 1.66 + 1.67 + nsCString mSpec; 1.68 + nsCString mScheme; 1.69 + nsCString mHost; 1.70 + int32_t mPort; 1.71 + 1.72 + NS_IMETHOD Run(void); /* nsRunnable */ 1.73 + 1.74 +private: 1.75 + nsPACMan *mPACMan; // weak reference 1.76 + nsRefPtr<nsPACManCallback> mCallback; 1.77 + bool mOnMainThreadOnly; 1.78 +}; 1.79 + 1.80 +/** 1.81 + * This class provides an abstraction layer above the PAC thread. The methods 1.82 + * defined on this class are intended to be called on the main thread only. 1.83 + */ 1.84 + 1.85 +class nsPACMan MOZ_FINAL : public nsIStreamLoaderObserver 1.86 + , public nsIInterfaceRequestor 1.87 + , public nsIChannelEventSink 1.88 +{ 1.89 +public: 1.90 + NS_DECL_THREADSAFE_ISUPPORTS 1.91 + 1.92 + nsPACMan(); 1.93 + 1.94 + /** 1.95 + * This method may be called to shutdown the PAC manager. Any async queries 1.96 + * that have not yet completed will either finish normally or be canceled by 1.97 + * the time this method returns. 1.98 + */ 1.99 + void Shutdown(); 1.100 + 1.101 + /** 1.102 + * This method queries a PAC result asynchronously. The callback runs on the 1.103 + * calling thread. If the PAC file has not yet been loaded, then this method 1.104 + * will queue up the request, and complete it once the PAC file has been 1.105 + * loaded. 1.106 + * 1.107 + * @param channel 1.108 + * The channel to query. 1.109 + * @param callback 1.110 + * The callback to run once the PAC result is available. 1.111 + * @param mustCallbackOnMainThread 1.112 + * If set to false the callback can be made from the PAC thread 1.113 + */ 1.114 + nsresult AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback, 1.115 + bool mustCallbackOnMainThread); 1.116 + 1.117 + /** 1.118 + * This method may be called to reload the PAC file. While we are loading 1.119 + * the PAC file, any asynchronous PAC queries will be queued up to be 1.120 + * processed once the PAC file finishes loading. 1.121 + * 1.122 + * @param pacSpec 1.123 + * The non normalized uri spec of this URI used for comparison with 1.124 + * system proxy settings to determine if the PAC uri has changed. 1.125 + */ 1.126 + nsresult LoadPACFromURI(const nsCString &pacSpec); 1.127 + 1.128 + /** 1.129 + * Returns true if we are currently loading the PAC file. 1.130 + */ 1.131 + bool IsLoading() { return mLoader != nullptr; } 1.132 + 1.133 + /** 1.134 + * Returns true if the given URI matches the URI of our PAC file or the 1.135 + * URI it has been redirected to. In the case of a chain of redirections 1.136 + * only the current one being followed and the original are considered 1.137 + * becuase this information is used, respectively, to determine if we 1.138 + * should bypass the proxy (to fetch the pac file) or if the pac 1.139 + * configuration has changed (and we should reload the pac file) 1.140 + */ 1.141 + bool IsPACURI(const nsACString &spec) 1.142 + { 1.143 + return mPACURISpec.Equals(spec) || mPACURIRedirectSpec.Equals(spec) || 1.144 + mNormalPACURISpec.Equals(spec); 1.145 + } 1.146 + 1.147 + bool IsPACURI(nsIURI *uri) { 1.148 + if (mPACURISpec.IsEmpty() && mPACURIRedirectSpec.IsEmpty()) 1.149 + return false; 1.150 + 1.151 + nsAutoCString tmp; 1.152 + uri->GetSpec(tmp); 1.153 + return IsPACURI(tmp); 1.154 + } 1.155 + 1.156 + NS_HIDDEN_(nsresult) Init(nsISystemProxySettings *); 1.157 + static nsPACMan *sInstance; 1.158 + 1.159 + // PAC thread operations only 1.160 + void ProcessPendingQ(); 1.161 + void CancelPendingQ(nsresult); 1.162 + 1.163 +private: 1.164 + NS_DECL_NSISTREAMLOADEROBSERVER 1.165 + NS_DECL_NSIINTERFACEREQUESTOR 1.166 + NS_DECL_NSICHANNELEVENTSINK 1.167 + 1.168 + friend class PendingPACQuery; 1.169 + friend class PACLoadComplete; 1.170 + friend class ExecutePACThreadAction; 1.171 + friend class WaitForThreadShutdown; 1.172 + 1.173 + ~nsPACMan(); 1.174 + 1.175 + /** 1.176 + * Cancel any existing load if any. 1.177 + */ 1.178 + void CancelExistingLoad(); 1.179 + 1.180 + /** 1.181 + * Start loading the PAC file. 1.182 + */ 1.183 + void StartLoading(); 1.184 + 1.185 + /** 1.186 + * Reload the PAC file if there is reason to. 1.187 + */ 1.188 + void MaybeReloadPAC(); 1.189 + 1.190 + /** 1.191 + * Called when we fail to load the PAC file. 1.192 + */ 1.193 + void OnLoadFailure(); 1.194 + 1.195 + /** 1.196 + * PostQuery() only runs on the PAC thread and it is used to 1.197 + * place a pendingPACQuery into the queue and potentially 1.198 + * execute the queue if it was otherwise empty 1.199 + */ 1.200 + nsresult PostQuery(PendingPACQuery *query); 1.201 + 1.202 + // PAC thread operations only 1.203 + void PostProcessPendingQ(); 1.204 + void PostCancelPendingQ(nsresult); 1.205 + bool ProcessPending(); 1.206 + void NamePACThread(); 1.207 + 1.208 +private: 1.209 + mozilla::net::ProxyAutoConfig mPAC; 1.210 + nsCOMPtr<nsIThread> mPACThread; 1.211 + nsCOMPtr<nsISystemProxySettings> mSystemProxySettings; 1.212 + 1.213 + mozilla::LinkedList<PendingPACQuery> mPendingQ; /* pac thread only */ 1.214 + 1.215 + // These specs are not nsIURI so that they can be used off the main thread. 1.216 + // The non-normalized versions are directly from the configuration, the 1.217 + // normalized version has been extracted from an nsIURI 1.218 + nsCString mPACURISpec; 1.219 + nsCString mPACURIRedirectSpec; 1.220 + nsCString mNormalPACURISpec; 1.221 + 1.222 + nsCOMPtr<nsIStreamLoader> mLoader; 1.223 + bool mLoadPending; 1.224 + bool mShutdown; 1.225 + mozilla::TimeStamp mScheduledReload; 1.226 + uint32_t mLoadFailureCount; 1.227 + 1.228 + bool mInProgress; 1.229 +}; 1.230 + 1.231 +namespace mozilla { 1.232 +namespace net { 1.233 +PRLogModuleInfo* GetProxyLog(); 1.234 +} 1.235 +} 1.236 + 1.237 +#endif // nsPACMan_h__