nsITraceableChannel thực sự là con đường để đi đây. bài đăng trên blog của Jan Odvarko (softwareishard.com) và bản thân tôi (ashita.org) cho thấy cách thực hiện điều này. Bạn cũng có thể muốn xem http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/, tuy nhiên nó không thực sự cần thiết để làm điều này trong một thành phần XPCOM.
Các bước cơ bản:
- Tạo mẫu Object thực hiện nsITraceableChannel; và tạo người quan sát để nghe http: // yêu cầu sửa đổi và http-on-kiểm tra-phản ứng
- người quan sát đăng ký
- người quan sát nghe hai loại yêu cầu thêm đối tượng nsITraceableChannel của chúng tôi vào chuỗi người nghe và đảm bảo rằng nsITC biết ai là tiếp theo trong chuỗi
đối tượng
- nsITC cung cấp ba callbacks và mỗi sẽ được gọi là ở giai đoạn thích hợp: onStartRequest, onDataAvailable, và onStopRequest
- trong mỗi callbacks trên, đối tượng nsITC của chúng ta phải vượt qua trên các dữ liệu mục tiếp theo trong chuỗi
Dưới đây là mã thực tế từ tiện ích bổ sung theo trang web cụ thể mà tôi đã viết có hành vi rất giống với của bạn từ những gì tôi có thể nói.
function TracingListener() {
//this.receivedData = [];
}
TracingListener.prototype =
{
originalListener: null,
receivedData: null, // array for incoming data.
onDataAvailable: function(request, context, inputStream, offset, count)
{
var binaryInputStream = CCIN("@mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
var storageStream = CCIN("@mozilla.org/storagestream;1", "nsIStorageStream");
binaryInputStream.setInputStream(inputStream);
storageStream.init(8192, count, null);
var binaryOutputStream = CCIN("@mozilla.org/binaryoutputstream;1",
"nsIBinaryOutputStream");
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
// Copy received data as they come.
var data = binaryInputStream.readBytes(count);
//var data = inputStream.readBytes(count);
this.receivedData.push(data);
binaryOutputStream.writeBytes(data, count);
this.originalListener.onDataAvailable(request, context,storageStream.newInputStream(0), offset, count);
},
onStartRequest: function(request, context) {
this.receivedData = [];
this.originalListener.onStartRequest(request, context);
},
onStopRequest: function(request, context, statusCode)
{
try
{
request.QueryInterface(Ci.nsIHttpChannel);
if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0)
{
var data = null;
if (request.requestMethod.toLowerCase() == "post")
{
var postText = this.readPostTextFromRequest(request, context);
if (postText)
data = ((String)(postText)).parseQuery();
}
var date = Date.parse(request.getResponseHeader("Date"));
var responseSource = this.receivedData.join('');
//fix leading spaces bug
responseSource = responseSource.replace(/^\s+(\S[\s\S]+)/, "$1");
piratequesting.ProcessRawResponse(request.originalURI.spec, responseSource, date, data);
}
}
catch (e)
{
dumpError(e);
}
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
readPostTextFromRequest : function(request, context) {
try
{
var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Ci.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
// Seek locks the file so, seek to the beginning only if necko hasn't read it yet,
// since necko doesn't seek to 0 before reading (at lest not till 459384 is fixed).
if (ss && prevOffset == 0)
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
dump("Failed to Query Interface for upload stream.\n");
}
}
catch(exc)
{
dumpError(exc);
}
return null;
},
readFromStream : function(stream, charset, noClose) {
var sis = CCSV("@mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
}
hRO = {
observe: function(request, aTopic, aData){
try {
if (typeof Cc == "undefined") {
var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
var Ci = Components.interfaces;
}
if (aTopic == "http-on-examine-response") {
request.QueryInterface(Ci.nsIHttpChannel);
if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0) {
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
}
}
} catch (e) {
dump("\nhRO error: \n\tMessage: " + e.message + "\n\tFile: " + e.fileName + " line: " + e.lineNumber + "\n");
}
},
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;
},
};
var observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(hRO,
"http-on-examine-response", false);
Trong đoạn mã trên, originalListener
là người nghe chúng tôi đang tự chèn vào trước trong chuỗi. Điều quan trọng là bạn giữ thông tin đó khi tạo Trình theo dõi và truyền dữ liệu trong cả ba cuộc gọi lại. Nếu không thì không có gì sẽ hoạt động (các trang thậm chí sẽ không tải. Firefox chính nó là cuối cùng trong chuỗi).
Lưu ý: có một số chức năng được gọi là trong đoạn mã trên là một phần của các piratequesting add-on, ví dụ .: parseQuery()
và dumpError()
Các chủ đề đã cho bạn một ý tưởng sai lầm, có lẽ. Tôi không tìm kiếm giải pháp hiện có. Vui lòng đọc toàn bộ vấn đề. Cảm ơn :) – Jumper
@ Jumper, Tamper Data có thể là cơ sở tốt để bắt đầu xây dựng tiện ích bổ sung của bạn. Bạn sẽ phải tách ra hầu hết mã UI, nhưng mã bạn cần theo dõi và thay đổi các yêu cầu XHR sẽ ở trong đó. –
Vâng, có một cái nhìn lướt qua trong quá khứ. Dường như sử dụng dịch vụ Observer. Các liên kết trong câu hỏi (nói về nsITraceableChannel) cũng sử dụng Observer. Sẽ xem lại mã tamperData hôm nay. – Jumper