简体   繁体   English

Firefox扩展:取消请求并发出虚假回复

[英]Firefox extension: Cancel requests and emit fake responses

I am trying to develop a Firefox extension that drops every HTTP request to a certain site and returns a fake response. 我正在尝试开发一个Firefox扩展,将每个HTTP请求丢弃到某个站点并返回一个假响应。 No request should get through to the original web server, but I want to be able to create a custom response. 没有请求应该通过原始Web服务器,但我希望能够创建自定义响应。 I tried to intercept the "http-on-modify-request" message, but cancelling the request doesn't seem to work, as I cannot simulate a real response afterwards. 我试图拦截“http-on-modify-request”消息,但是取消请求似乎不起作用,因为我之后无法模拟真实的响应。 Similarly, using an nsITraceableStream instance, I don't seem to be able to really cancel the request. 同样,使用nsITraceableStream实例,我似乎无法真正取消请求。 I am out of ideas, can somebody help? 我没有想法,有人可以帮忙吗?

The answer below has been superseded as of Firefox 21, now the nsIHttpChannel.redirectTo() method does the job nicely. 从Firefox 21开始,下面的答案已被取代,现在nsIHttpChannel.redirectTo()方法可以很好地完成工作。 You can redirect to a data: URI, something like this will work: 您可以重定向到数据:URI,这样的东西可以工作:

Components.utils.import("resource://gre/modules/Services.jsm");
const Ci = Components.interfaces;

[...]

onModifyRequest: function(channel)
{
  if (channel instanceof Ci.nsIHttpChannel && shouldRedirect(channel.URI.spec))
  {
    let redirectURL = "data:text/html," + encodeURIComponent("<html>Hi there!</html>");
    channel.redirectTo(Services.io.newURI(redirectURI, null, null));
  }
}

Original answer (outdated) 原始答案(过时)

Each channel has its associated stream listener that gets notified when data is received. 每个通道都有其关联的流监听器 ,在收到数据时会收到通知。 All you need to do to fake a response is to get this listener and feed it with wrong data. 你需要做的就是伪造一个响应就是获得这个监听器并用错误的数据提供它。 And nsITraceableChannel is in fact the way to do it. nsITraceableChannel实际上就是这样做的。 You need to replace the channel's usual listener by your own that won't do anything, after that you can cancel the channel without the listener being notified about it. 您需要自己替换频道的常用侦听器,这样就无法执行任何操作,之后您可以取消频道而不会通知侦听器。 And then you trigger the listener and give it your own data. 然后你触发监听器并给它自己的数据。 Something like this: 像这样的东西:

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;

[...]

onModifyRequest: function(channel)
{
  if (channel instanceof Ci.nsIHttpChannel && channel instanceof Ci.nsITraceableChannel)
  {
    // Our own listener for the channel
    var fakeListener = {
      QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener,
                        Ci.nsIRequestObserver, Ci.nsIRunnable]),
      oldListener: null,
      run: function()
      {
        // Replace old listener by our fake listener
        this.oldListener = channel.setNewListener(this);

        // Now we can cancel the channel, listener old won't notice
        //channel.cancel(Components.results.NS_BINDING_ABORTED);
      },
      onDataAvailable: function(){},
      onStartRequest: function(){},
      onStopRequest: function(request, context, status)
      {
        // Call old listener with our data and set "response" headers
        var stream = Cc["@mozilla.org/io/string-input-stream;1"]
                       .createInstance(Ci.nsIStringInputStream);
        stream.setData("<html>Hi there!</html>", -1);
        this.oldListener.onStartRequest(channel, context);
        channel.setResponseHeader("Refresh", "5; url=http://google.com/", false);
        this.oldListener.onDataAvailable(channel, context, stream, 0, stream.available());
        this.oldListener.onStopRequest(channel, context, Components.results.NS_OK);
      }
    }

    // We cannot replace the listener right now, see
    // https://bugzilla.mozilla.org/show_bug.cgi?id=646370.
    // Do it asynchronously instead.
    var threadManager = Cc["@mozilla.org/thread-manager;1"]
                          .getService(Ci.nsIThreadManager);
    threadManager.currentThread.dispatch(fakeListener, Ci.nsIEventTarget.DISPATCH_NORMAL);
  }
}

The problem with this code is still that the page shows up blank if the channel is canceled (so I commented that line) - it seems that the listener still looks at the channel and notices that it is canceled. 这段代码的问题仍然是如果频道被取消,页面显示为空白(所以我评论了该行) - 似乎听众仍然看着频道并注意到它已被取消。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM