如何确定Firefox浏览器中的哪个选项卡将发出http请求

How to determine which Tab in Firefox Browser is about to make a http request

本文关键字:请求 http 选项 Firefox 何确定 浏览器      更新时间:2023-09-26

我目前正在尝试构建一个firefox扩展,该扩展基于正则表达式为每个http请求确定一个代理。用于加载页面的代理应该记住来自该页面的任何新请求,即该页面所需的任何图像/script/css文件、任何传出链接或ajax请求。这也意味着每个打开的选项卡都需要记住代理。这就是我遇到问题的地方:到目前为止,我试图通过插入一个唯一的id作为选项卡的浏览器元素的属性来标记每个打开的选项卡,并在nsiContentPolicy的shouldLoad()方法的实现中查找该id。我为此使用的代码如下所示,它是从tabs/utils.js.中的addon-sdk的getTabForContentWindow方法中提取的

shouldLoad: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra)
  {
      var tabId = null;
      if (!(context instanceof CI.nsIDOMWindow))
      {
        // If this is an element, get the corresponding document
        if (context instanceof CI.nsIDOMNode && context.ownerDocument)
          context = context.ownerDocument;
        // Now we should have a document, get its window
        if (context instanceof CI.nsIDOMDocument)
          context = context.defaultView;
        else
          context = null;
      }
      let browser;
      try {
        browser = context.QueryInterface(CI.nsIInterfaceRequestor)
                        .getInterface(CI.nsIWebNavigation)
                        .QueryInterface(CI.nsIDocShell)
                        .chromeEventHandler;
      } catch(e) {
        this.console.log(e);
      }
      let chromeWindow = browser.ownerDocument.defaultView;
      if ('gBrowser' in chromeWindow && chromeWindow.gBrowser &&
           'browsers' in chromeWindow.gBrowser) {
      let browsers = chromeWindow.gBrowser.browsers;
      let i = browsers.indexOf(browser);
      if (i !== -1)
        tabId = chromeWindow.gBrowser.tabs[i].getAttribute("PMsMark");
      }     
    return CI.nsIContentPolicy.ACCEPT;
  }

这适用于任何不更改所显示文档的加载,但只要文档发生更改(即加载新页面),变量browser就会为null。

我已经研究了上描述的其他拦截页面加载的机制https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Intercepting_Page_Loads,但这些似乎不适合我想要实现的目标,因为据我所知,它们处理HTTP请求,并且为了使请求存在,代理已经需要确定。

因此,如果有人知道在即将加载的负载成为请求之前捕捉它们的方法,同时有可能找出哪些选项卡负责这些负载,我很高兴他们能在答案中告诉我!提前感谢!

https://developer.mozilla.org/en-US/docs/Code_snippets/Tabbed_browser#Getting_the_browser_that_fires_the_http-修改请求通知

Components.utils.import('resource://gre/modules/Services.jsm');
Services.obs.addObserver(httpObs, 'http-on-opening-request', false);
//Services.obs.removeObserver(httpObs, 'http-on-modify-request'); //uncomment this line, or run this line when you want to remove the observer
var httpObs = {
    observe: function (aSubject, aTopic, aData) {
        if (aTopic == 'http-on-opening-request') {
            /*start - do not edit here*/
            var oHttp = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel); //i used nsIHttpChannel but i guess you can use nsIChannel, im not sure why though
            var interfaceRequestor = oHttp.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
            //var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); //not to be done anymore because: https://developer.mozilla.org/en-US/docs/Updating_extensions_for_Firefox_3.5#Getting_a_load_context_from_a_request //instead do the loadContext stuff below
            var loadContext;
            try {
                loadContext = interfaceRequestor.getInterface(Components.interfaces.nsILoadContext);
            } catch (ex) {
                try {
                    loadContext = aSubject.loadGroup.notificationCallbacks.getInterface(Components.interfaces.nsILoadContext);
                    //in ff26 aSubject.loadGroup.notificationCallbacks was null for me, i couldnt find a situation where it wasnt null, but whenever this was null, and i knew a loadContext is supposed to be there, i found that "interfaceRequestor.getInterface(Components.interfaces.nsILoadContext);" worked fine, so im thinking in ff26 it doesnt use aSubject.loadGroup.notificationCallbacks anymore, but im not sure
                } catch (ex2) {
                    loadContext = null;
                    //this is a problem i dont know why it would get here
                }
            }
            /*end do not edit here*/
            /*start - do all your edits below here*/
            var url = oHttp.URI.spec; //can get url without needing loadContext
            if (loadContext) {
                var contentWindow = loadContext.associatedWindow; //this is the HTML window of the page that just loaded
                //aDOMWindow this is the firefox window holding the tab
                var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
                var gBrowser = aDOMWindow.gBrowser; //this is the gBrowser object of the firefox window this tab is in
                var aTab = gBrowser._getTabForContentWindow(contentWindow.top); //this is the clickable tab xul element, the one found in the tab strip of the firefox window, aTab.linkedBrowser is same as browser var above //can stylize tab like aTab.style.backgroundColor = 'blue'; //can stylize the tab like aTab.style.fontColor = 'red';
                var browser = aTab.linkedBrowser; //this is the browser within the tab //this is what the example in the previous section gives
                //end getting other useful stuff
            } else {
                Components.utils.reportError('EXCEPTION: Load Context Not Found!!');
                //this is likely no big deal as the channel proably has no associated window, ie: the channel was loading some resource. but if its an ajax call you may end up here
            }
        }
    }
};