2010-02-11 39 views
0

感謝大家提前!關於在完成之前停止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

我在一個相當懶惰此刻的心情,所以我不能說,我已經做了很多研究...

問題1:
爲什麼不直接掛載到loadDocument的load事件。如果contentDocument不早暴露,然後用下面的代碼,看看它是否是可用的,那麼:

Listener.prototype.onStateChange = function(webProgress, request, stateFlags, status) { 
    if(stateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP && stateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_NETWORK) { 
     // Should be ready now.... please? 
    } 
}; 

問題2:
我不知道你想這個怎麼做它涉及到xul:瀏覽器,但是一個非常全面的方法是掛鉤到nsIObserverService中以便進行http-on-modify-request並在那裏取消請求。

+0

感謝您的答覆 - 大加讚賞 1.那是相當接近我在做什麼已經 - 這好像與STATE_STOP是onStateChange | STATE_IS_NETWORK被多次調用所以它不可能確定過程是否完全完成 2.我實際上是在深入挖掘nsIObserverService,有兩個問題:這個nsIObserverService是否「觀察」所有標籤頁/瀏覽器的所有請求?什麼是終止請求的正確方法 - 如果您查看我的代碼,您可以看到我用來停止請求的所有不同方法,那是正確的嗎? 謝謝,sam – 2010-02-11 21:53:04

+0

關於nsIObserverService,我唯一知道的是我爲firefox擴展編寫的代碼,用於監控gmail請求並從中提取和解析數據。查看這個要點(http://gist.github.com/306052),瞭解您感興趣的兩個文件的內容,或下載擴展名(自從我上次使用該擴展名以來已經修改了很多)。關於你的問題,nsIObserverService是一個全球性的觀察者,所以一旦掛鉤,你就全部設置好了。 – warhammerkid 2010-02-16 23:03:34

+0

@warhammerkid當然取決於應用程序,但nsIObserverService + http-on-modify-request的問題在於,它加載了_each_ http請求 - 每頁多次 - 這可能會降低應用程序的速度。 – egbutter 2012-10-21 18:04:42

1

對於在未來這個問題的人......

這是一個體面的例子開始:https://developer.mozilla.org/en-US/docs/Code_snippets/Progress_Listeners#Example

一個恕我直言,更清潔的例子,照顧添加/刪除ProgressListeners作爲標籤打開和關閉的(防止內存泄漏)可在此處獲得:http://mdn.beonex.com/en/XUL_School/Intercepting_Page_Loads

只有使用STATE_IS_DOCUMENT和STATE_STOP,每個URI請求才會得到一個結果:用於加載最終頁面。

如果您想測試一個URL,您需要取消aLocation.spec和aRequest,以便您可以發出aRequest.cancel(NS_BINDING_ABORTED),您將需要獲取aLocation。您可以通過使用添加一些XUL的WebProgress.DOMWindow並重新加載來加載頁面。

HTH,

埃裏克

相關問題