Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added reference materials and supported platforms information for FDC3 in .NET via the [finos/fdc3-dotnet](https://github.com/finos/fdc3-dotnet) project. ([#1108](https://github.com/finos/FDC3/pull/1108))
* The supported platforms page in the FDC3 documentation was moved into the API section as the information it provides all relates to FDC3 Desktop Agent API implementations. ([#1108](https://github.com/finos/FDC3/pull/1108))
* FDC3 apps are now encouraged to instantiate their FDC3 interface (DesktopAgent) using the `getAgent()` function provided by the `@finos/fdc3` module. This will allow apps to interoperate in either traditional Preload DAs (i.e. Electron) as well as the new Browser-Resident DAs. ([#1191](https://github.com/finos/FDC3/pull/1191))
* SessionStorage use by `getAgent` was updated to scope the stored data by `window.name` and the app's `identityUrl`. ([#1442](https://github.com/finos/FDC3/pull/1442))

### Deprecated

Expand Down
33 changes: 30 additions & 3 deletions docs/api/ref/GetAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ A small number of arguments are accepted that can affect the behavior of `getAge
*
* @property {number} timeoutMs Number of milliseconds to allow for an FDC3
* implementation to be found before calling the failover function or
* rejecting (default 750). Note that the timeout is cancelled as soon as a
* rejecting (default 1000). Note that the timeout is cancelled as soon as a
* Desktop Agent is detected. There may be additional set-up steps to perform
* which will happen outside the timeout.
*
Expand Down Expand Up @@ -159,11 +159,34 @@ Failover functions MUST be asynchronous and MUST resolve to one of the following

## Persisted Connection Data

The `getAgent()` function uses [`SessionStorage`](https://html.spec.whatwg.org/multipage/webstorage.html) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)) to persist information on an instance of an app under the key `"FDC3-Desktop-Agent-Details"` and how it connected to a Desktop Agent in order to ensure a consistent connection type and `instanceId` when reconnecting after navigation or refresh events. Applications are not expected to interact with this information directly, rather it is set and used by the `getAgent()` implementation.
The `getAgent()` function uses [`SessionStorage`](https://html.spec.whatwg.org/multipage/webstorage.html) ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)) to persist information on an instance of an app and how it connected to a Desktop Agent in order to ensure a consistent connection type and `instanceId` when reconnecting after navigation or refresh events.

The details persisted conform to the following type:
:::warning
Apps do not need to and SHOULD NOT interact with data persisted in SessionStorage by `getAgent` directly, rather it is set and used by the `getAgent()` implementation.
:::

SessionStorage is used as for persistence as it is scoped to a single browser window and the current origin, ensuring apps in different windows or on different origins access different storage. However, as multiple iframes from the same-domain embedded within a window can share a SessionStorage instance, and multiple applications can be hosted on the same origin and be navigated to and from within a window, additional scoping is applied.

To differentiate storage for multiple iframes the name of the browsing context (`window.name`) is used to generate the key used in SessionStorage by concatenating the string `"FDC3-Desktop-Agent-Details-"` with `window.name`. The `window.name` remains stable during same-origin navigation and is persisted by the browser in its [session history](https://html.spec.whatwg.org/multipage/nav-history-apis.html#nav-traversal-apis) and is appropriate for scoping to a particular browsing context (window or iframe). Desktop Agents should assign a unique name to each window and iframe when they are created to facilitate such scoping. If no name is assigned, then the `getAgent` will assign a UUID as a unique name for that browsing context.

The data persisted is structured as an object conforming to the `SessionStorageFormat` type below, with the `identityUrl` of the app used as the key (if no `identityUrl` is provided the `actualUrl` is used instead), with the value conforming to the `DesktopAgentDetails` type. Hence, the data might be retrieved as follows:

```ts
const sessionData: SessionStorageFormat = sessionStorage.get("FDC3-Desktop-Agent-Details-myWindowName");
const agentDetails: DesktopAgentDetails = sessionStorage["myApIdentityUrl"];
Comment thread
kriswest marked this conversation as resolved.
Outdated
```

### Type Definitions

```ts
/** Type representing the format of data stored by `getAgent`
* in Session Storage. The `identityUrl` of each app is used
* as the key. */
type SessionStorageFormat = {
/** */
[key: string]: DesktopAgentDetails
}

/** Type representing data on the Desktop Agent that an app
* connected to that is persisted by the getAgent function
* to be used when re-connecting (after a navigation or
Expand Down Expand Up @@ -232,4 +255,8 @@ enum WebDesktopAgentType {
* function that was passed by the application. */
Failover = "FAILOVER"
}

const DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX = 'fdc3-desktop-agent-details';

const DEFAULT_TIMEOUT_MS = 1000;
```
14 changes: 13 additions & 1 deletion src/api/GetAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export type GetAgentType = (params?: GetAgentParams) => Promise<DesktopAgent>;
*
* @property {number} timeoutMs Number of milliseconds to allow for an FDC3
* implementation to be found before calling the failover function or
* rejecting (default 750). Note that the timeout is cancelled as soon as a
* rejecting (default 1000). Note that the timeout is cancelled as soon as a
* Desktop Agent is detected. There may be additional set-up steps to perform
* which will happen outside the timeout.
*
Expand Down Expand Up @@ -91,6 +91,14 @@ type GetAgentParams = {
failover?: (args: GetAgentParams) => Promise<WindowProxy | DesktopAgent>;
};

/** Type representing the format of data stored by `getAgent`
* in Session Storage. The `identityUrl` of each app is used
* as the key. */
export type SessionStorageFormat = {
/** */
[key: string]: DesktopAgentDetails
}

/** Type representing data on the Desktop Agent that an app
* connected to that is persisted by the getAgent function
* to be used when re-connecting (after a navigation or
Expand Down Expand Up @@ -159,3 +167,7 @@ export enum WebDesktopAgentType {
* function that was passed by the application. */
Failover = 'FAILOVER',
}

export const DESKTOP_AGENT_SESSION_STORAGE_KEY_PREFIX = 'fdc3-desktop-agent-details';

export const DEFAULT_TIMEOUT_MS = 1000;