Profile, XPCOM Startup and Extensions

Darin Fisher & Ben Goodger, 05/12/2004

Goal

To provide version-safe XPCOM startup and component registration with a simplified Profile system for Firefox 1.0.

Background, and Concerns

Changes should be as minimal as possible. Firefox 0.9 needs to ship "feature complete" and operational at the end of the first week of June, in order to meet a 1.0 release date of mid-September 2004. If we miss mid-September, there will be irreconcilable marketing and PR consequences that I cannot discuss, and we will not be able to ship until mid November.

Years of experience with this codebase has shown that big patches have a much higher incidence of follow-on problems because the set of problems that they contain and the rate at which they can be identified and resolved is not purely linear. While one might assume x errors per y lines of code, when one checks in a series of smaller patches those errors are considerably easier to identify if they cause problems, and the patches can be easily identified as the cause of problems, larger patches mean that a larger set of problems need to be isolated at the same time within a larger set of code.

The Proposal

Darin and I discussed how profile and XPCOM startup might work with an Extension manager based only on what is logically required.

We discovered three core areas where code is needed:

  1. A new simplified profile implementation.
  2. Version checking and identification of components directories to initialize XPCOM with.
  3. A cross platform way to restart the application.

Other elements, while idealistically desirable (such as a split appshell) are better suited for testing and development on the trunk until the 1.0 branch is on a strong, secure trajectory towards the September final release.

Based on the logical requirements here is a diagram showing how application startup is handled:

  1. AppRunner starts.
  2. The New Profile System (1) starts, determines a profile to be used. If no profile is supplied, the Profile System can take whatever steps it deems necessary to determine one - in Firefox's case this might be as simple as checking the Profile list for an item annotated as being the default, in a hypothetical future Thunderbird use this might include spinning up a profile manager UI and having the user select. In this case XPCOM is initialized with the default compreg.dat and xpti.dat, and once a profile is selected the app is restarted with that profile.
  3. A Compatibility Manifest(1) is read and the LastVersion key within that file is compared to the version compiled into the app.(2)

Branch 1 - Versions Are NOT Equal

  1. The compreg.dat and xpti.dat files in the given Profile directory are removed,
  2. The Compatibility Manifest is written with a LastVersion key that matches the current executing version of the app,
  3. An instance of nsXREDirProvider implementing nsIDirectoryServiceProvider2 is created that returns nsnull for the "ComsDL" property. (3) This ensures all extension components are disabled before XPCOM is initialized to prevent any compatibility problems that might be encountered by those components' app-startup category handlers.
  4. XPCOM is Initialized
  5. The Extension Manager is invoked and asked to check for mismatches.
  6. The Extension Manager writes a new Component Manifest (a file containing a list of paths that contain components to register) that contains only paths for compatible, enabled Extensions.
  7. The Extension Manager does its own internal disabling of incompatible items that it needs to do to maintain its own internal state. That is irrelevant to this proceeding.
  8. The Extension Manager's compatibility checking function returns a value indicating the application needs to be restarted.
  9. AppRunner code handles that, restarts the app and execution begins at the start of this loop but this time it runs through Branch 2

Branch 2 - Versions ARE Equal

  1. Either the app started normally last time, or there was a new version and the previous start ran the Extension Manager's compatibility checker in Branch 1 of a previous start. Either way, here we are.
  2. The Compatibility Manifest is checked for a flag that specifies that the Component Manifest has been changed since the last start. This implies a major event - e.g. an extension has been disabled, enabled, installed, uninstalled, or Branch 1 was executed on a previous start.
  3. If the Component Manifest has changed, the compreg.dat and xpti.dat files are removed, the Component Manifest it is parsed and when our instance of nsXREDirProvider is asked by XPCOM for the "ComsDL" property will return an enumeration of all of the paths specified in the Component Manifest.
  4. If the Component Manifest has not changed, nothing is done here.
  5. XPCOM is Initialized.
  6. If XPCOM needs to rebuild the Component Registry (i.e. the Compatibility Manifest has changed) it asks our XREDirProvider for the list of locations to register components in - in addition to the default locations. This generates a new, up-to-date compreg.dat.

All XPCOM Component/Profile related operations are now complete. Before the profile is completely selected, i.e. in the analog of "profile-do-change" before any of the services have had the chance to obtain locks on files the Extension Manager might need to change, the Extension Manager performs any of its own internal state management and Extension Installation/Uninstallation/Disabling/Enabling finalization.

The app now starts fully.

Application Restart

This document has given fairly in-depth coverage of how the control flows through the startup process with respect to registering components. We have treated the restart operation as something that can be factored into a method that can be called in a cross platform manner. There may be implications with DDE on Windows - if the app needs to be restarted DDE maybe be running for the initial instance which does not have the ability to respond to DDE messages. Thus we need to ensure in any restart process that if DDE has been initialized as a server it is properly shut down.

 

1 - this file can be in the same format as the New Profile System uses if there is a convenient shared reader utility available.
2 - The degree of granularity is a unique version for each release, and a version for the development period in between releases. (e.g. 0.8.0+)
3 - "ComsDL" is designed to return an enumeration of additional components directories to register components in - returning nsnull here tells the Component Manager to register only the default location(s).