summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/proxy_config_service_impl.h
blob: 7256a64767dc28b2f23c10066a99d652aaae8125 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_
#pragma once

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/values.h"
#include "chrome/browser/chromeos/login/signed_settings.h"
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_server.h"

namespace chromeos {

// Implementation of proxy config service for chromeos that:
// - is RefCountedThreadSafe
// - is wrapped by chromeos::ProxyConfigService which implements
//   net::ProxyConfigService interface by fowarding the methods to this class
// - retrieves initial system proxy configuration from cros settings persisted
//   on chromeos device
// - provides network stack with latest system proxy configuration for use on
//   IO thread
// - provides UI with methods to retrieve and modify system proxy configuration
//   on UI thread
// - TODO(kuan): persists proxy configuration settings on chromeos device using
//   cros settings
class ProxyConfigServiceImpl
    : public base::RefCountedThreadSafe<ProxyConfigServiceImpl>,
      public SignedSettings::Delegate<bool>,
      public SignedSettings::Delegate<std::string> {
 public:
  // ProxyConfigServiceImpl is created on the UI thread in
  // chrome/browser/net/proxy_service_factory.cc::CreateProxyConfigService
  // via BrowserProcess::chromeos_proxy_config_service_impl, and stored in
  // g_browser_process as a scoped_refptr (because it's RefCountedThreadSafe).
  //
  // Past that point, it can be accessed from the IO or UI threads.
  //
  // From the IO thread, it is accessed periodically through the wrapper class
  // chromeos::ProxyConfigService via net::ProxyConfigService interface
  // (GetLatestProxyConfig, AddObserver, RemoveObserver).
  //
  // From the UI thread, it is accessed via
  // BrowserProcess::chromeos_proxy_config_service_impl to allow user to read
  // or modify the proxy configuration via UIGetProxyConfig or
  // UISetProxyConfigTo* respectively.
  // The new modified proxy config is posted to the IO thread through
  // SetNewProxyConfig().  We then notify observers on the IO thread of the
  // configuration change.

  // In contrary to other platforms which simply use the systems' UI to allow
  // users to configure proxies, we have to implement our own UI on the chromeos
  // device.  This requires extra and specific UI requirements that
  // net::ProxyConfig does not suffice.  So we create an augmented analog to
  // net:ProxyConfig here to include and handle these UI requirements, e.g.
  // - where configuration was picked up from - policy or owner
  // - the read/write access of a proxy setting
  // - may add more stuff later.
  // This is then converted to the common net::ProxyConfig before being returned
  // to ProxyService::GetLatestProxyConfig on the IO thread to be used on the
  // network stack.
  struct ProxyConfig {
    // Specifies if proxy config is direct, auto-detect, using pac script,
    // single-proxy, or proxy-per-scheme.
    enum Mode {
      MODE_DIRECT,
      MODE_AUTO_DETECT,
      MODE_PAC_SCRIPT,
      MODE_SINGLE_PROXY,
      MODE_PROXY_PER_SCHEME,
    };

    // Specifies where proxy configuration was picked up from.
    enum Source {
      SOURCE_NONE,    // No default configuration.
      SOURCE_POLICY,  // Configuration is from policy.
      SOURCE_OWNER,   // Configuration is from owner.
    };

    struct Setting {
      Setting() : source(SOURCE_NONE) {}
      bool CanBeWrittenByUser(bool user_is_owner);

      Source source;
    };

    // Proxy setting for mode = direct or auto-detect or using pac script.
    struct AutomaticProxy : public Setting {
      GURL    pac_url;  // Set if proxy is using pac script.
    };

    // Proxy setting for mode = single-proxy or proxy-per-scheme.
    struct ManualProxy : public Setting {
      net::ProxyServer  server;
    };

    ProxyConfig() : mode(MODE_DIRECT) {}

    // Converts |this| to net::ProxyConfig.
    void ToNetProxyConfig(net::ProxyConfig* net_config);

    // Returns true if proxy config can be written by user.
    // If mode is MODE_PROXY_PER_SCHEME, |scheme| is one of "http", "https",
    // "ftp" or "socks"; otherwise, it should be empty or will be ignored.
    bool CanBeWrittenByUser(bool user_is_owner, const std::string& scheme);

    // Map |scheme| (one of "http", "https", "ftp" or "socks") to the correct
    // ManualProxy.  Returns NULL if scheme is invalid.
    ManualProxy* MapSchemeToProxy(const std::string& scheme);

    // Serializes config into a DictionaryValue and then into std::string
    // persisted as property on device.
    bool Serialize(std::string* output);
    // Deserializes from property value on device as std::string into a
    // DictionaryValue and then into the config.  Opposite of Serialize.
    bool Deserialize(const std::string& input);

    // Creates a textual dump of the configuration.
    std::string ToString() const;

    Mode mode;

    // Set if mode is MODE_DIRECT or MODE_AUTO_DETECT or MODE_PAC_SCRIPT.
    AutomaticProxy  automatic_proxy;
    // Set if mode is MODE_SINGLE_PROXY.
    ManualProxy     single_proxy;
    // Set if mode is MODE_PROXY_PER_SCHEME and has http proxy.
    ManualProxy     http_proxy;
    // Set if mode is MODE_PROXY_PER_SCHEME and has https proxy.
    ManualProxy     https_proxy;
    // Set if mode is MODE_PROXY_PER_SCHEME and has ftp proxy.
    ManualProxy     ftp_proxy;
    // Set if mode is MODE_PROXY_PER_SCHEME and has socks proxy.
    ManualProxy     socks_proxy;

    // Exceptions for when not to use a proxy.
    net::ProxyBypassRules  bypass_rules;

   private:
    // Encodes the proxy server as "<url-scheme>=<proxy-scheme>://<proxy>"
    static void EncodeAndAppendProxyServer(const std::string& scheme,
                                           const net::ProxyServer& server,
                                           std::string* spec);
  };

  // Usual constructor.
  ProxyConfigServiceImpl();
  // Constructor for testing.
  // |init_config| specifies the ProxyConfig to use for initialization.
  explicit ProxyConfigServiceImpl(const ProxyConfig& init_config);
  virtual ~ProxyConfigServiceImpl();

  // Methods called on IO thread from wrapper class chromeos::ProxyConfigService
  // as ProxyConfigService methods.
  void AddObserver(net::ProxyConfigService::Observer* observer);
  void RemoveObserver(net::ProxyConfigService::Observer* observer);
  // Called from GetLatestProxyConfig.
  net::ProxyConfigService::ConfigAvailability IOGetProxyConfig(
      net::ProxyConfig* config);

  // Called from UI thread to retrieve proxy configuration in |config|.
  void UIGetProxyConfig(ProxyConfig* config);

  // Called from UI thread to set flag to persist settings to device.
  // Subsequent UISet* methods will use this flag, until UI calls it again with
  // a different flag.
  void UISetPersistToDevice(bool persist) {
    persist_to_device_ = persist;
  }

  // Called from UI thread to update proxy configuration for different modes.
  // Returns true if config is set properly and config service has proceeded to
  // start activating it on network stack and persisting it to device.
  // Returns false if config is not set properly, probably because information
  // is incomplete or invalid; while config service won't proceed to activate or
  // persist this config, the information is "cached" in the service, so that
  // the next UIGetProxyConfig call will return this latest information.
  bool UISetProxyConfigToDirect();
  bool UISetProxyConfigToAutoDetect();
  bool UISetProxyConfigToPACScript(const GURL& pac_url);
  bool UISetProxyConfigToSingleProxy(const net::ProxyServer& server);
  // |scheme| is one of "http", "https", "ftp" or "socks".
  bool UISetProxyConfigToProxyPerScheme(const std::string& scheme,
                                        const net::ProxyServer& server);
  // Only valid for MODE_SINGLE_PROXY or MODE_PROXY_PER_SCHEME.
  bool UISetProxyConfigBypassRules(const net::ProxyBypassRules& bypass_rules);

  // Implementation for SignedSettings::Delegate
  virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
                                     std::string value);
  virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
                                     bool value);

 private:
  friend class base::RefCountedThreadSafe<ProxyConfigServiceImpl>;

  // Persists proxy config to device.
  void PersistConfigToDevice();

  // Called from UI thread from the various UISetProxyConfigTo*
  // |update_to_device| is true to persist new proxy config to device.
  void OnUISetProxyConfig(bool update_to_device);

  // Posted from UI thread to IO thread to carry the new config information.
  void IOSetProxyConfig(
      const ProxyConfig& new_config,
      net::ProxyConfigService::ConfigAvailability new_availability);

  // Checks that method is called on BrowserThread::IO thread.
  void CheckCurrentlyOnIOThread();

  // Checks that method is called on BrowserThread::UI thread.
  void CheckCurrentlyOnUIThread();

  // Data members.

  // True if tasks can be posted, which can only happen if constructor has
  // completed (NewRunnableMethod cannot be created for a RefCountedThreadBase's
  // method until the class's ref_count is at least one).
  bool can_post_task_;

  // Availability status of the configuration.
  net::ProxyConfigService::ConfigAvailability config_availability_;

  // True if settings are to be persisted to device.
  bool persist_to_device_;

  // True if there's a pending operation to store proxy setting to device.
  bool persist_to_device_pending_;

  // Cached proxy configuration, to be converted to net::ProxyConfig and
  // returned by IOGetProxyConfig.
  // Initially populated from the UI thread, but afterwards only accessed from
  // the IO thread.
  ProxyConfig cached_config_;

  // Copy of the proxy configuration kept on the UI thread of the last seen
  // proxy config, so as to avoid posting a call to SetNewProxyConfig when we
  // are called by UI to set new proxy but the config has not actually changed.
  ProxyConfig reference_config_;

  // List of observers for changes in proxy config.
  ObserverList<net::ProxyConfigService::Observer> observers_;

  // Operations to retrieve and store proxy setting from and to device
  // respectively.
  scoped_refptr<SignedSettings> retrieve_property_op_;
  scoped_refptr<SignedSettings> store_property_op_;

  DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceImpl);
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CHROMEOS_PROXY_CONFIG_SERVICE_IMPL_H_