# Restoring Data

Restoring consists of two steps:

1. Restore session history, which is handled in the {searchfox}`Session History module <toolkit/modules/sessionstore/SessionHistory.sys.mjs>`.
2. Restore the other collected data, which is handled in {searchfox}`SessionStoreUtils.webidl <dom/chrome-webidl/SessionStoreUtils.webidl>` and {searchfox}`SessionStoreUtils.cpp <toolkit/components/sessionstore/SessionStoreUtils.cpp>`

The reason for this is that restoring the session history implies navigating to the location of the restored active session history entry, and it's only possible to restore the state of the page after that navigation is complete.

Doing this is accomplished by calling `SessionHistory.restoreFromParent` followed by `SessionStoreUtils.initializeRestore`. `restoreFromParent` and `initializeRestore` aren't tightly coupled, and will work in separate situations. `restoreFromParent` will do just what it says, restore the session history initiated from the parent process and `initializeRestore` will load the tab and restore the saved state of a document tree separately. These steps can in turn be made arbitrarily complicated, depending on a lot of different parameters:

- Restoring several windows
- Restoring several tabs
- Restoring the currently selected tab
- ... and so on

but in the end it's just a matter of restoring the session history, reloading the tab and restoring document tree state.

The following (very) simplified sequence diagram illustrates the abstract control flow:

```{eval-rst}
.. mermaid::

   ---
   title: Session Store Restore Steps
   ---
   sequenceDiagram
       box Tab
       participant Parent
       participant Content
       end

       Parent->>Parent: SessionHistory.restoreFromParent
       Parent->>Parent: SessionStoreUtils.initializeRestore

       loop RestoreTabContentObserver::Observe
       Content->>Parent: PWindowGlobal.requestRestoreTabContent
       Parent->>Content: PWindowGlobal.restoreTabContent
       end
```

Restoring is a load order recursive procedure, and the validity of a restore is checked for every document that has restore data. If a document doesn't match its stored session history entry, restore is skipped for that document.

## Calling `SessionHistory.restoreFromParent`

`SessionHistory.restoreFromParent` expects the following arguments:

```webidl
partial interface SessionHistory {
  undefined restoreFromParent(history, tabData);
};
```

- `history` is the session history object
- `tabData` is the tabdata including all history entries.

The format of `history` isn't relevant, but it is the idl interface {searchfox}`nsISHistory <docshell/shistory/nsISHistory.idl>`.

The format of `tabData` is an object literal with the corresponding interface:

```webidl
interface {
  sequence<nsISHEntry> entries;
  long requestedIndex;
  long index;
  long fromIdx;
}
```

All this data is available when the embedder receives a call from `nsISessionStoreFunctions.UpdateSessionStore` as described in {ref}`interacting-with-sessionstore`.

## Calling `SessionStoreUtils.initializeRestore`

`SessionStoreUtils.initializeRestore` expects the following arguments:

```webidl
partial interface SessionStoreUtils {
  Promise<undefined> initializeRestore(CanonicalBrowsingContext browsingContext,
                                       nsISessionStoreRestoreData? data);
};
```

- `browsingContext` is the top browsing context for the tree to restore
- `data` is the collected data.

The `data` argument is an object described by the idl interface:

```webidl
interface nsISessionStoreRestoreData : nsISupports {
  // Setters for form data.
  attribute AUTF8String url;
  attribute AString innerHTML;

  // Setters for scroll data.
  attribute ACString scroll;

  // Methods for adding individual form fields which are called as the JS code
  // finds them.
  void addTextField(in boolean aIsXPath, in AString aIdOrXPath,
                    in AString aValue);
  void addCheckbox(in boolean aIsXPath, in AString aIdOrXPath,
                   in boolean aValue);
  void addFileList(in boolean aIsXPath, in AString aIdOrXPath, in AString aType,
                   in Array aFileList);
  void addSingleSelect(in boolean aIsXPath, in AString aIdOrXPath,
                       in unsigned long aSelectedIndex, in AString aValue);
  void addMultipleSelect(in boolean aIsXPath, in AString aIdOrXPath,
                         in Array aValues);
  void addCustomElement(in boolean aIsXPath, in AString aIdOrXPath,
                        in jsval aValue, in jsval aState);
  // Add a child data object to our children list.
  void addChild(in nsISessionStoreRestoreData aChild, in unsigned long aIndex);
};
```

All this data is available when the embedder receives a call from `nsISessionStoreFunctions.UpdateSessionStore` as described in {ref}`interacting-with-sessionstore`.
