とりあえず、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が混ざっているな。 まぁ、いいか?

