• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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_RESOLUTION_CONFIGURED_PROXY_RESOLUTION_SERVICE_H_
6 #define NET_PROXY_RESOLUTION_CONFIGURED_PROXY_RESOLUTION_SERVICE_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <vector>
14 
15 #include "base/gtest_prod_util.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/threading/thread_checker.h"
19 #include "net/base/completion_once_callback.h"
20 #include "net/base/load_states.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/net_export.h"
23 #include "net/base/network_change_notifier.h"
24 #include "net/log/net_log_with_source.h"
25 #include "net/proxy_resolution/proxy_config_service.h"
26 #include "net/proxy_resolution/proxy_config_with_annotation.h"
27 #include "net/proxy_resolution/proxy_info.h"
28 #include "net/proxy_resolution/proxy_resolution_request.h"
29 #include "net/proxy_resolution/proxy_resolution_service.h"
30 #include "net/proxy_resolution/proxy_resolver.h"
31 #include "net/traffic_annotation/network_traffic_annotation.h"
32 #include "third_party/abseil-cpp/absl/types/optional.h"
33 #include "url/gurl.h"
34 
35 namespace base {
36 class TimeDelta;
37 }  // namespace base
38 
39 namespace net {
40 
41 class ConfiguredProxyResolutionRequest;
42 class DhcpPacFileFetcher;
43 class NetLog;
44 class PacFileFetcher;
45 class ProxyDelegate;
46 class ProxyResolverFactory;
47 struct PacFileDataWithSource;
48 
49 // This class decides which proxy server(s) to use for a particular URL request.
50 // It uses the given ProxyResolver to evaluate a PAC file, which the
51 // ConfiguredProxyResolutionService then uses to resolve a proxy.  All proxy
52 // resolution in this class is based on first getting proxy configurations (ex:
53 // a PAC URL) from some source and then using these configurations to attempt to
54 // resolve that proxy.
55 class NET_EXPORT ConfiguredProxyResolutionService
56     : public ProxyResolutionService,
57       public NetworkChangeNotifier::IPAddressObserver,
58       public NetworkChangeNotifier::DNSObserver,
59       public ProxyConfigService::Observer {
60  public:
61   // This interface defines the set of policies for when to poll the PAC
62   // script for changes.
63   //
64   // The polling policy decides what the next poll delay should be in
65   // milliseconds. It also decides how to wait for this delay -- either
66   // by starting a timer to do the poll at exactly |next_delay_ms|
67   // (MODE_USE_TIMER) or by waiting for the first network request issued after
68   // |next_delay_ms| (MODE_START_AFTER_ACTIVITY).
69   //
70   // The timer method is more precise and guarantees that polling happens when
71   // it was requested. However it has the disadvantage of causing spurious CPU
72   // and network activity. It is a reasonable choice to use for short poll
73   // intervals which only happen a couple times.
74   //
75   // However for repeated timers this will prevent the browser from going
76   // idle. MODE_START_AFTER_ACTIVITY solves this problem by only polling in
77   // direct response to network activity. The drawback to
78   // MODE_START_AFTER_ACTIVITY is since the poll is initiated only after the
79   // request is received, the first couple requests initiated after a long
80   // period of inactivity will likely see a stale version of the PAC script
81   // until the background polling gets a chance to update things.
82   class NET_EXPORT_PRIVATE PacPollPolicy {
83    public:
84     enum Mode {
85       MODE_USE_TIMER,
86       MODE_START_AFTER_ACTIVITY,
87     };
88 
89     virtual ~PacPollPolicy() = default;
90 
91     // Decides the next poll delay. |current_delay| is the delay used
92     // by the preceding poll, or a negative TimeDelta value if determining
93     // the delay for the initial poll. |initial_error| is the network error
94     // code that the last PAC fetch (or WPAD initialization) failed with,
95     // or OK if it completed successfully. Implementations must set
96     // |next_delay| to a non-negative value.
97     virtual Mode GetNextDelay(int initial_error,
98                               base::TimeDelta current_delay,
99                               base::TimeDelta* next_delay) const = 0;
100   };
101 
102   // |net_log| is a possibly nullptr destination to send log events to. It must
103   // remain alive for the lifetime of this ConfiguredProxyResolutionService.
104   ConfiguredProxyResolutionService(
105       std::unique_ptr<ProxyConfigService> config_service,
106       std::unique_ptr<ProxyResolverFactory> resolver_factory,
107       NetLog* net_log,
108       bool quick_check_enabled);
109 
110   ConfiguredProxyResolutionService(const ConfiguredProxyResolutionService&) =
111       delete;
112   ConfiguredProxyResolutionService& operator=(
113       const ConfiguredProxyResolutionService&) = delete;
114 
115   ~ConfiguredProxyResolutionService() override;
116 
117   // ProxyResolutionService
118   //
119   // We use the three possible proxy access types in the following order,
120   // doing fallback if one doesn't work.  See "pac_script_decider.h"
121   // for the specifics.
122   //   1.  WPAD auto-detection
123   //   2.  PAC URL
124   //   3.  named proxy
125   int ResolveProxy(const GURL& url,
126                    const std::string& method,
127                    const NetworkAnonymizationKey& network_anonymization_key,
128                    ProxyInfo* results,
129                    CompletionOnceCallback callback,
130                    std::unique_ptr<ProxyResolutionRequest>* request,
131                    const NetLogWithSource& net_log) override;
132 
133   // ProxyResolutionService
134   bool MarkProxiesAsBadUntil(
135       const ProxyInfo& results,
136       base::TimeDelta retry_delay,
137       const std::vector<ProxyServer>& additional_bad_proxies,
138       const NetLogWithSource& net_log) override;
139 
140   // ProxyResolutionService
141   void ReportSuccess(const ProxyInfo& proxy_info) override;
142 
143   // Sets the PacFileFetcher and DhcpPacFileFetcher dependencies. This
144   // is needed if the ProxyResolver is of type ProxyResolverWithoutFetch.
145   void SetPacFileFetchers(
146       std::unique_ptr<PacFileFetcher> pac_file_fetcher,
147       std::unique_ptr<DhcpPacFileFetcher> dhcp_pac_file_fetcher);
148   PacFileFetcher* GetPacFileFetcher() const;
149 
150   // ProxyResolutionService
151   void SetProxyDelegate(ProxyDelegate* delegate) override;
152 
153   // ProxyResolutionService
154   void OnShutdown() override;
155 
156   // Returns the last configuration fetched from ProxyConfigService.
fetched_config()157   const absl::optional<ProxyConfigWithAnnotation>& fetched_config() const {
158     return fetched_config_;
159   }
160 
161   // Returns the current configuration being used by ProxyConfigService.
config()162   const absl::optional<ProxyConfigWithAnnotation>& config() const {
163     return config_;
164   }
165 
166   // ProxyResolutionService
167   const ProxyRetryInfoMap& proxy_retry_info() const override;
168 
169   // ProxyResolutionService
170   void ClearBadProxiesCache() override;
171 
172   // Forces refetching the proxy configuration, and applying it.
173   // This re-does everything from fetching the system configuration,
174   // to downloading and testing the PAC files.
175   void ForceReloadProxyConfig();
176 
177   // ProxyResolutionService
178   base::Value::Dict GetProxyNetLogValues() override;
179 
180   // ProxyResolutionService
181   [[nodiscard]] bool CastToConfiguredProxyResolutionService(
182       ConfiguredProxyResolutionService** configured_proxy_resolution_service)
183       override;
184 
185   // Same as CreateProxyResolutionServiceUsingV8ProxyResolver, except it uses
186   // system libraries for evaluating the PAC script if available, otherwise
187   // skips proxy autoconfig.
188   static std::unique_ptr<ConfiguredProxyResolutionService>
189   CreateUsingSystemProxyResolver(
190       std::unique_ptr<ProxyConfigService> proxy_config_service,
191       NetLog* net_log,
192       bool quick_check_enabled);
193 
194   // Creates a ConfiguredProxyResolutionService without support for proxy
195   // autoconfig.
196   static std::unique_ptr<ConfiguredProxyResolutionService>
197   CreateWithoutProxyResolver(
198       std::unique_ptr<ProxyConfigService> proxy_config_service,
199       NetLog* net_log);
200 
201   // Convenience methods that creates a proxy service using the
202   // specified fixed settings.
203   static std::unique_ptr<ConfiguredProxyResolutionService> CreateFixedForTest(
204       const ProxyConfigWithAnnotation& pc);
205   static std::unique_ptr<ConfiguredProxyResolutionService> CreateFixedForTest(
206       const std::string& proxy,
207       const NetworkTrafficAnnotationTag& traffic_annotation);
208 
209   // Creates a proxy service that uses a DIRECT connection for all requests.
210   static std::unique_ptr<ConfiguredProxyResolutionService> CreateDirect();
211 
212   // This method is used by tests to create a ConfiguredProxyResolutionService
213   // that returns a hardcoded proxy fallback list (|pac_string|) for every URL.
214   //
215   // |pac_string| is a list of proxy servers, in the format that a PAC script
216   // would return it. For example, "PROXY foobar:99; SOCKS fml:2; DIRECT"
217   static std::unique_ptr<ConfiguredProxyResolutionService>
218   CreateFixedFromPacResultForTest(
219       const std::string& pac_string,
220       const NetworkTrafficAnnotationTag& traffic_annotation);
221 
222   // Same as CreateFixedFromPacResultForTest(), except the resulting ProxyInfo
223   // from resolutions will be tagged as having been auto-detected.
224   static std::unique_ptr<ConfiguredProxyResolutionService>
225   CreateFixedFromAutoDetectedPacResultForTest(
226       const std::string& pac_string,
227       const NetworkTrafficAnnotationTag& traffic_annotation);
228 
229   // This method should only be used by unit tests.
set_stall_proxy_auto_config_delay(base::TimeDelta delay)230   void set_stall_proxy_auto_config_delay(base::TimeDelta delay) {
231     stall_proxy_auto_config_delay_ = delay;
232   }
233 
234   // This method should only be used by unit tests. Returns the previously
235   // active policy.
236   static const PacPollPolicy* set_pac_script_poll_policy(
237       const PacPollPolicy* policy);
238 
239   // This method should only be used by unit tests. Creates an instance
240   // of the default internal PacPollPolicy used by
241   // ConfiguredProxyResolutionService.
242   static std::unique_ptr<PacPollPolicy> CreateDefaultPacPollPolicy();
243 
quick_check_enabled_for_testing()244   bool quick_check_enabled_for_testing() const { return quick_check_enabled_; }
245 
246  private:
247   friend class ConfiguredProxyResolutionRequest;
248   FRIEND_TEST_ALL_PREFIXES(ProxyResolutionServiceTest,
249                            UpdateConfigAfterFailedAutodetect);
250   FRIEND_TEST_ALL_PREFIXES(ProxyResolutionServiceTest,
251                            UpdateConfigFromPACToDirect);
252   class InitProxyResolver;
253   class PacFileDeciderPoller;
254 
255   typedef std::set<ConfiguredProxyResolutionRequest*> PendingRequests;
256 
257   enum State {
258     STATE_NONE,
259     STATE_WAITING_FOR_PROXY_CONFIG,
260     STATE_WAITING_FOR_INIT_PROXY_RESOLVER,
261     STATE_READY,
262   };
263 
264   // We won't always be able to return a good LoadState. For example, the
265   // ConfiguredProxyResolutionService can only get this information from the
266   // InitProxyResolver, which is not always available.
267   bool GetLoadStateIfAvailable(LoadState* load_state) const;
268 
269   ProxyResolver* GetProxyResolver() const;
270 
271   // Resets all the variables associated with the current proxy configuration,
272   // and rewinds the current state to |STATE_NONE|. Returns the previous value
273   // of |current_state_|.  If |reset_fetched_config| is true then
274   // |fetched_config_| will also be reset, otherwise it will be left as-is.
275   // Resetting it means that we will have to re-fetch the configuration from
276   // the ProxyConfigService later.
277   State ResetProxyConfig(bool reset_fetched_config);
278 
279   // Retrieves the current proxy configuration from the ProxyConfigService, and
280   // starts initializing for it.
281   void ApplyProxyConfigIfAvailable();
282 
283   // Callback for when the proxy resolver has been initialized with a
284   // PAC script.
285   void OnInitProxyResolverComplete(int result);
286 
287   // Returns ERR_IO_PENDING if the request cannot be completed synchronously.
288   // Otherwise it fills |result| with the proxy information for |url|.
289   // Completing synchronously means we don't need to query ProxyResolver.
290   int TryToCompleteSynchronously(const GURL& url, ProxyInfo* result);
291 
292   // Cancels all of the requests sent to the ProxyResolver. These will be
293   // restarted when calling SetReady().
294   void SuspendAllPendingRequests();
295 
296   // Advances the current state to |STATE_READY|, and resumes any pending
297   // requests which had been stalled waiting for initialization to complete.
298   void SetReady();
299 
300   // Returns true if |pending_requests_| contains |req|.
301   bool ContainsPendingRequest(ConfiguredProxyResolutionRequest* req);
302 
303   // Removes |req| from the list of pending requests.
304   void RemovePendingRequest(ConfiguredProxyResolutionRequest* req);
305 
306   // Called when proxy resolution has completed (either synchronously or
307   // asynchronously). Handles logging the result, and cleaning out
308   // bad entries from the results list.
309   int DidFinishResolvingProxy(const GURL& url,
310                               const std::string& method,
311                               ProxyInfo* result,
312                               int result_code,
313                               const NetLogWithSource& net_log);
314 
315   // Start initialization using |fetched_config_|.
316   void InitializeUsingLastFetchedConfig();
317 
318   // Start the initialization skipping past the "decision" phase.
319   void InitializeUsingDecidedConfig(
320       int decider_result,
321       const PacFileDataWithSource& script_data,
322       const ProxyConfigWithAnnotation& effective_config);
323 
324   // NetworkChangeNotifier::IPAddressObserver
325   // When this is called, we re-fetch PAC scripts and re-run WPAD.
326   void OnIPAddressChanged() override;
327 
328   // NetworkChangeNotifier::DNSObserver
329   // We respond as above.
330   void OnDNSChanged() override;
331 
332   // ProxyConfigService::Observer
333   void OnProxyConfigChanged(
334       const ProxyConfigWithAnnotation& config,
335       ProxyConfigService::ConfigAvailability availability) override;
336 
337   // When using a PAC script there isn't a user-configurable ProxyBypassRules to
338   // check, as the one from manual settings doesn't apply. However we
339   // still check for matches against the implicit bypass rules, to prevent PAC
340   // scripts from being able to proxy localhost.
341   bool ApplyPacBypassRules(const GURL& url, ProxyInfo* results);
342 
343   std::unique_ptr<ProxyConfigService> config_service_;
344   std::unique_ptr<ProxyResolverFactory> resolver_factory_;
345 
346   // If non-null, the initialized ProxyResolver to use for requests.
347   std::unique_ptr<ProxyResolver> resolver_;
348 
349   // We store the proxy configuration that was last fetched from the
350   // ProxyConfigService, as well as the resulting "effective" configuration.
351   // The effective configuration is what we condense the original fetched
352   // settings to after testing the various automatic settings (auto-detect
353   // and custom PAC url).
354   //
355   // These are "optional" as their value remains unset while being calculated.
356   absl::optional<ProxyConfigWithAnnotation> fetched_config_;
357   absl::optional<ProxyConfigWithAnnotation> config_;
358 
359   // Map of the known bad proxies and the information about the retry time.
360   ProxyRetryInfoMap proxy_retry_info_;
361 
362   // Set of pending/inprogress requests.
363   PendingRequests pending_requests_;
364 
365   // The fetcher to use when downloading PAC scripts for the ProxyResolver.
366   // This dependency can be nullptr if our ProxyResolver has no need for
367   // external PAC script fetching.
368   std::unique_ptr<PacFileFetcher> pac_file_fetcher_;
369 
370   // The fetcher to use when attempting to download the most appropriate PAC
371   // script configured in DHCP, if any. Can be nullptr if the ProxyResolver has
372   // no need for DHCP PAC script fetching.
373   std::unique_ptr<DhcpPacFileFetcher> dhcp_pac_file_fetcher_;
374 
375   // Helper to download the PAC script (wpad + custom) and apply fallback rules.
376   //
377   // Note that the declaration is important here: |pac_file_fetcher_| and
378   // |proxy_resolver_| must outlive |init_proxy_resolver_|.
379   std::unique_ptr<InitProxyResolver> init_proxy_resolver_;
380 
381   // Helper to poll the PAC script for changes.
382   std::unique_ptr<PacFileDeciderPoller> script_poller_;
383 
384   State current_state_ = STATE_NONE;
385 
386   // Either OK or an ERR_* value indicating that a permanent error (e.g.
387   // failed to fetch the PAC script) prevents proxy resolution.
388   int permanent_error_ = OK;
389 
390   // This is the log where any events generated by |init_proxy_resolver_| are
391   // sent to.
392   raw_ptr<NetLog> net_log_;
393 
394   // The earliest time at which we should run any proxy auto-config. (Used to
395   // stall re-configuration following an IP address change).
396   base::TimeTicks stall_proxy_autoconfig_until_;
397 
398   // The amount of time to stall requests following IP address changes.
399   base::TimeDelta stall_proxy_auto_config_delay_;
400 
401   // Whether child PacFileDeciders should use QuickCheck
402   bool quick_check_enabled_;
403 
404   THREAD_CHECKER(thread_checker_);
405 
406   raw_ptr<ProxyDelegate> proxy_delegate_ = nullptr;
407 
408   // Flag used by |SetReady()| to check if |this| has been deleted by a
409   // synchronous callback.
410   base::WeakPtrFactory<ConfiguredProxyResolutionService> weak_ptr_factory_{
411       this};
412 };
413 
414 }  // namespace net
415 
416 #endif  // NET_PROXY_RESOLUTION_CONFIGURED_PROXY_RESOLUTION_SERVICE_H_
417