The page https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0
should have a summary of the changes and how extensions will need to be
updated: if you find this page confusing, please let me know so that I can
make it better and answer the right questions.
--BDS
In the linked document it says:
---
Typically, extensions observed app-startup because in the past, you
needed to load for app-startup in order to be able to register to
observe profile-after-change in the first place. As of Gecko 1.9.1, this
is no longer the case, however; you can now register for
profile-after-change using the Category Manager.
---
However when I change my code to register for profile-after-change, then
FF 3.6 does not call me. (I wasn't using app-startup to register for
profile-after-change, I was just trying to get called early).
This is the registration code if it matters:
categoryManager.addCategoryEntry(STARTUP_TOPIC, CLASS_NAME,
"service," + CONTRACT_ID, true, true);
jjb
> In the linked document it says:
> However when I change my code to register for profile-after-change, then
> FF 3.6 does not call me. (I wasn't using app-startup to register for
> profile-after-change, I was just trying to get called early).
>
> This is the registration code if it matters:
> categoryManager.addCategoryEntry(STARTUP_TOPIC, CLASS_NAME,
> "service," + CONTRACT_ID, true, true);
It looks like you are trying to add the category entry programatically, but
how would that code get loaded? You need to add it to your manifest:
category profile-after-change MyClass service,@foo/mycontractid;1
--BDS
Yes, I understand that for FF 4.0b2. But I am trying to work out how to
support FF 3.6 and 4.0b2. The first step would be to change from
app-startup (not supported in 4.0b2) to profile-after-change (supposedly
supported in both). The next step would us both manifest and runtime
registration. But I don't succeed on the first step. Sorry I should have
given the whole story first.
jjb
> Yes, I understand that for FF 4.0b2. But I am trying to work out how to
> support FF 3.6 and 4.0b2. The first step would be to change from
> app-startup (not supported in 4.0b2) to profile-after-change (supposedly
> supported in both). The next step would us both manifest and runtime
> registration. But I don't succeed on the first step. Sorry I should have
> given the whole story first.
Hrm, I don't know. profile-after-change is definitely supported (from 3.5b2
onwards). Assuming that your component was actually re-registered (remove
compreg.dat) and that your observe() method expects the new topic and not
app-startup, I'm not sure what to tell you.
--BDS
When I looked at the categories in chromebug I saw that everything
registered under app-startup started with "service," and everything
except my entry in profile-after-change did not. I removed "service,"+
above and the event arrives in my observer.
jjb
Do NOT use service,contractid just contractid.
The code that handles the profile-after-change category does always
initiate services and furthermore takes the registered value as-is (no
"service," stripping).
http://mxr.mozilla.org/mozilla-central/source/xpcom/components/nsCategoryManager.cpp#745
Cheers
Nils
Hmm, that means the component (and any data it carries) must be kept
around for the entire duration of the app, until xpcom service shutdown?
Just trying to keep things clear, since this means things will have to
cleanup from outside the destructor, given that services shutdown is
very, very late...
--
Mook
> The page
> https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0
> should have a summary of the changes and how extensions will need to
> be updated
function NSGetModule() XPCOMUtils.generateModule([mySample]);
has the advantage of begin a deferred "getter" - it is only called once,
so it doesn't have to do any work until it is called.
Could I write
function NSGetFactory(cid) (NSGetFactory =
XPCOMUtils.generateNSGetFactory([mySample]))(cid);
or does NSGetFactory get cached?
--
Warning: May contain traces of nuts.
> The page
> https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0
> should have a summary of the changes and how extensions will need to
> be updated: if you find this page confusing, please let me know so
> that I can make it better and answer the right questions.
Why was it necessary to switch to manifests in order to register
extensions after loading the extension manager?
> function NSGetModule() XPCOMUtils.generateModule([mySample]);
> has the advantage of begin a deferred "getter" - it is only called once,
> so it doesn't have to do any work until it is called.
It doesn't matter: we don't load the JS component now until we need it, and
then we immediately call NSGetFactory, so there is no real difference.
And yes, NSGetFactory is cached.
--BDS
> Why was it necessary to switch to manifests in order to register
> extensions after loading the extension manager?
Yes. The important part was to get rid of the flattened fastload cache of
registration data, and in order to do that we need to keep the registration
data for various components separate.
At that point, since we were making breaking changes to the registration
system, moving to manifests seemed like the best solution, because it solves
several problems with JS components, such as Cu.import not always working.
--BDS
> Hmm, that means the component (and any data it carries) must be kept
> around for the entire duration of the app, until xpcom service shutdown?
> Just trying to keep things clear, since this means things will have to
> cleanup from outside the destructor, given that services shutdown is
> very, very late...
Yes. You should *never* perform user-visible actions (such as saving data)
from XPCOM object destructors because you don't know who's going to hold a
reference to you or whether you might be leaked. Always do cleanup from
observer notifications or other globally known points.
--BDS
> You should *never* perform user-visible actions (such as saving data)
> from XPCOM object destructors because you don't know who's going to
> hold a reference to you
Well, nobody, I'd hope ;-)
[Presumably the actual issue is outstanding references created by
methods that you pass yourself to in your destructor.]
Well, there would have been a difference had NSGetFactory not been cached.
> And yes, NSGetFactory is cached.
So what I need is a top-level getter:
__defineGetter__("NSGetFactory", function()
XPCOMUtils.generateNSGetFactory([mySample]));
generateNSGetFactory intializes per-component factories and then returns
a function. gNGF does not touch or initialize your components expect
sanity checking .prototype.classID.
I don't really see a point of "deferring" the gNGF call, especially
since it will be called once your script is loaded, hence is actually
not deferred at all. Because your script is only loaded when some code
actually requests one of your components. And your script is loaded only
once and keeps running until the application quits again (nothing
changed here; same as with js modules)
Nils
Could an/some examples be posted on how to convert components to the
new way without using XPCOMUtils.jsm?
I managed to convert my extension's components over to using
XPCOMUtils, but I'd like to try hacking some other, more complicated,
extensions into working for me.
And the reason you don't want to convert to using XPCOMUtils.js is?
> I managed to convert my extension's components over to using
> XPCOMUtils, but I'd like to try hacking some other, more complicated,
> extensions into working for me.
I have a Frankenstein component that works all the way back to the old
XPFE component registration method, which I just updated to support
Firefox 4.0b2pre as well.
Yeah, I know it's ugly. In the next iteration I'm planning to drop
support for anything pre Gecko 1.9.0.
Phil
--
Philip Chee <phi...@aleytys.pc.my>, <phili...@gmail.com>
http://flashblock.mozdev.org/ http://xsidebar.mozdev.org
Guard us from the she-wolf and the wolf, and guard us from the thief,
oh Night, and so be good for us to pass.
[ ]Never park your hard disk in a tow-away zone.
* TagZilla 0.066.6
>I don't really see a point of "deferring" the gNGF call
>
I just don't like putting var statements in conditional branches.
>I managed to convert my extension's components over to using XPCOMUtils, but I'd like to try hacking some other, more complicated, extensions into working for me.
>
>
NSGetFactory is roughly equivalent to the old Module.getClassObject
method, except that it has a single parameter which is the cid of the
component to create.
You still need the manifest of course.
Well, I second that, but I don't care that much to code up alternatives.
(OK, I actually did :p)
this['NSGetFactory"] = XPCOMUtils.generateNSGetFactory([mySample]);
Not much nicer but far less confusing IMO ;)
As I understand it, "var " means "put the following variable in the
function scope". So why would it matter if 'var' is i a conditional
branch? I use 'var' in branches a lot, seems fine to me.
jjb
Can we have an updated version this document for Gecko_2.0?
Thanks.
--
Subrata
The Class ID is enclosed in braces in the chrome.manifest.
My question is which is the correct way to specify the class id. My
guess is that Class Id should be enclosed in the braces like we do in
the install.rdf file.
BTW, what is the point of creating a 'matching' manifest file for
javascript implementation if we have to declare the same component in
the chrome manifest. Can we reference to the JS manifest file like the
binary components.
Thanks.
--
Subrata
On 07/02/2010 02:51 PM, Benjamin Smedberg wrote:
> My question is which is the correct way to specify the class id. My
> guess is that Class Id should be enclosed in the braces like we do in
> the install.rdf file.
That is the recommended way, yes. They both work.
> BTW, what is the point of creating a 'matching' manifest file for
> javascript implementation if we have to declare the same component in
> the chrome manifest. Can we reference to the JS manifest file like the
> binary components.
In order to build the component list, we don't have to parse and execute the
JS in your component. This means that we can delay loading the JS component
until the app is in a stable started state:
* the profile location is known and all preferences are available at the top
level of the JS
* Components.utils.import("chrome://mypackage/content/foo.js") now works
correctly.
--BDS
I probably won't have time to update this code. If you need to work with
external libraries, I strongly recommend not using XPCOM components any
more; please consider using ctypes instead. If the external library
interface is straightforward, you can load it using JS directly. If it is a
c++ interface that cannot be scripted directly with ctypes you can insert a
shim which exports ctypes-friendly functions.
--BDS
If that's all, you could just predeclare them:
var NSGetModule, NSGetFactory;
if (XPCOMUtils.generateNSGetFactory)
NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
else
NSGetModule = XPCOMUtils.generateNSGetModule(components);
--BDS
I am disappointed in your response. My code already exists and I am
following a recommended approach. I am just looking for upgrade path to
Gecko 2.0. I thought that it would be just few small changes in the
original stub-loader code.
Since the XPCOM binary is loading is delayed in Gecko 2.0, would be be
possible to use Ctypes to force the loading of external library before
shared libraries for my XPCOM components.
Thanks.
--
Subrata
> I am disappointed in your response. My code already exists and I am
> following a recommended approach. I am just looking for upgrade path to
> Gecko 2.0. I thought that it would be just few small changes in the
> original stub-loader code.
I'm not saying it cannot be done. I'm saying that I do not have the time to
do it, and I strongly encourage you to move to ctypes, since that is going
to be a more stable solution in the future.
But if you want to implement a stub, you probably want to divide the pieces
like this:
Header:
#ifdef STUB_DLL
#define MY_IMPORT PR_IMPORT_DATA
#else
#define MY_IMPORT PR_EXPORT_DATA
#endif
extern MY_IMPORT(const mozilla::Module) kMyModule;
stub DLL:
extern "C" PR_EXPORT const mozilla::Module* NSModule;
static int run_for_side_effects()
{
// Load dependent libraries
NSModule = &kMyModule;
return 1;
}
int gIntToInitialize = run_for_side_effects();
real DLL:
MY_IMPORT(const mozilla::Module) kMyModule = {
... module data here...
};
> Since the XPCOM binary is loading is delayed in Gecko 2.0, would be be
> possible to use Ctypes to force the loading of external library before
> shared libraries for my XPCOM components.
No, I don't think so.
--BDS
Specially the secret mozilla folder with all needed files is wanted.
My favorite link is http://mxr.mozilla.org/mozilla-central/find?string=/ModuleUtils\.h....should
we use http://mxr.mozilla.org/mozilla-central/source/xpcom/components/ModuleUtils.h?
I have tryed to compile my xpcom extension dll with the firefox 4
changes.
I have take the xulrunner-2.0b2pre.en-US.win32.sdk and made a mozilla
folder with some headerfiles from mozilla-central.
When i compile i get the following errors:
c:\programme\gecko-sdk2.0b2\include\mozilla/mozalloc.h(107) : error
C3646: 'NS_ATTR_MALLOC' : unknown override specifier
c:\programme\gecko-sdk2.0b2\include\mozilla/mozalloc.h(107) : error
C3646: 'NS_WARN_UNUSED_RESULT' : unknown override specifier
ModuleUtils.h -> Module.h -> nsID.h -> nscore.h -> mozalloc.h
with Option MOZ_NO_MOZALLOC i get linker erros like this:
xpcomglue_s.lib(nsISupportsImpl.obj) : error LNK2001: unresolved
external symbol __imp__moz_xmalloc
xpcomglue_s.lib(nsISupportsImpl.obj) : error LNK2001: unresolved
external symbol __imp__moz_free
Have somebody an idea?
I've filed bug 577831. The first part is macros which should be added to
xpcom-config.h. The second part is interesting, because I'm guessing cjones
intends for you to link against mozalloc, but I'm not sure we ship that
library and I don't think you ought to be linking against it.
--BDS