--- a/widget/cocoa/OSXNotificationCenter.h
+++ b/widget/cocoa/OSXNotificationCenter.h
@@ -19,26 +19,24 @@
typedef NSInteger NSUserNotificationActivationType;
#endif
namespace mozilla {
class OSXNotificationInfo;
class OSXNotificationCenter : public nsIAlertsService,
- public imgINotificationObserver,
- public nsITimerCallback,
- public nsIAlertsIconData
+ public nsIAlertsIconData,
+ public nsIAlertNotificationImageListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIALERTSSERVICE
- NS_DECL_IMGINOTIFICATIONOBSERVER
- NS_DECL_NSITIMERCALLBACK
NS_DECL_NSIALERTSICONDATA
+ NS_DECL_NSIALERTNOTIFICATIONIMAGELISTENER
OSXNotificationCenter();
nsresult Init();
void CloseAlertCocoaString(NSString *aAlertName);
void OnActivate(NSString *aAlertName, NSUserNotificationActivationType aActivationType,
unsigned long long aAdditionalActionIndex);
void ShowPendingNotification(OSXNotificationInfo *osxni);
--- a/widget/cocoa/OSXNotificationCenter.mm
+++ b/widget/cocoa/OSXNotificationCenter.mm
@@ -2,28 +2,26 @@
/* 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 "OSXNotificationCenter.h"
#import <AppKit/AppKit.h>
#include "imgIRequest.h"
#include "imgIContainer.h"
+#include "nsICancelable.h"
#include "nsIStringBundle.h"
#include "nsNetUtil.h"
-#include "imgLoader.h"
#import "nsCocoaUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsObjCExceptions.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
-#include "nsIContentPolicy.h"
-#include "imgRequestProxy.h"
using namespace mozilla;
#define MAX_NOTIFICATION_NAME_LEN 5000
#if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8)
@protocol NSUserNotificationCenterDelegate
@end
@@ -145,33 +143,34 @@ enum {
namespace mozilla {
enum {
OSXNotificationActionDisable = 0,
OSXNotificationActionSettings = 1,
};
-class OSXNotificationInfo {
+class OSXNotificationInfo final : public nsISupports {
private:
- ~OSXNotificationInfo();
+ virtual ~OSXNotificationInfo();
public:
- NS_INLINE_DECL_REFCOUNTING(OSXNotificationInfo)
+ NS_DECL_ISUPPORTS
OSXNotificationInfo(NSString *name, nsIObserver *observer,
const nsAString & alertCookie);
NSString *mName;
nsCOMPtr<nsIObserver> mObserver;
nsString mCookie;
- RefPtr<imgRequestProxy> mIconRequest;
+ RefPtr<nsICancelable> mIconRequest;
id<FakeNSUserNotification> mPendingNotifiction;
- nsCOMPtr<nsITimer> mIconTimeoutTimer;
};
+NS_IMPL_ISUPPORTS0(OSXNotificationInfo)
+
OSXNotificationInfo::OSXNotificationInfo(NSString *name, nsIObserver *observer,
const nsAString & alertCookie)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NS_ASSERTION(name, "Cannot create OSXNotificationInfo without a name!");
mName = [name retain];
mObserver = observer;
@@ -215,18 +214,18 @@ OSXNotificationCenter::~OSXNotificationC
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
[GetNotificationCenter() removeAllDeliveredNotifications];
[mDelegate release];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
-NS_IMPL_ISUPPORTS(OSXNotificationCenter, nsIAlertsService, nsITimerCallback,
- imgINotificationObserver, nsIAlertsIconData)
+NS_IMPL_ISUPPORTS(OSXNotificationCenter, nsIAlertsService, nsIAlertsIconData,
+ nsIAlertNotificationImageListener)
nsresult OSXNotificationCenter::Init()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
return (!!NSClassFromString(@"NSUserNotification")) ? NS_OK : NS_ERROR_FAILURE;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@@ -382,67 +381,39 @@ OSXNotificationCenter::ShowAlertWithIcon
NSData *iconData = [NSData dataWithBytes:aIconData length:aIconSize];
NSImage *icon = [[[NSImage alloc] initWithData:iconData] autorelease];
[(NSObject*)notification setValue:icon forKey:@"_identityImage"];
[(NSObject*)notification setValue:@(NO) forKey:@"_identityImageHasBorder"];
}
- nsAutoString imageUrl;
- rv = aAlert->GetImageURL(imageUrl);
- NS_ENSURE_SUCCESS(rv, rv);
-
bool inPrivateBrowsing;
rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing);
NS_ENSURE_SUCCESS(rv, rv);
// Show the notification without waiting for an image if there is no icon URL or
// notification icons are not supported on this version of OS X.
- if (imageUrl.IsEmpty() || ![unClass instancesRespondToSelector:@selector(setContentImage:)]) {
+ if (![unClass instancesRespondToSelector:@selector(setContentImage:)]) {
CloseAlertCocoaString(alertName);
mActiveAlerts.AppendElement(osxni);
[GetNotificationCenter() deliverNotification:notification];
[notification release];
if (aAlertListener) {
aAlertListener->Observe(nullptr, "alertshow", cookie.get());
}
} else {
mPendingAlerts.AppendElement(osxni);
osxni->mPendingNotifiction = notification;
- imgLoader* il = inPrivateBrowsing ? imgLoader::PrivateBrowsingLoader()
- : imgLoader::NormalLoader();
- if (il) {
- nsCOMPtr<nsIURI> imageUri;
- NS_NewURI(getter_AddRefs(imageUri), imageUrl);
- if (imageUri) {
- nsCOMPtr<nsIPrincipal> principal;
- rv = aAlert->GetPrincipal(getter_AddRefs(principal));
- if (NS_SUCCEEDED(rv)) {
- rv = il->LoadImage(imageUri, nullptr, nullptr,
- mozilla::net::RP_Default,
- principal, nullptr,
- this, nullptr, nullptr,
- inPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
- nsIRequest::LOAD_NORMAL,
- nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE,
- EmptyString(),
- getter_AddRefs(osxni->mIconRequest));
- if (NS_SUCCEEDED(rv)) {
- // Set a timer for six seconds. If we don't have an icon by the time this
- // goes off then we go ahead without an icon.
- nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
- osxni->mIconTimeoutTimer = timer;
- timer->InitWithCallback(this, 6000, nsITimer::TYPE_ONE_SHOT);
- return NS_OK;
- }
- }
- }
+ // Wait six seconds for the image to load.
+ rv = aAlert->LoadImage(6000, this, osxni,
+ getter_AddRefs(osxni->mIconRequest));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ ShowPendingNotification(osxni);
}
- ShowPendingNotification(osxni);
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
@@ -478,16 +449,20 @@ OSXNotificationCenter::CloseAlertCocoaSt
}
for (unsigned int i = 0; i < mActiveAlerts.Length(); i++) {
OSXNotificationInfo *osxni = mActiveAlerts[i];
if ([aAlertName isEqualToString:osxni->mName]) {
if (osxni->mObserver) {
osxni->mObserver->Observe(nullptr, "alertfinished", osxni->mCookie.get());
}
+ if (osxni->mIconRequest) {
+ osxni->mIconRequest->Cancel(NS_BINDING_ABORTED);
+ osxni->mIconRequest = nullptr;
+ }
mActiveAlerts.RemoveElementAt(i);
break;
}
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@@ -533,21 +508,16 @@ OSXNotificationCenter::OnActivate(NSStri
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
OSXNotificationCenter::ShowPendingNotification(OSXNotificationInfo *osxni)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
- if (osxni->mIconTimeoutTimer) {
- osxni->mIconTimeoutTimer->Cancel();
- osxni->mIconTimeoutTimer = nullptr;
- }
-
if (osxni->mIconRequest) {
osxni->mIconRequest->Cancel(NS_BINDING_ABORTED);
osxni->mIconRequest = nullptr;
}
CloseAlertCocoaString(osxni->mName);
for (unsigned int i = 0; i < mPendingAlerts.Length(); i++) {
@@ -566,67 +536,52 @@ OSXNotificationCenter::ShowPendingNotifi
[osxni->mPendingNotifiction release];
osxni->mPendingNotifiction = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_IMETHODIMP
-OSXNotificationCenter::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
+OSXNotificationCenter::OnImageMissing(nsISupports* aUserData)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
- if (aType == imgINotificationObserver::LOAD_COMPLETE) {
- OSXNotificationInfo *osxni = nullptr;
- for (unsigned int i = 0; i < mPendingAlerts.Length(); i++) {
- if (aRequest == mPendingAlerts[i]->mIconRequest) {
- osxni = mPendingAlerts[i];
- break;
- }
- }
- if (!osxni || !osxni->mPendingNotifiction) {
- return NS_ERROR_FAILURE;
- }
- NSImage *cocoaImage = nil;
- uint32_t imgStatus = imgIRequest::STATUS_ERROR;
- nsresult rv = aRequest->GetImageStatus(&imgStatus);
- if (NS_SUCCEEDED(rv) && !(imgStatus & imgIRequest::STATUS_ERROR)) {
- nsCOMPtr<imgIContainer> image;
- rv = aRequest->GetImage(getter_AddRefs(image));
- if (NS_SUCCEEDED(rv)) {
- nsCocoaUtils::CreateNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, &cocoaImage, 1.0f);
- }
- }
- (osxni->mPendingNotifiction).contentImage = cocoaImage;
- [cocoaImage release];
+ OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
+ if (osxni->mPendingNotifiction) {
+ // If there was an error getting the image, or the request timed out, show
+ // the notification without a content image.
ShowPendingNotification(osxni);
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
-OSXNotificationCenter::Notify(nsITimer *timer)
+OSXNotificationCenter::OnImageReady(nsISupports* aUserData,
+ imgIRequest* aRequest)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
- if (!timer) {
+ nsCOMPtr<imgIContainer> image;
+ nsresult rv = aRequest->GetImage(getter_AddRefs(image));
+ if (NS_WARN_IF(NS_FAILED(rv) || !image)) {
+ return rv;
+ }
+
+ OSXNotificationInfo *osxni = static_cast<OSXNotificationInfo*>(aUserData);
+ if (!osxni->mPendingNotifiction) {
return NS_ERROR_FAILURE;
}
- for (unsigned int i = 0; i < mPendingAlerts.Length(); i++) {
- OSXNotificationInfo *osxni = mPendingAlerts[i];
- if (timer == osxni->mIconTimeoutTimer.get()) {
- osxni->mIconTimeoutTimer = nullptr;
- if (osxni->mPendingNotifiction) {
- ShowPendingNotification(osxni);
- break;
- }
- }
- }
+ NSImage *cocoaImage = nil;
+ nsCocoaUtils::CreateNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, &cocoaImage, 1.0f);
+ (osxni->mPendingNotifiction).contentImage = cocoaImage;
+ [cocoaImage release];
+ ShowPendingNotification(osxni);
+
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
} // namespace mozilla