Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarification re repeated addContextListener and addIntentListener calls #1394

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added `addEventListener` to the `DesktopAgent` API to provide support for event listener for non-context and non-intent events, including a `userChannelChanged` event ([#1207](https://github.com/finos/FDC3/pull/1207))
* Added an `async` `addEventListener` function to the `PrivateChannel` API to replace the deprecated, synchronous `onAddContextListener`, `onUnsubscribe` and `onDisconnect` functions and to keep consistency with the DesktopAgent API. ([#1305](https://github.com/finos/FDC3/pull/1305))
* Added support for broadcast actions to the `fdc3.action` context type, allowing an Action to represent the broadcast of a specified context to an app or user channel. ([#1368](https://github.com/finos/FDC3/pull/1368))
* Added clarification regarding expected behavior upon repeated calls to `addContextListener` on same or overlapping types (allowed) and `addIntentListener` on same intent (rejected; new error type added). ([#1394](https://github.com/finos/FDC3/pull/1394))

### Changed

Expand Down
2 changes: 2 additions & 0 deletions docs/api/ref/Channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ If, when this function is called, the channel already contains context that woul

Optional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.

Adding multiple context listeners on the same or overlapping types (i.e. specific `contextType` and `null` type) MUST be allowed, and MUST trigger all ContextHandlers when a relevant context type is broadcast on the current channel.

**Examples:**

Add a listener for any context that is broadcast on the channel:
Expand Down
7 changes: 6 additions & 1 deletion docs/api/ref/DesktopAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ Context may also be received via this listener if the application was launched v

Optional metadata about each context message received, including the app that originated the message, SHOULD be provided by the Desktop Agent implementation.

Adding multiple context listeners on the same or overlapping types (i.e. specific `contextType` and `null` type) MUST be allowed, and MUST trigger all ContextHandlers when a relevant context type is broadcast on the current user channel. Please note, that this behavior differs from [`fdc3.addIntentListener`](#addintentlistener) call; refer to the relevant documentation for more details.

**Examples:**

<Tabs groupId="lang">
Expand Down Expand Up @@ -264,6 +266,8 @@ The [`PrivateChannel`](PrivateChannel) type is provided to support synchronizati

Optional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.

Adding multiple intent listeners on the same type MUST be rejected with the [`ResolveError.IntentListenerConflict`](Errors#resolveerror), unless the previous listener was removed first though [`listener.unsubscribe`](Types#unsubscribe)

**Examples:**

<Tabs groupId="lang">
Expand Down Expand Up @@ -339,6 +343,7 @@ var listener = await _desktopAgent.AddIntentListener<IContext>("StartChat", (con
- [`Listener`](Types#listener)
- [`Context`](Types#context)
- [`IntentHandler`](Types#intenthandler)
- [`ResolveError`](Errors#resolveerror)

### `broadcast`

Expand Down Expand Up @@ -527,7 +532,7 @@ Task<IEnumerable<IAppIdentifier>> FindInstances(IAppIdentifier app);

Find all the available instances for a particular application.

If the application is not known to the agent, the returned promise should be rejected with the `ResolverError.NoAppsFound` error message. However, if the application is known but there are no instances of the specified app the returned promise should resolve to an empty array.
If the application is not known to the agent, the returned promise should be rejected with the `ResolveError.NoAppsFound` error message. However, if the application is known but there are no instances of the specified app the returned promise should resolve to an empty array.

If the request fails for another reason, the promise MUST be rejected with an `Error` Object with a `message` chosen from the [`ResolveError`](Errors#resolveerror) enumeration, or (if connected to a Desktop Agent Bridge) the [`BridgingError`](Errors#bridgingerror) enumeration.

Expand Down
2 changes: 2 additions & 0 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,8 @@ When an instance of an application is launched, it is expected to add an [`Inten

Intent handlers SHOULD be registered via [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) within 15 seconds of the application launch (the minimum timeout Desktop Agents are required to provide) in order to be widely compatible with Desktop Agent implementations. Individual Desktop Agent implementations MAY support longer timeouts or configuration to control or extend timeouts.

A single handler can be added for each specific intent. If the application attempts to call [`fdc3.addIntentListener`](ref/DesktopAgent#addintentlistener) passing the same `intent` a second time, before unsubscribing to the previously added listener, the Desktop Agent MUST reject it with an `Error` Object with the message given by [`ResolveError.IntentListenerConflict`](ref/Errors#resolveerror).

### Originating App Metadata

Optional metadata about each intent & context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation to registered intent handlers. As this metadata is optional, apps making use of it MUST handle cases where it is not provided.
Expand Down
3 changes: 3 additions & 0 deletions src/api/Channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ export interface Channel {
* If, when this function is called, the channel already contains context that would be passed to the listener it is NOT called or passed this context automatically (this behavior differs from that of the [`fdc3.addContextListener`](DesktopAgent#addcontextlistener) function). Apps wishing to access to the current context of the channel should instead call the `getCurrentContext(contextType)` function.
*
* Optional metadata about each context message received, including the app that originated the message, SHOULD be provided by the desktop agent implementation.
*
* Adding multiple context listeners on the same or overlapping types (i.e. named type and null type) MUST be allowed, and MUST trigger all context handlers when a relevant context type is broadcast on the current channel.
*
*/
addContextListener(contextType: string | null, handler: ContextHandler): Promise<Listener>;

Expand Down
4 changes: 4 additions & 0 deletions src/api/DesktopAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ export interface DesktopAgent {
* The `PrivateChannel` type is provided to support synchronization of data transmitted over returned channels, by allowing both parties to listen for events denoting subscription and unsubscription from the returned channel. `PrivateChannels` are only retrievable via raising an intent.
*
* Optional metadata about the raised intent, including the app that originated the message, SHOULD be provided by the desktop agent implementation.
*
* Adding multiple intent listeners on the same type MUST be rejected with the `ResolveError.IntentListenerConflict`, unless the previous listener was removed first though `listener.unsubscribe`
*
* ```javascript
* //Handle a raised intent
Expand Down Expand Up @@ -359,6 +361,8 @@ export interface DesktopAgent {
* Context may also be received via this listener if the application was launched via a call to `fdc3.open`, where context was passed as an argument. In order to receive this, applications SHOULD add their context listener as quickly as possible after launch, or an error MAY be returned to the caller and the context may not be delivered. The exact timeout used is set by the Desktop Agent implementation, but MUST be at least 15 seconds.
*
* Optional metadata about the context message, including the app that originated the message, SHOULD be provided by the desktop agent implementation.
*
* Adding multiple context listeners on the same or overlapping types (i.e. named type and null type) MUST be allowed, and MUST trigger all contextHandlers when a relevant context type is broadcast on the current user channel. Please note, that this behavior differes from `fdc3.addIntentListener`API call; refer to the relevant documentation for more detials.
*
* ```javascript
* // any context
Expand Down
2 changes: 2 additions & 0 deletions src/api/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export enum ResolveError {
IntentDeliveryFailed = 'IntentDeliveryFailed',
/** Returned if a call to one of the `raiseIntent` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/
MalformedContext = 'MalformedContext',
/** Returned if `fdc3.addIntentListener` is called for a specified intent that the application has already added a listener for and has not subsequently removed it. */
IntentListenerConflict = 'IntentListenerConflict',
/** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/
DesktopAgentNotFound = 'DesktopAgentNotFound',
}
Expand Down