From b71f89209b2f3476dc399b02de54a0d592573c2f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Aug 2020 19:29:15 -0600 Subject: [PATCH 01/45] Start a template for a widgets spec --- changelogs/widgets.rst | 0 changelogs/widgets/newsfragments/.gitignore | 1 + changelogs/widgets/pyproject.toml | 35 ++++++++++++++++ scripts/gendoc.py | 5 +++ scripts/templating/matrix_templates/units.py | 6 +++ specification/targets.yaml | 4 ++ specification/widgets.rst | 43 ++++++++++++++++++++ 7 files changed, 94 insertions(+) create mode 100644 changelogs/widgets.rst create mode 100644 changelogs/widgets/newsfragments/.gitignore create mode 100644 changelogs/widgets/pyproject.toml create mode 100644 specification/widgets.rst diff --git a/changelogs/widgets.rst b/changelogs/widgets.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/changelogs/widgets/newsfragments/.gitignore b/changelogs/widgets/newsfragments/.gitignore new file mode 100644 index 00000000000..b722e9e13ef --- /dev/null +++ b/changelogs/widgets/newsfragments/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/changelogs/widgets/pyproject.toml b/changelogs/widgets/pyproject.toml new file mode 100644 index 00000000000..cc4c62b2e22 --- /dev/null +++ b/changelogs/widgets/pyproject.toml @@ -0,0 +1,35 @@ +[tool.towncrier] + filename = "../widgets.rst" + directory = "newsfragments" + issue_format = "`#{issue} `_" + title_format = "{version}" + + [[tool.towncrier.type]] + directory = "breaking" + name = "Breaking Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "new" + name = "New Endpoints" + showcontent = true + + [[tool.towncrier.type]] + directory = "removal" + name = "Removed Endpoints" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Backwards Compatible Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "clarification" + name = "Spec Clarifications" + showcontent = true diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 7e68ccd7348..4874bc66aee 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -530,6 +530,10 @@ def extract_major(s): "--identity_release", "-i", action="store", default="unstable", help="The identity service release tag to generate, e.g. r1.2" ) + parser.add_argument( + "--widgets_release", "-w", action="store", default="unstable", + help="The widget release tag to generate, e.g. r1.2" + ) parser.add_argument( "--list_targets", action="store_true", help="Do not update the specification. Instead print a list of targets.", @@ -556,6 +560,7 @@ def extract_major(s): "%APPSERVICE_RELEASE_LABEL%": args.appservice_release, "%IDENTITY_RELEASE_LABEL%": args.identity_release, "%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release, + "%WIDGETS_RELEASE_LABEL%": args.widgets_release, } exit (main(args.target or ["all"], args.dest, args.nodelete, substitutions)) diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index ff614e34a2f..e8e62f5dede 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -788,6 +788,7 @@ def load_apis(self, substitutions): is_ver = substitutions.get("%IDENTITY_RELEASE_LABEL%", "unstable") as_ver = substitutions.get("%APPSERVICE_RELEASE_LABEL%", "unstable") push_gw_ver = substitutions.get("%PUSH_GATEWAY_RELEASE_LABEL%", "unstable") + widget_ver = substitutions.get("%WIDGET_RELEASE_LABEL%", "unstable") # we abuse the typetable to return this info to the templates return TypeTable(rows=[ @@ -811,6 +812,10 @@ def load_apis(self, substitutions): "`Push Gateway API `_", push_gw_ver, "Push notifications for Matrix events", + ), TypeTableRow( + "`Widgets `_", + widget_ver, + "Client-side embedded applications", ), ]) @@ -970,6 +975,7 @@ def load_changelogs(self, substitutions): "client_server": substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable"), "identity_service": substitutions.get("%IDENTITY_RELEASE_LABEL%", "unstable"), "push_gateway": substitutions.get("%PUSH_GATEWAY_RELEASE_LABEL%", "unstable"), + "widgets": substitutions.get("%WIDGETS_RELEASE_LABEL%", "unstable"), "application_service": substitutions.get("%APPSERVICE_RELEASE_LABEL%", "unstable"), } diff --git a/specification/targets.yaml b/specification/targets.yaml index df66218f6c0..88137149b35 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -25,6 +25,10 @@ targets: files: - push_gateway.rst version_label: "%PUSH_GATEWAY_RELEASE_LABEL%" + widgets: + files: + - widgets.rst + version_label: "%WIDGETS_RELEASE_LABEL%" rooms@v1: # this is translated to be rooms/v1.html files: - rooms/v1.rst diff --git a/specification/widgets.rst b/specification/widgets.rst new file mode 100644 index 00000000000..e58c3679d2c --- /dev/null +++ b/specification/widgets.rst @@ -0,0 +1,43 @@ +.. Copyright 2020 The Matrix.org Foundation C.I.C. +.. +.. Licensed under the Apache License, Version 2.0 (the "License"); +.. you may not use this file except in compliance with the License. +.. You may obtain a copy of the License at +.. +.. http://www.apache.org/licenses/LICENSE-2.0 +.. +.. Unless required by applicable law or agreed to in writing, software +.. distributed under the License is distributed on an "AS IS" BASIS, +.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.. See the License for the specific language governing permissions and +.. limitations under the License. + +Widgets +======= + +{{unstable_warning_block_WIDGETS_RELEASE_LABEL}} + +TODO + +.. contents:: Table of Contents +.. sectnum:: + +Changelog +--------- + +.. topic:: Version: %WIDGETS_RELEASE_LABEL% +{{widgets_changelog}} + +This version of the specification is generated from +`matrix-doc `_ as of Git commit +`{{git_version}} `_. + +For the full historical changelog, see +https://github.com/matrix-org/matrix-doc/blob/master/changelogs/widgets.rst + +Other versions of this specification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following other versions are also available, in reverse chronological order: + +- `HEAD `_: Includes all changes since the latest versioned release. From fb13f4985119c98d86409fc481d9edb4e1dafbfb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 28 Aug 2020 07:41:34 -0600 Subject: [PATCH 02/45] Specify what the different widget kinds are --- api/widgets/definitions/shared_props.yaml | 83 ++++++++++++++++++++ api/widgets/examples/shared_props.json | 12 +++ event-schemas/examples/m.widget | 8 ++ event-schemas/examples/m.widgets | 14 ++++ event-schemas/schema/m.widget | 18 +++++ event-schemas/schema/m.widgets | 33 ++++++++ scripts/templating/matrix_templates/units.py | 2 + specification/widgets.rst | 79 ++++++++++++++++++- 8 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 api/widgets/definitions/shared_props.yaml create mode 100644 api/widgets/examples/shared_props.json create mode 100644 event-schemas/examples/m.widget create mode 100644 event-schemas/examples/m.widgets create mode 100644 event-schemas/schema/m.widget create mode 100644 event-schemas/schema/m.widgets diff --git a/api/widgets/definitions/shared_props.yaml b/api/widgets/definitions/shared_props.yaml new file mode 100644 index 00000000000..59f173e7b34 --- /dev/null +++ b/api/widgets/definitions/shared_props.yaml @@ -0,0 +1,83 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: WidgetCommonProperties +description: |- + Common properties for widgets regardless of where they exist. +example: + $ref: "../examples/shared_props.json" +properties: + id: + type: string + description: |- + An opaque, unique, UTF-8 identifier for the widget. Uniqueness and other requirements + are defined by the widget kind. + example: "20200827_WidgetExample" + creatorUserId: + type: string + description: |- + The user ID who originally created the widget. This varies from the user who last + edited the widget, which is typically represented by the ``sender`` on events. + example: "@alice:example.org" + name: + type: string + description: A human-readable name for the widget. + example: "My Cool Widget" + type: + type: string + description: The type of widget being represented. + example: "m.custom" + url: + type: string + description: |- + The URL where the widget can be loaded, including template variables. See the + `URL Templating`_ section for more information on templating. + example: "https://example.org/my/widget.html?roomId=$matrix_room_id" + waitForIframeLoad: + type: boolean + default: true + description: |- + When true, the widget should be hidden from view until the iframe's ``onLoad`` (or + platform equivilant) event has been fired. When false, the widget should be hidden + from view until the ``content_loaded`` API action is sent by the widget. Defaults to + true. + example: true + data: + type: object + title: WidgetData + description: |- + Additional metadata for the widget. The widget can receive these in their URL safely + by using template variables. Note that some widget types may result in this property + being required. + + See the `URL Templating`_ section for more information on templating. + properties: + title: + type: string + description: |- + A human-readable title for the widget primarily shown next to the widget's name. + example: "This is a witty description for the widget" + additionalProperties: + type: object + example: { + "title": "This is a witty description for the widget", + "custom-key": "This is a custom key" + } + +required: + - id + - creatorUserId + - type + - url diff --git a/api/widgets/examples/shared_props.json b/api/widgets/examples/shared_props.json new file mode 100644 index 00000000000..ce848b3bc23 --- /dev/null +++ b/api/widgets/examples/shared_props.json @@ -0,0 +1,12 @@ +{ + "creatorUserId": "@alice:example.org", + "data": { + "custom-key": "This is a custom key", + "title": "This is a witty description for the widget" + }, + "id": "20200827_WidgetExample", + "name": "My Cool Widget", + "type": "m.custom", + "url": "https://example.org/my/widget.html?roomId=$matrix_room_id", + "waitForIframeLoad": true +} diff --git a/event-schemas/examples/m.widget b/event-schemas/examples/m.widget new file mode 100644 index 00000000000..817408f288d --- /dev/null +++ b/event-schemas/examples/m.widget @@ -0,0 +1,8 @@ +{ + "$ref": "core/state_event.json", + "type": "m.widget", + "state_key": "20200827_WidgetExample", + "content": { + "$ref": "../../../api/widgets/examples/shared_props.json" + } +} diff --git a/event-schemas/examples/m.widgets b/event-schemas/examples/m.widgets new file mode 100644 index 00000000000..623c19bf5c4 --- /dev/null +++ b/event-schemas/examples/m.widgets @@ -0,0 +1,14 @@ +{ + "$ref": "core/event.json", + "type": "m.widgets", + "content": { + "20200827_WidgetExample": { + "type": "m.widget", + "state_key": "20200827_WidgetExample", + "sender": "@alice:example.org", + "content": { + "$ref": "../../../api/widgets/examples/shared_props.json" + } + } + } +} diff --git a/event-schemas/schema/m.widget b/event-schemas/schema/m.widget new file mode 100644 index 00000000000..4ac4af98e51 --- /dev/null +++ b/event-schemas/schema/m.widget @@ -0,0 +1,18 @@ +--- +allOf: + - $ref: core-event-schema/state_event.yaml +description: Defines a room widget. The event's content is ``WidgetCommonProperties``. +properties: + content: + allOf: + - $ref: ../../api/widgets/definitions/shared_props.yaml + - title: EventContent # We use an explicit name so the rendering makes sense + type: object + state_key: + description: The ID for the widget. + type: string + type: + enum: + - m.widget + type: string +type: object diff --git a/event-schemas/schema/m.widgets b/event-schemas/schema/m.widgets new file mode 100644 index 00000000000..dc6af35dc19 --- /dev/null +++ b/event-schemas/schema/m.widgets @@ -0,0 +1,33 @@ +--- +allOf: + - $ref: core-event-schema/event.yaml +description: Defines all of the user's account widgets as a map of widget ID to ``AccountWidget``. +properties: + content: + type: object + additionalProperties: + type: object + title: AccountWidget + properties: + type: + enum: ['m.widget'] + type: string + state_key: + type: string + description: The widget's ID. + sender: + type: string + description: The current user's ID. + content: + allOf: + - $ref: ../../api/widgets/definitions/shared_props.yaml + required: + - type + - state_key + - sender + - content + type: + enum: + - m.widgets + type: string +type: object diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index e8e62f5dede..1d6250f53d9 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -42,6 +42,7 @@ os.path.join(matrix_doc_dir, "api/identity"): "is", os.path.join(matrix_doc_dir, "api/push-gateway"): "push", os.path.join(matrix_doc_dir, "api/server-server"): "ss", + os.path.join(matrix_doc_dir, "api/widgets"): "widgets", } SWAGGER_DEFINITIONS = { os.path.join(matrix_doc_dir, "api/application-service/definitions"): "as", @@ -49,6 +50,7 @@ os.path.join(matrix_doc_dir, "api/identity/definitions"): "is", os.path.join(matrix_doc_dir, "api/push-gateway/definitions"): "push", os.path.join(matrix_doc_dir, "api/server-server/definitions"): "ss", + os.path.join(matrix_doc_dir, "api/widgets/definitions"): "widgets", } EVENT_EXAMPLES = os.path.join(matrix_doc_dir, "event-schemas/examples") EVENT_SCHEMA = os.path.join(matrix_doc_dir, "event-schemas/schema") diff --git a/specification/widgets.rst b/specification/widgets.rst index e58c3679d2c..87de4ea65d0 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -17,7 +17,8 @@ Widgets {{unstable_warning_block_WIDGETS_RELEASE_LABEL}} -TODO +Widgets are client-side embedded applications which can communicate with Matrix clients. Widgets +are often used to present information to users and allow them to more interactively collaborate. .. contents:: Table of Contents .. sectnum:: @@ -41,3 +42,79 @@ Other versions of this specification The following other versions are also available, in reverse chronological order: - `HEAD `_: Includes all changes since the latest versioned release. + +API Standards +~~~~~~~~~~~~~ + +The mandatory baseline for a widget is a typical website with the optional communication protocol +described here. When communicating with a Matrix client, the mandatory baseline is the `JavaScript +postMessage API `_ using the +protocol described by this specification. In the future more accessible transports for clients will +be considered as optional extensions, such as using operating system-specific hooks. + +All objects exchanged over the Widget (``postMessage``) API are JSON objects. + +In essence, widgets are typically iframes or the platform equivilant to a website which are accessible +in the client. + +Widget Kinds +------------ + +Widgets currently can exist in the following places: + +* Within rooms, accessible by members/observers of the room. +* For a particular user, accessible only by that user. + +{{definition_widgets_shared_props}} + +Room Widgets +~~~~~~~~~~~~ + +Room widgets are defined by state events in the room, and are as such accessible to anyone who is +able to see the state of the room. Widgets can individually apply additional access restrictions +such as preventing non-joined members of the room from accessing the widget's functionality. + +Clients MUST NOT show room widgets to the user unless the user is viewing that room or unless the +widget has set an appropriate always-on-screen request through the Widget API. + +The ``state_key`` for a room widget MUST match the widget's ``id``. Due to this association, new +widgets in the room must use a unique ``state_key`` (and therefore ``id``). Widgets can be +updated by sending a new state event for the widget's ``state_key``. + +Invalid room widgets MUST NOT be shown to users. This is also how widgets are removed from a room: +send a new state event for the same widget ID with at least the ``url`` and/or ``type`` missing +from the event content. Once Matrix allows for state events to be properly deleted then doing so +to the widget state event will be just as valid to remove it from the room. + +.. WARNING:: + Do not store sensitive information such as tokens, secrets, or passwords + in the widget data as it can be viewed by anyone who can see the room state. + +{{m_widget_event}} + +Account Widgets +~~~~~~~~~~~~~~~ + +Account widgets are defined in the user's account data, and are as such only visible to them. +Widgets can individually apply additional access restrictions as needed. Account widgets are +not linked to any particular room. + +Account widgets are represented under the ``m.widgets`` account data event as a map of widget ID +to definition. As such, the widget's ``id`` must be unique within this object's properties. The +definition for an account widget is nearly equivilant to a room widget's state event representation, +using the ``type``, ``state_key``, ``sender``, and ``content`` fields of the state event. + +Account widgets can be added by adding a new key to the ``m.widgets`` account data, edited by +modifying the appropriate ``AccountWidget`` definition, or deleted by simply removing the appropriate +property from the ``m.widgets`` acount data. + +.. WARNING:: + Do not store sensitive information such as tokens, secrets, or passwords + in the widget data as it is not secure or encrypted. + +{{m_widgets_event}} + +URL Templating +-------------- + +TODO From bf646d04a6331d8648214b915da5254347665e41 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 30 Aug 2020 20:26:44 -0600 Subject: [PATCH 03/45] Add a section on rendering --- specification/widgets.rst | 68 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/specification/widgets.rst b/specification/widgets.rst index 87de4ea65d0..2dbcbac040e 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -114,7 +114,71 @@ property from the ``m.widgets`` acount data. {{m_widgets_event}} + +Rendering +--------- + +Widgets SHOULD be rendered using an iframe or platform equivilant. Clients can use platform-specific +rendering for widgets if they are confident in being able to do so, such as in the case of most +video conference widgets. + +Clients SHOULD ask for permission to load a widget from the user prior to presenting the widget. If +the user was the last ``sender`` of a widget (not the ``creatorUserId``), the prompt can be skipped. +This prompt is strongly encouraged to ensure that users do not inadvertently send their information +to a third party. + URL Templating --------------- +~~~~~~~~~~~~~~ + +The widget's URL is a template of what the client should render and should never be parsed by the +client to determine what the parameters are. All widgets make use of the ``data`` object to store +configuration-like values, which is also where clients should inspect for values needed to render +any UI. + +Variable names for the template are the keys of the ``data`` object, with the values being the same +values of the object. Variables are included unencoded in the URL for population by the client, which +MUST use appropriate escaping to ensure the URL will be as valid as possible. + +For example, given a ``data`` object like this:: + + { + "hello": "world", + "answer": 42 + } + +and a ``url`` of ``https://example.com?var1=$hello&answer=$answer`` the client MUST come up with +a URL of ``https://example.com?var1=world&answer=42`` to render. Complex types, such as objects and +arrays, for variable values do not have defined behaviour - widget creators are encouraged to stick +to "simple" types like numbers, strings, and booleans. Template variables can appear anywhere in the +URL. + +Nested variables are not supported, and as such clients should be careful in their templating +approach. For example, if ``hello`` in the above example ``data`` was set to ``$answer``, the literal +value ``$answer`` would be included in the widget URL rather than ``42``. + +As mentioned, clients must also encode values on behalf of the widget creator to maintain a valid +URL as much as possible. For example, ``test:value`` could become ``test%3Avalue`` when used as a +template variable value. + +A few default variables, which MUST take priority over the same names in ``data``, are: + +* ``matrix_user_id`` - The current user's ID. +* ``matrix_room_id`` - The room ID the user is currently viewing, or an empty string if none applicable. +* ``matrix_display_name`` - The current user's display name, or user ID if not set. +* ``matrix_avatar_url`` - The current user's avatar URL as reported in their profile, or and empty + string if not present. This shouldn't be the ``mxc://`` form of the user's avatar, but instead the + full HTTP URL to the ``/media/download`` endpoint for their avatar from the Client-Server API. + +Security Considerations +~~~~~~~~~~~~~~~~~~~~~~~ + +Clients SHOULD check to ensure that widgets are valid URLs *after* templating but *before* rendering +or asking for permission to load. Invalid URLs from the client's perspective should not be shown to +the user and can be treated as though no ``url`` was present (i.e.: a deleted/invalid widget). + +Clients SHOULD limit which URL schemes are able to be rendered to ensure that they are not rendering +potentially dangerous files. Most widgets will have schemes of ``http`` or ``https``. -TODO +Clients SHOULD apply a sandbox to their iframe or platform equivilant to ensure the widget cannot +get access to the data stored by the client, such as access tokens or cryptographic keys. More +information on origin restrictions is in the Widget API's security considerations section. From 826ce021501b3774cecb6ea61b7b711065087e2c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 30 Aug 2020 21:00:23 -0600 Subject: [PATCH 04/45] Start specifying widget types --- specification/widgets.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index 2dbcbac040e..10889b8911d 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -182,3 +182,23 @@ potentially dangerous files. Most widgets will have schemes of ``http`` or ``htt Clients SHOULD apply a sandbox to their iframe or platform equivilant to ensure the widget cannot get access to the data stored by the client, such as access tokens or cryptographic keys. More information on origin restrictions is in the Widget API's security considerations section. + +Widget Types +------------ + +A widget's ``type`` can be one of the following specified types or a custom type which preferably +uses the Java package naming convention as a namespace. Types prefixed with the ``m.`` namespace +are reserved by this specification. + +Besides the ``type`` itself, widget types influence the widget's ``data`` by requiring specified +keys to exist. It is expected that the widget will use these keys as variables for their URL, though +this specification does not require such behaviour. Clients SHOULD treat widgets without the +required ``data`` properties for the types specified here as invalid widgets, thus not rendering +them. + +Clients MUST treat widgets of unknown types as ``m.custom``, unless it is impossible for the client +to render the widget kind in that way. For example, custom widgets at the per-user rather than +per-room level might not be possible and thus can be treated as invalid (ignored). + +Clients are not required to support all of these widget types (with the implied exception of +``m.custom``) as they can all be safely represented as ``m.custom`` widgets. From 03d64bd1d6a72f0d3d02a646626277bcd52939b5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 30 Aug 2020 21:00:51 -0600 Subject: [PATCH 05/45] Specify Jitsi widgets No changes from MSC --- api/widgets/definitions/jitsi_data.yaml | 40 +++++++++++++++++++++++++ api/widgets/examples/jitsi_data.json | 5 ++++ specification/widgets.rst | 11 +++++++ 3 files changed, 56 insertions(+) create mode 100644 api/widgets/definitions/jitsi_data.yaml create mode 100644 api/widgets/examples/jitsi_data.json diff --git a/api/widgets/definitions/jitsi_data.yaml b/api/widgets/definitions/jitsi_data.yaml new file mode 100644 index 00000000000..64c506785f6 --- /dev/null +++ b/api/widgets/definitions/jitsi_data.yaml @@ -0,0 +1,40 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: JitsiWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.jitsi``. +example: + $ref: "../examples/jitsi_data.json" +properties: + domain: + type: string + description: |- + The Jitsi Meet domain where the conference is to be hosted. + conferenceId: + type: string + description: |- + The conference ID (also known as the room name) where the conference is to + be hosted on the given domain. + isAudioOnly: + type: boolean + default: false + description: |- + If true, the Jitsi Meet conference should be started as audio only ny the client + if possible. When false, the conference should be started normally (with video). + Defaults to false (normal conference) when not provided. +required: + - domain + - conferenceId diff --git a/api/widgets/examples/jitsi_data.json b/api/widgets/examples/jitsi_data.json new file mode 100644 index 00000000000..51996514dc9 --- /dev/null +++ b/api/widgets/examples/jitsi_data.json @@ -0,0 +1,5 @@ +{ + "domain": "meet.jit.si", + "conferenceId": "HelloWorld", + "isAudioOnly": false +} diff --git a/specification/widgets.rst b/specification/widgets.rst index 10889b8911d..fba3eb2f0b0 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -202,3 +202,14 @@ per-room level might not be possible and thus can be treated as invalid (ignored Clients are not required to support all of these widget types (with the implied exception of ``m.custom``) as they can all be safely represented as ``m.custom`` widgets. + +Jitsi Meet Conferences +~~~~~~~~~~~~~~~~~~~~~~ + +`Jitsi Meet `_ conferences can be held on a per-room basis with +a widget ``type`` of ``m.jitsi`` and ``data`` matching ``JitsiWidgetData``. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_jitsi_data}} From 65a290a8858fc7ba3ce1721d4d293d1fd49a8af4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 30 Aug 2020 21:01:15 -0600 Subject: [PATCH 06/45] Specify TradingView widgets The data object is completely different from the MSC due to implementation constraints. This spec matches the current implementation used by known integration managers. --- api/widgets/definitions/tradingview_data.yaml | 32 +++++++++++++++++++ api/widgets/examples/tradingview_data.json | 4 +++ specification/widgets.rst | 14 ++++++++ 3 files changed, 50 insertions(+) create mode 100644 api/widgets/definitions/tradingview_data.yaml create mode 100644 api/widgets/examples/tradingview_data.json diff --git a/api/widgets/definitions/tradingview_data.yaml b/api/widgets/definitions/tradingview_data.yaml new file mode 100644 index 00000000000..69973174de1 --- /dev/null +++ b/api/widgets/definitions/tradingview_data.yaml @@ -0,0 +1,32 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: TradingViewWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.tradingview``. +example: + $ref: "../examples/tradingview_data.json" +properties: + interval: + type: string + description: |- + The interval to supply to the TradingView chart, as supported by the chart. + pair: + type: string + description: |- + The symbol to represent by the TradingView chart, as supported by the chart. +required: + - interval + - pair diff --git a/api/widgets/examples/tradingview_data.json b/api/widgets/examples/tradingview_data.json new file mode 100644 index 00000000000..5eba7ad6c2b --- /dev/null +++ b/api/widgets/examples/tradingview_data.json @@ -0,0 +1,4 @@ +{ + "interval": "D", + "pair": "COINBASE:BTCUSD" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index fba3eb2f0b0..695dde42c9f 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -213,3 +213,17 @@ a widget ``type`` of ``m.jitsi`` and ``data`` matching ``JitsiWidgetData``. Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_jitsi_data}} + +TradingView +~~~~~~~~~~~ + +`TradingView `_ widgets can be addded on a per-room basis with +a widget ``type`` of ``m.tradingview`` and ``data`` matching ``TradingViewWidgetData``. + +This widget type is meant to be used with TradingView's +`Advanced Real-Time Chart Widget `_. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_tradingview_data}} From d2bfe5d1012cb82dae4f635fd6932d5b4c1c94e1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 15:52:44 -0600 Subject: [PATCH 07/45] Clarify that widgets are an optional feature --- specification/widgets.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index 695dde42c9f..ed610138061 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -20,6 +20,11 @@ Widgets Widgets are client-side embedded applications which can communicate with Matrix clients. Widgets are often used to present information to users and allow them to more interactively collaborate. +Due to platform constraints, unreasonable implementation effort, and client-specific design choices, +widgets are optional in Matrix. Clients are encouraged to support widgets if possible and reasonable, +though degraded behaviour, such as "open in browser" links, is considered acceptable by this +specification. + .. contents:: Table of Contents .. sectnum:: From 71cb98a8b6b3f8e95034039ddc4c9ed98e243c55 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 15:53:02 -0600 Subject: [PATCH 08/45] Fix understanding of what a "client" is in the context of widgets --- specification/widgets.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index ed610138061..1ca9298a2f3 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -51,6 +51,13 @@ The following other versions are also available, in reverse chronological order: API Standards ~~~~~~~~~~~~~ +Throughout this specification, a "client" is referred to as something which is rendering/supporting +("hosting") widgets. Widgets are unique in that they can be considered a client when referred to in +a typical network setting, though this specification ensures that a widget is always referred to as +a "widget" and the term "client" is solely reserved for the widget's host application. Note that +widgets can be hosts to widgets - deciphering which role is which in this context is left as an +exercise for the reader. + The mandatory baseline for a widget is a typical website with the optional communication protocol described here. When communicating with a Matrix client, the mandatory baseline is the `JavaScript postMessage API `_ using the From ee14c27e045af4a1dd7187c1579042258c92a0a9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 19:23:18 -0600 Subject: [PATCH 09/45] Specify Spotify widgets No differences from MSC --- api/widgets/definitions/spotify_data.yaml | 27 +++++++++++++++++++++++ api/widgets/examples/spotify_data.json | 3 +++ specification/widgets.rst | 11 +++++++++ 3 files changed, 41 insertions(+) create mode 100644 api/widgets/definitions/spotify_data.yaml create mode 100644 api/widgets/examples/spotify_data.json diff --git a/api/widgets/definitions/spotify_data.yaml b/api/widgets/definitions/spotify_data.yaml new file mode 100644 index 00000000000..8e349e56d9f --- /dev/null +++ b/api/widgets/definitions/spotify_data.yaml @@ -0,0 +1,27 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: SpotifyWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.spotify``. +example: + $ref: "../examples/spotify_data.json" +properties: + uri: + type: string + description: |- + The Spotify URI or share URL for the resource to embed, as supported by Spotify. +required: + - uri diff --git a/api/widgets/examples/spotify_data.json b/api/widgets/examples/spotify_data.json new file mode 100644 index 00000000000..f775e6fa8af --- /dev/null +++ b/api/widgets/examples/spotify_data.json @@ -0,0 +1,3 @@ +{ + "uri": "spotify:episode:3jVWns139xO1u6F13dhwuF" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index 1ca9298a2f3..03f55e82d6d 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -239,3 +239,14 @@ This widget type is meant to be used with TradingView's Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_tradingview_data}} + +Spotify +~~~~~~~ + +`Spotify Widgets `_ can be added on a +per-room basis with a widget ``type`` of ``m.spotify`` and ``data`` matching ``SpotifyWidgetData``. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_spotify_data}} From fa7334f310dcf84f916d9255e8b17004571e1300 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 19:27:36 -0600 Subject: [PATCH 10/45] Specify Video (YouTube) widgets No changes from the MSC --- api/widgets/definitions/video_data.yaml | 27 +++++++++++++++++++++++++ api/widgets/examples/video_data.json | 3 +++ specification/widgets.rst | 11 ++++++++++ 3 files changed, 41 insertions(+) create mode 100644 api/widgets/definitions/video_data.yaml create mode 100644 api/widgets/examples/video_data.json diff --git a/api/widgets/definitions/video_data.yaml b/api/widgets/definitions/video_data.yaml new file mode 100644 index 00000000000..903e6fccecb --- /dev/null +++ b/api/widgets/definitions/video_data.yaml @@ -0,0 +1,27 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: VideoWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.video``. +example: + $ref: "../examples/video_data.json" +properties: + url: + type: string + description: |- + The URL to the video to embed. +required: + - url diff --git a/api/widgets/examples/video_data.json b/api/widgets/examples/video_data.json new file mode 100644 index 00000000000..b2d68cd90e4 --- /dev/null +++ b/api/widgets/examples/video_data.json @@ -0,0 +1,3 @@ +{ + "url": "https://www.youtube.com/watch?v=gtbIWSsHICI" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index 03f55e82d6d..872beeb2ed3 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -250,3 +250,14 @@ per-room basis with a widget ``type`` of ``m.spotify`` and ``data`` matching ``S Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_spotify_data}} + +Videos +~~~~~~ + +Videos from video streaming sites can be added on a per-room basis with a widget ``type`` of +``m.video`` and ``data`` matching ``VideoWidgetData``. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_video_data}} From ea579564906a733f1cb2bdd9f397511a2bdf1f11 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 19:36:55 -0600 Subject: [PATCH 11/45] Specify Google Docs widgets No changes from the MSC --- api/widgets/definitions/googledocs_data.yaml | 26 ++++++++++++++++++++ api/widgets/examples/googledocs_data.json | 3 +++ specification/widgets.rst | 16 ++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 api/widgets/definitions/googledocs_data.yaml create mode 100644 api/widgets/examples/googledocs_data.json diff --git a/api/widgets/definitions/googledocs_data.yaml b/api/widgets/definitions/googledocs_data.yaml new file mode 100644 index 00000000000..3e3bf1dda18 --- /dev/null +++ b/api/widgets/definitions/googledocs_data.yaml @@ -0,0 +1,26 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: GoogleDocsWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.googledoc``. +example: + $ref: "../examples/googledocs_data.json" +properties: + url: + type: string + description: |- + The URL to the document to embed. Required if the widget's URL differs from the document's + URL, before templating occurs. diff --git a/api/widgets/examples/googledocs_data.json b/api/widgets/examples/googledocs_data.json new file mode 100644 index 00000000000..6ce8864039b --- /dev/null +++ b/api/widgets/examples/googledocs_data.json @@ -0,0 +1,3 @@ +{ + "url": "https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index 872beeb2ed3..d65a8cc7d62 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -261,3 +261,19 @@ Videos from video streaming sites can be added on a per-room basis with a widget Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_video_data}} + +Google Docs +~~~~~~~~~~~ + +Documents from Google Docs, Sheets, and Slides can be added as widgets on a per-room basis with a +widget ``type`` of ``m.googledoc`` and ``data`` matching ``GoogleDocsWidgetData``. + +.. Note:: + Documents typically need to be publicly accessible without authentication to be embedded. Most + documents that would be shared by widgets are not publicly accessible and thus generally will + refuse to embed properly. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_googledocs_data}} From 2ce44f68855db53ccc3e24725a7760a78e4f8067 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 19:43:25 -0600 Subject: [PATCH 12/45] Specify Google Calendar widgets There is disagreement between integration managers over whether this is supposed to be a `src` or `shareId`, however the MSC wants a `shareId` which at least 1 integration manager agrees with. --- .../definitions/googlecalendar_data.yaml | 27 +++++++++++++++++++ api/widgets/examples/googlecalendar_data.json | 3 +++ specification/widgets.rst | 16 +++++++++++ 3 files changed, 46 insertions(+) create mode 100644 api/widgets/definitions/googlecalendar_data.yaml create mode 100644 api/widgets/examples/googlecalendar_data.json diff --git a/api/widgets/definitions/googlecalendar_data.yaml b/api/widgets/definitions/googlecalendar_data.yaml new file mode 100644 index 00000000000..b9d486de40f --- /dev/null +++ b/api/widgets/definitions/googlecalendar_data.yaml @@ -0,0 +1,27 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: GoogleCalendarWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.googlecalendar``. +example: + $ref: "../examples/googlecalendar_data.json" +properties: + shareId: + type: string + description: |- + The Google Calendar ID to embed. +required: + - shareId diff --git a/api/widgets/examples/googlecalendar_data.json b/api/widgets/examples/googlecalendar_data.json new file mode 100644 index 00000000000..72e63541b09 --- /dev/null +++ b/api/widgets/examples/googlecalendar_data.json @@ -0,0 +1,3 @@ +{ + "shareId": "en.uk#holiday@group.v.calendar.google.com" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index d65a8cc7d62..c362b33f466 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -277,3 +277,19 @@ widget ``type`` of ``m.googledoc`` and ``data`` matching ``GoogleDocsWidgetData` Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_googledocs_data}} + +Google Calendar +~~~~~~~~~~~~~~~ + +Calendars from Google Calendar can be added as widgets on a per-room basis with a widget ``type`` +of ``m.googlecalendar`` and ``data`` matching ``GoogleCalendarWidgetData``. + +.. Note:: + Calendars typically need to be publicly accessible without authentication to be embedded. Most + calendars that would be shared by widgets are not publicly accessible and thus generally will + refuse to embed properly. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_googlecalendar_data}} From 4cfd97f529b627beca5efce18672b6cf93f84e5f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 19:51:21 -0600 Subject: [PATCH 13/45] Specify Etherpad widgets No changes from the MSC --- api/widgets/definitions/etherpad_data.yaml | 26 ++++++++++++++++++++++ api/widgets/examples/etherpad_data.json | 3 +++ specification/widgets.rst | 11 +++++++++ 3 files changed, 40 insertions(+) create mode 100644 api/widgets/definitions/etherpad_data.yaml create mode 100644 api/widgets/examples/etherpad_data.json diff --git a/api/widgets/definitions/etherpad_data.yaml b/api/widgets/definitions/etherpad_data.yaml new file mode 100644 index 00000000000..653d0a8781c --- /dev/null +++ b/api/widgets/definitions/etherpad_data.yaml @@ -0,0 +1,26 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: EtherpadWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.etherpad``. +example: + $ref: "../examples/etherpad_data.json" +properties: + url: + type: string + description: |- + The URL to the Etherpad editor to embed. Required if the widget's URL differs from the pad's + URL, before templating occurs. diff --git a/api/widgets/examples/etherpad_data.json b/api/widgets/examples/etherpad_data.json new file mode 100644 index 00000000000..ed86b45c800 --- /dev/null +++ b/api/widgets/examples/etherpad_data.json @@ -0,0 +1,3 @@ +{ + "url": "https://etherpad.example.org/p/ExamplePadName" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index c362b33f466..c55cd1d1e18 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -293,3 +293,14 @@ of ``m.googlecalendar`` and ``data`` matching ``GoogleCalendarWidgetData``. Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_googlecalendar_data}} + +Etherpad +~~~~~~~~ + +`Etherpad `_ editors can be added on a per-room basis with a widget ``type`` +of ``m.etherpad`` and ``data`` matching ``EtherpadWidgetData``. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_etherpad_data}} From afa38177cda41ce9bedb4953fc8c7674aa82b14f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 19:59:23 -0600 Subject: [PATCH 14/45] Specify Grafana widgets There is disagreement between integration managers over whether this is supposed to be a `curl` or `url`, however the MSC wants a `url` which at least 1 integration manager agrees with. --- api/widgets/definitions/grafana_data.yaml | 26 +++++++++++++++++++++++ api/widgets/examples/grafana_data.json | 3 +++ specification/widgets.rst | 12 +++++++++++ 3 files changed, 41 insertions(+) create mode 100644 api/widgets/definitions/grafana_data.yaml create mode 100644 api/widgets/examples/grafana_data.json diff --git a/api/widgets/definitions/grafana_data.yaml b/api/widgets/definitions/grafana_data.yaml new file mode 100644 index 00000000000..b54ee6b1297 --- /dev/null +++ b/api/widgets/definitions/grafana_data.yaml @@ -0,0 +1,26 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: GrafanaWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.grafana``. +example: + $ref: "../examples/grafana_data.json" +properties: + url: + type: string + description: |- + The URL to the Grafana dashboard, snapshot, or other embedded resource as supported by + Grafana. Required if the widget's URL differs from the Grafana URL, before templating occurs. diff --git a/api/widgets/examples/grafana_data.json b/api/widgets/examples/grafana_data.json new file mode 100644 index 00000000000..1f1720f2ceb --- /dev/null +++ b/api/widgets/examples/grafana_data.json @@ -0,0 +1,3 @@ +{ + "url": "https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index c55cd1d1e18..535c8d86c0e 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -304,3 +304,15 @@ of ``m.etherpad`` and ``data`` matching ``EtherpadWidgetData``. Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_etherpad_data}} + +Grafana +~~~~~~~ + +`Embedded Grafana Panels `_ can +be added on a per-room basis with a widget ``type`` of ``m.grafana`` and ``data`` matching +``GrafanaWidgetData``. + +.. Note:: + Though technically possible, this widget type should not be used outside of room widgets. + +{{definition_widgets_grafana_data}} From 09261b38fc00eceb16f06944793f2fa1ecf97a0b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 20:03:18 -0600 Subject: [PATCH 15/45] Specify Stickerpicker widgets No changes from the MSC --- .../definitions/stickerpicker_data.yaml | 22 +++++++++++++++++++ api/widgets/examples/stickerpicker_data.json | 1 + specification/widgets.rst | 12 ++++++++++ 3 files changed, 35 insertions(+) create mode 100644 api/widgets/definitions/stickerpicker_data.yaml create mode 100644 api/widgets/examples/stickerpicker_data.json diff --git a/api/widgets/definitions/stickerpicker_data.yaml b/api/widgets/definitions/stickerpicker_data.yaml new file mode 100644 index 00000000000..d85a322ee8e --- /dev/null +++ b/api/widgets/definitions/stickerpicker_data.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickerpickerWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.stickerpicker``. Currently no + requirements are specified. +example: + $ref: "../examples/stickerpicker_data.json" +properties: {} diff --git a/api/widgets/examples/stickerpicker_data.json b/api/widgets/examples/stickerpicker_data.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/api/widgets/examples/stickerpicker_data.json @@ -0,0 +1 @@ +{} diff --git a/specification/widgets.rst b/specification/widgets.rst index 535c8d86c0e..8cf38aa5169 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -316,3 +316,15 @@ be added on a per-room basis with a widget ``type`` of ``m.grafana`` and ``data` Though technically possible, this widget type should not be used outside of room widgets. {{definition_widgets_grafana_data}} + +Stickerpicker +~~~~~~~~~~~~~ + +Stickerpickers are user widgets which allow the user to send ``m.sticker`` events to the current +room using the Widget API described by this specification. They have a widget ``type`` of +``m.stickerpicker`` and ``data`` which matches ``StickerpickerWidgetData``. + +.. Note:: + Though technically possible, this widget type should not be used outside of user widgets. + +{{definition_widgets_stickerpicker_data}} From 927f4c08a148f3d67c9bf8fd9286c620620d0f33 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 20:10:04 -0600 Subject: [PATCH 16/45] Specify Custom (default) widgets No changes from the MSC --- api/widgets/definitions/custom_data.yaml | 32 ++++++++++++++++++++++++ api/widgets/examples/custom_data.json | 3 +++ specification/widgets.rst | 10 ++++++++ 3 files changed, 45 insertions(+) create mode 100644 api/widgets/definitions/custom_data.yaml create mode 100644 api/widgets/examples/custom_data.json diff --git a/api/widgets/definitions/custom_data.yaml b/api/widgets/definitions/custom_data.yaml new file mode 100644 index 00000000000..75b5c344bd9 --- /dev/null +++ b/api/widgets/definitions/custom_data.yaml @@ -0,0 +1,32 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: CustomWidgetData +description: |- + Definition for a widget's ``data`` when using a ``type`` of ``m.custom`` or using an + unknown/unsupported ``type``. Currently no requirements are specified. +example: + $ref: "../examples/custom_data.json" +properties: + url: + type: string + description: |- + The URL for the embedded content. Required only if the widget's URL does not match + the embedded content, before templating ocurrs. + + Clients should note that not all widgets which get interpretted as custom widgets + will have this property, though all widgets are required to have a higher level ``url`` + which can be used to display them. As such, requirements for this field being present + SHOULD only be enforced upon widgets with an explicit ``type`` of ``m.custom``. diff --git a/api/widgets/examples/custom_data.json b/api/widgets/examples/custom_data.json new file mode 100644 index 00000000000..6739fbd38ee --- /dev/null +++ b/api/widgets/examples/custom_data.json @@ -0,0 +1,3 @@ +{ + "url": "https://matrix.org" +} diff --git a/specification/widgets.rst b/specification/widgets.rst index 8cf38aa5169..da9b2aef782 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -328,3 +328,13 @@ room using the Widget API described by this specification. They have a widget `` Though technically possible, this widget type should not be used outside of user widgets. {{definition_widgets_stickerpicker_data}} + +Custom Widgets +~~~~~~~~~~~~~~ + +Custom widgets are the most basic form of widget possible, and represent teh default behaviour +for all widgets. They have an explicit widget ``type`` of ``m.custom``, though any +unknown/unsupported widget type for the client will be treated as a custom widget. They have +``data`` matching ``CustomWidgetData``. + +{{definition_widgets_custom_data}} From fa3e85ff66e610b41bdb9d0e4629da34b47eaf0e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 20:16:50 -0600 Subject: [PATCH 17/45] Add a note about widget wrappers These are extremely common in practice. --- specification/widgets.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index da9b2aef782..c54117c4a50 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -338,3 +338,17 @@ unknown/unsupported widget type for the client will be treated as a custom widge ``data`` matching ``CustomWidgetData``. {{definition_widgets_custom_data}} + +Widget Wrappers +--------------- + +Most widgets in the wild are "wrapped" with some website that provides added functionality or +handles the Widget API communications. They have no formal specification as they are implicitly +handled as part of rendering widgets. As such, they also have no specific requirements to have +any particular behaviour. + +A wrapper typically appears on a widget as a ``url`` pointing to a resource which then embeds +the content within another iframe. This allows the widget to be gated by authentication or be +more easily embedded within Matrix (as would be the case for Spotify and similar widgets - the +content to be embedded does not translate directly to a Matrix widget and instead needs a bit +of help from a wrapper to embed nicely). From 8c237c400fdaddc25c80862bde4f06824f44e9ee Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 20:18:01 -0600 Subject: [PATCH 18/45] Mention that invalid `data` means the widget is custom --- specification/widgets.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specification/widgets.rst b/specification/widgets.rst index c54117c4a50..a3474954143 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -213,7 +213,9 @@ to render the widget kind in that way. For example, custom widgets at the per-us per-room level might not be possible and thus can be treated as invalid (ignored). Clients are not required to support all of these widget types (with the implied exception of -``m.custom``) as they can all be safely represented as ``m.custom`` widgets. +``m.custom``) as they can all be safely represented as ``m.custom`` widgets. Similarly, if a +widget fails the schema requirements for its ``type`` then it should be treated as ``m.custom`` +by the client. Jitsi Meet Conferences ~~~~~~~~~~~~~~~~~~~~~~ From db96e6c90882296377431e6235196c4d37dafa18 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 20:18:58 -0600 Subject: [PATCH 19/45] Fix API Standards heading --- specification/widgets.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/widgets.rst b/specification/widgets.rst index a3474954143..ece4f7ba6d1 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -49,7 +49,7 @@ The following other versions are also available, in reverse chronological order: - `HEAD `_: Includes all changes since the latest versioned release. API Standards -~~~~~~~~~~~~~ +------------- Throughout this specification, a "client" is referred to as something which is rendering/supporting ("hosting") widgets. Widgets are unique in that they can be considered a client when referred to in From 6552523219da9baaa2a5d6d774f68361f08e950c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 31 Aug 2020 20:30:51 -0600 Subject: [PATCH 20/45] Record the remaining security considerations so far --- specification/widgets.rst | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/specification/widgets.rst b/specification/widgets.rst index ece4f7ba6d1..cdd27f152f0 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -137,7 +137,9 @@ video conference widgets. Clients SHOULD ask for permission to load a widget from the user prior to presenting the widget. If the user was the last ``sender`` of a widget (not the ``creatorUserId``), the prompt can be skipped. This prompt is strongly encouraged to ensure that users do not inadvertently send their information -to a third party. +to a third party. Private information such as the user's name, avatar, or IP address can be sent as +a result of how widgets work, and thus clients should attempt to prevent users from sending this +information unknowingly. URL Templating ~~~~~~~~~~~~~~ @@ -181,6 +183,11 @@ A few default variables, which MUST take priority over the same names in ``data` string if not present. This shouldn't be the ``mxc://`` form of the user's avatar, but instead the full HTTP URL to the ``/media/download`` endpoint for their avatar from the Client-Server API. +.. WARNING:: + The ``matrix_user_id`` variable MUST NOT be assumed to be the current authenticated user due to + how trivial it is to provide false details with. Widgets which need to store per-user details + or private information will need to verify the user's identity in some other way. + Security Considerations ~~~~~~~~~~~~~~~~~~~~~~~ @@ -188,13 +195,19 @@ Clients SHOULD check to ensure that widgets are valid URLs *after* templating bu or asking for permission to load. Invalid URLs from the client's perspective should not be shown to the user and can be treated as though no ``url`` was present (i.e.: a deleted/invalid widget). -Clients SHOULD limit which URL schemes are able to be rendered to ensure that they are not rendering -potentially dangerous files. Most widgets will have schemes of ``http`` or ``https``. +Clients MUST NOT attempt to render widgets with schemes other than ``http:`` and ``https:``. Widgets +using alternative schemes, including template variables as schemes, are considered invalid and thus +should be ignored. This is to prevent widget creators from using ``javascript:`` or similar schemes +to gain access to the user's data. Clients SHOULD apply a sandbox to their iframe or platform equivilant to ensure the widget cannot get access to the data stored by the client, such as access tokens or cryptographic keys. More information on origin restrictions is in the Widget API's security considerations section. +Clients should be aware of a potential `CSRF `_ +opportunity due to clients making arbitrary ``GET`` requests to URLs. Typical sites should not +be using ``GET`` as a state change method, though it is theoretically possible. + Widget Types ------------ From 2c08043ad62ac23ce369f651385aecc6f02d44ea Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 12:28:39 -0600 Subject: [PATCH 21/45] Move custom widgets up to indicate their importance --- specification/widgets.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/specification/widgets.rst b/specification/widgets.rst index cdd27f152f0..85a533261b7 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -230,6 +230,16 @@ Clients are not required to support all of these widget types (with the implied widget fails the schema requirements for its ``type`` then it should be treated as ``m.custom`` by the client. +Custom Widgets +~~~~~~~~~~~~~~ + +Custom widgets are the most basic form of widget possible, and represent the default behaviour +for all widgets. They have an explicit widget ``type`` of ``m.custom``, though any +unknown/unsupported widget type for the client will be treated as a custom widget. They have +``data`` matching ``CustomWidgetData``. + +{{definition_widgets_custom_data}} + Jitsi Meet Conferences ~~~~~~~~~~~~~~~~~~~~~~ @@ -344,16 +354,6 @@ room using the Widget API described by this specification. They have a widget `` {{definition_widgets_stickerpicker_data}} -Custom Widgets -~~~~~~~~~~~~~~ - -Custom widgets are the most basic form of widget possible, and represent teh default behaviour -for all widgets. They have an explicit widget ``type`` of ``m.custom``, though any -unknown/unsupported widget type for the client will be treated as a custom widget. They have -``data`` matching ``CustomWidgetData``. - -{{definition_widgets_custom_data}} - Widget Wrappers --------------- From 7a6e09b6a81c04d0b2eb9031a3ac3cd808fb26af Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 13:42:11 -0600 Subject: [PATCH 22/45] Early specification for the Widget API There are only a couple differences from the MSC here: * Timeouts are not specified in the MSC, and neither is the requirement to have a request acknowledged. Both timeouts and acknowledgment requirements happen in practice, so they've been included here. * The error response is slightly varied from the MSC due to misrepresentation and lack of usage. The MSC wants a JavaScript error object at the same level as the `message`, though in practice we include it under an `_error` key next to the `message`. Due to it being underscored, not used, and generally not translating well outside of web browsers, it's been omitted. --- api/widgets/definitions/api_error.yaml | 41 ++++++++++++++++ api/widgets/definitions/api_request.yaml | 57 +++++++++++++++++++++++ api/widgets/definitions/api_response.yaml | 38 +++++++++++++++ specification/widgets.rst | 43 +++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 api/widgets/definitions/api_error.yaml create mode 100644 api/widgets/definitions/api_request.yaml create mode 100644 api/widgets/definitions/api_response.yaml diff --git a/api/widgets/definitions/api_error.yaml b/api/widgets/definitions/api_error.yaml new file mode 100644 index 00000000000..dae2b45e78c --- /dev/null +++ b/api/widgets/definitions/api_error.yaml @@ -0,0 +1,41 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: WidgetApiErrorResponse +description: |- + Schema definition for an error response in the Widget API. This is a regular ``WidgetApiResponse`` + object with the ``response`` specified as follows. +allOf: + - $ref: "./api_response.yaml" +properties: + response: + type: object + title: WidgetErrorResponseData + description: |- + The response data. + properties: + error: + type: object + title: WidgetApiError + description: |- + Information about the error which happened. + properties: + message: + type: string + description: |- + Human-readable string for the cause of the error. + example: "Failed to process request: Server returned 500 error" + required: ['message'] + required: ['error'] diff --git a/api/widgets/definitions/api_request.yaml b/api/widgets/definitions/api_request.yaml new file mode 100644 index 00000000000..d50f469709c --- /dev/null +++ b/api/widgets/definitions/api_request.yaml @@ -0,0 +1,57 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: WidgetApiRequest +description: |- + Schema definition for a widget request object over the Widget API. +properties: + api: + type: string + enum: [fromWidget, toWidget] + description: |- + The API for which the request is to be sent over. + example: "fromWidget" + requestId: + type: string + description: |- + An opaque string which uniquely identifies the request in the context of the session. + example: "generated-id-1234" + action: + type: string + description: |- + The action to send to the other party. Custom actions can be sent using the Java package + naming convention as a namespace. + example: "com.example.say_hello" + widgetId: + type: string + description: |- + The widget's ID. + example: "20200827_WidgetExample" + data: + type: object + description: |- + The request data. + additionalProperties: + type: object + title: value # intentionally named strangely to make it show up as {string: value} + example: { + "request-param": "value" + } +required: + - api + - requestId + - action + - widgetId + - data diff --git a/api/widgets/definitions/api_response.yaml b/api/widgets/definitions/api_response.yaml new file mode 100644 index 00000000000..fb930dd033e --- /dev/null +++ b/api/widgets/definitions/api_response.yaml @@ -0,0 +1,38 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: WidgetApiResponse +description: |- + Schema definition for a widget response object over the Widget API. + + .. Note:: + This is intentionally designed to allow API users to copy the request object + verbatim and simply append their ``response``. + +allOf: + - $ref: "./api_request.yaml" +properties: + response: + type: object + description: |- + The response data. + additionalProperties: + type: object + title: value # intentionally named strangely to make it show up as {string: value} + example: { + "response-param": "value" + } +required: + - response diff --git a/specification/widgets.rst b/specification/widgets.rst index 85a533261b7..ddb0050f088 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -367,3 +367,46 @@ the content within another iframe. This allows the widget to be gated by authent more easily embedded within Matrix (as would be the case for Spotify and similar widgets - the content to be embedded does not translate directly to a Matrix widget and instead needs a bit of help from a wrapper to embed nicely). + +Widget API +---------- + +The widget API is a bidirectional communication channel between the widget and the client, initiated +by either side. This communication happens over the `JavaScript postMessage API +`_. + +The API is split into two parts: ``fromWidget`` (widget -> client) and ``toWidget`` (client -> widget). +Both have the same general API shape: A request, called an ``action``, is sent to the other party +using the ``WidgetApiRequest`` schema. The other party then processes the request and returns an +object matching ``WidgetApiResponse``. + +All communication is done within a "session", where the first message sent to either side indicates +the start of the session. Only the client can close/terminate a session by unloading/reloading the +widget. + +The ``data`` of a ``WidgetApiRequest`` varies depending on the ``action`` of the request, as does the +``response`` of a ``WidgetApiResponse``. + +{{definition_widgets_api_request}} + +{{definition_widgets_api_response}} + +Timeouts +~~~~~~~~ + +All requests sent over the API require a response from the other side, even if the response is to +just acknowledge that the request happened. Both widgets and clients should implement timeouts on +their requests to avoid them hanging forever. The default recommended timeout is 10 seconds, after +which the request should be considered not answered and failed. Requests can be retried if they are +failed, though some actions do not lend themselves well to idempotency. + +Error Handling +~~~~~~~~~~~~~~ + +When the receiver fails to handle a request, it should acknowledge the request with an error response. +Note that this doesn't include timeouts, as the receiver will not have had an error processing the +request - it simply did not receive it in time. + +An error response takes the shape of a ``WidgetApiErrorResponse``. + +{{definition_widgets_api_error}} From 2479ee5837a4161c19d18871d7c041914d06b374 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 13:46:09 -0600 Subject: [PATCH 23/45] Move widget data examples into their schema definitions This makes for a slightly easier directory structure to manage --- api/widgets/definitions/custom_data.yaml | 3 +-- api/widgets/definitions/etherpad_data.yaml | 3 +-- api/widgets/definitions/googlecalendar_data.yaml | 3 +-- api/widgets/definitions/googledocs_data.yaml | 3 +-- api/widgets/definitions/grafana_data.yaml | 3 +-- api/widgets/definitions/jitsi_data.yaml | 5 +++-- api/widgets/definitions/spotify_data.yaml | 3 +-- api/widgets/definitions/stickerpicker_data.yaml | 3 +-- api/widgets/definitions/tradingview_data.yaml | 4 ++-- api/widgets/definitions/video_data.yaml | 3 +-- api/widgets/examples/custom_data.json | 3 --- api/widgets/examples/etherpad_data.json | 3 --- api/widgets/examples/googlecalendar_data.json | 3 --- api/widgets/examples/googledocs_data.json | 3 --- api/widgets/examples/grafana_data.json | 3 --- api/widgets/examples/jitsi_data.json | 5 ----- api/widgets/examples/spotify_data.json | 3 --- api/widgets/examples/stickerpicker_data.json | 1 - api/widgets/examples/tradingview_data.json | 4 ---- api/widgets/examples/video_data.json | 3 --- 20 files changed, 13 insertions(+), 51 deletions(-) delete mode 100644 api/widgets/examples/custom_data.json delete mode 100644 api/widgets/examples/etherpad_data.json delete mode 100644 api/widgets/examples/googlecalendar_data.json delete mode 100644 api/widgets/examples/googledocs_data.json delete mode 100644 api/widgets/examples/grafana_data.json delete mode 100644 api/widgets/examples/jitsi_data.json delete mode 100644 api/widgets/examples/spotify_data.json delete mode 100644 api/widgets/examples/stickerpicker_data.json delete mode 100644 api/widgets/examples/tradingview_data.json delete mode 100644 api/widgets/examples/video_data.json diff --git a/api/widgets/definitions/custom_data.yaml b/api/widgets/definitions/custom_data.yaml index 75b5c344bd9..32a0c175425 100644 --- a/api/widgets/definitions/custom_data.yaml +++ b/api/widgets/definitions/custom_data.yaml @@ -17,8 +17,6 @@ title: CustomWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.custom`` or using an unknown/unsupported ``type``. Currently no requirements are specified. -example: - $ref: "../examples/custom_data.json" properties: url: type: string @@ -30,3 +28,4 @@ properties: will have this property, though all widgets are required to have a higher level ``url`` which can be used to display them. As such, requirements for this field being present SHOULD only be enforced upon widgets with an explicit ``type`` of ``m.custom``. + example: "https://matrix.org" diff --git a/api/widgets/definitions/etherpad_data.yaml b/api/widgets/definitions/etherpad_data.yaml index 653d0a8781c..ca63f0e2690 100644 --- a/api/widgets/definitions/etherpad_data.yaml +++ b/api/widgets/definitions/etherpad_data.yaml @@ -16,11 +16,10 @@ type: object title: EtherpadWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.etherpad``. -example: - $ref: "../examples/etherpad_data.json" properties: url: type: string description: |- The URL to the Etherpad editor to embed. Required if the widget's URL differs from the pad's URL, before templating occurs. + example: "https://etherpad.example.org/p/ExamplePadName" diff --git a/api/widgets/definitions/googlecalendar_data.yaml b/api/widgets/definitions/googlecalendar_data.yaml index b9d486de40f..79ccbc2efec 100644 --- a/api/widgets/definitions/googlecalendar_data.yaml +++ b/api/widgets/definitions/googlecalendar_data.yaml @@ -16,12 +16,11 @@ type: object title: GoogleCalendarWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.googlecalendar``. -example: - $ref: "../examples/googlecalendar_data.json" properties: shareId: type: string description: |- The Google Calendar ID to embed. + example: "en.uk#holiday@group.v.calendar.google.com" required: - shareId diff --git a/api/widgets/definitions/googledocs_data.yaml b/api/widgets/definitions/googledocs_data.yaml index 3e3bf1dda18..b2605511cf4 100644 --- a/api/widgets/definitions/googledocs_data.yaml +++ b/api/widgets/definitions/googledocs_data.yaml @@ -16,11 +16,10 @@ type: object title: GoogleDocsWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.googledoc``. -example: - $ref: "../examples/googledocs_data.json" properties: url: type: string description: |- The URL to the document to embed. Required if the widget's URL differs from the document's URL, before templating occurs. + example: "https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit" diff --git a/api/widgets/definitions/grafana_data.yaml b/api/widgets/definitions/grafana_data.yaml index b54ee6b1297..831fd804aee 100644 --- a/api/widgets/definitions/grafana_data.yaml +++ b/api/widgets/definitions/grafana_data.yaml @@ -16,11 +16,10 @@ type: object title: GrafanaWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.grafana``. -example: - $ref: "../examples/grafana_data.json" properties: url: type: string description: |- The URL to the Grafana dashboard, snapshot, or other embedded resource as supported by Grafana. Required if the widget's URL differs from the Grafana URL, before templating occurs. + example: "https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" diff --git a/api/widgets/definitions/jitsi_data.yaml b/api/widgets/definitions/jitsi_data.yaml index 64c506785f6..fb43dc92b43 100644 --- a/api/widgets/definitions/jitsi_data.yaml +++ b/api/widgets/definitions/jitsi_data.yaml @@ -16,18 +16,18 @@ type: object title: JitsiWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.jitsi``. -example: - $ref: "../examples/jitsi_data.json" properties: domain: type: string description: |- The Jitsi Meet domain where the conference is to be hosted. + example: "meet.jit.si" conferenceId: type: string description: |- The conference ID (also known as the room name) where the conference is to be hosted on the given domain. + example: "HelloWorld" isAudioOnly: type: boolean default: false @@ -35,6 +35,7 @@ properties: If true, the Jitsi Meet conference should be started as audio only ny the client if possible. When false, the conference should be started normally (with video). Defaults to false (normal conference) when not provided. + example: false required: - domain - conferenceId diff --git a/api/widgets/definitions/spotify_data.yaml b/api/widgets/definitions/spotify_data.yaml index 8e349e56d9f..ab1b3be2a8a 100644 --- a/api/widgets/definitions/spotify_data.yaml +++ b/api/widgets/definitions/spotify_data.yaml @@ -16,12 +16,11 @@ type: object title: SpotifyWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.spotify``. -example: - $ref: "../examples/spotify_data.json" properties: uri: type: string description: |- The Spotify URI or share URL for the resource to embed, as supported by Spotify. + example: "spotify:episode:3jVWns139xO1u6F13dhwuF" required: - uri diff --git a/api/widgets/definitions/stickerpicker_data.yaml b/api/widgets/definitions/stickerpicker_data.yaml index d85a322ee8e..ac04f15c40a 100644 --- a/api/widgets/definitions/stickerpicker_data.yaml +++ b/api/widgets/definitions/stickerpicker_data.yaml @@ -17,6 +17,5 @@ title: StickerpickerWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.stickerpicker``. Currently no requirements are specified. -example: - $ref: "../examples/stickerpicker_data.json" properties: {} +example: {} diff --git a/api/widgets/definitions/tradingview_data.yaml b/api/widgets/definitions/tradingview_data.yaml index 69973174de1..4fa0f416254 100644 --- a/api/widgets/definitions/tradingview_data.yaml +++ b/api/widgets/definitions/tradingview_data.yaml @@ -16,17 +16,17 @@ type: object title: TradingViewWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.tradingview``. -example: - $ref: "../examples/tradingview_data.json" properties: interval: type: string description: |- The interval to supply to the TradingView chart, as supported by the chart. + example: "D" pair: type: string description: |- The symbol to represent by the TradingView chart, as supported by the chart. + example: "COINBASE:BTCUSD" required: - interval - pair diff --git a/api/widgets/definitions/video_data.yaml b/api/widgets/definitions/video_data.yaml index 903e6fccecb..f1c17a79e71 100644 --- a/api/widgets/definitions/video_data.yaml +++ b/api/widgets/definitions/video_data.yaml @@ -16,12 +16,11 @@ type: object title: VideoWidgetData description: |- Definition for a widget's ``data`` when using a ``type`` of ``m.video``. -example: - $ref: "../examples/video_data.json" properties: url: type: string description: |- The URL to the video to embed. + example: "https://www.youtube.com/watch?v=gtbIWSsHICI" required: - url diff --git a/api/widgets/examples/custom_data.json b/api/widgets/examples/custom_data.json deleted file mode 100644 index 6739fbd38ee..00000000000 --- a/api/widgets/examples/custom_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "url": "https://matrix.org" -} diff --git a/api/widgets/examples/etherpad_data.json b/api/widgets/examples/etherpad_data.json deleted file mode 100644 index ed86b45c800..00000000000 --- a/api/widgets/examples/etherpad_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "url": "https://etherpad.example.org/p/ExamplePadName" -} diff --git a/api/widgets/examples/googlecalendar_data.json b/api/widgets/examples/googlecalendar_data.json deleted file mode 100644 index 72e63541b09..00000000000 --- a/api/widgets/examples/googlecalendar_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "shareId": "en.uk#holiday@group.v.calendar.google.com" -} diff --git a/api/widgets/examples/googledocs_data.json b/api/widgets/examples/googledocs_data.json deleted file mode 100644 index 6ce8864039b..00000000000 --- a/api/widgets/examples/googledocs_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "url": "https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit" -} diff --git a/api/widgets/examples/grafana_data.json b/api/widgets/examples/grafana_data.json deleted file mode 100644 index 1f1720f2ceb..00000000000 --- a/api/widgets/examples/grafana_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "url": "https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" -} diff --git a/api/widgets/examples/jitsi_data.json b/api/widgets/examples/jitsi_data.json deleted file mode 100644 index 51996514dc9..00000000000 --- a/api/widgets/examples/jitsi_data.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "domain": "meet.jit.si", - "conferenceId": "HelloWorld", - "isAudioOnly": false -} diff --git a/api/widgets/examples/spotify_data.json b/api/widgets/examples/spotify_data.json deleted file mode 100644 index f775e6fa8af..00000000000 --- a/api/widgets/examples/spotify_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "uri": "spotify:episode:3jVWns139xO1u6F13dhwuF" -} diff --git a/api/widgets/examples/stickerpicker_data.json b/api/widgets/examples/stickerpicker_data.json deleted file mode 100644 index 0967ef424bc..00000000000 --- a/api/widgets/examples/stickerpicker_data.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/api/widgets/examples/tradingview_data.json b/api/widgets/examples/tradingview_data.json deleted file mode 100644 index 5eba7ad6c2b..00000000000 --- a/api/widgets/examples/tradingview_data.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "interval": "D", - "pair": "COINBASE:BTCUSD" -} diff --git a/api/widgets/examples/video_data.json b/api/widgets/examples/video_data.json deleted file mode 100644 index b2d68cd90e4..00000000000 --- a/api/widgets/examples/video_data.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "url": "https://www.youtube.com/watch?v=gtbIWSsHICI" -} From 229a2ab8345278be942cbbbf8a2035f3505e36e3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 13:57:56 -0600 Subject: [PATCH 24/45] Clean up descriptions for API responses --- api/widgets/definitions/api_error.yaml | 2 +- api/widgets/definitions/api_response.yaml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/api/widgets/definitions/api_error.yaml b/api/widgets/definitions/api_error.yaml index dae2b45e78c..239632847f9 100644 --- a/api/widgets/definitions/api_error.yaml +++ b/api/widgets/definitions/api_error.yaml @@ -30,7 +30,7 @@ properties: type: object title: WidgetApiError description: |- - Information about the error which happened. + Information about the error that happened. properties: message: type: string diff --git a/api/widgets/definitions/api_response.yaml b/api/widgets/definitions/api_response.yaml index fb930dd033e..2eb4912a94f 100644 --- a/api/widgets/definitions/api_response.yaml +++ b/api/widgets/definitions/api_response.yaml @@ -34,5 +34,20 @@ properties: example: { "response-param": "value" } + # We define other properties from the api_request.yaml schema to override their descriptions + # for context purposes + api: + type: string + enum: [fromWidget, toWidget] + description: The API the request was sent over. + example: "fromWidget" + requestId: + type: string + description: The request ID supplied in the original request. + example: "generated-id-1234" + action: + type: string + description: The action which was invoked. + example: "com.example.say_hello" required: - response From ac74770031cb0110a46ef588c12801affdde3a9f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 14:28:58 -0600 Subject: [PATCH 25/45] Specify the startup sequence for the widget API The only deviation from the MSC here is that custom capabilities are allowed to exist, because they do. --- specification/widgets.rst | 102 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index ddb0050f088..4a494350021 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -410,3 +410,105 @@ request - it simply did not receive it in time. An error response takes the shape of a ``WidgetApiErrorResponse``. {{definition_widgets_api_error}} + +Initiating Communication +~~~~~~~~~~~~~~~~~~~~~~~~ + +Immediately prior to rendering a widget, the client MUST prepare itself to handle communications +with the widget. Typically this will result in setting up appropriate event listeners for the +API requests. + +If the widget was set up with ``waitForIframeLoad: false``, the widget will initiate the +communication by sending a ``fromWidget`` request with ``action`` of ``content_loaded`` (see below). +If ``waitForIframeLoad`` was ``true``, the client will initiate communication once the iframe or +platform equivilant has loaded successfully (see ``waitForIframeLoad``'s description). + +Once the client has established that the widget has loaded, as defined by ``waitForIframeLoad``, +it initiates a capabilities negotiation with the widget. This is done using the ``capabilities`` +action on the ``toWidget`` API. + +The capabilities negotiated set the stage for what the widget is allowed to do within the session. +Clients MUST NOT re-negotiate capabilities after the session has been established. + +A broad sequence diagram for ``waitForIframeLoad: false`` is as follows:: + + +---------+ +---------+ + | Client | | Widget | + +---------+ +---------+ + | | + | Render widget | + |-------------- | + | | | + |<------------- | + | | + | content_loaded request | + |<----------------------------------------| + | | + | Acknowledge content_loaded request | + |---------------------------------------->| + | | + | capabilities request | + |---------------------------------------->| + | | + | Requested capabilities response | + |<----------------------------------------| + | | + | Check/verify capabilities | + |-------------------------- | + | | | + |<------------------------- | + | | + +A broad sequence diagram for ``waitForIframeLoad: true`` is as follows:: + + +---------+ +---------+ + | Client | | Widget | + +---------+ +---------+ + | | + | Render widget | + |-------------- | + | | | + |<------------- | + | | + | capabilities request | + |---------------------------------------->| + | | + | Requested capabilities response | + |<----------------------------------------| + | | + | Check/verify capabilities | + |-------------------------- | + | | | + |<------------------------- | + | | + +After both sequence diagrams, the session has been successfully established and can continue as +normal. + +Verifying Capabilities +++++++++++++++++++++++ + +The client MUST have a mechanism to approve/deny capabilities. This can be done within the client's +code, not involving the user, by using heuristics such as the origin and widget type, or it can be +done by involving the user with a prompt to approve/deny particular capabilities. + +The capabilities negotiation does not specify a way for the client to indicate to the widget which +capabilities were denied. The widget SHOULD only request the bare minimum required to function and +assume that it will receive all the requested capabilities. Clients SHOULD NOT automatically approve +all requested capabilities from widgets. + +Whenever a widget attempts to do something with the API which requires a capability it was denied, +the client MUST respond with an error response indicating as such. + +Any capabilities requested by the widget which the client does not recognize MUST be denied +automatically. Similarly, a client MUST NOT send requests to a widget which require the widget +to have been aprroved for a capability that it was denied access to. Clients MUST NOT approve +capabilities the widget did not request - these are implicitly denied. + +A complete list of capabilities can be found in the `Available Capabilities`_ section. + +Available Capabilities +~~~~~~~~~~~~~~~~~~~~~~ + +The following capabilities are defined by this specification. Custom capabilities can only be +defined via a namespace using the Java package naming convention. From b6d7ce561d8e4e3e2d6931906ac56f5fab236c89 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 16:49:48 -0600 Subject: [PATCH 26/45] Specify widget screenshots No deviations from the MSC --- .../definitions/screenshot_action.yaml | 32 +++++++++++++++++ .../screenshot_action_request.yaml | 22 ++++++++++++ .../screenshot_action_response.yaml | 36 +++++++++++++++++++ specification/widgets.rst | 33 +++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 api/widgets/definitions/screenshot_action.yaml create mode 100644 api/widgets/definitions/screenshot_action_request.yaml create mode 100644 api/widgets/definitions/screenshot_action_response.yaml diff --git a/api/widgets/definitions/screenshot_action.yaml b/api/widgets/definitions/screenshot_action.yaml new file mode 100644 index 00000000000..5140ba4608b --- /dev/null +++ b/api/widgets/definitions/screenshot_action.yaml @@ -0,0 +1,32 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: ScreenshotActionBase +properties: + api: + type: string + enum: ["toWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "toWidget" + action: + type: string + enum: ["screenshot"] + description: "" # The enum will result in this being "Must be $0" + example: "screenshot" + data: + type: object + description: |- + An empty data object (no request parameters). + example: {} diff --git a/api/widgets/definitions/screenshot_action_request.yaml b/api/widgets/definitions/screenshot_action_request.yaml new file mode 100644 index 00000000000..cdd97420d2c --- /dev/null +++ b/api/widgets/definitions/screenshot_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: ScreenshotActionRequest +description: |- + Schema definition for a ``toWidget`` API request with action of ``screenshot``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./screenshot_action.yaml" +properties: {} diff --git a/api/widgets/definitions/screenshot_action_response.yaml b/api/widgets/definitions/screenshot_action_response.yaml new file mode 100644 index 00000000000..75579e7c5fa --- /dev/null +++ b/api/widgets/definitions/screenshot_action_response.yaml @@ -0,0 +1,36 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: ScreenshotActionResponse +description: |- + Schema definition for a response to a ``ScreenshotActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./screenshot_action.yaml" +properties: + response: + type: object + description: |- + The response data. + title: ScreenshotActionResponseData + properties: + screenshot: + type: object + title: JS Blob + description: |- + A `Blob `_ containing the + screenshot. + example: '' + required: ['screenshot'] diff --git a/specification/widgets.rst b/specification/widgets.rst index 4a494350021..08960bd6897 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -512,3 +512,36 @@ Available Capabilities The following capabilities are defined by this specification. Custom capabilities can only be defined via a namespace using the Java package naming convention. + +Screenshots ++++++++++++ + +``m.capbility.screenshot`` can be requested by widgets if they support screenshots being taken +of them via the ``screenshot`` action. Typically this is only used to verify that the widget API +communications work between a client and widget. Widgets cannot use this capability to initiate +screenshots being taken of them - clients must request screenshots with the ``screenshot`` action. + +``toWidget`` API +~~~~~~~~~~~~~~~~~~ + +The ``toWidget`` API is reserved for communications from the client to the widget. Custom +actions can be defined by using the Java package naming convention as a namespace. + +Screenshots ++++++++++++ + +If the widget is approved for use of the ``m.capbility.screenshot`` capability, the client can +send a ``screenshot`` action (``ScreenshotActionRequest``) to request an image from the widget +(returned as a ``ScreenshotActionResponse``). + +.. Note:: + This is typically only used to verify that communication is working between the widget and client. + +.. WARNING:: + Widgets have an ability to send extremely large files and non-images via this action. Clients + should only enable support for screenshots in a trusted environment, such as when a widget + developer is making use of the client to test their widget. + +{{definition_widgets_screenshot_action_request}} + +{{definition_widgets_screenshot_action_response}} From 700336f0099e7757df001763ff1ccdac3a8eb93a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 16:50:06 -0600 Subject: [PATCH 27/45] Clarify the iframe onLoad diagram for widgets --- specification/widgets.rst | 48 +++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/specification/widgets.rst b/specification/widgets.rst index 08960bd6897..61fbbcb6b90 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -461,26 +461,34 @@ A broad sequence diagram for ``waitForIframeLoad: false`` is as follows:: A broad sequence diagram for ``waitForIframeLoad: true`` is as follows:: - +---------+ +---------+ - | Client | | Widget | - +---------+ +---------+ - | | - | Render widget | - |-------------- | - | | | - |<------------- | - | | - | capabilities request | - |---------------------------------------->| - | | - | Requested capabilities response | - |<----------------------------------------| - | | - | Check/verify capabilities | - |-------------------------- | - | | | - |<------------------------- | - | | + +---------+ +---------+ + | Client | | Widget | + +---------+ +---------+ + | | + | Render widget | + |-------------- | + | | | + |<------------- | + | | + | | iframe loading + | |--------------- + | | | + | |<-------------- + | | + | Implicit onLoad event | + |<-------------------------------------| + | | + | capabilities request | + |------------------------------------->| + | | + | Requested capabilities response | + |<-------------------------------------| + | | + | Check/verify capabilities | + |-------------------------- | + | | | + |<------------------------- | + | | After both sequence diagrams, the session has been successfully established and can continue as normal. From 84d304c197117f53df4b4aba17427d9bda8c70cd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 20:17:30 -0600 Subject: [PATCH 28/45] Specify the capabilities action This diverges slightly from the MSC to match reality in that the MSC wants the widget to get all the permissions it asked for or be rejected, however in practice the client can deny some/all of the permissions without notifying the widget and the widget is expected to continue normally. This deviation is generally fine as most capabilities are in the client->widget direction anyhow. --- .../definitions/capabilities_action.yaml | 32 ++++++++++++++++ .../capabilities_action_request.yaml | 22 +++++++++++ .../capabilities_action_response.yaml | 37 +++++++++++++++++++ specification/widgets.rst | 11 ++++++ 4 files changed, 102 insertions(+) create mode 100644 api/widgets/definitions/capabilities_action.yaml create mode 100644 api/widgets/definitions/capabilities_action_request.yaml create mode 100644 api/widgets/definitions/capabilities_action_response.yaml diff --git a/api/widgets/definitions/capabilities_action.yaml b/api/widgets/definitions/capabilities_action.yaml new file mode 100644 index 00000000000..c0250095a12 --- /dev/null +++ b/api/widgets/definitions/capabilities_action.yaml @@ -0,0 +1,32 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: CapabilitiesActionBase +properties: + api: + type: string + enum: ["toWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "toWidget" + action: + type: string + enum: ["capabilities"] + description: "" # The enum will result in this being "Must be $0" + example: "capabilities" + data: + type: object + description: |- + An empty data object (no request parameters). + example: {} diff --git a/api/widgets/definitions/capabilities_action_request.yaml b/api/widgets/definitions/capabilities_action_request.yaml new file mode 100644 index 00000000000..af749ab42b4 --- /dev/null +++ b/api/widgets/definitions/capabilities_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: CapabilitiesActionRequest +description: |- + Schema definition for a ``toWidget`` API request with action of ``capabilities``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./capabilities_action.yaml" +properties: {} diff --git a/api/widgets/definitions/capabilities_action_response.yaml b/api/widgets/definitions/capabilities_action_response.yaml new file mode 100644 index 00000000000..3ed9111ecc7 --- /dev/null +++ b/api/widgets/definitions/capabilities_action_response.yaml @@ -0,0 +1,37 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: CapabilitiesActionResponse +description: |- + Schema definition for a response to a ``CapabilitiesActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./capabilities_action.yaml" +properties: + response: + type: object + description: |- + The response data. + title: CapabilitiesActionResponseData + properties: + capabilities: + type: array + items: + type: string + description: |- + The list of requested capabilities. An empty array indicates that no capabilities are + requested. + example: ["m.capabilitity.screenshot", "m.sticker"] + required: ['capabilities'] diff --git a/specification/widgets.rst b/specification/widgets.rst index 61fbbcb6b90..84c4328e590 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -535,6 +535,17 @@ screenshots being taken of them - clients must request screenshots with the ``sc The ``toWidget`` API is reserved for communications from the client to the widget. Custom actions can be defined by using the Java package naming convention as a namespace. +Capabilities +++++++++++++ + +As part of the capabilities negotiation, the client sends a request with an action of +``capabilities`` (``CapabilitiesActionRequest``) to the widget, which replies with the requested +set of capabilities (``CapabilitiesActionResponse``). + +{{definition_widgets_capabilities_action_request}} + +{{definition_widgets_capabilities_action_response}} + Screenshots +++++++++++ From db08e5472d0b6512005fa136a04fefc0d4c70f2f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 1 Sep 2020 21:20:38 -0600 Subject: [PATCH 29/45] Specify versioning for the widget API This has significant deviation from the MSC and practical implementation due to lack of validation. The MSC specifies the request/response schema as described in this commit, though the associated behaviour and timings are different. In practice, no widget has implemented `supported_api_versions` and no client has ever requested it from a widget. This is expected to change with the specification being present. Additionally, widgets are technically able to send an `api_version` request to get the *current* version, though this is implied by the `supported_api_versions` response and thus not considered. Tying the version to the spec release is something introduced by this commit, as are the restrictions about what can and cannot be sent by either side. This commit also introduces timing constraints that allow widgets/clients to check the other's versions at any time, even during session initialization, due to the potential need for the initialization sequence to change. Further, this lumps `0.0.1` and `0.0.2` into the same version (which is expected to release as `0.1.0`) despite minor differences between the two. These differences are years old and effectively not important in the eyes of the spec. It is arguable that this particular section should be an MSC on top of the widgets MSC rather than landing like this. --- .../supported_versions_action.yaml | 32 ++++ .../supported_versions_action_request.yaml | 22 +++ .../supported_versions_action_response.yaml | 36 ++++ specification/widgets.rst | 170 ++++++++++++------ 4 files changed, 206 insertions(+), 54 deletions(-) create mode 100644 api/widgets/definitions/supported_versions_action.yaml create mode 100644 api/widgets/definitions/supported_versions_action_request.yaml create mode 100644 api/widgets/definitions/supported_versions_action_response.yaml diff --git a/api/widgets/definitions/supported_versions_action.yaml b/api/widgets/definitions/supported_versions_action.yaml new file mode 100644 index 00000000000..f5822cb1677 --- /dev/null +++ b/api/widgets/definitions/supported_versions_action.yaml @@ -0,0 +1,32 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: SupportedVersionsActionBase +properties: + api: + type: string + enum: ["toWidget", "fromWidget"] + description: "The API for which the version request is going over." + example: "toWidget" + action: + type: string + enum: ["supported_api_versions"] + description: "" # The enum will result in this being "Must be $0" + example: "supported_api_versions" + data: + type: object + description: |- + An empty data object (no request parameters). + example: {} diff --git a/api/widgets/definitions/supported_versions_action_request.yaml b/api/widgets/definitions/supported_versions_action_request.yaml new file mode 100644 index 00000000000..e3879e1464a --- /dev/null +++ b/api/widgets/definitions/supported_versions_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: SupportedVersionsActionRequest +description: |- + Schema definition for an API request with action of ``supported_api_versions``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./supported_versions_action.yaml" +properties: {} diff --git a/api/widgets/definitions/supported_versions_action_response.yaml b/api/widgets/definitions/supported_versions_action_response.yaml new file mode 100644 index 00000000000..c55ec017fd1 --- /dev/null +++ b/api/widgets/definitions/supported_versions_action_response.yaml @@ -0,0 +1,36 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: SupportedVersionsActionResponse +description: |- + Schema definition for a response to a ``SupportedVersionsActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./supported_versions_action.yaml" +properties: + response: + type: object + description: |- + The response data. + title: SupportedVersionsActionResponseData + properties: + supported_versions: + type: array + items: + type: string + description: |- + The supported Widget API versions. + example: ['0.0.1', '0.0.2', '0.1.0'] + required: ['supported_versions'] diff --git a/specification/widgets.rst b/specification/widgets.rst index 84c4328e590..09d2d5db091 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -411,6 +411,33 @@ An error response takes the shape of a ``WidgetApiErrorResponse``. {{definition_widgets_api_error}} +Versioning +~~~~~~~~~~ + +The Widget API version tracks the version of this specification (``r0.1.0`` is Widget API version +``0.1.0``, for example). Both widgets and clients can perform a request with action of +``supported_api_versions`` (``SupportedVersionsActionRequest``) to get the other side's list of +supported versions (``SupportedVersionsActionResponse``). The sender SHOULD NOT use actions which +are unsupported by the intended destination. In the event that the sender and destination cannot +agree on a supported version, either side should abort their continued execution + +Actions in this specification list which version they were introduced in for historical purposes. +Actions will always be backwards compatible with prior versions of the specification, though the +specification from time to time may add/remove actions as needed. + +In order for a widget/client to support an API version, it MUST implement all actions supported +by that version. For clarity, all actions presented by this document at a given version are +supported by that version. Implicitly, the actions to request supported API versions are mandatory +for all implementations. + +.. Note:: + For historical purposes, ``0.0.1`` and ``0.0.2`` are additionally valid versions which implement + the same set as ``0.1.0`` (the first version of this specification). + +{{definition_widgets_supported_versions_action_request}} + +{{definition_widgets_supported_versions_action_response}} + Initiating Communication ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -430,65 +457,96 @@ action on the ``toWidget`` API. The capabilities negotiated set the stage for what the widget is allowed to do within the session. Clients MUST NOT re-negotiate capabilities after the session has been established. +Prior to the session being initiated, neither side should be sending actions outside of those +required to set up the session. Version checking can happen at any time by either side, though +the initiator of the session should be left responsible for the first version check. For example, +if the client is waiting for a ``content_loaded`` action then the widget should be the one to +request the supported API versions first. Once a version check has been started by one side, it is +implied that the other side can do the same. + A broad sequence diagram for ``waitForIframeLoad: false`` is as follows:: - +---------+ +---------+ - | Client | | Widget | - +---------+ +---------+ - | | - | Render widget | - |-------------- | - | | | - |<------------- | - | | - | content_loaded request | - |<----------------------------------------| - | | - | Acknowledge content_loaded request | - |---------------------------------------->| - | | - | capabilities request | - |---------------------------------------->| - | | - | Requested capabilities response | - |<----------------------------------------| - | | - | Check/verify capabilities | - |-------------------------- | - | | | - |<------------------------- | - | | + +---------+ +---------+ + | Client | | Widget | + +---------+ +---------+ + | | + | Render widget | + |-------------- | + | | | + |<------------- | + | | + | `supported_api_versions` request | + |<------------------------------------------| + | | + | `supported_api_versions` response | + |------------------------------------------>| + | | + | `supported_api_versions` request | + |------------------------------------------>| + | | + | `supported_api_versions` response | + |<------------------------------------------| + | | + | `content_loaded` request | + |<------------------------------------------| + | | + | Acknowledge `content_loaded` request | + |------------------------------------------>| + | | + | `capabilities` request | + |------------------------------------------>| + | | + | `capabilities` response | + |<------------------------------------------| + | | + | Approve/deny capabilities | + |-------------------------- | + | | | + |<------------------------- | + | | A broad sequence diagram for ``waitForIframeLoad: true`` is as follows:: - +---------+ +---------+ - | Client | | Widget | - +---------+ +---------+ - | | - | Render widget | - |-------------- | - | | | - |<------------- | - | | - | | iframe loading - | |--------------- - | | | - | |<-------------- - | | - | Implicit onLoad event | - |<-------------------------------------| - | | - | capabilities request | - |------------------------------------->| - | | - | Requested capabilities response | - |<-------------------------------------| - | | - | Check/verify capabilities | - |-------------------------- | - | | | - |<------------------------- | - | | + +---------+ +---------+ + | Client | | Widget | + +---------+ +---------+ + | | + | Render widget | + |-------------- | + | | | + |<------------- | + | | + | | iframe loading + | |--------------- + | | | + | |<-------------- + | | + | Implicit `onLoad` event from iframe | + |<-----------------------------------------| + | | + | `supported_api_versions` request | + |----------------------------------------->| + | | + | `supported_api_versions` response | + |<-----------------------------------------| + | | + | `supported_api_versions` request | + |<-----------------------------------------| + | | + | `supported_api_versions` response | + |----------------------------------------->| + | | + | `capabilities` request | + |----------------------------------------->| + | | + | `capabilities` response | + |<-----------------------------------------| + | | + | Approve/deny capabilities | + |-------------------------- | + | | | + |<------------------------- | + | | After both sequence diagrams, the session has been successfully established and can continue as normal. @@ -538,6 +596,8 @@ actions can be defined by using the Java package naming convention as a namespac Capabilities ++++++++++++ +:Introduced in: ``0.1.0`` + As part of the capabilities negotiation, the client sends a request with an action of ``capabilities`` (``CapabilitiesActionRequest``) to the widget, which replies with the requested set of capabilities (``CapabilitiesActionResponse``). @@ -549,6 +609,8 @@ set of capabilities (``CapabilitiesActionResponse``). Screenshots +++++++++++ +:Introduced in: ``0.1.0`` + If the widget is approved for use of the ``m.capbility.screenshot`` capability, the client can send a ``screenshot`` action (``ScreenshotActionRequest``) to request an image from the widget (returned as a ``ScreenshotActionResponse``). From c1c4f127e6a7589934365d6e49ef15169d287283 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 12:32:15 -0600 Subject: [PATCH 30/45] Add visibility to the API There are minor deviations from the MSC on this: * The action is different, as documented in the suggestions on the MSC. * The response is different. The MSC wants a `success: true` parameter, however to maintain consistency this has been removed. Nothing uses this in practice. --- .../definitions/visibility_action.yaml | 39 +++++++++++++++++++ .../visibility_action_request.yaml | 22 +++++++++++ .../visibility_action_response.yaml | 27 +++++++++++++ specification/widgets.rst | 23 +++++++++++ 4 files changed, 111 insertions(+) create mode 100644 api/widgets/definitions/visibility_action.yaml create mode 100644 api/widgets/definitions/visibility_action_request.yaml create mode 100644 api/widgets/definitions/visibility_action_response.yaml diff --git a/api/widgets/definitions/visibility_action.yaml b/api/widgets/definitions/visibility_action.yaml new file mode 100644 index 00000000000..98c38317226 --- /dev/null +++ b/api/widgets/definitions/visibility_action.yaml @@ -0,0 +1,39 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: VisibilityActionBase +properties: + api: + type: string + enum: ["toWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "toWidget" + action: + type: string + enum: ["visibility"] + description: "" # The enum will result in this being "Must be $0" + example: "visibility" + data: + type: object + description: |- + Information about whether or not the widget is visible. + title: VisibilityActionRequestData + properties: + visible: + type: boolean + description: |- + True if the widget is visible to the user, false otherwise. + example: false + required: ['visible'] diff --git a/api/widgets/definitions/visibility_action_request.yaml b/api/widgets/definitions/visibility_action_request.yaml new file mode 100644 index 00000000000..f18e5d94dcc --- /dev/null +++ b/api/widgets/definitions/visibility_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: VisibilityActionRequest +description: |- + Schema definition for a ``toWidget`` API request with action of ``visibility``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./visibility_action.yaml" +properties: {} diff --git a/api/widgets/definitions/visibility_action_response.yaml b/api/widgets/definitions/visibility_action_response.yaml new file mode 100644 index 00000000000..d0862312282 --- /dev/null +++ b/api/widgets/definitions/visibility_action_response.yaml @@ -0,0 +1,27 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: VisibilityActionResponse +description: |- + Schema definition for a response to a ``VisibilityActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./visibility_action_request.yaml" +properties: + response: + type: object + description: |- + An empty response body to acknowledge the request. + example: {} diff --git a/specification/widgets.rst b/specification/widgets.rst index 09d2d5db091..a4ca7cd2586 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -626,3 +626,26 @@ send a ``screenshot`` action (``ScreenshotActionRequest``) to request an image f {{definition_widgets_screenshot_action_request}} {{definition_widgets_screenshot_action_response}} + +Widget Visibility ++++++++++++++++++ + +:Introduced in: ``0.1.0`` + +The client can indicate to the widget whether it is visible or not to the user with the ``visbility`` +action request (``VisibilityActionRequest``). If the widget does not receive visibility information, +it must assume that it is visible to the user. + +Typically this action is not used on room widgets as they are visible implicitly to the user when +they view that room. Account widgets, however, often get rendered in the background by the client +and thus can be hidden/shown at times. + +.. Note:: + Stickerpicker widgets and similar often make the best use of this to reload the user's available + content when the widget gets shown again. + +This action should only be sent when visibility of the widget to the user changes. + +{{definition_widgets_visibility_action_request}} + +{{definition_widgets_visibility_action_response}} From 8aadcd3552b5637d91cc56996077aeb75ec9315c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 14:33:47 -0600 Subject: [PATCH 31/45] Specify the content_loaded action No deviations from the MSC --- .../definitions/content_loaded_action.yaml | 32 +++++++++++++++++++ .../content_loaded_action_request.yaml | 22 +++++++++++++ .../content_loaded_action_response.yaml | 27 ++++++++++++++++ specification/widgets.rst | 20 ++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 api/widgets/definitions/content_loaded_action.yaml create mode 100644 api/widgets/definitions/content_loaded_action_request.yaml create mode 100644 api/widgets/definitions/content_loaded_action_response.yaml diff --git a/api/widgets/definitions/content_loaded_action.yaml b/api/widgets/definitions/content_loaded_action.yaml new file mode 100644 index 00000000000..4b19076185c --- /dev/null +++ b/api/widgets/definitions/content_loaded_action.yaml @@ -0,0 +1,32 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: ContentLoadedActionBase +properties: + api: + type: string + enum: ["fromWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "fromWidget" + action: + type: string + enum: ["content_loaded"] + description: "" # The enum will result in this being "Must be $0" + example: "content_loaded" + data: + type: object + description: |- + An empty data object (no request parameters). + example: {} diff --git a/api/widgets/definitions/content_loaded_action_request.yaml b/api/widgets/definitions/content_loaded_action_request.yaml new file mode 100644 index 00000000000..27552184486 --- /dev/null +++ b/api/widgets/definitions/content_loaded_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: ContentLoadedActionRequest +description: |- + Schema definition for a ``fromWidget`` API request with action of ``content_loaded``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./content_loaded_action.yaml" +properties: {} diff --git a/api/widgets/definitions/content_loaded_action_response.yaml b/api/widgets/definitions/content_loaded_action_response.yaml new file mode 100644 index 00000000000..b146920858a --- /dev/null +++ b/api/widgets/definitions/content_loaded_action_response.yaml @@ -0,0 +1,27 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: ContentLoadedActionResponse +description: |- + Schema definition for a response to a ``ContentLoadedActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./content_loaded_action.yaml" +properties: + response: + type: object + description: |- + An empty response body to acknowledge the request. + example: {} diff --git a/specification/widgets.rst b/specification/widgets.rst index a4ca7cd2586..deb1d4df2e2 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -649,3 +649,23 @@ This action should only be sent when visibility of the widget to the user change {{definition_widgets_visibility_action_request}} {{definition_widgets_visibility_action_response}} + +``fromWidget`` API +~~~~~~~~~~~~~~~~~~ + +The ``fromWidget`` API is reserved for communications from the widget to the client. Custom actions +can be defined by using the Java package naming convention as a namespace. + +Indicating Content Loaded ++++++++++++++++++++++++++ + +:Introduced in: ``0.1.0`` + +In some rendering cases, the widget is expected to send a ``content_loaded`` action request taking +the shape of ``ContentLoadedActionRequest``. The widget can send this any time, even when not +required for establishing the session. Widgets SHOULD NOT send this action after the session has +been established. + +{{definition_widgets_content_loaded_action_request}} + +{{definition_widgets_content_loaded_action_response}} From 26b0a3a9b77b65ef2d373b2f873e0593dc397741 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 15:12:55 -0600 Subject: [PATCH 32/45] Specify stickers This has significant deviation from the MSC, though it aligns with reality. The capability name is the same in the MSC, but the action/request is completely different. --- api/widgets/definitions/sticker_action.yaml | 79 +++++++++++++++++++ .../definitions/sticker_action_request.yaml | 22 ++++++ .../definitions/sticker_action_response.yaml | 27 +++++++ specification/widgets.rst | 26 ++++++ 4 files changed, 154 insertions(+) create mode 100644 api/widgets/definitions/sticker_action.yaml create mode 100644 api/widgets/definitions/sticker_action_request.yaml create mode 100644 api/widgets/definitions/sticker_action_response.yaml diff --git a/api/widgets/definitions/sticker_action.yaml b/api/widgets/definitions/sticker_action.yaml new file mode 100644 index 00000000000..d98b7d0f2fc --- /dev/null +++ b/api/widgets/definitions/sticker_action.yaml @@ -0,0 +1,79 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickerActionBase +properties: + api: + type: string + enum: ["fromWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "fromWidget" + action: + type: string + enum: ["m.sticker"] + description: "" # The enum will result in this being "Must be $0" + example: "m.sticker" + data: + type: object + title: StickerActionRequestData + description: |- + Information about the sticker to send. + properties: + content: + type: object + title: StickerActionRequestEventContent + properties: + name: + type: string + description: |- + The human-readable name for the sticker. + example: "Smiling Face" + description: + type: string + description: |- + A longer form human-readable description for the sticker. + example: "A circular emoticon smiles blankly" + info: + type: object + # XXX: Ideally we'd link to the image info schema, but it has a bunch of backlinks which + # the widget spec cannot support. + title: ImageInfo + description: |- + Metadata about the image referred to in ``url`` including a thumbnail + representation. This value takes the same shape as ``ImageInfo`` as + defined for ``info`` on ``m.sticker`` events. + example: { + w: 512, + h: 512, + mimetype: "image/png", + size: 102400, + thumbnail_url: "mxc://example.org/def5678", + thumbnail_info: { + w: 256, + h: 256, + mimetype: "image/png", + size: 10240 + } + } + url: + description: |- + The URL to the sticker image. This must be a valid ``mxc://`` URI. + type: string + example: "mxc://example.org/abc1234" + required: + - name + - info + - url + required: ['content'] diff --git a/api/widgets/definitions/sticker_action_request.yaml b/api/widgets/definitions/sticker_action_request.yaml new file mode 100644 index 00000000000..a40f2e367d0 --- /dev/null +++ b/api/widgets/definitions/sticker_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickerActionRequest +description: |- + Schema definition for an API request with action of ``m.sticker``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./sticker_action.yaml" +properties: {} diff --git a/api/widgets/definitions/sticker_action_response.yaml b/api/widgets/definitions/sticker_action_response.yaml new file mode 100644 index 00000000000..92771c57273 --- /dev/null +++ b/api/widgets/definitions/sticker_action_response.yaml @@ -0,0 +1,27 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickerActionResponse +description: |- + Schema definition for a response to a ``StickerActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./sticker_action_request.yaml" +properties: + response: + type: object + description: |- + An empty response body to acknowledge the request. + example: {} diff --git a/specification/widgets.rst b/specification/widgets.rst index deb1d4df2e2..30d91a2030d 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -587,6 +587,13 @@ of them via the ``screenshot`` action. Typically this is only used to verify tha communications work between a client and widget. Widgets cannot use this capability to initiate screenshots being taken of them - clients must request screenshots with the ``screenshot`` action. +Sticker Sending ++++++++++++++++ + +``m.sticker`` can be requested by widgets if they would like to send stickers into the room the +user is currently viewing. This should be implicitly approved by clients for ``m.stickerpicker`` +widgets. + ``toWidget`` API ~~~~~~~~~~~~~~~~~~ @@ -669,3 +676,22 @@ been established. {{definition_widgets_content_loaded_action_request}} {{definition_widgets_content_loaded_action_response}} + +Sending Stickers +++++++++++++++++ + +:Introduced in: ``0.1.0`` + +If the widget is approved for use of the ``m.sticker`` capability, the widget can send ``m.sticker`` +action requests (``StickerActionRequest``) to have the client post an ``m.sticker`` event to the +room the user is currently viewing. If the room is encrypted, the client is responsible for +encrypting the widget's implied event. + +The stickers widgets produce MUST meet the requirements of stickers in ``m.sticker`` events. For +creating the sticker event, the client uses the ``name`` or ``description`` from the request +in the event's ``body``, and otherwise copies the ``url`` and ``info`` values from the request +to the event directly (potentially with some validation). + +{{definition_widgets_sticker_action_request}} + +{{definition_widgets_sticker_action_response}} From 5d469eb31582c030a737d0bd16355c4ae0125f69 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 15:14:00 -0600 Subject: [PATCH 33/45] Use the request schema as a base for the response schema Largely for sanity, even if they are all are shell definitions. --- api/widgets/definitions/capabilities_action_response.yaml | 2 +- api/widgets/definitions/content_loaded_action_response.yaml | 2 +- api/widgets/definitions/screenshot_action_response.yaml | 2 +- api/widgets/definitions/supported_versions_action_response.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/widgets/definitions/capabilities_action_response.yaml b/api/widgets/definitions/capabilities_action_response.yaml index 3ed9111ecc7..2f242b2e499 100644 --- a/api/widgets/definitions/capabilities_action_response.yaml +++ b/api/widgets/definitions/capabilities_action_response.yaml @@ -18,7 +18,7 @@ description: |- Schema definition for a response to a ``CapabilitiesActionRequest``. allOf: - $ref: "./api_response.yaml" - - $ref: "./capabilities_action.yaml" + - $ref: "./capabilities_action_request.yaml" properties: response: type: object diff --git a/api/widgets/definitions/content_loaded_action_response.yaml b/api/widgets/definitions/content_loaded_action_response.yaml index b146920858a..3d8c1eae870 100644 --- a/api/widgets/definitions/content_loaded_action_response.yaml +++ b/api/widgets/definitions/content_loaded_action_response.yaml @@ -18,7 +18,7 @@ description: |- Schema definition for a response to a ``ContentLoadedActionRequest``. allOf: - $ref: "./api_response.yaml" - - $ref: "./content_loaded_action.yaml" + - $ref: "./content_loaded_action_request.yaml" properties: response: type: object diff --git a/api/widgets/definitions/screenshot_action_response.yaml b/api/widgets/definitions/screenshot_action_response.yaml index 75579e7c5fa..57d6f0ef688 100644 --- a/api/widgets/definitions/screenshot_action_response.yaml +++ b/api/widgets/definitions/screenshot_action_response.yaml @@ -18,7 +18,7 @@ description: |- Schema definition for a response to a ``ScreenshotActionRequest``. allOf: - $ref: "./api_response.yaml" - - $ref: "./screenshot_action.yaml" + - $ref: "./screenshot_action_request.yaml" properties: response: type: object diff --git a/api/widgets/definitions/supported_versions_action_response.yaml b/api/widgets/definitions/supported_versions_action_response.yaml index c55ec017fd1..93615a3330c 100644 --- a/api/widgets/definitions/supported_versions_action_response.yaml +++ b/api/widgets/definitions/supported_versions_action_response.yaml @@ -18,7 +18,7 @@ description: |- Schema definition for a response to a ``SupportedVersionsActionRequest``. allOf: - $ref: "./api_response.yaml" - - $ref: "./supported_versions_action.yaml" + - $ref: "./supported_versions_action_request.yaml" properties: response: type: object From fe5363501d21ee2e6689f4e115f5fa52b8319529 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 15:30:57 -0600 Subject: [PATCH 34/45] Specify always on screen (MSC1354) The only deviation from this MSC is that the `value` request parameter is actually in `data`, as implied by the standardized format for the API. --- api/widgets/definitions/sticky_action.yaml | 40 +++++++++++++++++++ .../definitions/sticky_action_request.yaml | 22 ++++++++++ .../definitions/sticky_action_response.yaml | 37 +++++++++++++++++ specification/widgets.rst | 26 ++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 api/widgets/definitions/sticky_action.yaml create mode 100644 api/widgets/definitions/sticky_action_request.yaml create mode 100644 api/widgets/definitions/sticky_action_response.yaml diff --git a/api/widgets/definitions/sticky_action.yaml b/api/widgets/definitions/sticky_action.yaml new file mode 100644 index 00000000000..025ce3ddd6d --- /dev/null +++ b/api/widgets/definitions/sticky_action.yaml @@ -0,0 +1,40 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickyActionBase +properties: + api: + type: string + enum: ["fromWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "fromWidget" + action: + type: string + enum: ["set_always_on_screen"] + description: "" # The enum will result in this being "Must be $0" + example: "set_always_on_screen" + data: + type: object + title: StickyActionRequestData + description: |- + Details about the request to be always on screen. + properties: + value: + type: boolean + description: |- + If true, the widget should remain on screen if possible. If false, the widget + would like to use the default rendering behaviour. + example: true + required: ['value'] diff --git a/api/widgets/definitions/sticky_action_request.yaml b/api/widgets/definitions/sticky_action_request.yaml new file mode 100644 index 00000000000..85de8fb2a42 --- /dev/null +++ b/api/widgets/definitions/sticky_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickyActionRequest +description: |- + Schema definition for an API request with action of ``set_always_on_screen``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./sticky_action.yaml" +properties: {} diff --git a/api/widgets/definitions/sticky_action_response.yaml b/api/widgets/definitions/sticky_action_response.yaml new file mode 100644 index 00000000000..ffc48bda9d4 --- /dev/null +++ b/api/widgets/definitions/sticky_action_response.yaml @@ -0,0 +1,37 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: StickyActionResponse +description: |- + Schema definition for a response to a ``StickyActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./sticky_action_request.yaml" +properties: + response: + type: object + description: |- + The response data. + title: StickyActionResponseData + properties: + success: + type: boolean + description: |- + True to indicate the client was able to honour the request, false otherwise. The client + will only be able to honour the request if the widget is requesting to be set back to + the default behaviour, or if the widget is requesting to be on screen and no other widget + has done the same already. Permission errors relating to capabilities will result in an + error response instead of this response. + required: ['success'] diff --git a/specification/widgets.rst b/specification/widgets.rst index 30d91a2030d..97aed117434 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -594,6 +594,13 @@ Sticker Sending user is currently viewing. This should be implicitly approved by clients for ``m.stickerpicker`` widgets. +Always On Screen +++++++++++++++++ + +``m.always_on_screen`` can be requested by widgets if they would like to be able to use the +``set_always_on_screen`` action. This should be implicitly approved by clients for ``m.jitsi`` +widgets (see the action's spec for more information). + ``toWidget`` API ~~~~~~~~~~~~~~~~~~ @@ -695,3 +702,22 @@ to the event directly (potentially with some validation). {{definition_widgets_sticker_action_request}} {{definition_widgets_sticker_action_response}} + +Always On Screen +++++++++++++++++ + +:Introduced in: ``0.1.0`` + +If the widget is approved for use of the ``m.always_on_screen`` capability, the widget can request +that the client keep it always on screen with a ``set_always_on_screen`` action request +(``StickyActionRequest``). + +Widgets by default are *not* always on screen, and only one widget at a time can be always on the +screen. Typically this is used by video conferencing widgets to ensure that the call is not disrupted +when the user switches rooms, and as such clients SHOULD ignore the restriction regarding only +rendering widgets when the user is viewing that room while the widget has requested to be always on +screen. + +{{definition_widgets_sticky_action_request}} + +{{definition_widgets_sticky_action_response}} From b853bfafb6482c923855678aa918ecbeb1435092 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 15:32:33 -0600 Subject: [PATCH 35/45] Leave a note about how this spec tries to support auto-genned code --- specification/widgets.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index 97aed117434..df85b3409f9 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -69,6 +69,9 @@ All objects exchanged over the Widget (``postMessage``) API are JSON objects. In essence, widgets are typically iframes or the platform equivilant to a website which are accessible in the client. +All of the schemas in this specification are intended to be referenced by name, and thus can safely +be used in auto-generated implementations which rely on stable naming. + Widget Kinds ------------ From 84c627b7aa468179dc1f39f24fed000b7d26cc3e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 19:15:49 -0600 Subject: [PATCH 36/45] Remove simple widgets which serve no purpose All of these widgets can be represented safely as custom widgets, and thus need no specific behaviour. --- api/widgets/definitions/etherpad_data.yaml | 25 ----- .../definitions/googlecalendar_data.yaml | 26 ----- api/widgets/definitions/googledocs_data.yaml | 25 ----- api/widgets/definitions/grafana_data.yaml | 25 ----- api/widgets/definitions/spotify_data.yaml | 26 ----- api/widgets/definitions/tradingview_data.yaml | 32 ------ api/widgets/definitions/video_data.yaml | 26 ----- specification/widgets.rst | 99 +------------------ 8 files changed, 4 insertions(+), 280 deletions(-) delete mode 100644 api/widgets/definitions/etherpad_data.yaml delete mode 100644 api/widgets/definitions/googlecalendar_data.yaml delete mode 100644 api/widgets/definitions/googledocs_data.yaml delete mode 100644 api/widgets/definitions/grafana_data.yaml delete mode 100644 api/widgets/definitions/spotify_data.yaml delete mode 100644 api/widgets/definitions/tradingview_data.yaml delete mode 100644 api/widgets/definitions/video_data.yaml diff --git a/api/widgets/definitions/etherpad_data.yaml b/api/widgets/definitions/etherpad_data.yaml deleted file mode 100644 index ca63f0e2690..00000000000 --- a/api/widgets/definitions/etherpad_data.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: EtherpadWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.etherpad``. -properties: - url: - type: string - description: |- - The URL to the Etherpad editor to embed. Required if the widget's URL differs from the pad's - URL, before templating occurs. - example: "https://etherpad.example.org/p/ExamplePadName" diff --git a/api/widgets/definitions/googlecalendar_data.yaml b/api/widgets/definitions/googlecalendar_data.yaml deleted file mode 100644 index 79ccbc2efec..00000000000 --- a/api/widgets/definitions/googlecalendar_data.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: GoogleCalendarWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.googlecalendar``. -properties: - shareId: - type: string - description: |- - The Google Calendar ID to embed. - example: "en.uk#holiday@group.v.calendar.google.com" -required: - - shareId diff --git a/api/widgets/definitions/googledocs_data.yaml b/api/widgets/definitions/googledocs_data.yaml deleted file mode 100644 index b2605511cf4..00000000000 --- a/api/widgets/definitions/googledocs_data.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: GoogleDocsWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.googledoc``. -properties: - url: - type: string - description: |- - The URL to the document to embed. Required if the widget's URL differs from the document's - URL, before templating occurs. - example: "https://docs.google.com/document/d/1uPF7XWY_dXTKVKV7jZQ2KmsI19wn9-kFRgQ1tFQP7wQ/edit" diff --git a/api/widgets/definitions/grafana_data.yaml b/api/widgets/definitions/grafana_data.yaml deleted file mode 100644 index 831fd804aee..00000000000 --- a/api/widgets/definitions/grafana_data.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: GrafanaWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.grafana``. -properties: - url: - type: string - description: |- - The URL to the Grafana dashboard, snapshot, or other embedded resource as supported by - Grafana. Required if the widget's URL differs from the Grafana URL, before templating occurs. - example: "https://snapshot.raintank.io/dashboard-solo/snapshot/y7zwi2bZ7FcoTlB93WN7yWO4aMiz3pZb?from=1493369923321&to=1493377123321&panelId=4" diff --git a/api/widgets/definitions/spotify_data.yaml b/api/widgets/definitions/spotify_data.yaml deleted file mode 100644 index ab1b3be2a8a..00000000000 --- a/api/widgets/definitions/spotify_data.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: SpotifyWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.spotify``. -properties: - uri: - type: string - description: |- - The Spotify URI or share URL for the resource to embed, as supported by Spotify. - example: "spotify:episode:3jVWns139xO1u6F13dhwuF" -required: - - uri diff --git a/api/widgets/definitions/tradingview_data.yaml b/api/widgets/definitions/tradingview_data.yaml deleted file mode 100644 index 4fa0f416254..00000000000 --- a/api/widgets/definitions/tradingview_data.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: TradingViewWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.tradingview``. -properties: - interval: - type: string - description: |- - The interval to supply to the TradingView chart, as supported by the chart. - example: "D" - pair: - type: string - description: |- - The symbol to represent by the TradingView chart, as supported by the chart. - example: "COINBASE:BTCUSD" -required: - - interval - - pair diff --git a/api/widgets/definitions/video_data.yaml b/api/widgets/definitions/video_data.yaml deleted file mode 100644 index f1c17a79e71..00000000000 --- a/api/widgets/definitions/video_data.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2020 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -type: object -title: VideoWidgetData -description: |- - Definition for a widget's ``data`` when using a ``type`` of ``m.video``. -properties: - url: - type: string - description: |- - The URL to the video to embed. - example: "https://www.youtube.com/watch?v=gtbIWSsHICI" -required: - - url diff --git a/specification/widgets.rst b/specification/widgets.rst index df85b3409f9..51d1a7e1d2a 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -233,8 +233,8 @@ Clients are not required to support all of these widget types (with the implied widget fails the schema requirements for its ``type`` then it should be treated as ``m.custom`` by the client. -Custom Widgets -~~~~~~~~~~~~~~ +Custom/Basic Widgets +~~~~~~~~~~~~~~~~~~~~ Custom widgets are the most basic form of widget possible, and represent the default behaviour for all widgets. They have an explicit widget ``type`` of ``m.custom``, though any @@ -254,99 +254,8 @@ a widget ``type`` of ``m.jitsi`` and ``data`` matching ``JitsiWidgetData``. {{definition_widgets_jitsi_data}} -TradingView -~~~~~~~~~~~ - -`TradingView `_ widgets can be addded on a per-room basis with -a widget ``type`` of ``m.tradingview`` and ``data`` matching ``TradingViewWidgetData``. - -This widget type is meant to be used with TradingView's -`Advanced Real-Time Chart Widget `_. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_tradingview_data}} - -Spotify -~~~~~~~ - -`Spotify Widgets `_ can be added on a -per-room basis with a widget ``type`` of ``m.spotify`` and ``data`` matching ``SpotifyWidgetData``. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_spotify_data}} - -Videos -~~~~~~ - -Videos from video streaming sites can be added on a per-room basis with a widget ``type`` of -``m.video`` and ``data`` matching ``VideoWidgetData``. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_video_data}} - -Google Docs -~~~~~~~~~~~ - -Documents from Google Docs, Sheets, and Slides can be added as widgets on a per-room basis with a -widget ``type`` of ``m.googledoc`` and ``data`` matching ``GoogleDocsWidgetData``. - -.. Note:: - Documents typically need to be publicly accessible without authentication to be embedded. Most - documents that would be shared by widgets are not publicly accessible and thus generally will - refuse to embed properly. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_googledocs_data}} - -Google Calendar -~~~~~~~~~~~~~~~ - -Calendars from Google Calendar can be added as widgets on a per-room basis with a widget ``type`` -of ``m.googlecalendar`` and ``data`` matching ``GoogleCalendarWidgetData``. - -.. Note:: - Calendars typically need to be publicly accessible without authentication to be embedded. Most - calendars that would be shared by widgets are not publicly accessible and thus generally will - refuse to embed properly. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_googlecalendar_data}} - -Etherpad -~~~~~~~~ - -`Etherpad `_ editors can be added on a per-room basis with a widget ``type`` -of ``m.etherpad`` and ``data`` matching ``EtherpadWidgetData``. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_etherpad_data}} - -Grafana -~~~~~~~ - -`Embedded Grafana Panels `_ can -be added on a per-room basis with a widget ``type`` of ``m.grafana`` and ``data`` matching -``GrafanaWidgetData``. - -.. Note:: - Though technically possible, this widget type should not be used outside of room widgets. - -{{definition_widgets_grafana_data}} - -Stickerpicker -~~~~~~~~~~~~~ +Stickerpickers +~~~~~~~~~~~~~~ Stickerpickers are user widgets which allow the user to send ``m.sticker`` events to the current room using the Widget API described by this specification. They have a widget ``type`` of From e2c45cea1d82a96c9b1f7778711a0451ad8c9bb3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 19:23:00 -0600 Subject: [PATCH 37/45] Add a security aspect to the widget API --- specification/widgets.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index 51d1a7e1d2a..80126fe17b3 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -633,3 +633,12 @@ screen. {{definition_widgets_sticky_action_request}} {{definition_widgets_sticky_action_response}} + +Security Considerations +~~~~~~~~~~~~~~~~~~~~~~~ + +The Widget API can allow for significant control of a client/widget, and thus needs to be secured +as much as possible. Clients should refuse/ignore requests and responses from origins other than +the widget's rendered origin, and should verify that the widget ID matches the expected value. +Widgets have a harder time of determining the origin, though they can rely on techniques like +``window.parent`` to ensure they are talking/responding to the right place. From 5be26358fe7c8cf82e84fddb4c9ab5f2b7256027 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 2 Sep 2020 19:37:50 -0600 Subject: [PATCH 38/45] [swagger parsing] Support freeform objects --- api/widgets/definitions/api_request.yaml | 4 +--- api/widgets/definitions/api_response.yaml | 4 +--- api/widgets/definitions/shared_props.yaml | 3 +-- scripts/templating/matrix_templates/units.py | 5 +++++ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/widgets/definitions/api_request.yaml b/api/widgets/definitions/api_request.yaml index d50f469709c..c8eb7ee260d 100644 --- a/api/widgets/definitions/api_request.yaml +++ b/api/widgets/definitions/api_request.yaml @@ -43,9 +43,7 @@ properties: type: object description: |- The request data. - additionalProperties: - type: object - title: value # intentionally named strangely to make it show up as {string: value} + additionalProperties: true example: { "request-param": "value" } diff --git a/api/widgets/definitions/api_response.yaml b/api/widgets/definitions/api_response.yaml index 2eb4912a94f..76c9f5442d7 100644 --- a/api/widgets/definitions/api_response.yaml +++ b/api/widgets/definitions/api_response.yaml @@ -28,9 +28,7 @@ properties: type: object description: |- The response data. - additionalProperties: - type: object - title: value # intentionally named strangely to make it show up as {string: value} + additionalProperties: true example: { "response-param": "value" } diff --git a/api/widgets/definitions/shared_props.yaml b/api/widgets/definitions/shared_props.yaml index 59f173e7b34..aec0ae571b2 100644 --- a/api/widgets/definitions/shared_props.yaml +++ b/api/widgets/definitions/shared_props.yaml @@ -69,8 +69,7 @@ properties: description: |- A human-readable title for the widget primarily shown next to the widget's name. example: "This is a witty description for the widget" - additionalProperties: - type: object + additionalProperties: true example: { "title": "This is a witty description for the widget", "custom-key": "This is a custom key" diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 1d6250f53d9..bc00a6ab372 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -206,6 +206,11 @@ def get_json_schema_object_fields(obj, enforce_title=False): logger.debug("Processing object with title '%s'", obj_title) additionalProps = obj.get("additionalProperties") + + # When 'additionalProps: true` is defined, it should be treated as a freeform object + if additionalProps == True: + additionalProps = dict(type="object", title="value") + props = obj.get("properties") if additionalProps and not props: # not "really" an object, just a KV store From 63a7f7b69aebda9f995a49642e4a9207d4aba005 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 4 Sep 2020 16:36:04 -0600 Subject: [PATCH 39/45] Move name property for sticker action up a level This is how element web does it --- api/widgets/definitions/sticker_action.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/api/widgets/definitions/sticker_action.yaml b/api/widgets/definitions/sticker_action.yaml index d98b7d0f2fc..252405d166e 100644 --- a/api/widgets/definitions/sticker_action.yaml +++ b/api/widgets/definitions/sticker_action.yaml @@ -31,15 +31,15 @@ properties: description: |- Information about the sticker to send. properties: + name: + type: string + description: |- + The human-readable name for the sticker. + example: "Smiling Face" content: type: object title: StickerActionRequestEventContent properties: - name: - type: string - description: |- - The human-readable name for the sticker. - example: "Smiling Face" description: type: string description: |- @@ -73,7 +73,6 @@ properties: type: string example: "mxc://example.org/abc1234" required: - - name - info - url - required: ['content'] + required: ['content', 'name'] From c9d72d3b7d615beae94ebfe905f03f1ff984f69f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 4 Sep 2020 16:36:56 -0600 Subject: [PATCH 40/45] Move description up too See 63a7f7b69aebda9f995a49642e4a9207d4aba005 --- api/widgets/definitions/sticker_action.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/widgets/definitions/sticker_action.yaml b/api/widgets/definitions/sticker_action.yaml index 252405d166e..ff21bb15717 100644 --- a/api/widgets/definitions/sticker_action.yaml +++ b/api/widgets/definitions/sticker_action.yaml @@ -36,15 +36,15 @@ properties: description: |- The human-readable name for the sticker. example: "Smiling Face" + description: + type: string + description: |- + A longer form human-readable description for the sticker. + example: "A circular emoticon smiles blankly" content: type: object title: StickerActionRequestEventContent properties: - description: - type: string - description: |- - A longer form human-readable description for the sticker. - example: "A circular emoticon smiles blankly" info: type: object # XXX: Ideally we'd link to the image info schema, but it has a bunch of backlinks which From 87f61449298dcbc59db48473e91af6d84ee884c7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 23 Sep 2020 16:02:51 -0600 Subject: [PATCH 41/45] Specify MSC1960 --- .../definitions/get_openid_action.yaml | 33 +++++ .../get_openid_action_request.yaml | 22 +++ .../get_openid_action_response.yaml | 44 ++++++ .../openid_credentials_action.yaml | 56 ++++++++ .../openid_credentials_action_request.yaml | 22 +++ .../openid_credentials_action_response.yaml | 28 ++++ .../definitions/openid_widget_api.yaml | 37 +++++ specification/widgets.rst | 127 ++++++++++++++++++ 8 files changed, 369 insertions(+) create mode 100644 api/widgets/definitions/get_openid_action.yaml create mode 100644 api/widgets/definitions/get_openid_action_request.yaml create mode 100644 api/widgets/definitions/get_openid_action_response.yaml create mode 100644 api/widgets/definitions/openid_credentials_action.yaml create mode 100644 api/widgets/definitions/openid_credentials_action_request.yaml create mode 100644 api/widgets/definitions/openid_credentials_action_response.yaml create mode 100644 api/widgets/definitions/openid_widget_api.yaml diff --git a/api/widgets/definitions/get_openid_action.yaml b/api/widgets/definitions/get_openid_action.yaml new file mode 100644 index 00000000000..0ae60585e04 --- /dev/null +++ b/api/widgets/definitions/get_openid_action.yaml @@ -0,0 +1,33 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: GetOpenIDCredentialsActionBase +properties: + api: + type: string + enum: ["fromWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "fromWidget" + action: + type: string + enum: ["get_openid"] + description: "" # The enum will result in this being "Must be $0" + example: "get_openid" + data: + type: object + title: GetOpenIDCredentialsRequestData + description: |- + An empty request body. + example: {} diff --git a/api/widgets/definitions/get_openid_action_request.yaml b/api/widgets/definitions/get_openid_action_request.yaml new file mode 100644 index 00000000000..bb2a6b6eb82 --- /dev/null +++ b/api/widgets/definitions/get_openid_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: GetOpenIDCredentialsActionRequest +description: |- + Schema definition for a ``fromWidget`` API request with action of ``get_openid``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./get_openid_action.yaml" +properties: {} diff --git a/api/widgets/definitions/get_openid_action_response.yaml b/api/widgets/definitions/get_openid_action_response.yaml new file mode 100644 index 00000000000..d7d8c10c040 --- /dev/null +++ b/api/widgets/definitions/get_openid_action_response.yaml @@ -0,0 +1,44 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: GetOpenIDCredentialsActionResponse +description: |- + Schema definition for a response to a ``GetOpenIDCredentialsActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./get_openid_action_request.yaml" +properties: + response: + type: object + title: GetOpenIDCredentialsActionResponseData + description: |- + The state of the OpenID Connect credentials request with potentially token + information. + + When ``state`` is ``allowed``, several properties (defined below) are required. + They hold the same meaning and specification as their same-named properties in + the response of the Client-Server API ``/user/{userId}/openid/request_token`` + endpoint. + allOf: + - $ref: "./openid_widget_api.yaml" + properties: + state: + type: string + enum: ["allowed", "blocked", "request"] + description: |- + The state of the request, as defined above. + example: "allowed" + required: + - state diff --git a/api/widgets/definitions/openid_credentials_action.yaml b/api/widgets/definitions/openid_credentials_action.yaml new file mode 100644 index 00000000000..362b34a56a2 --- /dev/null +++ b/api/widgets/definitions/openid_credentials_action.yaml @@ -0,0 +1,56 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: OpenIDCredentialsActionBase +properties: + api: + type: string + enum: ["toWidget"] + description: "" # The enum will result in this being "Must be $0" + example: "toWidget" + action: + type: string + enum: ["openid_credentials"] + description: "" # The enum will result in this being "Must be $0" + example: "openid_credentials" + data: + type: object + title: OpenIDCredentialsRequestData + description: |- + The state of a previous OpenID Connect credentials request with potentially + token information. + + When ``state`` is ``allowed``, several properties (defined below) are required. + They hold the same meaning and specification as their same-named properties in + the response of the Client-Server API ``/user/{userId}/openid/request_token`` + endpoint. + allOf: + - $ref: "./openid_widget_api.yaml" + properties: + state: + type: string + enum: ["allowed", "blocked"] + description: |- + Whether or not the user has allowed the widget's request to verify their + identity. + example: "allowed" + original_request_id: + type: string + description: |- + The ``requestId`` of the original ``fromWidget`` ``get_openid`` action request. + example: "11223344" + required: + - state + - original_request_id diff --git a/api/widgets/definitions/openid_credentials_action_request.yaml b/api/widgets/definitions/openid_credentials_action_request.yaml new file mode 100644 index 00000000000..e3f6ca07473 --- /dev/null +++ b/api/widgets/definitions/openid_credentials_action_request.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: OpenIDCredentialsActionRequest +description: |- + Schema definition for a ``toWidget`` API request with action of ``openid_credentials``. +allOf: + - $ref: "./api_request.yaml" + - $ref: "./openid_credentials_action.yaml" +properties: {} diff --git a/api/widgets/definitions/openid_credentials_action_response.yaml b/api/widgets/definitions/openid_credentials_action_response.yaml new file mode 100644 index 00000000000..039e8b9a08c --- /dev/null +++ b/api/widgets/definitions/openid_credentials_action_response.yaml @@ -0,0 +1,28 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: OpenIDCredentialsActionResponse +description: |- + Schema definition for a response to a ``OpenIDCredentialsActionRequest``. +allOf: + - $ref: "./api_response.yaml" + - $ref: "./openid_credentials_action_request.yaml" +properties: + response: + type: object + description: |- + The response data (an empty object). + title: OpenIDCredentialsActionResponseData + example: {} diff --git a/api/widgets/definitions/openid_widget_api.yaml b/api/widgets/definitions/openid_widget_api.yaml new file mode 100644 index 00000000000..07e1927ae0f --- /dev/null +++ b/api/widgets/definitions/openid_widget_api.yaml @@ -0,0 +1,37 @@ +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: OpenIDTokenInfoInWidgetApi +properties: + access_token: + type: string + description: |- + Required when ``state`` is ``allowed``. See above for specification. + example: "SomeT0kenHere" + token_type: + type: string + description: |- + Required when ``state`` is ``allowed``. See above for specification. + example: "Bearer" + matrix_server_name: + type: string + description: |- + Required when ``state`` is ``allowed``. See above for specification. + example: "example.com" + expires_in: + type: integer + description: |- + Required when ``state`` is ``allowed``. See above for specification. + example: 3600 diff --git a/specification/widgets.rst b/specification/widgets.rst index 80126fe17b3..3c436de5a33 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -513,6 +513,90 @@ Always On Screen ``set_always_on_screen`` action. This should be implicitly approved by clients for ``m.jitsi`` widgets (see the action's spec for more information). +OpenID Connect Authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Widgets can request OpenID Connect credentials from the client (which in turn requests them from the +homeserver) to validate that the current user is who they say they are. The credentials are validated +out of band from the client to ensure the client is not able to falsify them. + +There is no required capability for using this flow, however clients SHOULD prompt the user to +approve the widget's request to validate their identity. This prompt can have a "always remember for +this widget"-style checkbox on it, which is supported by the API exchange. Including the user in the +approval prompt does mean that the request is at risk of timing out, and as such there is a two part +exchange involving the client and widget. + +The request is always initiated by the widget using the ``fromWidget`` ``get_openid`` action. This +is either responded to immediately with an OpenID Connect token, an indication of the request being +blocked, or an indication that the user is making a decision. When a user makes a selection, the +client uses the ``toWidget`` API to send a ``openid_credentials`` action with the relevant state. + +After the widget receives the token from the client, it should validate it with the federation API. +Typically this means handing it off to a backend service which will validate the token and return +another credential the widget can use for future requests. + +.. WARNING:: + Like with the OpenID Connect endpoints described by the Client-Server API and Federation API, it + is important that the widget ensure the user ID returned by the server matches the server name + given in the token from the client. + +When needed, the client MUST call ``/_matrix/client/%CLIENT_MAJOR_VERSION%/user/{userId}/request_token`` +to get the needed token to pass through to the widget. + +A typical diagram of this flow is:: + + +-------+ +---------+ +---------+ +---------------+ +-------------+ + | User | | Client | | Widget | | WidgetBackend | | Homeserver | + +-------+ +---------+ +---------+ +---------------+ +-------------+ + | | | | | + | | Establish Widget API session | | | + | |----------------------------------------->| | | + | | | | | + | | Establish Widget API session | | | + | |<-----------------------------------------| | | + | | | | | + | | fromWidget get_openid request | | | + | |<-----------------------------------------| | | + | | | | | + | | ack with state "request" | | | + | |----------------------------------------->| | | + | | | | | + | Ask if the widget can verify their identity | | | | + |<-------------------------------------------------| | | | + | | | | | + | Approve | | | | + |------------------------------------------------->| | | | + | | | | | + | | Call /_matrix/client/{version}/user/{userId}/request_token | | + | |-------------------------------------------------------------------------------------------------------------------------------------------------------->| + | | | | | + | | | | OpenID Connect token | + | |<--------------------------------------------------------------------------------------------------------------------------------------------------------| + | | | | | + | | toWidget openid_credentials request | | | + | |----------------------------------------->| | | + | | | | | + | | ack with empty response object | | | + | |<-----------------------------------------| | | + | | | | | + | | | Send received token for validation | | + | | |------------------------------------------->| | + | | | | | + | | | | Federated call to /_matrix/federation/v1/openid/userinfo | + | | | |---------------------------------------------------------------->| + | | | | | + | | | | User information | + | | | |<----------------------------------------------------------------| + | | | | | + | | | | Verify returned user information | + | | | |--------------------------------- | + | | | | | | + | | | |<-------------------------------- | + | | | | | + | | | Successful validation response | | + | | |<-------------------------------------------| | + | | | | | + ``toWidget`` API ~~~~~~~~~~~~~~~~~~ @@ -576,6 +660,25 @@ This action should only be sent when visibility of the widget to the user change {{definition_widgets_visibility_action_response}} +OpenID Connect Credential Information ++++++++++++++++++++++++++++++++++++++ + +:Introduced in: ``0.1.0`` + +.. Note:: + This section assumes the reader has the prior knowledge established by the + `OpenID Connect Authentication <#openid-connect-authentication>`_ section. + +This action is used by the client to indicate that the user has made a selection regarding the +prompt to confirm if the widget can verify their identity. + +If approved, the request will contain the OpenID Connect token the widget will have to verify. If +defined, the request will indicate as such. + +{{definition_widgets_openid_credentials_action_request}} + +{{definition_widgets_openid_credentials_action_response}} + ``fromWidget`` API ~~~~~~~~~~~~~~~~~~ @@ -634,6 +737,30 @@ screen. {{definition_widgets_sticky_action_response}} +Requesting OpenID Connect Tokens +++++++++++++++++++++++++++++++++ + +:Introduced in: ``0.1.0`` + +.. Note:: + This section assumes the reader has the prior knowledge established by the + `OpenID Connect Authentication <#openid-connect-authentication>`_ section. + +This action is used by the widget to ask the client to start the OpenID Connect token exchange. +The client has three possible responses: + +* A ``state`` of ``allowed`` alongside the OpenID Connect token. This is typically used if the user + indicated that the widget is always allowed to verify their identity. +* A ``state`` of ``blocked``. This is typically used when the user has indicated that the widget + can never verify their identity. +* A ``state`` of ``request``. This indicates that the client is asking the user for permission and + will follow up with an appropriate ``toWidget`` ``openid_credentials`` request later. + + +{{definition_widgets_get_openid_action_request}} + +{{definition_widgets_get_openid_action_response}} + Security Considerations ~~~~~~~~~~~~~~~~~~~~~~~ From 538864d1ce8ea5de0ce2511fdbd0dd4cba307853 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 23 Sep 2020 16:09:03 -0600 Subject: [PATCH 42/45] Fix sticky action examples --- api/widgets/definitions/sticky_action_response.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/api/widgets/definitions/sticky_action_response.yaml b/api/widgets/definitions/sticky_action_response.yaml index ffc48bda9d4..8c36b742660 100644 --- a/api/widgets/definitions/sticky_action_response.yaml +++ b/api/widgets/definitions/sticky_action_response.yaml @@ -34,4 +34,5 @@ properties: the default behaviour, or if the widget is requesting to be on screen and no other widget has done the same already. Permission errors relating to capabilities will result in an error response instead of this response. + example: true required: ['success'] From 4b6bf3221c7c4680f4698a85ac2b4d859fd4e318 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 22 Nov 2020 18:02:25 -0700 Subject: [PATCH 43/45] Specify avatar_url per MSC2765 https://github.com/matrix-org/matrix-doc/pull/2765 --- api/widgets/definitions/shared_props.yaml | 9 +++++++++ api/widgets/examples/shared_props.json | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/api/widgets/definitions/shared_props.yaml b/api/widgets/definitions/shared_props.yaml index aec0ae571b2..753789b9d64 100644 --- a/api/widgets/definitions/shared_props.yaml +++ b/api/widgets/definitions/shared_props.yaml @@ -54,6 +54,15 @@ properties: from view until the ``content_loaded`` API action is sent by the widget. Defaults to true. example: true + avatar_url: + type: string + description: |- + An optional MXC URI to an image which can be used to identify the widget. Recommended + for use alongside the ``name`` and ``data.title``. + + Images SHOULD be legible at small sizes, such as 20x20 pixels. The MXC URI here should + be the source material to allow clients to use the ``/thumbnail`` endpoint on the media. + example: "mxc://example.org/aaabbbccc" data: type: object title: WidgetData diff --git a/api/widgets/examples/shared_props.json b/api/widgets/examples/shared_props.json index ce848b3bc23..d384cc8830f 100644 --- a/api/widgets/examples/shared_props.json +++ b/api/widgets/examples/shared_props.json @@ -8,5 +8,6 @@ "name": "My Cool Widget", "type": "m.custom", "url": "https://example.org/my/widget.html?roomId=$matrix_room_id", - "waitForIframeLoad": true + "waitForIframeLoad": true, + "avatar_url": "mxc://example.org/aaabbbccc" } From d5927ec75dc7b2c1ad6d3436345fc3c772c8634c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 22 Nov 2020 18:04:29 -0700 Subject: [PATCH 44/45] Specify matrix_widget_id template variable per MSC2774 https://github.com/matrix-org/matrix-doc/pull/2774 --- specification/widgets.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/widgets.rst b/specification/widgets.rst index 3c436de5a33..a9a3b56541d 100644 --- a/specification/widgets.rst +++ b/specification/widgets.rst @@ -185,6 +185,7 @@ A few default variables, which MUST take priority over the same names in ``data` * ``matrix_avatar_url`` - The current user's avatar URL as reported in their profile, or and empty string if not present. This shouldn't be the ``mxc://`` form of the user's avatar, but instead the full HTTP URL to the ``/media/download`` endpoint for their avatar from the Client-Server API. +* ``matrix_widget_id`` - The widget's ID to allow the widget to communicate effectively with the client. .. WARNING:: The ``matrix_user_id`` variable MUST NOT be assumed to be the current authenticated user due to From b910b8966524febe7ffe78f723127a5037defe64 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 22 Nov 2020 18:05:32 -0700 Subject: [PATCH 45/45] Apply suggestions from code review Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> --- api/widgets/definitions/shared_props.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/widgets/definitions/shared_props.yaml b/api/widgets/definitions/shared_props.yaml index 753789b9d64..41031343da8 100644 --- a/api/widgets/definitions/shared_props.yaml +++ b/api/widgets/definitions/shared_props.yaml @@ -50,7 +50,7 @@ properties: default: true description: |- When true, the widget should be hidden from view until the iframe's ``onLoad`` (or - platform equivilant) event has been fired. When false, the widget should be hidden + platform equivalent) event has been fired. When false, the widget should be hidden from view until the ``content_loaded`` API action is sent by the widget. Defaults to true. example: true