Подтвердить что ты не робот

Запрос перенаправления (nsiHttpChannel?) В расширениях Firefox

Я пробовал это уже давно, и никаких хороших результатов не было.

var myObserver = {
    observe: function(subject, topic, data)
    {
        if (topic == "http-on-examine-response") 
        {   
             //  implement later
        } 
        else if(topic == "http-on-modify-request") 
        {
             //  implement later
        }
   },

   QueryInterface : function (id)
   {
       if (id.equals(Components.interfaces["nsIObserver"]) ||
           id.equals(Components.interfaces["nsISupports"]))
       {
           return this;
       }
       throw Components.results.NS_NOINTERFACE;
   }
};

var obs = new Service("observer-service", "ObserverService");
obs.addObserver(myObserver, "http-on-modify-request", false);

В принципе, на http-on-modify-request, я знаю, как исследовать URI, выяснить, какое окно (если есть) связано с ним, и множество других вещей. Я не могу понять, как перенаправить запрос, который, как я знаю, возможен отсюда, потому что я могу получить nsIHttpChannel до того, как любой запрос будет отправлен.

Кто-нибудь знает, что делать?:/Я пробовал пару недель вкл./Выкл., И не получил нигде.

4b9b3361

Ответ 1

Мы можем сделать это, переопределив nsiHttpChannel новым, делая это немного сложно, но, к счастью, надстройка https-everywhere реализует это, чтобы принудительно установить https-соединение.

https-everywhere доступен исходный код here

Большая часть кода, необходимого для этого, находится в файлах

[IO Util.js] [ChannelReplacement.js]

Мы можем работать только с вышеуказанными файлами, если у нас есть основные переменные, такие как Cc, Ci, и определена функция xpcom_generateQI.

var httpRequestObserver =
{ 
  observe: function(subject, topic, data) {
    if (topic == "http-on-modify-request") {

        var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);     
        var requestURL = subject.URI.spec;

        if(isToBeReplaced(requestURL))  {

            var newURL = getURL(requestURL);        
             ChannelReplacement.runWhenPending(subject, function() {
                    var cr = new ChannelReplacement(subject, ch);
                    cr.replace(true,null);
                    cr.open();
                });
        }
    }

  },

  get observerService() {
    return Components.classes["@mozilla.org/observer-service;1"]
                     .getService(Components.interfaces.nsIObserverService);
  },

  register: function() {
    this.observerService.addObserver(this, "http-on-modify-request", false);

  },

  unregister: function() {
    this.observerService.removeObserver(this, "http-on-modify-request");

  }
};


httpRequestObserver.register();

В коде заменить запрос не перенаправляется.

Хотя я достаточно хорошо проверил приведенный выше код, я не уверен в его реализации. Пока я могу разобрать, он копирует все атрибуты запрашиваемого канала и устанавливает их на переопределяемый канал. После чего какой-то выход, запрошенный исходным запросом, подается с использованием нового канала.

P.S. Я видел сообщение SO, в котором был предложен этот подход.

Ответ 2

У меня создается впечатление, что вы не можете сделать это на этом уровне - я пробовал различные методы внешне "обманывать" код, который требует создания nsIHttpChannel (пример в конце сообщения).

Я бы рекомендовал, если вы хотите перенаправить, обратитесь в окно владельца канала (что работает 99% времени) и попросите его перенаправить. Я знаю, что это не будет вести себя одинаково, но поскольку я точно не знаю, почему вы это делаете, это будет внешне (для пользователя), похоже, делает то же самое, что и вы.

Вот основы того, что я пытался:

if(aTopic == "http-on-examine-response") {                                                                                     
            var request = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);                                                      

            if(!request.URI.spec.match("^http://www.apple.com/")) {                                                          
                var ios = Components.classes["@mozilla.org/network/io-service;1"]                                                             
                    .getService(Components.interfaces.nsIIOService);                                                                          
                var ch = ios.newChannel("http://www.apple.com/", null, null);                                                                 

                var listener = {                                                                                                              
                    QueryInterface : XPCOMUtils.generateQI([Ci.nsIChannelEventSink]),                                                         
                    onDataAvailable: function() {},                                                                                           
                    onStopRequest: function() {},                                                                                             
                    onStartRequest: function() {}                                                                                             
                };                                                                                                                            

                ch.asyncOpen(listener,null);                                                                                                  

                var eventSink = request.notificationCallbacks.getInterface(Ci.nsIChannelEventSink);                                           
                eventSink.asyncOnChannelRedirect(request,ch,Ci.nsIChannelEventSink.REDIRECT_INTERNAL,function() {});                          
            } 

Ответ 3

Я сделал это следующим образом: stop nsIHttpChannel on "http-on-modify-request" событие, получить объект браузера для текущего окна, вызвать browser.loadURI.

var utils = require("sdk/window/utils");

function needsRedirect(url) {
    // to be implemented
    return true;
}

function generateNewUrl(url) {
    // to be implemented
    return "http://www.example.com/";
}

Cc["@mozilla.org/observer-service;1"]
    .getService(Ci.nsIObserverService)
    .addObserver({
        observe: function(subject, topic, data) {
            var channel = subject.QueryInterface(Ci.nsIHttpChannel);
            var url = channel.originalURI.spec;
            if (needsRedirect(url)) {
                //stop
                channel.cancel(Cr.NS_BINDING_ABORTED);

                //redirect
                var gBrowser = utils.getMostRecentBrowserWindow().gBrowser;
                var domWin = channel.notificationCallbacks.getInterface(Ci.nsIDOMWindow);
                var browser = gBrowser.getBrowserForDocument(domWin.top.document);
                browser.loadURI(generateNewUrl(url));

            }
        }
    }, "http-on-modify-request", false);

Ответ 4

Во время тестирования чего-то я создал сжатую версию (см. этот смысл) логики замены канала, упомянутой в других ответах.

Общая идея состоит в том, чтобы передать все критические свойства на новый канал, удалить обратные вызовы из старого канала, чтобы манипуляции не прерывали загрузку страницы, а затем закрывали старый канал.

С некоторыми изменениями можно изменить URI страницы для загрузки документов или оставить его как есть.

Предупреждение: это был просто быстрый взлом, чтобы загрузить несколько страниц, я не тестировал его в глубину, и он, вероятно, сломается для некоторых случаев. Я подозреваю, что есть причины, по которым HTTPS Everywhere является более сложным.