Javascript 如何确定Firefox浏览器中的哪个选项卡将发出http请求
我目前正在尝试构建一个firefox扩展,它基于正则表达式为每个http请求确定一个代理。用于加载页面的代理应该记住来自该页面的任何新请求,即该页面所需的任何图像/脚本/css文件、任何传出链接或ajax请求。这也意味着每个打开的选项卡都需要记住代理。 这就是我遇到问题的地方:到目前为止,我试图通过插入一个唯一的id作为选项卡浏览器元素的属性来标记每个打开的选项卡,并在nsiContentPolicy的shoulLoad()方法的实现中查找该id。我用于此目的的代码如下所示,它是从tabs/utils.js中的插件sdk的getTabForContentWindow方法中提取的Javascript 如何确定Firefox浏览器中的哪个选项卡将发出http请求,javascript,firefox,firefox-addon,Javascript,Firefox,Firefox Addon,我目前正在尝试构建一个firefox扩展,它基于正则表达式为每个http请求确定一个代理。用于加载页面的代理应该记住来自该页面的任何新请求,即该页面所需的任何图像/脚本/css文件、任何传出链接或ajax请求。这也意味着每个打开的选项卡都需要记住代理。 这就是我遇到问题的地方:到目前为止,我试图通过插入一个唯一的id作为选项卡浏览器元素的属性来标记每个打开的选项卡,并在nsiContentPolicy的shoulLoad()方法的实现中查找该id。我用于此目的的代码如下所示,它是从tabs/ut
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
即为空
我已经研究了上所述的拦截页面加载的其他机制,但这些机制似乎不适合我想要实现的目标,因为据我所知,它们适用于HTTP请求,并且对于存在的请求,已经需要确定代理
因此,如果有人知道一种方法来在即将到来的负载变成请求之前捕获它们,同时,可以找出哪个选项卡负责这些负载,我很高兴他们能在回答中告诉我!提前谢谢
当然,这只是http/https。我不确定你是否还能在这一点上摆弄代理。哦,并不是每个
nsILoadContext
都有一个associatedWindow
(或者topWindow
),所以最好改进错误处理嘿@pmuench在这里查看更好的错误处理版本:哦,等等@namaier我现在很困惑,在哪些情况下loaddcontext没有关联的窗口?如果它加载在选项卡中,它总是有关联的窗口,对吗?如果它没有加载到选项卡中,那么它甚至不应该具有loadcontext权限?文档(在idl中)状态可能为空。这就是合同。其中,只有一个可能返回窗口,1个确实返回null(webapps.jsm),2个始终抛出(LoadContext、OfflineCacheUpdateParent,两个都是e10)。此外,附加组件可以根据合同自由实现接口并返回null(例如Lightning就是这样做的)。有时候我不应该这么匆忙。当在打开请求时使用http而不是http-on-modify-request时,它会起作用。如下面对Noitidart建议的评论所述,在修改请求事件时侦听http并不能解决问题,因为事件是在确定请求的代理后触发的。但是,在打开请求事件时侦听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
}
}
}
};