Home | History | Annotate | Download | only in chromeos
      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 {
     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