blob: 1d528dcde3185c62cd79cf18e718dc52fa5ccfa1 [file] [log] [blame]
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_PROXY_PROXY_SERVICE_H_
#define NET_PROXY_PROXY_SERVICE_H_
#include <map>
#include <vector>
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "net/base/completion_callback.h"
#if defined(OS_WIN)
typedef LPVOID HINTERNET; // From winhttp.h
#endif
class GURL;
namespace net {
class ProxyConfigService;
class ProxyInfo;
class ProxyResolver;
// Proxy configuration used to by the ProxyService.
class ProxyConfig {
public:
typedef int ID;
// Indicates an invalid proxy config.
enum { INVALID_ID = 0 };
ProxyConfig();
// Default copy-constructor and assignment operator are OK!
// Used to numerically identify this configuration.
ID id() const { return id_; }
// True if the proxy configuration should be auto-detected.
bool auto_detect;
// If non-empty, indicates the URL of the proxy auto-config file to use.
GURL pac_url;
// If non-empty, indicates the proxy server to use (of the form host:port).
// If proxies depend on the scheme, a string of the format
// "scheme1=url[:port];scheme2=url[:port]" may be provided here.
std::string proxy_server;
// Indicates a list of hosts that should bypass any proxy configuration. For
// these hosts, a direct connection should always be used.
std::vector<std::string> proxy_bypass;
// Indicates whether local names (no dots) bypass proxies.
bool proxy_bypass_local_names;
// Returns true if the given config is equivalent to this config.
bool Equals(const ProxyConfig& other) const;
private:
static int last_id_;
int id_;
};
// Contains the information about when to retry a proxy server.
struct ProxyRetryInfo {
// We should not retry until this time.
base::TimeTicks bad_until;
// This is the current delay. If the proxy is still bad, we need to increase
// this delay.
base::TimeDelta current_delay;
};
// Map of proxy servers with the associated RetryInfo structures.
typedef std::map<std::string, ProxyRetryInfo> ProxyRetryInfoMap;
// This class can be used to resolve the proxy server to use when loading a
// HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy
// resolution. See ProxyResolverWinHttp for example.
class ProxyService {
public:
// The instance takes ownership of |config_service| and |resolver|.
ProxyService(ProxyConfigService* config_service,
ProxyResolver* resolver);
// Used internally to handle PAC queries.
class PacRequest;
// Returns OK if proxy information could be provided synchronously. Else,
// ERR_IO_PENDING is returned to indicate that the result will be available
// when the callback is run. The callback is run on the thread that calls
// ResolveProxy.
//
// The caller is responsible for ensuring that |results| and |callback|
// remain valid until the callback is run or until |pac_request| is cancelled
// via CancelPacRequest. |pac_request| is only valid while the completion
// callback is still pending. NULL can be passed for |pac_request| if
// the caller will not need to cancel the request.
//
// We use the three possible proxy access types in the following order, and
// we only use one of them (no falling back to other access types if the
// chosen one doesn't work).
// 1. named proxy
// 2. PAC URL
// 3. WPAD auto-detection
//
int ResolveProxy(const GURL& url,
ProxyInfo* results,
CompletionCallback* callback,
PacRequest** pac_request);
// This method is called after a failure to connect or resolve a host name.
// It gives the proxy service an opportunity to reconsider the proxy to use.
// The |results| parameter contains the results returned by an earlier call
// to ResolveProxy. The semantics of this call are otherwise similar to
// ResolveProxy.
//
// NULL can be passed for |pac_request| if the caller will not need to
// cancel the request.
//
// Returns ERR_FAILED if there is not another proxy config to try.
//
int ReconsiderProxyAfterError(const GURL& url,
ProxyInfo* results,
CompletionCallback* callback,
PacRequest** pac_request);
// Call this method with a non-null |pac_request| to cancel the PAC request.
void CancelPacRequest(PacRequest* pac_request);
// Create a proxy service using the specified settings. If |pi| is NULL then
// the system's default proxy settings will be used (on Windows this will
// use IE's settings).
static ProxyService* Create(const ProxyInfo* pi);
// Create a proxy service that always fails to fetch the proxy configuration,
// so it falls back to direct connect.
static ProxyService* CreateNull();
private:
friend class PacRequest;
ProxyResolver* resolver() { return resolver_.get(); }
base::Thread* pac_thread() { return pac_thread_.get(); }
// Identifies the proxy configuration.
ProxyConfig::ID config_id() const { return config_.id(); }
// Checks to see if the proxy configuration changed, and then updates config_
// to reference the new configuration.
void UpdateConfig();
// Called to indicate that a PacRequest completed. The |config_id| parameter
// indicates the proxy configuration that was queried. |result_code| is OK
// if the PAC file could be downloaded and executed. Otherwise, it is an
// error code, indicating a bad proxy configuration.
void DidCompletePacRequest(int config_id, int result_code);
// Returns true if the URL passed in should not go through the proxy server.
// 1. If the bypass proxy list contains the string <local> and the URL
// passed in is a local URL, i.e. a URL without a DOT (.)
// 2. The URL matches one of the entities in the proxy bypass list.
bool ShouldBypassProxyForURL(const GURL& url);
scoped_ptr<ProxyConfigService> config_service_;
scoped_ptr<ProxyResolver> resolver_;
scoped_ptr<base::Thread> pac_thread_;
// We store the proxy config and a counter that is incremented each time
// the config changes.
ProxyConfig config_;
// Indicates that the configuration is bad and should be ignored.
bool config_is_bad_;
// false if the ProxyService has not been initialized yet.
bool config_has_been_updated_;
// The time when the proxy configuration was last read from the system.
base::TimeTicks config_last_update_time_;
// Map of the known bad proxies and the information about the retry time.
ProxyRetryInfoMap proxy_retry_info_;
DISALLOW_COPY_AND_ASSIGN(ProxyService);
};
// This class is used to hold a list of proxies returned by GetProxyForUrl or
// manually configured. It handles proxy fallback if multiple servers are
// specified.
// TODO(eroman): The proxy list should work for multiple proxy types.
// See http://crbug.com/469.
class ProxyList {
public:
// Initializes the proxy list to a string containing one or more proxy servers
// delimited by a semicolon.
void Set(const std::string& proxy_list);
// Initializes the proxy list to a vector containing one or more proxy
// servers.
void SetVector(const std::vector<std::string>& proxy_list);
// Remove all proxies known to be bad from the proxy list.
void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info);
// Returns the first valid proxy server in the list.
std::string Get() const;
// Returns a PAC-style semicolon-separated list of valid proxy servers.
// For example: "PROXY xxx.xxx.xxx.xxx:xx; SOCKS yyy.yyy.yyy:yy".
// Since ProxyList is currently just used for HTTP, this will return only
// entries of type "PROXY" or "DIRECT".
std::string GetAnnotatedList() const;
// Marks the current proxy server as bad and deletes it from the list. The
// list of known bad proxies is given by proxy_retry_info. Returns true if
// there is another server available in the list.
bool Fallback(ProxyRetryInfoMap* proxy_retry_info);
private:
// List of proxies.
std::vector<std::string> proxies_;
};
// This object holds proxy information returned by ResolveProxy.
class ProxyInfo {
public:
ProxyInfo();
// Default copy-constructor and assignment operator are OK!
// Use the same proxy server as the given |proxy_info|.
void Use(const ProxyInfo& proxy_info);
// Use a direct connection.
void UseDirect();
// Use a specific proxy server, of the form: <hostname> [":" <port>]
// This may optionally be a semi-colon delimited list of proxy servers.
void UseNamedProxy(const std::string& proxy_server);
#if defined(OS_WIN)
// Apply this proxy information to the given WinHTTP request handle.
void Apply(HINTERNET request_handle);
#endif
// Returns true if this proxy info specifies a direct connection.
bool is_direct() const { return proxy_list_.Get().empty(); }
// Returns the first valid proxy server.
std::string proxy_server() const { return proxy_list_.Get(); }
// See description in ProxyList::GetAnnotatedList().
std::string GetAnnotatedProxyList();
// Marks the current proxy as bad. Returns true if there is another proxy
// available to try in proxy list_.
bool Fallback(ProxyRetryInfoMap* proxy_retry_info) {
return proxy_list_.Fallback(proxy_retry_info);
}
// Remove all proxies known to be bad from the proxy list.
void RemoveBadProxies(const ProxyRetryInfoMap& proxy_retry_info) {
proxy_list_.RemoveBadProxies(proxy_retry_info);
}
private:
friend class ProxyService;
// If proxy_list_ is set to empty, then a "direct" connection is indicated.
ProxyList proxy_list_;
// This value identifies the proxy config used to initialize this object.
ProxyConfig::ID config_id_;
// This flag is false when the proxy configuration was known to be bad when
// this proxy info was initialized. In such cases, we know that if this
// proxy info does not yield a connection that we might want to reconsider
// the proxy config given by config_id_.
bool config_was_tried_;
};
// Synchronously fetch the system's proxy configuration settings. Called on
// the IO Thread.
class ProxyConfigService {
public:
virtual ~ProxyConfigService() {}
// Get the proxy configuration. Returns OK if successful or an error code if
// otherwise. |config| should be in its initial state when this method is
// called.
virtual int GetProxyConfig(ProxyConfig* config) = 0;
};
// Synchronously resolve the proxy for a URL, using a PAC script. Called on the
// PAC Thread.
class ProxyResolver {
public:
virtual ~ProxyResolver() {}
// Query the proxy auto-config file (specified by |pac_url|) for the proxy to
// use to load the given |query_url|. Returns OK if successful or an error
// code otherwise.
virtual int GetProxyForURL(const GURL& query_url,
const GURL& pac_url,
ProxyInfo* results) = 0;
};
} // namespace net
#endif // NET_PROXY_PROXY_SERVICE_H_