Bug 1233086, Part 2 - Use unified image loading for libnotify alerts. r=karlt draft
authorKit Cambridge <kcambridge@mozilla.com>
Fri, 10 Jun 2016 18:37:38 -0700
changeset 381546 bd88f0e35c32ef634310c2b92774a790d3c9b7da
parent 381545 d63d61e4e7f5d96315a51ca8de0f932449ee5824
child 381547 54c144634f5c17a747d54a7d007e5fee0a1aabe4
push id21506
push userkcambridge@mozilla.com
push dateMon, 27 Jun 2016 18:27:43 +0000
reviewerskarlt
bugs1233086
milestone50.0a1
Bug 1233086, Part 2 - Use unified image loading for libnotify alerts. r=karlt MozReview-Commit-ID: 4gheorRE0q7
toolkit/system/gnome/nsAlertsIconListener.cpp
toolkit/system/gnome/nsAlertsIconListener.h
--- 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