• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
set_quick_check_enabled(bool enabled)82   void set_quick_check_enabled(bool enabled) {
83     quick_check_enabled_ = enabled;
84   }
85 
quick_check_enabled()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 
PacSourcePacSource98     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