Chromium Code Reviews| 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 |