是否有用于列出所有协议处理程序和内容类型处理程序的XPCOM接口?
我看到mimeTypes.rdf中提供了这些信息,虽然我看到了用于获取特定已知处理程序信息的接口,但我找不到任何列出所有这些信息的XPCOM接口。
答案 0 :(得分:3)
Hey Brett这是我在使用MailtoWebmails时写的东西,请分享你学到的东西,怪癖等等:
GitHubGIST :: Noitidart / _ff-addon-tutorial-CheckGetSetRemoveAddHandlerOfProtocol.md
handlerInfo
对象nsIHandlerService
方法
此处返回的handlerInfo
对象与上述nsiExternalProtocolService
方法完全相同。
如果您转到选项面板并更改为alwaysAsk,则日志alwaysAskBeforeHandling
中的handlerInfo
属性将正确反映。
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
possibleLocalHandlers
中没有handlerInfo
。
nsiExternalProtocolService
方法
此处返回的handlerInfo
对象与上述nsIHandlerService
方法完全相同。
如果您转到选项面板并更改为alwaysAsk,则日志alwaysAskBeforeHandling
中的handlerInfo
属性将正确反映。
var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
var handlerInfo = eps.getProtocolHandlerInfo('mailto');
console.log('epsHandlerInfo', handlerInfo)
possibleLocalHandlers
中没有handlerInfo
。
nsIMIMEService
方法
注意:有一些主要的怪癖,比如没有准确地重新选择preferedHandler
和alwaysAskBeforeHandling
(我刚刚注意到这两个到目前为止我没有探索其他属性,但它们可能同样被抬高
使用nsIHandlerService
和nsiExternalProtocolService
的前两种方法,如果您转到选项面板并更改为alwaysAsk,则日志alwaysAskBeforeHandling
中的handlerInfo
属性将反映出来正常。但是,如果您使用此方法获得handlerInfo
nsIMIMEService
,那么它并不能准确反映alwaysAskBeforeHandling
的下拉设置,这非常奇怪:
它还有possibleApplicationHandlers
,其长度为0
。奇。它也有possibleLocalHandlers
,在我的情况下长度为53
,很有趣。
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
此mimeServiceHandlerInfo
也有与EPS和HandlerService的前两种方法返回的handlerInfo
不同的对象键。
使用上述三种方法中的handlerInfo
(我还没有测试nsiMIMService
的{{1}},但我猜它应该有效)
handlerInfo
方法
这种方式没有列出“Microsoft Outlook”,它只列出了我添加的gmail,ymail和东西,很奇怪
queryElementAt
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);
}
方法
我不认为这种方式列出了“Microsoft Outlook”,但我不确定它只记录小enumerate
个对象。
这种方式只返回/记录第一个非系统默认处理程序的小对象(我通过添加handler
)(我认为它是什么,但它肯定只返回一个)。为此返回名称等handler
.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);
}
和enumerate
的说明
QI'ing queryElementAt
在Ci.nsIHandlerApp
对象中没有uriTemplate
,因此我将其更改为handler
,这会在hte对象中返回Ci.nsIWebHandlerApp
。
QI uriTemplate
handler
possibleApplicationHandlers
Ci.nsIHandlerApp
handler
possibleLocalHandlers
Ci.nsIWebHandlerApp
registerProtocolHandler
nsIWebAppHandler
nsILocalAppHandler
nsILocalAppHandler
以下例外:
异常:组件返回失败代码:0x80004002(NS_NOINTERFACE)[nsISupports.QueryInterface]
nsIAppHandler
显示添加处理程序时要进行的所有检查,并显示如何添加它。 MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #L368 - registerProtocolHandler
此代码段显示了如何添加possibleApplicationHandlers
。我不确定如何添加possibleLocalHandlers
(我不确定它是否甚至称为nsIWebAppHandler
也许它只是(实际上可能是)registerProtocolHandler
)。在此处添加之前不会进行验证检查。在添加之前,您应该执行以下检查:
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);
它没有handlerInfo
,我不知道为什么,但可能是因为我们正在处理handlerInfo
nsIHandlerService
做到了。 MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #402 所以最后这里是关于如何在不进行上述三项检查的情况下添加处理程序的代码。
handlerInfo
首先使用获取nsiExternalProtocolService
对象 - handlerInfo.alwaysAskBeforeHandling
- 方法或获取true
对象 - handlerInfo.preferredApplicationHandler
方法获取协议的handlerInfo.preferredAction
对象。
handlerInfo.alwaysAskBeforeHandling
是否为false
。如果是这种情况,则活动处理程序为“始终询问”。如果是这种情况,则handlerInfo.preferredAction
和handlerInfo.preferredAction == Ci.nsIHandlerInfo.useSystemDefault
陈旧。通过陈旧我的意思是他们不是真的,他们被设置为以前设置的任何东西。handler.preferredApplicaitonHandler
为userSystemDefault
,然后检查handlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp
。
handlerInfo.preferredApplicationHandler
比handler.preferredApplicaitonHandler
陈旧,那就是它是上次设置的任何内容。所以主动处理程序就是null
那个。 (在撰写本文时,2014年8月3日 - 我不知道如何找出协议的系统默认处理程序)handler.preferredApplicaitonHandler
比默认处理程序null
中保留的是handlerInfo.preferredAction == Ci.nsIHandlerInfo.saveToDisk
。在这种情况下,handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally
不应该是//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);
}
可能会{{1}}。{{1}}
{{1}}