gpt4 book ai didi

delphi - nsIProtocolHandler : trouble loading image for html page

转载 作者:行者123 更新时间:2023-12-03 18:52:02 26 4
gpt4 key购买 nike

我正在 Delphi 中构建一个 nsIProtocolHandler 实现。 (more here)
它已经开始工作了。模块构建的数据通过 nsIInputStream 流式传输。我已经让所有 nsIRequest、nsIChannel 和 nsIHttpChannel 方法和属性都在工作。

我已经开始测试,但遇到了一些奇怪的事情。我有一个带有这个简单 HTML 的页面“a.html”:
<img src="a.png">
"xxm://test/a.html"和 "xxm://test/a.png"都可以在 Firefox 中使用,并提供上面的 HTML 或 PNG 图像数据。
问题在于显示 HTML 页面时,图像未加载。当我调试时,我看到:

  • 为 a.png 调用 NewChannel,(当 Firefox 在 a.html 上处理 OnDataAvailable 通知时),
  • NotificationCallbacks 已设置(我只需要保留一个引用,对吗?)
  • 请求头“Accept”设置为“image/png,image/*;q=0.8,*/*;q=0.5
  • 但是随后, channel 对象被释放(很可能是由于引用计数为零)

  • 查看其他请求,我希望设置其他一些属性(例如 LoadFlags 或 OriginalURI)和 AsyncOpen被调用,我可以从那里开始响应请求。

    有人认识这个吗?难道我做错了什么?也许使用 LoadFlags 或 LoadGroup?我不确定何时在 LoadGroup 上调用 AddRequest 和 RemoveRequest,并从 nsHttpChannel 窥视。和 nsBaseChannel我不确定是早点还是晚点(在 OnStartRequest 或 OnStopRequest 之前或之后)调用 RemoveRequest 更好?

    更新:检查了全新的 Firefox 3.5,还是一样

    更新:为了进一步隔离问题,我尝试使用“file://test/a1.html”和 <img src="xxm://test/a.png" />并且仍然只能得到以上事件发生的顺序。如果我应该将此辅助请求添加到负载组以调用 AsyncOpen,我不知道从哪里获得对它的引用。

    还有更多:我只找到 one instance添加到请求 header 的“Accept”字符串中,它在创建新 channel 后立即查询 nsIHttpChannelInternal,但我什至没有通过此 QueryInterface 调用...(我发布了它 here)

    最佳答案

    又是我。

    我将引用 nsIChannel::asyncOpen() 中的相同内容:

    If asyncOpen returns successfully, the channel is responsible for keeping itself alive until it has called onStopRequest on aListener or called onChannelRedirect.



    如果您返回 nsViewSourceChannel.cpp ,有一个地方 loadGroup->AddRequest被称为和两个地方 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 是如何工作的,所以我必须通过阅读一些代码来猜测。从 channel 的角度来看,一旦加载了原始文件,它的工作就完成了。如果要加载像图像一样链接在文件中的辅助项目,则必须在监听器中实现它。见 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() , 它使用新的监听器创建新 channel 并调用 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 的另一个实例那里的对象,也可以无限加载更多的子项目,就像俄罗斯娃娃的情况一样。

    关于delphi - nsIProtocolHandler : trouble loading image for html page,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1046523/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com