[banshee] Overhaul GNOME proxy support (bmc#1920)



commit 0befd4634a737c0630f1d7cbfb6c0dd9612c1f50
Author: Aaron Bockover <abockover novell com>
Date:   Tue Jun 29 12:11:15 2010 -0400

    Overhaul GNOME proxy support (bmc#1920)
    
    - Use GConf.Client directly, do not use GConfConfigurationClient
    - Support automatic and manual proxy modes (bmc#1920,
      ting z zhou intel com)
    - Ensure proxy loads even if Brasero does not (bmc#1920)
    - Wait 5 seconds before reloading the proxy on GConf notifications
    - Support disposing
    - Code cleanup, and be more robust when proxy settings are invalid or in
      some kind of transitory state
    - When a direct connection is used, return null instead of an empty
      WebProxy to be passed to System.Net.HttpWebRequest.DefaultWebProxy

 .../Banshee.GnomeBackend/GConfProxy.cs             |  159 ++++++++++++--------
 .../Banshee.GnomeBackend/GnomeService.cs           |   18 ++-
 2 files changed, 114 insertions(+), 63 deletions(-)
---
diff --git a/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfProxy.cs b/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfProxy.cs
index 5fdff82..4d0d5b2 100644
--- a/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfProxy.cs
+++ b/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfProxy.cs
@@ -3,8 +3,12 @@
 // 
 // Author:
 //   Iain Lane <laney ubuntu com>
+//   Ting Z Zhou <ting z zhou intel com>
+//   Aaron Bockover <abockover novell com>
 // 
 // Copyright 2010 Iain Lane
+// Copyright 2010 Intel Corp
+// Copyright 2010 Novell, Inc.
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -29,96 +33,131 @@ using System.Net;
 
 using Hyena;
 
-using Banshee.Configuration;
-
 namespace Banshee.GnomeBackend
 {
-    public class GConfProxy
+    public class GConfProxy : IDisposable
     {
-        const string PROXY = "/system/http_proxy";
-        const string PROXY_USE_PROXY = "use_http_proxy";
-        const string PROXY_USE_AUTH = "use_authentication";
-        const string PROXY_HOST = "host";
-        const string PROXY_PORT = "port";
-        const string PROXY_USER = "authentication_user";
-        const string PROXY_PASSWORD = "authentication_password";
-        const string PROXY_BYPASS_LIST = "ignore_hosts";
-
-        private bool use_proxy, use_auth;
-        private string proxy_host, proxy_user, proxy_password;
-        private int proxy_port;
-        private string[] proxy_bypass_list;
-
-        private GConfConfigurationClient gconf_configuration_client;
+        private const string PROXY = "/system/proxy";
+        private const string PROXY_MODE = "mode";
+        private const string PROXY_AUTO_URL = "autoconfig_url";
+        private const string HTTP_PROXY = "/system/http_proxy";
+        private const string PROXY_USE_PROXY = "use_http_proxy";
+        private const string PROXY_USE_AUTH = "use_authentication";
+        private const string PROXY_HOST = "host";
+        private const string PROXY_PORT = "port";
+        private const string PROXY_USER = "authentication_user";
+        private const string PROXY_PASSWORD = "authentication_password";
+        private const string PROXY_BYPASS_LIST = "ignore_hosts";
+
+        private GConf.Client gconf_client;
+        private uint refresh_id;
 
         public GConfProxy ()
         {
-            gconf_configuration_client = new GConfConfigurationClient ();
+            gconf_client = new GConf.Client ();
+            gconf_client.AddNotify (PROXY, OnGConfNotify);
+            gconf_client.AddNotify (HTTP_PROXY, OnGConfNotify);
 
-            // Set them up the initial DefaultWebProxy
-            System.Net.HttpWebRequest.DefaultWebProxy = GetProxyFromGConf ();
+            RefreshProxy ();
+        }
 
-            // And hook up a callback so that we get notified of any changes in the proxy settings
-            AddCallback ();
+        public void Dispose ()
+        {
+            if (gconf_client != null) {
+                gconf_client.RemoveNotify (PROXY, OnGConfNotify);
+                gconf_client.RemoveNotify (HTTP_PROXY, OnGConfNotify);
+                gconf_client = null;
+            }
         }
 
-        private void AddCallback ()
+        private void OnGConfNotify (object o, GConf.NotifyEventArgs args)
         {
-            gconf_configuration_client.AddCallback (PROXY, new GConf.NotifyEventHandler(OnProxyChanged));
+            if (refresh_id > 0) {
+                return;
+            }
+
+            // Wait 5 seconds before reloading the proxy, and block any
+            // other notifications. This notification will be raised on
+            // any minor change (e.g. htt->http->http:->http:/->http://)
+            // to any of the GNOME proxy settings. Also, at any given
+            // point in the modification of the settings, the state may
+            // be invalid, so retain the previous good configuration.
+            refresh_id = GLib.Timeout.Add (5000, RefreshProxy);
+        }
+
+        private bool RefreshProxy ()
+        {
+            Log.Information ("Updating web proxy from GConf");
+            try {
+                HttpWebRequest.DefaultWebProxy = GetProxyFromGConf ();
+            } catch {
+                Log.Warning ("Not updating proxy settings. Invalid state");
+            }
+
+            refresh_id = 0;
+            return false;
         }
 
-        private void OnProxyChanged (object sender, GConf.NotifyEventArgs args)
+        private T Get<T> (string @namespace, string key)
         {
-            Log.Debug ("Updating web proxy");
-            HttpWebRequest.DefaultWebProxy = GetProxyFromGConf ();
+            try {
+                return (T)gconf_client.Get (@namespace == null
+                    ? key
+                    : @namespace + "/" + key);
+            } catch {
+                return default (T);
+            }
         }
 
         private WebProxy GetProxyFromGConf ()
         {
-            // Read the settings in from GConf
-            use_proxy = gconf_configuration_client.Get<bool> (PROXY, PROXY_USE_PROXY, false);
-            use_auth = gconf_configuration_client.Get<bool> (PROXY,  false);
-            proxy_host = gconf_configuration_client.Get<string> (PROXY, PROXY_HOST, null);
-            proxy_port = gconf_configuration_client.Get<int> (PROXY, PROXY_PORT, 0);
-            proxy_user = gconf_configuration_client.Get<string> (PROXY,  null);
-            proxy_password = gconf_configuration_client.Get<string> (PROXY, null);
-            proxy_bypass_list = gconf_configuration_client.Get<string[]> (PROXY, PROXY_BYPASS_LIST, new string[0]);
-
-            WebProxy proxy = new WebProxy ();
-
-            // No proxy set, just return the empty proxy
-            if (!use_proxy || proxy_host == null) {
-                Log.Debug ("No proxy in use");
-                return proxy;
+            var proxy_mode = Get<string> (PROXY, PROXY_MODE);
+            var proxy_auto_url = Get<string> (PROXY, PROXY_AUTO_URL);
+            var use_proxy = Get<bool> (HTTP_PROXY, PROXY_USE_PROXY);
+            var use_auth = Get<bool> (null, HTTP_PROXY);
+            var proxy_host = Get<string> (HTTP_PROXY, PROXY_HOST);
+            var proxy_port = Get<int> (HTTP_PROXY, PROXY_PORT);
+            var proxy_user = Get<string> (null, HTTP_PROXY);
+            var proxy_password = Get<string> (null, HTTP_PROXY);
+            var proxy_bypass_list = Get<string[]> (HTTP_PROXY, PROXY_BYPASS_LIST);
+
+            if (!use_proxy || proxy_mode == "none") {
+                Log.Debug ("Direct connection, no proxy in use");
+                return null;
             }
 
-            // otherwise we have a proxy. Let's get this show on the road.
+            var proxy = new WebProxy ();
 
-            // First we need to construct the uri of the proxy
+            if (proxy_mode == "auto") {
+                if (!String.IsNullOrEmpty (proxy_auto_url)) {
+                    proxy.Address = new Uri (proxy_auto_url);
+                    Log.Debug ("Automatic proxy connection", proxy.Address.AbsoluteUri);
+                } else {
+                    Log.Warning ("Direct connection, no proxy in use. Proxy mode was 'auto' but no automatic configuration URL was found.");
+                    return null;
+                }
+            } else {
+                proxy.Address = new Uri (String.Format ("http://{0}:{1}";, proxy_host, proxy_port));
+                proxy.Credentials = use_auth
+                    ? new NetworkCredential (proxy_user, proxy_password)
+                    : null;
+                Log.Debug ("Manual proxy connection", proxy.Address.AbsoluteUri);
+            }
 
-            string uri = String.Format ("http://{0}:{1}";, proxy_host, proxy_port);
-            proxy.Address = new Uri (uri);
+            if (proxy_bypass_list == null) {
+                return proxy;
+            }
 
-            // Next the list of websites to bypass the proxy for.
-            foreach (string host in proxy_bypass_list) {
+            foreach (var host in proxy_bypass_list) {
                 if (host.Contains ("*.local")) {
                     proxy.BypassProxyOnLocal = true;
                     continue;
                 }
 
-                proxy.BypassArrayList.Add (string.Format ("http://{0}";, host));
+                proxy.BypassArrayList.Add (String.Format ("http://{0}";, host));
             }
 
-            // and finally we might need to authenticate, so let's do that
-            if (use_auth) {
-                proxy.Credentials = new NetworkCredential (proxy_user, proxy_password);
-            } else {
-                proxy.Credentials = null;
-            }
-
-            Log.Debug (String.Format ("Set web proxy to: {0}", proxy.Address.AbsoluteUri));
-
             return proxy;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GnomeService.cs b/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GnomeService.cs
index d2b3f4c..5754d2a 100644
--- a/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GnomeService.cs
+++ b/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GnomeService.cs
@@ -35,6 +35,8 @@ namespace Banshee.GnomeBackend
 {
     public class GnomeService : IExtensionService, IDisposable
     {
+        private GConfProxy gconf_proxy;
+
         private Brasero brasero;
         internal Brasero Brasero {
             get { return brasero; }
@@ -47,11 +49,16 @@ namespace Banshee.GnomeBackend
         public void Initialize ()
         {
             try {
+                // FIXME: this needs to be deferred/delayed initialized
+                gconf_proxy = new GConfProxy ();
+            } catch (Exception e) {
+                Hyena.Log.Exception ("GConfProxy", e);
+                gconf_proxy = null;
+            }
+
+            try {
                 brasero = new Brasero ();
                 brasero.Initialize ();
-
-                new GConfProxy ();
-
             } catch {
                 brasero = null;
             }
@@ -68,6 +75,11 @@ namespace Banshee.GnomeBackend
                 brasero = null;
             }
 
+            if (gconf_proxy != null) {
+                gconf_proxy.Dispose ();
+                gconf_proxy = null;
+            }
+
             if (Browser.OpenHandler == (Banshee.Web.Browser.OpenUrlHandler) OpenUrl) {
                 Browser.OpenHandler = null;
             }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]