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

XPCOM Registration Changes Landed

21 views
Skip to first unread message

Benjamin Smedberg

unread,
Jul 2, 2010, 2:51:22 PM7/2/10
to
The change to XPCOM registration in bug 568691 has landed. This means that
any extension which has XPCOM components will need to be modified to work in
mozilla-central nightlies and Firefox 4.0beta2.

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

johnjbarton

unread,
Jul 2, 2010, 3:19:04 PM7/2/10
to

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

Benjamin Smedberg

unread,
Jul 2, 2010, 3:42:32 PM7/2/10
to
On 7/2/10 3:19 PM, johnjbarton wrote:

> 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

John J Barton

unread,
Jul 2, 2010, 4:54:54 PM7/2/10
to

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

Benjamin Smedberg

unread,
Jul 2, 2010, 5:09:48 PM7/2/10
to
On 7/2/10 4:54 PM, John J Barton wrote:

> 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

johnjbarton

unread,
Jul 3, 2010, 12:27:38 AM7/3/10
to
On 7/2/2010 12:42 PM, Benjamin Smedberg wrote:
> On 7/2/10 3:19 PM, johnjbarton wrote:
>
>> 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);

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

Nils Maier

unread,
Jul 3, 2010, 10:51:23 AM7/3/10
to


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

Mook

unread,
Jul 4, 2010, 2:20:44 AM7/4/10
to
On 2010-07-03 7:51 AM, Nils Maier wrote:
> 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

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

Neil

unread,
Jul 4, 2010, 6:05:39 AM7/4/10
to
Benjamin Smedberg wrote:

> 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.

Neil

unread,
Jul 4, 2010, 6:13:10 AM7/4/10
to
Benjamin Smedberg wrote:

> 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?

Benjamin Smedberg

unread,
Jul 4, 2010, 8:25:56 AM7/4/10
to
On 7/4/10 6:05 AM, Neil wrote:

> 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

Benjamin Smedberg

unread,
Jul 4, 2010, 8:29:35 AM7/4/10
to
On 7/4/10 6:13 AM, Neil wrote:

> 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

Benjamin Smedberg

unread,
Jul 4, 2010, 8:31:14 AM7/4/10
to
On 7/4/10 2:20 AM, Mook wrote:

> 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

Neil

unread,
Jul 4, 2010, 4:37:45 PM7/4/10
to
Benjamin Smedberg wrote:

> 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.]

Neil

unread,
Jul 4, 2010, 4:48:31 PM7/4/10
to
Benjamin Smedberg wrote:

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]));

Nils Maier

unread,
Jul 4, 2010, 6:15:56 PM7/4/10
to

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

KWierso

unread,
Jul 4, 2010, 8:42:46 PM7/4/10
to
On Jul 2, 1:51 pm, Benjamin Smedberg <benja...@smedbergs.us> wrote:
> if you find this page confusing, please let me know so that I can
> make it better and answer the right questions.

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.

Philip Chee

unread,
Jul 4, 2010, 10:00:01 PM7/4/10
to
On Sun, 4 Jul 2010 17:42:46 -0700 (PDT), KWierso wrote:
> On Jul 2, 1:51 pm, Benjamin Smedberg <benja...@smedbergs.us> wrote:
>> if you find this page confusing, please let me know so that I can
>> make it better and answer the right questions.
>
> Could an/some examples be posted on how to convert components to the
> new way without using XPCOMUtils.jsm?

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.

<http://www.mozdev.org/source/browse/console2/src/console2/components/console2-clhandler.js?view=markup&rev=1.4>

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

Neil

unread,
Jul 5, 2010, 9:16:48 AM7/5/10
to
Nils Maier wrote:

>I don't really see a point of "deferring" the gNGF call
>

I just don't like putting var statements in conditional branches.

Neil

unread,
Jul 5, 2010, 9:25:07 AM7/5/10
to
KWierso wrote:

>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.

Nils Maier

unread,
Jul 5, 2010, 12:08:00 PM7/5/10
to
Am 05.07.2010 15:16, schrieb Neil:
> Nils Maier wrote:
>
>> I don't really see a point of "deferring" the gNGF call
>>
> I just don't like putting var statements in conditional branches.
>

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 ;)

johnjbarton

unread,
Jul 5, 2010, 12:28:12 PM7/5/10
to
On 7/5/2010 9:08 AM, Nils Maier wrote:
> Am 05.07.2010 15:16, schrieb Neil:
>> Nils Maier wrote:
>>
>>> I don't really see a point of "deferring" the gNGF call
>>>
>> I just don't like putting var statements in conditional branches.
>>
>
> Well, I second that, but I don't care that much to code up alternatives.

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

Subrata Mazumdar

unread,
Jul 5, 2010, 7:06:01 PM7/5/10
to
Hi,
I use stub-loader for dependent libraries in my extension (as described
in
https://developer.mozilla.org/en/Using_Dependent_Libraries_In_Extension_Components).

Can we have an updated version this document for Gecko_2.0?
Thanks.
--
Subrata

Subrata Mazumdar

unread,
Jul 5, 2010, 10:51:04 PM7/5/10
to
I was trying to create manifest for JS implementation and noticed that
the content of nsSample.manifest (
http://mxr.mozilla.org/mozilla-central/source/xpcom/sample/nsSample.manifest
) does not match the description for chrome.manifest in
https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0#JavaScript_Components.

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:

Benjamin Smedberg

unread,
Jul 7, 2010, 8:31:52 AM7/7/10
to
On 7/5/10 10:51 PM, Subrata Mazumdar 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

Benjamin Smedberg

unread,
Jul 7, 2010, 8:35:11 AM7/7/10
to
On 7/5/10 4:06 PM, Subrata Mazumdar wrote:
> Hi,
> I use stub-loader for dependent libraries in my extension (as described
> in
> https://developer.mozilla.org/en/Using_Dependent_Libraries_In_Extension_Components).
>
>
> Can we have an updated version this document for Gecko_2.0?
> Thanks.

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

Benjamin Smedberg

unread,
Jul 7, 2010, 8:36:14 AM7/7/10
to
On 7/5/10 6:16 AM, Neil wrote:
> Nils Maier wrote:
>
>> I don't really see a point of "deferring" the gNGF call
>>
> I just don't like putting var statements in conditional branches.
>

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

Subrata Mazumdar

unread,
Jul 7, 2010, 12:57:27 PM7/7/10
to

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

Benjamin Smedberg

unread,
Jul 7, 2010, 2:48:02 PM7/7/10
to
On 7/7/10 9:57 AM, Subrata Mazumdar wrote:

> 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

Subrata Mazumdar

unread,
Jul 8, 2010, 2:52:42 PM7/8/10
to
Thanks, will explore the solution based on your suggestion.
--
Subrata

TheRave

unread,
Jul 9, 2010, 12:28:06 PM7/9/10
to
Where i can find a the gecko-sdk2.0?

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?

TheRave

unread,
Jul 10, 2010, 5:40:32 AM7/10/10
to
> we usehttp://mxr.mozilla.org/mozilla-central/source/xpcom/components/Module...

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?

Benjamin Smedberg

unread,
Jul 10, 2010, 12:06:02 PM7/10/10
to
On 7/10/10 2:40 AM, TheRave wrote:
> 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

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


0 new messages