Bug 469880. Support a libnotify-based implementation of nsIAlertsService for GTK. r+sr=roc,r=ted
authorMichael Ventnor <ventor.bugzilla@gmail.com>
Thu, 08 Jan 2009 21:12:16 +1300
changeset 23463 9891b174d8712de2465464cbcfd96cf8c3952c60
parent 23462 5041ce45310455ddecbe69b45fd7db46a2097966
child 23464 48e090c9811883fe787064804ccfa080677f1d44
push idunknown
push userunknown
push dateunknown
reviewersted
bugs469880
milestone1.9.2a1pre
Bug 469880. Support a libnotify-based implementation of nsIAlertsService for GTK. r+sr=roc,r=ted
config/autoconf.mk.in
config/system-headers
configure.in
js/src/config/system-headers
toolkit/components/alerts/src/Makefile.in
toolkit/components/alerts/src/nsAlertsService.cpp
toolkit/components/build/nsToolkitCompsCID.h
toolkit/system/gnome/Makefile.in
toolkit/system/gnome/nsAlertsIconListener.cpp
toolkit/system/gnome/nsAlertsIconListener.h
toolkit/system/gnome/nsAlertsService.cpp
toolkit/system/gnome/nsAlertsService.h
toolkit/system/gnome/nsGnomeModule.cpp
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -525,16 +525,20 @@ FT2_CFLAGS             = @FT2_CFLAGS@
 FT2_LIBS               = @FT2_LIBS@
 
 MOZ_PANGO_CFLAGS        = @MOZ_PANGO_CFLAGS@
 MOZ_PANGO_LIBS          = @MOZ_PANGO_LIBS@
 
 MOZ_XIE_LIBS		= @MOZ_XIE_LIBS@
 XT_LIBS			= @XT_LIBS@
 
+MOZ_LIBNOTIFY_CFLAGS	= @MOZ_LIBNOTIFY_CFLAGS@
+MOZ_LIBNOTIFY_LIBS	= @MOZ_LIBNOTIFY_LIBS@
+MOZ_ENABLE_LIBNOTIFY	= @MOZ_ENABLE_LIBNOTIFY@
+
 GLIB_CFLAGS	= @GLIB_CFLAGS@
 GLIB_LIBS	= @GLIB_LIBS@
 GLIB_GMODULE_LIBS	= @GLIB_GMODULE_LIBS@
 LIBIDL_CFLAGS = @LIBIDL_CFLAGS@
 LIBIDL_LIBS = @LIBIDL_LIBS@
 STATIC_LIBIDL = @STATIC_LIBIDL@
 
 MOZ_NATIVE_MAKEDEPEND	= @SYSTEM_MAKEDEPEND@
--- a/config/system-headers
+++ b/config/system-headers
@@ -430,16 +430,17 @@ libgnomevfs/gnome-vfs-init.h
 libgnomevfs/gnome-vfs-mime.h
 libgnomevfs/gnome-vfs-mime-handlers.h
 libgnomevfs/gnome-vfs-mime-info.h
 libgnomevfs/gnome-vfs-mime-utils.h
 libgnomevfs/gnome-vfs-ops.h
 libgnomevfs/gnome-vfs-standard-callbacks.h
 libIDL/IDL.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
@@ -128,16 +128,17 @@ W32API_VERSION=3.8
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 LIBGNOME_VERSION=2.0
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
 LCMS_VERSION=1.17
 SQLITE_VERSION=3.6.6.2
+LIBNOTIFY_VERSION=0.4
 
 MSMANIFEST_TOOL=
 
 dnl Set various checks
 dnl ========================================================
 MISSING_X=
 AC_PROG_AWK
 
@@ -5120,16 +5121,47 @@ 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)
 
 dnl ========================================================
+dnl = libnotify support
+dnl ========================================================
+
+MOZ_ARG_ENABLE_BOOL(libnotify,
+[  --enable-libnotify       Enable libnotify support ],
+    MOZ_ENABLE_LIBNOTIFY=1,
+    MOZ_ENABLE_LIBNOTIFY=)
+
+if test "$MOZ_ENABLE_GTK2"
+then
+    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 = Build Personal Security Manager
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(crypto,
 [  --disable-crypto        Disable crypto support (Personal Security Manager)],
     MOZ_PSM=,
     MOZ_PSM=1 )
 
 dnl ========================================================
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -430,16 +430,17 @@ libgnomevfs/gnome-vfs-init.h
 libgnomevfs/gnome-vfs-mime.h
 libgnomevfs/gnome-vfs-mime-handlers.h
 libgnomevfs/gnome-vfs-mime-info.h
 libgnomevfs/gnome-vfs-mime-utils.h
 libgnomevfs/gnome-vfs-ops.h
 libgnomevfs/gnome-vfs-standard-callbacks.h
 libIDL/IDL.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/components/alerts/src/Makefile.in
+++ b/toolkit/components/alerts/src/Makefile.in
@@ -55,11 +55,13 @@ REQUIRES  = xpcom \
             widget \
             gfx \
             $(NULL)
 
 CPPSRCS   = \
     nsAlertsService.cpp \
     $(NULL)
 
+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/build/
+
 include $(topsrcdir)/config/rules.mk
 
 EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
--- a/toolkit/components/alerts/src/nsAlertsService.cpp
+++ b/toolkit/components/alerts/src/nsAlertsService.cpp
@@ -42,16 +42,17 @@
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIServiceManager.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIWindowWatcher.h"
 #include "nsDependentString.h"
 #include "nsWidgetsCID.h"
 #include "nsILookAndFeel.h"
+#include "nsToolkitCompsCID.h"
 
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 
 #define ALERT_CHROME_URL "chrome://global/content/alerts/alert.xul"
 
 NS_IMPL_THREADSAFE_ADDREF(nsAlertsService)
 NS_IMPL_THREADSAFE_RELEASE(nsAlertsService)
 
@@ -68,16 +69,22 @@ nsAlertsService::~nsAlertsService()
 {}
 
 NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, 
                                                      const nsAString & aAlertText, PRBool aAlertTextClickable,
                                                      const nsAString & aAlertCookie,
                                                      nsIObserver * aAlertListener,
                                                      const nsAString & aAlertName)
 {
+  // Check if there is an optional service that handles system-level notifications
+  nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
+  if (sysAlerts)
+    return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
+                                            aAlertCookie, aAlertListener, aAlertName);
+
   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
   nsCOMPtr<nsIDOMWindow> newWindow;
   nsresult rv;
 
   nsCOMPtr<nsISupportsArray> argsArray;
   rv = NS_NewISupportsArray(getter_AddRefs(argsArray));
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -33,16 +33,23 @@
  * 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 ***** */
 
 #define NS_ALERTSERVICE_CONTRACTID \
   "@mozilla.org/alerts-service;1"
 
+// This separate service uses the same nsIAlertsService interface,
+// but instead sends a notification to a platform alerts API
+// if available. Using a separate CID allows us to overwrite the XUL
+// alerts service at runtime.
+#define NS_SYSTEMALERTSERVICE_CONTRACTID \
+  "@mozilla.org/system-alerts-service;1"
+
 #define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \
   "@mozilla.org/autocomplete/controller;1"
 
 #define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \
   "@mozilla.org/autocomplete/controller;1"
 
 #define NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID \
   "@mozilla.org/autocomplete/simple-result;1"
@@ -110,16 +117,20 @@
   "@mozilla.org/browser/favicon-service;1"
 
 /////////////////////////////////////////////////////////////////////////////
 
 // {A0CCAAF8-09DA-44D8-B250-9AC3E93C8117}
 #define NS_ALERTSSERVICE_CID \
 { 0xa0ccaaf8, 0x9da, 0x44d8, { 0xb2, 0x50, 0x9a, 0xc3, 0xe9, 0x3c, 0x81, 0x17 } }
 
+// {84E11F80-CA55-11DD-AD8B-0800200C9A66}
+#define NS_SYSTEMALERTSSERVICE_CID \
+{ 0x84e11f80, 0xca55, 0x11dd, { 0xad, 0x8b, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
+
 // {F6D5EBBD-34F4-487d-9D10-3D34123E3EB9}
 #define NS_AUTOCOMPLETECONTROLLER_CID \
 { 0xf6d5ebbd, 0x34f4, 0x487d, { 0x9d, 0x10, 0x3d, 0x34, 0x12, 0x3e, 0x3e, 0xb9 } }
 
 // {2ee3039b-2de4-43d9-93b0-649beacff39a}
 #define NS_AUTOCOMPLETESIMPLERESULT_CID \
 { 0x2ee3039b, 0x2de4, 0x43d9, { 0x93, 0xb0, 0x64, 0x9b, 0xea, 0xcf, 0xf3, 0x9a } }
 
--- a/toolkit/system/gnome/Makefile.in
+++ b/toolkit/system/gnome/Makefile.in
@@ -46,34 +46,50 @@ MODULE		= mozgnome
 LIBRARY_NAME	= mozgnome
 FORCE_SHARED_LIB = 1
 IS_COMPONENT	= 1
 
 REQUIRES = \
 	xpcom \
 	string \
 	necko \
+	alerts \
+	gfx \
+	imglib2 \
+	intl \
+	widget \
 	$(NULL)
 
 CPPSRCS = \
 	nsGConfService.cpp \
 	nsGnomeVFSService.cpp \
 	nsGnomeModule.cpp \
 	$(NULL)
 
+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) \
 		$(MOZ_LIBGNOME_LIBS) \
 		$(GLIB_LIBS) \
+		$(MOZ_LIBNOTIFY_LIBS) \
 		$(NULL)
 
+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/build/
+
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += \
 	$(MOZ_GCONF_CFLAGS) \
 	$(MOZ_GNOMEVFS_CFLAGS) \
 	$(MOZ_LIBGNOME_CFLAGS) \
 	$(GLIB_CFLAGS) \
+	$(MOZ_LIBNOTIFY_CFLAGS) \
 	$(NULL)
new file mode 100644
--- /dev/null
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -0,0 +1,263 @@
+/* -*- 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
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 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 "nsAlertsIconListener.h"
+#include "imgILoader.h"
+#include "imgIRequest.h"
+#include "gfxIImageFrame.h"
+#include "nsIImage.h"
+#include "nsNetUtil.h"
+#include "nsIImageToPixbuf.h"
+#include "nsIStringBundle.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libnotify/notify.h>
+
+NS_IMPL_ISUPPORTS2(nsAlertsIconListener, imgIContainerObserver, imgIDecoderObserver)
+
+nsAlertsIconListener::nsAlertsIconListener()
+: mLoadedFrame(PR_FALSE)
+{
+  MOZ_COUNT_CTOR(nsAlertsIconListener);
+}
+
+nsAlertsIconListener::~nsAlertsIconListener()
+{
+  MOZ_COUNT_DTOR(nsAlertsIconListener);
+
+  if (mIconRequest)
+    mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
+}
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStartRequest(imgIRequest* aRequest)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStartDecode(imgIRequest* aRequest)
+{
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStartContainer(imgIRequest* aRequest,
+                                       imgIContainer* aContainer)
+{
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStartFrame(imgIRequest* aRequest,
+                                   gfxIImageFrame* aFrame)
+{
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnDataAvailable(imgIRequest* aRequest,
+                                      gfxIImageFrame* aFrame,
+                                      const nsIntRect* aRect)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStopContainer(imgIRequest* aRequest,
+                                      imgIContainer* aContainer)
+{
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStopDecode(imgIRequest* aRequest,
+                                   nsresult status,
+                                   const PRUnichar* statusArg)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAlertsIconListener::FrameChanged(imgIContainer* aContainer,
+                                   gfxIImageFrame* aFrame,
+                                   nsIntRect* aDirtyRect)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStopRequest(imgIRequest* aRequest,
+                                    PRBool aIsLastPart)
+{
+  PRUint32 imgStatus = imgIRequest::STATUS_ERROR;
+  nsresult rv = aRequest->GetImageStatus(&imgStatus);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (imgStatus == imgIRequest::STATUS_ERROR && !mLoadedFrame) {
+    // We have an error getting the image. Display the notification with no icon.
+    ShowAlert(NULL);
+  }
+
+  if (mIconRequest) {
+    mIconRequest->Cancel(NS_BINDING_ABORTED);
+    mIconRequest = nsnull;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest,
+                                  gfxIImageFrame* aFrame)
+{
+  if (aRequest != mIconRequest)
+    return NS_ERROR_FAILURE;
+
+  if (mLoadedFrame)
+    return NS_OK; // only use one frame
+
+  nsCOMPtr<gfxIImageFrame> frame = aFrame;
+  nsCOMPtr<nsIImage> image = do_GetInterface(frame);
+  if (!image)
+    return NS_ERROR_FAILURE;
+
+  nsresult rv = image->LockImagePixels(PR_FALSE);
+  if (NS_FAILED(rv))
+    return rv;
+
+  nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
+    do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
+
+  GdkPixbuf* imagePixbuf = imgToPixbuf->ConvertImageToPixbuf(image);
+  if (!imagePixbuf)
+    return NS_ERROR_FAILURE;
+
+  rv = image->UnlockImagePixels(PR_FALSE);
+  if (NS_FAILED(rv))
+    return rv;
+
+  ShowAlert(imagePixbuf);
+
+  g_object_unref(imagePixbuf);
+
+  mLoadedFrame = PR_TRUE;
+  return NS_OK;
+}
+
+nsresult
+nsAlertsIconListener::ShowAlert(GdkPixbuf* aPixbuf)
+{
+  NotifyNotification* notify = notify_notification_new(mAlertTitle.get(),
+                                                       mAlertText.get(),
+                                                       NULL, NULL);
+  if (!notify)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  if (aPixbuf)
+    notify_notification_set_icon_from_pixbuf(notify, aPixbuf);
+
+  notify_notification_set_timeout(notify, NOTIFY_EXPIRES_DEFAULT);
+  gboolean result = notify_notification_show(notify, NULL);
+  g_object_unref(notify);
+
+  return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsAlertsIconListener::StartRequest(const nsAString & aImageUrl)
+{
+  if (mIconRequest) {
+    // Another icon request is already in flight.  Kill it.
+    mIconRequest->Cancel(NS_BINDING_ABORTED);
+    mIconRequest = nsnull;
+  }
+
+  nsCOMPtr<nsIURI> imageUri;
+  NS_NewURI(getter_AddRefs(imageUri), aImageUrl);
+  if (!imageUri)
+    return ShowAlert(NULL);
+
+  nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
+  if (!il)
+    return ShowAlert(NULL);
+
+  return il->LoadImage(imageUri, nsnull, nsnull, nsnull, this,
+                       nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
+                       getter_AddRefs(mIconRequest));
+}
+
+nsresult
+nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl,
+                                     const nsAString & aAlertTitle, 
+                                     const nsAString & aAlertText)
+{
+  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;
+      bundleService->CreateBundle("chrome://branding/locale/brand.properties",
+                                  getter_AddRefs(bundle));
+      nsAutoString appName;
+
+      if (bundle) {
+        bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+                                  getter_Copies(appName));
+        appShortName = NS_ConvertUTF16toUTF8(appName);
+      } else {
+        NS_WARNING("brand.properties not present, using default application name");
+        appShortName.AssignLiteral("Mozilla");
+      }
+    } else {
+      appShortName.AssignLiteral("Mozilla");
+    }
+
+    if (!notify_init(appShortName.get()))
+      return NS_ERROR_FAILURE;
+  }
+
+  mAlertTitle = NS_ConvertUTF16toUTF8(aAlertTitle);
+  mAlertText = NS_ConvertUTF16toUTF8(aAlertText);
+
+  return StartRequest(aImageUrl);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/system/gnome/nsAlertsIconListener.h
@@ -0,0 +1,74 @@
+/* -*- 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
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 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 ***** */
+
+#ifndef nsAlertsIconListener_h__
+#define nsAlertsIconListener_h__
+
+#include "nsCOMPtr.h"
+#include "imgIDecoderObserver.h"
+#include "nsStringAPI.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+class imgIRequest;
+
+class nsAlertsIconListener : public imgIDecoderObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IMGICONTAINEROBSERVER
+  NS_DECL_IMGIDECODEROBSERVER
+
+  nsAlertsIconListener();
+  virtual ~nsAlertsIconListener();
+
+  nsresult InitAlertAsync(const nsAString & aImageUrl,
+                          const nsAString & aAlertTitle, 
+                          const nsAString & aAlertText);
+
+protected:
+  nsCOMPtr<imgIRequest> mIconRequest;
+  nsCString mAlertTitle;
+  nsCString mAlertText;
+
+  PRPackedBool mLoadedFrame;
+
+  nsresult StartRequest(const nsAString & aImageUrl);
+  nsresult ShowAlert(GdkPixbuf* aPixbuf);
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/toolkit/system/gnome/nsAlertsService.cpp
@@ -0,0 +1,72 @@
+/* -*- 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
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 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 "nsAlertsService.h"
+#include "nsAlertsIconListener.h"
+
+NS_IMPL_THREADSAFE_ADDREF(nsAlertsService)
+NS_IMPL_THREADSAFE_RELEASE(nsAlertsService)
+
+NS_INTERFACE_MAP_BEGIN(nsAlertsService)
+   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertsService)
+   NS_INTERFACE_MAP_ENTRY(nsIAlertsService)
+NS_INTERFACE_MAP_END_THREADSAFE
+
+nsAlertsService::nsAlertsService()
+{}
+
+nsAlertsService::~nsAlertsService()
+{}
+
+nsresult
+nsAlertsService::Init()
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, 
+                                                     const nsAString & aAlertText, PRBool aAlertTextClickable,
+                                                     const nsAString & aAlertCookie,
+                                                     nsIObserver * aAlertListener,
+                                                     const nsAString & aAlertName)
+{
+  nsCOMPtr<nsAlertsIconListener> alertListener = new nsAlertsIconListener();
+  if (!alertListener)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  return alertListener->InitAlertAsync(aImageUrl, aAlertTitle, aAlertText);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/system/gnome/nsAlertsService.h
@@ -0,0 +1,59 @@
+/* -*- 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
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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 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 ***** */
+
+#ifndef nsAlertsService_h__
+#define nsAlertsService_h__
+
+#include "nsIAlertsService.h"
+#include "nsCOMPtr.h"
+
+class nsAlertsService : public nsIAlertsService
+{
+public:
+  NS_DECL_NSIALERTSSERVICE
+  NS_DECL_ISUPPORTS
+
+  nsAlertsService();
+  virtual ~nsAlertsService();
+
+  nsresult Init();
+
+protected:
+
+};
+
+#endif /* nsAlertsService_h__ */
--- a/toolkit/system/gnome/nsGnomeModule.cpp
+++ b/toolkit/system/gnome/nsGnomeModule.cpp
@@ -33,25 +33,40 @@
  * 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 "nsGnomeVFSService.h"
+#include "nsToolkitCompsCID.h"
 #include "nsIGenericFactory.h"
 
+#ifdef MOZ_ENABLE_LIBNOTIFY
+#include "nsAlertsService.h"
+#endif
+
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGConfService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGnomeVFSService, Init)
 
+#ifdef MOZ_ENABLE_LIBNOTIFY
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAlertsService, Init)
+#endif
+
 static const nsModuleComponentInfo components[] = {
   { "GConf Service",
     NS_GCONFSERVICE_CID,
     NS_GCONFSERVICE_CONTRACTID,
     nsGConfServiceConstructor },
   { "GnomeVFS Service",
     NS_GNOMEVFSSERVICE_CID,
     NS_GNOMEVFSSERVICE_CONTRACTID,
-    nsGnomeVFSServiceConstructor }
+    nsGnomeVFSServiceConstructor },
+#ifdef MOZ_ENABLE_LIBNOTIFY
+  { "Gnome Alerts Service",
+    NS_SYSTEMALERTSSERVICE_CID,
+    NS_SYSTEMALERTSERVICE_CONTRACTID,
+    nsAlertsServiceConstructor },
+#endif
 };
 
 NS_IMPL_NSGETMODULE(mozgnome, components)