Bug 382694 - Allow applications to specify notification names to growl other than the default. r=cbarrett, r=mano

This commit is contained in:
sdwilsh@shawnwilsher.com 2007-07-15 14:16:52 -07:00
parent f8417811ce
commit 8483004f7e
11 changed files with 345 additions and 48 deletions

View File

@ -45,7 +45,11 @@ include $(DEPTH)/config/autoconf.mk
MODULE = alerts
XPIDL_MODULE=alerts
XPIDLSRCS = nsIAlertsService.idl \
XPIDLSRCS = nsIAlertsService.idl
ifneq (,$(filter cocoa, $(MOZ_WIDGET_TOOLKIT)))
XPIDLSRCS += nsINotificationsList.idl
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,59 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(11e0176a-4a2d-4a90-8dcc-1590eeb1769d)]
interface nsINotificationsList : nsISupports
{
/**
* Adds a notification to the registration dictionary.
*
* @param aName The name of the notification we might be sending.
* @param aEnabled Indicates if the notification is enabled by default.
*/
void addNotification(in AString aName, in boolean aEnabled);
/**
* Checks to see if a paticular notification has already been registered.
*
* @param aName The name of the notification we are checking against.
*/
boolean isNotification(in AString aName);
};

View File

@ -58,6 +58,7 @@ CMMSRCS = \
nsAlertsService.mm \
mozGrowlDelegate.mm \
nsAlertsImageLoadListener.mm \
nsNotificationsList.mm \
$(NULL)
CPPSRCS = \
@ -69,6 +70,10 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/toolkit/components/build/ \
$(NULL)
EXPORTS = \
nsAlertsService.h \
$(NULL)
SHARED_LIBRARY_LIBS = \
growl/$(LIB_PREFIX)growl_s.$(LIB_SUFFIX) \
$(NULL)

View File

@ -71,6 +71,20 @@
key:(PRUint32)aKey
cookie:(const nsAString&)aCookie;
/**
* Adds notifications to the registration dictionary.
*
* @param aNames An NSArray of names of notifications.
*/
- (void) addNotificationNames:(NSArray*)aNames;
/**
* Adds enabled notifications to the registration dictionary.
*
* @param aEnabled An NSArray of names of enabled notifications.
*/
- (void) addEnabledNotifications:(NSArray*)aEnabled;
/**
* Adds an nsIObserver that we can query later for dispatching obsevers.
*

View File

@ -98,6 +98,16 @@
[super dealloc];
}
- (void) addNotificationNames:(NSArray*)aNames
{
[mNames addObjectsFromArray: aNames];
}
- (void) addEnabledNotifications:(NSArray*)aEnabled
{
[mEnabled addObjectsFromArray: aEnabled];
}
+ (void) notifyWithName:(const nsAString&)aName
title:(const nsAString&)aTitle
description:(const nsAString&)aText

View File

@ -48,7 +48,6 @@ public:
nsAlertsImageLoadListener(const nsAString &aName,
const nsAString& aAlertTitle,
const nsAString& aAlertText,
PRBool aAlertClickable,
const nsAString& aAlertCookie,
PRUint32 aAlertListenerKey);
@ -58,7 +57,6 @@ private:
nsString mName;
nsString mAlertTitle;
nsString mAlertText;
PRBool mAlertClickable;
nsString mAlertCookie;
PRUint32 mAlertListenerKey;
};

View File

@ -48,12 +48,10 @@ NS_IMPL_ISUPPORTS1(nsAlertsImageLoadListener, nsIStreamLoaderObserver)
nsAlertsImageLoadListener::nsAlertsImageLoadListener(const nsAString &aName,
const nsAString& aAlertTitle,
const nsAString& aAlertText,
PRBool aAlertClickable,
const nsAString& aAlertCookie,
PRUint32 aAlertListenerKey) :
mName(aName), mAlertTitle(aAlertTitle), mAlertText(aAlertText),
mAlertClickable(aAlertClickable), mAlertCookie(aAlertCookie),
mAlertListenerKey(aAlertListenerKey)
mAlertCookie(aAlertCookie), mAlertListenerKey(aAlertListenerKey)
{
}

View File

@ -42,6 +42,24 @@
struct GrowlDelegateWrapper;
/**
* Helper function to allow for C++ to dispatch named notifications.
*
* @param aName The name of the notification to dispatch to Growl.
* @param aImage The image to display in the notification.
* @param aTitle The text of the title of the notification.
* @param aMessage The message body of the notification.
* @param aCookie The cookie string that will be passed back to the observer.
* @param aListener The nsIObserver that will receive callbacks from Growl.
*/
nsresult
NS_DispatchNamedNotification(const nsAString &aName,
const nsAString &aImage,
const nsAString &aTitle,
const nsAString &aMessage,
const nsAString &aCookie,
nsIObserver *aListener);
class nsAlertsService : public nsIAlertsService,
public nsIObserver
{

View File

@ -40,22 +40,17 @@
#include "nsIURI.h"
#include "nsIStreamLoader.h"
#include "nsNetUtil.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "nsIStringBundle.h"
#include "nsIObserverService.h"
#include "nsAutoPtr.h"
#include "nsNotificationsList.h"
#import "mozGrowlDelegate.h"
#import "GrowlApplicationBridge.h"
NS_IMPL_THREADSAFE_ADDREF(nsAlertsService)
NS_IMPL_THREADSAFE_RELEASE(nsAlertsService)
NS_INTERFACE_MAP_BEGIN(nsAlertsService)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertsService)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIAlertsService)
NS_INTERFACE_MAP_END_THREADSAFE
////////////////////////////////////////////////////////////////////////////////
//// GrowlDelegateWrapper
struct GrowlDelegateWrapper
{
@ -72,6 +67,64 @@ struct GrowlDelegateWrapper
}
};
////////////////////////////////////////////////////////////////////////////////
//// NS_DispatchNamedNotification
nsresult
NS_DispatchNamedNotification(const nsAString &aName,
const nsAString &aImage,
const nsAString &aTitle,
const nsAString &aMessage,
const nsAString &aCookie,
nsIObserver *aListener)
{
if ([GrowlApplicationBridge isGrowlInstalled] == NO ||
[GrowlApplicationBridge isGrowlRunning] == NO)
return NS_ERROR_NOT_AVAILABLE;
mozGrowlDelegate *delegate =
static_cast<mozGrowlDelegate *>([GrowlApplicationBridge growlDelegate]);
if (!delegate)
return NS_ERROR_NOT_AVAILABLE;
PRUint32 ind = 0;
if (aListener)
ind = [delegate addObserver: aListener];
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aImage);
if (NS_FAILED(rv)) {
// image uri failed to resolve, so dispatch to growl with no image
[mozGrowlDelegate notifyWithName: aName
title: aTitle
description: aMessage
iconData: [NSData data]
key: ind
cookie: aCookie];
return NS_OK;
}
nsCOMPtr<nsAlertsImageLoadListener> listener =
new nsAlertsImageLoadListener(aName, aTitle, aMessage, aCookie, ind);
if (!listener)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIStreamLoader> loader;
return NS_NewStreamLoader(getter_AddRefs(loader), uri, listener);
}
////////////////////////////////////////////////////////////////////////////////
//// nsAlertsService
NS_IMPL_THREADSAFE_ADDREF(nsAlertsService)
NS_IMPL_THREADSAFE_RELEASE(nsAlertsService)
NS_INTERFACE_MAP_BEGIN(nsAlertsService)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertsService)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIAlertsService)
NS_INTERFACE_MAP_END_THREADSAFE
nsresult
nsAlertsService::Init()
{
@ -94,6 +147,9 @@ nsAlertsService::~nsAlertsService()
delete mDelegate;
}
////////////////////////////////////////////////////////////////////////////////
//// nsIAlertsService
NS_IMETHODIMP
nsAlertsService::ShowAlertNotification(const nsAString& aImageUrl,
const nsAString& aAlertTitle,
@ -105,13 +161,6 @@ nsAlertsService::ShowAlertNotification(const nsAString& aImageUrl,
NS_ASSERTION(mDelegate->delegate == [GrowlApplicationBridge growlDelegate],
"Growl Delegate was not registered properly.");
if ([GrowlApplicationBridge isGrowlRunning] == NO)
return NS_ERROR_NOT_AVAILABLE;
PRUint32 ind = 0;
if (aAlertListener)
ind = [mDelegate->delegate addObserver: aAlertListener];
nsresult rv;
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService("@mozilla.org/intl/stringbundle;1", &rv);
@ -130,43 +179,34 @@ nsAlertsService::ShowAlertNotification(const nsAString& aImageUrl,
}
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aImageUrl);
if (NS_FAILED(rv)) {
// image uri failed to resolve, so dispatch to growl with no image
[mozGrowlDelegate notifyWithName: name
title: aAlertTitle
description: aAlertText
iconData: [NSData data]
key: ind
cookie: aAlertCookie];
return NS_OK;
}
nsCOMPtr<nsAlertsImageLoadListener> listener =
new nsAlertsImageLoadListener(name, aAlertTitle, aAlertText,
aAlertClickable, aAlertCookie, ind);
if (!listener)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIStreamLoader> loader;
rv = NS_NewStreamLoader(getter_AddRefs(loader), uri, listener);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
return NS_DispatchNamedNotification(name, aImageUrl, aAlertTitle,
aAlertText, aAlertCookie, aAlertListener);
}
////////////////////////////////////////////////////////////////////////////////
//// nsIObserver
NS_IMETHODIMP
nsAlertsService::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
if (nsCRT::strcmp(aTopic, "final-ui-startup") == 0) {
if (strcmp(aTopic, "final-ui-startup") == 0) {
NS_ASSERTION([GrowlApplicationBridge growlDelegate] == nil,
"We already registered with Growl!");
nsRefPtr<nsNotificationsList> notifications = new nsNotificationsList();
if (notifications) {
nsCOMPtr<nsIObserverService> os =
do_GetService("@mozilla.org/observer-service;1");
(void)os->NotifyObservers(notifications, "before-growl-registration", nsnull);
}
mDelegate = new GrowlDelegateWrapper();
if (notifications)
notifications->informController(mDelegate->delegate);
// registers with Growl
[GrowlApplicationBridge setGrowlDelegate: mDelegate->delegate];
}

View File

@ -0,0 +1,60 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Growl implementation of nsIAlertsService.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsNotificationsList_h_
#define nsNotificationsList_h_
#include "nsINotificationsList.h"
#import "mozGrowlDelegate.h"
class nsNotificationsList : public nsINotificationsList
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINOTIFICATIONSLIST
nsNotificationsList();
void informController(mozGrowlDelegate *aCont);
private:
virtual ~nsNotificationsList();
NSMutableArray *mNames;
NSMutableArray *mEnabled;
};
#endif // nsNotificationsList_h_

View File

@ -0,0 +1,91 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Growl implementation of nsIAlertsService.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsNotificationsList.h"
#include "nsStringAPI.h"
NS_IMPL_ADDREF(nsNotificationsList)
NS_IMPL_RELEASE(nsNotificationsList)
NS_INTERFACE_MAP_BEGIN(nsNotificationsList)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINotificationsList)
NS_INTERFACE_MAP_ENTRY(nsINotificationsList)
NS_INTERFACE_MAP_END
nsNotificationsList::nsNotificationsList()
{
mNames = [[NSMutableArray alloc] init];
mEnabled = [[NSMutableArray alloc] init];
}
nsNotificationsList::~nsNotificationsList()
{
[mNames release];
[mEnabled release];
}
NS_IMETHODIMP
nsNotificationsList::AddNotification(const nsAString &aName, PRBool aEnabled)
{
NSString *name = [NSString stringWithCharacters: aName.BeginReading()
length: aName.Length()];
[mNames addObject: name];
if (aEnabled)
[mEnabled addObject: name];
return NS_OK;
}
NS_IMETHODIMP
nsNotificationsList::IsNotification(const nsAString &aName, PRBool *retVal)
{
NSString *name = [NSString stringWithCharacters: aName.BeginReading()
length: aName.Length()];
*retVal = [mNames containsObject: name] ? PR_TRUE : PR_FALSE;
return NS_OK;
}
void
nsNotificationsList::informController(mozGrowlDelegate *aController)
{
[aController addNotificationNames: mNames];
[aController addEnabledNotifications: mEnabled];
}