What is it
SnarlInterfaceMozilla (XPCOM) is a DLL to be embedded in extensions for Mozilla based applications to send notifications using the general notifcation system Snarl available for Windows at http://www.fullphat.net/
It makes sending notifications quite easy in a small number of lines written in JavaScript at any place you want. By design SnarlInterfaceMozilla (XPCOM) is made for developers but not for the normal user.
Embedding into an extension
To embed the interface into your extensions copy it into the folder "components"-folder in your extension (create it if you don't have it until now). The three files to be copied into the folder are:
- SnarlInterfaceMozilla.dll
- SnarlInterfaceMozilla.idl
- SnarlInterfaceMozilla.xpt
That's it - SnarlInterfaceMozilla (XPCOM) will now automatically be registered in Mozilla every time the extension is loaded.
Sending simple alerts
Locate the location in your JavaScript-code where you want to send a notification and include the following lines:
const cid = "@tlhan-ghun.de/snarlInterface;5";
var obj = Components.classes[cid].createInstance();
obj = obj.QueryInterface(Components.interfaces.ISNARLINTERFACE);
var returnMsg = obj.snShowMessage(TITLEinSNARL, BODYinSNARL, DISPLAYTIMEinSECONDS,PATHtoICON,0,0);
Where TITLEinSNARL, BODYinSNARL, DISPLAYTIMEinSECONDS and PATHtoICON of course should be exchanged to whatever you want to. PATHtoICON would be something like "c:\my\path\icon.png" or "\\myServer\my\network\path.png"
!!! That's the easy way - if you want to have much more interaction with Snarl read the following lines - if you only want to display some messages you could already stop reading here...
Sending alerts with classes
Registering with Snarl and sending notifications with predefined alert classes greatly improves the experience for the users. She or he is in this case able to easily define different stlyes for different alerts as well as disabling certain alerts or defining their display time on the settings dialog of Snarl.
The general workflow within an extension is as follows:
- register your extension with Snarl
- register one or more alert classes
- send notifications
- unregister your extension on exit
Register and unregister with Snarl
It's a little bit tricky to achieve the goal to only register your extension only once on the startup of the first window of your Mozilla based application and to only unregister on closing the last window. Because of this I additionally included an example JavaScript-file which does exactly this which is called "exampleStartStopObserver.js" into the archive. Copy this file also into your components folder. This file is widely commented so have a look there on how to register your extension. It also includes example code on how to find the path to an image you included in your extension which can be helpful for the app icon as well as icons for single alerts you send. It will be automatically executed on startup of of Mozilla based application if located in the components folder (no entry in install.rdf chrome.manifest needed!).
If you can use the startStopObserver to also add your notification code there (add other observers for example). In this case you don't have the problem with getting the interface window handle and can ignore chapter 4.2 completly.
Example:
var initReturnCode = snarlInterface.snRegisterConfig2(0, "Your application name", 0, "c:\\path\to\an\icon.png", snarlWindowName);
snarlInterface.snRegisterAlert("Your application name","First alert class");
snarlInterface.snRegisterAlert("Your application name","second alert class");
var msgId = snarlInterface.snShowMessageEx("Your title", "Your text", 15, "c:\\someIcon.png",0,0,"","First alert class");
Taking care of Snarl restart
You should take care if Snarl is being restarted during the execution and if it is started after your extension. SnarlInterfaceMozilla sends a notification to the observer service in Mozilla called xxx. If this observer is activated you should (re)register your extension as well as all alert classes within Snarl as described in 4.1.
Example:
SnarlStartAndStopObserver.prototype = {
classID: Components.ID("{4cadb252-b95a-4db5-b780-9855302e3d7d}"), // Generate an own ID
contractID: "@tlhan-ghun.de/snarlObserver/component;1", // generate an own ID
classDescription: "Observer for start and stop of Mozilla application", // some description
QueryInterface: function(aIID) {
if(!aIID.equals(CI.nsISupports) && !aIID.equals(CI.nsIObserver) && !aIID.equals(CI.nsISupportsWeakReference))
throw CR.NS_ERROR_NO_INTERFACE;
return this;
},
var obsSvc = CC["@mozilla.org/observer-service;1"].getService(CI.nsIObserverService);
obsSvc.addObserver(this, "SnarlInterfaceStatus", true);
observe: function(aSubject, aTopic, aData) {
switch(aTopic) {
case "SnarlInterfaceStatus":
if(aData=="Launched") {
var initReturnCode = snarlInterface.snRegisterConfig2(0, "Your application name", 0, "c:\\path\to\an\icon.png", snarlWindowName);
snarlInterface.snRegisterAlert("Your application name","First alert class");
snarlInterface.snRegisterAlert("Your application name","second alert class");
}
}
}
}
}
Getting handle to Snarl within any JavaScript-code
Typically Mozilla extensions are designed as overlays of certain JavaScript-files of the application itself. This also means that your JavaScript is newly loaded every time this JavaScript is started and a new instance is created. Because of this we have to solve two problems:
1. you can't register or deregister your application here - it would be done every time your code is run and you would have problems on detecting the closing of the application - because of this see 4.1
2. on registering a window handle (HWND) is created - but this handle is only known to the script which created it (normally the startStopObserver) and you have to first get it.
To solve this there is an extra command for detecting the window handle:
const cid = "@tlhan-ghun.de/snarlInterface;5";
var snarlInterface = Components.classes[cid5.createInstance();
snarlInterface = snarlInterface.QueryInterface(Components.interfaces.ISNARLINTERFACE);
var generateWindow = snarlInterface.snGetWindowHandle("YourWindowName");
Where "YourWindowName" is the same as defined in the startStopObserver. This command will register the window handle with this instance of this script and you don't need to care about that anymore
Sending notifications with alert classes
Sending a notification now is quite easy - here you see an example:
const cid = "@tlhan-ghun.de/snarlInterface;5";
var snarlInterface = Components.classes[cid].createInstance();
snarlInterface = snarlInterface.QueryInterface(Components.interfaces.ISNARLINTERFACE);
var generateWindow = snarlInterface.snGetWindowHandle("YourWindowName");
var alertID = snarlInterface.snShowMessageEx("Your title", "Your text", displayTimeInSeconds,pathToAnIcon,0,0,"","YourAlertClass");
var alertID2 = snarlInterface.snShowMessageEx("Another title", "Another text", displayTimeInSeconds,pathToAnIcon,0,0,"","AnotherAlertClass");
Reacting on mouse clicks
Snarl sends an information back to your extension if the user clicks the shown notification with the left or right mouse button as well when the notification times out automatically.
SnarlInterfaceMozilla wraps this feedback into a standard Mozilla observer you can listen to as usual within your JavaScript extension code.
Listening to observers
There are six observers:
- SnarlInterfaceACK,
- SnarlInterfaceClicked,
- SnarlInterfaceMiddleMouseButton,
- SnarlInterfaceTimedOut,
- SnarlInterfaceClosed,
- SnarlInterfaceMenu
You can use to detect if the user clicks on a shown notification. All these observers send you the alertID of the clicked notification which you get as return code of snShowMessageEx (see alertID and alertID2 in the example at 4.3).
Example:
var obsSvc = CC["@mozilla.org/observer-service;1"].getService(CI.nsIObserverService);
obsSvc.addObserver(someFunction, "SnarlInterfaceACK", true);
obsSvc.addObserver(someFunction, "SnarlInterfaceClicked", true);
(...)
switch(aTopic) {
// aData has the alertID of the clicked notification in it
case "SnarlInterfaceACK":
var returnMsg = obj.snShowMessage("Left clicked", "some text", 10, "c:\\sdfsf.png" ,0,0);
break;
case "SnarlInterfaceClicked":
var returnMsg = obj.snShowMessage("Right clicked", "some text", 10, "c:\\sdfsf.png" ,0,0);
break;
(...)
}
Reacting on clicks
While you can react generally on left or right mouse buttons (e.g. always bring the application window to front if the user clicks with the left mouse button on any notification) many times it makes more sense to exactly know on which specific notification a user has clicked (example: open in Thunderbird this specific email). To achieve this goal you need to memorize in your code which alertID belongs to which specific event. This ID is sent to to observer in the variable called "aData" for you
You can store this information whereever you want. I included an example in the exampleStartStopObserver where this information is stored in some arrays which can be filled using observers. Another idea could be storing it in the provided SQLite database of Mozilla
Additional commands
The following additonal commands are available in the Snarl API (see also http://www.fullphat.net/developer/developerGuide/api/index.html):
long snShowMessageEx(title, text, timeout, iconPath, hWndReply, uReplyMsg, soundPath, msgClass);
-> Displays a notification with a previous defined alert class
long snShowMessage(title, text, timeout, iconPath, hWndReply, uReplyMsg);
-> Display a simple message (no prior registration needed)
boolean snRegisterConfig2(hWnd, appName, replyMsg, icon, wname);
-> Register your extension with Snarl
boolean snRevokeConfig(hWnd);
-> Unregister your extension with Snarl
boolean snRegisterAlert(appName, className);
-> Register an alert class
boolean snHideMessage(Id);
-> hide a specific message
boolean snIsMessageVisible(Id);
-> check if a specific notification is still visible on the screen
boolean snUpdateMessage(id, title, text, iconPath);
-> change the content of an already displayed notification
long snSetTimeout(Id, Timeout);
-> change the timeout of an already displayed notification
long snGetVersionEx();
-> get Snarl version
long snGetWindowHandle(wname);
-> get (or create if not available already) a communication window between your extension and Snarl
boolean snGetIsRunning();
-> check if Snarl is running currently
License
SnarlInterfaceMozilla is open source and licensed under GPL v3
Sourcecode
The sourcecode (provided as a Visual Studio C++ project can be found in our Subversion.
Additional informations
Our website can be found at http://tlhan-ghun.de/. For feedback you can use our UserVoice. You can subscribe to our RSS-Newsfeed and follow us on Twitter.