OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NET_PROXY_PROXY_CONFIG_SERVICE_LINUX_H_ | 5 #ifndef NET_PROXY_PROXY_CONFIG_SERVICE_LINUX_H_ |
6 #define NET_PROXY_PROXY_CONFIG_SERVICE_LINUX_H_ | 6 #define NET_PROXY_PROXY_CONFIG_SERVICE_LINUX_H_ |
7 | 7 |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "base/message_loop.h" |
| 13 #include "base/ref_counted.h" |
12 #include "base/scoped_ptr.h" | 14 #include "base/scoped_ptr.h" |
| 15 #include "net/proxy/proxy_config.h" |
13 #include "net/proxy/proxy_config_service.h" | 16 #include "net/proxy/proxy_config_service.h" |
14 #include "net/proxy/proxy_server.h" | 17 #include "net/proxy/proxy_server.h" |
15 | 18 |
16 namespace net { | 19 namespace net { |
17 | 20 |
18 // Implementation of ProxyConfigService that retrieves the system proxy | 21 // Implementation of ProxyConfigService that retrieves the system proxy |
19 // settings from environment variables or gconf. | 22 // settings from environment variables or gconf. |
20 class ProxyConfigServiceLinux : public ProxyConfigService { | 23 class ProxyConfigServiceLinux : public ProxyConfigService { |
21 public: | 24 public: |
22 | 25 |
23 // These are used to derive mocks for unittests. | 26 // These are used to derive mocks for unittests. |
24 class EnvironmentVariableGetter { | 27 class EnvironmentVariableGetter { |
25 public: | 28 public: |
26 virtual ~EnvironmentVariableGetter() {} | 29 virtual ~EnvironmentVariableGetter() {} |
27 // Gets an environment variable's value and stores it in | 30 // Gets an environment variable's value and stores it in |
28 // result. Returns false if the key is unset. | 31 // result. Returns false if the key is unset. |
29 virtual bool Getenv(const char* variable_name, std::string* result) = 0; | 32 virtual bool Getenv(const char* variable_name, std::string* result) = 0; |
30 }; | 33 }; |
31 | 34 |
32 class GConfSettingGetter { | 35 class GConfSettingGetter { |
33 public: | 36 public: |
34 virtual ~GConfSettingGetter() {} | 37 virtual ~GConfSettingGetter() {} |
35 | 38 |
36 // GDK/GTK+ thread-safety: multi-threaded programs coordinate | |
37 // around a global lock. See | |
38 // http://library.gnome.org/devel/gdk/unstable/gdk-Threads.html | |
39 // and http://research.operationaldynamics.com/blogs/andrew/software/gnome-d
esktop/gtk-thread-awareness.html | |
40 // The following methods are used to grab said lock around any | |
41 // actual gconf usage: including calls to Init() and any of the | |
42 // Get* methods. | |
43 virtual void Enter() = 0; | |
44 virtual void Leave() = 0; | |
45 | |
46 // Initializes the class: obtains a gconf client, in the concrete | 39 // Initializes the class: obtains a gconf client, in the concrete |
47 // implementation. Returns true on success. Must be called before | 40 // implementation. Returns true on success. Must be called before |
48 // any of the Get* methods, and the Get* methods must not be used | 41 // using other methods. |
49 // if this method returns false. This method may be called again, | 42 virtual bool Init() = 0; |
50 // whether or not it succeeded before. | |
51 virtual bool InitIfNeeded() = 0; | |
52 | 43 |
53 // Gets a string type value from gconf and stores it in result. Returns | 44 // Releases the gconf client, which clears cached directories and |
54 // false if the key is unset or on error. | 45 // stops notifications. |
| 46 virtual void Release() = 0; |
| 47 |
| 48 // Requests notification of gconf setting changes for proxy |
| 49 // settings. Returns true on success. |
| 50 virtual bool SetupNotification(void* callback_user_data) = 0; |
| 51 |
| 52 // Gets a string type value from gconf and stores it in |
| 53 // result. Returns false if the key is unset or on error. Must |
| 54 // only be called after a successful call to Init(), and not |
| 55 // after a failed call to SetupNotification() or after calling |
| 56 // Release(). |
55 virtual bool GetString(const char* key, std::string* result) = 0; | 57 virtual bool GetString(const char* key, std::string* result) = 0; |
56 // Same thing for a bool typed value. | 58 // Same thing for a bool typed value. |
57 virtual bool GetBoolean(const char* key, bool* result) = 0; | 59 virtual bool GetBoolean(const char* key, bool* result) = 0; |
58 // Same for an int typed value. | 60 // Same for an int typed value. |
59 virtual bool GetInt(const char* key, int* result) = 0; | 61 virtual bool GetInt(const char* key, int* result) = 0; |
60 // And for a string list. | 62 // And for a string list. |
61 virtual bool GetStringList(const char* key, | 63 virtual bool GetStringList(const char* key, |
62 std::vector<std::string>* result) = 0; | 64 std::vector<std::string>* result) = 0; |
63 }; | 65 }; |
64 | 66 |
| 67 // ProxyConfigServiceLinux is created on the UI thread, and |
| 68 // SetupAndFetchInitialConfig() is immediately called to |
| 69 // synchronously fetch the original configuration and setup gconf |
| 70 // notifications on the UI thread. |
| 71 // |
| 72 // Passed that point, it is accessed periodically through |
| 73 // GetProxyConfig() from the IO thread. |
| 74 // |
| 75 // gconf change notification callbacks can occur at any time and are |
| 76 // run on the UI thread. The new gconf settings are fetched on the |
| 77 // UI thread, and the new resulting proxy config is posted to the IO |
| 78 // thread through Delegate::SetNewProxyConfig(). |
| 79 // |
| 80 // ProxyConfigServiceLinux is deleted from the IO thread. |
| 81 // |
| 82 // The substance of the ProxyConfigServiceLinux implementation is |
| 83 // wrapped in the Delegate ref counted class. On deleting the |
| 84 // ProxyConfigServiceLinux, Delegate::OnDestroy() is posted to the |
| 85 // UI thread where gconf notifications will be safely stopped before |
| 86 // releasing Delegate. |
| 87 |
| 88 class Delegate : public base::RefCountedThreadSafe<Delegate> { |
| 89 public: |
| 90 // Constructor receives gconf and env var getter implementations |
| 91 // to use, and takes ownership of them. |
| 92 Delegate(EnvironmentVariableGetter* env_var_getter, |
| 93 GConfSettingGetter* gconf_getter); |
| 94 // Synchronously obtains the proxy configuration. If gconf is |
| 95 // used, also enables gconf notification for setting |
| 96 // changes. gconf must only be accessed from the thread running |
| 97 // the default glib main loop, and so this method must be called |
| 98 // from the UI thread. The message loop for the IO thread is |
| 99 // specified so that notifications can post tasks to it (and for |
| 100 // assertions). |
| 101 void SetupAndFetchInitialConfig(MessageLoop* glib_default_loop, |
| 102 MessageLoop* io_loop); |
| 103 // Resets cached_config_ and releases the gconf_getter_, making it |
| 104 // possible to call SetupAndFetchInitialConfig() again. Only used |
| 105 // in testing. |
| 106 void Reset(); |
| 107 |
| 108 // Handler for gconf change notifications: fetches a new proxy |
| 109 // configuration from gconf settings, and if this config is |
| 110 // different than what we had before, posts a task to have it |
| 111 // stored in cached_config_. |
| 112 // Left public for simplicity. |
| 113 void OnCheckProxyConfigSettings(); |
| 114 |
| 115 // Called from IO thread. |
| 116 int GetProxyConfig(ProxyConfig* config); |
| 117 |
| 118 // Posts a call to OnDestroy() to the UI thread. Called from |
| 119 // ProxyConfigServiceLinux's destructor. |
| 120 void PostDestroyTask(); |
| 121 // Safely stops gconf notifications. Posted to the UI thread. |
| 122 void OnDestroy(); |
| 123 |
| 124 private: |
| 125 // Obtains an environment variable's value. Parses a proxy server |
| 126 // specification from it and puts it in result. Returns true if the |
| 127 // requested variable is defined and the value valid. |
| 128 bool GetProxyFromEnvVarForScheme(const char* variable, |
| 129 ProxyServer::Scheme scheme, |
| 130 ProxyServer* result_server); |
| 131 // As above but with scheme set to HTTP, for convenience. |
| 132 bool GetProxyFromEnvVar(const char* variable, ProxyServer* result_server); |
| 133 // Fills proxy config from environment variables. Returns true if |
| 134 // variables were found and the configuration is valid. |
| 135 bool GetConfigFromEnv(ProxyConfig* config); |
| 136 |
| 137 // Obtains host and port gconf settings and parses a proxy server |
| 138 // specification from it and puts it in result. Returns true if the |
| 139 // requested variable is defined and the value valid. |
| 140 bool GetProxyFromGConf(const char* key_prefix, bool is_socks, |
| 141 ProxyServer* result_server); |
| 142 // Fills proxy config from gconf. Returns true if settings were found |
| 143 // and the configuration is valid. |
| 144 bool GetConfigFromGConf(ProxyConfig* config); |
| 145 |
| 146 // Returns true if environment variables indicate that we are |
| 147 // running GNOME (and therefore we want to use gconf settings). |
| 148 bool ShouldTryGConf(); |
| 149 |
| 150 // This method is posted from the UI thread to the IO thread to |
| 151 // carry the new config information. |
| 152 void SetNewProxyConfig(const ProxyConfig& new_config); |
| 153 |
| 154 scoped_ptr<EnvironmentVariableGetter> env_var_getter_; |
| 155 scoped_ptr<GConfSettingGetter> gconf_getter_; |
| 156 |
| 157 // Cached proxy configuration, to be returned by |
| 158 // GetProxyConfig. Initially populated from the UI thread, but |
| 159 // afterwards only accessed from the IO thread. |
| 160 ProxyConfig cached_config_; |
| 161 |
| 162 // A copy kept on the UI thread of the last seen proxy config, so as |
| 163 // to avoid posting a call to SetNewProxyConfig when we get a |
| 164 // notification but the config has not actually changed. |
| 165 ProxyConfig reference_config_; |
| 166 |
| 167 // The MessageLoop for the UI thread, aka main browser thread. This |
| 168 // thread is where we run the glib main loop (see |
| 169 // base/message_pump_glib.h). It is the glib default loop in the |
| 170 // sense that it runs the glib default context: as in the context |
| 171 // where sources are added by g_timeout_add and g_idle_add, and |
| 172 // returned by g_main_context_default. gconf uses glib timeouts and |
| 173 // idles and possibly other callbacks that will all be dispatched on |
| 174 // this thread. Since gconf is not thread safe, any use of gconf |
| 175 // must be done on the thread running this loop. |
| 176 MessageLoop* glib_default_loop_; |
| 177 // MessageLoop for the IO thread. GetProxyConfig() is called from |
| 178 // the thread running this loop. |
| 179 MessageLoop* io_loop_; |
| 180 |
| 181 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 182 }; |
| 183 |
| 184 // Thin wrapper shell around Delegate. |
| 185 |
65 // Usual constructor | 186 // Usual constructor |
66 ProxyConfigServiceLinux(); | 187 ProxyConfigServiceLinux(); |
67 // For testing: pass in alternate gconf and env var getter implementations. | 188 // For testing: takes alternate gconf and env var getter implementations. |
68 // ProxyConfigServiceLinux takes ownership of the getter objects. | |
69 ProxyConfigServiceLinux(EnvironmentVariableGetter* env_var_getter, | 189 ProxyConfigServiceLinux(EnvironmentVariableGetter* env_var_getter, |
70 GConfSettingGetter* gconf_getter); | 190 GConfSettingGetter* gconf_getter); |
71 | 191 |
| 192 virtual ~ProxyConfigServiceLinux() { |
| 193 delegate_->PostDestroyTask(); |
| 194 } |
| 195 |
| 196 void SetupAndFetchInitialConfig(MessageLoop* glib_default_loop, |
| 197 MessageLoop* io_loop) { |
| 198 delegate_->SetupAndFetchInitialConfig(glib_default_loop, io_loop); |
| 199 } |
| 200 void Reset() { |
| 201 delegate_->Reset(); |
| 202 } |
| 203 void OnCheckProxyConfigSettings() { |
| 204 delegate_->OnCheckProxyConfigSettings(); |
| 205 } |
| 206 |
72 // ProxyConfigService methods: | 207 // ProxyConfigService methods: |
73 virtual int GetProxyConfig(ProxyConfig* config); | 208 // Called from IO thread. |
| 209 virtual int GetProxyConfig(ProxyConfig* config) { |
| 210 return delegate_->GetProxyConfig(config); |
| 211 } |
74 | 212 |
75 private: | 213 private: |
76 // Obtains an environment variable's value. Parses a proxy server | 214 scoped_refptr<Delegate> delegate_; |
77 // specification from it and puts it in result. Returns true if the | |
78 // requested variable is defined and the value valid. | |
79 bool GetProxyFromEnvVarForScheme(const char* variable, | |
80 ProxyServer::Scheme scheme, | |
81 ProxyServer* result_server); | |
82 // As above but with scheme set to HTTP, for convenience. | |
83 bool GetProxyFromEnvVar(const char* variable, ProxyServer* result_server); | |
84 | |
85 // Fills proxy config from environment variables. Returns true if | |
86 // variables were found and the configuration is valid. | |
87 bool GetConfigFromEnv(ProxyConfig* config); | |
88 | |
89 // Obtains host and port gconf settings and parses a proxy server | |
90 // specification from it and puts it in result. Returns true if the | |
91 // requested variable is defined and the value valid. | |
92 bool GetProxyFromGConf(const char* key_prefix, bool is_socks, | |
93 ProxyServer* result_server); | |
94 // Fills proxy config from gconf. Returns true if settings were found | |
95 // and the configuration is valid. | |
96 bool GetConfigFromGConf(ProxyConfig* config); | |
97 | |
98 scoped_ptr<EnvironmentVariableGetter> env_var_getter_; | |
99 scoped_ptr<GConfSettingGetter> gconf_getter_; | |
100 | 215 |
101 DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceLinux); | 216 DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceLinux); |
102 }; | 217 }; |
103 | 218 |
104 } // namespace net | 219 } // namespace net |
105 | 220 |
106 #endif // NET_PROXY_PROXY_CONFIG_SERVICE_LINUX_H_ | 221 #endif // NET_PROXY_PROXY_CONFIG_SERVICE_LINUX_H_ |
OLD | NEW |