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 25namespace net { 26 27class DhcpProxyScriptFetcher; 28class NetLogParameter; 29class ProxyResolver; 30class 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// 51class 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 void set_quick_check_enabled(bool enabled) { 83 quick_check_enabled_ = enabled; 84 } 85 86 bool quick_check_enabled() const { return quick_check_enabled_; } 87 88 private: 89 // Represents the sources from which we can get PAC files; two types of 90 // auto-detect or a custom URL. 91 struct PacSource { 92 enum Type { 93 WPAD_DHCP, 94 WPAD_DNS, 95 CUSTOM 96 }; 97 98 PacSource(Type type, const GURL& url) 99 : type(type), url(url) {} 100 101 // Returns a Value representing the PacSource. |effective_pac_url| must 102 // be non-NULL and point to the URL derived from information contained in 103 // |this|, if Type is not WPAD_DHCP. 104 base::Value* NetLogCallback(const GURL* effective_pac_url, 105 NetLog::LogLevel log_level) const; 106 107 Type type; 108 GURL url; // Empty unless |type == PAC_SOURCE_CUSTOM|. 109 }; 110 111 typedef std::vector<PacSource> PacSourceList; 112 113 enum State { 114 STATE_NONE, 115 STATE_WAIT, 116 STATE_WAIT_COMPLETE, 117 STATE_QUICK_CHECK, 118 STATE_QUICK_CHECK_COMPLETE, 119 STATE_FETCH_PAC_SCRIPT, 120 STATE_FETCH_PAC_SCRIPT_COMPLETE, 121 STATE_VERIFY_PAC_SCRIPT, 122 STATE_VERIFY_PAC_SCRIPT_COMPLETE, 123 }; 124 125 // Returns ordered list of PAC urls to try for |config|. 126 PacSourceList BuildPacSourcesFallbackList(const ProxyConfig& config) const; 127 128 void OnIOCompletion(int result); 129 int DoLoop(int result); 130 void DoCallback(int result); 131 132 int DoWait(); 133 int DoWaitComplete(int result); 134 135 int DoQuickCheck(); 136 int DoQuickCheckComplete(int result); 137 138 int DoFetchPacScript(); 139 int DoFetchPacScriptComplete(int result); 140 141 int DoVerifyPacScript(); 142 int DoVerifyPacScriptComplete(int result); 143 144 // Tries restarting using the next fallback PAC URL: 145 // |pac_sources_[++current_pac_source_index]|. 146 // Returns OK and rewinds the state machine when there 147 // is something to try, otherwise returns |error|. 148 int TryToFallbackPacSource(int error); 149 150 // Gets the initial state (we skip fetching when the 151 // ProxyResolver doesn't |expect_pac_bytes()|. 152 State GetStartState() const; 153 154 void DetermineURL(const PacSource& pac_source, GURL* effective_pac_url); 155 156 // Returns the current PAC URL we are fetching/testing. 157 const PacSource& current_pac_source() const; 158 159 void OnWaitTimerFired(); 160 void DidComplete(); 161 void Cancel(); 162 163 ProxyResolver* resolver_; 164 ProxyScriptFetcher* proxy_script_fetcher_; 165 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_; 166 167 net::CompletionCallback callback_; 168 169 size_t current_pac_source_index_; 170 171 // Filled when the PAC script fetch completes. 172 base::string16 pac_script_; 173 174 // Flag indicating whether the caller requested a mandatory pac script 175 // (i.e. fallback to direct connections are prohibited). 176 bool pac_mandatory_; 177 178 // Whether we have an existing custom PAC URL. 179 bool have_custom_pac_url_; 180 181 PacSourceList pac_sources_; 182 State next_state_; 183 184 BoundNetLog net_log_; 185 186 bool fetch_pac_bytes_; 187 188 base::TimeDelta wait_delay_; 189 base::OneShotTimer<ProxyScriptDecider> wait_timer_; 190 191 // Whether to do DNS quick check 192 bool quick_check_enabled_; 193 194 // Results. 195 ProxyConfig effective_config_; 196 scoped_refptr<ProxyResolverScriptData> script_data_; 197 198 AddressList wpad_addresses_; 199 base::OneShotTimer<ProxyScriptDecider> quick_check_timer_; 200 scoped_ptr<SingleRequestHostResolver> host_resolver_; 201 base::Time quick_check_start_time_; 202 203 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDecider); 204}; 205 206} // namespace net 207 208#endif // NET_PROXY_PROXY_SCRIPT_DECIDER_H_ 209