--- a/netwerk/base/public/Makefile.in
+++ b/netwerk/base/public/Makefile.in
@@ -99,16 +99,17 @@ XPIDLSRCS = \
nsIServerSocket.idl \
nsIResumableChannel.idl \
nsIRequestObserverProxy.idl \
nsIStreamListenerTee.idl \
nsISimpleStreamListener.idl \
nsIStreamTransportService.idl \
nsIStreamLoader.idl \
nsISyncStreamListener.idl \
+ nsISystemProxySettings.idl \
nsIUnicharStreamLoader.idl \
nsIStandardURL.idl \
nsINestedURI.idl \
nsIURLParser.idl \
nsIURIChecker.idl \
nsISecurityEventSink.idl \
nsISecretDecoderRing.idl \
nsISecureBrowserUI.idl \
new file mode 100644
--- /dev/null
+++ b/netwerk/base/public/nsISystemProxySettings.idl
@@ -0,0 +1,61 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is Novell.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert O'Callahan (robert@ocallahan.org)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIURI.idl"
+
+/**
+ * This interface allows the proxy code to use platform-specific proxy
+ * settings when the proxy preference is set to "automatic discovery". This service
+ * acts like a PAC parser to netwerk, but it will actually read the system settings and
+ * either return the proper proxy data from the autoconfig URL specified in the system proxy,
+ * or generate proxy data based on the system's manual proxy settings.
+ */
+[scriptable, uuid(a9f3ae38-b769-4e0b-9317-578388e326c9)]
+interface nsISystemProxySettings : nsISupports
+{
+ /**
+ * If non-empty, use this PAC file. If empty, call getProxyForURI instead.
+ */
+ readonly attribute AUTF8String PACURI;
+
+ /**
+ * See nsIProxyAutoConfig::getProxyForURI; this function behaves exactly
+ * the same way.
+ */
+ AUTF8String getProxyForURI(in nsIURI aURI);
+};
--- a/netwerk/base/src/nsPACMan.h
+++ b/netwerk/base/src/nsPACMan.h
@@ -123,16 +123,24 @@ public:
*/
nsresult LoadPACFromURI(nsIURI *pacURI);
/**
* Returns true if we are currently loading the PAC file.
*/
PRBool IsLoading() { return mLoader != nsnull; }
+ /**
+ * Returns true if the given URI matches the URI of our PAC file.
+ */
+ PRBool IsPACURI(nsIURI *uri) {
+ PRBool result;
+ return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
+ }
+
private:
NS_DECL_NSISTREAMLOADEROBSERVER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
~nsPACMan();
/**
@@ -157,24 +165,16 @@ private:
*/
void MaybeReloadPAC();
/**
* Called when we fail to load the PAC file.
*/
void OnLoadFailure();
- /**
- * Returns true if the given URI matches the URI of our PAC file.
- */
- PRBool IsPACURI(nsIURI *uri) {
- PRBool result;
- return mPACURI && NS_SUCCEEDED(mPACURI->Equals(uri, &result)) && result;
- }
-
private:
nsCOMPtr<nsIProxyAutoConfig> mPAC;
nsCOMPtr<nsIURI> mPACURI;
PRCList mPendingQ;
nsCOMPtr<nsIStreamLoader> mLoader;
PRPackedBool mLoadPending;
PRPackedBool mShutdown;
PRTime mScheduledReload;
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -399,16 +399,22 @@ nsProtocolProxyService::PrefsChanged(nsI
prefBranch->SetIntPref(PROXY_PREF("type"), type);
} else if (type >= eProxyConfig_Last) {
LOG(("unknown proxy type: %lu; assuming direct\n", type));
type = eProxyConfig_Direct;
}
mProxyConfig = static_cast<ProxyConfig>(type);
reloadPAC = PR_TRUE;
}
+
+ if (mProxyConfig == eProxyConfig_System) {
+ mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
+ } else {
+ mSystemProxySettings = nsnull;
+ }
}
if (!pref || !strcmp(pref, PROXY_PREF("http")))
proxy_GetStringPref(prefBranch, PROXY_PREF("http"), mHTTPProxyHost);
if (!pref || !strcmp(pref, PROXY_PREF("http_port")))
proxy_GetIntPref(prefBranch, PROXY_PREF("http_port"), mHTTPProxyPort);
@@ -456,43 +462,48 @@ nsProtocolProxyService::PrefsChanged(nsI
if (!pref || !strcmp(pref, PROXY_PREF("no_proxies_on"))) {
rv = prefBranch->GetCharPref(PROXY_PREF("no_proxies_on"),
getter_Copies(tempString));
if (NS_SUCCEEDED(rv))
LoadHostFilters(tempString.get());
}
- // We're done if not using PAC or WPAD
- if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD)
+ // We're done if not using something that could give us a PAC URL
+ // (PAC, WPAD or System)
+ if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD &&
+ mProxyConfig != eProxyConfig_System)
return;
// OK, we need to reload the PAC file if:
// 1) network.proxy.type changed, or
// 2) network.proxy.autoconfig_url changed and PAC is configured
if (!pref || !strcmp(pref, PROXY_PREF("autoconfig_url")))
reloadPAC = PR_TRUE;
if (reloadPAC) {
tempString.Truncate();
if (mProxyConfig == eProxyConfig_PAC) {
prefBranch->GetCharPref(PROXY_PREF("autoconfig_url"),
getter_Copies(tempString));
- }
- else if (mProxyConfig == eProxyConfig_WPAD) {
+ } else {
// We diverge from the WPAD spec here in that we don't walk the
// hosts's FQDN, stripping components until we hit a TLD. Doing so
// is dangerous in the face of an incomplete list of TLDs, and TLDs
// get added over time. We could consider doing only a single
// substitution of the first component, if that proves to help
// compatibility.
- tempString.AssignLiteral(WPAD_URL);
+ if (mSystemProxySettings)
+ mSystemProxySettings->GetPACURI(tempString);
+ else
+ tempString.AssignLiteral(WPAD_URL);
}
- ConfigureFromPAC(tempString);
+ if (!tempString.IsEmpty())
+ ConfigureFromPAC(tempString);
}
}
PRBool
nsProtocolProxyService::CanUseProxy(nsIURI *aURI, PRInt32 defaultPort)
{
if (mHostFiltersArray.Count() == 0)
return PR_TRUE;
@@ -750,23 +761,26 @@ nsresult
nsProtocolProxyService::ConfigureFromPAC(const nsCString &spec)
{
if (!mPACMan) {
mPACMan = new nsPACMan();
if (!mPACMan)
return NS_ERROR_OUT_OF_MEMORY;
}
- mFailedProxies.Clear();
-
nsCOMPtr<nsIURI> pacURI;
nsresult rv = NS_NewURI(getter_AddRefs(pacURI), spec);
if (NS_FAILED(rv))
return rv;
+ if (mPACMan->IsPACURI(pacURI))
+ return NS_OK;
+
+ mFailedProxies.Clear();
+
return mPACMan->LoadPACFromURI(pacURI);
}
void
nsProtocolProxyService::ProcessPACString(const nsCString &pacString,
nsIProxyInfo **result)
{
if (pacString.IsEmpty()) {
@@ -931,18 +945,20 @@ nsProtocolProxyService::NewProxyInfo(con
}
NS_IMETHODIMP
nsProtocolProxyService::GetFailoverForProxy(nsIProxyInfo *aProxy,
nsIURI *aURI,
nsresult aStatus,
nsIProxyInfo **aResult)
{
- // We only support failover when a PAC file is configured.
- if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD)
+ // We only support failover when a PAC file is configured, either
+ // directly or via system settings
+ if (mProxyConfig != eProxyConfig_PAC && mProxyConfig != eProxyConfig_WPAD &&
+ mProxyConfig != eProxyConfig_System)
return NS_ERROR_NOT_AVAILABLE;
// Verify that |aProxy| is one of our nsProxyInfo objects.
nsCOMPtr<nsProxyInfo> pi = do_QueryInterface(aProxy);
NS_ENSURE_ARG(pi);
// OK, the QI checked out. We can proceed.
// Remember that this proxy is down.
@@ -1229,25 +1245,47 @@ nsProtocolProxyService::Resolve_Internal
NS_ENSURE_ARG_POINTER(uri);
*usePAC = PR_FALSE;
*result = nsnull;
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
return NS_OK; // Can't proxy this (filters may not override)
+ if (mSystemProxySettings) {
+ nsCAutoString PACURI;
+ if (NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
+ !PACURI.IsEmpty()) {
+ // Switch to new PAC file if that setting has changed. If the setting
+ // hasn't changed, ConfigureFromPAC will exit early.
+ nsresult rv = ConfigureFromPAC(PACURI);
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ nsCAutoString proxy;
+ nsresult rv = mSystemProxySettings->GetProxyForURI(uri, proxy);
+ if (NS_SUCCEEDED(rv)) {
+ ProcessPACString(proxy, result);
+ return NS_OK;
+ }
+ // no proxy, stop search
+ return NS_OK;
+ }
+ }
+
// if proxies are enabled and this host:port combo is supposed to use a
// proxy, check for a proxy.
if (mProxyConfig == eProxyConfig_Direct ||
(mProxyConfig == eProxyConfig_Manual &&
!CanUseProxy(uri, info.defaultPort)))
return NS_OK;
-
+
// Proxy auto config magic...
- if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD) {
+ if (mProxyConfig == eProxyConfig_PAC || mProxyConfig == eProxyConfig_WPAD ||
+ mProxyConfig == eProxyConfig_System) {
// Do not query PAC now.
*usePAC = PR_TRUE;
return NS_OK;
}
// proxy info values
const char *type = nsnull;
const nsACString *host = nsnull;
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -42,16 +42,17 @@
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsVoidArray.h"
#include "nsIPrefBranch.h"
#include "nsIProtocolProxyService2.h"
#include "nsIProtocolProxyFilter.h"
#include "nsIProxyAutoConfig.h"
+#include "nsISystemProxySettings.h"
#include "nsIProxyInfo.h"
#include "nsIObserver.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsPACMan.h"
#include "prtime.h"
#include "prmem.h"
#include "prio.h"
@@ -310,16 +311,17 @@ public:
protected:
enum ProxyConfig {
eProxyConfig_Direct,
eProxyConfig_Manual,
eProxyConfig_PAC,
eProxyConfig_Direct4x,
eProxyConfig_WPAD,
+ eProxyConfig_System, // use system proxy settings if available, otherwise DIRECT
eProxyConfig_Last
};
// simplified array of filters defined by this struct
struct HostInfo {
PRBool is_ipaddr;
PRInt32 port;
union {
@@ -371,15 +373,16 @@ protected:
PRInt32 mHTTPSProxyPort;
nsCString mSOCKSProxyHost;
PRInt32 mSOCKSProxyPort;
PRInt32 mSOCKSProxyVersion;
PRBool mSOCKSProxyRemoteDNS;
nsRefPtr<nsPACMan> mPACMan; // non-null if we are using PAC
+ nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
PRTime mSessionStart;
nsFailedProxyTable mFailedProxies;
PRInt32 mFailedProxyTimeout;
};
#endif // !nsProtocolProxyService_h__
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -321,16 +321,20 @@
0x11b2, \
{0xa9, 0x04, 0xac, 0x1d, 0x6d, 0xa7, 0x7a, 0x02} \
}
// component implementing nsIIncrementalDownload.
#define NS_INCREMENTALDOWNLOAD_CONTRACTID \
"@mozilla.org/network/incremental-download;1"
+// component implementing nsISystemProxySettings.
+#define NS_SYSTEMPROXYSETTINGS_CONTRACTID \
+ "@mozilla.org/system-proxy-settings;1"
+
// service implementing nsIStreamTransportService
#define NS_STREAMTRANSPORTSERVICE_CLASSNAME \
"nsStreamTransportService"
#define NS_STREAMTRANSPORTSERVICE_CONTRACTID \
"@mozilla.org/network/stream-transport-service;1"
#define NS_STREAMTRANSPORTSERVICE_CID \
{ /* 0885d4f8-f7b8-4cda-902e-94ba38bc256e */ \
0x0885d4f8, \
--- a/toolkit/Makefile.in
+++ b/toolkit/Makefile.in
@@ -46,16 +46,20 @@ include $(DEPTH)/config/autoconf.mk
DIRS = \
content \
locales \
obsolete \
profile \
themes \
$(NULL)
+ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT)))
+DIRS += system/unixproxy
+endif
+
ifdef MOZ_CRASHREPORTER
DIRS += crashreporter
endif
ifndef MINIMO
DIRS += \
xre \
mozapps \
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -142,16 +142,24 @@ endif
ifdef MOZ_XPFE_COMPONENTS
DEFINES += -DMOZ_XPFE_COMPONENTS
COMPONENT_LIBS += \
mozfind \
appcomps \
$(NULL)
endif
+ifdef MOZ_XUL
+ifdef MOZ_ENABLE_GTK2
+COMPONENT_LIBS += \
+ unixproxy \
+ $(NULL)
+endif
+endif
+
ifdef MOZ_PERF_METRICS
EXTRA_DSO_LIBS += mozutil_s
endif
ifdef MOZ_XPINSTALL
DEFINES += -DMOZ_XPINSTALL
COMPONENT_LIBS += \
xpinstall \
--- a/toolkit/library/nsStaticXULComponents.cpp
+++ b/toolkit/library/nsStaticXULComponents.cpp
@@ -257,16 +257,25 @@
#endif
#ifdef MOZ_XMLEXTRAS
#define XMLEXTRAS_MODULE MODULE(nsXMLExtrasModule)
#else
#define XMLEXTRAS_MODULE
#endif
+#ifdef MOZ_XUL
+#ifdef MOZ_ENABLE_GTK2
+#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
+#endif
+#endif
+#ifndef UNIXPROXY_MODULE
+#define UNIXPROXY_MODULE
+#endif
+
#define XUL_MODULES \
MODULE(xpconnect) \
MATHML_MODULES \
MODULE(nsUConvModule) \
MODULE(nsI18nModule) \
MODULE(nsChardetModule) \
UNIVERSALCHARDET_MODULE \
MODULE(necko) \
@@ -308,16 +317,17 @@
XPINSTALL_MODULES \
JSDEBUGGER_MODULES \
MODULE(BOOT) \
MODULE(NSS) \
SYSTEMPREF_MODULES \
SPELLCHECK_MODULE \
XMLEXTRAS_MODULE \
LAYOUT_DEBUG_MODULE \
+ UNIXPROXY_MODULE \
/* end of list */
#define MODULE(_name) \
NSGETMODULE_ENTRY_POINT(_name) (nsIComponentManager*, nsIFile*, nsIModule**);
XUL_MODULES
#undef MODULE
--- a/toolkit/system/gnome/nsGConfService.cpp
+++ b/toolkit/system/gnome/nsGConfService.cpp
@@ -33,16 +33,20 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsGConfService.h"
#include "nsStringAPI.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIMutableArray.h"
#include <gconf/gconf-client.h>
nsGConfService::~nsGConfService()
{
if (mClient)
g_object_unref(mClient);
}
@@ -119,16 +123,47 @@ nsGConfService::GetFloat(const nsACStrin
g_error_free(error);
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
+nsGConfService::GetStringList(const nsACString &aKey, nsIArray** aResult)
+{
+ nsCOMPtr<nsIMutableArray> items(do_CreateInstance(NS_ARRAY_CONTRACTID));
+ if (!items)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ GError* error = nsnull;
+ GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(),
+ GCONF_VALUE_STRING, &error);
+ if (error) {
+ g_error_free(error);
+ return NS_ERROR_FAILURE;
+ }
+
+ for (GSList* l = list; l; l = l->next) {
+ nsCOMPtr<nsISupportsString> obj(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
+ if (!obj) {
+ g_slist_free(list);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ obj->SetData(NS_ConvertUTF8toUTF16((const char*)l->data));
+ items->AppendElement(obj, PR_FALSE);
+ g_free(l->data);
+ }
+
+ g_slist_free(list);
+ NS_ADDREF(*aResult = items);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsGConfService::SetBool(const nsACString &aKey, PRBool aValue)
{
PRBool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(),
aValue, nsnull);
return res ? NS_OK : NS_ERROR_FAILURE;
}
new file mode 100644
--- /dev/null
+++ b/toolkit/system/unixproxy/Makefile.in
@@ -0,0 +1,65 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Mozilla GNOME integration code.
+#
+# The Initial Developer of the Original Code is
+# IBM Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Brian Ryner <bryner@brianryner.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = unixproxy
+LIBRARY_NAME = unixproxy
+
+EXPORT_LIBRARY = 1
+IS_COMPONENT = 1
+MODULE_NAME = nsUnixProxyModule
+GRE_MODULE = 1
+LIBXUL_LIBRARY = 1
+
+REQUIRES = \
+ xpcom \
+ string \
+ necko \
+ mozgnome \
+ $(NULL)
+
+CPPSRCS = \
+ nsUnixSystemProxySettings.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
@@ -0,0 +1,428 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert O'Callahan (robert@ocallahan.org)
+ * Michael Ventnor (m.ventnor@gmail.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISystemProxySettings.h"
+#include "nsIGenericFactory.h"
+#include "nsIServiceManager.h"
+#include "nsIGConfService.h"
+#include "nsIURI.h"
+#include "nsReadableUtils.h"
+#include "nsArrayUtils.h"
+#include "prnetdb.h"
+#include "prenv.h"
+#include "nsPrintfCString.h"
+#include "nsNetUtil.h"
+#include "nsISupportsPrimitives.h"
+
+class nsUnixSystemProxySettings : public nsISystemProxySettings {
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISYSTEMPROXYSETTINGS
+
+ nsUnixSystemProxySettings() {}
+ nsresult Init();
+
+private:
+ ~nsUnixSystemProxySettings() {}
+
+ nsCOMPtr<nsIGConfService> mGConf;
+ PRBool 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);
+};
+
+NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
+
+nsresult
+nsUnixSystemProxySettings::Init()
+{
+ mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
+ return NS_OK;
+}
+
+PRBool
+nsUnixSystemProxySettings::IsProxyMode(const char* aMode)
+{
+ nsCAutoString mode;
+ return NS_SUCCEEDED(mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) &&
+ mode.EqualsASCII(aMode);
+}
+
+nsresult
+nsUnixSystemProxySettings::GetPACURI(nsACString& aResult)
+{
+ if (!mGConf || !IsProxyMode("auto")) {
+ // Return an empty string in this case
+ aResult.Truncate();
+ return NS_OK;
+ }
+
+ return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"),
+ aResult);
+}
+
+static PRBool
+IsInNoProxyList(const nsACString& aHost, PRInt32 aPort, const char* noProxyVal)
+{
+ NS_ASSERTION(aPort >= 0, "Negative port?");
+
+ nsCAutoString noProxy(noProxyVal);
+ if (noProxy.EqualsLiteral("*"))
+ return PR_TRUE;
+
+ noProxy.StripWhitespace();
+
+ nsReadingIterator<char> pos;
+ nsReadingIterator<char> end;
+ noProxy.BeginReading(pos);
+ noProxy.EndReading(end);
+ while (pos != end) {
+ nsReadingIterator<char> last = pos;
+ nsReadingIterator<char> nextPos;
+ if (FindCharInReadable(',', last, end)) {
+ nextPos = last;
+ ++nextPos;
+ } else {
+ last = end;
+ nextPos = end;
+ }
+
+ nsReadingIterator<char> colon = pos;
+ PRInt32 port = -1;
+ if (FindCharInReadable(':', colon, last)) {
+ ++colon;
+ nsDependentCSubstring portStr(colon, last);
+ nsCAutoString portStr2(portStr); // We need this for ToInteger. String API's suck.
+ PRInt32 err;
+ port = portStr2.ToInteger(&err);
+ if (NS_FAILED(err)) {
+ port = -2; // don't match any port, so we ignore this pattern
+ }
+ --colon;
+ } else {
+ colon = last;
+ }
+
+ if (port == -1 || port == aPort) {
+ nsDependentCSubstring hostStr(pos, colon);
+ // By using StringEndsWith instead of an equality comparator, we can include sub-domains
+ if (StringEndsWith(aHost, hostStr, nsCaseInsensitiveCStringComparator()))
+ return PR_TRUE;
+ }
+
+ pos = nextPos;
+ }
+
+ return PR_FALSE;
+}
+
+static void SetProxyResult(const char* aType, const nsACString& aHost,
+ PRInt32 aPort, nsACString& aResult)
+{
+ aResult.AppendASCII(aType);
+ aResult.Append(' ');
+ aResult.Append(aHost);
+ aResult.Append(':');
+ aResult.Append(nsPrintfCString("%d", aPort));
+}
+
+static nsresult
+GetProxyFromEnvironment(const nsACString& aScheme,
+ const nsACString& aHost,
+ PRInt32 aPort,
+ nsACString& aResult)
+{
+ nsCAutoString envVar;
+ envVar.Append(aScheme);
+ envVar.AppendLiteral("_proxy");
+ const char* proxyVal = PR_GetEnv(envVar.get());
+ if (!proxyVal) {
+ proxyVal = PR_GetEnv("all_proxy");
+ if (!proxyVal) {
+ // Return failure so that the caller can detect the failure and
+ // fall back to other proxy detection (e.g., WPAD)
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ const char* noProxyVal = PR_GetEnv("no_proxy");
+ if (noProxyVal && IsInNoProxyList(aHost, aPort, noProxyVal)) {
+ aResult.AppendLiteral("DIRECT");
+ return NS_OK;
+ }
+
+ // Use our URI parser to crack the proxy URI
+ nsCOMPtr<nsIURI> proxyURI;
+ nsresult rv = NS_NewURI(getter_AddRefs(proxyURI), proxyVal);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Is there a way to specify "socks://" or something in these environment
+ // variables? I can't find any documentation.
+ PRBool isHTTP;
+ rv = proxyURI->SchemeIs("http", &isHTTP);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isHTTP)
+ return NS_ERROR_UNKNOWN_PROTOCOL;
+
+ nsCAutoString proxyHost;
+ rv = proxyURI->GetHost(proxyHost);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRInt32 proxyPort;
+ rv = proxyURI->GetPort(&proxyPort);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ SetProxyResult("PROXY", proxyHost, proxyPort, aResult);
+ return NS_OK;
+}
+
+nsresult
+nsUnixSystemProxySettings::SetProxyResultFromGConf(const char* aKeyBase, const char* aType,
+ nsACString& aResult)
+{
+ nsCAutoString hostKey;
+ hostKey.AppendASCII(aKeyBase);
+ hostKey.AppendLiteral("host");
+ nsCAutoString host;
+ nsresult rv = mGConf->GetString(hostKey, host);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (host.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ nsCAutoString portKey;
+ portKey.AppendASCII(aKeyBase);
+ portKey.AppendLiteral("port");
+ PRInt32 port;
+ rv = mGConf->GetInt(portKey, &port);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ SetProxyResult(aType, host, port, aResult);
+ return NS_OK;
+}
+
+/* copied from nsProtocolProxyService.cpp --- we should share this! */
+static void
+proxy_MaskIPv6Addr(PRIPv6Addr &addr, PRUint16 mask_len)
+{
+ if (mask_len == 128)
+ return;
+
+ if (mask_len > 96) {
+ addr.pr_s6_addr32[3] = PR_htonl(
+ PR_ntohl(addr.pr_s6_addr32[3]) & (~0L << (128 - mask_len)));
+ }
+ else if (mask_len > 64) {
+ addr.pr_s6_addr32[3] = 0;
+ addr.pr_s6_addr32[2] = PR_htonl(
+ PR_ntohl(addr.pr_s6_addr32[2]) & (~0L << (96 - mask_len)));
+ }
+ else if (mask_len > 32) {
+ addr.pr_s6_addr32[3] = 0;
+ addr.pr_s6_addr32[2] = 0;
+ addr.pr_s6_addr32[1] = PR_htonl(
+ PR_ntohl(addr.pr_s6_addr32[1]) & (~0L << (64 - mask_len)));
+ }
+ else {
+ addr.pr_s6_addr32[3] = 0;
+ addr.pr_s6_addr32[2] = 0;
+ addr.pr_s6_addr32[1] = 0;
+ addr.pr_s6_addr32[0] = PR_htonl(
+ PR_ntohl(addr.pr_s6_addr32[0]) & (~0L << (32 - mask_len)));
+ }
+}
+
+static PRBool ConvertToIPV6Addr(const nsACString& aName,
+ PRIPv6Addr* aAddr)
+{
+ PRNetAddr addr;
+ if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
+ return PR_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);
+ } else if (addr.raw.family == PR_AF_INET6) {
+ // copy the address
+ memcpy(&ipv6, &addr.ipv6.ip, sizeof(PRIPv6Addr));
+ } else {
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+static PRBool GConfIgnoreHost(const nsACString& aIgnore,
+ const nsACString& aHost)
+{
+ if (aIgnore.Equals(aHost, nsCaseInsensitiveCStringComparator()))
+ return PR_TRUE;
+
+ if (aIgnore.First() == '*' &&
+ StringEndsWith(aHost, nsDependentCSubstring(aIgnore, 1),
+ nsCaseInsensitiveCStringComparator()))
+ return PR_TRUE;
+
+ PRInt32 mask = 128;
+ nsReadingIterator<char> start;
+ nsReadingIterator<char> slash;
+ nsReadingIterator<char> end;
+ aIgnore.BeginReading(start);
+ aIgnore.BeginReading(slash);
+ aIgnore.EndReading(end);
+ if (FindCharInReadable('/', slash, end)) {
+ ++slash;
+ nsDependentCSubstring maskStr(slash, end);
+ nsCAutoString maskStr2(maskStr);
+ PRInt32 err;
+ mask = maskStr2.ToInteger(&err);
+ if (err != 0) {
+ mask = 128;
+ }
+ --slash;
+ } else {
+ slash = end;
+ }
+
+ PRIPv6Addr ignoreAddr, hostAddr;
+ if (!ConvertToIPV6Addr(aIgnore, &ignoreAddr) ||
+ !ConvertToIPV6Addr(aHost, &hostAddr))
+ return PR_FALSE;
+
+ proxy_MaskIPv6Addr(ignoreAddr, mask);
+ proxy_MaskIPv6Addr(hostAddr, mask);
+
+ return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0;
+}
+
+nsresult
+nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme,
+ const nsACString& aHost,
+ PRInt32 aPort,
+ nsACString& aResult)
+{
+ PRBool masterProxySwitch = PR_FALSE;
+ mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_http_proxy"), &masterProxySwitch);
+ if (!IsProxyMode("manual") || !masterProxySwitch) {
+ aResult.AppendLiteral("DIRECT");
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIArray> ignoreList;
+ if (NS_SUCCEEDED(mGConf->GetStringList(NS_LITERAL_CSTRING("/system/http_proxy/ignore_hosts"),
+ getter_AddRefs(ignoreList))) && ignoreList) {
+ PRUint32 len = 0;
+ ignoreList->GetLength(&len);
+ for (PRUint32 i = 0; i < len; ++i) {
+ nsCOMPtr<nsISupportsString> str = do_QueryElementAt(ignoreList, i);
+ if (str) {
+ nsAutoString s;
+ if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) {
+ if (GConfIgnoreHost(NS_ConvertUTF16toUTF8(s), aHost)) {
+ aResult.AppendLiteral("DIRECT");
+ return NS_OK;
+ }
+ }
+ }
+ }
+ }
+
+ PRBool useHttpProxyForAll = PR_FALSE;
+ // This setting sometimes doesn't exist, don't bail on failure
+ mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_same_proxy"), &useHttpProxyForAll);
+
+ nsresult rv;
+ if (!useHttpProxyForAll) {
+ rv = SetProxyResultFromGConf("/system/proxy/socks_", "SOCKS", aResult);
+ if (NS_SUCCEEDED(rv))
+ return rv;
+ }
+
+ if (aScheme.LowerCaseEqualsLiteral("http") || useHttpProxyForAll) {
+ rv = SetProxyResultFromGConf("/system/http_proxy/", "PROXY", aResult);
+ } else if (aScheme.LowerCaseEqualsLiteral("https")) {
+ rv = SetProxyResultFromGConf("/system/proxy/secure_", "PROXY", aResult);
+ } else if (aScheme.LowerCaseEqualsLiteral("ftp")) {
+ rv = SetProxyResultFromGConf("/system/proxy/ftp_", "PROXY", aResult);
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+
+ if (NS_FAILED(rv)) {
+ aResult.AppendLiteral("DIRECT");
+ }
+ return NS_OK;
+}
+
+nsresult
+nsUnixSystemProxySettings::GetProxyForURI(nsIURI* aURI, nsACString& aResult)
+{
+ nsCAutoString scheme;
+ nsresult rv = aURI->GetScheme(scheme);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCAutoString host;
+ rv = aURI->GetHost(host);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRInt32 port;
+ rv = aURI->GetPort(&port);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mGConf)
+ return GetProxyFromEnvironment(scheme, host, port, aResult);
+
+ return GetProxyFromGConf(scheme, host, port, aResult);
+}
+
+#define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\
+ { 0x0fa3158c, 0xd5a7, 0x43de, \
+ {0x91, 0x81, 0xa2, 0x85, 0xe7, 0x4c, 0xf1, 0xd4 } }
+
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUnixSystemProxySettings, Init)
+
+static const nsModuleComponentInfo components[] = {
+ { "Unix System Proxy Settings Service",
+ NS_UNIXSYSTEMPROXYSERVICE_CID,
+ NS_SYSTEMPROXYSETTINGS_CONTRACTID,
+ nsUnixSystemProxySettingsConstructor }
+};
+
+NS_IMPL_NSGETMODULE(nsUnixProxyModule, components)
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -656,16 +656,17 @@ MAKEFILES_xulapp="
toolkit/components/commandlines/src/Makefile
toolkit/components/console/Makefile
toolkit/components/cookie/Makefile
toolkit/components/downloads/public/Makefile
toolkit/components/downloads/Makefile
toolkit/components/downloads/src/Makefile
toolkit/components/filepicker/Makefile
toolkit/system/gnome/Makefile
+ toolkit/system/unixproxy/Makefile
toolkit/components/help/Makefile
toolkit/components/history/Makefile
toolkit/components/history/public/Makefile
toolkit/components/history/src/Makefile
toolkit/components/passwordmgr/Makefile
toolkit/components/passwordmgr/public/Makefile
toolkit/components/passwordmgr/src/Makefile
toolkit/components/passwordmgr/content/Makefile
--- a/xpcom/system/nsIGConfService.idl
+++ b/xpcom/system/nsIGConfService.idl
@@ -32,26 +32,33 @@
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
+#include "nsIArray.idl"
-[scriptable, uuid(01ac7b2e-c07c-465f-b35c-542eaef420a9)]
+[scriptable, uuid(5009acae-6973-48c3-b6d6-52c692cc5d9d)]
interface nsIGConfService : nsISupports
{
/* Basic registry access */
boolean getBool(in AUTF8String key);
AUTF8String getString(in AUTF8String key);
long getInt(in AUTF8String key);
float getFloat(in AUTF8String key);
+ /*
+ * Use this to return any list items in GConf, this will return
+ * an array of UTF16 nsISupportsString's.
+ */
+ nsIArray getStringList(in AUTF8String key);
+
void setBool(in AUTF8String key, in boolean value);
void setString(in AUTF8String key, in AUTF8String value);
void setInt(in AUTF8String key, in long value);
void setFloat(in AUTF8String key, in float value);
/*
* Look up the handler for a protocol under the
* /desktop/gnome/url-handlers hierarchy.