我现在已经在这方面努力了很长时间,并没有很好的结果。
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。
任何人都知道该怎么办? :/我一直试着打了几个星期,然后无处可去。
答案 0 :(得分:3)
我们可以通过用新的覆盖nsiHttpChannel
来做到这一点,这样做有点复杂但幸运的是,加载项https-everywhere
实现了强制https连接。
https-everywhere
的源代码可用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();
代码将替换请求不重定向。
虽然我已经足够好地测试了上面的代码,但我不确定它的实现。据我所知,它复制了所请求频道的所有属性,并将它们设置为要覆盖的频道。之后以某种方式使用新通道提供原始请求所请求的输出。
P.S。我看过一篇SO帖子,其中提出了这种方法。
答案 1 :(得分: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() {});
}
答案 2 :(得分: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);
答案 3 :(得分:0)
在测试某些内容时,我创建了其他答案中提到的频道替换逻辑的精简版本(参见this gist)。
一般的想法似乎是将所有关键属性转移到新频道,从旧频道中删除回调,这样操作就不会使页面加载绊倒,然后关闭旧频道。
通过一些修改,可以更改文档加载的页面URI或保持原样。
警告:这只是一个加载几页的快速入侵,我没有深入测试它,它可能会在某些情况下中断。我怀疑为什么HTTPS Everywhere更复杂。