proxy_config_service_impl.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1// Copyright (c) 2011 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#pragma once
8
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/observer_list.h"
16#include "base/values.h"
17#include "chrome/browser/chromeos/login/signed_settings.h"
18#include "net/proxy/proxy_config.h"
19#include "net/proxy/proxy_config_service.h"
20#include "net/proxy/proxy_server.h"
21
22namespace chromeos {
23
24// Implementation of proxy config service for chromeos that:
25// - is RefCountedThreadSafe
26// - is wrapped by chromeos::ProxyConfigService which implements
27//   net::ProxyConfigService interface by fowarding the methods to this class
28// - retrieves initial system proxy configuration from cros settings persisted
29//   on chromeos device
30// - provides network stack with latest system proxy configuration for use on
31//   IO thread
32// - provides UI with methods to retrieve and modify system proxy configuration
33//   on UI thread
34// - TODO(kuan): persists proxy configuration settings on chromeos device using
35//   cros settings
36class ProxyConfigServiceImpl
37    : public base::RefCountedThreadSafe<ProxyConfigServiceImpl>,
38      public SignedSettings::Delegate<bool>,
39      public SignedSettings::Delegate<std::string> {
40 public:
41  // ProxyConfigServiceImpl is created on the UI thread in
42  // chrome/browser/net/proxy_service_factory.cc::CreateProxyConfigService
43  // via BrowserProcess::chromeos_proxy_config_service_impl, and stored in
44  // g_browser_process as a scoped_refptr (because it's RefCountedThreadSafe).
45  //
46  // Past that point, it can be accessed from the IO or UI threads.
47  //
48  // From the IO thread, it is accessed periodically through the wrapper class
49  // chromeos::ProxyConfigService via net::ProxyConfigService interface
50  // (GetLatestProxyConfig, AddObserver, RemoveObserver).
51  //
52  // From the UI thread, it is accessed via
53  // BrowserProcess::chromeos_proxy_config_service_impl to allow user to read
54  // or modify the proxy configuration via UIGetProxyConfig or
55  // UISetProxyConfigTo* respectively.
56  // The new modified proxy config is posted to the IO thread through
57  // SetNewProxyConfig().  We then notify observers on the IO thread of the
58  // configuration change.
59
60  // In contrary to other platforms which simply use the systems' UI to allow
61  // users to configure proxies, we have to implement our own UI on the chromeos
62  // device.  This requires extra and specific UI requirements that
63  // net::ProxyConfig does not suffice.  So we create an augmented analog to
64  // net:ProxyConfig here to include and handle these UI requirements, e.g.
65  // - where configuration was picked up from - policy or owner
66  // - the read/write access of a proxy setting
67  // - may add more stuff later.
68  // This is then converted to the common net::ProxyConfig before being returned
69  // to ProxyService::GetLatestProxyConfig on the IO thread to be used on the
70  // network stack.
71  struct ProxyConfig {
72    // Specifies if proxy config is direct, auto-detect, using pac script,
73    // single-proxy, or proxy-per-scheme.
74    enum Mode {
75      MODE_DIRECT,
76      MODE_AUTO_DETECT,
77      MODE_PAC_SCRIPT,
78      MODE_SINGLE_PROXY,
79      MODE_PROXY_PER_SCHEME,
80    };
81
82    // Specifies where proxy configuration was picked up from.
83    enum Source {
84      SOURCE_NONE,    // No default configuration.
85      SOURCE_POLICY,  // Configuration is from policy.
86      SOURCE_OWNER,   // Configuration is from owner.
87    };
88
89    struct Setting {
90      Setting() : source(SOURCE_NONE) {}
91      bool CanBeWrittenByUser(bool user_is_owner);
92
93      Source source;
94    };
95
96    // Proxy setting for mode = direct or auto-detect or using pac script.
97    struct AutomaticProxy : public Setting {
98      GURL    pac_url;  // Set if proxy is using pac script.
99    };
100
101    // Proxy setting for mode = single-proxy or proxy-per-scheme.
102    struct ManualProxy : public Setting {
103      net::ProxyServer  server;
104    };
105
106    ProxyConfig() : mode(MODE_DIRECT) {}
107
108    // Converts |this| to net::ProxyConfig.
109    void ToNetProxyConfig(net::ProxyConfig* net_config);
110
111    // Returns true if proxy config can be written by user.
112    // If mode is MODE_PROXY_PER_SCHEME, |scheme| is one of "http", "https",
113    // "ftp" or "socks"; otherwise, it should be empty or will be ignored.
114    bool CanBeWrittenByUser(bool user_is_owner, const std::string& scheme);
115
116    // Map |scheme| (one of "http", "https", "ftp" or "socks") to the correct
117    // ManualProxy.  Returns NULL if scheme is invalid.
118    ManualProxy* MapSchemeToProxy(const std::string& scheme);
119
120    // Serializes config into a DictionaryValue and then into std::string
121    // persisted as property on device.
122    bool Serialize(std::string* output);
123    // Deserializes from property value on device as std::string into a
124    // DictionaryValue and then into the config.  Opposite of Serialize.
125    bool Deserialize(const std::string& input);
126
127    // Creates a textual dump of the configuration.
128    std::string ToString() const;
129
130    Mode mode;
131
132    // Set if mode is MODE_DIRECT or MODE_AUTO_DETECT or MODE_PAC_SCRIPT.
133    AutomaticProxy  automatic_proxy;
134    // Set if mode is MODE_SINGLE_PROXY.
135    ManualProxy     single_proxy;
136    // Set if mode is MODE_PROXY_PER_SCHEME and has http proxy.
137    ManualProxy     http_proxy;
138    // Set if mode is MODE_PROXY_PER_SCHEME and has https proxy.
139    ManualProxy     https_proxy;
140    // Set if mode is MODE_PROXY_PER_SCHEME and has ftp proxy.
141    ManualProxy     ftp_proxy;
142    // Set if mode is MODE_PROXY_PER_SCHEME and has socks proxy.
143    ManualProxy     socks_proxy;
144
145    // Exceptions for when not to use a proxy.
146    net::ProxyBypassRules  bypass_rules;
147
148   private:
149    // Encodes the proxy server as "<url-scheme>=<proxy-scheme>://<proxy>"
150    static void EncodeAndAppendProxyServer(const std::string& scheme,
151                                           const net::ProxyServer& server,
152                                           std::string* spec);
153  };
154
155  // Usual constructor.
156  ProxyConfigServiceImpl();
157  // Constructor for testing.
158  // |init_config| specifies the ProxyConfig to use for initialization.
159  explicit ProxyConfigServiceImpl(const ProxyConfig& init_config);
160  virtual ~ProxyConfigServiceImpl();
161
162  // Methods called on IO thread from wrapper class chromeos::ProxyConfigService
163  // as ProxyConfigService methods.
164  void AddObserver(net::ProxyConfigService::Observer* observer);
165  void RemoveObserver(net::ProxyConfigService::Observer* observer);
166  // Called from GetLatestProxyConfig.
167  net::ProxyConfigService::ConfigAvailability IOGetProxyConfig(
168      net::ProxyConfig* config);
169
170  // Called from UI thread to retrieve proxy configuration in |config|.
171  void UIGetProxyConfig(ProxyConfig* config);
172
173  // Called from UI thread to set flag to persist settings to device.
174  // Subsequent UISet* methods will use this flag, until UI calls it again with
175  // a different flag.
176  void UISetPersistToDevice(bool persist) {
177    persist_to_device_ = persist;
178  }
179
180  // Called from UI thread to update proxy configuration for different modes.
181  // Returns true if config is set properly and config service has proceeded to
182  // start activating it on network stack and persisting it to device.
183  // Returns false if config is not set properly, probably because information
184  // is incomplete or invalid; while config service won't proceed to activate or
185  // persist this config, the information is "cached" in the service, so that
186  // the next UIGetProxyConfig call will return this latest information.
187  bool UISetProxyConfigToDirect();
188  bool UISetProxyConfigToAutoDetect();
189  bool UISetProxyConfigToPACScript(const GURL& pac_url);
190  bool UISetProxyConfigToSingleProxy(const net::ProxyServer& server);
191  // |scheme| is one of "http", "https", "ftp" or "socks".
192  bool UISetProxyConfigToProxyPerScheme(const std::string& scheme,
193                                        const net::ProxyServer& server);
194  // Only valid for MODE_SINGLE_PROXY or MODE_PROXY_PER_SCHEME.
195  bool UISetProxyConfigBypassRules(const net::ProxyBypassRules& bypass_rules);
196
197  // Implementation for SignedSettings::Delegate
198  virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
199                                     std::string value);
200  virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
201                                     bool value);
202
203 private:
204  friend class base::RefCountedThreadSafe<ProxyConfigServiceImpl>;
205
206  // Persists proxy config to device.
207  void PersistConfigToDevice();
208
209  // Called from UI thread from the various UISetProxyConfigTo*
210  // |update_to_device| is true to persist new proxy config to device.
211  void OnUISetProxyConfig(bool update_to_device);
212
213  // Posted from UI thread to IO thread to carry the new config information.
214  void IOSetProxyConfig(
215      const ProxyConfig& new_config,
216      net::ProxyConfigService::ConfigAvailability new_availability);
217
218  // Checks that method is called on BrowserThread::IO thread.
219  void CheckCurrentlyOnIOThread();
220
221  // Checks that method is called on BrowserThread::UI thread.
222  void CheckCurrentlyOnUIThread();
223
224  // Data members.
225
226  // True if tasks can be posted, which can only happen if constructor has
227  // completed (NewRunnableMethod cannot be created for a RefCountedThreadBase's
228  // method until the class's ref_count is at least one).
229  bool can_post_task_;
230
231  // Availability status of the configuration.
232  net::ProxyConfigService::ConfigAvailability config_availability_;
233
234  // True if settings are to be persisted to device.
235  bool persist_to_device_;
236
237  // True if there's a pending operation to store proxy setting to device.
238  bool persist_to_device_pending_;
239
240  // Cached proxy configuration, to be converted to net::ProxyConfig and
241  // returned by IOGetProxyConfig.
242  // Initially populated from the UI thread, but afterwards only accessed from
243  // the IO thread.
244  ProxyConfig cached_config_;
245
246  // Copy of the proxy configuration kept on the UI thread of the last seen
247  // proxy config, so as to avoid posting a call to SetNewProxyConfig when we
248  // are called by UI to set new proxy but the config has not actually changed.
249  ProxyConfig reference_config_;
250
251  // List of observers for changes in proxy config.
252  ObserverList<net::ProxyConfigService::Observer> observers_;
253
254  // Operations to retrieve and store proxy setting from and to device
255  // respectively.
256  scoped_refptr<SignedSettings> retrieve_property_op_;
257  scoped_refptr<SignedSettings> store_property_op_;
258
259  DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceImpl);
260};
261
262}  // namespace chromeos
263
264#endif  // CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_
265