|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef NET_PROXY_PAC_FILE_DECIDER_H_ | 
|  | #define NET_PROXY_PAC_FILE_DECIDER_H_ | 
|  |  | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/strings/string16.h" | 
|  | #include "base/time/time.h" | 
|  | #include "base/timer/timer.h" | 
|  | #include "net/base/address_list.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 "starboard/types.h" | 
|  | #include "url/gurl.h" | 
|  |  | 
|  | namespace base { | 
|  | class Value; | 
|  | } | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | class DhcpPacFileFetcher; | 
|  | class NetLog; | 
|  | class NetLogCaptureMode; | 
|  | class ProxyResolver; | 
|  | class PacFileFetcher; | 
|  |  | 
|  | // PacFileDecider is a helper class used by ProxyResolutionService 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); | 
|  |  | 
|  | // 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. | 
|  | void OnShutdown(); | 
|  |  | 
|  | const ProxyConfigWithAnnotation& effective_config() const; | 
|  |  | 
|  | const scoped_refptr<PacFileData>& 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| must | 
|  | // be non-NULL and point to the URL derived from information contained in | 
|  | // |this|, if Type is not WPAD_DHCP. | 
|  | std::unique_ptr<base::Value> NetLogCallback( | 
|  | const GURL* effective_pac_url, | 
|  | NetLogCaptureMode capture_mode) 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(); | 
|  |  | 
|  | PacFileFetcher* pac_file_fetcher_; | 
|  | DhcpPacFileFetcher* dhcp_pac_file_fetcher_; | 
|  |  | 
|  | CompletionOnceCallback callback_; | 
|  |  | 
|  | size_t current_pac_source_index_; | 
|  |  | 
|  | // Filled when the PAC script fetch completes. | 
|  | base::string16 pac_script_; | 
|  |  | 
|  | // Flag indicating whether the caller requested a mandatory PAC script | 
|  | // (i.e. fallback to direct connections are prohibited). | 
|  | bool pac_mandatory_; | 
|  |  | 
|  | // Whether we have an existing custom PAC URL. | 
|  | bool have_custom_pac_url_; | 
|  |  | 
|  | PacSourceList pac_sources_; | 
|  | State next_state_; | 
|  |  | 
|  | NetLogWithSource net_log_; | 
|  |  | 
|  | bool fetch_pac_bytes_; | 
|  |  | 
|  | base::TimeDelta wait_delay_; | 
|  | base::OneShotTimer wait_timer_; | 
|  |  | 
|  | net::MutableNetworkTrafficAnnotationTag traffic_annotation_; | 
|  |  | 
|  | // Whether to do DNS quick check | 
|  | bool quick_check_enabled_; | 
|  |  | 
|  | // Results. | 
|  | ProxyConfigWithAnnotation effective_config_; | 
|  | scoped_refptr<PacFileData> script_data_; | 
|  |  | 
|  | AddressList wpad_addresses_; | 
|  | base::OneShotTimer quick_check_timer_; | 
|  | std::unique_ptr<HostResolver::Request> request_; | 
|  | base::Time quick_check_start_time_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(PacFileDecider); | 
|  | }; | 
|  |  | 
|  | }  // namespace net | 
|  |  | 
|  | #endif  // NET_PROXY_PAC_FILE_DECIDER_H_ |