Comment puis-je modifier le corps de la réponse HTTP dans une extension Firefox? J'ai mis en place un observateur http-on-examine-response et un objet nsIStreamListener avec le code ci-dessous. Après avoir récupéré les données, les avoir analysées et les avoir modifiées, comment repousser la réponse modifiée au navigateur Firefox? Par exemple, disons que je vais sur Google.com avec mon extension activée, l'extension devrait intercepter la réponse et changer chaque occurrence de "google" en "masque". Ainsi, lorsque la page est chargée, l'utilisateur verra "goggle" partout.Modification des réponses HTTP dans l'extension Firefox
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;
}
};