configured_proxy_resolution_service.cc 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489
  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. #include "net/proxy_resolution/configured_proxy_resolution_service.h"
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <memory>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/callback_helpers.h"
  11. #include "base/compiler_specific.h"
  12. #include "base/location.h"
  13. #include "base/logging.h"
  14. #include "base/memory/raw_ptr.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/metrics/histogram_macros.h"
  17. #include "base/strings/string_util.h"
  18. #include "base/task/single_thread_task_runner.h"
  19. #include "base/threading/thread_task_runner_handle.h"
  20. #include "base/time/time.h"
  21. #include "base/values.h"
  22. #include "build/build_config.h"
  23. #include "build/chromeos_buildflags.h"
  24. #include "net/base/net_errors.h"
  25. #include "net/base/net_info_source_list.h"
  26. #include "net/base/network_isolation_key.h"
  27. #include "net/base/proxy_delegate.h"
  28. #include "net/base/proxy_server.h"
  29. #include "net/base/proxy_string_util.h"
  30. #include "net/base/url_util.h"
  31. #include "net/log/net_log.h"
  32. #include "net/log/net_log_event_type.h"
  33. #include "net/log/net_log_util.h"
  34. #include "net/log/net_log_with_source.h"
  35. #include "net/proxy_resolution/configured_proxy_resolution_request.h"
  36. #include "net/proxy_resolution/dhcp_pac_file_fetcher.h"
  37. #include "net/proxy_resolution/multi_threaded_proxy_resolver.h"
  38. #include "net/proxy_resolution/pac_file_decider.h"
  39. #include "net/proxy_resolution/pac_file_fetcher.h"
  40. #include "net/proxy_resolution/proxy_config_service_fixed.h"
  41. #include "net/proxy_resolution/proxy_resolver_factory.h"
  42. #include "net/url_request/url_request_context.h"
  43. #if BUILDFLAG(IS_WIN)
  44. #include "net/proxy_resolution/win/proxy_resolver_winhttp.h"
  45. #elif BUILDFLAG(IS_IOS)
  46. #include "net/proxy_resolution/proxy_resolver_mac.h"
  47. #elif BUILDFLAG(IS_MAC)
  48. #include "net/proxy_resolution/proxy_resolver_mac.h"
  49. #endif
  50. using base::TimeTicks;
  51. namespace net {
  52. namespace {
  53. const size_t kDefaultNumPacThreads = 4;
  54. // When the IP address changes we don't immediately re-run proxy auto-config.
  55. // Instead, we wait for |kDelayAfterNetworkChangesMs| before
  56. // attempting to re-valuate proxy auto-config.
  57. //
  58. // During this time window, any resolve requests sent to the
  59. // ConfiguredProxyResolutionService will be queued. Once we have waited the
  60. // required amount of them, the proxy auto-config step will be run, and the
  61. // queued requests resumed.
  62. //
  63. // The reason we play this game is that our signal for detecting network
  64. // changes (NetworkChangeNotifier) may fire *before* the system's networking
  65. // dependencies are fully configured. This is a problem since it means if
  66. // we were to run proxy auto-config right away, it could fail due to spurious
  67. // DNS failures. (see http://crbug.com/50779 for more details.)
  68. //
  69. // By adding the wait window, we give things a better chance to get properly
  70. // set up. Network failures can happen at any time though, so we additionally
  71. // poll the PAC script for changes, which will allow us to recover from these
  72. // sorts of problems.
  73. const int64_t kDelayAfterNetworkChangesMs = 2000;
  74. // This is the default policy for polling the PAC script.
  75. //
  76. // In response to a failure, the poll intervals are:
  77. // 0: 8 seconds (scheduled on timer)
  78. // 1: 32 seconds
  79. // 2: 2 minutes
  80. // 3+: 4 hours
  81. //
  82. // In response to a success, the poll intervals are:
  83. // 0+: 12 hours
  84. //
  85. // Only the 8 second poll is scheduled on a timer, the rest happen in response
  86. // to network activity (and hence will take longer than the written time).
  87. //
  88. // Explanation for these values:
  89. //
  90. // TODO(eroman): These values are somewhat arbitrary, and need to be tuned
  91. // using some histograms data. Trying to be conservative so as not to break
  92. // existing setups when deployed. A simple exponential retry scheme would be
  93. // more elegant, but places more load on server.
  94. //
  95. // The motivation for trying quickly after failures (8 seconds) is to recover
  96. // from spurious network failures, which are common after the IP address has
  97. // just changed (like DNS failing to resolve). The next 32 second boundary is
  98. // to try and catch other VPN weirdness which anecdotally I have seen take
  99. // 10+ seconds for some users.
  100. //
  101. // The motivation for re-trying after a success is to check for possible
  102. // content changes to the script, or to the WPAD auto-discovery results. We are
  103. // not very aggressive with these checks so as to minimize the risk of
  104. // overloading existing PAC setups. Moreover it is unlikely that PAC scripts
  105. // change very frequently in existing setups. More research is needed to
  106. // motivate what safe values are here, and what other user agents do.
  107. //
  108. // Comparison to other browsers:
  109. //
  110. // In Firefox the PAC URL is re-tried on failures according to
  111. // network.proxy.autoconfig_retry_interval_min and
  112. // network.proxy.autoconfig_retry_interval_max. The defaults are 5 seconds and
  113. // 5 minutes respectively. It doubles the interval at each attempt.
  114. //
  115. // TODO(eroman): Figure out what Internet Explorer does.
  116. class DefaultPollPolicy
  117. : public ConfiguredProxyResolutionService::PacPollPolicy {
  118. public:
  119. DefaultPollPolicy() = default;
  120. DefaultPollPolicy(const DefaultPollPolicy&) = delete;
  121. DefaultPollPolicy& operator=(const DefaultPollPolicy&) = delete;
  122. Mode GetNextDelay(int initial_error,
  123. base::TimeDelta current_delay,
  124. base::TimeDelta* next_delay) const override {
  125. if (initial_error != OK) {
  126. // Re-try policy for failures.
  127. const int kDelay1Seconds = 8;
  128. const int kDelay2Seconds = 32;
  129. const int kDelay3Seconds = 2 * 60; // 2 minutes
  130. const int kDelay4Seconds = 4 * 60 * 60; // 4 Hours
  131. // Initial poll.
  132. if (current_delay.is_negative()) {
  133. *next_delay = base::Seconds(kDelay1Seconds);
  134. return MODE_USE_TIMER;
  135. }
  136. switch (current_delay.InSeconds()) {
  137. case kDelay1Seconds:
  138. *next_delay = base::Seconds(kDelay2Seconds);
  139. return MODE_START_AFTER_ACTIVITY;
  140. case kDelay2Seconds:
  141. *next_delay = base::Seconds(kDelay3Seconds);
  142. return MODE_START_AFTER_ACTIVITY;
  143. default:
  144. *next_delay = base::Seconds(kDelay4Seconds);
  145. return MODE_START_AFTER_ACTIVITY;
  146. }
  147. } else {
  148. // Re-try policy for succeses.
  149. *next_delay = base::Hours(12);
  150. return MODE_START_AFTER_ACTIVITY;
  151. }
  152. }
  153. };
  154. // Config getter that always returns direct settings.
  155. class ProxyConfigServiceDirect : public ProxyConfigService {
  156. public:
  157. // ProxyConfigService implementation:
  158. void AddObserver(Observer* observer) override {}
  159. void RemoveObserver(Observer* observer) override {}
  160. ConfigAvailability GetLatestProxyConfig(
  161. ProxyConfigWithAnnotation* config) override {
  162. *config = ProxyConfigWithAnnotation::CreateDirect();
  163. return CONFIG_VALID;
  164. }
  165. };
  166. // Proxy resolver that fails every time.
  167. class ProxyResolverNull : public ProxyResolver {
  168. public:
  169. ProxyResolverNull() = default;
  170. // ProxyResolver implementation.
  171. int GetProxyForURL(const GURL& url,
  172. const NetworkIsolationKey& network_isolation_key,
  173. ProxyInfo* results,
  174. CompletionOnceCallback callback,
  175. std::unique_ptr<Request>* request,
  176. const NetLogWithSource& net_log) override {
  177. return ERR_NOT_IMPLEMENTED;
  178. }
  179. };
  180. // ProxyResolver that simulates a PAC script which returns
  181. // |pac_string| for every single URL.
  182. class ProxyResolverFromPacString : public ProxyResolver {
  183. public:
  184. explicit ProxyResolverFromPacString(const std::string& pac_string)
  185. : pac_string_(pac_string) {}
  186. int GetProxyForURL(const GURL& url,
  187. const NetworkIsolationKey& network_isolation_key,
  188. ProxyInfo* results,
  189. CompletionOnceCallback callback,
  190. std::unique_ptr<Request>* request,
  191. const NetLogWithSource& net_log) override {
  192. results->UsePacString(pac_string_);
  193. return OK;
  194. }
  195. private:
  196. const std::string pac_string_;
  197. };
  198. // Creates ProxyResolvers using a platform-specific implementation.
  199. class ProxyResolverFactoryForSystem : public MultiThreadedProxyResolverFactory {
  200. public:
  201. explicit ProxyResolverFactoryForSystem(size_t max_num_threads)
  202. : MultiThreadedProxyResolverFactory(max_num_threads,
  203. false /*expects_pac_bytes*/) {}
  204. ProxyResolverFactoryForSystem(const ProxyResolverFactoryForSystem&) = delete;
  205. ProxyResolverFactoryForSystem& operator=(
  206. const ProxyResolverFactoryForSystem&) = delete;
  207. std::unique_ptr<ProxyResolverFactory> CreateProxyResolverFactory() override {
  208. #if BUILDFLAG(IS_WIN)
  209. return std::make_unique<ProxyResolverFactoryWinHttp>();
  210. #elif BUILDFLAG(IS_APPLE)
  211. return std::make_unique<ProxyResolverFactoryMac>();
  212. #else
  213. NOTREACHED();
  214. return nullptr;
  215. #endif
  216. }
  217. static bool IsSupported() {
  218. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
  219. return true;
  220. #else
  221. return false;
  222. #endif
  223. }
  224. };
  225. class ProxyResolverFactoryForNullResolver : public ProxyResolverFactory {
  226. public:
  227. ProxyResolverFactoryForNullResolver() : ProxyResolverFactory(false) {}
  228. ProxyResolverFactoryForNullResolver(
  229. const ProxyResolverFactoryForNullResolver&) = delete;
  230. ProxyResolverFactoryForNullResolver& operator=(
  231. const ProxyResolverFactoryForNullResolver&) = delete;
  232. // ProxyResolverFactory overrides.
  233. int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
  234. std::unique_ptr<ProxyResolver>* resolver,
  235. CompletionOnceCallback callback,
  236. std::unique_ptr<Request>* request) override {
  237. *resolver = std::make_unique<ProxyResolverNull>();
  238. return OK;
  239. }
  240. };
  241. class ProxyResolverFactoryForPacResult : public ProxyResolverFactory {
  242. public:
  243. explicit ProxyResolverFactoryForPacResult(const std::string& pac_string)
  244. : ProxyResolverFactory(false), pac_string_(pac_string) {}
  245. ProxyResolverFactoryForPacResult(const ProxyResolverFactoryForPacResult&) =
  246. delete;
  247. ProxyResolverFactoryForPacResult& operator=(
  248. const ProxyResolverFactoryForPacResult&) = delete;
  249. // ProxyResolverFactory override.
  250. int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
  251. std::unique_ptr<ProxyResolver>* resolver,
  252. CompletionOnceCallback callback,
  253. std::unique_ptr<Request>* request) override {
  254. *resolver = std::make_unique<ProxyResolverFromPacString>(pac_string_);
  255. return OK;
  256. }
  257. private:
  258. const std::string pac_string_;
  259. };
  260. // Returns NetLog parameters describing a proxy configuration change.
  261. base::Value NetLogProxyConfigChangedParams(
  262. const absl::optional<ProxyConfigWithAnnotation>* old_config,
  263. const ProxyConfigWithAnnotation* new_config) {
  264. base::Value::Dict dict;
  265. // The "old_config" is optional -- the first notification will not have
  266. // any "previous" configuration.
  267. if (old_config->has_value())
  268. dict.Set("old_config", (*old_config)->value().ToValue());
  269. dict.Set("new_config", new_config->value().ToValue());
  270. return base::Value(std::move(dict));
  271. }
  272. base::Value NetLogBadProxyListParams(const ProxyRetryInfoMap* retry_info) {
  273. base::Value::Dict dict;
  274. base::Value list(base::Value::Type::LIST);
  275. for (const auto& retry_info_pair : *retry_info)
  276. list.Append(retry_info_pair.first);
  277. dict.Set("bad_proxy_list", std::move(list));
  278. return base::Value(std::move(dict));
  279. }
  280. // Returns NetLog parameters on a successful proxy resolution.
  281. base::Value NetLogFinishedResolvingProxyParams(const ProxyInfo* result) {
  282. base::Value::Dict dict;
  283. dict.Set("pac_string", result->ToPacString());
  284. return base::Value(std::move(dict));
  285. }
  286. // Returns a sanitized copy of |url| which is safe to pass on to a PAC script.
  287. //
  288. // PAC scripts are modelled as being controllable by a network-present
  289. // attacker (since such an attacker can influence the outcome of proxy
  290. // auto-discovery, or modify the contents of insecurely delivered PAC scripts).
  291. //
  292. // As such, it is important that the full path/query of https:// URLs not be
  293. // sent to PAC scripts, since that would give an attacker access to data that
  294. // is ordinarily protected by TLS.
  295. //
  296. // Obscuring the path for http:// URLs isn't being done since it doesn't matter
  297. // for security (attacker can already route traffic through their HTTP proxy
  298. // and see the full URL for http:// requests).
  299. //
  300. // TODO(https://crbug.com/882536): Use the same stripping for insecure URL
  301. // schemes.
  302. GURL SanitizeUrl(const GURL& url) {
  303. DCHECK(url.is_valid());
  304. GURL::Replacements replacements;
  305. replacements.ClearUsername();
  306. replacements.ClearPassword();
  307. replacements.ClearRef();
  308. if (url.SchemeIsCryptographic()) {
  309. replacements.ClearPath();
  310. replacements.ClearQuery();
  311. }
  312. return url.ReplaceComponents(replacements);
  313. }
  314. } // namespace
  315. // ConfiguredProxyResolutionService::InitProxyResolver
  316. // ----------------------------------
  317. // This glues together two asynchronous steps:
  318. // (1) PacFileDecider -- try to fetch/validate a sequence of PAC scripts
  319. // to figure out what we should configure against.
  320. // (2) Feed the fetched PAC script into the ProxyResolver.
  321. //
  322. // InitProxyResolver is a single-use class which encapsulates cancellation as
  323. // part of its destructor. Start() or StartSkipDecider() should be called just
  324. // once. The instance can be destroyed at any time, and the request will be
  325. // cancelled.
  326. class ConfiguredProxyResolutionService::InitProxyResolver {
  327. public:
  328. InitProxyResolver() = default;
  329. InitProxyResolver(const InitProxyResolver&) = delete;
  330. InitProxyResolver& operator=(const InitProxyResolver&) = delete;
  331. // Note that the destruction of PacFileDecider will automatically cancel
  332. // any outstanding work.
  333. ~InitProxyResolver() = default;
  334. // Begins initializing the proxy resolver; calls |callback| when done. A
  335. // ProxyResolver instance will be created using |proxy_resolver_factory| and
  336. // assigned to |*proxy_resolver| if the final result is OK.
  337. int Start(std::unique_ptr<ProxyResolver>* proxy_resolver,
  338. ProxyResolverFactory* proxy_resolver_factory,
  339. PacFileFetcher* pac_file_fetcher,
  340. DhcpPacFileFetcher* dhcp_pac_file_fetcher,
  341. NetLog* net_log,
  342. const ProxyConfigWithAnnotation& config,
  343. base::TimeDelta wait_delay,
  344. CompletionOnceCallback callback) {
  345. DCHECK_EQ(State::kNone, next_state_);
  346. proxy_resolver_ = proxy_resolver;
  347. proxy_resolver_factory_ = proxy_resolver_factory;
  348. decider_ = std::make_unique<PacFileDecider>(pac_file_fetcher,
  349. dhcp_pac_file_fetcher, net_log);
  350. decider_->set_quick_check_enabled(quick_check_enabled_);
  351. config_ = config;
  352. wait_delay_ = wait_delay;
  353. callback_ = std::move(callback);
  354. next_state_ = State::kDecidePacFile;
  355. return DoLoop(OK);
  356. }
  357. // Similar to Start(), however it skips the PacFileDecider stage. Instead
  358. // |effective_config|, |decider_result| and |script_data| will be used as the
  359. // inputs for initializing the ProxyResolver. A ProxyResolver instance will
  360. // be created using |proxy_resolver_factory| and assigned to
  361. // |*proxy_resolver| if the final result is OK.
  362. int StartSkipDecider(std::unique_ptr<ProxyResolver>* proxy_resolver,
  363. ProxyResolverFactory* proxy_resolver_factory,
  364. const ProxyConfigWithAnnotation& effective_config,
  365. int decider_result,
  366. const PacFileDataWithSource& script_data,
  367. CompletionOnceCallback callback) {
  368. DCHECK_EQ(State::kNone, next_state_);
  369. proxy_resolver_ = proxy_resolver;
  370. proxy_resolver_factory_ = proxy_resolver_factory;
  371. effective_config_ = effective_config;
  372. script_data_ = script_data;
  373. callback_ = std::move(callback);
  374. if (decider_result != OK)
  375. return decider_result;
  376. next_state_ = State::kCreateResolver;
  377. return DoLoop(OK);
  378. }
  379. // Returns the proxy configuration that was selected by PacFileDecider.
  380. // Should only be called upon completion of the initialization.
  381. const ProxyConfigWithAnnotation& effective_config() const {
  382. DCHECK_EQ(State::kNone, next_state_);
  383. return effective_config_;
  384. }
  385. // Returns the PAC script data that was selected by PacFileDecider.
  386. // Should only be called upon completion of the initialization.
  387. const PacFileDataWithSource& script_data() {
  388. DCHECK_EQ(State::kNone, next_state_);
  389. return script_data_;
  390. }
  391. LoadState GetLoadState() const {
  392. if (next_state_ == State::kDecidePacFileComplete) {
  393. // In addition to downloading, this state may also include the stall time
  394. // after network change events (kDelayAfterNetworkChangesMs).
  395. return LOAD_STATE_DOWNLOADING_PAC_FILE;
  396. }
  397. return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
  398. }
  399. // This must be called before the HostResolver is torn down.
  400. void OnShutdown() {
  401. if (decider_)
  402. decider_->OnShutdown();
  403. }
  404. void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
  405. bool quick_check_enabled() const { return quick_check_enabled_; }
  406. private:
  407. enum class State {
  408. kNone,
  409. kDecidePacFile,
  410. kDecidePacFileComplete,
  411. kCreateResolver,
  412. kCreateResolverComplete,
  413. };
  414. int DoLoop(int result) {
  415. DCHECK_NE(next_state_, State::kNone);
  416. int rv = result;
  417. do {
  418. State state = next_state_;
  419. next_state_ = State::kNone;
  420. switch (state) {
  421. case State::kDecidePacFile:
  422. DCHECK_EQ(OK, rv);
  423. rv = DoDecidePacFile();
  424. break;
  425. case State::kDecidePacFileComplete:
  426. rv = DoDecidePacFileComplete(rv);
  427. break;
  428. case State::kCreateResolver:
  429. DCHECK_EQ(OK, rv);
  430. rv = DoCreateResolver();
  431. break;
  432. case State::kCreateResolverComplete:
  433. rv = DoCreateResolverComplete(rv);
  434. break;
  435. default:
  436. NOTREACHED() << "bad state: " << static_cast<int>(state);
  437. rv = ERR_UNEXPECTED;
  438. break;
  439. }
  440. } while (rv != ERR_IO_PENDING && next_state_ != State::kNone);
  441. return rv;
  442. }
  443. int DoDecidePacFile() {
  444. next_state_ = State::kDecidePacFileComplete;
  445. return decider_->Start(config_, wait_delay_,
  446. proxy_resolver_factory_->expects_pac_bytes(),
  447. base::BindOnce(&InitProxyResolver::OnIOCompletion,
  448. base::Unretained(this)));
  449. }
  450. int DoDecidePacFileComplete(int result) {
  451. if (result != OK)
  452. return result;
  453. effective_config_ = decider_->effective_config();
  454. script_data_ = decider_->script_data();
  455. next_state_ = State::kCreateResolver;
  456. return OK;
  457. }
  458. int DoCreateResolver() {
  459. DCHECK(script_data_.data);
  460. // TODO(eroman): Should log this latency to the NetLog.
  461. next_state_ = State::kCreateResolverComplete;
  462. return proxy_resolver_factory_->CreateProxyResolver(
  463. script_data_.data, proxy_resolver_,
  464. base::BindOnce(&InitProxyResolver::OnIOCompletion,
  465. base::Unretained(this)),
  466. &create_resolver_request_);
  467. }
  468. int DoCreateResolverComplete(int result) {
  469. if (result != OK)
  470. proxy_resolver_->reset();
  471. return result;
  472. }
  473. void OnIOCompletion(int result) {
  474. DCHECK_NE(State::kNone, next_state_);
  475. int rv = DoLoop(result);
  476. if (rv != ERR_IO_PENDING)
  477. std::move(callback_).Run(result);
  478. }
  479. ProxyConfigWithAnnotation config_;
  480. ProxyConfigWithAnnotation effective_config_;
  481. PacFileDataWithSource script_data_;
  482. base::TimeDelta wait_delay_;
  483. std::unique_ptr<PacFileDecider> decider_;
  484. raw_ptr<ProxyResolverFactory> proxy_resolver_factory_ = nullptr;
  485. std::unique_ptr<ProxyResolverFactory::Request> create_resolver_request_;
  486. raw_ptr<std::unique_ptr<ProxyResolver>> proxy_resolver_ = nullptr;
  487. CompletionOnceCallback callback_;
  488. State next_state_ = State::kNone;
  489. bool quick_check_enabled_ = true;
  490. };
  491. // ConfiguredProxyResolutionService::PacFileDeciderPoller
  492. // ---------------------------
  493. // This helper class encapsulates the logic to schedule and run periodic
  494. // background checks to see if the PAC script (or effective proxy configuration)
  495. // has changed. If a change is detected, then the caller will be notified via
  496. // the ChangeCallback.
  497. class ConfiguredProxyResolutionService::PacFileDeciderPoller {
  498. public:
  499. typedef base::RepeatingCallback<
  500. void(int, const PacFileDataWithSource&, const ProxyConfigWithAnnotation&)>
  501. ChangeCallback;
  502. // Builds a poller helper, and starts polling for updates. Whenever a change
  503. // is observed, |callback| will be invoked with the details.
  504. //
  505. // |config| specifies the (unresolved) proxy configuration to poll.
  506. // |proxy_resolver_expects_pac_bytes| the type of proxy resolver we expect
  507. // to use the resulting script data with
  508. // (so it can choose the right format).
  509. // |pac_file_fetcher| this pointer must remain alive throughout our
  510. // lifetime. It is the dependency that will be used
  511. // for downloading PAC files.
  512. // |dhcp_pac_file_fetcher| similar to |pac_file_fetcher|, but for
  513. // he DHCP dependency.
  514. // |init_net_error| This is the initial network error (possibly success)
  515. // encountered by the first PAC fetch attempt. We use it
  516. // to schedule updates more aggressively if the initial
  517. // fetch resulted in an error.
  518. // |init_script_data| the initial script data from the PAC fetch attempt.
  519. // This is the baseline used to determine when the
  520. // script's contents have changed.
  521. // |net_log| the NetLog to log progress into.
  522. PacFileDeciderPoller(ChangeCallback callback,
  523. const ProxyConfigWithAnnotation& config,
  524. bool proxy_resolver_expects_pac_bytes,
  525. PacFileFetcher* pac_file_fetcher,
  526. DhcpPacFileFetcher* dhcp_pac_file_fetcher,
  527. int init_net_error,
  528. const PacFileDataWithSource& init_script_data,
  529. NetLog* net_log)
  530. : change_callback_(callback),
  531. config_(config),
  532. proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
  533. pac_file_fetcher_(pac_file_fetcher),
  534. dhcp_pac_file_fetcher_(dhcp_pac_file_fetcher),
  535. last_error_(init_net_error),
  536. last_script_data_(init_script_data),
  537. last_poll_time_(TimeTicks::Now()),
  538. net_log_(net_log) {
  539. // Set the initial poll delay.
  540. next_poll_mode_ = poll_policy()->GetNextDelay(
  541. last_error_, base::Seconds(-1), &next_poll_delay_);
  542. TryToStartNextPoll(false);
  543. }
  544. PacFileDeciderPoller(const PacFileDeciderPoller&) = delete;
  545. PacFileDeciderPoller& operator=(const PacFileDeciderPoller&) = delete;
  546. void OnLazyPoll() {
  547. // We have just been notified of network activity. Use this opportunity to
  548. // see if we can start our next poll.
  549. TryToStartNextPoll(true);
  550. }
  551. static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
  552. const PacPollPolicy* prev = poll_policy_;
  553. poll_policy_ = policy;
  554. return prev;
  555. }
  556. void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
  557. bool quick_check_enabled() const { return quick_check_enabled_; }
  558. private:
  559. // Returns the effective poll policy (the one injected by unit-tests, or the
  560. // default).
  561. const PacPollPolicy* poll_policy() {
  562. if (poll_policy_)
  563. return poll_policy_;
  564. return &default_poll_policy_;
  565. }
  566. void StartPollTimer() {
  567. DCHECK(!decider_.get());
  568. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  569. FROM_HERE,
  570. base::BindOnce(&PacFileDeciderPoller::DoPoll,
  571. weak_factory_.GetWeakPtr()),
  572. next_poll_delay_);
  573. }
  574. void TryToStartNextPoll(bool triggered_by_activity) {
  575. switch (next_poll_mode_) {
  576. case PacPollPolicy::MODE_USE_TIMER:
  577. if (!triggered_by_activity)
  578. StartPollTimer();
  579. break;
  580. case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
  581. if (triggered_by_activity && !decider_.get()) {
  582. base::TimeDelta elapsed_time = TimeTicks::Now() - last_poll_time_;
  583. if (elapsed_time >= next_poll_delay_)
  584. DoPoll();
  585. }
  586. break;
  587. }
  588. }
  589. void DoPoll() {
  590. last_poll_time_ = TimeTicks::Now();
  591. // Start the PAC file decider to see if anything has changed.
  592. decider_ = std::make_unique<PacFileDecider>(
  593. pac_file_fetcher_, dhcp_pac_file_fetcher_, net_log_);
  594. decider_->set_quick_check_enabled(quick_check_enabled_);
  595. int result = decider_->Start(
  596. config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_,
  597. base::BindOnce(&PacFileDeciderPoller::OnPacFileDeciderCompleted,
  598. base::Unretained(this)));
  599. if (result != ERR_IO_PENDING)
  600. OnPacFileDeciderCompleted(result);
  601. }
  602. void OnPacFileDeciderCompleted(int result) {
  603. if (HasScriptDataChanged(result, decider_->script_data())) {
  604. // Something has changed, we must notify the
  605. // ConfiguredProxyResolutionService so it can re-initialize its
  606. // ProxyResolver. Note that we post a notification task rather than
  607. // calling it directly -- this is done to avoid an ugly destruction
  608. // sequence, since |this| might be destroyed as a result of the
  609. // notification.
  610. base::ThreadTaskRunnerHandle::Get()->PostTask(
  611. FROM_HERE,
  612. base::BindOnce(
  613. &PacFileDeciderPoller::NotifyProxyResolutionServiceOfChange,
  614. weak_factory_.GetWeakPtr(), result, decider_->script_data(),
  615. decider_->effective_config()));
  616. return;
  617. }
  618. decider_.reset();
  619. // Decide when the next poll should take place, and possibly start the
  620. // next timer.
  621. next_poll_mode_ = poll_policy()->GetNextDelay(last_error_, next_poll_delay_,
  622. &next_poll_delay_);
  623. TryToStartNextPoll(false);
  624. }
  625. bool HasScriptDataChanged(int result,
  626. const PacFileDataWithSource& script_data) {
  627. if (result != last_error_) {
  628. // Something changed -- it was failing before and now it succeeded, or
  629. // conversely it succeeded before and now it failed. Or it failed in
  630. // both cases, however the specific failure error codes differ.
  631. return true;
  632. }
  633. if (result != OK) {
  634. // If it failed last time and failed again with the same error code this
  635. // time, then nothing has actually changed.
  636. return false;
  637. }
  638. // Otherwise if it succeeded both this time and last time, we need to look
  639. // closer and see if we ended up downloading different content for the PAC
  640. // script.
  641. return !script_data.data->Equals(last_script_data_.data.get()) ||
  642. (script_data.from_auto_detect != last_script_data_.from_auto_detect);
  643. }
  644. void NotifyProxyResolutionServiceOfChange(
  645. int result,
  646. const PacFileDataWithSource& script_data,
  647. const ProxyConfigWithAnnotation& effective_config) {
  648. // Note that |this| may be deleted after calling into the
  649. // ConfiguredProxyResolutionService.
  650. change_callback_.Run(result, script_data, effective_config);
  651. }
  652. ChangeCallback change_callback_;
  653. ProxyConfigWithAnnotation config_;
  654. bool proxy_resolver_expects_pac_bytes_;
  655. raw_ptr<PacFileFetcher> pac_file_fetcher_;
  656. raw_ptr<DhcpPacFileFetcher> dhcp_pac_file_fetcher_;
  657. int last_error_;
  658. PacFileDataWithSource last_script_data_;
  659. std::unique_ptr<PacFileDecider> decider_;
  660. base::TimeDelta next_poll_delay_;
  661. PacPollPolicy::Mode next_poll_mode_;
  662. TimeTicks last_poll_time_;
  663. const raw_ptr<NetLog> net_log_;
  664. // Polling policy injected by unit-tests. Otherwise this is nullptr and the
  665. // default policy will be used.
  666. static const PacPollPolicy* poll_policy_;
  667. const DefaultPollPolicy default_poll_policy_;
  668. bool quick_check_enabled_;
  669. base::WeakPtrFactory<PacFileDeciderPoller> weak_factory_{this};
  670. };
  671. // static
  672. const ConfiguredProxyResolutionService::PacPollPolicy*
  673. ConfiguredProxyResolutionService::PacFileDeciderPoller::poll_policy_ =
  674. nullptr;
  675. // ConfiguredProxyResolutionService
  676. // -----------------------------------------------------
  677. ConfiguredProxyResolutionService::ConfiguredProxyResolutionService(
  678. std::unique_ptr<ProxyConfigService> config_service,
  679. std::unique_ptr<ProxyResolverFactory> resolver_factory,
  680. NetLog* net_log,
  681. bool quick_check_enabled)
  682. : config_service_(std::move(config_service)),
  683. resolver_factory_(std::move(resolver_factory)),
  684. net_log_(net_log),
  685. stall_proxy_auto_config_delay_(
  686. base::Milliseconds(kDelayAfterNetworkChangesMs)),
  687. quick_check_enabled_(quick_check_enabled) {
  688. NetworkChangeNotifier::AddIPAddressObserver(this);
  689. NetworkChangeNotifier::AddDNSObserver(this);
  690. config_service_->AddObserver(this);
  691. }
  692. // static
  693. std::unique_ptr<ConfiguredProxyResolutionService>
  694. ConfiguredProxyResolutionService::CreateUsingSystemProxyResolver(
  695. std::unique_ptr<ProxyConfigService> proxy_config_service,
  696. NetLog* net_log,
  697. bool quick_check_enabled) {
  698. DCHECK(proxy_config_service);
  699. if (!ProxyResolverFactoryForSystem::IsSupported()) {
  700. VLOG(1) << "PAC support disabled because there is no system implementation";
  701. return CreateWithoutProxyResolver(std::move(proxy_config_service), net_log);
  702. }
  703. std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
  704. std::make_unique<ConfiguredProxyResolutionService>(
  705. std::move(proxy_config_service),
  706. std::make_unique<ProxyResolverFactoryForSystem>(
  707. kDefaultNumPacThreads),
  708. net_log, quick_check_enabled);
  709. return proxy_resolution_service;
  710. }
  711. // static
  712. std::unique_ptr<ConfiguredProxyResolutionService>
  713. ConfiguredProxyResolutionService::CreateWithoutProxyResolver(
  714. std::unique_ptr<ProxyConfigService> proxy_config_service,
  715. NetLog* net_log) {
  716. return std::make_unique<ConfiguredProxyResolutionService>(
  717. std::move(proxy_config_service),
  718. std::make_unique<ProxyResolverFactoryForNullResolver>(), net_log,
  719. /*quick_check_enabled=*/false);
  720. }
  721. // static
  722. std::unique_ptr<ConfiguredProxyResolutionService>
  723. ConfiguredProxyResolutionService::CreateFixedForTest(
  724. const ProxyConfigWithAnnotation& pc) {
  725. // TODO(eroman): This isn't quite right, won't work if |pc| specifies
  726. // a PAC script.
  727. return CreateUsingSystemProxyResolver(
  728. std::make_unique<ProxyConfigServiceFixed>(pc), nullptr,
  729. /*quick_check_enabled=*/true);
  730. }
  731. // static
  732. std::unique_ptr<ConfiguredProxyResolutionService>
  733. ConfiguredProxyResolutionService::CreateFixedForTest(
  734. const std::string& proxy,
  735. const NetworkTrafficAnnotationTag& traffic_annotation) {
  736. ProxyConfig proxy_config;
  737. proxy_config.proxy_rules().ParseFromString(proxy);
  738. ProxyConfigWithAnnotation annotated_config(proxy_config, traffic_annotation);
  739. return ConfiguredProxyResolutionService::CreateFixedForTest(annotated_config);
  740. }
  741. // static
  742. std::unique_ptr<ConfiguredProxyResolutionService>
  743. ConfiguredProxyResolutionService::CreateDirect() {
  744. // Use direct connections.
  745. return std::make_unique<ConfiguredProxyResolutionService>(
  746. std::make_unique<ProxyConfigServiceDirect>(),
  747. std::make_unique<ProxyResolverFactoryForNullResolver>(), nullptr,
  748. /*quick_check_enabled=*/true);
  749. }
  750. // static
  751. std::unique_ptr<ConfiguredProxyResolutionService>
  752. ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
  753. const std::string& pac_string,
  754. const NetworkTrafficAnnotationTag& traffic_annotation) {
  755. // We need the settings to contain an "automatic" setting, otherwise the
  756. // ProxyResolver dependency we give it will never be used.
  757. auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
  758. ProxyConfigWithAnnotation(ProxyConfig::CreateFromCustomPacURL(GURL(
  759. "https://my-pac-script.invalid/wpad.dat")),
  760. traffic_annotation));
  761. return std::make_unique<ConfiguredProxyResolutionService>(
  762. std::move(proxy_config_service),
  763. std::make_unique<ProxyResolverFactoryForPacResult>(pac_string), nullptr,
  764. /*quick_check_enabled=*/true);
  765. }
  766. // static
  767. std::unique_ptr<ConfiguredProxyResolutionService>
  768. ConfiguredProxyResolutionService::CreateFixedFromAutoDetectedPacResultForTest(
  769. const std::string& pac_string,
  770. const NetworkTrafficAnnotationTag& traffic_annotation) {
  771. auto proxy_config_service =
  772. std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
  773. ProxyConfig::CreateAutoDetect(), traffic_annotation));
  774. return std::make_unique<ConfiguredProxyResolutionService>(
  775. std::move(proxy_config_service),
  776. std::make_unique<ProxyResolverFactoryForPacResult>(pac_string), nullptr,
  777. /*quick_check_enabled=*/true);
  778. }
  779. int ConfiguredProxyResolutionService::ResolveProxy(
  780. const GURL& raw_url,
  781. const std::string& method,
  782. const NetworkIsolationKey& network_isolation_key,
  783. ProxyInfo* result,
  784. CompletionOnceCallback callback,
  785. std::unique_ptr<ProxyResolutionRequest>* out_request,
  786. const NetLogWithSource& net_log) {
  787. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  788. DCHECK(!callback.is_null());
  789. DCHECK(out_request);
  790. net_log.BeginEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
  791. // Notify our polling-based dependencies that a resolve is taking place.
  792. // This way they can schedule their polls in response to network activity.
  793. config_service_->OnLazyPoll();
  794. if (script_poller_.get())
  795. script_poller_->OnLazyPoll();
  796. if (current_state_ == STATE_NONE)
  797. ApplyProxyConfigIfAvailable();
  798. // Sanitize the URL before passing it on to the proxy resolver (i.e. PAC
  799. // script). The goal is to remove sensitive data (like embedded user names
  800. // and password), and local data (i.e. reference fragment) which does not need
  801. // to be disclosed to the resolver.
  802. GURL url = SanitizeUrl(raw_url);
  803. // Check if the request can be completed right away. (This is the case when
  804. // using a direct connection for example).
  805. int rv = TryToCompleteSynchronously(url, result);
  806. if (rv != ERR_IO_PENDING) {
  807. rv = DidFinishResolvingProxy(url, method, result, rv, net_log);
  808. return rv;
  809. }
  810. auto req = std::make_unique<ConfiguredProxyResolutionRequest>(
  811. this, url, method, network_isolation_key, result, std::move(callback),
  812. net_log);
  813. if (current_state_ == STATE_READY) {
  814. // Start the resolve request.
  815. rv = req->Start();
  816. if (rv != ERR_IO_PENDING)
  817. return req->QueryDidCompleteSynchronously(rv);
  818. } else {
  819. req->net_log()->BeginEvent(
  820. NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC);
  821. }
  822. DCHECK_EQ(ERR_IO_PENDING, rv);
  823. DCHECK(!ContainsPendingRequest(req.get()));
  824. pending_requests_.insert(req.get());
  825. // Completion will be notified through |callback|, unless the caller cancels
  826. // the request using |out_request|.
  827. *out_request = std::move(req);
  828. return rv; // ERR_IO_PENDING
  829. }
  830. int ConfiguredProxyResolutionService::TryToCompleteSynchronously(
  831. const GURL& url,
  832. ProxyInfo* result) {
  833. DCHECK_NE(STATE_NONE, current_state_);
  834. if (current_state_ != STATE_READY)
  835. return ERR_IO_PENDING; // Still initializing.
  836. DCHECK(config_);
  837. // If it was impossible to fetch or parse the PAC script, we cannot complete
  838. // the request here and bail out.
  839. if (permanent_error_ != OK) {
  840. // Before returning the permanent error check if the URL would have been
  841. // implicitly bypassed.
  842. if (ApplyPacBypassRules(url, result))
  843. return OK;
  844. return permanent_error_;
  845. }
  846. if (config_->value().HasAutomaticSettings())
  847. return ERR_IO_PENDING; // Must submit the request to the proxy resolver.
  848. // Use the manual proxy settings.
  849. config_->value().proxy_rules().Apply(url, result);
  850. result->set_traffic_annotation(
  851. MutableNetworkTrafficAnnotationTag(config_->traffic_annotation()));
  852. return OK;
  853. }
  854. ConfiguredProxyResolutionService::~ConfiguredProxyResolutionService() {
  855. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  856. NetworkChangeNotifier::RemoveIPAddressObserver(this);
  857. NetworkChangeNotifier::RemoveDNSObserver(this);
  858. config_service_->RemoveObserver(this);
  859. // Cancel any inprogress requests.
  860. // This cancels the internal requests, but leaves the responsibility of
  861. // canceling the high-level Request (by deleting it) to the client.
  862. // Since |pending_requests_| might be modified in one of the requests'
  863. // callbacks (if it deletes another request), iterating through the set in a
  864. // for-loop will not work.
  865. while (!pending_requests_.empty()) {
  866. ConfiguredProxyResolutionRequest* req = *pending_requests_.begin();
  867. req->QueryComplete(ERR_ABORTED);
  868. pending_requests_.erase(req);
  869. }
  870. }
  871. void ConfiguredProxyResolutionService::SuspendAllPendingRequests() {
  872. for (ConfiguredProxyResolutionRequest* req : pending_requests_) {
  873. if (req->is_started()) {
  874. req->CancelResolveJob();
  875. req->net_log()->BeginEvent(
  876. NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC);
  877. }
  878. }
  879. }
  880. void ConfiguredProxyResolutionService::SetReady() {
  881. DCHECK(!init_proxy_resolver_.get());
  882. current_state_ = STATE_READY;
  883. // TODO(lilyhoughton): This is necessary because a callback invoked by
  884. // |StartAndCompleteCheckingForSynchronous()| might delete |this|. A better
  885. // solution would be to disallow synchronous callbacks altogether.
  886. base::WeakPtr<ConfiguredProxyResolutionService> weak_this =
  887. weak_ptr_factory_.GetWeakPtr();
  888. auto pending_requests_copy = pending_requests_;
  889. for (auto* req : pending_requests_copy) {
  890. if (!ContainsPendingRequest(req))
  891. continue;
  892. if (!req->is_started()) {
  893. req->net_log()->EndEvent(
  894. NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC);
  895. // Note that we re-check for synchronous completion, in case we are
  896. // no longer using a ProxyResolver (can happen if we fell-back to manual.)
  897. req->StartAndCompleteCheckingForSynchronous();
  898. if (!weak_this)
  899. return; // Synchronous callback deleted |this|
  900. }
  901. }
  902. }
  903. void ConfiguredProxyResolutionService::ApplyProxyConfigIfAvailable() {
  904. DCHECK_EQ(STATE_NONE, current_state_);
  905. config_service_->OnLazyPoll();
  906. // If we have already fetched the configuration, start applying it.
  907. if (fetched_config_) {
  908. InitializeUsingLastFetchedConfig();
  909. return;
  910. }
  911. // Otherwise we need to first fetch the configuration.
  912. current_state_ = STATE_WAITING_FOR_PROXY_CONFIG;
  913. // Retrieve the current proxy configuration from the ProxyConfigService.
  914. // If a configuration is not available yet, we will get called back later
  915. // by our ProxyConfigService::Observer once it changes.
  916. ProxyConfigWithAnnotation config;
  917. ProxyConfigService::ConfigAvailability availability =
  918. config_service_->GetLatestProxyConfig(&config);
  919. if (availability != ProxyConfigService::CONFIG_PENDING)
  920. OnProxyConfigChanged(config, availability);
  921. }
  922. void ConfiguredProxyResolutionService::OnInitProxyResolverComplete(int result) {
  923. DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
  924. DCHECK(init_proxy_resolver_.get());
  925. DCHECK(fetched_config_);
  926. DCHECK(fetched_config_->value().HasAutomaticSettings());
  927. config_ = init_proxy_resolver_->effective_config();
  928. // At this point we have decided which proxy settings to use (i.e. which PAC
  929. // script if any). We start up a background poller to periodically revisit
  930. // this decision. If the contents of the PAC script change, or if the
  931. // result of proxy auto-discovery changes, this poller will notice it and
  932. // will trigger a re-initialization using the newly discovered PAC.
  933. script_poller_ = std::make_unique<PacFileDeciderPoller>(
  934. base::BindRepeating(
  935. &ConfiguredProxyResolutionService::InitializeUsingDecidedConfig,
  936. base::Unretained(this)),
  937. fetched_config_.value(), resolver_factory_->expects_pac_bytes(),
  938. pac_file_fetcher_.get(), dhcp_pac_file_fetcher_.get(), result,
  939. init_proxy_resolver_->script_data(), net_log_);
  940. script_poller_->set_quick_check_enabled(quick_check_enabled_);
  941. init_proxy_resolver_.reset();
  942. if (result != OK) {
  943. if (fetched_config_->value().pac_mandatory()) {
  944. VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
  945. "traffic.";
  946. config_ = fetched_config_;
  947. result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
  948. } else {
  949. VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
  950. "proxy servers.";
  951. ProxyConfig proxy_config = fetched_config_->value();
  952. proxy_config.ClearAutomaticSettings();
  953. config_ = ProxyConfigWithAnnotation(
  954. proxy_config, fetched_config_->traffic_annotation());
  955. result = OK;
  956. }
  957. }
  958. permanent_error_ = result;
  959. // Resume any requests which we had to defer until the PAC script was
  960. // downloaded.
  961. SetReady();
  962. }
  963. bool ConfiguredProxyResolutionService::MarkProxiesAsBadUntil(
  964. const ProxyInfo& result,
  965. base::TimeDelta retry_delay,
  966. const std::vector<ProxyServer>& additional_bad_proxies,
  967. const NetLogWithSource& net_log) {
  968. result.proxy_list().UpdateRetryInfoOnFallback(&proxy_retry_info_, retry_delay,
  969. false, additional_bad_proxies,
  970. OK, net_log);
  971. return result.proxy_list().size() > (additional_bad_proxies.size() + 1);
  972. }
  973. void ConfiguredProxyResolutionService::ReportSuccess(const ProxyInfo& result) {
  974. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  975. const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info();
  976. if (new_retry_info.empty())
  977. return;
  978. for (const auto& iter : new_retry_info) {
  979. auto existing = proxy_retry_info_.find(iter.first);
  980. if (existing == proxy_retry_info_.end()) {
  981. proxy_retry_info_[iter.first] = iter.second;
  982. if (proxy_delegate_) {
  983. const ProxyServer& bad_proxy =
  984. ProxyUriToProxyServer(iter.first, ProxyServer::SCHEME_HTTP);
  985. const ProxyRetryInfo& proxy_retry_info = iter.second;
  986. proxy_delegate_->OnFallback(bad_proxy, proxy_retry_info.net_error);
  987. }
  988. } else if (existing->second.bad_until < iter.second.bad_until) {
  989. existing->second.bad_until = iter.second.bad_until;
  990. }
  991. }
  992. if (net_log_) {
  993. net_log_->AddGlobalEntry(NetLogEventType::BAD_PROXY_LIST_REPORTED, [&] {
  994. return NetLogBadProxyListParams(&new_retry_info);
  995. });
  996. }
  997. }
  998. bool ConfiguredProxyResolutionService::ContainsPendingRequest(
  999. ConfiguredProxyResolutionRequest* req) {
  1000. return pending_requests_.count(req) == 1;
  1001. }
  1002. void ConfiguredProxyResolutionService::RemovePendingRequest(
  1003. ConfiguredProxyResolutionRequest* req) {
  1004. DCHECK(ContainsPendingRequest(req));
  1005. pending_requests_.erase(req);
  1006. }
  1007. int ConfiguredProxyResolutionService::DidFinishResolvingProxy(
  1008. const GURL& url,
  1009. const std::string& method,
  1010. ProxyInfo* result,
  1011. int result_code,
  1012. const NetLogWithSource& net_log) {
  1013. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1014. // Log the result of the proxy resolution.
  1015. if (result_code == OK) {
  1016. // Allow the proxy delegate to interpose on the resolution decision,
  1017. // possibly modifying the ProxyInfo.
  1018. if (proxy_delegate_)
  1019. proxy_delegate_->OnResolveProxy(url, method, proxy_retry_info_, result);
  1020. net_log.AddEvent(
  1021. NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
  1022. [&] { return NetLogFinishedResolvingProxyParams(result); });
  1023. // This check is done to only log the NetLog event when necessary, it's
  1024. // not a performance optimization.
  1025. if (!proxy_retry_info_.empty()) {
  1026. result->DeprioritizeBadProxies(proxy_retry_info_);
  1027. net_log.AddEvent(
  1028. NetLogEventType::PROXY_RESOLUTION_SERVICE_DEPRIORITIZED_BAD_PROXIES,
  1029. [&] { return NetLogFinishedResolvingProxyParams(result); });
  1030. }
  1031. } else {
  1032. net_log.AddEventWithNetErrorCode(
  1033. NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
  1034. result_code);
  1035. bool reset_config = result_code == ERR_PAC_SCRIPT_TERMINATED;
  1036. if (config_ && !config_->value().pac_mandatory()) {
  1037. // Fall-back to direct when the proxy resolver fails. This corresponds
  1038. // with a javascript runtime error in the PAC script.
  1039. //
  1040. // This implicit fall-back to direct matches Firefox 3.5 and
  1041. // Internet Explorer 8. For more information, see:
  1042. //
  1043. // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
  1044. result->UseDirect();
  1045. result_code = OK;
  1046. // Allow the proxy delegate to interpose on the resolution decision,
  1047. // possibly modifying the ProxyInfo.
  1048. if (proxy_delegate_)
  1049. proxy_delegate_->OnResolveProxy(url, method, proxy_retry_info_, result);
  1050. } else {
  1051. result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
  1052. }
  1053. if (reset_config) {
  1054. ResetProxyConfig(false);
  1055. // If the ProxyResolver crashed, force it to be re-initialized for the
  1056. // next request by resetting the proxy config. If there are other pending
  1057. // requests, trigger the recreation immediately so those requests retry.
  1058. if (pending_requests_.size() > 1)
  1059. ApplyProxyConfigIfAvailable();
  1060. }
  1061. }
  1062. net_log.EndEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
  1063. return result_code;
  1064. }
  1065. void ConfiguredProxyResolutionService::SetPacFileFetchers(
  1066. std::unique_ptr<PacFileFetcher> pac_file_fetcher,
  1067. std::unique_ptr<DhcpPacFileFetcher> dhcp_pac_file_fetcher) {
  1068. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1069. State previous_state = ResetProxyConfig(false);
  1070. pac_file_fetcher_ = std::move(pac_file_fetcher);
  1071. dhcp_pac_file_fetcher_ = std::move(dhcp_pac_file_fetcher);
  1072. if (previous_state != STATE_NONE)
  1073. ApplyProxyConfigIfAvailable();
  1074. }
  1075. void ConfiguredProxyResolutionService::SetProxyDelegate(
  1076. ProxyDelegate* delegate) {
  1077. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1078. DCHECK(!proxy_delegate_ || !delegate);
  1079. proxy_delegate_ = delegate;
  1080. }
  1081. void ConfiguredProxyResolutionService::OnShutdown() {
  1082. // Order here does not matter for correctness. |init_proxy_resolver_| is first
  1083. // because shutting it down also cancels its requests using the fetcher.
  1084. if (init_proxy_resolver_)
  1085. init_proxy_resolver_->OnShutdown();
  1086. if (pac_file_fetcher_)
  1087. pac_file_fetcher_->OnShutdown();
  1088. if (dhcp_pac_file_fetcher_)
  1089. dhcp_pac_file_fetcher_->OnShutdown();
  1090. }
  1091. const ProxyRetryInfoMap& ConfiguredProxyResolutionService::proxy_retry_info()
  1092. const {
  1093. return proxy_retry_info_;
  1094. }
  1095. void ConfiguredProxyResolutionService::ClearBadProxiesCache() {
  1096. proxy_retry_info_.clear();
  1097. }
  1098. PacFileFetcher* ConfiguredProxyResolutionService::GetPacFileFetcher() const {
  1099. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1100. return pac_file_fetcher_.get();
  1101. }
  1102. bool ConfiguredProxyResolutionService::GetLoadStateIfAvailable(
  1103. LoadState* load_state) const {
  1104. if (current_state_ == STATE_WAITING_FOR_INIT_PROXY_RESOLVER) {
  1105. *load_state = init_proxy_resolver_->GetLoadState();
  1106. return true;
  1107. }
  1108. return false;
  1109. }
  1110. ProxyResolver* ConfiguredProxyResolutionService::GetProxyResolver() const {
  1111. return resolver_.get();
  1112. }
  1113. ConfiguredProxyResolutionService::State
  1114. ConfiguredProxyResolutionService::ResetProxyConfig(bool reset_fetched_config) {
  1115. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1116. State previous_state = current_state_;
  1117. permanent_error_ = OK;
  1118. proxy_retry_info_.clear();
  1119. script_poller_.reset();
  1120. init_proxy_resolver_.reset();
  1121. SuspendAllPendingRequests();
  1122. resolver_.reset();
  1123. config_ = absl::nullopt;
  1124. if (reset_fetched_config)
  1125. fetched_config_ = absl::nullopt;
  1126. current_state_ = STATE_NONE;
  1127. return previous_state;
  1128. }
  1129. void ConfiguredProxyResolutionService::ForceReloadProxyConfig() {
  1130. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  1131. ResetProxyConfig(false);
  1132. ApplyProxyConfigIfAvailable();
  1133. }
  1134. base::Value::Dict ConfiguredProxyResolutionService::GetProxyNetLogValues() {
  1135. base::Value::Dict net_info_dict;
  1136. // Log Proxy Settings.
  1137. {
  1138. base::Value::Dict dict;
  1139. if (fetched_config_)
  1140. dict.Set("original", fetched_config_->value().ToValue());
  1141. if (config_)
  1142. dict.Set("effective", config_->value().ToValue());
  1143. net_info_dict.Set(kNetInfoProxySettings, std::move(dict));
  1144. }
  1145. // Log Bad Proxies.
  1146. {
  1147. base::Value list(base::Value::Type::LIST);
  1148. for (const auto& it : proxy_retry_info_) {
  1149. const std::string& proxy_uri = it.first;
  1150. const ProxyRetryInfo& retry_info = it.second;
  1151. base::Value::Dict dict;
  1152. dict.Set("proxy_uri", proxy_uri);
  1153. dict.Set("bad_until", NetLog::TickCountToString(retry_info.bad_until));
  1154. list.Append(base::Value(std::move(dict)));
  1155. }
  1156. net_info_dict.Set(kNetInfoBadProxies, std::move(list));
  1157. }
  1158. return net_info_dict;
  1159. }
  1160. bool ConfiguredProxyResolutionService::CastToConfiguredProxyResolutionService(
  1161. ConfiguredProxyResolutionService** configured_proxy_resolution_service) {
  1162. *configured_proxy_resolution_service = this;
  1163. return true;
  1164. }
  1165. // static
  1166. const ConfiguredProxyResolutionService::PacPollPolicy*
  1167. ConfiguredProxyResolutionService::set_pac_script_poll_policy(
  1168. const PacPollPolicy* policy) {
  1169. return PacFileDeciderPoller::set_policy(policy);
  1170. }
  1171. // static
  1172. std::unique_ptr<ConfiguredProxyResolutionService::PacPollPolicy>
  1173. ConfiguredProxyResolutionService::CreateDefaultPacPollPolicy() {
  1174. return std::make_unique<DefaultPollPolicy>();
  1175. }
  1176. void ConfiguredProxyResolutionService::OnProxyConfigChanged(
  1177. const ProxyConfigWithAnnotation& config,
  1178. ProxyConfigService::ConfigAvailability availability) {
  1179. // Retrieve the current proxy configuration from the ProxyConfigService.
  1180. // If a configuration is not available yet, we will get called back later
  1181. // by our ProxyConfigService::Observer once it changes.
  1182. ProxyConfigWithAnnotation effective_config;
  1183. switch (availability) {
  1184. case ProxyConfigService::CONFIG_PENDING:
  1185. // ProxyConfigService implementors should never pass CONFIG_PENDING.
  1186. NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";
  1187. return;
  1188. case ProxyConfigService::CONFIG_VALID:
  1189. effective_config = config;
  1190. break;
  1191. case ProxyConfigService::CONFIG_UNSET:
  1192. effective_config = ProxyConfigWithAnnotation::CreateDirect();
  1193. break;
  1194. }
  1195. // Emit the proxy settings change to the NetLog stream.
  1196. if (net_log_) {
  1197. net_log_->AddGlobalEntry(NetLogEventType::PROXY_CONFIG_CHANGED, [&] {
  1198. return NetLogProxyConfigChangedParams(&fetched_config_,
  1199. &effective_config);
  1200. });
  1201. }
  1202. // Set the new configuration as the most recently fetched one.
  1203. fetched_config_ = effective_config;
  1204. InitializeUsingLastFetchedConfig();
  1205. }
  1206. bool ConfiguredProxyResolutionService::ApplyPacBypassRules(const GURL& url,
  1207. ProxyInfo* results) {
  1208. DCHECK(config_);
  1209. if (ProxyBypassRules::MatchesImplicitRules(url)) {
  1210. results->UseDirectWithBypassedProxy();
  1211. return true;
  1212. }
  1213. return false;
  1214. }
  1215. void ConfiguredProxyResolutionService::InitializeUsingLastFetchedConfig() {
  1216. ResetProxyConfig(false);
  1217. DCHECK(fetched_config_);
  1218. if (!fetched_config_->value().HasAutomaticSettings()) {
  1219. config_ = fetched_config_;
  1220. SetReady();
  1221. return;
  1222. }
  1223. // Start downloading + testing the PAC scripts for this new configuration.
  1224. current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
  1225. // If we changed networks recently, we should delay running proxy auto-config.
  1226. base::TimeDelta wait_delay = stall_proxy_autoconfig_until_ - TimeTicks::Now();
  1227. init_proxy_resolver_ = std::make_unique<InitProxyResolver>();
  1228. init_proxy_resolver_->set_quick_check_enabled(quick_check_enabled_);
  1229. int rv = init_proxy_resolver_->Start(
  1230. &resolver_, resolver_factory_.get(), pac_file_fetcher_.get(),
  1231. dhcp_pac_file_fetcher_.get(), net_log_, fetched_config_.value(),
  1232. wait_delay,
  1233. base::BindOnce(
  1234. &ConfiguredProxyResolutionService::OnInitProxyResolverComplete,
  1235. base::Unretained(this)));
  1236. if (rv != ERR_IO_PENDING)
  1237. OnInitProxyResolverComplete(rv);
  1238. }
  1239. void ConfiguredProxyResolutionService::InitializeUsingDecidedConfig(
  1240. int decider_result,
  1241. const PacFileDataWithSource& script_data,
  1242. const ProxyConfigWithAnnotation& effective_config) {
  1243. DCHECK(fetched_config_);
  1244. DCHECK(fetched_config_->value().HasAutomaticSettings());
  1245. ResetProxyConfig(false);
  1246. current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
  1247. init_proxy_resolver_ = std::make_unique<InitProxyResolver>();
  1248. int rv = init_proxy_resolver_->StartSkipDecider(
  1249. &resolver_, resolver_factory_.get(), effective_config, decider_result,
  1250. script_data,
  1251. base::BindOnce(
  1252. &ConfiguredProxyResolutionService::OnInitProxyResolverComplete,
  1253. base::Unretained(this)));
  1254. if (rv != ERR_IO_PENDING)
  1255. OnInitProxyResolverComplete(rv);
  1256. }
  1257. void ConfiguredProxyResolutionService::OnIPAddressChanged() {
  1258. // See the comment block by |kDelayAfterNetworkChangesMs| for info.
  1259. stall_proxy_autoconfig_until_ =
  1260. TimeTicks::Now() + stall_proxy_auto_config_delay_;
  1261. // With a new network connection, using the proper proxy configuration for the
  1262. // new connection may be essential for URL requests to work properly. Reset
  1263. // the config to ensure new URL requests are blocked until the potential new
  1264. // proxy configuration is loaded.
  1265. State previous_state = ResetProxyConfig(false);
  1266. if (previous_state != STATE_NONE)
  1267. ApplyProxyConfigIfAvailable();
  1268. }
  1269. void ConfiguredProxyResolutionService::OnDNSChanged() {
  1270. // Do not fully reset proxy config on DNS change notifications. Instead,
  1271. // inform the poller that it would be a good time to check for changes.
  1272. //
  1273. // While a change to DNS servers in use could lead to different WPAD results,
  1274. // and thus a different proxy configuration, it is extremely unlikely to ever
  1275. // be essential for that changed proxy configuration to be picked up
  1276. // immediately. Either URL requests on the connection are generally working
  1277. // fine without the proxy, or requests are already broken, leaving little harm
  1278. // in letting a couple more requests fail until Chrome picks up the new proxy.
  1279. if (script_poller_.get())
  1280. script_poller_->OnLazyPoll();
  1281. }
  1282. } // namespace net