1// Copyright (c) 2010 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
5#ifndef NET_PROXY_INIT_PROXY_RESOLVER_H_
6#define NET_PROXY_INIT_PROXY_RESOLVER_H_
7#pragma once
8
9#include <vector>
10
11#include "base/string16.h"
12#include "base/time.h"
13#include "base/timer.h"
14#include "googleurl/src/gurl.h"
15#include "net/base/completion_callback.h"
16#include "net/base/net_log.h"
17
18namespace net {
19
20class ProxyConfig;
21class ProxyResolver;
22class ProxyScriptFetcher;
23
24// InitProxyResolver is a helper class used by ProxyService to
25// initialize a ProxyResolver with the PAC script data specified
26// by a particular ProxyConfig.
27//
28// This involves trying to use PAC scripts in this order:
29//
30//   (1) WPAD (DNS) if auto-detect is on.
31//   (2) Custom PAC script if a URL was given.
32//
33// If no PAC script was successfully downloaded + parsed, then it fails with
34// a network error. Otherwise the proxy resolver is left initialized with
35// the PAC script.
36//
37// Deleting InitProxyResolver while Init() is in progress, will
38// cancel the request.
39//
40class InitProxyResolver {
41 public:
42  // |resolver|, |proxy_script_fetcher| and |net_log| must remain valid for
43  // the lifespan of InitProxyResolver.
44  InitProxyResolver(ProxyResolver* resolver,
45                    ProxyScriptFetcher* proxy_script_fetcher,
46                    NetLog* net_log);
47
48  // Aborts any in-progress request.
49  ~InitProxyResolver();
50
51  // Applies the PAC settings of |config| to |resolver_|.
52  // If |wait_delay| is positive, the initialization will pause for this
53  // amount of time before getting started.
54  // If |effective_config| is non-NULL, then on successful initialization of
55  // |resolver_| the "effective" proxy settings we ended up using will be
56  // written out to |*effective_config|. Note that this may differ from
57  // |config| since we will have stripped any manual settings, and decided
58  // whether to use auto-detect or the custom PAC URL. Finally, if auto-detect
59  // was used we may now have resolved that to a specific script URL.
60  int Init(const ProxyConfig& config,
61           const base::TimeDelta wait_delay,
62           ProxyConfig* effective_config,
63           CompletionCallback* callback);
64
65 private:
66  struct PacURL {
67    PacURL(bool auto_detect, const GURL& url)
68        : auto_detect(auto_detect), url(url) {}
69    bool auto_detect;
70    GURL url;
71  };
72
73  typedef std::vector<PacURL> UrlList;
74
75  enum State {
76    STATE_NONE,
77    STATE_WAIT,
78    STATE_WAIT_COMPLETE,
79    STATE_FETCH_PAC_SCRIPT,
80    STATE_FETCH_PAC_SCRIPT_COMPLETE,
81    STATE_SET_PAC_SCRIPT,
82    STATE_SET_PAC_SCRIPT_COMPLETE,
83  };
84
85  // Returns ordered list of PAC urls to try for |config|.
86  UrlList BuildPacUrlsFallbackList(const ProxyConfig& config) const;
87
88  void OnIOCompletion(int result);
89  int DoLoop(int result);
90  void DoCallback(int result);
91
92  int DoWait();
93  int DoWaitComplete(int result);
94
95  int DoFetchPacScript();
96  int DoFetchPacScriptComplete(int result);
97
98  int DoSetPacScript();
99  int DoSetPacScriptComplete(int result);
100
101  // Tries restarting using the next fallback PAC URL:
102  // |pac_urls_[++current_pac_url_index]|.
103  // Returns OK and rewinds the state machine when there
104  // is something to try, otherwise returns |error|.
105  int TryToFallbackPacUrl(int error);
106
107  // Gets the initial state (we skip fetching when the
108  // ProxyResolver doesn't |expect_pac_bytes()|.
109  State GetStartState() const;
110
111  // Returns the current PAC URL we are fetching/testing.
112  const PacURL& current_pac_url() const;
113
114  void OnWaitTimerFired();
115  void DidCompleteInit();
116  void Cancel();
117
118  ProxyResolver* resolver_;
119  ProxyScriptFetcher* proxy_script_fetcher_;
120
121  CompletionCallbackImpl<InitProxyResolver> io_callback_;
122  CompletionCallback* user_callback_;
123
124  size_t current_pac_url_index_;
125
126  // Filled when the PAC script fetch completes.
127  string16 pac_script_;
128
129  UrlList pac_urls_;
130  State next_state_;
131
132  BoundNetLog net_log_;
133
134  base::TimeDelta wait_delay_;
135  base::OneShotTimer<InitProxyResolver> wait_timer_;
136
137  ProxyConfig* effective_config_;
138
139  DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
140};
141
142}  // namespace net
143
144#endif  // NET_PROXY_INIT_PROXY_RESOLVER_H_
145