2009-10-11 2 views
1

В моем расширении firefox я создаю элемент xul: browser. Я хочу иметь наблюдателя, который перехватывает любые изменения URL-адресов внутри встроенного браузера и открывает URL-адрес на новой вкладке браузера (в главном браузере). Я также хотел бы, чтобы новые окна, порожденные окном xul: browser, открывались на вкладке вместо нового окна браузера.Наблюдатель за загрузку страниц в пользовательском xul: browser

Я создал наблюдателя, который работает, но я еще не знаю, как применить этого наблюдателя только к элементу 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

поэтому в основном, вы хотите проверить контекст, из которого запрос берет свое начало, а затем отменить его, и сообщить браузеру, чтобы открыть новую вкладку с предыдущим URL запроса и заголовки? (Я не думаю, что есть способ изменить цель запроса после его запуска, но я посмотрю) –

+0

Да, это именно то, что я хочу сделать. – makeee

+0

Решение на основе «http-on-modify-request» не отслеживает изменения URL-адресов, оно отслеживает нагрузки HTTP. Для изменения URL вам нужен слушатель прогресса. – Nickolay

ответ

4

Вы можете попробовать:

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

Я буду обновлять это, чтобы заполнить пробелы в немного.

Редактировать: см. http://forums.mozillazine.org/viewtopic.php?p=2772951#p2772951, как получить исходное окно запроса.

Код аннулирования от http://zenit.senecac.on.ca/wiki/index.php/Support_For_OpenID.

см. http://mxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsIRequest.idl для получения более подробной информации о nsIRequest.

См. http://forums.mozillazine.org/viewtopic.php?p=2404533#p2404533 и https://developer.mozilla.org/en/XUL/Method/addTab для определения addTab.

parseQuery исходит из http://blog.strictly-software.com/2008/10/using-javascript-to-parse-querystring.html.

См. https://developer.mozilla.org/en/Code_snippets/Post_data_to_window#Preprocessing_POST_data о том, как обрабатывать данные почтового отправления в форме, подходящей для addTab.

ReadPostFromText и ReadTextFromStream оба из поджигатель (хотя немного изменен)

+0

Эй, это отлично! Прямо сейчас я пытаюсь выяснить, как определить, пришел ли запрос из моего элемента xul: browser. У меня на самом деле есть несколько элементов xul: browser в любой момент времени, и я хотел бы перехватить запросы от всех из них. Возможно ли, что я могу просто указать каждому элементу браузера одно и то же имя класса: new_browser_element.setAttribute ('class', 'mini_browser'); И тогда: if (DOMWindow.attr ('class') == 'mini_browser') .... Очевидно, что это неверно, но будет ли это имя класса содержать внутри объекта DOMWindow? – makeee

+0

Возможно, вам понадобится jQuery (DOMWindow) .hasClass ('mini_browser'). Я подозреваю, что вам нужно будет использовать jQuery() для доступа к методу hasClass –

+0

добавленные данные передачи данных и проверка класса мини-браузера –

Смежные вопросы