MozillaFirefox/dbus.patch

566 lines
18 KiB
Diff

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,68 @@
+# ###### 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 = $(MOZ_DBUS_GLIB_LIBS) \
+ $(MOZ_GTHREAD_LIBS) \
+ $(MOZ_COMPONENT_LIBS)
+
+CPPSRCS = \
+ nsDBusModule.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS += $(TK_CFLAGS) $(MOZ_DBUS_GLIB_CFLAGS) $(MOZ_GTHREAD_CFLAGS)
+CXXFLAGS := $(subst -pedantic,,$(CXXFLAGS))
--- extensions/dbus/nsDBusModule.cpp
+++ extensions/dbus/nsDBusModule.cpp
@@ -0,0 +1,414 @@
+/* -*- 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;
+
+ nsCOMPtr<nsIPrefBranch2> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
+ if (prefs) {
+ 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)