列出协议和内容类型处理程序

时间:2015-01-25 06:32:01

标签: javascript firefox-addon

是否有用于列出所有协议处理程序和内容类型处理程序的XPCOM接口?

我看到mimeTypes.rdf中提供了这些信息,虽然我看到了用于获取特定已知处理程序信息的接口,但我找不到任何列出所有这些信息的XPCOM接口。

1 个答案:

答案 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方法 注意:有一些主要的怪癖,比如没有准确地重新选择preferedHandleralwaysAskBeforeHandling(我刚刚注意到这两个到目前为止我没有探索其他属性,但它们可能同样被抬高

使用nsIHandlerServicensiExternalProtocolService的前两种方法,如果您转到选项面板并更改为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 queryElementAtCi.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)。在此处添加之前不会进行验证检查。在添加之前,您应该执行以下检查:

  1. 检查我们添加的处理程序是否已作为可能的处理程序MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #349 - _protocolHandlerRegistered存在
    • 这里有一个好奇的注意事项:这只检查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
  2. 检查以确保我们正在添加处理程序的协议尚未在内部处理(我们不想让它们接管,比如“chrome”)。 MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #390
  3. 检查我们添加处理程序的协议是否在黑名单中。如果它在黑名单中,则意味着它不希望添加其他处理程序。我不确定这有多重要,但nsIHandlerService做到了。 MXR :: mozilla-release/ mozilla/ browser/ components/ feeds/ src/ WebContentConverter.js #402
  4. 所以最后这里是关于如何在不进行上述三项检查的情况下添加处理程序的代码。

    handlerInfo

    如何获取协议的当前设置处理程序

    首先使用获取nsiExternalProtocolService对象 - handlerInfo.alwaysAskBeforeHandling - 方法或获取true对象 - handlerInfo.preferredApplicationHandler方法获取协议的handlerInfo.preferredAction对象。

    1. 然后首先检查handlerInfo.alwaysAskBeforeHandling是否为false。如果是这种情况,则活动处理程序为“始终询问”。如果是这种情况,则handlerInfo.preferredActionhandlerInfo.preferredAction == Ci.nsIHandlerInfo.useSystemDefault陈旧。通过陈旧我的意思是他们不是真的,他们被设置为以前设置的任何东西。
    2. handler.preferredApplicaitonHandleruserSystemDefault,然后检查handlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp
      • 如果handlerInfo.preferredApplicationHandlerhandler.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}}比默认处理程序是我不知道截至撰写时(2014年8月3日)
    3. 演示/示例 - 将mailto处理程序设置为“Yahoo! Mail”

      {{1}}

      演示/如何删除处理程序

      的示例
      {{1}}