2010-01-26 20 views
6

Aggiornamento: Immagino che il soggetto abbia dato un'idea errata che sto cercando un addon esistente. Questo è un problema personalizzato e NON voglio una soluzione esistente.
Desidero WRITE (o più appropriatamente, modifica ed esistente) Addon.Crea Addon per Firefox per osservare e modificare le richieste e le risposte XHR

Ecco la mia richiesta:

  • voglio che il mio addon di lavorare per un particolare sito solo
  • I dati relativi alle pagine sono codificati usando un hash 2 modo
  • Una buona dose di informazioni viene caricato richieste XHR e talvolta visualizzate in bolle animate ecc.
  • La versione corrente del mio addon analizza la pagina tramite espressioni XPath , decodifica i dati e li sostituisce

  • Il problema arriva con quelle scatole bubblified che vengono visualizzati su evento del mouse-over

  • Così, mi sono reso conto che potrebbe essere una buona idea per creare un XHR ponte che potrebbe ascoltare tutti i dati e codifica/decodifica al volo
  • Dopo un paio di ricerche, mi sono imbattuto nsITraceableInterface [1] [2] [3]

volevo solo sapere se sono sulla strada giusta. Se "sì", gentilmente fornire eventuali suggerimenti e suggerimenti aggiuntivi che potrebbero essere appropriati; e se "No", poi .. beh, si prega di aiuto con i puntatori corretti :)

Grazie,
Bipin.

[1]. https://developer.mozilla.org/en/NsITraceableChannel
[2]. http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
[3]. http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/

risposta

8

nsITraceableChannel è davvero il modo di andare qui. i post del blog di Jan Odvarko (softwareishard.com) e io (ashita.org) mostrano come farlo. Si potrebbe anche voler vedere http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/, tuttavia non è davvero necessario farlo in un componente XPCOM.

I passi sono fondamentalmente:

  1. Creare prototipo oggetto che implementa nsITraceableChannel; e creare osservatore ad ascoltare la http-on-modifica-richiesta e http-on-esame-risposta
  2. registro osservatore
  3. osservatore ad ascoltare i due tipi di richiesta aggiunge nostri nsITraceableChannel oggetto nella catena di ascoltatori e assicurarsi che il nostro nsITC sa che è successivo della catena
  4. oggetto
  5. nsITC fornisce tre callback e ognuno sarà chiamato al momento opportuno: onStartRequest, OnDataAvailable e onStopRequest
  6. in ciascuna delle callback sopra, il nostro oggetto nsITC deve trasmettere dati al prossimo articolo della catena

Di seguito è riportato il codice effettivo da un componente aggiuntivo specifico del sito che ho scritto che si comporta in modo molto simile al tuo da quello che posso dire.

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

Nel codice precedente, originalListener è l'ascoltatore stiamo inserendo stessi prima della catena. È fondamentale conservare tali informazioni durante la creazione del listener di tracciamento e inoltrare i dati in tutte e tre le callback. Altrimenti nulla funzionerà (le pagine non verranno nemmeno caricate. Firefox stesso è l'ultimo della catena).

Nota: ci sono alcune funzioni chiamate nel codice qui sopra, che fanno parte della piratequesting add-on, per es .: parseQuery() e dumpError()

0

Tamper Data Add-on. Vedi anche la How to Use it pagina

+0

Il soggetto che si ha un'idea sbagliata, forse. Non sto cercando una soluzione esistente. Si prega di leggere il problema completo. Grazie :) – Jumper

+0

@Jumper, Tamper Data sarebbe probabilmente una buona base per iniziare a costruire il tuo componente aggiuntivo. Dovresti strappare la maggior parte del codice dell'interfaccia utente, ma il codice che devi monitorare e modificare le richieste XHR sarà lì. –

+0

Sì, ha avuto un aspetto superficiale in passato. Sembrava utilizzare il servizio Observer. I link nella domanda (che parlano di nsITraceableChannel) usano anche Observer. Guarderà ancora il codice TamperData oggi. – Jumper

0

Si potrebbe provare a creare uno script greasemonkey e sovrascrivere XMLHttpRequest.
Il codice dovrebbe essere simile:

 
function request() { 
}; 
request.prototype.open = function (type, path, block) { 
GM_xmlhttpRequest({ 
    method: type, 
    url: path, 
    onload: function (response) { 
    // some code here 
    } 
}); 
}; 
unsafeWindow.XMLHttpRequest = request; 

noti inoltre che è possibile attivare uno script di GM in un addon per Firefox

+0

L'avevo preso in considerazione, ma ho deciso di evitare a causa dell'insicurezza della vista considerata non sicura. Qualche idea sul canale nsITraceable? – Jumper

+0

unsafeWindow è solo un problema se si dispone di codice scadente. Basandomi sul suono della tua domanda, penso che dovresti stare bene usando unsafeWindow. L'unica ragione per non usarlo sarebbe se si sentisse che il sito su cui verrebbe usato proverebbe in qualche modo a violare il sistema (questo non succederà se non si rilascia il codice, e anche se lo si farebbe, sarebbe devono essere molto utili prima che molto probabilmente si preoccupino), anche se vi hanno fatto un po 'come, il vostro codice dovrebbe essere abbastanza sicuro da poterlo gestire. Se sei preoccupato di questo, un addon FF sarebbe peggio. –