Index: net/proxy/proxy_config_service_linux.cc |
=================================================================== |
--- net/proxy/proxy_config_service_linux.cc (revision 0) |
+++ net/proxy/proxy_config_service_linux.cc (revision 0) |
@@ -0,0 +1,306 @@ |
+// Copyright (c) 2009 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. |
+ |
+#include "net/proxy/proxy_config_service_linux.h" |
+ |
+#include <ctype.h> |
+#include <string.h> |
+#include <gdk/gdk.h> |
+#include <gconf/gconf-client.h> |
+ |
+#include <string> |
+#include <sstream> |
+#include <vector> |
+ |
+#include "base/string_tokenizer.h" |
+#include "base/sys_string_conversions.h" |
+#include "net/base/net_errors.h" |
+#include "net/proxy/proxy_config.h" |
+#include "net/proxy/proxy_info.h" |
+#include "net/proxy/proxy_server.h" |
+ |
+#define GCONF_MODE_KEY "/system/proxy/mode" |
+#define GCONF_USE_HTTP_PROXY_KEY "/system/http_proxy/use_http_proxy" |
+#define GCONF_AUTOCONFIG_KEY "/system/proxy/autoconfig_url" |
+#define GCONF_SAME_PROXY_KEY "/system/http_proxy/use_same_proxy" |
+#define GCONF_HTTP_PROXY_KEY "/system/http_proxy/host" |
+#define GCONF_HTTP_PROXY_PORT_KEY "/system/http_proxy/port" |
+#define GCONF_SHTTP_PROXY_KEY "/system/proxy/secure_host" |
+#define GCONF_SHTTP_PROXY_PORT_KEY "/system/proxy/secure_port" |
+#define GCONF_FTP_PROXY_KEY "/system/proxy/ftp_host" |
+#define GCONF_FTP_PROXY_PORT_KEY "/system/proxy/ftp_port" |
+#define GCONF_PROXY_BYPASS_LIST_KEY "/system/http_proxy/ignore_hosts" |
+#define GCONF_SOCKS_PROXY_KEY "/system/proxy/socks_host" |
+#define GCONF_SOCKS_PROXY_PORT_KEY "/system/proxy/socks_port" |
+ |
+const struct SchemeInGCONF { |
+ const gchar* scheme; |
+ const gchar* host_key; |
+ const gchar* port_key; |
+} kSchemeInGCONF[] = { |
+ {"http", GCONF_HTTP_PROXY_KEY, GCONF_HTTP_PROXY_PORT_KEY}, |
+ {"https", GCONF_SHTTP_PROXY_KEY, GCONF_SHTTP_PROXY_PORT_KEY}, |
+ {"ftp", GCONF_FTP_PROXY_KEY, GCONF_FTP_PROXY_PORT_KEY}, |
+}; |
+ |
+namespace net { |
+ |
+// Simple test input data |
+bool IsValidDomain(const std::string& str) { |
eroman
2009/03/30 21:25:08
nit: make this "static".
|
+ if (str.size () < 3) |
+ return false; |
+ for (size_t i = 0; i < str.size(); i++) { |
+ if ( !(isalnum(str[i]) || str[i] == '.' || str[i] == '-' || |
eroman
2009/03/30 21:25:08
nit: remove the space here "( !"
|
+ str[i] == ':' || str[i] == '[' || str [i] == ']')) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+ProxyServer GetProxyServerFromGconf( |
eroman
2009/03/30 21:25:08
nit: make this "static".
|
+ GConfClient* client, |
+ ProxyServer::Scheme scheme, |
+ const char* host_key, |
+ const char* port_key) { |
+ gchar* proxy_host = gconf_client_get_string(client, host_key, NULL); |
+ gint proxy_port = gconf_client_get_int(client, port_key, NULL); |
+ |
+ ProxyServer result; // Initialized to invalid. |
eroman
2009/03/30 21:25:08
nit: two spaces between ";" and "/"
|
+ |
+ if (proxy_host != NULL && IsValidDomain(proxy_host)) { |
+ if (proxy_port == 0) |
+ proxy_port = ProxyServer::GetDefaultPortForScheme (scheme); |
eroman
2009/03/30 21:25:08
nit: no space between "GetDefaultPortForScheme" an
|
+ result = ProxyServer(scheme, proxy_host, proxy_port); |
+ } |
+ |
+ g_free(proxy_host); |
+ return result; |
+} |
+ |
+bool GetProxyConfigGCONF(ProxyConfig* config) { |
eroman
2009/03/30 21:25:08
nit: make this "static".
|
+ bool res = true; |
eroman
2009/03/30 21:25:08
nit: I would suggest a more descriptive name like
|
+ GConfClient* client = GCONF_CLIENT(gconf_client_get_default()); |
+ gchar* mode; |
+ |
+ mode = gconf_client_get_string(client, GCONF_MODE_KEY, NULL); |
+ if (mode) { |
+ if (strcmp(mode, "auto") == 0) { |
+ gchar* url = gconf_client_get_string(client, GCONF_AUTOCONFIG_KEY, NULL); |
+ if (url) { |
+ if (strlen (url)) |
+ config->pac_url = GURL(url); |
+ else |
+ config->auto_detect = true; |
+ } else { |
+ res = false; |
+ } |
+ g_free(url); |
+ } |
+ |
+ if (strcmp(mode, "manual") == 0) { |
+ gboolean same_proxy, use_http_proxy; |
+ |
+ use_http_proxy = gconf_client_get_bool(client, GCONF_USE_HTTP_PROXY_KEY, |
+ NULL); |
+ config->proxy_rules = ""; |
+ |
+ if (!use_http_proxy) { |
+ ProxyServer proxy_server = GetProxyServerFromGconf( |
+ client, |
eroman
2009/03/30 21:25:08
nit: indent these parameters by 4 spaces instead o
|
+ ProxyServer::SCHEME_SOCKS4, |
+ GCONF_SOCKS_PROXY_KEY, |
+ GCONF_SOCKS_PROXY_PORT_KEY); |
+ |
+ if (proxy_server.is_valid()) { |
+ config->proxy_rules += proxy_server.ToURI(); |
+ } else { |
+ res = false; |
+ } |
+ } else { |
+ same_proxy = gconf_client_get_bool(client, GCONF_SAME_PROXY_KEY, NULL); |
+ |
+ if (same_proxy) { |
+ ProxyServer proxy_server = GetProxyServerFromGconf( |
+ client, |
eroman
2009/03/30 21:25:08
nit: indent these parameters by 4 spaces instead o
|
+ ProxyServer::SCHEME_HTTP, |
+ GCONF_HTTP_PROXY_KEY, |
+ GCONF_HTTP_PROXY_PORT_KEY); |
+ |
+ if (proxy_server.is_valid()) { |
+ config->proxy_rules = proxy_server.ToURI(); |
+ } else { |
+ res = false; |
+ } |
+ } else { |
+ for (size_t i = 0; i < arraysize(kSchemeInGCONF); ++i) { |
+ ProxyServer proxy_server = GetProxyServerFromGconf( |
+ client, |
eroman
2009/03/30 21:25:08
nit: indent these parameters by 4 spaces instead o
|
+ ProxyServer::SCHEME_HTTP, |
+ kSchemeInGCONF[i].host_key, |
+ kSchemeInGCONF[i].port_key); |
+ |
+ if (proxy_server.is_valid()) { |
+ if (config->proxy_rules.size()) { |
+ config->proxy_rules += ";"; |
+ } |
+ config->proxy_rules += kSchemeInGCONF[i].scheme; |
+ config->proxy_rules += "="; |
+ config->proxy_rules += proxy_server.ToURI(); |
+ } |
+ } |
+ if (!config->proxy_rules.size()) { |
+ ProxyServer proxy_server = GetProxyServerFromGconf( |
+ client, |
+ ProxyServer::SCHEME_SOCKS4, |
+ GCONF_SOCKS_PROXY_KEY, |
+ GCONF_SOCKS_PROXY_PORT_KEY); |
+ |
+ if (proxy_server.is_valid()) { |
+ config->proxy_rules += proxy_server.ToURI(); |
+ } |
+ } |
+ } |
+ } |
+ if (res && config->proxy_rules.size()) { |
+ GSList* list; |
+ |
+ list = gconf_client_get_list(client, GCONF_PROXY_BYPASS_LIST_KEY, |
+ GCONF_VALUE_STRING, NULL); |
eroman
2009/03/30 21:25:08
nit: two more spaces to line this up.
|
+ config->proxy_bypass.clear(); |
+ |
+ for (GSList* i = list; i; i = g_slist_next(i)) { |
+ if (i->data) |
+ config->proxy_bypass.push_back(static_cast<gchar*>(i->data)); |
+ } |
+ |
+ g_slist_foreach(list, GFunc(g_free), NULL); |
+ g_slist_free(list); |
+ } |
+ } |
+ g_free(mode); |
+ } else { |
+ res = false; |
+ } |
+ |
+ g_object_unref(client); |
+ return res; |
+} |
+ |
+const struct SchemeInEnv { |
+ const gchar* scheme; |
+ const gchar* env_name; |
+} kSchemeInEnv[] = { |
eroman
2009/03/30 21:25:08
nit: can you make this "static" ?
|
+ {"http", "http_proxy"}, |
+ {"https", "https_proxy"}, |
+ {"ftp", "ftp_proxy"}, |
+}; |
+ |
+bool GetProxyConfigEnv(ProxyConfig* config) { |
+ gchar* no_proxy = g_strdup(g_getenv("no_proxy")); |
+ gchar* socks_ver = g_strdup(g_getenv("SOCKS_VERSION")); |
+ gchar* socks_server = g_strdup(g_getenv("SOCKS_SERVER")); |
+ gchar* auto_proxy = g_strdup(g_getenv("auto_proxy")); |
+ bool res = true; |
+ |
+ config->proxy_rules = ""; |
+ |
+ if (auto_proxy != NULL) { |
eroman
2009/03/30 21:25:08
nit: for consistency, consider "if (auto_proxy)"
|
+ if (strlen(auto_proxy) == 0) |
+ config->auto_detect = true; |
+ else |
+ config->pac_url = GURL(auto_proxy); |
+ } |
+ |
+ if (socks_ver != NULL && socks_server != NULL) { |
eroman
2009/03/30 21:25:08
nit: for consistency consider omitting "!= NULL"
|
+ int ver = 0; |
+ ProxyServer server; |
+ |
+ ver = atoi(socks_ver); |
+ if (ver != 4 && ver != 5) |
+ ver = 4; |
+ |
+ if (strncmp(socks_server, "socks", 5) == 0) { |
+ server = ProxyServer::FromURI(socks_server); |
+ } else { |
+ if (ver == 4) |
+ server = ProxyServer::FromURI("socks4://" + std::string(socks_server)); |
+ else |
+ server = ProxyServer::FromURI("socks5://" + std::string(socks_server)); |
+ } |
+ if (!server.is_valid()) |
+ res = false; |
+ else |
+ config->proxy_rules += server.ToURI(); |
+ } else { |
+ gchar* all_proxy = g_strdup(g_getenv("all_proxy")); |
+ if (all_proxy != NULL) { |
eroman
2009/03/30 21:25:08
nit: for consistency consider omitting "!= NULL".
|
+ ProxyServer server = ProxyServer::FromURI(all_proxy); |
+ if (!server.is_valid()) |
+ res = false; |
+ else |
+ config->proxy_rules = server.ToURI(); |
+ } else { |
+ for (size_t i = 0; i < arraysize(kSchemeInEnv); ++i) { |
+ gchar* proxy = g_strdup(g_getenv(kSchemeInEnv[i].env_name)); |
+ if (proxy != NULL) { |
eroman
2009/03/30 21:25:08
nit: for consistency consider omitting "!= NULL".
|
+ ProxyServer server = ProxyServer::FromURI(proxy); |
+ if (server.is_valid()) { |
+ if (config->proxy_rules.size() > 1) |
eroman
2009/03/30 21:25:08
I believe you can just test > 0 here (i.e. not emp
|
+ config->proxy_rules += ";"; |
+ config->proxy_rules += kSchemeInEnv[i].scheme; |
+ config->proxy_rules += "="; |
+ config->proxy_rules += server.ToURI(); |
+ } |
+ } |
+ g_free(proxy); |
+ } |
+ } |
+ g_free(all_proxy); |
+ } |
+ |
+ if (no_proxy) { |
+ std::string str; |
+ for (size_t i = 0, k = strlen(no_proxy); i < k; i++) { |
+ if (no_proxy[i] != ' ') |
+ str += no_proxy[i]; |
eroman
2009/03/30 21:25:08
instead of stripping whitespace here, I would sugg
|
+ } |
+ StringTokenizer proxy_server_bypass_list(str, ","); |
+ while (proxy_server_bypass_list.GetNext()) { |
+ int i[4]; |
+ std::string bypass_url_domain = proxy_server_bypass_list.token(); |
+ if (sscanf(bypass_url_domain.c_str(), "%d.%d.%d.%d", |
eroman
2009/03/30 21:25:08
I recommend using GURL to test if it is an IP addr
|
+ i, i + 1, i + 2, i + 3) == 4) { |
+ config->proxy_bypass.push_back(bypass_url_domain); |
+ } else { |
+ config->proxy_bypass.push_back("*" + bypass_url_domain); |
+ } |
+ } |
+ } |
+ |
+ g_free(no_proxy); |
+ g_free(socks_ver); |
+ g_free(socks_server); |
+ g_free(auto_proxy); |
+ return res; |
+} |
+ |
+int ProxyConfigServiceLinux::GetProxyConfig(ProxyConfig* config) { |
+ if (g_getenv("DESKTOP_SESSION") && |
+ strcmp(g_getenv("DESKTOP_SESSION"), "gnome") == 0 || |
+ g_getenv("GNOME_DESKTOP_SESSION_ID")) { |
+ gdk_threads_enter(); |
+ if (GetProxyConfigGCONF(config)) { |
+ gdk_threads_leave(); |
+ return OK; |
+ } |
+ gdk_threads_leave(); |
+ } |
+ |
+ if (GetProxyConfigEnv(config)) { |
+ return OK; |
+ } |
+ return ERR_FAILED; |
+} |
+ |
+} // namespace net |