Skip to content

Commit

Permalink
Merge pull request #1349 from finos/fdc3-for-web-impl-refactor-rm
Browse files Browse the repository at this point in the history
Merging Kris' Latest Additions - Several tests are now failing due to changes in the raise intent model
  • Loading branch information
robmoffat authored Sep 12, 2024
2 parents 154c59f + 166cbfa commit 0e73f82
Show file tree
Hide file tree
Showing 72 changed files with 1,812 additions and 2,046 deletions.
14 changes: 7 additions & 7 deletions docs/agent-bridging/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ In any Desktop Agent Bridging scenario, it is expected that each DA is being ope

The Desktop Agent Bridging Part of the FDC3 Standard is composed of three components:

- **[Connection](#connection)**: A means for Desktop Agents to communicate with a bridge, and through that bridge, with each other.
- **[Connection Protocol](#connection-protocol)**: A protocol defining message exchanges necessary to connect to a Bridge and to perform initial state synchronization.
- **[Messaging Protocol](#messaging-protocol)**: A protocol defining message exchanges that allow FDC3 API interop to extend across multiple Desktop Agents.
- **[Bridge Connection](#connection)**: A means for Desktop Agents to communicate with a bridge, and through that bridge, with each other.
- **[Bridge Connection Protocol (BCP)](#bridge-connection-protocol)**: A protocol defining message exchanges necessary to connect to a Bridge and to perform initial state synchronization.
- **[Bridge Messaging Protocol (BMP)](#bridge-messaging-protocol)**: A protocol defining message exchanges that allow FDC3 API interop to extend across multiple Desktop Agents.

Detail on each of these components is defined in the following sections.

Expand All @@ -69,7 +69,7 @@ Agent Bridging is introduced in FDC3 2.1 as an [@experimental](../fdc3-complianc

### JSON Message Protocol & JSON Schema

The connection and messaging protocols that the Desktop Agent Bridging Part defines are based on messages encoded in JSON. [JSON Schema](https://json-schema.org/) is used to define the format of each message in the protocol and should be considered the 'source of truth' for each and may be used to validate that individual messages are in the correct format. However, examples are provided in the documentation in TypeScript and JavaScript formats for convenience. TypeScript interfaces for individual messages, included in the FDC3 NPM module, are generated from the JSON Schema source files using [quicktype](https://quicktype.io/).
The Bridge Connection Protocol (BCP) and Bridge Messaging Protocols (BMP) that the Desktop Agent Bridging Part defines are based on messages encoded in JSON. [JSON Schema](https://json-schema.org/) is used to define the format of each message in the protocol and should be considered the 'source of truth' for each and may be used to validate that individual messages are in the correct format. However, examples are provided in the documentation in TypeScript and JavaScript formats for convenience. TypeScript interfaces for individual messages, included in the FDC3 NPM module, are generated from the JSON Schema source files using [quicktype](https://quicktype.io/).

## Connection

Expand Down Expand Up @@ -156,7 +156,7 @@ Both DAs and bridge implementations SHOULD support at least connection to the re

As the bridge binds its websocket on the loopback address (127.0.0.1) it cannot be connected to from another device. Hence, an instance of the standalone bridge may be run on each device and those instances exchange messages by other means in order to implement the bridge cross-device.

## Connection Protocol
## Bridge Connection Protocol

On connection to the bridge's websocket, a handshake must be completed that may include an authentication step before a name is assigned to the Desktop Agent for use in routing messages. The purpose of the handshake is to allow:

Expand Down Expand Up @@ -435,7 +435,7 @@ Desktop Agents SHOULD provide visual feedback to end users when they or other ag

Although not part of the connection protocol, it should be noted that the `connectedAgentsUpdate` message sent in step 6 should also be sent whenever an agent disconnects from the bridge to update other agents. If any agents remain connected, then the `channelState` does not change and can be omitted. However, if the last agent disconnects the bridge SHOULD discard its internal `channelState`, instead of issuing the update.

## Messaging Protocol
## Bridge Messaging Protocol

In order for Desktop Agents to communicate with the Desktop Agent Bridge and thereby other Desktop Agents, a messaging protocol is required. FDC3 supports both 'fire and forget' interactions (such as the broadcast of context messages) and interactions with specific responses (such as raising intents and returning a resolution and optional result), both of which must be handled by that messaging protocol and message formats it defines, as described in this section.

Expand Down Expand Up @@ -1006,7 +1006,7 @@ However, `PrivateChannel` instances allow the registration of additional event h

#### Message Schemas and generated sources

JSONSchema definitions are provided for all Desktop Agent Bridging message exchanges (see links in each reference page), which may be used to validate the correct generation of messages to or from a bridge (a separate schema is provided for the agent and bridge versions of each message).
JSONSchema definitions are provided for all Desktop Agent Bridging message exchanges defined by the Bridge Messaging Protocol (see links in each reference page), which may be used to validate the correct generation of messages to or from a bridge (a separate schema is provided for the agent and bridge versions of each message).

The JSONSchema definitions are also used to generate TypeScript interfaces for the messages to aid in implementation of a Desktop Agent Bridge or client library. These may be imported from the FDC3 npm module:

Expand Down
48 changes: 10 additions & 38 deletions docs/api/ref/GetAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { getAgent, DesktopAgent } from "@finos/fdc3";
try {
const fdc3: DesktopAgent = await getAgent();
//do FDC3 things here
} catch (e) {
} catch (e: AgentError) {
// Failed to connect
}
```
Expand Down Expand Up @@ -47,7 +47,7 @@ If no Desktop Agent is found, a failover function may be supplied by app allowin
The definition of the `getAgent()` function is as follows:

```ts
type getAgent = (
type GetAgentType = (
params?: GetAgentParams,
) => Promise<DesktopAgent>;
```
Expand All @@ -68,7 +68,7 @@ A small number of arguments are accepted that can affect the behavior of `getAge
*
* @property {number} timeout Number of milliseconds to allow for an fdc3
* implementation to be found before calling the failover function or
* rejecting (default 1000). Note that the timeout is cancelled as soon as a
* rejecting (default 750). 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 All @@ -87,7 +87,7 @@ A small number of arguments are accepted that can affect the behavior of `getAge
* @property {boolean} dontSetWindowFdc3 For backwards compatibility, `getAgent`
* will set a reference to the Desktop Agent implementation at `window.fdc3`
* if one does not already exist, and will fire the fdc3Ready event. Setting
* this flag to `false` will inhibit that behavior, leaving `window.fdc3` unset.
* this flag to `true` will inhibit that behavior, leaving `window.fdc3` unset.
*
* @property {function} failover An optional function that provides a
* means of connecting to or starting a Desktop Agent, which will be called
Expand All @@ -114,33 +114,7 @@ As web applications can navigate to or be navigated by users to different URLs a

:::

Finally, if there is still no Desktop Agent available, or an issue prevent connection to it, the `getAgent()` function will reject its promise with a message from the `AgentError` enumeration.

```ts
/**
* Contains constants representing the errors that can be encountered when
* trying to connect to a web-based Desktop Agent with the getAgent function.
*/
enum AgentError {
/** Returned if no Desktop Agent was found by any means available or
* if the Agent previously connected to is not contactable on a
* subsequent connection attempt.*/
AgentNotFound = "AgentNotFound",

/** Returned if validation of the app identity by the Desktop Agent
* Failed or the app is not being allowed to connect to the Desktop Agent
* for another reason. */
AccessDenied = "AccessDenied",

/** Returned if an error or exception occurs while trying to set
* up communication with a Desktop Agent. */
ErrorOnConnect = "ErrorOnConnect",

/** Returned if either the failover function itself, or what it returned,
* was not the right type. */
InvalidFailover = "InvalidFailover"
}
```
Finally, if there is still no Desktop Agent available, or an issue prevent connection to it, the `getAgent()` function will reject its promise with a message from the [`AgentError`](./Errors#agenterror) enumeration.

## Failover function

Expand All @@ -166,18 +140,16 @@ If you wish to _completely override FDC3s standard mechanisms_, then do not use

:::

Failover functions MUST be asynchronous MUST resolve to one of the following types:
Failover functions MUST be asynchronous and MUST resolve to one of the following types:

1. [`DesktopAgent`](./DesktopAgent)
The application may choose to directly import or load code that provides a `DesktopAgent` implementation. `getAgent()` will then resolve to the provided `DesktopAgent`.
2. [`WindowProxy`](https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object) ([MDN](https://developer.mozilla.org/en-US/docs/Glossary/WindowProxy))
The application may open a window or create a hidden iframe which may then provide access to a compliant browser-resident DA. Ensure that the iframe has loaded (listen for the `load` event) or for separate windows allow a suitable timeout for the window load, then resolve to the `WindowProxy` object for the window or iframe. The `getAgent()` call will then use the supplied `WindowProxy` to establish a connection.


The application may choose to directly import or load code that provides a `DesktopAgent` implementation. `getAgent()` will then resolve to the provided `DesktopAgent`.
2. [`WindowProxy`](https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-windowproxy-exotic-object) ([MDN](https://developer.mozilla.org/en-US/docs/Glossary/WindowProxy))
The application may open a window or create a hidden iframe which may then provide access to a compliant browser-resident DA. Ensure that the iframe has loaded (listen for the `load` event) or for separate windows allow a suitable timeout for the window load, then resolve to the `WindowProxy` object for the window or iframe. The `getAgent()` call will then use the supplied `WindowProxy` to establish a connection.

## 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 and how it connected to a Desktop Agent in order to ensure a consistent connection type and instance Id, in case it navigates or is refreshed. 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 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 details persisted conform to the following type:

Expand Down
10 changes: 4 additions & 6 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,17 @@ The FDC3 API specification consists of interfaces. It is expected that each Des
- [`Channel`](ref/Channel)
- [`PrivateChannel`](ref/PrivateChannel)
- [`Listener`](ref/Types#listener)
- [Utility types](ref/Types#listener) and [Metadata Objects](ref/Metadata).

Other interfaces defined in the spec are not critical to define as concrete types. Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.

The means to access an API interface is defined separately for each language in which FDC3 is implemented. These definitions are important as they affect whether applicaitons can be written in a vendor agnostic format so that they run under any Standards-conformant implementation. For details of how to access an API interface in particular languages please see [Supported Platforms](supported-platforms).
The means to access the main FDC3 API interface (a `DesktopAgent` implementation) is defined separately for each language in which FDC3 is implemented. These definitions are important as they affect whether applications can be written in a vendor agnostic format so that they run under any Standards-conformant implementation.

### Implementation language

FDC3 and the Desktop Agent API it defines are intended to be independent of particular programming languages and platforms and hence the original definitions, produced in TypeScript, may be translated into other languages. However, this also places limitations on the API definitions as they need to be widely implementable in other languages.

Specifically, the use of ['unions'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of primitive values in API type and metadata objects, or function parameters SHOULD be avoided as they often cannot be replicated in other languages. Unions of more complex types (such as specific [Context](ref/Context) Types) may be used where a suitable interface is available or can be created to allow the required polymorphism in languages other than TypeScript.

For implementation details relating to particular languages, and how to access the API in those languages, please see [Supported Platforms](supported-platforms).
For implementation details relating to particular languages and how to access the API in those languages please see [Supported Platforms](supported-platforms).

### Standards vs. Implementation

Expand All @@ -80,7 +79,7 @@ Are all areas of functionality that any feature-complete desktop agent would imp

A goal of the FDC3 Standard is that applications running in different Desktop Agent contexts on the same desktop, or operated by the same user, would be able to interoperate and that one Desktop Agent context would be able to discover and launch an application in another Desktop Application context. As Desktop Agent interop is supported by common standards for APIs an app in one Desktop Agent context would not need to know a different syntax to launch or interact with an app in another Desktop Agent context.

Inter-agent communication at the API layer may be achieved via the [Desktop Agent Bridging Part of the FDC3 Standard](../agent-bridging/spec) ([@experimental](../fdc3-compliance#experimental-features)), which defines an independent service that Desktop Agents may connect to, and a protocol for the exchange of messages relating to FDC3 API calls. Hence, by implementing support for Desktop Agent Bridging, a platform may extend interop across applications running in multiple Desktop Agent contexts.
Inter-agent communication at the API layer may be achieved via the [Desktop Agent Bridging Part of the FDC3 Standard](../agent-bridging/spec) ([@experimental](../fdc3-compliance#experimental-features)), which defines an independent service that Desktop Agents may connect to (via the Bridge Connection Protocol or BCP), and a protocol for the exchange of messages relating to FDC3 API calls (the Bridge Messaging Protocol or BMP). Hence, by implementing support for Desktop Agent Bridging, a platform may extend interop across applications running in multiple Desktop Agent contexts.

Desktop Agent Bridging provides message exchanges and a workflow for performing intent resolution across multiple agents. Hence, app discovery is supported across the agents connected to the bridge for intent-based workflows. Further, as channels are also supported by bridging, context sharing also works across multiple agents.

Expand Down Expand Up @@ -132,7 +131,6 @@ An FDC3 Standard compliant Desktop Agent implementation **SHOULD**:
- Make metadata about each context message or intent and context message received (including the app that originated the message) available to the receiving application.
- Prevent external apps from listening or publishing on a [`PrivateChannel`](ref/PrivateChannel) that they did not request or provide.
- Enforce compliance with the expected behavior of intents (where Intents specify a contract that is enforceable by schema, for example, return object types) and return an error if the interface is not met.
- Implement [`validateAppIdentity()`](ref/DesktopAgent#validateappidentity).

An FDC3 Standard compliant Desktop Agent implementation **MAY**:

Expand Down
Loading

0 comments on commit 0e73f82

Please sign in to comment.