Bug 1233086, Part 2 - Use unified image loading for libnotify alerts. r=karlt
authorKit Cambridge <kcambridge@mozilla.com>
Fri, 10 Jun 2016 18:37:38 -0700
changeset 342813 21f3d3f6baa20da311007eccfc34861a97bb97a9
parent 342812 e6fc6996103a59b11dcaa3a6c454eb41cdc810f1
child 342814 14e487fc2bad07b1d1da91fa31e6b8e5955a2bbd
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1233086
milestone50.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 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