とりあえず、httpリクエスト送信前にリクエストを察知できるイベントでhttp-on-modify-requestってのがあります。 http-on-modify-requestのリスナを書くと、こんな感じです。
var httpRequestObserver = { observe: function (aSubject, aTopic, aData) { if (aTopic !== "http-on-modify-request") return; var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel); ... }, QueryInterface: XPCOMUtils.generateQI(["nsIObserver"]) };
ここで、aSubjectをnsIHttpChannelにキャストしているコードはよく見ます。 でも、nsIHttpChannelに通信を止めるようなメソッドはありません。 nsIHttpChannelだけじゃhttpリクエストのキャンセルはできないんですね。
「じゃあこのイベントでhttpリクエストのキャンセルはできないのか?」というと、できます。 aSubjectがどのインターフェースを実装しているか調べると、こんなに出てきました。
nsIStreamListener、nsICacheListener、nsIHttpChannel、nsIHttpAuthenticableChannel、nsITraceableChannel、nsIChannel、nsIWritablePropertyBag2、nsIUploadChannel、nsIRequest、nsITransportEventSink、nsIEncodedChannel、nsIProxiedChannel、nsICacheInfoChannel、nsIPropertyBag2、nsIApplicationCacheContainer、nsIProtocolProxyCallback、nsIHttpChannelInternal、nsIRequestObserver、nsISupports、nsICachingChannel、nsIAsyncVerifyRedirectCallback、nsIWritablePropertyBag、nsIApplicationCacheChannel、nsIUploadChannel2、nsISupportsPriority、nsIResumableChannel、nsIPropertyBag、nsITimedChannel
調べ方は前の投稿参照。
サンプルコードなどで見つかるのがnsIHttpChannelへのキャストってだけで、他にも色々あるんですね。 で、aSubjectはnsIRequestを実装している事が判明しました。 これでcancel可能です。
それを使ってコードを書いたらこうなりました。 リクエスト先のホスト名が「.yahoo.com」で終わっていたらリクエストの送信をキャンセルします。 (ちなみに、yahoo.comを選んだのはタマタマであり、意味はありません。)
// bootstrap.js const Ci = Components.interfaces; const Cr = Components.results; const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); const TOPIC = "http-on-modify-request"; var httpRequestObserver = { observe: function (aSubject, aTopic, aData) { if (aTopic !== TOPIC) return; var request = aSubject.QueryInterface(Ci.nsIRequest) .QueryInterface(Ci.nsIHttpChannel); if (endsWith(request.URI.host, ".yahoo.com") ) { log("drop ... " + request.URI.spec); request.cancel(Cr.NS_ERROR_FAILURE); } else { log("allow ... " + request.URI.spec); } }, QueryInterface: XPCOMUtils.generateQI(["nsIObserver"]) }; function endsWith(text, pattern) { var textLen = text.length; var patLen = pattern.length; return patLen <= textLen && text.indexOf(pattern, textLen - patLen) !== -1; } function log() { let text = "[HttpRequestCanceller] " + Array.join(arguments, " "); Services.console.logStringMessage(text); dump(text + '\n'); } function install (aData, aReason) { } function uninstall(aData, aReason) { } function startup (aData, aReason) { log("Start"); Services.obs.addObserver(httpRequestObserver, TOPIC, false); } function shutdown (aData, aReason) { log("Shutdown"); Services.obs.removeObserver(httpRequestObserver, TOPIC); }
う~ん。letとvarが混ざっているな。 まぁ、いいか?