DATE : 2008/11/22 (Sat)
Firefox 拡張で、特定の URL が読み込まれた際に他のページへ飛ばすには、nsIWebProgressListener インタフェースを実装したオブジェクトを作ります。
function MyListener() { } MyListener.prototype = { /* * nsIWebProgressListener の実装 */ QueryInterface : function(aIID) { if (aIID.equals(Components.interfaces.nsIWebProgressListener) || aIID.equals(Components.interfaces.nsISupportsWeakReference) || aIID.equals(Components.interfaces.nsISupports)) { return this; } throw Components.results.NS_NOINSTANCE; }, onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) { }, onLocationChange : function(aProgress, aRequest, aURI) { }, onProgressChange : function(aProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { }, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { }, onSecurityChange : function(aWebProgress, aRequest, aState) { } }
nsIWebProgressListener インタフェースを実装したオブジェクトは、ページへのリクエストを監視できます。ページへのリクエストが発生すると onStateChange メソッドが呼ばれるので、このメソッド内に、移動したいページの URL へのリクエストを監視するコードを書きます。
onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) { var url = aRequest.name; if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_START) { // url のページへのリクエストが発生した際に到達する } },
リクエストされた URL を取得するには、引数 aRequest の型である nsIRequest の name プロパティを使用します。また、リクエストの開始かどうかは、引数 aFlag のビット列を見ることでわかります。
引数 aRequest の name プロパティの中身が予期していた URL と同じであれば、別のページへ飛ばすようなコードを書きます。ここで、SOURCE_URL は別ページへ飛ばす対象となる URL、DESTINATION_URL は、移動先の URL を表します。
onStateChange : function(aWebProgress, aRequest, aFlag, aStatus) { var url = aRequest.name; if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_START) { if (url == SOURCE_URL) { aWebProgress.DOMWindow.location.replace(DESTINATION_URL); } } },
nsIWebProgress 型である引数 aWebProgress から、現在のページを表示している nsIDOMWindow 型のオブジェクトを取得し、そのページの場所を表す Location オブジェクトを使用して、移動先のページに置き換えます。Location オブジェクトでは、assign メソッドを使用してページを置き換える方法もありますが、上記のコードでは replace メソッドを使用しました。assing メソッドでは置き換えた元のページが履歴に残りますが、replace では残りません。
現在のページの URL は、 nsIDOMWindow 型のオブジェクトから取得した Location オブジェクトを使用しても取得できますが、今回はその方法が使えません。Location オブジェクトの表す URL はすでに読み込みが完了した後のページのものなので、上記のコードで新しくリクエストされた URL を Location オブジェクトから取得しようとしても、現在表示されているページの URL が取得されてしまいます。replace メソッドを使用してページを置き換えると新しいリクエストが発生するので、無限ループになる場合もあります。そのため、リクエストされた URL を使用する際には、必ず引数 aRequest の name プロパティから取得するようにしてください。
(;^ω^)これで長時間つまりました。
あとは、このリスナーオブジェクトを Firefox に登録します。
var myListener = new MyListener(); function load() { gBrowser.addProgressListener( myListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT); } function unload() { gBrowser.removeProgressListener(myListener); } window.addEventListener("load", load, false); window.addEventListener("unload", unload, false);
参考文献
- On page load - MDC
- Progress Listeners - MDC
- nsIWebProgressListener - MDC
- nsIWebProgress - MDC
- Interface Reference - nsIRequest
- nsIDOMWindow - MDC
- location - MDC