diff options
Diffstat (limited to 'netwerk/base/nsPACMan.h')
-rw-r--r-- | netwerk/base/nsPACMan.h | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/netwerk/base/nsPACMan.h b/netwerk/base/nsPACMan.h new file mode 100644 index 000000000..def0843cb --- /dev/null +++ b/netwerk/base/nsPACMan.h @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsPACMan_h__ +#define nsPACMan_h__ + +#include "nsIStreamLoader.h" +#include "nsIInterfaceRequestor.h" +#include "nsIChannelEventSink.h" +#include "ProxyAutoConfig.h" +#include "nsThreadUtils.h" +#include "nsIURI.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "mozilla/Attributes.h" +#include "mozilla/LinkedList.h" +#include "nsAutoPtr.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/Logging.h" +#include "mozilla/Atomics.h" + +class nsISystemProxySettings; +class nsIThread; + +namespace mozilla { +namespace net { + +class nsPACMan; +class WaitForThreadShutdown; + +/** + * This class defines a callback interface used by AsyncGetProxyForURI. + */ +class NS_NO_VTABLE nsPACManCallback : public nsISupports +{ +public: + /** + * This method is invoked on the same thread that called AsyncGetProxyForURI. + * + * @param status + * This parameter indicates whether or not the PAC query succeeded. + * @param pacString + * This parameter holds the value of the PAC string. It is empty when + * status is a failure code. + * @param newPACURL + * This parameter holds the URL of a new PAC file that should be loaded + * before the query is evaluated again. At least one of pacString and + * newPACURL should be 0 length. + */ + virtual void OnQueryComplete(nsresult status, + const nsCString &pacString, + const nsCString &newPACURL) = 0; +}; + +class PendingPACQuery final : public Runnable, + public LinkedListElement<PendingPACQuery> +{ +public: + PendingPACQuery(nsPACMan *pacMan, nsIURI *uri, + nsPACManCallback *callback, + bool mainThreadResponse); + + // can be called from either thread + void Complete(nsresult status, const nsCString &pacString); + void UseAlternatePACFile(const nsCString &pacURL); + + nsCString mSpec; + nsCString mScheme; + nsCString mHost; + int32_t mPort; + + NS_IMETHOD Run(void); /* Runnable */ + +private: + nsPACMan *mPACMan; // weak reference + +private: + RefPtr<nsPACManCallback> mCallback; + bool mOnMainThreadOnly; +}; + +/** + * This class provides an abstraction layer above the PAC thread. The methods + * defined on this class are intended to be called on the main thread only. + */ + +class nsPACMan final : public nsIStreamLoaderObserver + , public nsIInterfaceRequestor + , public nsIChannelEventSink +{ +public: + NS_DECL_THREADSAFE_ISUPPORTS + + nsPACMan(); + + /** + * This method may be called to shutdown the PAC manager. Any async queries + * that have not yet completed will either finish normally or be canceled by + * the time this method returns. + */ + void Shutdown(); + + /** + * This method queries a PAC result asynchronously. The callback runs on the + * calling thread. If the PAC file has not yet been loaded, then this method + * will queue up the request, and complete it once the PAC file has been + * loaded. + * + * @param uri + * The URI to query. + * @param callback + * The callback to run once the PAC result is available. + * @param mustCallbackOnMainThread + * If set to false the callback can be made from the PAC thread + */ + nsresult AsyncGetProxyForURI(nsIURI *uri, + nsPACManCallback *callback, + bool mustCallbackOnMainThread); + + /** + * This method may be called to reload the PAC file. While we are loading + * the PAC file, any asynchronous PAC queries will be queued up to be + * processed once the PAC file finishes loading. + * + * @param pacSpec + * The non normalized uri spec of this URI used for comparison with + * system proxy settings to determine if the PAC uri has changed. + */ + nsresult LoadPACFromURI(const nsCString &pacSpec); + + /** + * Returns true if we are currently loading the PAC file. + */ + bool IsLoading() { return mLoader != nullptr; } + + /** + * Returns true if the given URI matches the URI of our PAC file or the + * URI it has been redirected to. In the case of a chain of redirections + * only the current one being followed and the original are considered + * becuase this information is used, respectively, to determine if we + * should bypass the proxy (to fetch the pac file) or if the pac + * configuration has changed (and we should reload the pac file) + */ + bool IsPACURI(const nsACString &spec) + { + return mPACURISpec.Equals(spec) || mPACURIRedirectSpec.Equals(spec) || + mNormalPACURISpec.Equals(spec); + } + + bool IsPACURI(nsIURI *uri) { + if (mPACURISpec.IsEmpty() && mPACURIRedirectSpec.IsEmpty()) { + return false; + } + + nsAutoCString tmp; + nsresult rv = uri->GetSpec(tmp); + if (NS_FAILED(rv)) { + return false; + } + + return IsPACURI(tmp); + } + + nsresult Init(nsISystemProxySettings *); + static nsPACMan *sInstance; + + // PAC thread operations only + void ProcessPendingQ(); + void CancelPendingQ(nsresult); + +private: + NS_DECL_NSISTREAMLOADEROBSERVER + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSICHANNELEVENTSINK + + friend class PendingPACQuery; + friend class PACLoadComplete; + friend class ExecutePACThreadAction; + friend class WaitForThreadShutdown; + + ~nsPACMan(); + + /** + * Cancel any existing load if any. + */ + void CancelExistingLoad(); + + /** + * Start loading the PAC file. + */ + void StartLoading(); + + /** + * Reload the PAC file if there is reason to. + */ + void MaybeReloadPAC(); + + /** + * Called when we fail to load the PAC file. + */ + void OnLoadFailure(); + + /** + * PostQuery() only runs on the PAC thread and it is used to + * place a pendingPACQuery into the queue and potentially + * execute the queue if it was otherwise empty + */ + nsresult PostQuery(PendingPACQuery *query); + + // PAC thread operations only + void PostProcessPendingQ(); + void PostCancelPendingQ(nsresult); + bool ProcessPending(); + void NamePACThread(); + +private: + ProxyAutoConfig mPAC; + nsCOMPtr<nsIThread> mPACThread; + nsCOMPtr<nsISystemProxySettings> mSystemProxySettings; + + LinkedList<PendingPACQuery> mPendingQ; /* pac thread only */ + + // These specs are not nsIURI so that they can be used off the main thread. + // The non-normalized versions are directly from the configuration, the + // normalized version has been extracted from an nsIURI + nsCString mPACURISpec; + nsCString mPACURIRedirectSpec; + nsCString mNormalPACURISpec; + + nsCOMPtr<nsIStreamLoader> mLoader; + bool mLoadPending; + Atomic<bool, Relaxed> mShutdown; + TimeStamp mScheduledReload; + uint32_t mLoadFailureCount; + + bool mInProgress; + bool mIncludePath; +}; + +extern LazyLogModule gProxyLog; + +} // namespace net +} // namespace mozilla + +#endif // nsPACMan_h__ |