Bug 1233086, Part 2 - Use unified image loading for libnotify alerts. r=karlt
MozReview-Commit-ID: 4gheorRE0q7
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -1,21 +1,21 @@
/* -*- 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 "nsAlertsIconListener.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
-#include "imgLoader.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsSystemAlertsService.h"
#include "nsIAlertsService.h"
+#include "nsICancelable.h"
#include "nsIImageToPixbuf.h"
#include "nsIStringBundle.h"
#include "nsIObserverService.h"
#include "nsIURI.h"
#include "nsCRT.h"
#include <dlfcn.h>
#include <gdk/gdk.h>
@@ -66,24 +66,23 @@ GetPixbufFromImgRequest(imgIRequest* aRe
}
nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
return imgToPixbuf->ConvertImageToPixbuf(image);
}
-NS_IMPL_ISUPPORTS(nsAlertsIconListener, imgINotificationObserver,
+NS_IMPL_ISUPPORTS(nsAlertsIconListener, nsIAlertNotificationImageListener,
nsIObserver, nsISupportsWeakReference)
nsAlertsIconListener::nsAlertsIconListener(nsSystemAlertsService* aBackend,
const nsAString& aAlertName)
: mAlertName(aAlertName),
mBackend(aBackend),
- mLoadedFrame(false),
mNotification(nullptr)
{
if (!libNotifyHandle && !libNotifyNotAvail) {
libNotifyHandle = dlopen("libnotify.so.4", RTLD_LAZY);
if (!libNotifyHandle) {
libNotifyHandle = dlopen("libnotify.so.1", RTLD_LAZY);
if (!libNotifyHandle) {
libNotifyNotAvail = true;
@@ -104,89 +103,38 @@ nsAlertsIconListener::nsAlertsIconListen
libNotifyHandle = nullptr;
}
}
}
nsAlertsIconListener::~nsAlertsIconListener()
{
mBackend->RemoveListener(mAlertName, this);
- if (mIconRequest)
- mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
// Don't dlclose libnotify as it uses atexit().
}
NS_IMETHODIMP
-nsAlertsIconListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
+nsAlertsIconListener::OnImageMissing(nsISupports*)
{
- if (aType == imgINotificationObserver::LOAD_COMPLETE) {
- return OnLoadComplete(aRequest);
- }
-
- if (aType == imgINotificationObserver::FRAME_COMPLETE) {
- return OnFrameComplete(aRequest);
- }
-
- return NS_OK;
+ // This notification doesn't have an image, or there was an error getting
+ // the image. Show the notification without an icon.
+ return ShowAlert(nullptr);
}
-nsresult
-nsAlertsIconListener::OnLoadComplete(imgIRequest* aRequest)
+NS_IMETHODIMP
+nsAlertsIconListener::OnImageReady(nsISupports*, 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);
-
- // Cancel any pending request
- mIconRequest->Cancel(NS_BINDING_ABORTED);
- mIconRequest = nullptr;
- }
-
- nsCOMPtr<imgIContainer> image;
- rv = aRequest->GetImage(getter_AddRefs(image));
- if (NS_WARN_IF(NS_FAILED(rv) || !image)) {
- return rv;
- }
-
- // Ask the image to decode at its intrinsic size.
- int32_t width = 0, height = 0;
- image->GetWidth(&width);
- image->GetHeight(&height);
- image->RequestDecodeForSize(nsIntSize(width, height), imgIContainer::FLAG_NONE);
-
- return NS_OK;
-}
-
-nsresult
-nsAlertsIconListener::OnFrameComplete(imgIRequest* aRequest)
-{
- NS_ASSERTION(mIconRequest == aRequest, "aRequest does not match!");
-
- if (mLoadedFrame)
- return NS_OK; // only use one frame
-
GdkPixbuf* imagePixbuf = GetPixbufFromImgRequest(aRequest);
if (!imagePixbuf) {
ShowAlert(nullptr);
} else {
ShowAlert(imagePixbuf);
g_object_unref(imagePixbuf);
}
- mLoadedFrame = true;
-
- // Cancel any pending request (multipart image loading/decoding for instance)
- mIconRequest->Cancel(NS_BINDING_ABORTED);
- mIconRequest = nullptr;
-
return NS_OK;
}
nsresult
nsAlertsIconListener::ShowAlert(GdkPixbuf* aPixbuf)
{
if (!mBackend->IsActiveListener(mAlertName, this))
return NS_OK;
@@ -229,48 +177,16 @@ nsAlertsIconListener::ShowAlert(GdkPixbu
}
if (mAlertListener)
mAlertListener->Observe(nullptr, "alertshow", mAlertCookie.get());
return NS_OK;
}
-nsresult
-nsAlertsIconListener::StartRequest(const nsAString & aImageUrl, bool aInPrivateBrowsing)
-{
- if (mIconRequest) {
- // Another icon request is already in flight. Kill it.
- mIconRequest->Cancel(NS_BINDING_ABORTED);
- mIconRequest = nullptr;
- }
-
- nsCOMPtr<nsIURI> imageUri;
- NS_NewURI(getter_AddRefs(imageUri), aImageUrl);
- if (!imageUri)
- return ShowAlert(nullptr);
-
- imgLoader* il = aInPrivateBrowsing ? imgLoader::PrivateBrowsingLoader()
- : imgLoader::NormalLoader();
- if (!il)
- return ShowAlert(nullptr);
-
- nsresult rv = il->LoadImageXPCOM(imageUri, nullptr, nullptr,
- NS_LITERAL_STRING("default"), nullptr, nullptr,
- this, nullptr,
- aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
- nsIRequest::LOAD_NORMAL,
- nullptr, 0 /* use default */,
- getter_AddRefs(mIconRequest));
- if (NS_FAILED(rv))
- return rv;
-
- return NS_OK;
-}
-
void
nsAlertsIconListener::SendCallback()
{
if (mAlertListener)
mAlertListener->Observe(nullptr, "alertclickcallback", mAlertCookie.get());
}
void
@@ -395,23 +311,17 @@ nsAlertsIconListener::InitAlertAsync(nsI
NS_ENSURE_SUCCESS(rv, rv);
mAlertText = NS_ConvertUTF16toUTF8(text);
mAlertListener = aAlertListener;
rv = aAlert->GetCookie(mAlertCookie);
NS_ENSURE_SUCCESS(rv, rv);
- nsAutoString imageUrl;
- rv = aAlert->GetImageURL(imageUrl);
- NS_ENSURE_SUCCESS(rv, rv);
- bool inPrivateBrowsing;
- rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return StartRequest(imageUrl, inPrivateBrowsing);
+ return aAlert->LoadImage(/* aTimeout = */ 0, this, /* aUserData = */ nullptr,
+ getter_AddRefs(mIconRequest));
}
void nsAlertsIconListener::NotifyFinished()
{
if (mAlertListener)
mAlertListener->Observe(nullptr, "alertfinished", mAlertCookie.get());
}
--- a/toolkit/system/gnome/nsAlertsIconListener.h
+++ b/toolkit/system/gnome/nsAlertsIconListener.h
@@ -2,95 +2,90 @@
/* 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 "nsIAlertsService.h"
#include "nsString.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
-class imgIRequest;
class nsIAlertNotification;
+class nsICancelable;
class nsSystemAlertsService;
struct NotifyNotification;
-class nsAlertsIconListener : public imgINotificationObserver,
+class nsAlertsIconListener : public nsIAlertNotificationImageListener,
public nsIObserver,
public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
- NS_DECL_IMGINOTIFICATIONOBSERVER
+ NS_DECL_NSIALERTNOTIFICATIONIMAGELISTENER
NS_DECL_NSIOBSERVER
nsAlertsIconListener(nsSystemAlertsService* aBackend,
const nsAString& aAlertName);
nsresult InitAlertAsync(nsIAlertNotification* aAlert,
nsIObserver* aAlertListener);
nsresult Close();
void SendCallback();
void SendClosed();
protected:
virtual ~nsAlertsIconListener();
- nsresult OnLoadComplete(imgIRequest* aRequest);
- nsresult OnFrameComplete(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*, GError**);
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);
typedef bool (*notify_notification_close_t)(void*, GError**);
- nsCOMPtr<imgIRequest> mIconRequest;
+ nsCOMPtr<nsICancelable> mIconRequest;
nsCString mAlertTitle;
nsCString mAlertText;
nsCOMPtr<nsIObserver> mAlertListener;
nsString mAlertCookie;
nsString mAlertName;
RefPtr<nsSystemAlertsService> mBackend;
- 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;
static notify_notification_close_t notify_notification_close;
NotifyNotification* mNotification;
gulong mClosureHandler;
- nsresult StartRequest(const nsAString & aImageUrl, bool aInPrivateBrowsing);
nsresult ShowAlert(GdkPixbuf* aPixbuf);
void NotifyFinished();
};
#endif