netwerk/base/nsProtocolProxyService.h
author Andrew Osmond <aosmond@mozilla.com>
Fri, 17 Nov 2017 06:45:28 -0500
changeset 392351 b9a29d94ccac646c9336fa75e084bbc8581501ad
parent 367749 6a629adbb62a299d7208373d1c6f375149d2afdb
child 403094 77c14093bc69d945cc6646c3e5a4d09ecd760eee
permissions -rw-r--r--
Bug 1368776 - Part 15. Cache flags passed to ImageResource::GetImageContainerImpl for consistency. r=tnikkel When FLAG_HIGH_QUALITY_SCALING is used, we need to make sure we continue using that flag when we update the container. We should also use it for comparing whether or not an existing image container is equivalent.

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 nsProtocolProxyService_h__
#define nsProtocolProxyService_h__

#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsIProtocolProxyService2.h"
#include "nsIProtocolProxyFilter.h"
#include "nsIProxyInfo.h"
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "prio.h"
#include "mozilla/Attributes.h"

class nsIPrefBranch;
class nsISystemProxySettings;

namespace mozilla {
namespace net {

typedef nsDataHashtable<nsCStringHashKey, uint32_t> nsFailedProxyTable;

class nsPACMan;
class nsProxyInfo;
struct nsProtocolInfo;

// CID for the nsProtocolProxyService class
// 091eedd8-8bae-4fe3-ad62-0c87351e640d
#define NS_PROTOCOL_PROXY_SERVICE_IMPL_CID        \
{ 0x091eedd8, 0x8bae, 0x4fe3, \
        { 0xad, 0x62, 0x0c, 0x87, 0x35, 0x1e, 0x64, 0x0d } }

class nsProtocolProxyService final : public nsIProtocolProxyService2
                                   , public nsIObserver
{
public:
    NS_DECL_ISUPPORTS
    NS_DECL_NSIPROTOCOLPROXYSERVICE2
    NS_DECL_NSIPROTOCOLPROXYSERVICE
    NS_DECL_NSIOBSERVER

    NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)

    nsProtocolProxyService();

    nsresult Init();

protected:
    friend class nsAsyncResolveRequest;
    friend class TestProtocolProxyService_LoadHostFilters_Test; // for gtest

    ~nsProtocolProxyService();

    /**
     * This method is called whenever a preference may have changed or
     * to initialize all preferences.
     *
     * @param prefs
     *        This must be a pointer to the root pref branch.
     * @param name
     *        This can be the name of a fully-qualified preference, or it can
     *        be null, in which case all preferences will be initialized.
     */
    void PrefsChanged(nsIPrefBranch *prefs, const char *name);

    /**
     * This method is called to create a nsProxyInfo instance from the given
     * PAC-style proxy string.  It parses up to the end of the string, or to
     * the next ';' character.
     *
     * @param proxy
     *        The PAC-style proxy string to parse.  This must not be null.
     * @param aResolveFlags
     *        The flags passed to Resolve or AsyncResolve that are stored in
     *        proxyInfo.
     * @param result
     *        Upon return this points to a newly allocated nsProxyInfo or null
     *        if the proxy string was invalid.
     *
     * @return A pointer beyond the parsed proxy string (never null).
     */
    const char * ExtractProxyInfo(const char *proxy,
                                              uint32_t aResolveFlags,
                                              nsProxyInfo **result);

    /**
     * Load the specified PAC file.
     *
     * @param pacURI
     *        The URI spec of the PAC file to load.
     */
    nsresult ConfigureFromPAC(const nsCString &pacURI, bool forceReload);

    /**
     * This method builds a list of nsProxyInfo objects from the given PAC-
     * style string.
     *
     * @param pacString
     *        The PAC-style proxy string to parse.  This may be empty.
     * @param aResolveFlags
     *        The flags passed to Resolve or AsyncResolve that are stored in
     *        proxyInfo.
     * @param result
     *        The resulting list of proxy info objects.
     */
    void ProcessPACString(const nsCString &pacString,
                                      uint32_t aResolveFlags,
                                      nsIProxyInfo **result);

    /**
     * This method generates a string valued identifier for the given
     * nsProxyInfo object.
     *
     * @param pi
     *        The nsProxyInfo object from which to generate the key.
     * @param result
     *        Upon return, this parameter holds the generated key.
     */
    void GetProxyKey(nsProxyInfo *pi, nsCString &result);

    /**
     * @return Seconds since start of session.
     */
    uint32_t SecondsSinceSessionStart();

    /**
     * This method removes the specified proxy from the disabled list.
     *
     * @param pi
     *        The nsProxyInfo object identifying the proxy to enable.
     */
    void EnableProxy(nsProxyInfo *pi);

    /**
     * This method adds the specified proxy to the disabled list.
     *
     * @param pi
     *        The nsProxyInfo object identifying the proxy to disable.
     */
    void DisableProxy(nsProxyInfo *pi);

    /**
     * This method tests to see if the given proxy is disabled.
     *
     * @param pi
     *        The nsProxyInfo object identifying the proxy to test.
     *
     * @return True if the specified proxy is disabled.
     */
    bool IsProxyDisabled(nsProxyInfo *pi);

    /**
     * This method queries the protocol handler for the given scheme to check
     * for the protocol flags and default port.
     *
     * @param uri
     *        The URI to query.
     * @param info
     *        Holds information about the protocol upon return.  Pass address
     *        of structure when you call this method.  This parameter must not
     *        be null.
     */
    nsresult GetProtocolInfo(nsIURI *uri, nsProtocolInfo *result);

    /**
     * This method is an internal version nsIProtocolProxyService::newProxyInfo
     * that expects a string literal for the type.
     *
     * @param type
     *        The proxy type.
     * @param host
     *        The proxy host name (UTF-8 ok).
     * @param port
     *        The proxy port number.
     * @param username
     *        The username for the proxy (ASCII). May be "", but not null.
     * @param password
     *        The password for the proxy (ASCII). May be "", but not null.
     * @param flags
     *        The proxy flags (nsIProxyInfo::flags).
     * @param timeout
     *        The failover timeout for this proxy.
     * @param next
     *        The next proxy to try if this one fails.
     * @param aResolveFlags
     *        The flags passed to resolve (from nsIProtocolProxyService).
     * @param result
     *        The resulting nsIProxyInfo object.
     */
    nsresult NewProxyInfo_Internal(const char *type,
                                               const nsACString &host,
                                               int32_t port,
                                               const nsACString &username,
                                               const nsACString &password,
                                               uint32_t flags,
                                               uint32_t timeout,
                                               nsIProxyInfo *next,
                                               uint32_t aResolveFlags,
                                               nsIProxyInfo **result);

    /**
     * This method is an internal version of Resolve that does not query PAC.
     * It performs all of the built-in processing, and reports back to the
     * caller with either the proxy info result or a flag to instruct the
     * caller to use PAC instead.
     *
     * @param channel
     *        The channel to test.
     * @param info
     *        Information about the URI's protocol.
     * @param flags
     *        The flags passed to either the resolve or the asyncResolve method.
     * @param usePAC
     *        If this flag is set upon return, then PAC should be queried to
     *        resolve the proxy info.
     * @param result
     *        The resulting proxy info or null.
     */
    nsresult Resolve_Internal(nsIChannel *channel,
                              const nsProtocolInfo &info,
                              uint32_t flags,
                              bool *usePAC,
                              nsIProxyInfo **result);

    /**
     * This method applies the registered filters to the given proxy info
     * list, and returns a possibly modified list.
     *
     * @param channel
     *        The channel corresponding to this proxy info list.
     * @param info
     *        Information about the URI's protocol.
     * @param proxyInfo
     *        The proxy info list to be modified.  This is an inout param.
     */
    void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
                                  nsIProxyInfo **proxyInfo);

    /**
     * This method is a simple wrapper around ApplyFilters that takes the
     * proxy info list inout param as a nsCOMPtr.
     */
    inline void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
                             nsCOMPtr<nsIProxyInfo> &proxyInfo)
    {
      nsIProxyInfo *pi = nullptr;
      proxyInfo.swap(pi);
      ApplyFilters(channel, info, &pi);
      proxyInfo.swap(pi);
    }

    /**
     * This method prunes out disabled and disallowed proxies from a given
     * proxy info list.
     *
     * @param info
     *        Information about the URI's protocol.
     * @param proxyInfo
     *        The proxy info list to be modified.  This is an inout param.
     */
    void PruneProxyInfo(const nsProtocolInfo &info,
                                    nsIProxyInfo **proxyInfo);

    /**
     * This method populates mHostFiltersArray from the given string.
     *
     * @param hostFilters
     *        A "no-proxy-for" exclusion list.
     */
    void LoadHostFilters(const nsACString& hostFilters);

    /**
     * This method checks the given URI against mHostFiltersArray.
     *
     * @param uri
     *        The URI to test.
     * @param defaultPort
     *        The default port for the given URI.
     *
     * @return True if the URI can use the specified proxy.
     */
    bool CanUseProxy(nsIURI *uri, int32_t defaultPort);

    /**
     * Disable Prefetch in the DNS service if a proxy is in use.
     *
     * @param aProxy
     *        The proxy information
     */
    void MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy);

private:
    nsresult SetupPACThread(nsIEventTarget *mainThreadEventTarget = nullptr);
    nsresult ResetPACThread();
    nsresult ReloadNetworkPAC();

    nsresult AsyncConfigureFromPAC(bool aForceReload, bool aResetPACThread);
    nsresult OnAsyncGetPACURI(bool aForceReload,
                              bool aResetPACThread,
                              nsresult aResult,
                              const nsACString& aUri);

public:
    // The Sun Forte compiler and others implement older versions of the
    // C++ standard's rules on access and nested classes.  These structs
    // need to be public in order to deal with those compilers.

    struct HostInfoIP {
        uint16_t   family;
        uint16_t   mask_len;
        PRIPv6Addr addr; // possibly IPv4-mapped address
    };

    struct HostInfoName {
        char    *host;
        uint32_t host_len;
    };

protected:

    // simplified array of filters defined by this struct
    struct HostInfo {
        bool    is_ipaddr;
        int32_t port;
        union {
            HostInfoIP   ip;
            HostInfoName name;
        };

        HostInfo()
            : is_ipaddr(false)
            , port(0)
            { /* other members intentionally uninitialized */ }
       ~HostInfo() {
            if (!is_ipaddr && name.host)
                free(name.host);
        }
    };

    // An instance of this struct is allocated for each registered
    // nsIProtocolProxyFilter and each nsIProtocolProxyChannelFilter.
    struct FilterLink {
      struct FilterLink                *next;
      uint32_t                          position;
      nsCOMPtr<nsIProtocolProxyFilter> filter;
      nsCOMPtr<nsIProtocolProxyChannelFilter> channelFilter;
      FilterLink(uint32_t p, nsIProtocolProxyFilter *f)
        : next(nullptr), position(p), filter(f), channelFilter(nullptr) {}
      FilterLink(uint32_t p, nsIProtocolProxyChannelFilter *cf)
        : next(nullptr), position(p), filter(nullptr), channelFilter(cf) {}
      // Chain deletion to simplify cleaning up the filter links
      ~FilterLink() { if (next) delete next; }
    };

private:
    // Private methods to insert and remove FilterLinks from the FilterLink chain.
    nsresult InsertFilterLink(FilterLink *link, uint32_t position);
    nsresult RemoveFilterLink(nsISupports *givenObject);

protected:
    // Indicates if local hosts (plain hostnames, no dots) should use the proxy
    bool mFilterLocalHosts;

    // Holds an array of HostInfo objects
    nsTArray<nsAutoPtr<HostInfo> > mHostFiltersArray;

    // Points to the start of a sorted by position, singly linked list
    // of FilterLink objects.
    FilterLink                  *mFilters;

    uint32_t                     mProxyConfig;

    nsCString                    mHTTPProxyHost;
    int32_t                      mHTTPProxyPort;

    nsCString                    mFTPProxyHost;
    int32_t                      mFTPProxyPort;

    nsCString                    mHTTPSProxyHost;
    int32_t                      mHTTPSProxyPort;

    // mSOCKSProxyTarget could be a host, a domain socket path,
    // or a named-pipe name.
    nsCString                    mSOCKSProxyTarget;
    int32_t                      mSOCKSProxyPort;
    int32_t                      mSOCKSProxyVersion;
    bool                         mSOCKSProxyRemoteDNS;
    bool                         mProxyOverTLS;

    RefPtr<nsPACMan>           mPACMan;  // non-null if we are using PAC
    nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;

    PRTime                       mSessionStart;
    nsFailedProxyTable           mFailedProxies;
    int32_t                      mFailedProxyTimeout;

private:
    nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
                                  nsIProtocolProxyCallback *callback,
                                  nsICancelable **result,
                                  bool isSyncOK,
                                  nsIEventTarget *mainThreadEventTarget);
    bool                          mIsShutdown;
    nsCOMPtr<nsIThread>           mProxySettingThread;
};

NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService, NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)

} // namespace net
} // namespace mozilla

#endif // !nsProtocolProxyService_h__