本文介绍了nsIProtocol示例不明确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在比较MDN上的这个例子:



如何创建自定义协议的附加组件:
p>

有人可以请详细说明它正在尝试做什么。 SMTP的东西把我扔了。

我无法理解MDN上的这个例子是怎么做的,它在没有chrome.manifst的情况下做什么。我知道这个附加组件正在创建fosdem:// blah,其中blah就是我想要的基于 WhereToGo 中的定义,但是它使用了一个chrome.manifest。 p>

我正在考虑mdn的例子和addon做的是一样的事情,我会这样做来设置我的自定义协议后复制粘贴该mdn代码:


$ b $ pre $ function myCustomBlah(){}
$ b myCustomBlah.prototype =
makeProtocolHandler(mycustomblah,
-1,
b14c2b67-8680-4c11-8d63-9403c7d4f757); //我可以生成任何id

var components = [myCustomBlah];
const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);


解决方案

Alrighty让我们给出一个更明智的自定义协议处理程序。

我决定实现一个 ddg:协议处理程序,一旦注册就可以用来输入 ddg:一些搜索字词到地址栏中(除此之外),它将加载DuckDuckGo搜索页面以查找某些搜索字词。



组件



需要实现界面。这个示例组件所做的是重定向到DuckDuckGo(好吧,不是真正的重定向,但是它为duckduckgo.com返回一个频道)。

$ $ p $ code $ var b $ c
$ c
code $ $
结果:Cr,
构造函数:CC
} =组件;
Cm.QueryInterface(Ci.nsIComponentRegistrar);

Components.utils.import(resource://gre/modules/Services.jsm);
Components.utils.import(resource://gre/modules/XPCOMUtils.jsm);

const SCHEME =ddg;
const DDG_URI = Services.io.newURI(https://duckduckgo.com/?q=%s,null,null);

const nsIURI = CC(@ mozilla.org/network/simple-uri; 1,nsIURI);

函数DuckDuckGoProtocolHandler(){}
DuckDuckGoProtocolHandler.prototype = Object.freeze({
classDescription:DuckDuckGo Protocol Handler,
contractID:@ mozilla.org / network / protocol; 1?name =+ SCHEME,
classID:Components.ID('{858ea860-129a-11e4-9191-0800200c9a66}'),
QueryInterface:XPCOMUtils.generateQI([Ci .nsIProtocolHandler]),

// nsIProtocolHandler
scheme:SCHEME,
defaultPort:-1,//无默认端口

// nsIProtocolHandler
allowPort:函数(端口,方案){
//此协议处理程序不支持端口
返回false;
},

// nsIProtocolHandler
//我们的协议处理程序不支持认证,
//但是可以从任何web页面加载,而不仅仅是特权页面
protocolFlags:Ci.nsIProtocolHandler。 URI_NOAUTH |
Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,

// nsIProtocolHandler
newURI:函数(aSpec,aOriginCharset,aBaseURI){
//这里没什么特别的,实际上。我们被要求创建一个新的URI。

//如果有一个base-URI,这意味着浏览器试图解析
//一个依赖资源(一个图像,脚本),或者用户点击一个相对链接。
//在这种情况下,我们不能真正返回另一个ddgURI,但是需要返回
//正确的https URI。
if(aBaseURI& aBaseURI.scheme == SCHEME){
return Services.io.newURI(aSpec,aOriginCharset,DDG_URI);
}

//我们不关心字符集,所以忽略
//(我们支持nsIURI支持的)。
让rv = new nsIURI();
rv.spec = aSpec;
return rv;
},

// nsIProtocolHandler
newChannel:function(aURI){
//我们被要求打开一个新频道。
//我们可以实现一个完全自定义的通道,支持
//(大部分)nsIChannel。但是这是一个巨大的工作,并且在这个基本例子的范围之外(这是关于协议处理程序和
//不是通道)的
//。
//或者我们可以返回任何其他我们可以创建的频道。
//由于我们要实现ddg:协议,只需要打开一个
//常规https频道到duckduckgo.com,使用URI作为搜索项
/ /并返回该频道。
let spec = DDG_URI.spec.replace(%s,aURI.path);
let channel = Services.io.newChannel(spec,aURI.originCharset,null);

//设置.originalURI不仅会让其他代码知道这个
//最初来自哪里,而且UI实际上会显示.originalURI。
channel.originalURI = aURI;

返回通道;
}
});



chrome.manifest中的组件注册



如果我们的组件是通过chrome.manifest注册的JavaScript组件
,我们需要实现 NSGetFactory 。幸运的是, XPCOMUtils.jsm 有一个帮助器。

  var NSGetFactory = 
XPCOMUtils.generateNSGetFactory([DuckDuckGoProtocolHandler]);



在自举加载项(和Scratchpad)中注册



在引导/重新启动的附加组件(包括SDK附加组件)和便签本中,需要手动注册组件,因为 chrome.manifest 注册是不可用。

可以注册 NSGetFactory(classID)的结果,但是这里有一些代码创建了一个Factory手动和注册它。

$ p $ 函数工厂(组件){
this.createInstance = function(outer,iid){
if(outer){
throw Cr.NS_ERROR_NO_AGGREGATION;

return new component();
};
this.register = function(){
Cm.registerFactory(component.prototype.classID,
component.prototype.classDescription,
component.prototype.contractID,
这个);
};
this.unregister = function(){
Cm.unregisterFactory(component.prototype.classID,this);
}
Object.freeze(this);
this.register();
}
var factory = new Factory(DuckDuckGoProtocolHandler);

请注意,在无重启加载项中,您还需要再次注销
关闭!

  factory.unregister(); 



在便签本中测试



组件代码和手动注册代码放入暂存器,将环境设置为浏览器并运行。然后在一个标签中打开 ddg:一些搜索条件;)
$ b

I was comparing this example on MDN:https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIProtocolHandler#Implementation

To this add-on on how to create custom protocol:https://addons.mozilla.org/en-US/firefox/files/browse/141969/file/components/AboutFosdem.js#top

Can someone please detail what exactly it's trying to do. The SMTP stuff threw me off.

I couldn't understand what that example on MDN is doing, its doing it whatever its doing without a chrome.manifst. I know the add-on is creating "fosdem://blah" where blah is whatever I want based on the definitions in WhereToGo but it uses a chrome.manifest.

I'm thinking that the mdn example is doing same thing as addon and I would do something like this to set my custom protocol after copy pasting that mdn code:

function myCustomBlah() {}

myCustomBlah.prototype =
  makeProtocolHandler("mycustomblah",
                      -1,
                      "b14c2b67-8680-4c11-8d63-9403c7d4f757"); //i can generate any id

var components = [myCustomBlah];
const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
解决方案

Alrighty lets give a more sensible example of a custom protocol handler.

I decided to implement a ddg: protocol handler, that once registered can be used to type ddg:some search terms into the address bar (among other things) and it will load the DuckDuckGo search page for "some search terms".

The component

One needs to implement the nsIProtocolHandler interface.

What this example component does is "redirect" to DuckDuckGo (well, not really redirect, but it returns a channel for duckduckgo.com). See comments inline.

var {classes: Cc,
     interfaces: Ci,
     manager: Cm,
     results: Cr,
     Constructor: CC
    } = Components;
Cm.QueryInterface(Ci.nsIComponentRegistrar);

Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

const SCHEME = "ddg";
const DDG_URI = Services.io.newURI("https://duckduckgo.com/?q=%s", null, null);

const nsIURI = CC("@mozilla.org/network/simple-uri;1", "nsIURI");

function DuckDuckGoProtocolHandler() {}
DuckDuckGoProtocolHandler.prototype = Object.freeze({
  classDescription: "DuckDuckGo Protocol Handler",
  contractID: "@mozilla.org/network/protocol;1?name=" + SCHEME,
  classID: Components.ID('{858ea860-129a-11e4-9191-0800200c9a66}'),
  QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),

  // nsIProtocolHandler
  scheme: SCHEME,
  defaultPort: -1, // No default port.

  // nsIProtocolHandler
  allowPort: function(port, scheme) {
    // This protocol handler does not support ports.
    return false;
  },

  // nsIProtocolHandler
  // Our protocol handler does not support authentication,
  // but it is OK to be loaded from any web-page, not just privileged pages""
  protocolFlags: Ci.nsIProtocolHandler.URI_NOAUTH |
                 Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,

  // nsIProtocolHandler
  newURI: function(aSpec, aOriginCharset, aBaseURI) {
    // Nothing special here, actually. We were asked to create a new URI.

    // If there is a base-URI, this means that the browser tries to resolve
    // a dependent resource (an image, script) or the user clicked on a relative link.
    // In this case we cannot really return another "ddg" URI, but need to return
    // the proper https URI.
    if (aBaseURI && aBaseURI.scheme == SCHEME) {
      return Services.io.newURI(aSpec, aOriginCharset, DDG_URI);
    }

    // We don't care about the charset, so just ignore that
    // (we support what nsIURI supports).
    let rv = new nsIURI();
    rv.spec = aSpec;
    return rv;
  },

  // nsIProtocolHandler
  newChannel: function(aURI) {
    // We were asked to open a new channel.
    // We could implement an entirely custom channel that supports
    // (most of) nsIChannel. But that is tremendous work and outside
    // of the scope of this basic example (which is about protocol handlers and
    // not channels).
    // Or we can just return any other channel we can create.
    // Since we're going to implement the "ddg:" protocol, lets just open a
    // regular https channel to duckduckgo.com, use the URI as the search term
    // and return that channel.
    let spec = DDG_URI.spec.replace("%s", aURI.path);
    let channel = Services.io.newChannel(spec, aURI.originCharset, null);

    // Setting .originalURI will not only let other code know where this
    // originally came from, but the UI will actually show that .originalURI.
    channel.originalURI = aURI;

    return channel;
  }
});

Component registration in chrome.manifest

We need to implement NSGetFactory if our component is a JavaScript componentregistered via chrome.manifest. Luckily, XPCOMUtils.jsm has a helper for that.

var NSGetFactory =
  XPCOMUtils.generateNSGetFactory([DuckDuckGoProtocolHandler]);

Registration in bootstrapped add-ons (and Scratchpad)

In bootstrapped/restartless add-ons (incl. SDK add-ons) and Scratchpad, one will need to register the component manually, as chrome.manifest registration is not available.

One could register the result of NSGetFactory(classID), but here is some code creating a Factory manually and registering it.

function Factory(component) {
  this.createInstance = function(outer, iid) {
    if (outer) {
      throw Cr.NS_ERROR_NO_AGGREGATION;
    }
    return new component();
  };
  this.register = function() {
    Cm.registerFactory(component.prototype.classID,
                       component.prototype.classDescription,
                       component.prototype.contractID,
                       this);
  };
  this.unregister = function() {
    Cm.unregisterFactory(component.prototype.classID, this);
  }
    Object.freeze(this);
  this.register();
}
var factory = new Factory(DuckDuckGoProtocolHandler);

Please note that in restartless add-ons you'll also need to unregister itagain on shutdown!

factory.unregister();

Testing in a Scratchpad

Copy the component code and the manual registration code into a scratchpad, set the Enviroment to Browser, and run it. Then open ddg:some search terms in a tab ;)

这篇关于nsIProtocol示例不明确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 14:23