2012-02-14 6 views
1

私はカスタムプロトコルを簡単に実装しています。 newURIメソッドは3つの引数(spec、charset & baseURI)とをとります。 "プロトコルに相対URIの概念がない場合、3番目のパラメータは無視されます"nsIProtocolHandlerとnsIURI:自己作成プロトコルの相対URL

だから私はこの多田のようにページを開く:newURIがある(

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

しかし、私は自分のプロトコルにproduct.dtdに関するすべての要求が表示されない:XMLは、この始まるました//ドメイン/ samplepage呼び出されることさえありません)。私は私の実装で一味違いますか? BTW:ページ自体は正しく開きますが、DTDファイルへのリクエストはありません。

const 
    Cc = Components.classes, 
    Ci = Components.interfaces, 
    Cr = Components.results, 
    Cu = Components.utils, 
    nsIProtocolHandler = Ci.nsIProtocolHandler; 

Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 

function TadaProtocol() { 
} 

TadaProtocol.prototype = { 
    scheme: "tada", 
    protocolFlags: nsIProtocolHandler.URI_DANGEROUS_TO_LOAD, 

    newURI: function(aSpec, aOriginCharset, aBaseURI) { 
     let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI); 
     uri.spec = (aBaseURI === null) 
      ? aSpec 
      : aBaseURI.resolve(aSpec); 

     return uri; 
    }, 

    newChannel: function(aURI) { 
     let 
      ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService), 
      uri = ioService.newURI("chrome://my-extension/content/about/product.xml", null, null); 

     return ioService.newChannelFromURI(uri); 
    }, 

    classDescription: "Sample Protocol Handler", 
    contractID: "@mozilla.org/network/protocol;1?name=tada", 
    classID: Components.ID('{1BC90DA3-5450-4FAF-B6FF-F110BB73A5EB}'), 
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]) 
} 

let NSGetFactory = XPCOMUtils.generateNSGetFactory([TadaProtocol]); 

答えて

1

ボリスとウラジミール、ありがとう!

しばらくすると解決策があります。問題は、カスタム作成のプロトコルからDTDファイルをロードできなかったことです。アイデアは、Proxy APIを使用して、nSIProtocolHandlerのnewURIメソッドで呼び出されたschemeIs()メソッドをオーバーライドすることでした。

だから今、私は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)); 

proxyHandlerMakerだけでプロキシAPIを実装し、必要に応じschemeIs()メソッドをオーバーライドします。これで問題は解決し、すべてのリクエストはnewChannelに送られ、そこで処理できます。


重要事項:DTDへ

  1. 要求)(newURI()メソッドに来て、newChannelに来ていません。これがデフォルト動作です。これは、newURI()メソッドによって返されたオブジェクトに対してschemeIs( "chrome")メソッドが呼び出されるために発生します。要求がnewChannel()メソッドに到達するようにするには、このメソッドはDTD要求に対して「true」を返す必要があります。
  2. newURIメソッドで返されたオブジェクトと同じではないではない{nsIURI}オブジェクトでnewChannel()メソッドが呼び出されます。
  3. あなたはプロトコルの両方扱うようにしたい場合は、次のページ&プロトコル://ドメイン/ページあなたのプロトコルで URLを、あなたは両方の{たnsIURI}と{nsIStandardURL}オブジェクト
  4. を使用する必要がありますあなたは{作成を渡すことができますnsIStandardUrl} -object(上記のスニペットのstandardUrl)をProxy.create()関数の2番目の引数として使用します。これにより、baseURI(newURIの3番目の引数)が "baseURI instanceof nsIStandardUrl"に渡されます。このプロキシされたオブジェクトのSchemeIs()メソッドは、DTDファイル要求に対してもtrueを返します。しかし残念ながらリクエストはnewChannel()メソッドには届きません。これは素晴らしいDTD問題の解決策かもしれませんが、私はこの問題を解決できません。
1

あなたはnewChannelから戻るチャネルを使用すると、そのURIとしてnewChannelFromURIに渡さchrome:// URIを持っています。これは、ページがURIとして持つURIであり、そのベースURIです。したがって、DTDの読み込みは「chrome://my-extension/content/about/product.dtd」から直接行われます。

あなたがしたいことは、newChannelから返すチャンネルのオリジナルURIとしてaURIを設定することです。

+0

Ehh ...これはなんですか? [MDN docs](https://developer.mozilla.org/en/nsIProtocolHandler)でこの属性が見つかりません –

+0

https://developer.mozilla.org/en/nsIChannelを見たいと思っています –

1

Borisが答えたとおり、プロトコルの実装でnsIChannel.originalURIプロパティが設定されていないため、URLはのURLではなく、chrome:のURLを基準に解決されます。ただし、Firefoxで外部DTDをロードすると、chrome:のURLでしか機能しません。このチェックはハードコードされています。限られた数のサポートされているDTDがローカルファイル(さまざまなHTMLのdoctype)にマップされていますが、それだけです.GeckoはランダムURLを<!DOCTYPE>でサポートしていません。現在のロジックはsource codeにあります。関連するバグは修正されないbug 22942です。

関連する問題