| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_PROXY_RESOLUTION_PAC_FILE_DECIDER_H_ |
| #define NET_PROXY_RESOLUTION_PAC_FILE_DECIDER_H_ |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "base/values.h" |
| #include "net/base/completion_once_callback.h" |
| #include "net/base/net_export.h" |
| #include "net/dns/host_resolver.h" |
| #include "net/log/net_log_with_source.h" |
| #include "net/proxy_resolution/proxy_config_with_annotation.h" |
| #include "net/proxy_resolution/proxy_resolver.h" |
| #include "url/gurl.h" |
| |
| namespace net { |
| |
| class DhcpPacFileFetcher; |
| class NetLog; |
| class ProxyResolver; |
| class PacFileFetcher; |
| |
| // Structure that encapsulates the result a PacFileData along with an |
| // indication of its origin: was it obtained implicitly from auto-detect, |
| // or was it read from a more explicitly configured URL. |
| // |
| // Note that |!from_auto_detect| does NOT imply the script was securely |
| // delivered. Most commonly PAC scripts are configured from http:// URLs, |
| // both for auto-detect and not. |
| struct NET_EXPORT_PRIVATE PacFileDataWithSource { |
| PacFileDataWithSource(); |
| PacFileDataWithSource(const PacFileDataWithSource&); |
| ~PacFileDataWithSource(); |
| |
| PacFileDataWithSource& operator=(const PacFileDataWithSource&); |
| |
| scoped_refptr<PacFileData> data; |
| bool from_auto_detect = false; |
| }; |
| |
| // PacFileDecider is a helper class used by ConfiguredProxyResolutionService to |
| // determine which PAC script to use given our proxy configuration. |
| // |
| // This involves trying to use PAC scripts in this order: |
| // |
| // (1) WPAD (DHCP) if auto-detect is on. |
| // (2) WPAD (DNS) if auto-detect is on. |
| // (3) Custom PAC script if a URL was given. |
| // |
| // If no PAC script was successfully selected, then it fails with either a |
| // network error, or PAC_SCRIPT_FAILED (indicating it did not pass our |
| // validation). |
| // |
| // On successful completion, the fetched PAC script data can be accessed using |
| // script_data(). |
| // |
| // Deleting PacFileDecider while Init() is in progress, will |
| // cancel the request. |
| // |
| class NET_EXPORT_PRIVATE PacFileDecider { |
| public: |
| // |pac_file_fetcher|, |dhcp_pac_file_fetcher| and |
| // |net_log| must remain valid for the lifespan of PacFileDecider. |
| PacFileDecider(PacFileFetcher* pac_file_fetcher, |
| DhcpPacFileFetcher* dhcp_pac_file_fetcher, |
| NetLog* net_log); |
| |
| PacFileDecider(const PacFileDecider&) = delete; |
| PacFileDecider& operator=(const PacFileDecider&) = delete; |
| |
| // Aborts any in-progress request. |
| ~PacFileDecider(); |
| |
| // Evaluates the effective proxy settings for |config|, and downloads the |
| // associated PAC script. |
| // If |wait_delay| is positive, the initialization will pause for this |
| // amount of time before getting started. |
| // On successful completion, the "effective" proxy settings we ended up |
| // deciding on will be available vial the effective_settings() accessor. |
| // Note that this may differ from |config| since we will have stripped any |
| // manual settings, and decided whether to use auto-detect or the custom PAC |
| // URL. Finally, if auto-detect was used we may now have resolved that to a |
| // specific script URL. |
| int Start(const ProxyConfigWithAnnotation& config, |
| const base::TimeDelta wait_delay, |
| bool fetch_pac_bytes, |
| CompletionOnceCallback callback); |
| |
| // Shuts down any in-progress DNS requests, and cancels any ScriptFetcher |
| // requests. Does not call OnShutdown() on the [Dhcp]PacFileFetcher. Any |
| // pending callback will not be invoked. |
| void OnShutdown(); |
| |
| const ProxyConfigWithAnnotation& effective_config() const; |
| |
| const PacFileDataWithSource& script_data() const; |
| |
| void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; } |
| |
| bool quick_check_enabled() const { return quick_check_enabled_; } |
| |
| private: |
| // Represents the sources from which we can get PAC files; two types of |
| // auto-detect or a custom URL. |
| struct PacSource { |
| enum Type { WPAD_DHCP, WPAD_DNS, CUSTOM }; |
| |
| PacSource(Type type, const GURL& url) : type(type), url(url) {} |
| |
| // Returns a Value representing the PacSource. |effective_pac_url| is the |
| // URL derived from information contained in |
| // |this|, if Type is not WPAD_DHCP. |
| base::Value::Dict NetLogParams(const GURL& effective_pac_url) const; |
| |
| Type type; |
| GURL url; // Empty unless |type == PAC_SOURCE_CUSTOM|. |
| }; |
| |
| typedef std::vector<PacSource> PacSourceList; |
| |
| enum State { |
| STATE_NONE, |
| STATE_WAIT, |
| STATE_WAIT_COMPLETE, |
| STATE_QUICK_CHECK, |
| STATE_QUICK_CHECK_COMPLETE, |
| STATE_FETCH_PAC_SCRIPT, |
| STATE_FETCH_PAC_SCRIPT_COMPLETE, |
| STATE_VERIFY_PAC_SCRIPT, |
| STATE_VERIFY_PAC_SCRIPT_COMPLETE, |
| }; |
| |
| // Returns ordered list of PAC urls to try for |config|. |
| PacSourceList BuildPacSourcesFallbackList(const ProxyConfig& config) const; |
| |
| void OnIOCompletion(int result); |
| int DoLoop(int result); |
| |
| int DoWait(); |
| int DoWaitComplete(int result); |
| |
| int DoQuickCheck(); |
| int DoQuickCheckComplete(int result); |
| |
| int DoFetchPacScript(); |
| int DoFetchPacScriptComplete(int result); |
| |
| int DoVerifyPacScript(); |
| int DoVerifyPacScriptComplete(int result); |
| |
| // Tries restarting using the next fallback PAC URL: |
| // |pac_sources_[++current_pac_source_index]|. |
| // Returns OK and rewinds the state machine when there |
| // is something to try, otherwise returns |error|. |
| int TryToFallbackPacSource(int error); |
| |
| // Gets the initial state (we skip fetching when the |
| // ProxyResolver doesn't |expect_pac_bytes()|. |
| State GetStartState() const; |
| |
| void DetermineURL(const PacSource& pac_source, GURL* effective_pac_url); |
| |
| // Returns the current PAC URL we are fetching/testing. |
| const PacSource& current_pac_source() const; |
| |
| void OnWaitTimerFired(); |
| void DidComplete(); |
| void Cancel(); |
| |
| raw_ptr<PacFileFetcher> pac_file_fetcher_; |
| raw_ptr<DhcpPacFileFetcher> dhcp_pac_file_fetcher_; |
| |
| CompletionOnceCallback callback_; |
| |
| size_t current_pac_source_index_ = 0u; |
| |
| // Filled when the PAC script fetch completes. |
| std::u16string pac_script_; |
| |
| // Flag indicating whether the caller requested a mandatory PAC script |
| // (i.e. fallback to direct connections are prohibited). |
| bool pac_mandatory_ = false; |
| |
| // Whether we have an existing custom PAC URL. |
| bool have_custom_pac_url_; |
| |
| PacSourceList pac_sources_; |
| State next_state_ = STATE_NONE; |
| |
| NetLogWithSource net_log_; |
| |
| bool fetch_pac_bytes_ = false; |
| |
| base::TimeDelta wait_delay_; |
| base::OneShotTimer wait_timer_; |
| |
| net::MutableNetworkTrafficAnnotationTag traffic_annotation_; |
| |
| // Whether to do DNS quick check |
| bool quick_check_enabled_ = true; |
| |
| // Results. |
| ProxyConfigWithAnnotation effective_config_; |
| PacFileDataWithSource script_data_; |
| |
| std::unique_ptr<HostResolver::ResolveHostRequest> resolve_request_; |
| |
| base::OneShotTimer quick_check_timer_; |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_PROXY_RESOLUTION_PAC_FILE_DECIDER_H_ |