Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_PROXY_PROXY_SCRIPT_DECIDER_H_
      6 #define NET_PROXY_PROXY_SCRIPT_DECIDER_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/memory/ref_counted.h"
     12 #include "base/strings/string16.h"
     13 #include "base/time/time.h"
     14 #include "base/timer/timer.h"
     15 #include "net/base/address_list.h"
     16 #include "net/base/completion_callback.h"
     17 #include "net/base/net_export.h"
     18 #include "net/base/net_log.h"
     19 #include "net/dns/host_resolver.h"
     20 #include "net/dns/single_request_host_resolver.h"
     21 #include "net/proxy/proxy_config.h"
     22 #include "net/proxy/proxy_resolver.h"
     23 #include "url/gurl.h"
     24 
     25 namespace net {
     26 
     27 class DhcpProxyScriptFetcher;
     28 class NetLogParameter;
     29 class ProxyResolver;
     30 class ProxyScriptFetcher;
     31 
     32 // ProxyScriptDecider is a helper class used by ProxyService to determine which
     33 // PAC script to use given our proxy configuration.
     34 //
     35 // This involves trying to use PAC scripts in this order:
     36 //
     37 //   (1) WPAD (DHCP) if auto-detect is on.
     38 //   (2) WPAD (DNS) if auto-detect is on.
     39 //   (3) Custom PAC script if a URL was given.
     40 //
     41 // If no PAC script was successfully selected, then it fails with either a
     42 // network error, or PAC_SCRIPT_FAILED (indicating it did not pass our
     43 // validation).
     44 //
     45 // On successful completion, the fetched PAC script data can be accessed using
     46 // script_data().
     47 //
     48 // Deleting ProxyScriptDecider while Init() is in progress, will
     49 // cancel the request.
     50 //
     51 class NET_EXPORT_PRIVATE ProxyScriptDecider {
     52  public:
     53   // |proxy_script_fetcher|, |dhcp_proxy_script_fetcher| and
     54   // |net_log| must remain valid for the lifespan of ProxyScriptDecider.
     55   ProxyScriptDecider(ProxyScriptFetcher* proxy_script_fetcher,
     56                      DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
     57                      NetLog* net_log);
     58 
     59   // Aborts any in-progress request.
     60   ~ProxyScriptDecider();
     61 
     62   // Evaluates the effective proxy settings for |config|, and downloads the
     63   // associated PAC script.
     64   // If |wait_delay| is positive, the initialization will pause for this
     65   // amount of time before getting started.
     66   // On successful completion, the "effective" proxy settings we ended up
     67   // deciding on will be available vial the effective_settings() accessor.
     68   // Note that this may differ from |config| since we will have stripped any
     69   // manual settings, and decided whether to use auto-detect or the custom PAC
     70   // URL. Finally, if auto-detect was used we may now have resolved that to a
     71   // specific script URL.
     72   int Start(const ProxyConfig& config,
     73             const base::TimeDelta wait_delay,
     74             bool fetch_pac_bytes,
     75             const net::CompletionCallback& callback);
     76 
     77   const ProxyConfig& effective_config() const;
     78 
     79   // TODO(eroman): Return a const-pointer.
     80   ProxyResolverScriptData* script_data() const;
     81 
     82  private:
     83   // Represents the sources from which we can get PAC files; two types of
     84   // auto-detect or a custom URL.
     85   struct PacSource {
     86     enum Type {
     87       WPAD_DHCP,
     88       WPAD_DNS,
     89       CUSTOM
     90     };
     91 
     92     PacSource(Type type, const GURL& url)
     93         : type(type), url(url) {}
     94 
     95     // Returns a Value representing the PacSource.  |effective_pac_url| must
     96     // be non-NULL and point to the URL derived from information contained in
     97     // |this|, if Type is not WPAD_DHCP.
     98     base::Value* NetLogCallback(const GURL* effective_pac_url,
     99                                 NetLog::LogLevel log_level) const;
    100 
    101     Type type;
    102     GURL url;  // Empty unless |type == PAC_SOURCE_CUSTOM|.
    103   };
    104 
    105   typedef std::vector<PacSource> PacSourceList;
    106 
    107   enum State {
    108     STATE_NONE,
    109     STATE_WAIT,
    110     STATE_WAIT_COMPLETE,
    111     STATE_QUICK_CHECK,
    112     STATE_QUICK_CHECK_COMPLETE,
    113     STATE_FETCH_PAC_SCRIPT,
    114     STATE_FETCH_PAC_SCRIPT_COMPLETE,
    115     STATE_VERIFY_PAC_SCRIPT,
    116     STATE_VERIFY_PAC_SCRIPT_COMPLETE,
    117   };
    118 
    119   // Returns ordered list of PAC urls to try for |config|.
    120   PacSourceList BuildPacSourcesFallbackList(const ProxyConfig& config) const;
    121 
    122   void OnIOCompletion(int result);
    123   int DoLoop(int result);
    124   void DoCallback(int result);
    125 
    126   int DoWait();
    127   int DoWaitComplete(int result);
    128 
    129   int DoQuickCheck();
    130   int DoQuickCheckComplete(int result);
    131 
    132   int DoFetchPacScript();
    133   int DoFetchPacScriptComplete(int result);
    134 
    135   int DoVerifyPacScript();
    136   int DoVerifyPacScriptComplete(int result);
    137 
    138   // Tries restarting using the next fallback PAC URL:
    139   // |pac_sources_[++current_pac_source_index]|.
    140   // Returns OK and rewinds the state machine when there
    141   // is something to try, otherwise returns |error|.
    142   int TryToFallbackPacSource(int error);
    143 
    144   // Gets the initial state (we skip fetching when the
    145   // ProxyResolver doesn't |expect_pac_bytes()|.
    146   State GetStartState() const;
    147 
    148   void DetermineURL(const PacSource& pac_source, GURL* effective_pac_url);
    149 
    150   // Returns the current PAC URL we are fetching/testing.
    151   const PacSource& current_pac_source() const;
    152 
    153   void OnWaitTimerFired();
    154   void DidComplete();
    155   void Cancel();
    156 
    157   ProxyResolver* resolver_;
    158   ProxyScriptFetcher* proxy_script_fetcher_;
    159   DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
    160 
    161   net::CompletionCallback callback_;
    162 
    163   size_t current_pac_source_index_;
    164 
    165   // Filled when the PAC script fetch completes.
    166   base::string16 pac_script_;
    167 
    168   // Flag indicating whether the caller requested a mandatory pac script
    169   // (i.e. fallback to direct connections are prohibited).
    170   bool pac_mandatory_;
    171 
    172   // Whether we have an existing custom PAC URL.
    173   bool have_custom_pac_url_;
    174 
    175   PacSourceList pac_sources_;
    176   State next_state_;
    177 
    178   BoundNetLog net_log_;
    179 
    180   bool fetch_pac_bytes_;
    181 
    182   base::TimeDelta wait_delay_;
    183   base::OneShotTimer<ProxyScriptDecider> wait_timer_;
    184 
    185   // Results.
    186   ProxyConfig effective_config_;
    187   scoped_refptr<ProxyResolverScriptData> script_data_;
    188 
    189   AddressList wpad_addresses_;
    190   base::OneShotTimer<ProxyScriptDecider> quick_check_timer_;
    191   scoped_ptr<SingleRequestHostResolver> host_resolver_;
    192   base::Time quick_check_start_time_;
    193 
    194   DISALLOW_COPY_AND_ASSIGN(ProxyScriptDecider);
    195 };
    196 
    197 }  // namespace net
    198 
    199 #endif  // NET_PROXY_PROXY_SCRIPT_DECIDER_H_
    200