我正在为 Mozilla Firefox 开发一个扩展,我用自己的扩展覆盖本机侦听器并监控所有 HTTP 请求,如这里的帖子所示:http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
我监视那些驻留在特定域下的请求,并使用我从我自己的 XMLHTTPRequest 收到的响应正文更改其相应的响应正文。对于文本文件,一切正常。
但是,我在下载图像时遇到问题。出于某种原因,当我将传入数据写入流,然后尝试打开图像时,我收到图像包含错误且无法显示的错误。
我可能做错了什么?
更新:我提供了一些代码,以阐明我的方法。
var xmlRequest = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Ci.nsIXMLHttpRequest);
...
xmlRequest.open('GET', xmlRequestURL, false);
xmlRequest.send(null);
function TracingListener() {}
TracingListener.prototype = {
originalListener: null,
onStartRequest: function (request, context) {
httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
try {
this.originalListener.onStartRequest(request, context);
}
catch (ex) {
request.cancel(ex);
}
},
onDataAvailable: function (request, context, inputStream, offset, count) {
httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
//Read the contents from the stream, but ignore them.
var binaryInputStream = CCIN('@mozilla.org/binaryinputstream;1', 'nsIBinaryInputStream');
binaryInputStream.setInputStream(inputStream);
var binaryOutputStream = CCIN('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream');
var data = binaryInputStream.readBytes(count);
//Delay the call to the original listener.
},
onStopRequest: function (request, context, statusCode) {
httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
//Check if the response is successful.
if(xmlRequest.status == 200) {
try {
var responseLen = xmlRequest.getResponseHeader("Content-Length");
var response = xmlRequest.response;
var storageStream = CCIN('@mozilla.org/storagestream;1', 'nsIStorageStream');
storageStream.init(8192, responseLen, null);
var binaryOutputStream = CCIN('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream');
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
binaryOutputStream.writeBytes(response, responseLen);
//Make the call to the original listener.
this.originalListener.onDataAvailable(request, context, storageStream.newInputStream(0), 0, responseLen);
}
catch (e) {
dumpError(e);
}
//Pass it to the original listener
this.originalListener.onStopRequest(request, context, statusCode);
}
else {
console.log('[INFO] onStopRequest not processed, status is ' + xmlRequest.status + ', for URL: ' + requestURL);
}
}
}
var observer = {
httpRequestObserver: {
observe: function (request, aTopic, aData) {
httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
if(mustBeMonitored(requestURL)) {
console.log('[INFO] Observing URL: ' + requestURL);
if (aTopic == 'http-on-modify-request') {
console.log('[INFO] ' + aTopic + ' for URL: ' + requestURL);
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
}
}
},
register: function () {
observerService.addObserver(observer.httpRequestObserver, 'http-on-modify-request', false);
},
unregister: function () {
observerService.removeObserver(observer.httpRequestObserver, 'http-on-modify-request');
},
QueryInterface: function (aIID) {
/*if (typeof Cc == "undefined") {
var Cc = components.classes;
}
if (typeof Ci == "undefined") {
var Ci = components.interfaces;
}*/
if (aIID.equals(Ci.nsIObserver) || aIID.equals(Ci.nsISupports))
return this;
throw components.results.NS_NOINTERFACE;
}
}
};
最后,我能够检测到问题。对于 XMLHttpRequest,我必须指定其响应类型,如下所示:
xmlRequest.responseType = 'arraybuffer';
然后,响应存储在JavaScript ArrayBuffer
中,我必须将其转换为Uint8Array
,然后将其存储到流中。
此解决方案适用于二进制文件和文本文件。