-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Window Management
The Firefox iOS client supports multiple windows on iPad devices. This feature brought with it several key changes to the app architecture which will be discussed in further detail below.
The management of UUIDs is a critical component of Firefox iOS, since each window contains its own unique set of tabs and manages its own set of events and notifications. For these reasons, a window must be uniquely identifiable by its UUID. The diagram below provides a simplified overview of how UUIDs are established whenever a new window is created (or a previously used window is restored).

Our UISceneDelegate entry point is the topmost hook that iOS provides to signal to the client that a new window (scene) is being connected in the client. This triggers the creation of the scene's SceneCoordinator
, which in turn calls into the ubiquitous WindowManager
to "reserve" a UUID for the window that is being created.
This process is referred to as "UUID reservation" because the process of configuring and launching a new window is not synchronous, and actually takes place over several iterations of the main thread run loop. The implications of this are important, since multiple windows can potentially be restored simultaneously, before the first window is actually finished.
The WindowManager
, upon receiving a request for a new window UUID, "reserves" a UUID and ensures that UUID won't be supplied to any other requests for other windows. To determine the specific UUID, it taps the TabDataStore
to check for on-disk window data. The associated UUIDs for these windows, along with ordering preferences stored in UserDefaults
, are used to allow multiple windows (and their tabs) to be closed and re-opened on iPad in the correct order.
Once a window that is being created has "reserved" its UUID, this is stored initially on the SceneCoordinator, and then once the browser is launched, the critical / topmost sub-components are created and this UUID is injected into those. These key components include:
- The window's unique TabManager instance
- The
BrowserCoordinator
- The
BrowserViewController
instance
From here, the UUID is further injected down the object dependency graph to allow any component to identify which window it belongs to in a multi-window environment.
There are a few distinct UUIDs which are used for special purposes in the app. These are defined in WindowUUID+Extension.swift
and discussed further below:
Unavailable UUID ("E1E1E1E1-E1E1-E1E1-E1E1-CD68A019860B"
)
During early multi-window planning, we were faced with the choice of allowing UUIDs to be optional throughout the architecture (so that some events would be allowed to have no associated UUID at all), or to always enforce non-optional UUIDs and use a sentinel placeholder UUID in cases where an actual UUID wasn't available. The latter was opted for, because it provides additional safety mechanisms, and simplifies code (we don't need to unwrap optionals every time a UUID is referenced, since everything can be guaranteed to have a UUID).
However, some events or notifications are posted (or received) in a way that can't or shouldn't directly be associated with a specific window, or may apply to all windows. An example of this might be an event that originates from a widget, outside the app, or even internally to the app but in a way that is app-specific rather than window-specific.
In these scenarios, the .unavailable
UUID should be used. It is easily identifiable in logs due to its E1E1E1E1 prefix. In general, uses of this sentinel value should be rare and handled very carefully. But it is available as a last resort for scenarios where there is no correct way to associate a single window.
XCTestDefaultUUID & DefaultUITestingUUID
These two UUIDs are provided for unit testing and UI testing purposes, respectively.