proxy_config_service_impl.h revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_
6#define CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/prefs/pref_member.h"
13#include "base/values.h"
14#include "chrome/browser/chromeos/cros/network_library.h"
15#include "chrome/browser/net/pref_proxy_config_tracker_impl.h"
16
17class PrefRegistrySimple;
18
19namespace user_prefs {
20class PrefRegistrySyncable;
21}
22
23namespace chromeos {
24
25// Implementation of proxy config service for chromeos that:
26// - extends PrefProxyConfigTrackerImpl (and so lives and runs entirely on UI
27//   thread) to handle proxy from prefs (via PrefProxyConfigTrackerImpl) and
28//   system i.e. network (via shill notifications)
29// - exists one per profile and one per local state
30// - persists proxy setting per network in flimflim
31// - provides network stack with latest effective proxy configuration for
32//   currently active network via PrefProxyConfigTrackerImpl's mechanism of
33//   pushing config to ChromeProxyConfigService
34// - provides UI with methods to retrieve and modify proxy configuration for
35//   any remembered network (either currently active or non-active) of current
36//   user profile
37class ProxyConfigServiceImpl : public PrefProxyConfigTrackerImpl,
38                               public NetworkLibrary::NetworkManagerObserver,
39                               public NetworkLibrary::NetworkObserver {
40 public:
41  // ProxyConfigServiceImpl is created in ProxyServiceFactory::
42  // CreatePrefProxyConfigTrackerImpl via Profile::GetProxyConfigTracker() for
43  // profile or IOThread constructor for local state and is owned by the
44  // respective classes.
45  //
46  // From the UI, it is accessed via Profile::GetProxyConfigTracker to allow
47  // user to read or modify the proxy configuration via UIGetProxyConfig or
48  // UISetProxyConfigTo* respectively.
49  // The new modified proxy config, together with proxy from prefs if available,
50  // are used to determine the effective proxy config, which is then pushed
51  // through PrefProxyConfigTrackerImpl to ChromeProxyConfigService to the
52  // network stack.
53  //
54  // In contrary to other platforms which simply use the systems' UI to allow
55  // users to configure proxies, we have to implement our own UI on the chromeos
56  // device.  This requires extra and specific UI requirements that
57  // net::ProxyConfig does not suffice.  So we create an augmented analog to
58  // net:ProxyConfig here to include and handle these UI requirements, e.g.
59  // - state of configuration e.g. where it was picked up from - policy,
60  //   extension, etc (refer to ProxyPrefs::ConfigState)
61  // - the read/write access of a proxy setting
62  // - may add more stuff later.
63  // This is then converted to the common net::ProxyConfig before being pushed
64  // to PrefProxyConfigTrackerImpl::OnProxyConfigChanged and then to the network
65  // stack.
66  struct ProxyConfig {
67    // Specifies if proxy config is direct, auto-detect, using pac script,
68    // single-proxy, or proxy-per-scheme.
69    enum Mode {
70      MODE_DIRECT,
71      MODE_AUTO_DETECT,
72      MODE_PAC_SCRIPT,
73      MODE_SINGLE_PROXY,
74      MODE_PROXY_PER_SCHEME,
75    };
76
77    // Proxy setting for mode = direct or auto-detect or using pac script.
78    struct AutomaticProxy {
79      GURL pac_url;  // Set if proxy is using pac script.
80    };
81
82    // Proxy setting for mode = single-proxy or proxy-per-scheme.
83    struct ManualProxy {
84      net::ProxyServer server;
85    };
86
87    ProxyConfig();
88    ~ProxyConfig();
89
90    // Converts net::ProxyConfig to |this|.
91    bool FromNetProxyConfig(const net::ProxyConfig& net_config);
92
93    // Converts |this| to Dictionary of ProxyConfigDictionary format (which
94    // is the same format used by prefs).
95    DictionaryValue* ToPrefProxyConfig();
96
97    // Map |scheme| (one of "http", "https", "ftp" or "socks") to the correct
98    // ManualProxy.  Returns NULL if scheme is invalid.
99    ManualProxy* MapSchemeToProxy(const std::string& scheme);
100
101    // Serializes config into a ProxyConfigDictionary and then std::string
102    // persisted as string property in shill for a network.
103    bool SerializeForNetwork(std::string* output);
104
105    // Encodes the proxy server as "<url-scheme>=<proxy-scheme>://<proxy>"
106    static void EncodeAndAppendProxyServer(const std::string& url_scheme,
107                                           const net::ProxyServer& server,
108                                           std::string* spec);
109
110    Mode mode;
111
112    ProxyPrefs::ConfigState state;
113
114    // True if user can modify proxy settings via UI.
115    // If proxy is managed by policy or extension or other_precde or is for
116    // shared network but kUseSharedProxies is turned off, it can't be modified
117    // by user.
118    bool user_modifiable;
119
120    // Set if mode is MODE_DIRECT or MODE_AUTO_DETECT or MODE_PAC_SCRIPT.
121    AutomaticProxy  automatic_proxy;
122    // Set if mode is MODE_SINGLE_PROXY.
123    ManualProxy     single_proxy;
124    // Set if mode is MODE_PROXY_PER_SCHEME and has http proxy.
125    ManualProxy     http_proxy;
126    // Set if mode is MODE_PROXY_PER_SCHEME and has https proxy.
127    ManualProxy     https_proxy;
128    // Set if mode is MODE_PROXY_PER_SCHEME and has ftp proxy.
129    ManualProxy     ftp_proxy;
130    // Set if mode is MODE_PROXY_PER_SCHEME and has socks proxy.
131    ManualProxy     socks_proxy;
132
133    // Exceptions for when not to use a proxy.
134    net::ProxyBypassRules  bypass_rules;
135  };
136
137  // Constructor.
138  explicit ProxyConfigServiceImpl(PrefService* pref_service);
139  virtual ~ProxyConfigServiceImpl();
140
141  // Called by UI to set service path of |network| to be displayed or edited.
142  // Subsequent UISet* methods will use this network, until UI calls it again
143  // with a different network.
144  void UISetCurrentNetwork(const std::string& current_network);
145
146  // Called from UI to make the currently active network the one to be displayed
147  // or edited. Subsequent UISet* methods will use this network until UI calls
148  // it again when the active network has changed.
149  void UIMakeActiveNetworkCurrent();
150
151  // Called from UI to get name of the current network set via
152  // UISetCurrentNetwork or UIMakeActiveNetworkCurrent.
153  void UIGetCurrentNetworkName(std::string* network_name);
154
155  // Called from UI to retrieve proxy configuration in |current_ui_config_|.
156  void UIGetProxyConfig(ProxyConfig* config);
157
158  // Called from UI to update proxy configuration for different modes.
159  // Returns true if config is set properly and persisted to shill for the
160  // current network (set via UISetCurrentNetwork/UIMakeActiveNetworkCurrent).
161  // If this network is also currently active, config service proceeds to start
162  // activating it on network stack.
163  // Returns false if config is not set properly, probably because information
164  // is incomplete or invalid; while config service won't proceed to activate or
165  // persist this config, the information is "cached" in the service, so that
166  // the next UIGetProxyConfig call will return this latest information.
167  bool UISetProxyConfigToDirect();
168  bool UISetProxyConfigToAutoDetect();
169  bool UISetProxyConfigToPACScript(const GURL& pac_url);
170  bool UISetProxyConfigToSingleProxy(const net::ProxyServer& server);
171  // |scheme| is one of "http", "https", "ftp" or "socks".
172  bool UISetProxyConfigToProxyPerScheme(const std::string& scheme,
173                                        const net::ProxyServer& server);
174  // Only valid for MODE_SINGLE_PROXY or MODE_PROXY_PER_SCHEME.
175  bool UISetProxyConfigBypassRules(const net::ProxyBypassRules& bypass_rules);
176
177  // Add/Remove callback functions for notification when network to be viewed is
178  // changed by the UI.
179  void AddNotificationCallback(base::Closure callback);
180  void RemoveNotificationCallback(base::Closure callback);
181
182  // PrefProxyConfigTrackerImpl implementation.
183  virtual void OnProxyConfigChanged(ProxyPrefs::ConfigState config_state,
184                                    const net::ProxyConfig& config) OVERRIDE;
185
186  // NetworkLibrary::NetworkManagerObserver implementation.
187  virtual void OnNetworkManagerChanged(NetworkLibrary* cros) OVERRIDE;
188
189  // NetworkLibrary::NetworkObserver implementation.
190  virtual void OnNetworkChanged(NetworkLibrary* cros,
191                                const Network* network) OVERRIDE;
192
193  // Parse |proxy_config_string| and store result in |proxy_config|.
194  // Returns true if proxy config was successfully parsed.
195  static bool ParseProxyConfig(const std::string& proxy_config_string,
196                               net::ProxyConfig* proxy_config);
197
198  // Register UseShardProxies preference.
199  static void RegisterPrefs(PrefRegistrySimple* registry);
200  static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
201
202#if defined(UNIT_TEST)
203  void SetTesting(ProxyConfig* test_config) {
204    UIMakeActiveNetworkCurrent();
205    if (test_config) {
206      std::string value;
207      test_config->SerializeForNetwork(&value);
208      SetProxyConfigForNetwork(active_network_, value, false);
209    }
210  }
211#endif  // defined(UNIT_TEST)
212
213 private:
214  // Called when the kUseSharedProxies preference changes.
215  void OnUseSharedProxiesChanged();
216
217  // Called from the various UISetProxyConfigTo*.
218  void OnUISetProxyConfig();
219
220  // Called from OnNetworkManagerChanged and OnNetworkChanged for currently
221  // active network, to handle previously active network, new active network,
222  // and if necessary, activates proxy setting of new network.
223  void OnActiveNetworkChanged(NetworkLibrary* cros,
224                              const Network* active_network);
225
226  // Sets proxy config for |network_path| into shill and activates setting
227  // if the network is currently active.  If |only_set_if_empty| is true,
228  // proxy will be set and saved only if network has no proxy.
229  void SetProxyConfigForNetwork(const std::string& network_path,
230                                const std::string& value,
231                                bool only_set_if_empty);
232
233  // Returns value of UseSharedProxies preference if it's not default, else
234  // returns false if user is logged in and true otherwise.
235  bool GetUseSharedProxies();
236
237  // Returns true if proxy is to be ignored for network, which happens if
238  // network is shared and use-shared-proxies is turned off.
239  bool IgnoreProxy(const Network* network);
240
241  // Determines effective proxy config based on prefs from config tracker,
242  // |network| and if user is using shared proxies.
243  // If |activate| is true, effective config is stored in |active_config_| and
244  // activated on network stack, and hence, picked up by observers.
245  // if |activate| is false, effective config is stored in |current_ui_config_|
246  // but not activated on network stack, and hence, not picked up by observers.
247  void DetermineEffectiveConfig(const Network* network, bool activate);
248
249  // Determines |current_ui_config_| based on |network|, called from
250  // UISetCurrentNetwork and UIMakeActiveNetworkActive.
251  void OnUISetCurrentNetwork(const Network* network);
252
253  // Reset UI cache variables that keep track of UI activities.
254  void ResetUICache();
255
256  void FetchProxyPolicy();
257
258  // Data members.
259
260  // Service path of currently active network (determined via shill
261  // notifications); if effective proxy config is from system, proxy of this
262  // network will be the one taking effect.
263  std::string active_network_;
264
265  // State of |active_config_|.  |active_config_| is only valid if
266  // |active_config_state_| is not ProxyPrefs::CONFIG_UNSET.
267  ProxyPrefs::ConfigState active_config_state_;
268
269  // Active proxy configuration, which could be from prefs or network.
270  net::ProxyConfig active_config_;
271
272  // Service path of network whose proxy configuration is being displayed or
273  // edited via UI, separate from |active_network_| which may be same or
274  // different.
275  std::string current_ui_network_;
276
277  // Proxy configuration of |current_ui_network_|.
278  ProxyConfig current_ui_config_;
279
280  // Track changes in UseSharedProxies user preference.
281  BooleanPrefMember use_shared_proxies_;
282
283  // Callbacks for notification when network to be viewed has been changed from
284  // the UI.
285  std::vector<base::Closure> callbacks_;
286
287  base::WeakPtrFactory<ProxyConfigServiceImpl> pointer_factory_;
288
289  DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceImpl);
290};
291
292}  // namespace chromeos
293
294#endif  // CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_
295