感謝大家提前!關於在完成之前停止nsIRequest並確定nsIRequest何時完成(Firefox擴展)
我正在使用一個xul:瀏覽器並將一個nsIWebProgressListener附加到它。我試圖完成兩件事情: 1.確定請求何時完成(文檔完全加載所有css/js/imgs時)。 2.停止完成請求,特別是包含發佈下載提示的文件的URL。
關於我的第一個問題,因爲aStateFlags參數在nsIWebProgressListener.onStateChange()中設置爲(STATE_IS_ * | STATE_STOP)並且被多次調用,所以無法確定請求何時完成,並且存在沒有更多的狀態改變。這是如何完成的?
我正在嘗試完成具體與我遇到的第二個問題是當找到某個「內容類型」標頭值時終止請求。例如,如果找到「應用程序/ pdf」內容類型,如果請求被終止,那麼下載提示(根據我的理解,它不是nsIDownloadManager的一部分)從不顯示 - 這是我想要完成的確切行爲。
這裏是nsIWebProgressListener代碼我目前的工作:
//setup progress listener
var progressListener = {
stateIsRequest:false,
methodCalled:"",
WebProgress:"",
Request:"",
Flag:"",
Status:"",
Location:"",
CurSelfProgress:"",
MaxSelfProgress:"",
CurTotalProgress:"",
MaxTotalProgress:"",
Message:"",
State:"",
QueryInterface : function(aIID) {
if(aIID.equals(Components.interfaces.nsIWebProgressListener) || aIID.equals(Components.interfaces.nsISupportsWeakReference) || aIID.equals(Components.interfaces.nsISupports)){
return this;
}
else{
throw Components.results.NS_NOINTERFACE;
}
},
onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) {
this.methodCalled = "onStateChange";
this.WebProgress = aWebProgress;
this.Request = aRequest;
this.Flag = aFlag;
this.Status = aStatus;
this.Location = "";
this.CurSelfProgress = "";
this.MaxSelfProgress = "";
this.CurTotalProgress = "";
this.MaxTotalProgress = "";
this.Message = "";
this.State = "";
this.CaptureHeaders(aRequest);
},
onLocationChange : function(aWebProgress, aRequest, aLocation) {
this.methodCalled = "onLocationChange";
this.WebProgress = aWebProgress;
this.Request = aRequest;
this.Flag = "";
this.Status = "";
this.Location = aLocation;
this.CurSelfProgress = "";
this.MaxSelfProgress = "";
this.CurTotalProgress = "";
this.MaxTotalProgress = "";
this.Message = "";
this.State = "";
this.CaptureHeaders(aRequest);
},
onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress){
this.methodCalled = "onProgressChange";
this.WebProgress = aWebProgress;
this.Request = aRequest;
this.Flag = "";
this.Status = "";
this.Location = "";
this.CurSelfProgress = aCurSelfProgress;
this.MaxSelfProgress = aMaxSelfProgress;
this.CurTotalProgress = aCurTotalProgress;
this.MaxTotalProgress = aMaxTotalProgress;
this.Message = "";
this.State = "";
this.CaptureHeaders(aRequest);
},
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage){
this.methodCalled = "onStatusChange";
this.WebProgress = aWebProgress;
this.Request = aRequest;
this.Flag = "";
this.Status = aStatus;
this.Location = "";
this.CurSelfProgress = "";
this.MaxSelfProgress = "";
this.CurTotalProgress = "";
this.MaxTotalProgress = "";
this.Message = aMessage;
this.State = "";
this.CaptureHeaders(aRequest);
},
onSecurityChange : function(aWebProgress, aRequest, aState){
this.methodCalled = "onSecurityChange";
this.WebProgress = aWebProgress;
this.Request = aRequest;
this.Flag = "";
this.Status = "";
this.Location = "";
this.CurSelfProgress = "";
this.MaxSelfProgress = "";
this.CurTotalProgress = "";
this.MaxTotalProgress = "";
this.Message = "";
this.State = aState;
this.CaptureHeaders(aRequest);
},
onLinkIconAvailable : function(a){},
CaptureHeaders : function(ThisRequest){
try{
//specify response headers to get
var ResponseHeaders = new Array();
ResponseHeaders.push("status");
ResponseHeaders.push("data");
ResponseHeaders.push("server");
ResponseHeaders.push("content-language");
ResponseHeaders.push("content-encoding");
ResponseHeaders.push("content-length");
ResponseHeaders.push("expires");
ResponseHeaders.push("cache-control");
ResponseHeaders.push("keep-alive");
ResponseHeaders.push("status");
ResponseHeaders.push("connection");
ResponseHeaders.push("content-type");
ResponseHeaders.push("set-cookie");
//specify request headers to get
var RequestHeaders = new Array();
RequestHeaders.push("host");
RequestHeaders.push("user-agent");
RequestHeaders.push("accept");
RequestHeaders.push("accept-language");
RequestHeaders.push("accept-encoding");
RequestHeaders.push("accept-charset");
RequestHeaders.push("keep-alive");
RequestHeaders.push("connection");
RequestHeaders.push("cookie");
RequestHeaders.push("cache-control");
//get browser
var CurrentBrowser = document.getElementById("current_browser");
//var CurrentURL = CurrentBrowser.current_url;
//var CurrentURL = ThisRequest.nsIHttpChannel.originalURI.spec;
if(ThisRequest.nsIHttpChannel != undefined){
var CurrentURL = ThisRequest.nsIHttpChannel.originalURI.spec;
//is this the first time headers were created for this browser?
if(CurrentBrowser.headers instanceof Object){
//have we collected headers for this url before
if(CurrentBrowser.headers[CurrentURL] instanceof Object){
//do nothing
}
else{
CurrentBrowser.headers[CurrentURL] = new Object();
CurrentBrowser.headers[CurrentURL].request = new Object();
CurrentBrowser.headers[CurrentURL].response = new Object()
}
}
else{
CurrentBrowser.headers = new Object();
CurrentBrowser.headers[CurrentURL] = new Object();
CurrentBrowser.headers[CurrentURL].request = new Object();
CurrentBrowser.headers[CurrentURL].response = new Object()
}
//load up headers
//add response headers
for(i = 0; i < ResponseHeaders.length; i++){
try{
if(ResponseHeaders[i] == "status"){
CurrentBrowser.headers[CurrentURL].response[ResponseHeaders[i]] = ThisRequest.nsIHttpChannel.responseStatus;
}
else{
CurrentBrowser.headers[CurrentURL].response[ResponseHeaders[i]] = ThisRequest.nsIHttpChannel.getResponseHeader(ResponseHeaders[i]);
}
}
catch(e){}
}
//add request headers
for(i = 0; i < RequestHeaders.length; i++){
try{
CurrentBrowser.headers[CurrentURL].request[RequestHeaders[i]] = ThisRequest.nsIHttpChannel.getRequestHeader(RequestHeaders[i]);
}
catch(e){}
}
//end load up headers
/*
Completed flag - STATE_IS_REQUEST:65552
Completed flag - STATE_IS_DOCUMENT:131088
Completed flag - STATE_IS_NETWORK:262160
Completed flag - STATE_IS_WINDOW:524304
//CurrentBrowser.webNavigation.nsIWebNavigation.stop(1);
//CurrentBrowser.webNavigation.nsIWebNavigation.stop(2);
//CurrentBrowser.webNavigation.nsIWebNavigation.stop(3);
//CurrentBrowser.stop();
//ThisRequest.cancel(2152398850);
//ThisRequest.cancel(Components.results.NS_OK);
//ThisRequest.suspend();
*/
//setup nonload rules
if(CurrentBrowser.headers[CurrentURL].response["content-type"] == "application/zip"){
MyExtension.WriteToDebug("Cancelled Request: "+ CurrentURL);
//try multiple ways to terminate the request
if(ThisRequest.nsIHttpChannel.loadGroup.activeCount > 0){
ThisRequest.nsIHttpChannel.loadGroup.removeRequest(ThisRequest, ThisRequest, Components.results.NS_BINDING_ABORTED);
}
CurrentBrowser.webNavigation.nsIWebNavigation.stop(1);
CurrentBrowser.webNavigation.nsIWebNavigation.stop(2);
CurrentBrowser.webNavigation.nsIWebNavigation.stop(3);
CurrentBrowser.stop();
ThisRequest.cancel(Components.results.NS_OK);
//end try multiple ways to terminate the request
//after request is terminated execute onNONload
CurrentBrowser.OnNonLoad(CurrentURL);
}
//setup nonload rules
else if(CurrentBrowser.headers[CurrentURL].response["content-type"] == "application/pdf"){
MyExtension.WriteToDebug("Cancelled Request: "+ CurrentURL);
//try multiple ways to terminate the request
if(ThisRequest.nsIHttpChannel.loadGroup.activeCount > 0){
ThisRequest.nsIHttpChannel.loadGroup.removeRequest(ThisRequest, ThisRequest, Components.results.NS_BINDING_ABORTED);
}
CurrentBrowser.webNavigation.nsIWebNavigation.stop(1);
CurrentBrowser.webNavigation.nsIWebNavigation.stop(2);
CurrentBrowser.webNavigation.nsIWebNavigation.stop(3);
CurrentBrowser.stop();
ThisRequest.cancel(Components.results.NS_OK);
//end try multiple ways to terminate the request
//after request is terminated execute onNONload
CurrentBrowser.OnNonLoad(CurrentURL);
}
//determine if finished loading
else if(this.Flag == 65552 || this.Flag == 131088 || this.Flag == 262160 || this.Flag == 524304){
MyExtension.WriteToDebug("Request Completed!");
MyExtension.WriteToDebug("pending:"+ ThisRequest.isPending() +"<br/>name:"+ ThisRequest.name +"<br/>URL:"+ CurrentURL +"<br/>content-type:"+ CurrentBrowser.headers[CurrentURL].response["content-type"]+"<br/>status:"+ CurrentBrowser.headers[CurrentURL].response["status"]);
if(this.Flag == (Components.interfaces.nsIWebProgressListener.STATE_IS_REQUEST | Components.interfaces.nsIWebProgressListener.STATE_STOP)){
MyExtension.WriteToDebug("Completed flag - STATE_IS_REQUEST:"+ (Components.interfaces.nsIWebProgressListener.STATE_IS_REQUEST | Components.interfaces.nsIWebProgressListener.STATE_STOP));
}
if(this.Flag == (Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT | Components.interfaces.nsIWebProgressListener.STATE_STOP)){
MyExtension.WriteToDebug("Completed flag - STATE_IS_DOCUMENT:"+ (Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT | Components.interfaces.nsIWebProgressListener.STATE_STOP));
}
if(this.Flag == (Components.interfaces.nsIWebProgressListener.STATE_IS_NETWORK | Components.interfaces.nsIWebProgressListener.STATE_STOP)){
MyExtension.WriteToDebug("Completed flag - STATE_IS_NETWORK:"+ (Components.interfaces.nsIWebProgressListener.STATE_IS_NETWORK | Components.interfaces.nsIWebProgressListener.STATE_STOP));
}
if(this.Flag == (Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW | Components.interfaces.nsIWebProgressListener.STATE_STOP)){
MyExtension.WriteToDebug("Completed flag - STATE_IS_WINDOW:"+ (Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW | Components.interfaces.nsIWebProgressListener.STATE_STOP));
}
//MyExtension.WriteToDebug("methodCalled:"+ this.methodCalled);
//MyExtension.WriteToDebug("WebProgress:"+ this.WebProgress);
//MyExtension.WriteToDebug("Request:"+ this.Request);
MyExtension.WriteToDebug("Flag:"+ this.Flag);
//MyExtension.WriteToDebug("Status:"+ this.Status);
//MyExtension.WriteToDebug("Location:"+ this.Location);
//MyExtension.WriteToDebug("CurSelfProgress:"+ this.CurSelfProgress);
//MyExtension.WriteToDebug("MaxSelfProgress:"+ this.MaxSelfProgress);
//MyExtension.WriteToDebug("CurTotalProgress:"+ this.CurTotalProgress);
//MyExtension.WriteToDebug("MaxTotalProgress:"+ this.MaxTotalProgress);
//MyExtension.WriteToDebug("Message:"+ this.Message);
//MyExtension.WriteToDebug("State:"+ this.State);
MyExtension.WriteToDebug("Load group count:"+ ThisRequest.nsIHttpChannel.loadGroup.activeCount);
MyExtension.WriteToDebug("WebProgress.isLoadingDocument:"+ this.WebProgress.isLoadingDocument);
MyExtension.WriteToDebug("WebProgress.DOMWindow:"+ this.WebProgress.DOMWindow);
//execute non load
//CurrentBrowser.OnNonLoad(CurrentURL);
}
}
}
catch(e){
MyExtension.WriteToDebug("Error Name:"+ e.name +" Message:"+ e.message);
}
}
};
//add progress listener
ThisBrowser.addProgressListener(progressListener);
//end setup progress listener
https://developer.mozilla.org/en/nsIWebProgressListener
感謝您的答覆 - 大加讚賞 1.那是相當接近我在做什麼已經 - 這好像與STATE_STOP是onStateChange | STATE_IS_NETWORK被多次調用所以它不可能確定過程是否完全完成 2.我實際上是在深入挖掘nsIObserverService,有兩個問題:這個nsIObserverService是否「觀察」所有標籤頁/瀏覽器的所有請求?什麼是終止請求的正確方法 - 如果您查看我的代碼,您可以看到我用來停止請求的所有不同方法,那是正確的嗎? 謝謝,sam – 2010-02-11 21:53:04
關於nsIObserverService,我唯一知道的是我爲firefox擴展編寫的代碼,用於監控gmail請求並從中提取和解析數據。查看這個要點(http://gist.github.com/306052),瞭解您感興趣的兩個文件的內容,或下載擴展名(自從我上次使用該擴展名以來已經修改了很多)。關於你的問題,nsIObserverService是一個全球性的觀察者,所以一旦掛鉤,你就全部設置好了。 – warhammerkid 2010-02-16 23:03:34
@warhammerkid當然取決於應用程序,但nsIObserverService + http-on-modify-request的問題在於,它加載了_each_ http請求 - 每頁多次 - 這可能會降低應用程序的速度。 – egbutter 2012-10-21 18:04:42