代码之家  ›  专栏  ›  技术社区  ›  Avindra Goolcharan

重定向请求(nsiHttpChannel?)在Firefox扩展中

  •  43
  • Avindra Goolcharan  · 技术社区  · 15 年前

    我已经尝试了很长一段时间,但没有好的结果。

    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,找出它与哪个窗口(如果有的话)关联,以及其他一些东西。我不知道的是如何重定向一个请求,我知道这是可能的,因为我可以在任何请求发出之前得到一个nsittpchannel。

    4 回复  |  直到 13 年前
        1
  •  3
  •   Daniel Marschall    10 年前

    我们可以通过覆盖 nsiHttpChannel 对于一个新的,这样做有点复杂,但幸运的是附加组件 https-everywhere 实现此操作以强制https连接。

    https无处不在 的源代码可用 here

    这所需的大部分代码都在文件中

    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();
    

    代码将 请求没有重定向。

    虽然我已经对上述代码进行了足够好的测试,但我不确定它的实现。据我所知,它复制了请求通道的所有属性,并将它们设置为要重写的通道。之后,原始请求请求的输出将使用新通道提供。

    顺便说一句,我在一篇SO的帖子里看到过这样的建议。

        2
  •  1
  •   Daniel    13 年前

    我的印象是,您不能在这个级别上这样做-我尝试了各种方法,从外部“欺骗”调用要创建的nsithttpchannel的代码(本文末尾的示例)。

    我的建议是,如果你想重定向,请联系频道的所有者窗口(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() {});                          
                } 
    
        3
  •  0
  •   Daniel Marschall    10 年前

    我是这样做的:住手 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);
    
        4
  •  0
  •   the8472    9 年前

    在测试某些东西时,我创建了一个压缩版本(参见 this gist )其他答案中提到的通道替换逻辑。

    通过一些修改,可以更改文档加载的页面URI或保持原样。