darin wrote:
+mozSRoaming::mozSRoaming()
+ : mFiles(10)
+{
+ mIsRoaming = PR_FALSE;
+ mMethod = 0;
+ mRegistry = 0;
+}
nit: why not initialize all variables using the variable initializer list?
mFiles is an array or so, thus the custom constructor call via init list. I thought the general style was to use the ctor body, thus the rest, but both is fine with me.

It's generally better to assign member variables in the constructor's initializer list.  By doing so, you enable the compiler to warn you if the order of initialization does not match the order in which the member variables are declared.  Initializing them in order helps with performance (I presume).


nit: do you want to use NSPR logging instead? commenting out printf statements is a messy way to manage debug logging.
True, but NSPR log is even more messy IMHO - set up env vars each session, figure out the right module name and log level etc.. We can remove the printfs entirely, if they are a concern.
$ export NSPR_LOG_MODULES=sroaming:5
$ export NSPR_LOG_FILE=/tmp/sroaming.log

how hard is that?

NSPR logging is nice precisely because it allows you to have logging without editing and recompiling the source.  Also, you can enable NSPR logging in release builds.  This is nice if you find people reporting bugs in the field.  Being able to ask people to send you a NSPR log has proven invaluable to me while trying to figure out wierd necko bugs.  Still, it's your module... if you want printf-style log statements scattered throughout, then so be it.


+
+ rv = ReadRoamingPrefs();
+ nsresult rv = NS_OK;

nit: no reason to initialize |rv| if you are going to assign a
value into it immediately.
There is: IIRC, I found myself moving around the definition and adding/removing init all the time, IIRC even having it accidently uninitalized at one point in this very module. Our code is not set in stone, OTOH compilers may optimize this away anyways. For consistency and safety, I always define and init nsresult at the very top.

Compilers usually warn you if you try to use an uninitialized variable.  I think it's bad form to rely on the compiler to clean up things like this, but it's just a personal nit.  I'm not going to hold you to it.


passing nsCOMPtr<nsIFile> by value has significant cost.
Huch? I assumes nsCOMPtr to be lightweight, only slightly more heavy than a raw pointer and only increasing/decreasing a counter.

Oh, it's much more than increasing/decreasing a counter.  AddRef and Release are virtual function calls.  The overhead associated with the virtual function call far outweighs the cost of incrementing/decrementing a counter.  If you can avoid virtual function calls, then you should.  Passing a nsCOMPtr by value is bad form.


are you sure you want to do this? i would recommend using the standard XPCOM getter
style, which would be much more efficient, e.g.:
The idea was to have the result be a return value, so that I can use nested function calls. XPCOM style doesn't allow that, which I find extremly inconvient. In this case, however, I see that I don't use the function in a nested way anyways and always check the return value, so the XPCOM way would be better, yes, we could then maybe also return an error code.

returning an error code is good :-)


+ ioParamBlock->SetInt(0, download ? 1 : 2);
+ ioParamBlock->SetInt(1, files.Count());
should these indicies (0 and 1) correspond to some enum type? magic
numbers are bad. it is not at all clear to me (the casual code reader)
what they are supposed to mean.
It's defined in the long comment right above it ;-).

This just passes information to/from the JS code. I agree that the nsIDialogParamBlock used is a bad solution, but I didn't know any other one which wouldn't require considerably more [complicated] code.
enums give me some string to grep on to learn more about the identifier :-)
Yes, but these are also used in the JS code, so your grep would fail => misleading.

Your JS code could define constants by the same name.  Associating names to magic numbers (especially an enumeration) is almost always a good thing.


OK. (I find the if-operator *much* easier to decipher.)

Fine by me.


it seems kind of odd to fetch the nsIRegistry instance in this way given that
it happens to be a member variable (mRegistry).
Keep in mind that this code is run at most once at each of startup and shutdown.

My point was that you already have the member variable so why not just provide an inline accessor on the class.


nit: GetRegistryTree might be a better name for this.
OK. But the same would need to apply for ProfileDir(), FilesToRoam(), then.
Yeah, that sounds good.


nit: "else" after a return statement is unnecessary.
Note that this (any many other comments) probably makes no difference in the resulting exe.
Yes, I agree.  However, it just helps unclutter code if you remove unnecessary text.  In some cases it can help reduce indenting, which can improve readability.  This is just a nit.  Feel free to ignore.


should mMethod be an enumeration type? magic numbers (1 & 2)... what do they
mean?
They are defined somewhere, they simply mean "use mozSRoamingStream" and "use mozSRoamingCopy". I guess we could use an enum here, but the values must stay, they are used in the user's registry, IIRC, even as new values (= for new 'protocol handlers') are added.
It's just good form to give a descriptive name to these numbers.


+ So, I just power netlib up again and then power it down again by sending
+ the corresponding profile change notification.
this will have effect on SSL.
IIRC, I tested the code with SSL and it works, but not sure.
for example, if you are fetching the profile over an SSL connection and the user had already agreed to accept the site's certificate for this session, then you will end up requiring the user tore-accept the certificate.
If you put your profile on an SSL-protected server and don't permanently accept the server's certificate, you are insane. Any other cases?
I don't know... lot's of stuff happens when you issue a profile change notification.  I worry that you could end up causing unexpected side-effects.  If not now, maybe later.  It seems wrong to co-opt these notifications like this.


of course, i'm not sure how the UI for that would be handled anyways. perhaps we need a better event. restarting necko like this seems like a hack.
It is, as written. But adding a new event didn't (and doesn't) seem very tempting.


Yeah, I agree that it would be painful.  I think at the very least it should be something to explore in the future.


nit: comment style really varies in this file.
There is a system behind it, but OK to change it however the editor pleases.


Well, it's your module.  I'm just pointing out the inconsistencies as I see them.  If you have a system, then by all means ;-)


why are you using wide strings for URLs? why not just use UTF-8?
Don't remember, anything is fine with me.

UTF-8 is generally better for URL strings in C++ Mozilla code.



+ Unfortunately, this doesn't work. I have to
+ block this function until the transfer is done, but have the transfer
+ itself and the progress UI working. darin says, I will get threading
+ issues then. He suggested to initiate the transfer from the dialog
I said this?
Yes, I can give you the IRC logs, if that helps.

I think there had to have been more to what I said then what you are mentioning here.  Maybe quote me exactly instead? ;-)


It's not clear from your comments here what threading
issues have to do with this... where are the threads? Maybe we spoke
about spinning up a new thread for the downloads? That would be a problem
for sure since Necko is not threadsafe.
What I wanted to do was to put all the transfer logic into the C++ part, still have a dialog showing the progress and results to the user, and not return |Download()| until all of that is finished (all transfers done, dialog closed (automatically when successful, by user when failure)).

As far I as I understood you, putting the transfer logic into JS was the only way, because of said threading issues (which I didn't understand, I have zero clue about Mozilla's threading).

It's too late now anyways, because all the code is written. I'm not going to re-implement it in C++. But if I misunderstood you, we should update the comment.
I'm thinking that the new synchronous I/O support that went into Necko during the 1.6 dev cycle may greatly simply some of this.  But, oh well... you're right. It's all written now, and it presumably works well, so there's not much point in rewriting it.


*phew*! done.

Yeah, no kidding!  This was a really big patch!

I look forward to trying it out in 1.8 alpha :-)