The handlerInfo
object returned here is exactly same as doing it with the above method of nsiExternalProtocolService
.
If you go to the options panel and change to alwaysAsk the alwaysAskBeforeHandling
property in the log handlerInfo
s will reflect properly.
var handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].getService(Ci.nsIHandlerService);
var listOfWrappedHandlers = handlerService.enumerate();
var i = 0;
while (listOfWrappedHandlers.hasMoreElements()) {
var handlerInfo = listOfWrappedHandlers.getNext().QueryInterface(Ci.nsIHandlerInfo);
//console.log(i, 'handler for', wrappedHandlerInfo.type, wrappedHandlerInfo);
if (handlerInfo.type == 'mailto') {
break;
}
i++;
}
console.log('handlerServicehandlerInfo=', handlerInfo); //is the mailto one as we broke the loop once it found that
Does not have possibleLocalHandlers
in handlerInfo
.
The handlerInfo
object returned here is exactly same as doing it with the above method of nsIHandlerService
.
If you go to the options panel and change to alwaysAsk the alwaysAskBeforeHandling
property in the log handlerInfo
s will reflect properly.
var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
var handlerInfo = eps.getProtocolHandlerInfo('mailto');
console.log('epsHandlerInfo', handlerInfo)
Does not have possibleLocalHandlers
in handlerInfo
.
note: has major quirks, like not accurately refelect preferedHandler
and alwaysAskBeforeHandling
(i just noticed these two so far I didnt explore other properties but they may be equally jacked up
Using the top two methods of nsIHandlerService
and nsiExternalProtocolService
, if you go to the options panel and change to alwaysAsk the alwaysAskBeforeHandling
property in the log handlerInfo
s will reflect properly. However if you get handlerInfo
with this method, nsIMIMEService
, then it doesnt accurately reflect the drop down setting from alwaysAskBeforeHandling
its so weird:
It also has possibleApplicationHandlers
which is length of 0
. Odd. It also has possibleLocalHandlers
which has a length of 53
in my case, interesting.
var mimeService = Cc['@mozilla.org/mime;1'].getService(Ci.nsIMIMEService);
var CONTENT_TYPE = 'mailto';
var TYPE_EXTENSION = '';
var handlerInfo = mimeService.getFromTypeAndExtension(CONTENT_TYPE, TYPE_EXTENSION);
console.info('mimeServiceHandlerInfo:', handlerInfo); //http://i.imgur.com/dUKox24.png
This mimeServiceHandlerInfo
also has different object keys from the handlerInfo
returned by the top two methods of EPS and HandlerService.
Using handlerInfo
from any of the three methods above (well I haven't yet tested nsiMIMService
's handlerInfo
but I'm guessing it should work)
This way does not list the "Microsoft Outlook", it only lists the gmail, ymail and things i added, weird
var handlers = handlerInfo.possibleApplicationHandlers;
console.log('handlers', handlers)
for (var i = 0; i < handlers.length; ++i) {
var handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp); //instead of Ci.nsIHandlerApp
console.log('poss handler', i, handler, handler.uriTemplate);
}
I don't think this way lists the "Microsoft Outlook" either but I'm not sure as it's only logging small handler
objects.
This way only returns/logs small object ( I fixed this problem by adding in handler
) for the first non system default handler (i think thats what it is, but it definitely only returns for one). for which it returns the name etc.QueryInterface(Ci.nsIHandlerApp)
var handlers = handlerInfo.possibleApplicationHandlers.enumerate();
while (handlers.hasMoreElements()) {
var handler = handlers.getNext().QueryInterface(Ci.nsIWebHandlerApp); //instead of Ci.nsIHandlerApp
console.log('handler', handler);
}
-
It was QI'ing
Ci.nsIHandlerApp
which would not haveuriTemplate
in thehandler
object, so I changed it toCi.nsIWebHandlerApp
, this retuns in hte objecturiTemplate
. -
Can QI
handler
s inpossibleApplicationHandlers
withCi.nsIHandlerApp
BUT CANNOT QIhandler
s inpossibleLocalHandlers
withCi.nsIWebHandlerApp
it will throw the following exception:Exception: Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsISupports.QueryInterface]
registerProtocolHandler
shows all the checks to make when adding a handler, and it shows how to add it. MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #L368 - registerProtocolHandler
This snippet shows how to add a nsIWebAppHandler
. I'm not sure how to add a nsILocalAppHandler
(im not sure if it's even called nsILocalAppHandler
maybe its just (actually probably is) nsIAppHandler
). No validation checks are made before adding it here. You should do the following checks before adding:
- Check if the handler we're adding already exists as possible handler MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #349 - _protocolHandlerRegistered
- Curious note here: This only checks
possibleApplicationHandlers
it doesn't dopossibleLocalHandlers
, i'm not sure why, but probably because we are dealing with ansIWebAppHandler
- Check to make sure the protocol we are adding handler to isn't already handled internally (we don't want to let them take over, say "chrome"). MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #390
- Check if the protocol we are adding handler to is in the black list. If it's in the blacklist it means it does not want other handlers added to it. I'm not sure how important this is but
registerProtocolHandler
does it. MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #402
So finally here is the code on how to add a handler without doing any of the three checks above.
var protocol = 'mailto';
var name = 'Hotmail Mailto Handler';
var newURIArgs = {
aURL: 'http://mail.live.com/secure/start?action=compose&to=%s',
aOriginCharset: null,
aBaseURI: null
};
var myURI = Services.io.newURI(newURIArgs.aURL, newURIArgs.aOriginCharset, newURIArgs.aBaseURI);
var myURISpec = myURI.spec;
var handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance(Ci.nsIWebHandlerApp);
handler.name = name;
handler.uriTemplate = myURISpec;
var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
var handlerInfo = eps.getProtocolHandlerInfo(protocol);
handlerInfo.possibleApplicationHandlers.appendElement(handler, false);
if (handlerInfo.possibleApplicationHandlers.length > 1) {
// May want to always ask user before handling because it now has multiple possibleApplicationsHandlers BUT dont have to
//handlerInfo.alwaysAskBeforeHandling = true;
}
var hs = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
hs.store(handlerInfo);
First get the handlerInfo
object for the protocol by using Get the handlerInfo
object - nsIHandlerService
- Method or Get the handlerInfo
object - nsiExternalProtocolService
Method.
- Then first check if
handlerInfo.alwaysAskBeforeHandling
istrue
. If this is the case than the active handler is "Always Ask". If this is the case thanhandlerInfo.preferredApplicationHandler
andhandlerInfo.preferredAction
are stale. By stale I mean that they are not true, they are set to whatever it was set at before. handlerInfo.alwaysAskBeforeHandling
isfalse
then checkhandlerInfo.preferredAction
.
- If
handlerInfo.preferredAction == Ci.nsIHandlerInfo.useSystemDefault
than thehandler.preferredApplicaitonHandler
is stale in that it is whatever it was set to last time. So the active handler is whatever theuserSystemDefault
one is. (at the time of this writing August 3rd, 2014 - I'm not sure how to figure out the system default handler for a protocol) - If
handlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp
than default handler is whatever is held inhandlerInfo.preferredApplicationHandler
. In this casehandler.preferredApplicaitonHandler
should not benull
. In all other caseshandler.preferredApplicaitonHandler
has the potential to benull
. - If
handlerInfo.preferredAction == Ci.nsIHandlerInfo.saveToDisk
than default handler is to download it - If
handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally
than default handler is I don't know as of writing of this (August 3rd, 2014)
//start - demo make handler for mailto be y! mail
var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
var handlerInfo = eps.getProtocolHandlerInfo('mailto');
console.log('epsHandlerInfo', handlerInfo)
var handlers = handlerInfo.possibleApplicationHandlers.enumerate();
var foundYahooMailHandler = false;
while (handlers.hasMoreElements()) {
var handler = handlers.getNext();
if (handler.QueryInterface(Ci.nsIWebHandlerApp).uriTemplate == 'https://compose.mail.yahoo.com/?To=%s') { //this is how i decided to indentify if the handler is of yahoo mail
foundYahooMailHandler = true;
break;
}
}
if (foundYahooMailHandler) {
//it was found. and in the while loop when i found it, i "break"ed out of the loop which left handlerInfo set at the yahoo mail handler
//set this to the prefered handler as this handler is the y! mail handler
handlerInfo.preferredAction = Ci.nsIHandlerInfo.useHelperApp; //Ci.nsIHandlerInfo has keys: alwaysAsk:1, handleInternally:3, saveToDisk:0, useHelperApp:2, useSystemDefault:4
handlerInfo.preferredApplicationHandler = handler;
handlerInfo.alwaysAskBeforeHandling = false;
var hs = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
hs.store(handlerInfo);
} else {
alert('could not find yahoo mail handler. meaning i couldnt find a handler with uriTemplate of ...compose.mail.yahoo....')
}
//end - demo make handler for mailto be y! mail
var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
var handlerInfo = eps.getProtocolHandlerInfo('mailto');
console.log('epsHandlerInfo', handlerInfo)
console.log('handlerInfo.preferredApplicationHandler', handlerInfo.preferredApplicationHandler);
console.log('handlerInfo.possibleApplicationHandlers', handlerInfo.possibleApplicationHandlers);
var handlers = handlerInfo.possibleApplicationHandlers;
console.log('handlers', handlers)
for (var i = 0; i < handlers.length; ++i) {
var handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp);
console.log('handler', i, handler, handler.uriTemplate);
if (Services.wm.getMostRecentWindow(null).confirm('delete handler at position ' + i + '? its uriTemplate = "' + handler.uriTemplate + '" and name = "' + handler.name + '"')) {
if (handler.equals(handlerInfo.preferredApplicationHandler)) {
Services.wm.getMostRecentWindow(null).alert('the preferredApplicationHandler was the one we are removing now, so null the preferredAppHand and set to always ask');
//if the last preferredApplicationHandler was this then nullify it, just me trying to keep things not stale
handlerInfo.preferredApplicationHandler = null;
if (handlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp) {
//it looks like the preferredAction was to use this helper app, so now that its no longer there we will have to ask what the user wants to do next time the uesrs clicks a mailto: link
handlerInfo.alwaysAskBeforeHandling = true;
handlerInfo.preferredAction = Ci.nsIHandlerInfo.alwaysAsk; //this doesnt really do anything but its just nice to be not stale. it doesnt do anything because firefox checks handlerInfo.alwaysAskBeforeHandling to decide if it should ask. so me doing this is just formality to be looking nice
}
}
handlers.removeElementAt(i);
i--;
}
var hs = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
hs.store(handlerInfo);
}
quick snipets i use:
list all handlers and their infos for mailto: