问题描述
我正在尝试在Delphi中构建nsIProtocolHandler实现。 (我已经成功完成了IInternetProtocol,并希望在FireFox中拥有Internet Explorer中的功能。)
感谢项目,它以某种方式将TInterfacedObject魔术链接到nsISupports魔术,我能够制作一个DLL,该DLL在被询问时提供nsIModule,而在提供nsIFactory时提供问,在询问时提供我的nsIProtocolHandler之一,在询问时提供我的nsIChannel / nsIHttpChannel之一。
I'm trying to build an nsIProtocolHandler implementation in Delphi. (I've done an IInternetProtocol before with success, and want to have in FireFox what I've got in Internet Explorer.)Thanks to the d-gecko project, that somehow links the TInterfacedObject magic to the nsISupports magic, I'm able to make a DLL that provides an nsIModule when asked, which provides an nsIFactory when asked, which provides one of my nsIProtocolHandler's when asked, which provides one of my nsIChannel/nsIHttpChannel's when asked.
使用firefox.exe作为宿主进程进行调试时,我可以看到我的库被加载,NewURI被调用三次,NewChannel被调用,并且我传递了一个实现nsIChannel和。
When debugging using firefox.exe as host process, I can see my library gets loaded, NewURI gets called three times, NewChannel gets called, and I pass an object that implements nsIChannel and nsIHttpChannel.
这是我遇到的麻烦。在从AsyncOpen返回控制之前,我不应该在获得的nsIStreamListener上调用OnStartRequest和OnDataAvailable,但似乎无法在调用AsyncOpen的线程中重新获得控制。
This is where I'm troubled. I'm not supposed to call OnStartRequest and OnDataAvailable on the nsIStreamListener I get, until I return control from AsyncOpen, but I don't seem to get control back in the thread that AsyncOpen was called in.
我尝试使用默认http处理程序(用 CreateInstanceByContractID('@ mozilla.org/network/protocol;1?name=http' ,
...)。我还包装了通过的侦听器。奇怪的是,我看到在通道包装器死后,在同一线程中OnStartRequest和OnDataAvailable被称为。
I've tried debugging with a self-made wrapper around a default http handler (gotten with CreateInstanceByContractID('@mozilla.org/network/protocol;1?name=http',
...). I also wrapped the listener passed. Oddly enough, I see OnStartRequest and OnDataAvailable get called after my channel wrapper dies, in the same thread. But who's calling? If it's the http-channel I was trying to wrap, how does it survive (in the same thread) and how does it get control to call the listener? I'm baffled. And stuck.
我曾尝试与d-gecko项目的主要开发人员联系,但没有得到答复。
I've tried to contact the main developer of the d-gecko project, but got no response.
(此外,有人请注意在nsIProtocolHandler上的MDC上的对话页面?)
(Also, did someone ever notice my blurb at the bottom of the talk page on MDC on nsIProtocolHandler?)
(哦,还有一件事,是的,我知道生活会更简单如果我只是从C ++中的nsBaseChannel继承。但是关键是要在现有的Delphi项目核心中添加FireFox协议处理程序。)
(Oh one more thing, yes I know "life would be simpler" if I would just inherit from nsBaseChannel in C++. But the point is to add a FireFox protocol-handler to an existing Delphi project core.)
更新:我已经做了一些阅读,也在提及:流侦听器的方法是在调用asyncOpen [...]的线程上调用
,但我不清楚如何在不首先从托管应用程序调用的情况下实现这种方法。那是XPCOM的把戏吗?我想我必须先阅读(大量)更多的firefox源。
Update: I've done some more reading, It's mentioned here as well: "The stream listener's methods are called on the thread that calls asyncOpen [...]" but how that is possible without being called from the 'hosting application' first, isn't clear to me. Is that an XPCOM trick? I guess I'll have to read (a lot) more firefox source before I get it.
推荐答案
我不知道Mozilla编码,但是就可以了。
I have no idea about Mozilla coding, but here it goes.
根据,
因此,作为协议处理程序,您可以自己实现通道对象或将其重定向到通道对象,通道的使用者使用 asyncOpen()
调用您的通道。由于这是一个异步调用,因此其想法是立即将控件返回给使用者,并且假定在加载到数据中时调用回调。
So as the protocol hander, you implement a channel object on your own or redirect it to a channel object, the consumer of the channel calls your channel up using asyncOpen()
. Since it is an async call, the idea is to return the control back to the consumer immediately, and it is suppose to call the callbacks as it loads in the data.
我不确定我是否理解您的意思,但是我似乎并没有在调用AsyncOpen的线程中重新获得控制权。线程是由您的协议的使用者创建的,并打开了通道。
I am not sure if I understand what you mean by "but I don't seem to get control back in the thread that AsyncOpen was called in." The thread is created by the consumer of your protocol, and it opens the channel.
也来自:
由于asyncOpen会立即返回控件,因此通道本身需要保持活动状态。
Since asyncOpen returns the control right back, the channel itself needs to keep itself alive somewhere.
如果您正在寻找示例代码中,我发现codase非常有用。请参见和
。使用它,我遇到了 (此实现可能会更旧,但没有关系)。
If you are looking for example code, I found codase to be very useful. See nsIProtocolHandler andnsIChannel. Using that I came across view-source protocol (this implementation may be older, but doesn't matter).
实现自定义渠道。
nsViewSourceHandler
implements custom channel.
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;
}
这是的AsyncOpen:
Here's the nsViewSourceChannel
's 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;
}
无论如何,这是一个漫长而曲折的提问方式,您如何创建您的频道?
Anyway, this is a long and winding way of asking, how are you creating your channel?
这篇关于用Delphi实现nsIProtocolHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!