2013-04-17 9 views
7

Ehi, sono stato in grado di scrivere un listener nsIStreamListener per ascoltare le risposte e ottenere il testo della risposta seguendo le esercitazioni al numero nsitraceablechannel-intercept-http-traffic. Ma non sono in grado di modificare la risposta inviata al browser. restituire la risposta e inviarlo alla catena che riflette in firebug ma non nel browser.Come modificare la risposta http nell'estensione per Firefox

Quello che sto indovinando è che dovremo sostituire il listener predefinito piuttosto che ascoltare nella catena. Non posso ottenere alcun documento ovunque che spiega come farlo.

Qualcuno potrebbe darmi qualche idea su questo. Questo è principalmente per scopi educativi.

Grazie in anticipo

Edit: A partire da ora sono arrivato a un po 'di soluzioni sono in grado di fare questo

var old; 

function TracingListener() {} 

TracingListener.prototype = { 
    originalListener: null, 
    receivedData: null, //will be an array for incoming data. 

//For the listener this is step 1. 
onStartRequest: function (request, context) { 
    this.receivedData = []; //initialize the array 

    //Pass on the onStartRequest call to the next listener in the chain -- VERY   IMPORTANT 
    //old.onStartRequest(request, context); 
}, 

//This is step 2. This gets called every time additional data is available 
onDataAvailable: function (request, context, inputStream, offset, count) { 
    var binaryInputStream = CCIN("@mozilla.org/binaryinputstream;1", 
     "nsIBinaryInputStream"); 
    binaryInputStream.setInputStream(inputStream); 

    var storageStream = CCIN("@mozilla.org/storagestream;1", 
     "nsIStorageStream"); 
    //8192 is the segment size in bytes, count is the maximum size of the stream in  bytes 
    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); 

    this.receivedData.push(data); 

    binaryOutputStream.writeBytes(data, count); 



    //Pass it on down the chain 
    //old.onDataAvailable(request, context,storageStream.newInputStream(0), offset, count); 
}, 
onStopRequest: function (request, context, statusCode) { 
    try { 
     //QueryInterface into HttpChannel to access originalURI and requestMethod properties 
     request.QueryInterface(Ci.nsIHttpChannel); 


     //Combine the response into a single string 
     var responseSource = this.receivedData.join(''); 


     //edit data as needed 
     responseSource = "test"; 
     console.log(responseSource); 

    } catch (e) { 
     //standard function to dump a formatted version of the error to console 
     dumpError(e); 
    } 

    var stream = Cc["@mozilla.org/io/string-input-stream;1"] 
     .createInstance(Ci.nsIStringInputStream); 
    stream.setData(responseSource, -1); 

    //Pass it to the original listener 
    //old.originalListener=null; 
    old.onStartRequest(channel, context); 
    old.onDataAvailable(channel, context, stream, 0, stream.available()); 
    old.onStopRequest(channel, 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); 

      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; 
} 

} 

httpRequestObserver = { 

observe: function (request, aTopic, aData) { 
    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); 

     console.log(request.statusCode); 

     var newListener = new TracingListener(); 
     request.QueryInterface(Ci.nsITraceableChannel); 

     channel = request; 
     //newListener.originalListener 
     //add new listener as default and save old one 
     old = request.setNewListener(newListener); 
     old.originalListener = null; 

     var threadManager = Cc["@mozilla.org/thread-manager;1"] 
      .getService(Ci.nsIThreadManager); 
     threadManager.currentThread.dispatch(newListener,  Ci.nsIEventTarget.DISPATCH_NORMAL); 


    } 
}, 

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(httpRequestObserver, 
"http-on-examine-response", false); 

risposta

3

Questo esempio funziona per me su Firefox 34 (corrente notturno): https://github.com/Noitidart/demo-nsITraceableChannel

ho scaricato il XPI, bootstrap.js a cura di modificare il flusso:

132   // Copy received data as they come. 
133   var data = binaryInputStream.readBytes(count); 
134   data = data.replace(/GitHub/g, "TEST"); 
135   this.receivedData.push(data); 

installato l'XPI quindi ricaricato la pagina github. Legge "TEST" nel footer.

La versione del codice che hai postato non passa effettivamente i risultati al vecchio listener, quindi questa è la prima cosa che dovrebbe essere cambiata.

Potrebbe anche aver interagito male con Firebug o un'altra estensione. È una buona idea provare a riprodurre il problema in un profilo pulito (con solo l'estensione installata).

+0

Woo la mia demo/lavoro sperimentale sta aiutando gli altri! Grazie per aver citato le mie cose! :) Come sei arrivato a quella storia? – Noitidart

+1

Più uno perché non ho mai saputo che questo potrebbe essere usato per modificare la sorgente visualizzata/renderizzata. Ho pensato che fosse solo per ottenere una copia di ciò che veniva richiesto http. Super cool ho imparato qualcosa sulla merda che ho copiato e passato con il togather! – Noitidart

+1

@Noitidart: via Google; bello sapere che ci siamo aiutati a vicenda. Vai open-source! – Nickolay

Problemi correlati