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