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 22 namespace 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 36 class 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 { SettingProxyConfig::Setting90 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 ProxyConfigProxyConfig106 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. UISetPersistToDevice(bool persist)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