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