1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_service.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/values.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "googleurl/src/gurl.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/net_log.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/init_proxy_resolver.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/proxy/multi_threaded_proxy_resolver.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_config_service_fixed.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/proxy/proxy_resolver.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/proxy/proxy_resolver_js_bindings.h"
23d77e7f37b175317d38b1e3067d27eba0584b93c6Kristian Monsen#ifndef ANDROID
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/proxy/proxy_resolver_v8.h"
25d77e7f37b175317d38b1e3067d27eba0584b93c6Kristian Monsen#endif
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_script_fetcher.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/proxy/sync_host_resolver_bridge.h"
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/url_request/url_request_context.h"
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_config_service_win.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_resolver_winhttp.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_MACOSX)
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_config_service_mac.h"
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_resolver_mac.h"
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/proxy/proxy_config_service_linux.h"
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta;
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeTicks;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace {
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst size_t kMaxNumNetLogEntries = 100;
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst size_t kDefaultNumPacThreads = 4;
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// When the IP address changes we don't immediately re-run proxy auto-config.
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Instead, we  wait for |kNumMillisToStallAfterNetworkChanges| before
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// attempting to re-valuate proxy auto-config.
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// During this time window, any resolve requests sent to the ProxyService will
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// be queued. Once we have waited the required amount of them, the proxy
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// auto-config step will be run, and the queued requests resumed.
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The reason we play this game is that our signal for detecting network
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// changes (NetworkChangeNotifier) may fire *before* the system's networking
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// dependencies are fully configured. This is a problem since it means if
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// we were to run proxy auto-config right away, it could fail due to spurious
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// DNS failures. (see http://crbug.com/50779 for more details.)
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// By adding the wait window, we give things a chance to get properly set up.
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Now by the time we run the proxy-autoconfig there is a lower chance of
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// getting transient DNS / connect failures.
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Admitedly this is a hack. Ideally we would have NetworkChangeNotifier
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// deliver a reliable signal indicating that the network has changed AND is
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ready for action... But until then, we can reduce the likelihood of users
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// getting wedged because of proxy detection failures on network switch.
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The obvious downside to this strategy is it introduces an additional
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// latency when switching networks. This delay shouldn't be too disruptive
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// assuming network switches are infrequent and user initiated. However if
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// NetworkChangeNotifier delivers network changes more frequently this could
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// cause jankiness. (NetworkChangeNotifier broadcasts a change event when ANY
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// interface goes up/down. So in theory if the non-primary interface were
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// hopping on and off wireless networks our constant delayed reconfiguration
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// could add noticeable jank.)
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The specific hard-coded wait time below is arbitrary.
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Basically I ran some experiments switching between wireless networks on
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// a Linux Ubuntu (Lucid) laptop, and experimentally found this timeout fixes
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// things. It is entirely possible that the value is insuficient for other
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// setups.
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int64 kNumMillisToStallAfterNetworkChanges = 2000;
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Config getter that always returns direct settings.
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ProxyConfigServiceDirect : public ProxyConfigService {
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ProxyConfigService implementation:
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void AddObserver(Observer* observer) {}
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void RemoveObserver(Observer* observer) {}
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) {
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *config = ProxyConfig::CreateDirect();
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return CONFIG_VALID;
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Proxy resolver that fails every time.
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ProxyResolverNull : public ProxyResolver {
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProxyResolverNull() : ProxyResolver(false /*expects_pac_bytes*/) {}
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ProxyResolver implementation:
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual int GetProxyForURL(const GURL& url,
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             ProxyInfo* results,
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             CompletionCallback* callback,
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             RequestHandle* request,
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             const BoundNetLog& net_log) {
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_NOT_IMPLEMENTED;
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void CancelRequest(RequestHandle request) {
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void CancelSetPacScript() {
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    NOTREACHED();
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int SetPacScript(
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const scoped_refptr<ProxyResolverScriptData>& /*script_data*/,
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CompletionCallback* /*callback*/) {
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_NOT_IMPLEMENTED;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ProxyResolver that simulates a PAC script which returns
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// |pac_string| for every single URL.
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ProxyResolverFromPacString : public ProxyResolver {
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ProxyResolverFromPacString(const std::string& pac_string)
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : ProxyResolver(false /*expects_pac_bytes*/),
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        pac_string_(pac_string) {}
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual int GetProxyForURL(const GURL& url,
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             ProxyInfo* results,
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             CompletionCallback* callback,
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             RequestHandle* request,
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const BoundNetLog& net_log) {
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    results->UsePacString(pac_string_);
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return OK;
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void CancelRequest(RequestHandle request) {
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void CancelSetPacScript() {
15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    NOTREACHED();
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual int SetPacScript(
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const scoped_refptr<ProxyResolverScriptData>& pac_script,
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      CompletionCallback* callback) {
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return OK;
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const std::string pac_string_;
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
165d77e7f37b175317d38b1e3067d27eba0584b93c6Kristian Monsen#ifndef ANDROID
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This factory creates V8ProxyResolvers with appropriate javascript bindings.
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ProxyResolverFactoryForV8 : public ProxyResolverFactory {
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |async_host_resolver|, |io_loop| and |net_log| must remain
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // valid for the duration of our lifetime.
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // |async_host_resolver| will only be operated on |io_loop|.
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ProxyResolverFactoryForV8(HostResolver* async_host_resolver,
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            MessageLoop* io_loop,
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            NetLog* net_log)
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : ProxyResolverFactory(true /*expects_pac_bytes*/),
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        async_host_resolver_(async_host_resolver),
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        io_loop_(io_loop),
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        net_log_(net_log) {
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ProxyResolver* CreateProxyResolver() {
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create a synchronous host resolver wrapper that operates
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // |async_host_resolver_| on |io_loop_|.
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SyncHostResolverBridge* sync_host_resolver =
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new SyncHostResolverBridge(async_host_resolver_, io_loop_);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ProxyResolverJSBindings* js_bindings =
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        ProxyResolverJSBindings::CreateDefault(sync_host_resolver, net_log_);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // ProxyResolverV8 takes ownership of |js_bindings|.
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return new ProxyResolverV8(js_bindings);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  HostResolver* const async_host_resolver_;
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop* io_loop_;
19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  NetLog* net_log_;
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
199d77e7f37b175317d38b1e3067d27eba0584b93c6Kristian Monsen#endif
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Creates ProxyResolvers using a platform-specific implementation.
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass ProxyResolverFactoryForSystem : public ProxyResolverFactory {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ProxyResolverFactoryForSystem()
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : ProxyResolverFactory(false /*expects_pac_bytes*/) {}
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ProxyResolver* CreateProxyResolver() {
208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DCHECK(IsSupported());
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return new ProxyResolverWinHttp();
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_MACOSX)
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return new ProxyResolverMac();
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NOTREACHED();
215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return NULL;
216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif
217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  static bool IsSupported() {
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if defined(OS_WIN) || defined(OS_MACOSX)
221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return true;
222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#else
223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// NetLog parameter to describe a proxy configuration change.
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ProxyConfigChangedNetLogParam : public NetLog::EventParameters {
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ProxyConfigChangedNetLogParam(const ProxyConfig& old_config,
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const ProxyConfig& new_config)
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : old_config_(old_config),
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new_config_(new_config) {
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual Value* ToValue() const {
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DictionaryValue* dict = new DictionaryValue();
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // The "old_config" is optional -- the first notification will not have
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // any "previous" configuration.
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (old_config_.is_valid())
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      dict->Set("old_config", old_config_.ToValue());
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dict->Set("new_config", new_config_.ToValue());
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return dict;
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const ProxyConfig old_config_;
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const ProxyConfig new_config_;
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(ProxyConfigChangedNetLogParam);
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ProxyService::PacRequest ---------------------------------------------------
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ProxyService::PacRequest
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public base::RefCounted<ProxyService::PacRequest> {
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PacRequest(ProxyService* service,
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             const GURL& url,
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             ProxyInfo* results,
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             CompletionCallback* user_callback,
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const BoundNetLog& net_log)
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : service_(service),
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        user_callback_(user_callback),
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            this, &PacRequest::QueryComplete)),
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        results_(results),
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        url_(url),
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        resolve_job_(NULL),
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        config_id_(ProxyConfig::INVALID_ID),
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net_log_(net_log) {
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(user_callback);
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Starts the resolve proxy request.
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int Start() {
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!was_cancelled());
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!is_started());
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(service_->config_.is_valid());
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    config_id_ = service_->config_.id();
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return resolver()->GetProxyForURL(
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        url_, results_, &io_callback_, &resolve_job_, net_log_);
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool is_started() const {
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Note that !! casts to bool. (VS gives a warning otherwise).
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return !!resolve_job_;
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void StartAndCompleteCheckingForSynchronous() {
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int rv = service_->TryToCompleteSynchronously(url_, results_);
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv == ERR_IO_PENDING)
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rv = Start();
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv != ERR_IO_PENDING)
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      QueryComplete(rv);
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CancelResolveJob() {
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(is_started());
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The request may already be running in the resolver.
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    resolver()->CancelRequest(resolve_job_);
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    resolve_job_ = NULL;
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!is_started());
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Cancel() {
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (is_started())
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CancelResolveJob();
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Mark as cancelled, to prevent accessing this again later.
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    service_ = NULL;
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    user_callback_ = NULL;
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    results_ = NULL;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net_log_.EndEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if Cancel() has been called.
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool was_cancelled() const { return user_callback_ == NULL; }
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Helper to call after ProxyResolver completion (both synchronous and
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // asynchronous). Fixes up the result that is to be returned to user.
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int QueryDidComplete(int result_code) {
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!was_cancelled());
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Make a note in the results which configuration was in use at the
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // time of the resolve.
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    results_->config_id_ = config_id_;
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Reset the state associated with in-progress-resolve.
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    resolve_job_ = NULL;
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    config_id_ = ProxyConfig::INVALID_ID;
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return service_->DidFinishResolvingProxy(results_, result_code, net_log_);
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog* net_log() { return &net_log_; }
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class base::RefCounted<ProxyService::PacRequest>;
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~PacRequest() {}
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Callback for when the ProxyResolver request has completed.
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void QueryComplete(int result_code) {
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result_code = QueryDidComplete(result_code);
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Remove this completed PacRequest from the service's pending list.
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /// (which will probably cause deletion of |this|).
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CompletionCallback* callback = user_callback_;
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    service_->RemovePendingRequest(this);
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    callback->Run(result_code);
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProxyResolver* resolver() const { return service_->resolver_.get(); }
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Note that we don't hold a reference to the ProxyService. Outstanding
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // requests are cancelled during ~ProxyService, so this is guaranteed
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to be valid throughout our lifetime.
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProxyService* service_;
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallback* user_callback_;
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallbackImpl<PacRequest> io_callback_;
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProxyInfo* results_;
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GURL url_;
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProxyResolver::RequestHandle resolve_job_;
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProxyConfig::ID config_id_;  // The config id when the resolve was started.
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog net_log_;
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ProxyService ---------------------------------------------------------------
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyService::ProxyService(ProxyConfigService* config_service,
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           ProxyResolver* resolver,
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           NetLog* net_log)
3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : resolver_(resolver),
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_config_id_(1),
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(init_proxy_resolver_callback_(
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &ProxyService::OnInitProxyResolverComplete)),
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      current_state_(STATE_NONE) ,
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net_log_(net_log),
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stall_proxy_auto_config_delay_(
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          base::TimeDelta::FromMilliseconds(
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              kNumMillisToStallAfterNetworkChanges)) {
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NetworkChangeNotifier::AddIPAddressObserver(this);
3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ResetConfigService(config_service);
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
396d77e7f37b175317d38b1e3067d27eba0584b93c6Kristian Monsen#ifndef ANDROID
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
398731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickProxyService* ProxyService::CreateUsingV8ProxyResolver(
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ProxyConfigService* proxy_config_service,
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t num_pac_threads,
401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ProxyScriptFetcher* proxy_script_fetcher,
402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    HostResolver* host_resolver,
403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NetLog* net_log) {
404731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(proxy_config_service);
405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(proxy_script_fetcher);
406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(host_resolver);
407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (num_pac_threads == 0)
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    num_pac_threads = kDefaultNumPacThreads;
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
411731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ProxyResolverFactory* sync_resolver_factory =
412731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      new ProxyResolverFactoryForV8(
413731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          host_resolver,
414731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          MessageLoop::current(),
415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          net_log);
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ProxyResolver* proxy_resolver =
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new MultiThreadedProxyResolver(sync_resolver_factory, num_pac_threads);
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ProxyService* proxy_service =
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new ProxyService(proxy_config_service, proxy_resolver, net_log);
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
423731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Configure PAC script downloads to be issued using |proxy_script_fetcher|.
424731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  proxy_service->SetProxyScriptFetcher(proxy_script_fetcher);
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return proxy_service;
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
428d77e7f37b175317d38b1e3067d27eba0584b93c6Kristian Monsen#endif
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
431731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickProxyService* ProxyService::CreateUsingSystemProxyResolver(
432731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ProxyConfigService* proxy_config_service,
433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    size_t num_pac_threads,
434731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NetLog* net_log) {
435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(proxy_config_service);
436731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!ProxyResolverFactoryForSystem::IsSupported()) {
438731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(WARNING) << "PAC support disabled because there is no "
439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    "system implementation";
440731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return CreateWithoutProxyResolver(proxy_config_service, net_log);
441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (num_pac_threads == 0)
444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    num_pac_threads = kDefaultNumPacThreads;
445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ProxyResolver* proxy_resolver = new MultiThreadedProxyResolver(
447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      new ProxyResolverFactoryForSystem(), num_pac_threads);
448731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return new ProxyService(proxy_config_service, proxy_resolver, net_log);
450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
451731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
452731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
453731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickProxyService* ProxyService::CreateWithoutProxyResolver(
454731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ProxyConfigService* proxy_config_service,
455731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NetLog* net_log) {
456731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return new ProxyService(proxy_config_service,
457731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          new ProxyResolverNull(),
458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          net_log);
459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
460731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
461731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) {
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(eroman): This isn't quite right, won't work if |pc| specifies
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //               a PAC script.
465731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return CreateUsingSystemProxyResolver(new ProxyConfigServiceFixed(pc),
466731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                        0, NULL);
467731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
468731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
469731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
470731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickProxyService* ProxyService::CreateFixed(const std::string& proxy) {
471731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::ProxyConfig proxy_config;
472731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  proxy_config.proxy_rules().ParseFromString(proxy);
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return ProxyService::CreateFixed(proxy_config);
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyService* ProxyService::CreateDirect() {
47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return CreateDirectWithNetLog(NULL);
47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
48021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
48121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenProxyService* ProxyService::CreateDirectWithNetLog(NetLog* net_log) {
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Use direct connections.
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return new ProxyService(new ProxyConfigServiceDirect, new ProxyResolverNull,
48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                          net_log);
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyService* ProxyService::CreateFixedFromPacResult(
4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& pac_string) {
4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We need the settings to contain an "automatic" setting, otherwise the
4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // ProxyResolver dependency we give it will never be used.
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<ProxyConfigService> proxy_config_service(
4943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new ProxyConfigServiceFixed(ProxyConfig::CreateAutoDetect()));
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<ProxyResolver> proxy_resolver(
4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new ProxyResolverFromPacString(pac_string));
4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return new ProxyService(proxy_config_service.release(),
5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          proxy_resolver.release(),
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          NULL);
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint ProxyService::ResolveProxy(const GURL& raw_url,
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               ProxyInfo* result,
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               CompletionCallback* callback,
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               PacRequest** pac_request,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const BoundNetLog& net_log) {
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(callback);
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  config_service_->OnLazyPoll();
5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (current_state_ == STATE_NONE)
5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ApplyProxyConfigIfAvailable();
5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Strip away any reference fragments and the username/password, as they
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // are not relevant to proxy resolution.
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GURL url = SimplifyUrlForRequest(raw_url);
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Check if the request can be completed right away. (This is the case when
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // using a direct connection for example).
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = TryToCompleteSynchronously(url, result);
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv != ERR_IO_PENDING)
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return DidFinishResolvingProxy(result, rv, net_log);
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
528513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<PacRequest> req(
529513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new PacRequest(this, url, result, callback, net_log));
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (current_state_ == STATE_READY) {
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Start the resolve request.
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = req->Start();
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv != ERR_IO_PENDING)
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return req->QueryDidComplete(rv);
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    req->net_log()->BeginEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC,
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               NULL);
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(ERR_IO_PENDING, rv);
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!ContainsPendingRequest(req));
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pending_requests_.push_back(req);
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Completion will be notifed through |callback|, unless the caller cancels
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the request using |pac_request|.
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (pac_request)
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *pac_request = req.get();
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv;  // ERR_IO_PENDING
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint ProxyService::TryToCompleteSynchronously(const GURL& url,
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                             ProxyInfo* result) {
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_NE(STATE_NONE, current_state_);
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (current_state_ != STATE_READY)
5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return ERR_IO_PENDING;  // Still initializing.
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_NE(config_.id(), ProxyConfig::INVALID_ID);
5603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (config_.HasAutomaticSettings())
5623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return ERR_IO_PENDING;  // Must submit the request to the proxy resolver.
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use the manual proxy settings.
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  config_.proxy_rules().Apply(url, result);
5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  result->config_id_ = config_.id();
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyService::~ProxyService() {
571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NetworkChangeNotifier::RemoveIPAddressObserver(this);
5723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  config_service_->RemoveObserver(this);
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Cancel any inprogress requests.
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (PendingRequests::iterator it = pending_requests_.begin();
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != pending_requests_.end();
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ++it) {
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    (*it)->Cancel();
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::SuspendAllPendingRequests() {
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (PendingRequests::iterator it = pending_requests_.begin();
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != pending_requests_.end();
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ++it) {
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PacRequest* req = it->get();
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (req->is_started()) {
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      req->CancelResolveJob();
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      req->net_log()->BeginEvent(
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC, NULL);
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ProxyService::SetReady() {
5973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!init_proxy_resolver_.get());
5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  current_state_ = STATE_READY;
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Make a copy in case |this| is deleted during the synchronous completion
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of one of the requests. If |this| is deleted then all of the PacRequest
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // instances will be Cancel()-ed.
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PendingRequests pending_copy = pending_requests_;
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (PendingRequests::iterator it = pending_copy.begin();
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != pending_copy.end();
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ++it) {
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PacRequest* req = it->get();
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!req->is_started() && !req->was_cancelled()) {
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      req->net_log()->EndEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC,
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               NULL);
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Note that we re-check for synchronous completion, in case we are
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // no longer using a ProxyResolver (can happen if we fell-back to manual).
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      req->StartAndCompleteCheckingForSynchronous();
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ProxyService::ApplyProxyConfigIfAvailable() {
6213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_EQ(STATE_NONE, current_state_);
6223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  config_service_->OnLazyPoll();
6243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If we have already fetched the configuration, start applying it.
6263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (fetched_config_.is_valid()) {
6273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    InitializeUsingLastFetchedConfig();
6283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
6293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Otherwise we need to first fetch the configuration.
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  current_state_ = STATE_WAITING_FOR_PROXY_CONFIG;
6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Retrieve the current proxy configuration from the ProxyConfigService.
6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If a configuration is not available yet, we will get called back later
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // by our ProxyConfigService::Observer once it changes.
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ProxyConfig config;
638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProxyConfigService::ConfigAvailability availability =
639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      config_service_->GetLatestProxyConfig(&config);
640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (availability != ProxyConfigService::CONFIG_PENDING)
641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnProxyConfigChanged(config, availability);
6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::OnInitProxyResolverComplete(int result) {
6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_proxy_resolver_.get());
6473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(fetched_config_.HasAutomaticSettings());
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_proxy_resolver_.reset();
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != OK) {
651731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
652731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               "proxy servers.";
6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    config_ = fetched_config_;
6543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    config_.ClearAutomaticSettings();
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  config_.set_id(fetched_config_.id());
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Resume any requests which we had to defer until the PAC script was
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // downloaded.
6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetReady();
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint ProxyService::ReconsiderProxyAfterError(const GURL& url,
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            ProxyInfo* result,
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            CompletionCallback* callback,
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            PacRequest** pac_request,
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            const BoundNetLog& net_log) {
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check to see if we have a new config since ResolveProxy was called.  We
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // direct connection failed and we never tried the current config.
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool re_resolve = result->config_id_ != config_.id();
6763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (re_resolve) {
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If we have a new config or the config was never tried, we delete the
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // list of bad proxies and we try again.
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_retry_info_.clear();
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ResolveProxy(url, result, callback, pac_request, net_log);
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We don't have new proxy settings to try, try to fallback to the next proxy
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // in the list.
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool did_fallback = result->Fallback(&proxy_retry_info_);
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Return synchronous failure if there is nothing left to fall-back to.
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(eroman): This is a yucky API, clean it up.
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return did_fallback ? OK : ERR_FAILED;
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::CancelPacRequest(PacRequest* req) {
694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(req);
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  req->Cancel();
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RemovePendingRequest(req);
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ProxyService::ContainsPendingRequest(PacRequest* req) {
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PendingRequests::iterator it = std::find(
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pending_requests_.begin(), pending_requests_.end(), req);
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return pending_requests_.end() != it;
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::RemovePendingRequest(PacRequest* req) {
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ContainsPendingRequest(req));
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PendingRequests::iterator it = std::find(
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pending_requests_.begin(), pending_requests_.end(), req);
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pending_requests_.erase(it);
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint ProxyService::DidFinishResolvingProxy(ProxyInfo* result,
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          int result_code,
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const BoundNetLog& net_log) {
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Log the result of the proxy resolution.
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result_code == OK) {
718731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // When logging all events is enabled, dump the proxy list.
719731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (net_log.IsLoggingAllEvents()) {
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net_log.AddEvent(
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
722513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          make_scoped_refptr(new NetLogStringParameter(
723513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch              "pac_string", result->ToPacString())));
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result->DeprioritizeBadProxies(proxy_retry_info_);
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net_log.AddEvent(
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
729513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        make_scoped_refptr(new NetLogIntegerParameter(
730513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch            "net_error", result_code)));
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Fall-back to direct when the proxy resolver fails. This corresponds
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // with a javascript runtime error in the PAC script.
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This implicit fall-back to direct matches Firefox 3.5 and
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Internet Explorer 8. For more information, see:
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result->UseDirect();
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result_code = OK;
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result_code;
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::SetProxyScriptFetcher(
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ProxyScriptFetcher* proxy_script_fetcher) {
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
7503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  State previous_state = ResetProxyConfig(false);
7513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  proxy_script_fetcher_.reset(proxy_script_fetcher);
7523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (previous_state != STATE_NONE)
7533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ApplyProxyConfigIfAvailable();
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyScriptFetcher* ProxyService::GetProxyScriptFetcher() const {
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return proxy_script_fetcher_.get();
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7613345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
7633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  State previous_state = current_state_;
7643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  proxy_retry_info_.clear();
7663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  init_proxy_resolver_.reset();
7673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SuspendAllPendingRequests();
7683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  config_ = ProxyConfig();
7693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (reset_fetched_config)
7703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    fetched_config_ = ProxyConfig();
7713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  current_state_ = STATE_NONE;
7723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return previous_state;
7743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::ResetConfigService(
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ProxyConfigService* new_proxy_config_service) {
778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
7793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  State previous_state = ResetProxyConfig(true);
7803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Release the old configuration service.
7823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (config_service_.get())
7833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    config_service_->RemoveObserver(this);
7843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Set the new configuration service.
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  config_service_.reset(new_proxy_config_service);
7873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  config_service_->AddObserver(this);
7883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (previous_state != STATE_NONE)
7903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ApplyProxyConfigIfAvailable();
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::PurgeMemory() {
794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (resolver_.get())
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    resolver_->PurgeMemory();
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::ForceReloadProxyConfig() {
800ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
8013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ResetProxyConfig(false);
8023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ApplyProxyConfigIfAvailable();
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyConfigService* ProxyService::CreateSystemProxyConfigService(
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoop* io_loop, MessageLoop* file_loop) {
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new ProxyConfigServiceWin();
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_MACOSX)
8113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return new ProxyConfigServiceMac(io_loop);
8123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(OS_CHROMEOS)
8133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NOTREACHED() << "ProxyConfigService for ChromeOS should be created in "
814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               << "profile_io_data.cc::CreateProxyConfigService.";
8153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
8162d04b11d60881569d8142cf294b1fad59f14a2a5Kristian Monsen#elif defined(ANDROID)
8172d04b11d60881569d8142cf294b1fad59f14a2a5Kristian Monsen  NOTREACHED() << "ProxyConfigService for Android should be created in "
8182d04b11d60881569d8142cf294b1fad59f14a2a5Kristian Monsen               << "WebCache.cpp: WebCache::WebCache";
8192d04b11d60881569d8142cf294b1fad59f14a2a5Kristian Monsen  return NULL;
8202d04b11d60881569d8142cf294b1fad59f14a2a5Kristian Monsen#elif defined(OS_LINUX)
821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProxyConfigServiceLinux* linux_config_service =
822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new ProxyConfigServiceLinux();
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Assume we got called from the UI loop, which runs the default
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // glib main loop, so the current thread is where we should be
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // running gconf calls from.
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop* glib_default_loop = MessageLoopForUI::current();
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The file loop should be a MessageLoopForIO on Linux.
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, file_loop->type());
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Synchronously fetch the current proxy config (since we are
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // running on glib_default_loop). Additionally register for
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // notifications (delivered in either |glib_default_loop| or
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |file_loop|) to keep us updated when the proxy config changes.
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  linux_config_service->SetupAndFetchInitialConfig(glib_default_loop, io_loop,
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      static_cast<MessageLoopForIO*>(file_loop));
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return linux_config_service;
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  "for this platform.";
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new ProxyConfigServiceNull();
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProxyService::OnProxyConfigChanged(
848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ProxyConfig& config,
849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ProxyConfigService::ConfigAvailability availability) {
850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Retrieve the current proxy configuration from the ProxyConfigService.
851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If a configuration is not available yet, we will get called back later
852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // by our ProxyConfigService::Observer once it changes.
853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProxyConfig effective_config;
854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (availability) {
855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case ProxyConfigService::CONFIG_PENDING:
856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // ProxyConfigService implementors should never pass CONFIG_PENDING.
857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";
858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case ProxyConfigService::CONFIG_VALID:
860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      effective_config = config;
861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case ProxyConfigService::CONFIG_UNSET:
863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      effective_config = ProxyConfig::CreateDirect();
864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
8673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Emit the proxy settings change to the NetLog stream.
8683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (net_log_) {
869513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<NetLog::EventParameters> params(
870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new ProxyConfigChangedNetLogParam(fetched_config_, effective_config));
8713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net_log_->AddEntry(net::NetLog::TYPE_PROXY_CONFIG_CHANGED,
8723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       base::TimeTicks::Now(),
8733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       NetLog::Source(),
8743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       NetLog::PHASE_NONE,
8753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       params);
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Set the new configuration as the most recently fetched one.
879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  fetched_config_ = effective_config;
8803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fetched_config_.set_id(1);  // Needed for a later DCHECK of is_valid().
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  InitializeUsingLastFetchedConfig();
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ProxyService::InitializeUsingLastFetchedConfig() {
8863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ResetProxyConfig(false);
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(fetched_config_.is_valid());
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Increment the ID to reflect that the config has changed.
8913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fetched_config_.set_id(next_config_id_++);
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!fetched_config_.HasAutomaticSettings()) {
8943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    config_ = fetched_config_;
8953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SetReady();
8963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start downloading + testing the PAC scripts for this new configuration.
9003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_proxy_resolver_.reset(
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new InitProxyResolver(resolver_.get(), proxy_script_fetcher_.get(),
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            net_log_));
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If we changed networks recently, we should delay running proxy auto-config.
9073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::TimeDelta wait_delay =
9083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stall_proxy_autoconfig_until_ - base::TimeTicks::Now();
9093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = init_proxy_resolver_->Init(
9113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      fetched_config_, wait_delay, &config_, &init_proxy_resolver_callback_);
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv != ERR_IO_PENDING)
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OnInitProxyResolverComplete(rv);
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ProxyService::OnIPAddressChanged() {
9183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info.
9193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  stall_proxy_autoconfig_until_ =
9203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::TimeTicks::Now() + stall_proxy_auto_config_delay_;
9213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  State previous_state = ResetProxyConfig(false);
9233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (previous_state != STATE_NONE)
9243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ApplyProxyConfigIfAvailable();
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSyncProxyServiceHelper::SyncProxyServiceHelper(MessageLoop* io_message_loop,
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                               ProxyService* proxy_service)
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : io_message_loop_(io_message_loop),
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_service_(proxy_service),
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      event_(false, false),
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &SyncProxyServiceHelper::OnCompletion)) {
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(io_message_loop_ != MessageLoop::current());
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SyncProxyServiceHelper::ResolveProxy(const GURL& url,
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         ProxyInfo* proxy_info,
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         const BoundNetLog& net_log) {
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(io_message_loop_ != MessageLoop::current());
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this, &SyncProxyServiceHelper::StartAsyncResolve, url, net_log));
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_.Wait();
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result_ == net::OK) {
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *proxy_info = proxy_info_;
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result_;
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SyncProxyServiceHelper::ReconsiderProxyAfterError(
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url, ProxyInfo* proxy_info, const BoundNetLog& net_log) {
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(io_message_loop_ != MessageLoop::current());
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this, &SyncProxyServiceHelper::StartAsyncReconsider, url, net_log));
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_.Wait();
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result_ == net::OK) {
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *proxy_info = proxy_info_;
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result_;
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
968731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSyncProxyServiceHelper::~SyncProxyServiceHelper() {}
969731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncProxyServiceHelper::StartAsyncResolve(const GURL& url,
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               const BoundNetLog& net_log) {
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result_ = proxy_service_->ResolveProxy(
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url, &proxy_info_, &callback_, NULL, net_log);
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result_ != net::ERR_IO_PENDING) {
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OnCompletion(result_);
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncProxyServiceHelper::StartAsyncReconsider(const GURL& url,
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  const BoundNetLog& net_log) {
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result_ = proxy_service_->ReconsiderProxyAfterError(
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url, &proxy_info_, &callback_, NULL, net_log);
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result_ != net::ERR_IO_PENDING) {
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OnCompletion(result_);
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncProxyServiceHelper::OnCompletion(int rv) {
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result_ = rv;
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_.Signal();
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
994