Shutting down Firefox for Android¶
Background¶
Normally, apps on Android don’t need to provide any support for explicit quitting, instead they are just sent into the background where they eventually get killed by the OS’s low-memory killer.
Nevertheless, Firefox on Android allows explicit quitting to support the use case of users wanting to clear part or all of their private data after finishing a browsing session. When this option to “Clear private data on exit” is activated from the settings, a “Quit” button is provided in the menu.
Because Firefox on Android uses a native UI (written in Java), which also holds some of the user’s browsing data, this creates some additional complications when compared to quitting on desktop.
Technical details¶
When the “Quit” button is used, the UI sends a Browser:Quit notification to Gecko’s BrowserApp,
which initiates the normal Gecko shutdown procedure. At the same time however, the native UI needs to
shutdown as well, so as to
- provide an immediate visual feedback to the user that Firefox is indeed quitting
- avoid a state where the UI is still running “normally” while the rendering engine is already shutting down, which could lead to loosing incoming external tabs if they were to arrive within that period.
Therefore, shutdown of the native UI was originally started simultaneously with notifying Gecko.
Because the clearing of private data during shutdown is handled by Gecko’s Sanitizer, while some
private data, e.g. the browsing history, is held in a database by the native UI, this means that
Gecko needs to message the native UI during shutdown if the user wants the browsing history to be
cleared on quitting.
Shutting down the UI simultaneously with Gecko therefore introduced a race condition where the data
clearing could fail because the native UI thread responsible for receiving Gecko’s sanitization
messages had already exited by the time Gecko’s Sanitizer was attempting to e.g. clear the
user’s browsing history (for further reading, compare bug 1266594).
To fix this issue, the native UI (in GeckoApp) now waits for the Sanitizer to run and
message all necessary sanitization handlers and only starts its shutdown after receiving a
Sanitize:Finished message with a shutdown: true parameter set. While this introduces a
certain delay in closing the UI, it is still faster than having to wait for Gecko to exit completely
before starting to close the UI.
Currently, quitting Firefox therefore proceeds roughly as follows:
- The user presses the “Quit” button in the main menu, which sends a
Browser:Quitnotification toBrowserApp. This notification also contains additional parameters indicating which types of private user data - if any - to clear during shutdown. BrowserApp.quitruns, which initiates Gecko shutdown by sending out aquit-application-requestednotification.- If nobody cancelled shutdown in response to the
quit-application-requestednotification, quitting proceeds and theSessionStoreenters shutdown mode (STATE_QUITTING), which basically means that no new (asynchronous) writes are started to prevent any interference with the final flushing of data. BrowserAppcalls theSanitizerto clear up any private user data that might need cleaning. After theSanitizerhas invoked all required sanitization handlers (including any on the native Java UI side, e.g. for the browsing history) and finished running, it sends aSanitize:Finishedmessage back to the native UI.- On receiving the
Sanitize:Finishedmessage,GeckoAppstarts the shutdown of the native UI as well by callingdoShutdown(). - After sending the
Sanitize:Finishedmessage, Gecko’sSanitizerruns the callback provided byBrowserApp.quit, which isappStartup.quit(Ci.nsIAppStartup.eForceQuit), thereby starting the actual and final shutting down of Gecko. - On receiving the final
quit-applicationnotification, theSessionStoresynchronously writes its current state to disk.