Firefox addon 自定义xul:浏览器中页面加载的观察者
在我的firefox扩展中,我创建了一个xul:browser元素。我希望有一个观测者可以截取嵌入式浏览器中的任何url更改,并在新的浏览器选项卡(在主浏览器中)中打开url。我还希望由xul:browser窗口生成的新窗口在选项卡中打开,而不是在新的浏览器窗口中打开 我已经创建了一个可以工作的观察者,但我还不知道如何将该观察者仅应用于xul:browser元素Firefox addon 自定义xul:浏览器中页面加载的观察者,firefox-addon,Firefox Addon,在我的firefox扩展中,我创建了一个xul:browser元素。我希望有一个观测者可以截取嵌入式浏览器中的任何url更改,并在新的浏览器选项卡(在主浏览器中)中打开url。我还希望由xul:browser窗口生成的新窗口在选项卡中打开,而不是在新的浏览器窗口中打开 我已经创建了一个可以工作的观察者,但我还不知道如何将该观察者仅应用于xul:browser元素 function myFunction(){ var container = jQuery("#container")[0];
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;
}
};
你可以试试:
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;
}
我会更新这个来填补一些空白
编辑:有关如何获取请求的源窗口,请参阅
从中请求取消代码
有关请求的详细信息,请参阅
有关addTab的定义,请参见和
parseQuery来自
有关如何以适合addTab的形式处理post数据的信息,请参阅
ReadPostFromText和ReadTextFromStream都来自firebug(尽管略有修改)您可以尝试:
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;
}
我会更新这个来填补一些空白
编辑:有关如何获取请求的源窗口,请参阅
从中请求取消代码
有关请求的详细信息,请参阅
有关addTab的定义,请参见和
parseQuery来自
有关如何以适合addTab的形式处理post数据的信息,请参阅
ReadPostFromText和ReadTextFromStream都来自firebug(虽然略有修改)因此,基本上,您希望检查请求发起的上下文,然后取消它,并告诉浏览器打开一个包含上一个请求的url和标题的新选项卡?(我认为没有办法在请求启动后更改其目标,但我会查看)是的,这正是我想要做的。基于“修改请求时使用http”的解决方案不观察URL更改,而是观察http加载。对于URL更改,您需要一个进度侦听器。因此,基本上,您希望检查发出请求的上下文,然后取消它,并告诉浏览器打开一个包含上一个请求的URL和标题的新选项卡?(我认为没有办法在请求启动后更改其目标,但我会查看)是的,这正是我想要做的。基于“修改请求时使用http”的解决方案不观察URL更改,而是观察http加载。对于URL更改,您需要一个进度侦听器。嘿,这看起来很棒!现在我正试图弄清楚如何判断请求是否来自我的xul:browser元素。实际上,我在任何给定的时间都有许多xul:browser元素,我希望截获所有这些元素的请求。我是否可以给每个浏览器元素赋予相同的类名:new_browser_element.setAttribute('class','mini_browser');然后:if(DOMWindow.attr('class')=='mini_browser')。。。。显然这是不正确的,但是这个类名会包含在“DOMWindow”对象中吗?您可能需要jQuery(DOMWindow).hasClass('mini_browser')。我想您需要使用jQuery()来访问hasClass methodadded post数据传递和minibrowser类checkCool,非常接近实现这一点。几个快速问题:是否应该是(aTopic==“修改请求时的http”)。。?现在,您的代码还将把嵌入页面中的图像加载到一个新选项卡中,因为http on modify请求包括所有请求,而不仅仅是页面url。你知道如何把它限制在主页url上吗?谢谢!我编写了一个Jetpack附加组件,希望在打开/关闭浏览器窗口时得到一个回调。我尝试使用nsIWindowWatcher、nsIWindowMediator、主题为“DomWindowOpened”的nsIObserverService和主题为“DomWindowOpened”的Jetpack ObserverService,这是一种具有相同主题和Jetpacks WindowTracker类的Jetpack observer服务,但没有任何效果。还有别的方法吗?我的代码(在DBAIServer.start的底部):嘿,这看起来很棒!现在我正试图弄清楚如何判断请求是否来自我的xul:browser元素。实际上,我在任何给定的时间都有许多xul:browser元素,我希望截获所有这些元素的请求。我是否可以给每个浏览器元素赋予相同的类名:new_browser_element.setAttribute('class','mini_browser');然后:if(DOMWindow.attr('class')=='mini_browser')。。。。显然这是不正确的,但是这个类名会包含在“DOMWindow”对象中吗?您可能需要jQuery(DOMWindow).hasClass('mini_browser')。我想您需要使用jQuery()来访问hasClass methodadded post数据传递和minibrowser类checkCool,非常接近实现这一点。几个快速问题:是否应该是(aTopic==“修改请求时的http”)。。?现在,您的代码还将把嵌入页面中的图像加载到一个新选项卡中,因为http on modify请求包括所有请求,而不仅仅是页面url。你知道如何把它限制在主页url上吗?谢谢!我编写了一个Jetpack附加组件,希望在打开/关闭浏览器窗口时得到一个回调。我尝试使用nsIWindowWatcher、nsIWindowMediator、主题为“DomWindowOpened”的nsIObserverService和主题为“DomWindowOpened”的Jetpack ObserverService,这是一种具有相同主题和Jetpacks WindowTracker类的Jetpack observer服务,但没有任何效果。还有别的方法吗?我的代码(在DBAIServer.start的底部附近):