diff -up mozilla-release/toolkit/components/alerts/nsAlertsService.cpp.858919 mozilla-release/toolkit/components/alerts/nsAlertsService.cpp --- mozilla-release/toolkit/components/alerts/nsAlertsService.cpp.858919 2014-11-26 03:17:37.000000000 +0100 +++ mozilla-release/toolkit/components/alerts/nsAlertsService.cpp 2014-12-01 11:58:31.896101722 +0100 @@ -100,10 +100,12 @@ NS_IMETHODIMP nsAlertsService::ShowAlert nsCOMPtr sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); nsresult rv; if (sysAlerts) { - return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, - aAlertCookie, aAlertListener, aAlertName, - aBidi, aLang, aData, - IPC::Principal(aPrincipal)); + rv = sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, + aAlertCookie, aAlertListener, aAlertName, + aBidi, aLang, aData, + IPC::Principal(aPrincipal)); + if (NS_SUCCEEDED(rv)) + return NS_OK; } if (!ShouldShowAlert()) { diff -up mozilla-release/toolkit/system/gnome/moz.build.858919 mozilla-release/toolkit/system/gnome/moz.build --- mozilla-release/toolkit/system/gnome/moz.build.858919 2014-11-26 03:17:39.000000000 +0100 +++ mozilla-release/toolkit/system/gnome/moz.build 2014-12-01 11:58:31.896101722 +0100 @@ -5,7 +5,9 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. SOURCES += [ + 'nsAlertsIconListener.cpp', 'nsGnomeModule.cpp', + 'nsSystemAlertsService.cpp', ] if CONFIG['MOZ_ENABLE_GCONF']: diff -up mozilla-release/toolkit/system/gnome/nsAlertsIconListener.cpp.858919 mozilla-release/toolkit/system/gnome/nsAlertsIconListener.cpp --- mozilla-release/toolkit/system/gnome/nsAlertsIconListener.cpp.858919 2014-11-26 03:17:39.000000000 +0100 +++ mozilla-release/toolkit/system/gnome/nsAlertsIconListener.cpp 2014-12-01 12:00:39.455960137 +0100 @@ -51,6 +51,21 @@ static void notify_closed_marshal(GClosu NS_RELEASE(alert); } +static GdkPixbuf* +GetPixbufFromImgRequest(imgIRequest* aRequest) +{ + nsCOMPtr image; + nsresult rv = aRequest->GetImage(getter_AddRefs(image)); + if (NS_FAILED(rv)) { + return nullptr; + } + + nsCOMPtr imgToPixbuf = + do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1"); + + return imgToPixbuf->ConvertImageToPixbuf(image); +} + NS_IMPL_ISUPPORTS(nsAlertsIconListener, imgINotificationObserver, nsIObserver, nsISupportsWeakReference) @@ -106,15 +121,15 @@ nsAlertsIconListener::Notify(imgIRequest nsresult nsAlertsIconListener::OnStopRequest(imgIRequest* aRequest) { + NS_ASSERTION(mIconRequest == aRequest, "aRequest does not match!"); + uint32_t 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(nullptr); - } - if (mIconRequest) { mIconRequest->Cancel(NS_BINDING_ABORTED); mIconRequest = nullptr; } @@ -124,29 +139,25 @@ nsAlertsIconListener::OnStopRequest(imgI nsresult nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest) { - if (aRequest != mIconRequest) - return NS_ERROR_FAILURE; + NS_ASSERTION(mIconRequest == aRequest, "aRequest does not match!"); if (mLoadedFrame) return NS_OK; // only use one frame - nsCOMPtr image; - nsresult rv = aRequest->GetImage(getter_AddRefs(image)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr imgToPixbuf = - do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1"); - - GdkPixbuf* imagePixbuf = imgToPixbuf->ConvertImageToPixbuf(image); - if (!imagePixbuf) - return NS_ERROR_FAILURE; + GdkPixbuf* imagePixbuf = GetPixbufFromImgRequest(aRequest); + if (!imagePixbuf) { + ShowAlert(nullptr); + } else { + ShowAlert(imagePixbuf); + g_object_unref(imagePixbuf); + } - ShowAlert(imagePixbuf); + mLoadedFrame = true; - g_object_unref(imagePixbuf); + // Cancel any pending request (multipart image loading/decoding for instance) + mIconRequest->Cancel(NS_BINDING_ABORTED); + mIconRequest = nullptr; - mLoadedFrame = true; return NS_OK; } @@ -180,6 +191,9 @@ nsAlertsIconListener::ShowAlert(GdkPixbu mClosureHandler = g_signal_connect_closure(mNotification, "closed", closure, FALSE); gboolean result = notify_notification_show(mNotification, nullptr); + if (result && mAlertListener) + mAlertListener->Observe(nullptr, "alertshow", mAlertCookie.get()); + return result ? NS_OK : NS_ERROR_FAILURE; } @@ -201,9 +215,15 @@ nsAlertsIconListener::StartRequest(const if (!il) return ShowAlert(nullptr); - return il->LoadImageXPCOM(imageUri, nullptr, nullptr, nullptr, nullptr, - this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - nullptr, getter_AddRefs(mIconRequest)); + nsresult rv = il->LoadImageXPCOM(imageUri, nullptr, nullptr, nullptr, nullptr, + this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, + 0 /* use default */, getter_AddRefs(mIconRequest)); + if (NS_FAILED(rv)) + return rv; + + mIconRequest->StartDecoding(); + + return NS_OK; } void diff -up mozilla-release/toolkit/system/gnome/nsAlertsIconListener.h.858919 mozilla-release/toolkit/system/gnome/nsAlertsIconListener.h --- mozilla-release/toolkit/system/gnome/nsAlertsIconListener.h.858919 2014-12-01 11:58:31.896101722 +0100 +++ mozilla-release/toolkit/system/gnome/nsAlertsIconListener.h 2014-12-01 11:58:31.896101722 +0100 @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsAlertsIconListener_h__ +#define nsAlertsIconListener_h__ + +#include "nsCOMPtr.h" +#include "imgINotificationObserver.h" +#include "nsStringAPI.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" + +#include + +class imgIRequest; + +struct NotifyNotification; + +class nsAlertsIconListener : public imgINotificationObserver, + public nsIObserver, + public nsSupportsWeakReference +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_IMGINOTIFICATIONOBSERVER + NS_DECL_NSIOBSERVER + + nsAlertsIconListener(); + + nsresult InitAlertAsync(const nsAString & aImageUrl, + const nsAString & aAlertTitle, + const nsAString & aAlertText, + bool aAlertTextClickable, + const nsAString & aAlertCookie, + nsIObserver * aAlertListener); + + void SendCallback(); + void SendClosed(); + +protected: + virtual ~nsAlertsIconListener(); + + nsresult OnStopRequest(imgIRequest* aRequest); + nsresult OnStopFrame(imgIRequest* aRequest); + + /** + * 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 mIconRequest; + nsCString mAlertTitle; + nsCString mAlertText; + + nsCOMPtr 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 diff -up mozilla-release/toolkit/system/gnome/nsGnomeModule.cpp.858919 mozilla-release/toolkit/system/gnome/nsGnomeModule.cpp --- mozilla-release/toolkit/system/gnome/nsGnomeModule.cpp.858919 2014-11-26 03:17:39.000000000 +0100 +++ mozilla-release/toolkit/system/gnome/nsGnomeModule.cpp 2014-12-01 11:58:31.896101722 +0100 @@ -22,6 +22,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGn NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIOService) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGSettingsService, Init) #endif +#include "nsSystemAlertsService.h" +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemAlertsService, Init) #ifdef MOZ_ENABLE_GCONF NS_DEFINE_NAMED_CID(NS_GCONFSERVICE_CID); @@ -33,6 +35,7 @@ NS_DEFINE_NAMED_CID(NS_GNOMEVFSSERVICE_C NS_DEFINE_NAMED_CID(NS_GIOSERVICE_CID); NS_DEFINE_NAMED_CID(NS_GSETTINGSSERVICE_CID); #endif +NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID); static const mozilla::Module::CIDEntry kGnomeCIDs[] = { #ifdef MOZ_ENABLE_GCONF @@ -45,6 +48,7 @@ static const mozilla::Module::CIDEntry k { &kNS_GIOSERVICE_CID, false, nullptr, nsGIOServiceConstructor }, { &kNS_GSETTINGSSERVICE_CID, false, nullptr, nsGSettingsServiceConstructor }, #endif + { &kNS_SYSTEMALERTSSERVICE_CID, false, nullptr, nsSystemAlertsServiceConstructor }, { nullptr } }; @@ -59,6 +63,7 @@ static const mozilla::Module::ContractID { NS_GIOSERVICE_CONTRACTID, &kNS_GIOSERVICE_CID }, { NS_GSETTINGSSERVICE_CONTRACTID, &kNS_GSETTINGSSERVICE_CID }, #endif + { NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_CID }, { nullptr } }; diff -up mozilla-release/toolkit/system/gnome/nsSystemAlertsService.cpp.858919 mozilla-release/toolkit/system/gnome/nsSystemAlertsService.cpp --- mozilla-release/toolkit/system/gnome/nsSystemAlertsService.cpp.858919 2014-12-01 11:58:31.897101728 +0100 +++ mozilla-release/toolkit/system/gnome/nsSystemAlertsService.cpp 2014-12-01 11:58:31.896101722 +0100 @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsXULAppAPI.h" +#include "nsSystemAlertsService.h" +#include "nsAlertsIconListener.h" +#include "nsAutoPtr.h" + +NS_IMPL_ADDREF(nsSystemAlertsService) +NS_IMPL_RELEASE(nsSystemAlertsService) + +NS_INTERFACE_MAP_BEGIN(nsSystemAlertsService) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertsService) + NS_INTERFACE_MAP_ENTRY(nsIAlertsService) +NS_INTERFACE_MAP_END_THREADSAFE + +nsSystemAlertsService::nsSystemAlertsService() +{ +} + +nsSystemAlertsService::~nsSystemAlertsService() +{} + +nsresult +nsSystemAlertsService::Init() +{ + return NS_OK; +} + +NS_IMETHODIMP nsSystemAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, + const nsAString & aAlertText, bool aAlertTextClickable, + const nsAString & aAlertCookie, + nsIObserver * aAlertListener, + const nsAString & aAlertName, + const nsAString & aBidi, + const nsAString & aLang, + const nsAString & aData, + nsIPrincipal * aPrincipal) +{ + nsRefPtr alertListener = new nsAlertsIconListener(); + if (!alertListener) + return NS_ERROR_OUT_OF_MEMORY; + + return alertListener->InitAlertAsync(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, + aAlertCookie, aAlertListener); +} + +NS_IMETHODIMP nsSystemAlertsService::CloseAlert(const nsAString& aAlertName, + nsIPrincipal* aPrincipal) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} diff -up mozilla-release/toolkit/system/gnome/nsSystemAlertsService.h.858919 mozilla-release/toolkit/system/gnome/nsSystemAlertsService.h --- mozilla-release/toolkit/system/gnome/nsSystemAlertsService.h.858919 2014-12-01 11:58:31.897101728 +0100 +++ mozilla-release/toolkit/system/gnome/nsSystemAlertsService.h 2014-12-01 11:58:31.897101728 +0100 @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsSystemAlertsService_h__ +#define nsSystemAlertsService_h__ + +#include "nsIAlertsService.h" +#include "nsCOMPtr.h" + +class nsSystemAlertsService : public nsIAlertsService +{ +public: + NS_DECL_NSIALERTSSERVICE + NS_DECL_ISUPPORTS + + nsSystemAlertsService(); + + nsresult Init(); + +protected: + virtual ~nsSystemAlertsService(); + +}; + +#endif /* nsSystemAlertsService_h__ */