2013-04-17 6 views
7

Hej, udało mi się napisać odbiornik nsIStreamListener, aby wysłuchać odpowiedzi i uzyskać tekst odpowiedzi po tutorialach pod numerem nsitraceablechannel-intercept-http-traffic .Jednakże nie jestem w stanie zmodyfikować odpowiedzi wysłanej do przeglądarki. zwróć odpowiedź i odeślij ją do łańcucha, który odzwierciedla w firebug, ale nie w przeglądarce.Jak zmodyfikować odpowiedź http w rozszerzeniu przeglądarki Firefox

Zgaduję, że będziemy musieli zastąpić domyślnego słuchacza, zamiast słuchać go w łańcuchu. Nie mogę uzyskać żadnych dokumentów w dowolnym miejscu, co wyjaśnia, jak to zrobić.

Czy ktoś może mi w tym pomóc? To głównie w celach edukacyjnych.

góry dzięki

Edit: Jak teraz mam przybył na trochę rozwiązań jestem w stanie to zrobić

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

Odpowiedz

3

Ten przykład działa dla mnie na Firefox 34 (prąd nocny): https://github.com/Noitidart/demo-nsITraceableChannel

Pobrałem xpi pod redakcją bootstrap.js modyfikację strumienia:

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

zainstalował XPI, a następnie ponownie załadował stronę github. W stopce przeczytano "TEST".

Ta wersja kodu, który wysłałeś, nie przekazuje wyników wstecz do starego słuchacza, więc to pierwsza rzecz, która powinna zostać zmieniona.

Może również źle współpracować z Firebug lub innym rozszerzeniem. Warto spróbować odtworzyć problem w czystym profilu (tylko z zainstalowanym rozszerzeniem).

+0

Woo moja praca demo/eksperymentalna pomaga innym! Dzięki za cytowanie moich rzeczy! :) Jak się z tym spotkałeś? – Noitidart

+1

Plus, ponieważ nigdy nie wiedziałem, że można to wykorzystać do modyfikacji wyświetlanego/renderowanego źródła. Myślałem, że to po prostu uzyskać kopię tego, o co prosiła http. Super fajne dowiedziałem się czegoś o bzdurach, które skopiowałem wklejono i zmiksowałem togather! – Noitidart

+1

@Noitidart: za pośrednictwem Google; miło wiedzieć, że sobie pomagaliśmy. Idź z otwartym kodem źródłowym! – Nickolay