在Firefox扩展中改变HTTP响应 [英] Altering HTTP Responses in Firefox Extension

查看:179
本文介绍了在Firefox扩展中改变HTTP响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Firefox扩展中更改HTTP响应正文?我用下面的代码设置了一个http-on-examine-response观察者和一个nsIStreamListener对象。获取数据后,解析并修改数据,如何将更改的响应返回给Firefox浏览器?例如,假设我在启用了我的扩展程序的情况下访问Google.com,扩展程序应拦截响应,并将每次发生的google更改为goggle。因此,当页面加载时,用户会在任何地方看到护目镜。
$ b $ pre $函数TmSteroidsObserver()
{
this.register();



TmSteroidsObserver.prototype = {
观察:函数(主题,主题,数据){

if(topic == http-on-examine-response){

}
else if(topic ==http-on-modify-request){
var channel = subject。的QueryInterface(Components.interfaces.nsIChannel);
var listener = new StreamListener(channel);



$ b register:function(){
var observerService = Components.classes [@ mozilla.org/observer-service; 1]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(监听器,http-on-modify-request,false);
observerService.addObserver(listener,http-on-examine-response,false);
},

unregister:function(){
var observerService = Components.classes [@ mozilla.org/observer-service;1]
.getService (Components.interfaces.nsIObserverService);
observerService.removeObserver(这个http-on-modify-request);
observerService.removeObserver(这是http-on-examine-response);


QueryInterface:function(aIID){
if(aIID.equals(Components.interfaces.nsISupports)||
aIID.equals(Components.interfaces .nsIObserver))
return this;
throw Components.results.NS_NOINTERFACE;



$ b函数StreamListener(channel){

channel.notificationCallbacks = listener;
channel.asyncOpen(listener,null);


$ b StreamListener.prototype = {
mData:,
mChannel:null,

// nsIStreamListener
onStartRequest:function(aRequest,aContext){
this.mData =;
$,

onDataAvailable:function(aRequest,aContext,aStream,aSourceOffset,aLength){
var scriptableInputStream =
Components.classes [@ mozilla.org/ scriptableinputstream; 1]
.createInstance(Components.interfaces.nsIScriptableInputStream);
scriptableInputStream.init(aStream);

this.mData + = scriptableInputStream.read(aLength);
$,

onStopRequest:function(aRequest,aContext,aStatus){
if(Components.isSuccessCode(aStatus)){
// request is successfull
this.mCallbackFunc(this.mData);
} else {
//请求失败
this.mCallbackFunc(null);
}

this.mChannel = null;
$,b
$ b // nsIChannelEventSink
onChannelRedirect:function(aOldChannel,aNewChannel,aFlags){
//如果重定向,存储新频道
this .mChannel = aNewChannel;
},

// nsIInterfaceRequestor
getInterface:function(aIID){
try {
return this.QueryInterface(aIID);
} catch(e){
throw Components.results.NS_NOINTERFACE;



// nsIProgressEventSink(不执行会导致恼人的异常)
onProgress:function(aRequest,aContext,aProgress,aProgressMax){},
onStatus:函数(aRequest,aContext,aStatus,aStatusArg){},

// nsIHttpEventSink(不执行会导致恼人的异常)
onRedirect:function(aOldChannel,aNewChannel){ },

//我们伪造一个XPCOM接口,所以我们需要实现QI
QueryInterface:function(aIID){
if(aIID.equals(Components.interfaces。 nsISupports)||
aIID.equals(Components.interfaces.nsIInterfaceRequestor)||
aIID.equals(Components.interfaces.nsIChannelEventSink)||
aIID.equals(Components.interfaces.nsIProgressEventSink) ||
aIID.equals(Components.interfaces.nsIHttpEventSink)||
aIID.equals(Components.interfaces.nsIStreamListener))
return this;

throw Components.results.NS_NOINTERFACE;
}
};


解决方案

您可以使用nsITraceableChannel来拦截响应。 p>

您应该修改所需的数据并将其传递给innerListener的OnDataAvailable



帮助你更好地理解这一点。

http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/

http://www.ashita.org/howto-xhr-listening-by- a-firefox-addon /


How can I alter the HTTP response body in a Firefox extension? I have setup an http-on-examine-response observer and an nsIStreamListener object with the code below. After I get the data, parse it, and alter it, how do I push the altered response back to the firefox browser? For example, let's say I go to Google.com with my extension enabled, the extension should intercept the response and change every occurence of "google" to "goggle". So when the page is loaded, the user will see "goggle" everywhere.

function TmSteroidsObserver()
{
  this.register();
}


TmSteroidsObserver.prototype = {
  observe: function(subject, topic, data) {

    if (topic == "http-on-examine-response") {

    }
    else if (topic == "http-on-modify-request") {
       var channel = subject.QueryInterface(Components.interfaces.nsIChannel);
       var listener = new StreamListener(channel);
    }

  },

  register: function() {
    var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                .getService(Components.interfaces.nsIObserverService);
    observerService.addObserver(listener, "http-on-modify-request", false);
    observerService.addObserver(listener, "http-on-examine-response", false);
  },

  unregister: function() {
    var observerService = Components.classes["@mozilla.org/observer-service;1"]
                            .getService(Components.interfaces.nsIObserverService);
    observerService.removeObserver(this, "http-on-modify-request");
    observerService.removeObserver(this, "http-on-examine-response");
  },

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

}

function StreamListener(channel) {

    channel.notificationCallbacks = listener;
    channel.asyncOpen(listener, null);

}

StreamListener.prototype = {
  mData: "",
  mChannel: null,

  // nsIStreamListener
  onStartRequest: function (aRequest, aContext) {
    this.mData = "";
  },

  onDataAvailable: function (aRequest, aContext, aStream, aSourceOffset, aLength) {
    var scriptableInputStream = 
      Components.classes["@mozilla.org/scriptableinputstream;1"]
        .createInstance(Components.interfaces.nsIScriptableInputStream);
    scriptableInputStream.init(aStream);

    this.mData += scriptableInputStream.read(aLength);
  },

  onStopRequest: function (aRequest, aContext, aStatus) {
    if (Components.isSuccessCode(aStatus)) {
      // request was successfull
      this.mCallbackFunc(this.mData);
    } else {
      // request failed
      this.mCallbackFunc(null);
    }

    this.mChannel = null;
  },

  // nsIChannelEventSink
  onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) {
    // if redirecting, store the new channel
    this.mChannel = aNewChannel;
  },

  // nsIInterfaceRequestor
  getInterface: function (aIID) {
    try {
      return this.QueryInterface(aIID);
    } catch (e) {
      throw Components.results.NS_NOINTERFACE;
    }
  },

  // nsIProgressEventSink (not implementing will cause annoying exceptions)
  onProgress : function (aRequest, aContext, aProgress, aProgressMax) { },
  onStatus : function (aRequest, aContext, aStatus, aStatusArg) { },

  // nsIHttpEventSink (not implementing will cause annoying exceptions)
  onRedirect : function (aOldChannel, aNewChannel) { },

  // we are faking an XPCOM interface, so we need to implement QI
  QueryInterface : function(aIID) {
    if (aIID.equals(Components.interfaces.nsISupports) ||
        aIID.equals(Components.interfaces.nsIInterfaceRequestor) ||
        aIID.equals(Components.interfaces.nsIChannelEventSink) || 
        aIID.equals(Components.interfaces.nsIProgressEventSink) ||
        aIID.equals(Components.interfaces.nsIHttpEventSink) ||
        aIID.equals(Components.interfaces.nsIStreamListener))
      return this;

    throw Components.results.NS_NOINTERFACE;
  }
};

解决方案

You can use nsITraceableChannel to intercept the response.

You should modify the data which is available to what you need and pass it to the innerListener's OnDataAvailable

Below links would help you understand this better.

http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/

http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/

这篇关于在Firefox扩展中改变HTTP响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆