Ändern von HTTP-Antworten in der Firefox-Erweiterung
Wie kann ich den HTTP-Antworttext in einer Firefox-Erweiterung ändern? Ich habe einen Beobachter für http-on-exam-response und ein nsIStreamListener-Objekt mit dem folgenden Code eingerichtet. Wie kann ich die geänderte Antwort an den Firefox-Browser zurückschieben, nachdem ich die Daten erhalten, analysiert und geändert habe? Angenommen, ich gehe mit aktivierter Erweiterung zu Google.com. Die Erweiterung sollte die Antwort abfangen und jedes Vorkommen von "google" in "goggle" ändern. Wenn die Seite geladen wird, sieht der Benutzer überall "Brille".
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;
}
};