Browser Startup

How do first run/first startup experiments work?

Why does synchronously reading Nimbus feature values work for customizing display features like about:welcome onboarding and the default browser prompt? The key invariant is that the display decisions wait for sessionstore-windows-restored to show customizable UI, and therefore we just need Nimbus available to read at that point. This is arranged either via the --first-startup flag; or, for subsequent startups, the relevant Nimbus features being marked isEarlyStartup: true. When isEarlyStartup: true, Nimbus caches all its feature variables as Gecko preferences, ready to be read during early startup. (See the early startup docs.)

Customizable display features like about:welcome or the default browser prompt are used in _maybeShowDefaultBrowserPrompt(), which is invoked as part of a startup idle task. Startup idle tasks are scheduled in response to sessionstore-windows-restored.

Now, why is sessionstore-windows-restored late enough for a first startup experiment? The answer is subtle.

During Firefox launch, final-ui-startup is notified, and in response SessionStore is initialized. Additionally, Nimbus/Normandy initialization is started but not awaited.

Then the command line is handled. When --first-startup is passed, we spin the event loop to allow Nimbus/Normandy time to complete its initialization and first fetch before continuing to process the command line. See the FirstStartup module. (Important caveat: --first-startup is only used on Windows; see Bug 1872934, for example.)

This races with SessionStore, which itself waits for the first browser window to be shown – in particular, the sessionstore-windows-restored notification waits for the first browser window’s browser-delayed-startup-finished notification.

This first browser-delayed-startup-finished notification is not guaranteed to be after --first-startup has spun the event loop! But, when launched with only --first-startup and flags considered very early in nsAppRunner.cpp – as the stub installer does – then the first window is guaranteed to be after the event loop has been spun, and therefore sessionstore-windows-restored is after as well. (As a counter-example: try firefox.exe --browser --first-startup and witness the --browser flag creating a window before spinning the event loop, inadvertently racing against sessionstore-windows-restored.) Making this deterministic is tracked by Bug 1944431.

Together, this means that first-startup experiments will be loaded in time to impact display features such as about:welcome and the default browser prompt, and we should not have a “split brain” scenario in which the Nimbus feature is intermittently unavailable to the relevant display features.