Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

nsIChannel & threading

5 views
Skip to first unread message

Diaa

unread,
Aug 9, 2007, 4:43:34 PM8/9/07
to
I'm developing an nsIChannel-derived class as part of a protocol
handler, unfortunately I have to use an external synchronous
networking library, normally this would be done using threads, so I'm
wondering how can I do this, if it is threads, then how to do it, can
someone provide me with a little guidance?

Thanks.

Christian Biesinger

unread,
Aug 13, 2007, 1:10:10 AM8/13/07
to dev-tech...@lists.mozilla.org

Your channel implementation can certainly use threads. You only have to
make sure that you use your notificationCallbacks, loadgroup, listener
(this one is the most important), etc. only on the main thread.

nsISupports proxies can help with that:
http://www.mozilla.org/projects/xpcom/Proxies.html


Diaa

unread,
Aug 26, 2007, 12:10:07 PM8/26/07
to

Thanks very much for your reply.

Ok, I already started working on it.
Is there any example/sample code that I can use as a guide?
How to use the listener, for example, from the main thread when the
data is actually received in the worker thread?

Thanks again

Christian Biesinger

unread,
Aug 27, 2007, 1:41:16 AM8/27/07
to dev-tech...@lists.mozilla.org
Diaa wrote:
> Is there any example/sample code that I can use as a guide?
> How to use the listener, for example, from the main thread when the
> data is actually received in the worker thread?

Unfortunately I'm not aware of any sample code for this. As for calling
the listener, all you have to do is use
nsIProxyObjectManager::GetProxyForObject (or the NS_GetProxyForObject
helper method) at asyncOpen time (make sure to pass PROXY_ALWAYS), then
you can just call methods on that object from any thread and have the
calls be forwarded to the correct thread.

-christian

Diaa

unread,
Sep 14, 2007, 11:35:45 PM9/14/07
to

Yes I did that and it worked properly, thanks much.
There's another problem I ran into which is that no progress bar is
displayed and FF is not aware about loading(even the Stop button is
disabled), I tried using the NotificationCallbacks provided by the
client but nothing happened, then when I used the loadgroup(Called
AddRequest & RemoveRequest), everything went fine except that -
strangely - 2 channels(and sometimes more) are created for each
request, other channels are created with the same URI and load the
resource again, I can't find out why this is happeneing, but when I
remove the loadgroup AddRequest and RemoveRequest it works properly
and only one channel is created.
Do you have any ideas?

Here's a log that shows sequence of function calls:

ZipChannel()
Init()
SetNotificationCallbacks()
SetLoadFlags()
AsyncOpen()
Leaving AsyncOpen()
ZipChannel() <-- another channel created.
Init()
SetNotificationCallbacks()
SetLoadFlags()
SetOriginalURI()
SetLoadFlags()
SetLoadFlags()
GetURI()
SetLoadGroup()
AsyncOpen()
SetLoadFlags()
SetLoadFlags()
SetLoadFlags()
GetURI()
GetURI()
SetLoadFlags()
Leaving AsyncOpen()
Cancel()
OnStartRequest()
GetContentType()
Cancel()
OnStartRequest()
GetStatus()
GetContentType()
filesize: 568159
Retrieving data
filesize: 568159
Thread finished
Done retrieving data, 131072 bytes
OnDataAvailable()
SetContentType()
GetStatus()
GetContentType()
SetLoadFlags()
SetLoadFlags()
SetLoadFlags()
GetURI()
SetLoadFlags()
GetOriginalURI()
SetLoadFlags()
GetContentType()
SetLoadFlags()
GetOriginalURI()
GetLoadGroup()
GetSecurityInfo()
GetSecurityInfo()
GetURI()
GetURI()
GetContentType()
GetURI()
SetLoadFlags()
GetLoadGroup()
GetContentType()
GetStatus()
Retrieving data
GetURI()
Done retrieving data, 131072 bytes
OnDataAvailable()
Retrieving data
Done retrieving data, 131072 bytes
OnDataAvailable()
Retrieving data
Done retrieving data, 131072 bytes
OnDataAvailable()
Retrieving data
Done retrieving data, 43871 bytes
OnDataAvailable()
Thread finished
OnStopRequest()
GetOriginalURI()
SetLoadFlags()
GetURI()
SetLoadFlags()
GetURI()
SetLoadFlags()
GetNotificationCallbacks()
GetSecurityInfo()
GetSecurityInfo()
GetStatus()
GetURI()
SetLoadFlags()
GetURI()
GetURI()
GetOriginalURI()
ZipChannel() <-- A third channel created.
Init()
SetNotificationCallbacks()
AsyncOpen()
Leaving AsyncOpen()
GetURI()
GetURI()
SetLoadFlags()
OnStartRequest()
filesize: 568159
Retrieving data
Done retrieving data, 131072 bytes
OnDataAvailable()
Retrieving data
calling OnProgress
Done retrieving data, 131072 bytes
Retrieving data
OnDataAvailable()
calling OnProgress
Done retrieving data, 131072 bytes
Retrieving data
OnDataAvailable()
calling OnProgress
Done retrieving data, 131072 bytes
Retrieving data
OnDataAvailable()
calling OnProgress
Done retrieving data, 43871 bytes
Thread finished
OnDataAvailable()
calling OnProgress
OnStopRequest()

Thanks

Christian Biesinger

unread,
Sep 17, 2007, 10:56:29 AM9/17/07
to dev-tech...@lists.mozilla.org
Diaa wrote:
> Yes I did that and it worked properly, thanks much.
> There's another problem I ran into which is that no progress bar is
> displayed and FF is not aware about loading(even the Stop button is
> disabled),

To have a working progress bar, you need to get an nsIProgressEventSink
from your notification callbacks (and, if that fails, from the
loadgroup's notification callbacks) and call onProgress/onStatus as needed.

You also have to put the channel into the loadgroup in AsyncOpen, and
remove it after calling OnStopRequest, but you seem to have figured that
out.


Unfortunately I don't have an idea on why the second channel would be
created; the only reason I can think of is that you don't have a
contentCharset and the data contains a <meta> element with charset info.
That causes a new channel to be created and loaded, but that wouldn't
happen right after asyncOpen...

--
All the world's a stage,
And all the men and women merely players:
They have their exits and their entrances;
And one man in his time plays many parts, [...] --W. Shakespeare

Diaa

unread,
Sep 25, 2007, 3:35:47 PM9/25/07
to
On Sep 17, 5:56 pm, Christian Biesinger <cbiesin...@web.de> wrote:
>
> To have a working progress bar, you need to get an nsIProgressEventSink
> from your notification callbacks (and, if that fails, from the
> loadgroup's notification callbacks) and call onProgress/onStatus as needed.
>
> You also have to put the channel into the loadgroup in AsyncOpen, and
> remove it after calling OnStopRequest, but you seem to have figured that
> out.
>
> Unfortunately I don't have an idea on why the second channel would be
> created; the only reason I can think of is that you don't have a
> contentCharset and the data contains a <meta> element with charset info.
> That causes a new channel to be created and loaded, but that wouldn't
> happen right after asyncOpen...
>

Do you have any ideas that help me understand what's wrong? may be
using a debug firefox executable can help(though the amount of source-
code is huge), What do you think?


Christian Biesinger

unread,
Sep 26, 2007, 4:15:03 AM9/26/07
to dev-tech...@lists.mozilla.org
Diaa wrote:
> Do you have any ideas that help me understand what's wrong? may be
> using a debug firefox executable can help(though the amount of source-
> code is huge), What do you think?

Yeah, in a debug build (or, in fact, if you use Windows you can use the
symbol server -
http://developer.mozilla.org/en/docs/Using_the_Mozilla_symbol_server)
you could set a breakpoint in yourchannel::AsyncOpen and see where that
was called from. That should help figuring out why it happens.

-christian

Diaa

unread,
Sep 28, 2007, 5:49:41 PM9/28/07
to
On Sep 26, 10:15 am, Christian Biesinger <cbiesin...@web.de> wrote:
> Diaa wrote:
> > Do you have any ideas that help me understand what's wrong? may be
> > using a debug firefox executable can help(though the amount of source-
> > code is huge), What do you think?
>
> Yeah, in a debug build (or, in fact, if you use Windows you can use the
> symbol server -http://developer.mozilla.org/en/docs/Using_the_Mozilla_symbol_server)

> you could set a breakpoint in yourchannel::AsyncOpen and see where that
> was called from. That should help figuring out why it happens.
>
> -christian
>
> --
> All the world's a stage,
> And all the men and women merely players:
> They have their exits and their entrances;
> And one man in his time plays many parts, [...] --W. Shakespeare

Thanks again for your help, the symbol server is a very good facility
that saves the trouble/time compiling firefox.
I found out what the problem is, it was memory corruption, I should
have known that because usually it's only memory corruption that can
does such sorts of magic, but what's strange is that the application
didn't crash.

Well anyway, now I'm on my way back continuing the development of the
protocol handler and I have some questions:

is nsIRequest::Cancel() synchronous or asynchronous? if it's async,
how to notify the host that I've finished cleaning up?
Which values are allowed to be returned from nsIRequest::GetStatus()?

Regards,
Diaa Sami

Christian Biesinger

unread,
Sep 28, 2007, 6:54:42 PM9/28/07
to dev-tech...@lists.mozilla.org
Diaa wrote:
> I found out what the problem is, it was memory corruption, I should
> have known that because usually it's only memory corruption that can
> does such sorts of magic, but what's strange is that the application
> didn't crash.

Interesting, strange that memory corruption caused that problem...

> is nsIRequest::Cancel() synchronous or asynchronous? if it's async,
> how to notify the host that I've finished cleaning up?

Asynchronous; you need to (asynchronously) call
onStartRequest/onStopRequest on your stream listener, if they haven't
been called yet.

> Which values are allowed to be returned from nsIRequest::GetStatus()?

Any valid nsresult. For a channel that loaded successfully it'd be
NS_OK, for a cancelled channel generally the value that was passed to
cancel, and otherwise a value that depends on the error. nsNetError.h
has a list of some error codes, or you can define your own (see
NS_GENERATE_FAILURE).

0 new messages