私は再び。
から同じものを引用しますnsIChannel::asyncOpen()
:
正常に返された場合、チャネルは、 onまたは
asyncOpen
が呼び出されるまで自身を存続させる責任があります
。onStopRequest
aListener
onChannelRedirect
nsViewSourceChannel.cppに戻ると、 が呼び出される場所が 1 つと、loadGroup->AddRequest
が呼び出される場所が 2 つありloadGroup->RemoveRequest
ます。
nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
mListener = aListener;
/*
* We want to add ourselves to the loadgroup before opening
* mChannel, since we want to make sure we're in the loadgroup
* when mChannel finishes and fires OnStopRequest()
*/
nsCOMPtr<nsILoadGroup> loadGroup;
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup)
loadGroup->AddRequest(NS_STATIC_CAST(nsIViewSourceChannel*,
this), nsnull);
nsresult rv = mChannel->AsyncOpen(this, ctxt);
if (NS_FAILED(rv) && loadGroup)
loadGroup->RemoveRequest(NS_STATIC_CAST(nsIViewSourceChannel*,
this),
nsnull, rv);
if (NS_SUCCEEDED(rv)) {
mOpened = PR_TRUE;
}
return rv;
}
と
nsViewSourceChannel::OnStopRequest(nsIRequest *aRequest, nsISupports* aContext,
nsresult aStatus)
{
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
if (mChannel)
{
nsCOMPtr<nsILoadGroup> loadGroup;
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup)
{
loadGroup->RemoveRequest(NS_STATIC_CAST(nsIViewSourceChannel*,
this),
nsnull, aStatus);
}
}
return mListener->OnStopRequest(NS_STATIC_CAST(nsIViewSourceChannel*,
this),
aContext, aStatus);
}
編集:
私は Mozilla がどのように機能するかについて手がかりがないので、いくつかのコードを読んで推測する必要があります。チャネルの観点からは、元のファイルが読み込まれると、その作業は完了です。画像のようにファイルにリンクされたセカンダリ アイテムをロードする場合は、リスナーでそれを実装する必要があります。TestPageLoad.cppを参照してください。これは粗いパーサーを実装し、次の条件で子アイテムを取得しますOnDataAvailable
。
NS_IMETHODIMP
MyListener::OnDataAvailable(nsIRequest *req, nsISupports *ctxt,
nsIInputStream *stream,
PRUint32 offset, PRUint32 count)
{
//printf(">>> OnDataAvailable [count=%u]\n", count);
nsresult rv = NS_ERROR_FAILURE;
PRUint32 bytesRead=0;
char buf[1024];
if(ctxt == nsnull) {
bytesRead=0;
rv = stream->ReadSegments(streamParse, &offset, count, &bytesRead);
} else {
while (count) {
PRUint32 amount = PR_MIN(count, sizeof(buf));
rv = stream->Read(buf, amount, &bytesRead);
count -= bytesRead;
}
}
if (NS_FAILED(rv)) {
printf(">>> stream->Read failed with rv=%x\n", rv);
return rv;
}
return NS_OK;
}
重要なことは、と要素の属性streamParse()
を調べる を呼び出し、新しいリスナーで新しいチャネルを作成し を呼び出す を呼び出すことです。src
img
script
auxLoad()
AsyncOpen()
uriList->AppendElement(uri);
rv = NS_NewChannel(getter_AddRefs(chan), uri, nsnull, nsnull, callbacks);
RETURN_IF_FAILED(rv, "NS_NewChannel");
gKeepRunning++;
rv = chan->AsyncOpen(listener, myBool);
RETURN_IF_FAILED(rv, "AsyncOpen");
そこにオブジェクトの別のインスタンスを渡してMyListener
いるため、ロシアの人形のように無限に子アイテムをロードすることもできます。