43

私はこれを長い間試みてきましたが、良い結果はありません。

var myObserver = {
    observe: function(subject, topic, data)
    {
        if (topic == "http-on-examine-response") 
        {   
             //  implement later
        } 
        else if(topic == "http-on-modify-request") 
        {
             //  implement later
        }
   },

   QueryInterface : function (id)
   {
       if (id.equals(Components.interfaces["nsIObserver"]) ||
           id.equals(Components.interfaces["nsISupports"]))
       {
           return this;
       }
       throw Components.results.NS_NOINTERFACE;
   }
};

var obs = new Service("observer-service", "ObserverService");
obs.addObserver(myObserver, "http-on-modify-request", false);

基本的にhttp-on-modify-request、私は URI を調べる方法、関連付けられているウィンドウ (存在する場合) を特定する方法、およびその他の多くのことを知っています。私が理解できないのは、リクエストが送信される前に nsIHttpChannel を取得できるため、ここから可能であることを知っているリクエストをリダイレクトする方法です。

誰が何をすべきか知っていますか?:/ 私は数週間オンとオフを試みてきましたが、どこにも行きませんでした.

4

4 に答える 4

3

を新しいものでオーバーライドすることでこれを行うことができます。これを行うのnsiHttpChannelは少し複雑ですが、幸いなことに、アドオンはhttps-everywhereこれを実装して https 接続を強制します。

https-everywhereのソースコードはこちらから入手できます

これに必要なコードのほとんどはファイルにあります

[ IO Util.js] [ ChannelReplacement.js]

Cc、Ci などの基本的な変数が設定され、関数がxpcom_generateQI定義されていれば、上記のファイルだけで作業できます。

var httpRequestObserver =
{ 
  observe: function(subject, topic, data) {
    if (topic == "http-on-modify-request") {

        var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);     
        var requestURL = subject.URI.spec;

        if(isToBeReplaced(requestURL))  {

            var newURL = getURL(requestURL);        
             ChannelReplacement.runWhenPending(subject, function() {
                    var cr = new ChannelReplacement(subject, ch);
                    cr.replace(true,null);
                    cr.open();
                });
        }
    }

  },

  get observerService() {
    return Components.classes["@mozilla.org/observer-service;1"]
                     .getService(Components.interfaces.nsIObserverService);
  },

  register: function() {
    this.observerService.addObserver(this, "http-on-modify-request", false);

  },

  unregister: function() {
    this.observerService.removeObserver(this, "http-on-modify-request");

  }
};


httpRequestObserver.register();

コードは、リダイレクトではなくリクエストを置き換えます。

上記のコードを十分にテストしましたが、その実装については確信が持てません。私が理解できる限り、要求されたチャネルのすべての属性をコピーし、それらをオーバーライドするチャネルに設定します。その後、元のリクエストによってリクエストされた出力が、新しいチャネルを使用して何らかの形で提供されます。

PS私は、このアプローチが提案されたSOの投稿を見たことがあります。

于 2012-09-26T12:43:23.910 に答える
1

このレベルではこれを行うことはできないという印象を受けています - nsIHttpChannel の作成を要求するコードを外部から「だます」さまざまな方法を試しました (例は投稿の最後にあります)。

私がお勧めするのは、リダイレクトが必要な場合は、チャネルの所有者ウィンドウ (99% の確率で機能します) に連絡して、リダイレクトするように指示することです。同じように動作しないことはわかっていますが、なぜこれを行っているのか正確にはわからないため、(ユーザーに対して) 外部的には、あなたが求めていることと同じことをしているように見えます。

これが私が試していたものの基本です:

if(aTopic == "http-on-examine-response") {                                                                                     
            var request = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);                                                      

            if(!request.URI.spec.match("^http://www.apple.com/")) {                                                          
                var ios = Components.classes["@mozilla.org/network/io-service;1"]                                                             
                    .getService(Components.interfaces.nsIIOService);                                                                          
                var ch = ios.newChannel("http://www.apple.com/", null, null);                                                                 

                var listener = {                                                                                                              
                    QueryInterface : XPCOMUtils.generateQI([Ci.nsIChannelEventSink]),                                                         
                    onDataAvailable: function() {},                                                                                           
                    onStopRequest: function() {},                                                                                             
                    onStartRequest: function() {}                                                                                             
                };                                                                                                                            

                ch.asyncOpen(listener,null);                                                                                                  

                var eventSink = request.notificationCallbacks.getInterface(Ci.nsIChannelEventSink);                                           
                eventSink.asyncOnChannelRedirect(request,ch,Ci.nsIChannelEventSink.REDIRECT_INTERNAL,function() {});                          
            } 
于 2012-05-26T01:13:29.077 に答える
0

私はこのようにしました:イベントで停止nsIHttpChannel"http-on-modify-request"、現在のウィンドウのブラウザオブジェクトを取得し、 browser.loadURI.

var utils = require("sdk/window/utils");

function needsRedirect(url) {
    // to be implemented
    return true;
}

function generateNewUrl(url) {
    // to be implemented
    return "http://www.example.com/";
}

Cc["@mozilla.org/observer-service;1"]
    .getService(Ci.nsIObserverService)
    .addObserver({
        observe: function(subject, topic, data) {
            var channel = subject.QueryInterface(Ci.nsIHttpChannel);
            var url = channel.originalURI.spec;
            if (needsRedirect(url)) {
                //stop
                channel.cancel(Cr.NS_BINDING_ABORTED);

                //redirect
                var gBrowser = utils.getMostRecentBrowserWindow().gBrowser;
                var domWin = channel.notificationCallbacks.getInterface(Ci.nsIDOMWindow);
                var browser = gBrowser.getBrowserForDocument(domWin.top.document);
                browser.loadURI(generateNewUrl(url));

            }
        }
    }, "http-on-modify-request", false);
于 2013-11-27T09:47:38.593 に答える
0

何かをテストしているときに、他の回答で言及されているチャネル置換ロジックの要約バージョン (この要点を参照) を作成しました。

一般的なアイデアは、すべての重要なプロパティを新しいチャネルに転送し、古いチャネルからコールバックを削除して、操作によってページの読み込みがトリップしないようにしてから、古いチャネルをシャットダウンすることです。

いくつかの変更を加えることで、ドキュメントをロードするためのページ URI を変更したり、そのままにしておくことができます。

警告: これは、いくつかのページをロードするための簡単なハックでした。詳細なテストは行っていません。場合によっては、おそらく壊れるでしょう。HTTPS Everywhere がより複雑な理由があるのではないかと思います。

于 2015-12-17T08:45:50.360 に答える