Bug 783765 - Use libnotify as a dynamic library. r=glandium
authorMarco Castelluccio <mar.castelluccio@studenti.unina.it>
Sat, 25 Aug 2012 08:54:16 +0200
changeset 103380 d7fb23a822dd7ce3d641dcaa7ca485ee96fafb0e
parent 103379 542e9ac22e76fc3d462add927c788063b940cd9d
child 103381 8056f890ce791be8e9b8d4b55fd21203171e83fd
push id23345
push userryanvm@gmail.com
push dateSat, 25 Aug 2012 15:42:14 +0000
treeherdermozilla-central@e874475efe15 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs783765
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 783765 - Use libnotify as a dynamic library. r=glandium
config/system-headers
configure.in
js/src/config/system-headers
toolkit/system/gnome/Makefile.in
toolkit/system/gnome/nsAlertsIconListener.cpp
toolkit/system/gnome/nsAlertsIconListener.h
toolkit/system/gnome/nsGnomeModule.cpp
--- a/config/system-headers
+++ b/config/system-headers
@@ -399,17 +399,16 @@ libgnomevfs/gnome-vfs-file-info.h
 libgnomevfs/gnome-vfs.h
 libgnomevfs/gnome-vfs-init.h
 libgnomevfs/gnome-vfs-mime.h
 libgnomevfs/gnome-vfs-mime-handlers.h
 libgnomevfs/gnome-vfs-mime-utils.h
 libgnomevfs/gnome-vfs-ops.h
 libgnomevfs/gnome-vfs-standard-callbacks.h
 lib$routines.h
-libnotify/notify.h
 limits
 limits.h
 link.h
 linux/kernel.h
 linux/limits.h
 linux/rtc.h
 linux/version.h
 list
--- a/configure.in
+++ b/configure.in
@@ -69,17 +69,16 @@ WINDRES_VERSION=2.14.90
 W32API_VERSION=3.14
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 GIO_VERSION=2.18
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
 SQLITE_VERSION=3.7.13
-LIBNOTIFY_VERSION=0.4
 
 MSMANIFEST_TOOL=
 
 dnl Set various checks
 dnl ========================================================
 MISSING_X=
 AC_PROG_AWK
 
@@ -4924,61 +4923,22 @@ then
         AC_DEFINE(MOZ_ENABLE_LIBPROXY)
     fi
 fi
 AC_SUBST(MOZ_ENABLE_LIBPROXY)
 AC_SUBST(MOZ_LIBPROXY_CFLAGS)
 AC_SUBST(MOZ_LIBPROXY_LIBS)
 
 dnl ========================================================
-dnl = libnotify support
+dnl = GNOME component (mozgnome)
 dnl ========================================================
 
 if test "$MOZ_ENABLE_GTK2"
 then
-    MOZ_ENABLE_LIBNOTIFY=1
-
-    MOZ_ARG_DISABLE_BOOL(libnotify,
-    [  --disable-libnotify     Disable libnotify support ],
-    MOZ_ENABLE_LIBNOTIFY=,
-    MOZ_ENABLE_LIBNOTIFY=1)
-
-    if test "$MOZ_ENABLE_LIBNOTIFY"
-    then
-        AC_DEFINE(MOZ_ENABLE_LIBNOTIFY)
-    fi
-fi
-
-if test -z "$SKIP_LIBRARY_CHECKS"
-then
-    if test "$MOZ_ENABLE_GTK2"
-    then
-        if test "$MOZ_ENABLE_LIBNOTIFY"
-        then
-            PKG_CHECK_MODULES(MOZ_LIBNOTIFY, libnotify >= $LIBNOTIFY_VERSION)
-        fi
-    fi
-fi
-AC_SUBST(MOZ_ENABLE_LIBNOTIFY)
-AC_SUBST(MOZ_LIBNOTIFY_CFLAGS)
-AC_SUBST(MOZ_LIBNOTIFY_LIBS)
-
-dnl ========================================================
-dnl = GNOME component (mozgnome)
-dnl ========================================================
-
-# The GNOME component is built if one of
-# gnome-vfs, gio, gconf or libnotify is available.
-if test "$MOZ_ENABLE_GCONF" -o \
-   "$MOZ_ENABLE_GNOMEVFS" -o \
-   "$MOZ_ENABLE_GIO" -o \
-   "$MOZ_ENABLE_LIBNOTIFY"; then
     MOZ_ENABLE_GNOME_COMPONENT=1
-else
-    MOZ_ENABLE_GNOME_COMPONENT=
 fi
 AC_SUBST(MOZ_ENABLE_GNOME_COMPONENT)
 
 dnl ========================================================
 dnl = libgnomeui support module
 dnl ========================================================
 
 if test "$MOZ_ENABLE_GTK2"
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -399,17 +399,16 @@ libgnomevfs/gnome-vfs-file-info.h
 libgnomevfs/gnome-vfs.h
 libgnomevfs/gnome-vfs-init.h
 libgnomevfs/gnome-vfs-mime.h
 libgnomevfs/gnome-vfs-mime-handlers.h
 libgnomevfs/gnome-vfs-mime-utils.h
 libgnomevfs/gnome-vfs-ops.h
 libgnomevfs/gnome-vfs-standard-callbacks.h
 lib$routines.h
-libnotify/notify.h
 limits
 limits.h
 link.h
 linux/kernel.h
 linux/limits.h
 linux/rtc.h
 linux/version.h
 list
--- a/toolkit/system/gnome/Makefile.in
+++ b/toolkit/system/gnome/Makefile.in
@@ -10,18 +10,22 @@ VPATH	  = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= mozgnome
 LIBRARY_NAME	= mozgnome
 FORCE_SHARED_LIB = 1
 IS_COMPONENT	= 1
 
 
-CPPSRCS = nsGnomeModule.cpp
-	
+CPPSRCS = \
+  nsGnomeModule.cpp \
+  nsAlertsService.cpp \
+  nsAlertsIconListener.cpp \
+  $(NULL)
+
 ifdef MOZ_ENABLE_GCONF
 CPPSRCS += \
   nsGConfService.cpp \
   $(NULL)
 endif
 
 ifdef MOZ_ENABLE_GNOMEVFS
 CPPSRCS += \
@@ -31,38 +35,29 @@ endif
 
 ifdef MOZ_ENABLE_GIO
 CPPSRCS += \
 	nsGIOService.cpp \
 	nsGSettingsService.cpp \
 	$(NULL)
 endif
 
-ifdef MOZ_ENABLE_LIBNOTIFY
-CPPSRCS += \
-	nsAlertsService.cpp \
-	nsAlertsIconListener.cpp \
-	$(NULL)
-endif
-
 EXTRA_DSO_LDOPTS += \
 		$(XPCOM_GLUE_LDOPTS) \
 		$(XPCOM_FROZEN_LDOPTS) \
 		$(NSPR_LIBS) \
 		$(MOZ_GCONF_LIBS) \
 		$(MOZ_GNOMEVFS_LIBS) \
 		$(GLIB_LIBS) \
-		$(MOZ_LIBNOTIFY_LIBS) \
 		$(MOZ_GIO_LIBS) \
 		$(NULL)
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/build/
 
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += \
 	$(MOZ_GCONF_CFLAGS) \
 	$(MOZ_GNOMEVFS_CFLAGS) \
 	$(MOZ_GIO_CFLAGS) \
 	$(GLIB_CFLAGS) \
-	$(MOZ_LIBNOTIFY_CFLAGS) \
 	$(MOZ_GTK2_CFLAGS) \
 	$(NULL)
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -8,26 +8,32 @@
 #include "imgILoader.h"
 #include "imgIRequest.h"
 #include "nsNetUtil.h"
 #include "nsIImageToPixbuf.h"
 #include "nsIStringBundle.h"
 #include "nsIObserverService.h"
 #include "nsCRT.h"
 
+#include <dlfcn.h>
 #include <gdk/gdk.h>
 
-// Compatibility macro for <libnotify-0.7
-#ifndef NOTIFY_CHECK_VERSION
-#define NOTIFY_CHECK_VERSION(x,y,z) 0
-#endif
-
 static bool gHasActions = false;
 static bool gHasCaps = false;
 
+void* nsAlertsIconListener::libNotifyHandle = nullptr;
+bool nsAlertsIconListener::libNotifyNotAvail = false;
+nsAlertsIconListener::notify_is_initted_t nsAlertsIconListener::notify_is_initted = nullptr;
+nsAlertsIconListener::notify_init_t nsAlertsIconListener::notify_init = nullptr;
+nsAlertsIconListener::notify_get_server_caps_t nsAlertsIconListener::notify_get_server_caps = nullptr;
+nsAlertsIconListener::notify_notification_new_t nsAlertsIconListener::notify_notification_new = nullptr;
+nsAlertsIconListener::notify_notification_show_t nsAlertsIconListener::notify_notification_show = nullptr;
+nsAlertsIconListener::notify_notification_set_icon_from_pixbuf_t nsAlertsIconListener::notify_notification_set_icon_from_pixbuf = nullptr;
+nsAlertsIconListener::notify_notification_add_action_t nsAlertsIconListener::notify_notification_add_action = nullptr;
+
 static void notify_action_cb(NotifyNotification *notification,
                              gchar *action, gpointer user_data)
 {
   nsAlertsIconListener* alert = static_cast<nsAlertsIconListener*> (user_data);
   alert->SendCallback();
 }
 
 static void notify_closed_marshal(GClosure* closure,
@@ -47,22 +53,45 @@ static void notify_closed_marshal(GClosu
 
 NS_IMPL_ISUPPORTS4(nsAlertsIconListener, imgIContainerObserver,
                    imgIDecoderObserver, nsIObserver, nsISupportsWeakReference)
 
 nsAlertsIconListener::nsAlertsIconListener()
 : mLoadedFrame(false),
   mNotification(NULL)
 {
+  if (!libNotifyHandle && !libNotifyNotAvail) {
+    libNotifyHandle = dlopen("libnotify.so.4", RTLD_LAZY);
+    if (!libNotifyHandle) {
+      libNotifyHandle = dlopen("libnotify.so.1", RTLD_LAZY);
+      if (!libNotifyHandle) {
+        libNotifyNotAvail = true;
+        return;
+      }
+    }
+
+    notify_is_initted = (notify_is_initted_t)dlsym(libNotifyHandle, "notify_is_initted");
+    notify_init = (notify_init_t)dlsym(libNotifyHandle, "notify_init");
+    notify_get_server_caps = (notify_get_server_caps_t)dlsym(libNotifyHandle, "notify_get_server_caps");
+    notify_notification_new = (notify_notification_new_t)dlsym(libNotifyHandle, "notify_notification_new");
+    notify_notification_show = (notify_notification_show_t)dlsym(libNotifyHandle, "notify_notification_show");
+    notify_notification_set_icon_from_pixbuf = (notify_notification_set_icon_from_pixbuf_t)dlsym(libNotifyHandle, "notify_notification_set_icon_from_pixbuf");
+    notify_notification_add_action = (notify_notification_add_action_t)dlsym(libNotifyHandle, "notify_notification_add_action");
+    if (!notify_is_initted || !notify_init || !notify_get_server_caps || !notify_notification_new || !notify_notification_show || !notify_notification_set_icon_from_pixbuf || !notify_notification_add_action) {
+      dlclose(libNotifyHandle);
+      libNotifyHandle = nullptr;
+    }
+  }
 }
 
 nsAlertsIconListener::~nsAlertsIconListener()
 {
   if (mIconRequest)
     mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
+  // Don't dlclose libnotify as it uses atexit().
 }
 
 NS_IMETHODIMP
 nsAlertsIconListener::OnStartRequest(imgIRequest* aRequest)
 {
   return NS_OK;
 }
 
@@ -180,24 +209,17 @@ nsAlertsIconListener::OnStopFrame(imgIRe
 
   mLoadedFrame = true;
   return NS_OK;
 }
 
 nsresult
 nsAlertsIconListener::ShowAlert(GdkPixbuf* aPixbuf)
 {
-  mNotification = notify_notification_new(mAlertTitle.get(),
-                                          mAlertText.get(),
-                                          NULL
-// >=libnotify-0.7.0 has no support for attaching to widgets
-#if !NOTIFY_CHECK_VERSION(0,7,0)
-                                          , NULL
-#endif
-                                          );
+  mNotification = notify_notification_new(mAlertTitle.get(), mAlertText.get(), NULL, NULL);
 
   if (!mNotification)
     return NS_ERROR_OUT_OF_MEMORY;
 
   if (aPixbuf)
     notify_notification_set_icon_from_pixbuf(mNotification, aPixbuf);
 
   NS_ADDREF(this);
@@ -279,16 +301,19 @@ nsAlertsIconListener::Observe(nsISupport
 nsresult
 nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl,
                                      const nsAString & aAlertTitle, 
                                      const nsAString & aAlertText,
                                      bool aAlertTextClickable,
                                      const nsAString & aAlertCookie,
                                      nsIObserver * aAlertListener)
 {
+  if (!libNotifyHandle)
+    return NS_ERROR_FAILURE;
+
   if (!notify_is_initted()) {
     // Give the name of this application to libnotify
     nsCOMPtr<nsIStringBundleService> bundleService = 
       do_GetService(NS_STRINGBUNDLE_CONTRACTID);
 
     nsCAutoString appShortName;
     if (bundleService) {
       nsCOMPtr<nsIStringBundle> bundle;
--- a/toolkit/system/gnome/nsAlertsIconListener.h
+++ b/toolkit/system/gnome/nsAlertsIconListener.h
@@ -8,20 +8,21 @@
 
 #include "nsCOMPtr.h"
 #include "imgIDecoderObserver.h"
 #include "nsStringAPI.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
-#include <libnotify/notify.h>
 
 class imgIRequest;
 
+struct NotifyNotification;
+
 class nsAlertsIconListener : public imgIDecoderObserver,
                              public nsIObserver,
                              public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGICONTAINEROBSERVER
   NS_DECL_IMGIDECODEROBSERVER
@@ -36,26 +37,50 @@ public:
                           bool aAlertTextClickable,
                           const nsAString & aAlertCookie,
                           nsIObserver * aAlertListener);
 
   void SendCallback();
   void SendClosed();
 
 protected:
+  /**
+   * The only difference between libnotify.so.4 and libnotify.so.1 for these symbols
+   * is that notify_notification_new takes three arguments in libnotify.so.4 and
+   * four in libnotify.so.1.
+   * Passing the fourth argument as NULL is binary compatible.
+   */
+  typedef void (*NotifyActionCallback)(NotifyNotification*, char*, gpointer);
+  typedef bool (*notify_is_initted_t)(void);
+  typedef bool (*notify_init_t)(const char*);
+  typedef GList* (*notify_get_server_caps_t)(void);
+  typedef NotifyNotification* (*notify_notification_new_t)(const char*, const char*, const char*, const char*);
+  typedef bool (*notify_notification_show_t)(void*, char*);
+  typedef void (*notify_notification_set_icon_from_pixbuf_t)(void*, GdkPixbuf*);
+  typedef void (*notify_notification_add_action_t)(void*, const char*, const char*, NotifyActionCallback, gpointer, GFreeFunc);
+
   nsCOMPtr<imgIRequest> mIconRequest;
   nsCString mAlertTitle;
   nsCString mAlertText;
 
   nsCOMPtr<nsIObserver> mAlertListener;
   nsString mAlertCookie;
 
   bool mLoadedFrame;
   bool mAlertHasAction;
 
+  static void* libNotifyHandle;
+  static bool libNotifyNotAvail;
+  static notify_is_initted_t notify_is_initted;
+  static notify_init_t notify_init;
+  static notify_get_server_caps_t notify_get_server_caps;
+  static notify_notification_new_t notify_notification_new;
+  static notify_notification_show_t notify_notification_show;
+  static notify_notification_set_icon_from_pixbuf_t notify_notification_set_icon_from_pixbuf;
+  static notify_notification_add_action_t notify_notification_add_action;
   NotifyNotification* mNotification;
   gulong mClosureHandler;
 
   nsresult StartRequest(const nsAString & aImageUrl);
   nsresult ShowAlert(GdkPixbuf* aPixbuf);
 };
 
 #endif
--- a/toolkit/system/gnome/nsGnomeModule.cpp
+++ b/toolkit/system/gnome/nsGnomeModule.cpp
@@ -17,67 +17,59 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGC
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGnomeVFSService, Init)
 #endif
 #ifdef MOZ_ENABLE_GIO
 #include "nsGIOService.h"
 #include "nsGSettingsService.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIOService)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGSettingsService, Init)
 #endif
-#ifdef MOZ_ENABLE_LIBNOTIFY
 #include "nsAlertsService.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAlertsService, Init)
-#endif
 
 #ifdef MOZ_ENABLE_GCONF
 NS_DEFINE_NAMED_CID(NS_GCONFSERVICE_CID);
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
 NS_DEFINE_NAMED_CID(NS_GNOMEVFSSERVICE_CID);
 #endif
 #ifdef MOZ_ENABLE_GIO
 NS_DEFINE_NAMED_CID(NS_GIOSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_GSETTINGSSERVICE_CID);
 #endif
-#ifdef MOZ_ENABLE_LIBNOTIFY
 NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID);
-#endif
 
 
 static const mozilla::Module::CIDEntry kGnomeCIDs[] = {
 #ifdef MOZ_ENABLE_GCONF
   { &kNS_GCONFSERVICE_CID, false, NULL, nsGConfServiceConstructor },
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
   { &kNS_GNOMEVFSSERVICE_CID, false, NULL, nsGnomeVFSServiceConstructor },
 #endif
 #ifdef MOZ_ENABLE_GIO
   { &kNS_GIOSERVICE_CID, false, NULL, nsGIOServiceConstructor },
   { &kNS_GSETTINGSSERVICE_CID, false, NULL, nsGSettingsServiceConstructor },
 #endif
-#ifdef MOZ_ENABLE_LIBNOTIFY
   { &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, nsAlertsServiceConstructor },
-#endif
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kGnomeContracts[] = {
 #ifdef MOZ_ENABLE_GCONF
   { NS_GCONFSERVICE_CONTRACTID, &kNS_GCONFSERVICE_CID },
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
   { NS_GNOMEVFSSERVICE_CONTRACTID, &kNS_GNOMEVFSSERVICE_CID },
 #endif
 #ifdef MOZ_ENABLE_GIO
   { NS_GIOSERVICE_CONTRACTID, &kNS_GIOSERVICE_CID },
   { NS_GSETTINGSSERVICE_CONTRACTID, &kNS_GSETTINGSSERVICE_CID },
 #endif
-#ifdef MOZ_ENABLE_LIBNOTIFY
   { NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_CID },
-#endif
   { NULL }
 };
 
 static nsresult
 InitGType ()
 {
   g_type_init();
   return NS_OK;