1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
.. -*- Mode: rst; fill-column: 100; -*-
===================================
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
1) provide an immediate visual feedback to the user that Firefox is indeed quitting
2) 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
<https://bugzilla.mozilla.org/show_bug.cgi?id=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:
1) The user presses the "Quit" button in the main menu, which sends a ``Browser:Quit`` notification
to ``BrowserApp``. This notification also contains additional parameters indicating which types
of private user data - if any - to clear during shutdown.
2) ``BrowserApp.quit`` runs, which initiates Gecko shutdown by sending out a
``quit-application-requested`` notification.
3) If nobody cancelled shutdown in response to the ``quit-application-requested`` notification,
quitting proceeds and the ``SessionStore`` enters shutdown mode (``STATE_QUITTING``), which
basically means that no new (asynchronous) writes are started to prevent any interference with
the final flushing of data.
4) ``BrowserApp`` calls the ``Sanitizer`` to clear up any private user data that might need cleaning.
After the ``Sanitizer`` has invoked all required sanitization handlers (including any on the
native Java UI side, e.g. for the browsing history) and finished running, it sends a
``Sanitize:Finished`` message back to the native UI.
5) On receiving the ``Sanitize:Finished`` message, ``GeckoApp`` starts the shutdown of the native UI
as well by calling ``doShutdown()``.
6) After sending the ``Sanitize:Finished`` message, Gecko's ``Sanitizer`` runs the callback provided
by ``BrowserApp.quit``, which is ``appStartup.quit(Ci.nsIAppStartup.eForceQuit)``, thereby
starting the actual and final shutting down of Gecko.
7) On receiving the final ``quit-application`` notification, the ``SessionStore`` synchronously
writes its current state to disk.
|