I'm building an nsIProtocolHandler implementation in Delphi. (more here)
And it's working already. Data the module builds gets streamed over an nsIInputStream. I've got all the nsIRequest, nsIChannel and nsIHttpChannel methods and properties working.
I've started testing and I run into something strange. I have a page "a.html" with this simple HTML:
<img src="a.png">
Both "xxm://test/a.html" and "xxm://test/a.png" work in Firefox, and give above HTML or the PNG image data.
The problem is with displaying the HTML page, the image doesn't get loaded. When I debug, I see:
- NewChannel gets called for a.png, (when Firefox is processing an OnDataAvailable notice on a.html),
- NotificationCallbacks is set (I only need to keep a reference, right?)
- RequestHeader "
Accept
" is set to "image/png,image/*;q=0.8,*/*;q=0.5
" - but then, the channel object is released (most probably due to a zero reference count)
Looking at other requests, I would expect some other properties to get set (such as LoadFlags or OriginalURI) and AsyncOpen to get called, from where I can start getting the request responded to.
Does anybody recognise this? Am I doing something wrong? Perhaps with LoadFlags or the LoadGroup? I'm not sure when to call AddRequest and RemoveRequest on the LoadGroup, and peeping from nsHttpChannel and nsBaseChannel I'm not sure it's better to call RemoveRequest early or late (before or after OnStartRequest or OnStopRequest)?
Update: Checked on the freshly new Firefox 3.5, still the same
Update: To try to further isolate the issue, I try "file://test/a1.html" with <img src="xxm://test/a.png" />
and still only get above sequence of events happening. If I'm supposed to add this secundary request to a load-group to get AsyncOpen called on it, I have no idea where to get a reference to it.
There's more: I find only one instance of the "Accept" string that get's added to the request headers, it queries for nsIHttpChannelInternal right after creating a new channel, but I don't even get this QueryInterface call through… (I posted it here)
Best Answer
Me again.
I am going to quote the same stuff from
nsIChannel::asyncOpen()
:If you go back to nsViewSourceChannel.cpp, there's one place where
loadGroup->AddRequest
is called and two places whereloadGroup->RemoveRequest
is being called.and
Edit:
As I have no clue about how Mozilla works, so I have to guess from reading some code. From the channel's point of view, once the original file is loaded, its job is done. If you want to load the secondary items linked in file like an image, you have to implement that in the listener. See TestPageLoad.cpp. It implements a crude parser and it retrieves child items upon
OnDataAvailable
:The important thing is that it calls
streamParse()
, which looks atsrc
attribute ofimg
andscript
element, and callsauxLoad()
, which creates new channel with new listener and callsAsyncOpen()
.Since it's passing in another instance of
MyListener
object in there, that can also load more child items ad infinitum like a Russian doll situation.