2010-11-04 15 views
5

Estoy trabajando en una extensión de Firefox y quiero saber cuando una página inicia una solicitud xhr, vi algunos códigos pero eran bastante grandes, ¿hay alguna muestra simple para lograr esto?¿Cómo escuchar fácilmente las solicitudes xhr con javascript?

Estoy probando este código:

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) { 
        // var newListener = new TracingListener(); 
        //request.QueryInterface(Ci.nsITraceableChannel); 
        //newListener.originalListener = request.setNewListener(newListener); 
       //} GOOGLE FAILS TO LOAD IF I UNCOMMENT THIS 
      } 
     } 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); 

Pero en observar al agregar el newListener, si quitar los comentarios que los sitios de piezas como Google (con función de búsqueda instantánea) de carga costumbre en absoluto, me gustaría ser capaz para leer responseSource en onStopRequest, traté de agregar una alerta, pero nunca se dispara y se arruinan sitios como he dicho que sucede con la búsqueda instantánea de Google.

Respuesta

6

En javascript, puede redefinir cualquier función u objeto sobre la marcha. Para su problema, puede intentar algo como esto:

var original_xhr = XMLHttpRequest; 
XMLHttpRequest = function() { 
    /* logic that notifies your plugin goes here */ 
    ... 
    original_xhr(); 
    alert ("I redefined this function"); 

Espero que ayude.

-tjw

+0

Esto no captura la solicitud para la función de búsqueda en vivo de Google, ¿sabes si utilizan algo diferente de xhr? – gtilx

+2

Sí, Google usa algo similar a JSONP, que incorpora una etiqueta de script en la página utilizando document.write(). Entonces, para google, sobrescribirá la función document.write(). Algunas implementaciones JSONP usan document.appendChild (script_tag). –

3

Aquí es la versión completa de la solución de Travis J Webb. Simplemente ponga esto cerca de la parte superior de su archivo JS o HMTL.

(function(){ 
    var original_xhr = XMLHttpRequest; 
    window.XMLHttpRequest = function() { 
     /* logic that notifies your plugin goes here */ 

     original_xhr.apply(this, Array.prototype.slice.call(arguments)); 
     alert ("I redefined this function"); 
    } 
}()); 
+0

Esto no captura la solicitud para la función de búsqueda en vivo de Google, ¿sabes si utilizan algo diferente a xhr? – gtilx

+0

Ejecuté el código actualizado con FireFox 3.6.3 y Firebug y detectó la solicitud, pero también mostró un error de javascript en el código de Google. Esto lleva a creer que hay un margen de mejora. – Eric

Cuestiones relacionadas