Bug 682832 - Don't ignore Gnome 3 proxy settings. r=karlt

This commit is contained in:
jhorak@redhat.com 2011-12-05 15:45:54 +01:00
Родитель 7e1051e6b3
Коммит 22ddfbac75
3 изменённых файлов: 190 добавлений и 17 удалений

Просмотреть файл

@ -44,6 +44,8 @@
#include "nsMemory.h"
#include "prlink.h"
#include "nsComponentManagerUtils.h"
#include "nsIMutableArray.h"
#include "nsISupportsPrimitives.h"
#include <glib.h>
#include <glib-object.h>
@ -60,6 +62,7 @@ typedef struct _GVariant GVariant;
# define G_VARIANT_TYPE_STRING ((const GVariantType *) "s")
# define G_VARIANT_TYPE_OBJECT_PATH ((const GVariantType *) "o")
# define G_VARIANT_TYPE_SIGNATURE ((const GVariantType *) "g")
# define G_VARIANT_TYPE_STRING_ARRAY ((const GVariantType *) "as")
#endif
#define GSETTINGS_FUNCTIONS \
@ -72,6 +75,7 @@ typedef struct _GVariant GVariant;
FUNC(g_variant_get_int32, gint32, (GVariant* variant)) \
FUNC(g_variant_get_boolean, gboolean, (GVariant* variant)) \
FUNC(g_variant_get_string, const char *, (GVariant* value, gsize* length)) \
FUNC(g_variant_get_strv, const char **, (GVariant* value, gsize* length)) \
FUNC(g_variant_is_of_type, gboolean, (GVariant* value, const GVariantType* type)) \
FUNC(g_variant_new_int32, GVariant *, (gint32 value)) \
FUNC(g_variant_new_boolean, GVariant *, (gboolean value)) \
@ -95,6 +99,7 @@ GSETTINGS_FUNCTIONS
#define g_variant_get_int32 _g_variant_get_int32
#define g_variant_get_boolean _g_variant_get_boolean
#define g_variant_get_string _g_variant_get_string
#define g_variant_get_strv _g_variant_get_strv
#define g_variant_is_of_type _g_variant_is_of_type
#define g_variant_new_int32 _g_variant_new_int32
#define g_variant_new_boolean _g_variant_new_boolean
@ -276,6 +281,49 @@ struct nsGSettingsDynamicFunction {
nsGSettingsFunc *function;
};
NS_IMETHODIMP
nsGSettingsCollection::GetStringList(const nsACString& aKey, nsIArray** aResult)
{
if (!KeyExists(aKey))
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIMutableArray> items(do_CreateInstance(NS_ARRAY_CONTRACTID));
if (!items) {
return NS_ERROR_OUT_OF_MEMORY;
}
GVariant *value = g_settings_get_value(mSettings,
PromiseFlatCString(aKey).get());
if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY)) {
g_variant_unref(value);
return NS_ERROR_FAILURE;
}
const gchar ** gs_strings = g_variant_get_strv(value, NULL);
if (!gs_strings) {
// empty array
NS_ADDREF(*aResult = items);
g_variant_unref(value);
return NS_OK;
}
const gchar** p_gs_strings = gs_strings;
while (*p_gs_strings != NULL)
{
nsCOMPtr<nsISupportsCString> obj(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
if (obj) {
obj->SetData(nsDependentCString(*p_gs_strings));
items->AppendElement(obj, false);
}
p_gs_strings++;
}
g_free(gs_strings);
NS_ADDREF(*aResult = items);
g_variant_unref(value);
return NS_OK;
}
nsresult
nsGSettingsService::Init()
{

Просмотреть файл

@ -49,6 +49,7 @@
#include "nsPrintfCString.h"
#include "nsNetUtil.h"
#include "nsISupportsPrimitives.h"
#include "nsIGSettingsService.h"
class nsUnixSystemProxySettings : public nsISystemProxySettings {
public:
@ -62,9 +63,12 @@ private:
~nsUnixSystemProxySettings() {}
nsCOMPtr<nsIGConfService> mGConf;
nsCOMPtr<nsIGSettingsService> mGSettings;
bool IsProxyMode(const char* aMode);
nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult);
};
NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
@ -73,6 +77,7 @@ nsresult
nsUnixSystemProxySettings::Init()
{
mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
mGSettings = do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
return NS_OK;
}
@ -87,14 +92,31 @@ nsUnixSystemProxySettings::IsProxyMode(const char* aMode)
nsresult
nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
{
if (!mGConf || !IsProxyMode("auto")) {
// Return an empty string in this case
aResult.Truncate();
return NS_OK;
if (mGSettings) {
nsCOMPtr<nsIGSettingsCollection> proxy_settings;
mGSettings->GetCollectionForSchema(NS_LITERAL_CSTRING("org.gnome.system.proxy"),
getter_AddRefs(proxy_settings));
if (proxy_settings) {
nsCString proxyMode;
// Check if mode is auto
nsresult rv = proxy_settings->GetString(NS_LITERAL_CSTRING("mode"), proxyMode);
if (rv == NS_OK && proxyMode.Equals("auto")) {
return proxy_settings->GetString(NS_LITERAL_CSTRING("autoconfig-url"), aResult);
}
/* The org.gnome.system.proxy schema has been found, but auto mode is not set.
* Don't try the GConf and return empty string. */
aResult.Truncate();
return NS_OK;
}
}
return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"),
aResult);
if (mGConf && IsProxyMode("auto")) {
return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"),
aResult);
}
// Return an empty string when auto mode is not set.
aResult.Truncate();
return NS_OK;
}
static bool
@ -231,7 +253,38 @@ nsUnixSystemProxySettings::SetProxyResultFromGConf(const char* aKeyBase, const c
PRInt32 port;
rv = mGConf->GetInt(portKey, &port);
NS_ENSURE_SUCCESS(rv, rv);
/* When port is 0, proxy is not considered as enabled even if host is set. */
if (port == 0)
return NS_ERROR_FAILURE;
SetProxyResult(aType, host, port, aResult);
return NS_OK;
}
nsresult
nsUnixSystemProxySettings::SetProxyResultFromGSettings(const char* aKeyBase, const char* aType,
nsACString& aResult)
{
nsCOMPtr<nsIGSettingsCollection> proxy_settings;
nsresult rv = mGSettings->GetCollectionForSchema(nsDependentCString(aKeyBase),
getter_AddRefs(proxy_settings));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString host;
rv = proxy_settings->GetString(NS_LITERAL_CSTRING("host"), host);
NS_ENSURE_SUCCESS(rv, rv);
if (host.IsEmpty())
return NS_ERROR_FAILURE;
PRInt32 port;
rv = proxy_settings->GetInt(NS_LITERAL_CSTRING("port"), &port);
NS_ENSURE_SUCCESS(rv, rv);
/* When port is 0, proxy is not considered as enabled even if host is set. */
if (port == 0)
return NS_ERROR_FAILURE;
SetProxyResult(aType, host, port, aResult);
return NS_OK;
}
@ -271,17 +324,17 @@ static bool ConvertToIPV6Addr(const nsACString& aName,
PRIPv6Addr* aAddr)
{
PRNetAddr addr;
// try to convert hostname to IP
if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
return false;
PRIPv6Addr ipv6;
// convert parsed address to IPv6
if (addr.raw.family == PR_AF_INET) {
// convert to IPv4-mapped address
PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &ipv6);
PR_ConvertIPv4AddrToIPv6(addr.inet.ip, aAddr);
} else if (addr.raw.family == PR_AF_INET6) {
// copy the address
memcpy(&ipv6, &addr.ipv6.ip, sizeof(PRIPv6Addr));
memcpy(aAddr, &addr.ipv6.ip, sizeof(PRIPv6Addr));
} else {
return false;
}
@ -289,8 +342,8 @@ static bool ConvertToIPV6Addr(const nsACString& aName,
return true;
}
static bool GConfIgnoreHost(const nsACString& aIgnore,
const nsACString& aHost)
static bool HostIgnoredByProxy(const nsACString& aIgnore,
const nsACString& aHost)
{
if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator()))
return true;
@ -321,8 +374,9 @@ static bool GConfIgnoreHost(const nsACString& aIgnore,
slash = end;
}
nsDependentCSubstring ignoreStripped(start, slash);
PRIPv6Addr ignoreAddr, hostAddr;
if (!ConvertToIPV6Addr(aIgnore, &ignoreAddr) ||
if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr) ||
!ConvertToIPV6Addr(aHost, &hostAddr))
return false;
@ -355,7 +409,7 @@ nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme,
if (str) {
nsAutoString s;
if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) {
if (GConfIgnoreHost(NS_ConvertUTF16toUTF8(s), aHost)) {
if (HostIgnoredByProxy(NS_ConvertUTF16toUTF8(s), aHost)) {
aResult.AppendLiteral("DIRECT");
return NS_OK;
}
@ -391,6 +445,71 @@ nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme,
return NS_OK;
}
nsresult
nsUnixSystemProxySettings::GetProxyFromGSettings(const nsACString& aScheme,
const nsACString& aHost,
PRInt32 aPort,
nsACString& aResult)
{
nsCOMPtr<nsIGSettingsCollection> proxy_settings;
nsresult rv;
rv = mGSettings->GetCollectionForSchema(NS_LITERAL_CSTRING("org.gnome.system.proxy"),
getter_AddRefs(proxy_settings));
NS_ENSURE_SUCCESS(rv, rv);
nsCString proxyMode;
rv = proxy_settings->GetString(NS_LITERAL_CSTRING("mode"), proxyMode);
NS_ENSURE_SUCCESS(rv, rv);
if (!proxyMode.Equals("manual")) {
aResult.AppendLiteral("DIRECT");
return NS_OK;
}
nsCOMPtr<nsIArray> ignoreList;
if (NS_SUCCEEDED(proxy_settings->GetStringList(NS_LITERAL_CSTRING("ignore-hosts"),
getter_AddRefs(ignoreList))) && ignoreList) {
PRUint32 len = 0;
ignoreList->GetLength(&len);
for (PRUint32 i = 0; i < len; ++i) {
nsCOMPtr<nsISupportsCString> str = do_QueryElementAt(ignoreList, i);
if (str) {
nsCString s;
if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) {
if (HostIgnoredByProxy(s, aHost)) {
aResult.AppendLiteral("DIRECT");
return NS_OK;
}
}
}
}
}
if (aScheme.LowerCaseEqualsLiteral("http")) {
rv = SetProxyResultFromGSettings("org.gnome.system.proxy.http", "PROXY", aResult);
} else if (aScheme.LowerCaseEqualsLiteral("https")) {
rv = SetProxyResultFromGSettings("org.gnome.system.proxy.https", "PROXY", aResult);
/* Try to use HTTP proxy when HTTPS proxy is not explicitly defined */
if (rv != NS_OK)
rv = SetProxyResultFromGSettings("org.gnome.system.proxy.http", "PROXY", aResult);
} else if (aScheme.LowerCaseEqualsLiteral("ftp")) {
rv = SetProxyResultFromGSettings("org.gnome.system.proxy.ftp", "PROXY", aResult);
} else {
rv = NS_ERROR_FAILURE;
}
if (rv != NS_OK) {
/* If proxy for scheme is not specified, use SOCKS proxy for all schemes */
rv = SetProxyResultFromGSettings("org.gnome.system.proxy.socks", "SOCKS", aResult);
}
if (NS_FAILED(rv)) {
aResult.AppendLiteral("DIRECT");
}
return NS_OK;
}
nsresult
nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
{
@ -406,10 +525,15 @@ nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
rv = aURI->GetPort(&port);
NS_ENSURE_SUCCESS(rv, rv);
if (!mGConf)
return GetProxyFromEnvironment(scheme, host, port, aResult);
if (mGSettings) {
rv = GetProxyFromGSettings(scheme, host, port, aResult);
if (rv == NS_OK)
return rv;
}
if (mGConf)
return GetProxyFromGConf(scheme, host, port, aResult);
return GetProxyFromGConf(scheme, host, port, aResult);
return GetProxyFromEnvironment(scheme, host, port, aResult);
}
#define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\

Просмотреть файл

@ -39,7 +39,7 @@
#include "nsISupports.idl"
#include "nsIArray.idl"
[scriptable, uuid(09637d3c-3c07-40b4-aff9-1d2a0f046f3c)]
[scriptable, uuid(16d5b0ed-e756-4f1b-a8ce-9132e869acd8)]
interface nsIGSettingsCollection : nsISupports
{
void setString(in AUTF8String key, in AUTF8String value);
@ -48,6 +48,7 @@ interface nsIGSettingsCollection : nsISupports
AUTF8String getString(in AUTF8String key);
boolean getBoolean(in AUTF8String key);
long getInt(in AUTF8String key);
nsIArray getStringList(in AUTF8String key);
};
[scriptable, uuid(849c088b-57d1-4f24-b7b2-3dc4acb04c0a)]