michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsProtocolProxyService_h__ michael@0: #define nsProtocolProxyService_h__ michael@0: michael@0: #include "nsString.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsTArray.h" michael@0: #include "nsIProtocolProxyService2.h" michael@0: #include "nsIProtocolProxyFilter.h" michael@0: #include "nsIProxyInfo.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsDataHashtable.h" michael@0: #include "nsHashKeys.h" michael@0: #include "prio.h" michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: typedef nsDataHashtable nsFailedProxyTable; michael@0: michael@0: class nsProxyInfo; michael@0: struct nsProtocolInfo; michael@0: class nsIPrefBranch; michael@0: class nsISystemProxySettings; michael@0: class nsPACMan; michael@0: michael@0: // CID for the nsProtocolProxyService class michael@0: // 091eedd8-8bae-4fe3-ad62-0c87351e640d michael@0: #define NS_PROTOCOL_PROXY_SERVICE_IMPL_CID \ michael@0: { 0x091eedd8, 0x8bae, 0x4fe3, \ michael@0: { 0xad, 0x62, 0x0c, 0x87, 0x35, 0x1e, 0x64, 0x0d } } michael@0: michael@0: class nsProtocolProxyService MOZ_FINAL : public nsIProtocolProxyService2 michael@0: , public nsIObserver michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIPROTOCOLPROXYSERVICE2 michael@0: NS_DECL_NSIPROTOCOLPROXYSERVICE michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID) michael@0: michael@0: nsProtocolProxyService() NS_HIDDEN; michael@0: michael@0: NS_HIDDEN_(nsresult) Init(); michael@0: nsresult DeprecatedBlockingResolve(nsIChannel *aChannel, michael@0: uint32_t aFlags, michael@0: nsIProxyInfo **retval); michael@0: michael@0: protected: michael@0: friend class nsAsyncResolveRequest; michael@0: michael@0: ~nsProtocolProxyService() NS_HIDDEN; michael@0: michael@0: /** michael@0: * This method is called whenever a preference may have changed or michael@0: * to initialize all preferences. michael@0: * michael@0: * @param prefs michael@0: * This must be a pointer to the root pref branch. michael@0: * @param name michael@0: * This can be the name of a fully-qualified preference, or it can michael@0: * be null, in which case all preferences will be initialized. michael@0: */ michael@0: NS_HIDDEN_(void) PrefsChanged(nsIPrefBranch *prefs, const char *name); michael@0: michael@0: /** michael@0: * This method is called to create a nsProxyInfo instance from the given michael@0: * PAC-style proxy string. It parses up to the end of the string, or to michael@0: * the next ';' character. michael@0: * michael@0: * @param proxy michael@0: * The PAC-style proxy string to parse. This must not be null. michael@0: * @param aResolveFlags michael@0: * The flags passed to Resolve or AsyncResolve that are stored in michael@0: * proxyInfo. michael@0: * @param result michael@0: * Upon return this points to a newly allocated nsProxyInfo or null michael@0: * if the proxy string was invalid. michael@0: * michael@0: * @return A pointer beyond the parsed proxy string (never null). michael@0: */ michael@0: NS_HIDDEN_(const char *) ExtractProxyInfo(const char *proxy, michael@0: uint32_t aResolveFlags, michael@0: nsProxyInfo **result); michael@0: michael@0: /** michael@0: * Load the specified PAC file. michael@0: * michael@0: * @param pacURI michael@0: * The URI spec of the PAC file to load. michael@0: */ michael@0: NS_HIDDEN_(nsresult) ConfigureFromPAC(const nsCString &pacURI, bool forceReload); michael@0: michael@0: /** michael@0: * This method builds a list of nsProxyInfo objects from the given PAC- michael@0: * style string. michael@0: * michael@0: * @param pacString michael@0: * The PAC-style proxy string to parse. This may be empty. michael@0: * @param aResolveFlags michael@0: * The flags passed to Resolve or AsyncResolve that are stored in michael@0: * proxyInfo. michael@0: * @param result michael@0: * The resulting list of proxy info objects. michael@0: */ michael@0: NS_HIDDEN_(void) ProcessPACString(const nsCString &pacString, michael@0: uint32_t aResolveFlags, michael@0: nsIProxyInfo **result); michael@0: michael@0: /** michael@0: * This method generates a string valued identifier for the given michael@0: * nsProxyInfo object. michael@0: * michael@0: * @param pi michael@0: * The nsProxyInfo object from which to generate the key. michael@0: * @param result michael@0: * Upon return, this parameter holds the generated key. michael@0: */ michael@0: NS_HIDDEN_(void) GetProxyKey(nsProxyInfo *pi, nsCString &result); michael@0: michael@0: /** michael@0: * @return Seconds since start of session. michael@0: */ michael@0: NS_HIDDEN_(uint32_t) SecondsSinceSessionStart(); michael@0: michael@0: /** michael@0: * This method removes the specified proxy from the disabled list. michael@0: * michael@0: * @param pi michael@0: * The nsProxyInfo object identifying the proxy to enable. michael@0: */ michael@0: NS_HIDDEN_(void) EnableProxy(nsProxyInfo *pi); michael@0: michael@0: /** michael@0: * This method adds the specified proxy to the disabled list. michael@0: * michael@0: * @param pi michael@0: * The nsProxyInfo object identifying the proxy to disable. michael@0: */ michael@0: NS_HIDDEN_(void) DisableProxy(nsProxyInfo *pi); michael@0: michael@0: /** michael@0: * This method tests to see if the given proxy is disabled. michael@0: * michael@0: * @param pi michael@0: * The nsProxyInfo object identifying the proxy to test. michael@0: * michael@0: * @return True if the specified proxy is disabled. michael@0: */ michael@0: NS_HIDDEN_(bool) IsProxyDisabled(nsProxyInfo *pi); michael@0: michael@0: /** michael@0: * This method queries the protocol handler for the given scheme to check michael@0: * for the protocol flags and default port. michael@0: * michael@0: * @param uri michael@0: * The URI to query. michael@0: * @param info michael@0: * Holds information about the protocol upon return. Pass address michael@0: * of structure when you call this method. This parameter must not michael@0: * be null. michael@0: */ michael@0: NS_HIDDEN_(nsresult) GetProtocolInfo(nsIURI *uri, nsProtocolInfo *result); michael@0: michael@0: /** michael@0: * This method is an internal version nsIProtocolProxyService::newProxyInfo michael@0: * that expects a string literal for the type. michael@0: * michael@0: * @param type michael@0: * The proxy type. michael@0: * @param host michael@0: * The proxy host name (UTF-8 ok). michael@0: * @param port michael@0: * The proxy port number. michael@0: * @param username michael@0: * The username for the proxy (ASCII). May be "", but not null. michael@0: * @param password michael@0: * The password for the proxy (ASCII). May be "", but not null. michael@0: * @param flags michael@0: * The proxy flags (nsIProxyInfo::flags). michael@0: * @param timeout michael@0: * The failover timeout for this proxy. michael@0: * @param next michael@0: * The next proxy to try if this one fails. michael@0: * @param aResolveFlags michael@0: * The flags passed to resolve (from nsIProtocolProxyService). michael@0: * @param result michael@0: * The resulting nsIProxyInfo object. michael@0: */ michael@0: NS_HIDDEN_(nsresult) NewProxyInfo_Internal(const char *type, michael@0: const nsACString &host, michael@0: int32_t port, michael@0: const nsACString &username, michael@0: const nsACString &password, michael@0: uint32_t flags, michael@0: uint32_t timeout, michael@0: nsIProxyInfo *next, michael@0: uint32_t aResolveFlags, michael@0: nsIProxyInfo **result); michael@0: michael@0: /** michael@0: * This method is an internal version of Resolve that does not query PAC. michael@0: * It performs all of the built-in processing, and reports back to the michael@0: * caller with either the proxy info result or a flag to instruct the michael@0: * caller to use PAC instead. michael@0: * michael@0: * @param channel michael@0: * The channel to test. michael@0: * @param info michael@0: * Information about the URI's protocol. michael@0: * @param flags michael@0: * The flags passed to either the resolve or the asyncResolve method. michael@0: * @param usePAC michael@0: * If this flag is set upon return, then PAC should be queried to michael@0: * resolve the proxy info. michael@0: * @param result michael@0: * The resulting proxy info or null. michael@0: */ michael@0: NS_HIDDEN_(nsresult) Resolve_Internal(nsIChannel *channel, michael@0: const nsProtocolInfo &info, michael@0: uint32_t flags, michael@0: bool *usePAC, michael@0: nsIProxyInfo **result); michael@0: michael@0: /** michael@0: * This method applies the registered filters to the given proxy info michael@0: * list, and returns a possibly modified list. michael@0: * michael@0: * @param channel michael@0: * The channel corresponding to this proxy info list. michael@0: * @param info michael@0: * Information about the URI's protocol. michael@0: * @param proxyInfo michael@0: * The proxy info list to be modified. This is an inout param. michael@0: */ michael@0: NS_HIDDEN_(void) ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info, michael@0: nsIProxyInfo **proxyInfo); michael@0: michael@0: /** michael@0: * This method is a simple wrapper around ApplyFilters that takes the michael@0: * proxy info list inout param as a nsCOMPtr. michael@0: */ michael@0: inline void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info, michael@0: nsCOMPtr &proxyInfo) michael@0: { michael@0: nsIProxyInfo *pi = nullptr; michael@0: proxyInfo.swap(pi); michael@0: ApplyFilters(channel, info, &pi); michael@0: proxyInfo.swap(pi); michael@0: } michael@0: michael@0: /** michael@0: * This method prunes out disabled and disallowed proxies from a given michael@0: * proxy info list. michael@0: * michael@0: * @param info michael@0: * Information about the URI's protocol. michael@0: * @param proxyInfo michael@0: * The proxy info list to be modified. This is an inout param. michael@0: */ michael@0: NS_HIDDEN_(void) PruneProxyInfo(const nsProtocolInfo &info, michael@0: nsIProxyInfo **proxyInfo); michael@0: michael@0: /** michael@0: * This method populates mHostFiltersArray from the given string. michael@0: * michael@0: * @param hostFilters michael@0: * A "no-proxy-for" exclusion list. michael@0: */ michael@0: NS_HIDDEN_(void) LoadHostFilters(const char *hostFilters); michael@0: michael@0: /** michael@0: * This method checks the given URI against mHostFiltersArray. michael@0: * michael@0: * @param uri michael@0: * The URI to test. michael@0: * @param defaultPort michael@0: * The default port for the given URI. michael@0: * michael@0: * @return True if the URI can use the specified proxy. michael@0: */ michael@0: NS_HIDDEN_(bool) CanUseProxy(nsIURI *uri, int32_t defaultPort); michael@0: michael@0: /** michael@0: * Disable Prefetch in the DNS service if a proxy is in use. michael@0: * michael@0: * @param aProxy michael@0: * The proxy information michael@0: */ michael@0: NS_HIDDEN_(void) MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy); michael@0: michael@0: private: michael@0: nsresult SetupPACThread(); michael@0: nsresult ResetPACThread(); michael@0: michael@0: public: michael@0: // The Sun Forte compiler and others implement older versions of the michael@0: // C++ standard's rules on access and nested classes. These structs michael@0: // need to be public in order to deal with those compilers. michael@0: michael@0: struct HostInfoIP { michael@0: uint16_t family; michael@0: uint16_t mask_len; michael@0: PRIPv6Addr addr; // possibly IPv4-mapped address michael@0: }; michael@0: michael@0: struct HostInfoName { michael@0: char *host; michael@0: uint32_t host_len; michael@0: }; michael@0: michael@0: protected: michael@0: michael@0: // simplified array of filters defined by this struct michael@0: struct HostInfo { michael@0: bool is_ipaddr; michael@0: int32_t port; michael@0: union { michael@0: HostInfoIP ip; michael@0: HostInfoName name; michael@0: }; michael@0: michael@0: HostInfo() michael@0: : is_ipaddr(false) michael@0: { /* other members intentionally uninitialized */ } michael@0: ~HostInfo() { michael@0: if (!is_ipaddr && name.host) michael@0: nsMemory::Free(name.host); michael@0: } michael@0: }; michael@0: michael@0: // An instance of this struct is allocated for each registered michael@0: // nsIProtocolProxyFilter and each nsIProtocolProxyChannelFilter. michael@0: struct FilterLink { michael@0: struct FilterLink *next; michael@0: uint32_t position; michael@0: nsCOMPtr filter; michael@0: nsCOMPtr channelFilter; michael@0: FilterLink(uint32_t p, nsIProtocolProxyFilter *f) michael@0: : next(nullptr), position(p), filter(f), channelFilter(nullptr) {} michael@0: FilterLink(uint32_t p, nsIProtocolProxyChannelFilter *cf) michael@0: : next(nullptr), position(p), filter(nullptr), channelFilter(cf) {} michael@0: // Chain deletion to simplify cleaning up the filter links michael@0: ~FilterLink() { if (next) delete next; } michael@0: }; michael@0: michael@0: private: michael@0: // Private methods to insert and remove FilterLinks from the FilterLink chain. michael@0: nsresult InsertFilterLink(FilterLink *link, uint32_t position); michael@0: nsresult RemoveFilterLink(nsISupports *givenObject); michael@0: michael@0: protected: michael@0: // Indicates if local hosts (plain hostnames, no dots) should use the proxy michael@0: bool mFilterLocalHosts; michael@0: michael@0: // Holds an array of HostInfo objects michael@0: nsTArray > mHostFiltersArray; michael@0: michael@0: // Points to the start of a sorted by position, singly linked list michael@0: // of FilterLink objects. michael@0: FilterLink *mFilters; michael@0: michael@0: uint32_t mProxyConfig; michael@0: michael@0: nsCString mHTTPProxyHost; michael@0: int32_t mHTTPProxyPort; michael@0: michael@0: nsCString mFTPProxyHost; michael@0: int32_t mFTPProxyPort; michael@0: michael@0: nsCString mHTTPSProxyHost; michael@0: int32_t mHTTPSProxyPort; michael@0: michael@0: nsCString mSOCKSProxyHost; michael@0: int32_t mSOCKSProxyPort; michael@0: int32_t mSOCKSProxyVersion; michael@0: bool mSOCKSProxyRemoteDNS; michael@0: nsCString mSOCKSProxyUsername; michael@0: nsCString mSOCKSProxyPassword; michael@0: michael@0: nsRefPtr mPACMan; // non-null if we are using PAC michael@0: nsCOMPtr mSystemProxySettings; michael@0: michael@0: PRTime mSessionStart; michael@0: nsFailedProxyTable mFailedProxies; michael@0: int32_t mFailedProxyTimeout; michael@0: michael@0: private: michael@0: nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags, michael@0: nsIProtocolProxyCallback *callback, michael@0: nsICancelable **result, michael@0: bool isSyncOK); michael@0: michael@0: }; michael@0: michael@0: NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService, NS_PROTOCOL_PROXY_SERVICE_IMPL_CID) michael@0: michael@0: #endif // !nsProtocolProxyService_h__