Index: configure.in
================================================================================
--- browser/installer/unix/packages-static
+++ browser/installer/unix/packages-static
@@ -341,6 +341,7 @@
 ;
 bin/components/libnkgnomevfs.so
 bin/components/libauth.so
+bin/components/libdbusservice.so
 
 ; [Additional Developer Tools]
 [adt]
--- config/autoconf.mk.in
+++ config/autoconf.mk.in
@@ -458,6 +458,12 @@
 MOZ_GTK2_CFLAGS		= @MOZ_GTK2_CFLAGS@
 MOZ_GTK2_LIBS		= @MOZ_GTK2_LIBS@
 
+MOZ_DBUS_GLIB_CFLAGS    = @MOZ_DBUS_GLIB_CFLAGS@
+MOZ_DBUS_GLIB_LIBS      = @MOZ_DBUS_GLIB_LIBS@
+
+MOZ_GTHREAD_CFLAGS           = @MOZ_GTHREAD_CFLAGS@
+MOZ_GTHREAD_LIBS             = @MOZ_GTHREAD_LIBS@
+
 MOZ_XLIB_CFLAGS		= @MOZ_XLIB_CFLAGS@
 MOZ_XLIB_LDFLAGS	= @MOZ_XLIB_LDFLAGS@
 
--- configure.in
+++ configure.in
@@ -4776,6 +4776,33 @@
 AC_SUBST(MOZ_GNOMEUI_LIBS)
 
 dnl ========================================================
+dnl = dbus support
+dnl ========================================================
+
+if test "$MOZ_ENABLE_GTK2"
+then
+    MOZ_ARG_ENABLE_BOOL(dbus,
+    [  --enable-dbus       Enable dbus support (default: disabled) ],
+        MOZ_ENABLE_DBUS=1,
+        MOZ_ENABLE_DBUS=)
+
+    if test "$MOZ_ENABLE_DBUS"
+    then
+        PKG_CHECK_MODULES(MOZ_DBUS_GLIB, dbus-glib-1)
+        PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
+    fi
+
+    if test "$MOZ_ENABLE_DBUS"; then
+        AC_DEFINE(MOZ_ENABLE_DBUS)
+    fi
+fi
+AC_SUBST(MOZ_ENABLE_DBUS)
+AC_SUBST(MOZ_DBUS_GLIB_CFLAGS)
+AC_SUBST(MOZ_DBUS_GLIB_LIBS)
+AC_SUBST(MOZ_GTHREAD_CFLAGS)
+AC_SUBST(MOZ_GTHREAD_LIBS)
+
+dnl ========================================================
 dnl = Setting MOZ_EXTRA_X11CONVERTERS turns on additional 
 dnl = converters in intl/uconv that are used only by X11 gfx 
 dnl = implementations. By default, it's undefined so that 
@@ -5128,6 +5155,13 @@
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gnomevfs||'`
 fi
 
+if test -z "$MOZ_ENABLE_DBUS" && test `echo "$MOZ_EXTENSIONS" | grep -c dbus` -ne 0; then
+    if test -n "$MOZ_X11"; then
+        AC_MSG_WARN([Cannot build dbus without required libraries. Removing dbus from MOZ_EXTENSIONS.])
+    fi
+    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|dbus||'`
+fi
+
 if test -z "$MOZ_JSDEBUGGER" && test `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
     AC_MSG_WARN([Cannot build venkman without JavaScript debug library. Removing venkman from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|venkman||'`
--- extensions/dbus/Makefile.in
+++ extensions/dbus/Makefile.in
@@ -0,0 +1,70 @@
+# ###### BEGIN LICENSE BLOCK ######
+# Version: NPL 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, Inc.
+#
+# Original Author: Robert O'Callahan (rocallahan@novell.com)
+#
+# Contributor(s):
+#
+# 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 NPL, 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 NPL, the GPL or the LGPL.
+#
+# ###### END LICENSE BLOCK ######
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = dbus
+LIBRARY_NAME = dbusservice
+GRE_MODULE = 1
+#EXPORT_LIBRARY = 1
+IS_COMPONENT = 1
+FORCE_SHARED_LIB = 1
+
+REQUIRES  = xpcom \
+                      string \
+                      necko \
+                      embedcomponents \
+            $(NULL)
+
+EXTRA_DSO_LDOPTS = $(XPCOM_GLUE_LDOPTS) \
+                   $(NSPR_LIBS) \
+                   $(MOZ_DBUS_GLIB_LIBS) \
+	            $(MOZ_GTHREAD_LIBS) \
+		    $(NULL)
+                
+CPPSRCS =   \
+  nsDBusModule.cpp         \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS += $(TK_CFLAGS) $(MOZ_DBUS_GLIB_CFLAGS) $(MOZ_GTHREAD_CFLAGS)
+CXXFLAGS := $(subst -pedantic,,$(CXXFLAGS))
Index: config/system-headers
===================================================================
RCS file: /cvsroot/mozilla/config/system-headers,v
retrieving revision 3.4.4.3
diff -u -r3.4.4.3 system-headers
--- config/system-headers	18 Dec 2006 23:48:58 -0000	3.4.4.3
+++ config/system-headers	13 Nov 2007 23:04:10 -0000
@@ -141,6 +141,9 @@
 curses.h
 cxxabi.h
 DateTimeUtils.h
+dbus/dbus.h
+dbus/dbus-glib.h
+dbus/dbus-glib-lowlevel.h
 ddeml.h
 Debug.h
 dem.h
--- extensions/dbus/nsDBusModule.cpp.none	1970-01-01 01:00:00.000000000 +0100
+++ extensions/dbus/nsDBusModule.cpp	2008-01-15 17:09:51.000000000 +0100
@@ -0,0 +1,418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 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, Inc.
+ *
+ * Original Author: Robert O'Callahan (rocallahan@novell.com)
+ *
+ * Contributor(s):
+ *
+ * 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+
+#include "nsIObserverService.h"
+#include "nsIObserver.h"
+#include "nsIIOService.h"
+#include "nsWeakReference.h"
+#include "nsIPrefBranch2.h"
+#include "nsIPrefService.h"
+#include "nsServiceManagerUtils.h"
+#include "nsNetCID.h"
+#include "nsCRT.h"
+#include "nsICategoryManager.h"
+#include "nsIGenericFactory.h"
+#include "nsIAppStartupNotifier.h"
+#include "nsITimer.h"
+#include "nsComponentManagerUtils.h"
+
+#include "nsStringAPI.h"
+
+// Define NetworkManager API constants. This avoids a dependency on
+// NetworkManager-devel.
+#define NM_DBUS_SERVICE                 "org.freedesktop.NetworkManager"
+#define NM_DBUS_PATH                            "/org/freedesktop/NetworkManager"
+#define NM_DBUS_INTERFACE                       "org.freedesktop.NetworkManager"
+#define NM_DBUS_SIGNAL_STATE_CHANGE             "StateChange"
+typedef enum NMState
+{
+        NM_STATE_UNKNOWN = 0,
+        NM_STATE_ASLEEP,
+        NM_STATE_CONNECTING,
+        NM_STATE_CONNECTED,
+        NM_STATE_DISCONNECTED
+} NMState;
+
+#define NS_DBUS_CONTRACTID "@mozilla.org/dbus;1"
+#define NS_DBUS_CLASSNAME "DBus Interface"
+#define NS_DBUS_CID                  \
+  { 0x85899443,                                        \
+    0x2842,                                            \
+    0x4cc4,                                            \
+    { 0x87, 0x0c, 0x7a, 0x6f, 0x22, 0xb0, 0xaa, 0x11 } \
+  }
+  
+/**
+ * The nsDBusService component interfaces with DBUS to communicate with daemons
+ * in systems supporting DBUS. It links dynamically to the DBUS libraries so
+ * will not load on systems without those libraries ... but that's harmless.
+ *
+ * Currently the only daemon we communicate with is NetworkManager. We listen
+ * for NetworkManager state changes; we set nsIOService's offline status to
+ * FALSE when NetworkManager reports NM_STATE_CONNECTED, and to TRUE otherwise.
+ * We also solicit the current status from NetworkManager when this component
+ * gets loaded. In addition to setting IOService, we also set the
+ * "browser.offline" preference (because Firefox treats that preference as
+ * authoritative). We have to wait until prefs have been loaded before setting
+ * "browser.offline".
+ * 
+ * In the future we could extend this class to talk to other daemons.
+ * 
+ * Currently all communication is asynchronous. This isn't hard to implement
+ * and avoids blocking our main thread.
+ */
+class nsDBusService : public nsIObserver,
+                      public nsSupportsWeakReference
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  nsDBusService();
+  virtual ~nsDBusService();
+
+  nsresult Init();
+
+  /**
+   * This gets called when NetworkManager sends us a StateChange signal,
+   * or when we receive a reply to our inquiry.
+   * The message contains the current NMState.
+   */
+  void UpdateNetworkStatus(DBusMessage* message);
+
+  /**
+   * Handle a message.
+   * @return PR_TRUE to indicate that the message has been handled
+   */
+  PRBool HandleMessage(DBusMessage* message);
+
+  void DoTimerCallback(nsITimer* aTimer);
+  
+private:
+  /**
+   * Try to connect to the dbus service.
+   */
+  nsresult ConnectToDBus();
+  /**
+   * Ask NetworkManager to send us the current status.
+   */
+  void RequestNetworkStatus();
+  /**
+   * Update Gecko networking settings based on information we have received.
+   */
+  void SetGeckoNetworkStatus();
+  /**
+   * DBUS has disconnected. Hopefull it will restart; we need to restore
+   * our connection.
+   */
+  void HandleDBusDisconnect();
+
+  DBusConnection*    mConnection;
+  nsCOMPtr<nsITimer> mReconnectTimer;
+  
+  /**
+   * Set to PR_TRUE after we have received at least one status indication
+   * from NetworkManager.
+   */
+  PRPackedBool    mGotNetworkStatus;
+  /**
+   * When mGotNetworkStatus is PR_TRUE, this contains the status indicated
+   * by NetworkManager.
+   */
+  PRPackedBool    mNetworkOnline;
+  /**
+   * Set to PR_TRUE after prefs have been loaded.
+   */
+  PRPackedBool    mPrefsLoaded;
+};
+
+NS_IMPL_ISUPPORTS2(nsDBusService, nsIObserver, nsISupportsWeakReference)
+
+nsDBusService::nsDBusService() {
+  mConnection = nsnull;
+  mGotNetworkStatus = PR_FALSE;
+  mPrefsLoaded = PR_FALSE;
+}
+
+nsDBusService::~nsDBusService() {
+  if (mConnection) {
+    dbus_connection_unref(mConnection);
+  }
+  if (mReconnectTimer) {
+    mReconnectTimer->Cancel();
+  }
+}
+
+void nsDBusService::SetGeckoNetworkStatus() {
+  // Don't set Gecko status until after prefs have been loaded. When
+  // prefs are loaded, we'll get called again.
+  if (!mPrefsLoaded || !mGotNetworkStatus)
+    return;
+  
+  // ignore set requests if special pref is set
+  nsCOMPtr<nsIPrefBranch2> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
+  if (prefs) {
+    PRBool ignore = PR_FALSE;
+    prefs->GetBoolPref("browser.ignoreNM", &ignore);
+    if (!ignore) {
+      prefs->SetBoolPref("browser.offline", !mNetworkOnline);
+      nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
+      if (ios) {
+        ios->SetOffline(!mNetworkOnline);
+      }
+    }
+  }
+}
+
+void nsDBusService::UpdateNetworkStatus(DBusMessage* msg) {
+  PRInt32 result;
+  if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &result,
+                            DBUS_TYPE_INVALID)) {
+    mGotNetworkStatus = PR_TRUE;
+    mNetworkOnline = result == NM_STATE_CONNECTED;
+    SetGeckoNetworkStatus();
+  }
+}
+
+static void NetworkStatusNotify(DBusPendingCall *pending,
+                                void* user_data) {
+  DBusMessage* msg = dbus_pending_call_steal_reply(pending);
+  if (!msg)
+    return;
+  if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+    NS_STATIC_CAST(nsDBusService*, user_data)->UpdateNetworkStatus(msg);
+  }
+  dbus_message_unref(msg);
+}
+
+void nsDBusService::RequestNetworkStatus() {
+  DBusMessage* msg =
+    dbus_message_new_method_call(NM_DBUS_SERVICE, NM_DBUS_PATH,
+                                 NM_DBUS_INTERFACE, "state");
+  if (!msg)
+    return;
+
+  DBusPendingCall* reply;
+  if (dbus_connection_send_with_reply(mConnection, msg, &reply, -1)) {
+    dbus_pending_call_set_notify(reply, NetworkStatusNotify, this, NULL);
+    dbus_pending_call_unref(reply);
+  }
+  dbus_message_unref(msg);
+}
+
+void nsDBusService::DoTimerCallback(nsITimer *aTimer) {
+  if (aTimer == mReconnectTimer.get()) {
+    nsresult rv = ConnectToDBus();
+    if (NS_SUCCEEDED(rv)) {
+      mReconnectTimer->Cancel();
+      mReconnectTimer = nsnull;
+    }
+  }
+}
+
+static void TimerCallback(nsITimer *aTimer, void *aClosure) {
+  NS_STATIC_CAST(nsDBusService*, aClosure)->DoTimerCallback(aTimer);
+}
+
+void nsDBusService::HandleDBusDisconnect() {
+  if (mConnection) {
+    dbus_connection_unref(mConnection);
+    mConnection = nsnull;
+  }
+  
+  nsresult rv;
+  mReconnectTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
+  if (NS_FAILED(rv))
+    return;
+  rv = mReconnectTimer->InitWithFuncCallback(TimerCallback, this,
+                                             5000, nsITimer::TYPE_REPEATING_SLACK);
+  if (NS_FAILED(rv)) {
+    mReconnectTimer = nsnull;
+    return;
+  }
+}
+
+PRBool nsDBusService::HandleMessage(DBusMessage* message) {
+  if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
+                             "Disconnected")) {
+    HandleDBusDisconnect();
+    return PR_FALSE;
+  }
+
+  if (dbus_message_is_signal(message, NM_DBUS_INTERFACE,
+                             NM_DBUS_SIGNAL_STATE_CHANGE)) {
+    UpdateNetworkStatus(message);
+    return PR_TRUE;
+  }
+  
+  return PR_FALSE;
+}
+
+NS_IMETHODIMP nsDBusService::Observe(nsISupports *aSubject,
+                                     const char *aTopic,
+                                     const PRUnichar *aData) {
+  if (!aTopic)
+    return NS_OK;
+
+  if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
+    mPrefsLoaded = PR_TRUE;
+    SetGeckoNetworkStatus();
+  }
+  return NS_OK;
+}
+
+static DBusHandlerResult dbus_filter(DBusConnection* connection,
+                                     DBusMessage* message,
+                                     void* user_data) {
+  return NS_STATIC_CAST(nsDBusService*, user_data)->HandleMessage(message)
+    ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+nsresult nsDBusService::ConnectToDBus() {
+  DBusError error;
+  dbus_error_init(&error);
+  
+  mConnection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+  if (!mConnection) {
+    dbus_error_free(&error);
+    return NS_ERROR_FAILURE;
+  }
+
+  dbus_connection_set_exit_on_disconnect(mConnection, PR_FALSE);
+  dbus_connection_setup_with_g_main(mConnection, NULL);
+
+  if (!dbus_connection_add_filter(mConnection, dbus_filter, this, NULL)) {
+    dbus_error_free(&error);
+    return NS_ERROR_FAILURE;
+  }
+
+  dbus_bus_add_match(mConnection,
+                     "type='signal',"
+                     "interface='" NM_DBUS_INTERFACE "',"
+                     "sender='" NM_DBUS_SERVICE "',"
+                     "path='" NM_DBUS_PATH "'", &error);
+  if (dbus_error_is_set(&error)) {
+    dbus_error_free(&error);
+    return NS_ERROR_FAILURE;
+  }
+  
+  RequestNetworkStatus();
+  
+  dbus_error_free(&error);
+
+  return NS_OK;
+}
+
+nsresult nsDBusService::Init() {
+  nsresult rv;
+  nsCOMPtr<nsIObserverService> observerService =
+    do_GetService("@mozilla.org/observer-service;1", &rv);
+  if (NS_FAILED(rv))
+    return rv;
+
+  rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID,
+                                    PR_FALSE);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (!g_thread_supported ())
+    g_thread_init (NULL);
+  dbus_g_thread_init();
+
+  return ConnectToDBus();
+}
+
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDBusService, Init)
+
+static NS_METHOD
+RegisterDBus(nsIComponentManager *aCompMgr,
+             nsIFile *aPath,
+             const char *registryLocation,
+             const char *componentType,
+             const nsModuleComponentInfo *info) {
+    nsresult rv;
+
+    nsCOMPtr<nsICategoryManager>
+        categoryManager(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+    if (NS_SUCCEEDED(rv)) {
+        rv = categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY,
+                                               "DBus Module",
+                                               NS_DBUS_CONTRACTID,
+                                               PR_TRUE, PR_TRUE, nsnull);
+    }
+
+    return rv;
+}
+
+static NS_METHOD
+UnRegisterDBus(nsIComponentManager *aCompMgr,
+               nsIFile *aPath,
+               const char *registryLocation,
+               const nsModuleComponentInfo *info) {
+    nsresult rv;
+    nsCOMPtr<nsICategoryManager>
+        categoryManager(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+    if (NS_SUCCEEDED(rv)) {
+        rv = categoryManager->DeleteCategoryEntry(APPSTARTUP_CATEGORY,
+                                                  "DBus Module",
+                                                  PR_TRUE);
+    }
+    return rv;
+}
+
+static const nsModuleComponentInfo components[] = {
+    { NS_DBUS_CLASSNAME,
+      NS_DBUS_CID,
+      NS_DBUS_CONTRACTID,
+      nsDBusServiceConstructor,
+      RegisterDBus,
+      UnRegisterDBus,
+    },
+};
+
+NS_IMPL_NSGETMODULE(nsDBusModule, components)
