Multiple breaking changes are coming for components in extensions

Are you an extension or application developer? Have you written any XPCOM components, JS, binary or otherwise? If not you can probably ignore the rest of this post, unless you are interested anyway.

If you do then you might be interested to hear that your components are probably going to break in an upcoming Firefox nightly, maybe as early as next week. I’m going to blog specific examples on the changes you need to make once we have better documentation up and builds to test against, for now it is just important for you to know that the changes are coming.

Changing XPCOM component registration

One of the things we are doing is changing how XPCOM components are registered. Previously during registration we would load all binary and JS component files and call them asking them to register themselves. If you used XPCOMUtils.jsm then some of that ugliness will have been hidden from you. The future though will be registration using manifest files, similar to how chrome is registered (in the same files in fact). Every single JS or binary component will need fixes to support this. The amount of work to do is fairly trivial per component and it is possible to support both old and new styles of registration in the same component but until that work is done your components will not work.

Starting extension components later

Currently there are a bunch of different notifications that components can listen for to perform actions during startup. Commonly xpcom-startup, app-startup and profile-after-change have been the most common. The latter is generally the best to use since this is one of the earliest notifications that occurs after the profile folder (and hence preferences and other services) is available.

The news is that once we make our changes components from extensions will no longer be able to register for and receive the xpcom-startup or app-startup notifications at all. profile-after-change will be the first notification that components can be loaded by.

Most of the reasons for loading on app-startup were either because developers didn’t know about profile-after-change or at one point it used to be necessary to load for app-startup just to be able to register for profile-after-change in the observer service. That is no longer the case as you can register for it in the category manager exactly as you can for app-startup.

Why?

You might well ask why we are making all these changes.

Currently whenever we detect a potential change in the set of usable components (meaning either the application version has changed or an extension has been added/removed/enabled/disabled) we must throw away existing component registrations and then perform what has become known as the EM restart where the application is restarted during its startup (in theory invisibly to the user) to make sure that any component that weren’t meant to be loaded are unloaded and to re-register everything and load any new components that need it.

Registration is itself a costly process since every component must be loaded and executed when really many if not most of them do not need to be loaded during startup. In the E10S world there are even more problems. Content processes must either register all components during every startup or somehow share a component cache with the chrome process.

The new registration model allows us to do away with the EM restart. On startup rather than relying on a potentially stale component cache we will read the registrations for the main application out of a manifest file. This will give us enough of XPCOM to then be able to load the extension manager and do any necessary work to install/uninstall/update any extensions after which we can simply load the component registrations for those out of the manifest file. Startup then just proceeds as normal, no restart is necessary since nothing from extensions can have been loaded when it shouldn’t.

E10S content processes can just read the component registrations during startup, since they are in simple manifest files this will go a lot faster

25 comments on “Multiple breaking changes are coming for components in extensions”

  1. Philip Chee wrote on

    I’ve a command line handler component.

    1. Is there an example for how to do this post change?

    2. Can I have one component that contains both methods of registration so that I don’t need to do two versions (or three) versions of my extension one for each of Firefox 3.5, 3.6 and 3.7/4.0?

    Phil

    1. Dave Townsend wrote on

      I’ll blog about specific examples once we’re sure there won’t be any further changes to avoid confusion. I mainly wanted to make sure people were aware that this was coming and that they need to keep an eye out for updates over the next week.

      Components can support both styles of registration too.

  2. j wrote on

    how does this work for binary components in the platform folder, can one just list all components and only the once for the right platform get loaded?

    1. Dave Townsend wrote on

      As before you should be able to use platform specific subdirectories to handle this, but now you would also be able to use the OS tests in the manifest file to achieve the same thing

  3. Wladimir Palant wrote on

    I guess “dynamic” registration of components via nsIComponentRegistrar and nsICategoryManager doesn’t change? If so then these changes should be sufficient for Adblock Plus: https://hg.adblockplus.org/adblockplus/rev/56ee081b763c

  4. Wladimir Palant wrote on

    PS: This way to specify GUIDs is inconsistent – chrome.manifest usually uses the {00000000-0000-0000-0000-000000000000} form (with brackets), particularly for application identifiers.

    1. Dave Townsend wrote on

      That’s a good point, I’ll make sure that is taken into account

  5. Guenter wrote on

    With ReminderFox we have the same situation as Philip Chee described! A commandLine handler.
    So same questions as he has!

  6. Ray wrote on

    What is the tracking or meta bug for this for when this is first to land? Thanks.

    1. Dave Townsend wrote on

      https://bugzilla.mozilla.org/show_bug.cgi?id=568691 is probably the main bug of interest. Unless any problems come up in review the hope is to land early next week.

      1. Ray wrote on

        Thank, Dave.

  7. Michael wrote on

    In which Firefox version will this change be included?

    1. Dave Townsend wrote on

      Firefox 4.0, likely in the first beta release.

  8. U wrote on

    “your components are probably going to break in an upcoming Firefox nightly”

    When will these changes be implemented in a release version of Firefox (one that end-users use, like 3.6.4 etc.)?

    1. Benjamin Smedberg wrote on

      These changes have landed on trunk and will be in Firefox 4.0 beta 2 (and then Firefox 4.0). They will not be backported to the Firefox 3.6 stable releases.

  9. j wrote on

    why is {classId} required for javascript components but not for binary components?

    component {classId} some.js
    vs
    binary-component some.so

    1. Benjamin Smedberg wrote on

      The registration information for binary components is located in a binary table within the component itself. The manifest merely points to the binary and says “go get registration data from there”. This is done so that binaries which fail to load (because of missing dependencies, most often) don’t register.

      For JS components, it’s the other way around: we want all the registration data in the manifest file so that we don’t have to load the JS component until it is actually required. This also help make certain features such as Components.utils.import work consistently.

  10. juan wrote on

    Hi!

    I have a command line handler component that worked perfectly on Beta 1 version of Firefox 4, but now that Beta 2 is out, it just stopped working.

    Any idea why?

    The registration lines at chrome.manifest file are look like these:

    interfaces components/myArgumentsHandler.xpt

    component {UUID-GOES-HERE} components/myArgumentHandler.js
    contract @mozilla.org/commandlinehandler/general-startup;1?type=myarghandler {UUID-GOES-HERE}
    category profile-after-change MyArgumentHandler @mozilla.org/commandlinehandler/general-startup;1?type=myarghandler

    The reason why I also declared the xpt file is because my handler holds some flags depending on the arguments passed to firefox, and I query the component for these flags from the extension, so I had to create an idl file to declare the flags being held.

    The point is that it worked just fine in Beta 1 and now it doesn’t on Beta 2.

    Please help!

    1. Mossop wrote on

      I would suggest either filing a bug or starting a discussion in the newsgroups so we can track down what the problem might be.

      1. juan wrote on

        Hi

        what’s the url for the newsgroups?

        and where can I file the bug (bugzilla.mozilla.org)?

        Thanks

        1. juan wrote on

          Well, I managed to make my command line handler work. I had a look at Firefox’s browser.manifest file (inside the components folder in the installation folder) to see how the default command line handler is registered, then changed the registration entries to make them match my component.

          Here are the chrome.manifest lines that made my command line handler work:

          component {UUID-GOES-HERE} components/ebayArgumentHandler.js
          contract @mozilla.org/commandlinehandler/general-startup;1?type=myarghandler {UUID-GOES-HERE}
          category command-line-handler m-myarghandler @mozilla.org/commandlinehandler/general-startup;1?type=myarghandler

          the only differences are in the “category” line, where I used “command-line-handler” instead of “profile-after-change” and use the XPCOM category’s entry name (m-myarghandler) instead of the component name (MyArgumentHandler)

          If your command line handler worked in Firefox 3, you shouldn’t have much difficulties adapting the previous lines to fit your needs.

          It wasn’t very difficult and now that I made it work it seems kind of obvious, but some documentation about this would certainly help a lot to save hours of research and frustration to other developers :P.

  11. Alexander wrote on

    Hello!

    I added the following lines to manifest file:

    interfaces components/icomponent.xpt
    binary-component components/component.dll

    but my component is still can’t be registered. What is the reason?

    1. Manish wrote on

      Hi Alexander, did you find solution to this one , I am having the same problem?Thanks.

  12. Gal wrote on

    Hi,

    I’m using XPCOM,
    Can I support old versions and new version of FF in one xpi ?
    I mean must I change the current code, or can I add the new way to the existing one ?

    If I must use 2 xpi files, how does it work when a user arrives to Mozilla to download or to upgrade the addon ? can I give Mozilla 2 xpi file one for each version of FF, and they will know what to install ?

    Gal

  13. Sudip wrote on

    Hi ,

    Can any one please help me with the answer? , my question is , How to check the component has registered or not in FireFox 4.0 b 11?
    I am not able find any compreg.dat and xpi.dat in FireFox 4.0 b11 , Please help me i am getting stuck with this
    Thanks in Advance