| « nsIWebBrowserPersist の基本的な使い方 (4) ~ POST メソッド | [Exception… “‘Component is not available’ when calling method: [nsIHandlerService::getTypeFromExtension] » |
nsIWebBrowserPersist の基本的な使い方 (5) ~ ダウンロード進捗状況
nsIWebBrowserPersist で HTTP によってダウンロードする際、ダウンロードの進捗状況を監視する。
サンプルコードは nsIWebBrowserPersist の基本的な使い方 (1) ~ 基本形 をベースとしており、一部省略しています。
saveURI の場合
nsIWebBrowserPersist の progressListener プロパティに nsIWebProgressListener インタフェースを実装したオブジェクトを自前で作成してセットすると、ダウンロードの状況の変化によって以下のメソッドが呼び出される。
| メソッド名 | 呼び出されるタイミング |
|---|---|
| onStateChange | 引数 aStateFlags の値を調べ、 nsIWebProgressListener.STATE_START フラグが立っている場合はダウンロード開始、 nsIWebProgressListener.STATE_STOP フラグが立っている場合はダウンロード終了。 |
| onProgressChange | ダウンロード進行中に呼び出される。引数 aCurSelfProgress, aMaxSelfProgress の値を調べることで、合計何バイト中の何バイトをダウンロードしたかがわかる。 |
| onLocationChange | 呼び出し無し。(xul:tabbrowser 要素の持つ nsIWebProgress オブジェクト専用?) |
| onStatusChange | |
| onSecurityChange |
wbp.progressListener = {
// implements nsIWebProgressListener
onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START)
dump("started
");
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
dump("stopped
");
},
onProgressChange: function (aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
dump("downloading... " + aCurSelfProgress + "/" + aMaxSelfProgress + "
");
},
onLocationChange: function (aWebProgress, aRequest, aLocation) {},
onStatusChange : function (aWebProgress, aRequest, aStatus, aMessage) {},
onSecurityChange: function (aWebProgress, aRequest, aState) {},
};
saveChannel の場合
saveURI の場合と異なり、なぜか nsIWebProgressListener の onProgressChange メソッドが呼び出されない。代わりに、 nsIChannel の notificationCallbacks プロパティに nsIProgressEventSink インタフェースを実装する。
参考: nsIWebBrowserPersist.saveChannel – やんばるもじら
channel.notificationCallbacks = {
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIProgressEventSink))
return this;
Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
return null;
},
// implements nsIInterfaceRequestor
getInterface: function (aIID, aInstance) {
return this.QueryInterface(aIID);
},
// implements nsIProgressEventSink
onProgress: function (aRequest, aContext, aProgress, aProgressMax) {
dump("downloading... " + aProgress + "/" + aProgressMax + "
");
},
onStatus: function (aRequest, aContext, aStatus, aStatusArg) {},
};
nsIChannel.notificationCallbacks プロパティは nsIInterfaceRequestor 型であり、 nsIChannel オブジェクトに発生する様々なイベントに応じて、まずはじめに getInterface メソッドが呼び出される。 getInterface メソッドは引数にて指定されたインタフェースへと QI して返すだけ。
なお、 nsIChannel.asyncOpen によって要求開始した場合、 notificationCallbacks に nsIRequestObserver インタフェースを実装することで、要求開始時と要求終了時に onStartRequest, onStopRequest メソッドが呼び出されるが、 nsIWebBrowserPersist.saveChannel によるダウンロードではこの呼び出しは発生しない。
別の方法として、 notificationCallbacks プロパティに nsIWebBrowserPersist オブジェクト自体をセットする手もあるようだ。
wbp.progressListener = {
/* snip */
};
channel.notificationCallbacks = wbp;
参考
nsIWebProgressListener.idl
nsIInterfaceRequestor.idl
nsIProgressEventSink.idl
関連記事
nsIWebBrowserPersist の基本的な使い方 (1) ~ 基本形
nsIWebBrowserPersist の基本的な使い方 (2) ~ persistFlags
nsIWebBrowserPersist の基本的な使い方 (3) ~ 各種ヘッダの追加
nsIWebBrowserPersist の基本的な使い方 (4) ~ POST メソッド
nsIWebBrowserPersist の基本的な使い方 (5) ~ ダウンロード進捗状況
つづく…?
Hi,
Just wanna come over and thank you for your useful firefox extensions.
Thanks again.