2009-10-11 6 views
1

Dans mon extension firefox, je crée un élément xul: browser. Je souhaite qu'un observateur intercepte les modifications d'URL dans le navigateur intégré et ouvre l'URL dans un nouvel onglet du navigateur (dans le navigateur principal). J'aimerais aussi que les nouvelles fenêtres engendrées par la fenêtre xul: browser s'ouvrent dans un onglet au lieu d'une nouvelle fenêtre de navigateur.Un observateur pour les chargements de page dans un xul personnalisé: navigateur

J'ai créé un observateur qui fonctionne, mais je ne sais pas encore comment appliquer cet observateur uniquement à l'élément xul: browser.

function myFunction(){ 
    var container = jQuery("#container")[0]; 
    var new_browser_element = document.createElement('browser'); 
    container.appendChild(new_browser_element); 

    var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); 
    observerService.addObserver(myObserver, "http-on-modify-request", false); 
} 


var myObserver = { 
    observe: function(aSubject, aTopic, aData){ 
     if (aTopic != 'http-on-modify-request'){ 
     aSubject.QueryInterface(Components.interfaces.nsIHttpChannel); 
     // alert(aSubject.URI.spec); 
     // Now open url in new tab 
     } 
    }, 

    QueryInterface: function(iid){ 
     if (!iid.equals(Components.interfaces.nsISupports) && 
     !iid.equals(Components.interfaces.nsIObserver)) 
     throw Components.results.NS_ERROR_NO_INTERFACE; 

     return this; 
    } 
}; 
+0

donc en gros, vous voulez vérifier le contexte dans lequel la demande est originaire, puis l'annuler, et dire au navigateur d'ouvrir un nouvel onglet avec la précédente l'URL et les en-têtes de la requête? (Je ne pense pas qu'il existe un moyen de changer la cible d'une requête après qu'elle a commencé, mais je vais regarder) –

+0

Oui c'est exactement ce que je veux faire. – makeee

+0

la solution "http-on-modify-request" n'observe pas les changements d'URL, elle observe les charges HTTP. Pour les changements d'URL, vous avez besoin d'un écouteur de progression. – Nickolay

Répondre

4

Vous pouvez essayer:

var myObserver = { 
    observe: function(aSubject, aTopic, aData){ 
     if (aTopic == 'http-on-modify-request') 
       { 
       aSubject.QueryInterface(Components.interfaces.nsIHttpChannel); 
       var url = aSubject.URI.spec; 
       var postData ; 
       if (aSubject.requestMethod.toLowerCase() == "post") 
       { 
        var postText = this.readPostTextFromRequest(request); 
        if (postText) 
        { 
        var dataString = parseQuery(postText); 
        postData = postDataFromString(dataString); 
        } 
       } 

       var oHttp = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel); 

       var interfaceRequestor = oHttp.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor); 
       var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); 


       //check if it is one of your mini browser windows 
       if (jQuery(DOMWindow).hasClass('mini_browser')) 
       { 

        openInTab(url, postData); 

        var request = aSubject.QueryInterface(Components.interfaces.nsIRequest); 
        request.cancel(Components.results.NS_BINDING_ABORTED); 

       } 

     } 
    }, 

    QueryInterface: function(iid){ 
     if (!iid.equals(Components.interfaces.nsISupports) && 
      !iid.equals(Components.interfaces.nsIObserver)) 
     throw Components.results.NS_ERROR_NO_INTERFACE; 

     return this; 
    }, 

    readPostTextFromRequest : function(request) { 
    var is = request.QueryInterface(Components.interfaces.nsIUploadChannel).uploadStream; 
    if (is) 
    { 
     var ss = is.QueryInterface(Components.interfaces.nsISeekableStream); 
     var prevOffset; 
     if (ss) 
     { 
     prevOffset = ss.tell(); 
     ss.seek(Components.interfaces.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(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0); 

     return text; 
    } 
    else { 
     dump("Failed to Query Interface for upload stream.\n"); 
    } 
    } 
    return null; 
}, 

readFromStream : function(stream, charset, noClose)  
{ 
    var sis = Components.classes["@mozilla.org/binaryinputstream;1"] 
        .getService(Components.interfaces.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; 
    } 
}; 

function openInTab(url, postData) 
{ 
    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] 
     .getService(Components.interfaces.nsIWindowMediator); 
    var recentWindow = wm.getMostRecentWindow("navigator:browser"); 
    if (recentWindow) 
    { 
    // Use an existing browser window, open tab and "select" it 
    recentWindow.gBrowser.selectedTab = recentWindow.gBrowser.addTab(url, null, null, postData); 
    } 
} 

function parseQuery() { 
    var qry = this; 
    var rex = /[?&]?([^=]+)(?:=([^&#]*))?/g; 
    var qmatch, key; 
    var paramValues = {}; 
    // parse querystring storing key/values in the ParamValues associative array 
    while (qmatch = rex.exec(qry)) { 
    key = decodeURIComponent(qmatch[1]);// get decoded key 
    val = decodeURIComponent(qmatch[2]);// get decoded value 

    paramValues[key] = val; 
    } 
    return paramValues; 
} 

function postDataFromString(dataString) 
{ 
    // POST method requests must wrap the encoded text in a MIME 
    // stream 
    var stringStream = Components.classes["@mozilla.org/io/string-input-stream;1"] 
       .createInstance(Components.interfaces.nsIStringInputStream); 
    if ("data" in stringStream) // Gecko 1.9 or newer 
    stringStream.data = dataString; 
    else // 1.8 or older 
    stringStream.setData(dataString, dataString.length); 

    var postData = Components.classes["@mozilla.org/network/mime-input-stream;1"]. 
      createInstance(Components.interfaces.nsIMIMEInputStream); 
    postData.addHeader("Content-Type", "application/x-www-form-urlencoded"); 
    postData.addContentLength = true; 
    postData.setData(stringStream); 

    return postData; 
} 

Je mettrai à jour ce pour remplir les blancs dans un peu. Edit: voir http://forums.mozillazine.org/viewtopic.php?p=2772951#p2772951 pour savoir comment obtenir la fenêtre source d'une requête.

Pour demander un code d'annulation de http://zenit.senecac.on.ca/wiki/index.php/Support_For_OpenID. Pour plus de détails sur nsIRequest, voir http://mxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsIRequest.idl pour plus de détails. Voir http://forums.mozillazine.org/viewtopic.php?p=2404533#p2404533 et https://developer.mozilla.org/en/XUL/Method/addTab pour la définition de addTab.

parseQuery provient de http://blog.strictly-software.com/2008/10/using-javascript-to-parse-querystring.html.

Voir https://developer.mozilla.org/en/Code_snippets/Post_data_to_window#Preprocessing_POST_data pour savoir comment traiter les données de publication dans une forme adaptée à addTab.

ReadPostFromText et ReadTextFromStream les deux viennent de Firebug (bien que légèrement modifié)

+0

Hé, ça a l'air génial! En ce moment j'essaye de comprendre comment dire si la demande provenait de mon élément xul: browser. J'ai en fait un certain nombre de xul: éléments du navigateur à un moment donné et je voudrais intercepter les demandes de tous. Est-il possible que je puisse juste donner à chaque élément du navigateur le même nom de classe: new_browser_element.setAttribute ('class', 'mini_browser'); Et puis: if (DOMWindow.attr ('class') == 'mini_browser') ... Evidemment ce n'est pas correct, mais ce nom de classe serait-il contenu dans l'objet "DOMWindow"? – makeee

+0

Vous pourriez avoir besoin de jQuery (DOMWindow) .hasClass ('mini_browser'). Je suppose que vous aurez besoin d'utiliser jQuery() pour accéder à la méthode hasClass –

+0

ajouté après la transmission des données et le contrôle de classe minibrowser –

Questions connexes