Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirecting Request (nsiHttpChannel?) in Firefox Extensions

I've been trying at this for a long time now, and no good results.

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

Basically, on http-on-modify-request, I know how to examine the URI, figure out which window (if any) it's associated with, and a bunch of other stuff. What I can't figure out is how to redirect a request, which I know is possible from here, because I can get an nsIHttpChannel before any request is ever sent out.

Anyone know what to do? :/ I've been trying for a couple of weeks on and off, and got nowhere.

like image 292
Avindra Goolcharan Avatar asked Feb 10 '10 13:02

Avindra Goolcharan


1 Answers

We can do this by overriding the nsiHttpChannel with a new one, doing this is slightly complicated but luckily the add-on https-everywhere implements this to force a https connection.

https-everywhere's source code is available here

Most of the code needed for this is in the files

[IO Util.js] [ChannelReplacement.js]

We can work with the above files alone provided we have the basic variables like Cc,Ci set up and the function xpcom_generateQI defined.

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

The code will replace the request not redirect.

While I have tested the above code well enough, I am not sure about its implementation. As far I can make out, it copies all the attributes of the requested channel and sets them to the channel to be overridden. After which somehow the output requested by original request is supplied using the new channel.

P.S. I had seen a SO post in which this approach was suggested.

like image 115
mdprasadeng Avatar answered Oct 02 '22 09:10

mdprasadeng