执行nsIProtocolHandler用德尔菲
题
我在试图建立一个nsIProtocolHandler执行在德尔福。(我做了一个IInternetProtocol之前成功,并希望有FireFox什么我在互联网浏览器。) 谢谢来 d-壁虎 的项目,即以某种方式连接TInterfacedObject魔法的nsISupports魔法,我能够做出DLL,提供了一个nsIModule当要求,其中提供了一个nsIFactory当要求,其中提供了一个我nsIProtocolHandler的当要求,其中提供了一个我nsIChannel/nsIHttpChannel的当要求。
当试利用firefox.exe 作为东道主的过程中,我可以看看我的图书馆得到加载,NewURI被称为三次,NewChannel调,我通过一个对象实现和nsIChannel nsIHttpChannel.
这是我的困扰。我不应该呼叫OnStartRequest和OnDataAvailable在nsIStreamListener我得到的,直到我回来控制从AsyncOpen,但我似乎没有得到控制在线程,AsyncOpen被称为。
我已经试过调试用一个自制的包装默认http处理(经得到了与 CreateInstanceByContractID('@mozilla.org/network/protocol;1?name=http',
...).我还裹的听众通过。奇怪的是,我看到OnStartRequest和OnDataAvailable得到所谓的 后 我的通道包装死了,在同一线。但是谁的电话?如果它是http道我想包装,它是如何生存下去(在同一线)以及它如何得到控制电话监听器?我百思不得其解。和坚持。
我试图联系的主要开发d-壁虎的项目,但没有得到响应。
(此外,有人曾经通知我的blurb在底部的 讨论页上MDC在nsIProtocolHandler?)
(哦还有一件事,是的,我知道"的生活会更简单的"如果我只是继承自nsBaseChannel在C++。但是添加一个火狐协议的处理程序的现有德尔斐项目的核心。)
更新: 我已经做了一些更多的阅读,它的提及 在这里, 为:"流听众的方法 所谓的在线电话asyncOpen[...]",但如何,可能没有被从所谓的'托管的应用'第一,不是我清楚。那是一个XPCOM伎俩?我想我已经读(很多)更多的火狐源之前,我得到它。
解决方案
我不知道Mozilla的编码的想法,但在这里不言而喻。
异步打开该通道。数据 被供给到指定的流 听众变得可用。该 流听者的方法被称为 在调用asyncOpen和线程 不叫,直到asyncOpen后 回报。如果asyncOpen回报 成功,该通道承诺 调用至少onStartRequest和 onStopRequest。
因此,作为协议处理程序,需要实现一个通道对象是自己或重定向到一个通道对象,该通道的使用者调用您的频道上使用asyncOpen()
。由于它是一个异步调用,这个想法是立即返回控制权交还给消费者,它是假设调用回调函数在加载数据。
我不知道如果我明白你的意思“但我似乎并没有得到控制回到线程AsyncOpen被称为”。线是用您的协议的消费者创建,并且它打开的通道。
另外,从 nsIChannel :: asyncOpen():
如果asyncOpen成功返回时, 信道是负责保持 本身的生命,直到它被称为 onStopRequest上aListener或者叫 onChannelRedirect。
由于asyncOpen返回控制权后面,通道本身需要保持本身活着的某个地方。
如果您正在寻找示例代码中,我发现codase是非常有用的。请参见 nsIProtocolHandler 和 nsIChannel 。使用我碰到查看源代码协议 (这种实现可能是年纪大的,但并不重要)。
nsViewSourceHandler
实现自定义信道。
nsViewSourceHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
{
nsresult rv;
nsViewSourceChannel* channel;
rv = nsViewSourceChannel::Create(nsnull, NS_GET_IID(nsIChannel), (void**)&channel);
if (NS_FAILED(rv)) return rv;
rv = channel->Init(uri);
if (NS_FAILED(rv)) {
NS_RELEASE(channel);
return rv;
}
*result = NS_STATIC_CAST(nsIViewSourceChannel*, channel);
return NS_OK;
}
这里的 nsViewSourceChannel
的AsyncOpen:
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;
}
无论如何,这是问,你是如何创建频道的一个漫长而曲折的道路?