Firefox nsIProtocolHandler和nsIURI:自创协议中的相对URL

Firefox nsIProtocolHandler和nsIURI:自创协议中的相对URL,firefox,firefox-addon,xpcom,Firefox,Firefox Addon,Xpcom,我有一个自定义协议的简单实现。据说newURI方法接受3个参数(spec、charset和baseURI),并且“如果协议没有相对uri的概念,则忽略第三个参数” 所以我打开一个这样的页面tada://domain/samplepage 其中包含以以下内容开头的XML: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE Product SYSTEM "product.dtd"> 从newChannel返回的频道具有传递给n

我有一个自定义协议的简单实现。据说newURI方法接受3个参数(spec、charset和baseURI),并且“如果协议没有相对uri的概念,则忽略第三个参数”

所以我打开一个这样的页面tada://domain/samplepage 其中包含以以下内容开头的XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Product SYSTEM "product.dtd">

从newChannel返回的频道具有传递给
newChannelFromURI
chrome://
URI作为其URI。这就是页面的URI,作为它的URI,作为它的基本URI。因此,DTD负载发生在“chrome://my-extension/content/about/product.dtd“直接


您可能想做的是将aURI设置为您从newChannel返回的频道上的originalURI。

正如Boris在回答中提到的那样,您的协议实现没有设置
nsIChannel.originalURI
属性,因此URL将相对于
chrome:
URL解析,而不是相对于
tada:
URL解析。但是,您的代码还有第二个问题:在Firefox中,加载外部DTD仅适用于
chrome:
URL,此检查是硬编码的。映射到本地文件(各种HTML文档类型)的受支持DTD数量有限,但仅此而已-Gecko不支持
中的随机URL。您可以在中看到当前逻辑。相关的bug是无法修复的。

Boris和Wladimir,谢谢

过了一段时间,我有了一个解决办法。问题是无法从自定义创建的协议加载DTD文件。其思想是使用代理API重写schemeIs()方法,该方法在nsIProtocolHandler的newURI方法中调用

现在我在newURI方法中有了这段代码:

let standardUrl = Cc["@mozilla.org/network/standard-url;1"].createInstance(Ci.nsIStandardURL);
standardUrl.init(standardUrl.URLTYPE_STANDARD, -1, spec, charset, baseURI);
standardUrl.QueryInterface(Ci.nsIURL);

return Proxy.create(proxyHandlerMaker(standardUrl));
只需实现代理API并重写所需的schemeIs()方法。这就解决了问题,现在所有的请求都来到了newChannel,我们可以在那里处理它们


重要提示:

  • 对DTD的请求到达newURI()方法,而不到达newChannel()。这是默认行为。这是因为对newURI()方法返回的对象调用了schemeIs(“chrome”)方法。如果希望DTD请求到达newChannel()方法,则此方法应为DTD请求返回“true”
  • newChannel()方法由{nsIURI}对象调用,该对象与newURI方法返回的对象不同
  • 如果要同时处理协议:第页&protocol://domain/pageURL根据您的协议,您应该同时使用{nsIURI}和{nsisStandardUrl}对象
  • 您可以将创建的{nsisStandardUrl}-对象(上面代码段中的standardUrl)作为第二个参数传递给Proxy.create()函数。这将使您的baseURI(newURI中的第三个参数)通过“nsIStandardUrl的baseURI实例”检查。对于DTD文件请求,此代理对象的SchemeIs()方法也将返回true。但不幸的是,请求无法到达newChannel()方法。这可能是一个很好的DTD问题解决方案,但我无法解决这个问题

  • 嗯。。。这是什么?我在中找不到此属性
    let standardUrl = Cc["@mozilla.org/network/standard-url;1"].createInstance(Ci.nsIStandardURL);
    standardUrl.init(standardUrl.URLTYPE_STANDARD, -1, spec, charset, baseURI);
    standardUrl.QueryInterface(Ci.nsIURL);
    
    return Proxy.create(proxyHandlerMaker(standardUrl));