Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

inputcapture: add support for persist_mode and restore_token #1186

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion data/org.freedesktop.impl.portal.InputCapture.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#org.freedesktop.portal.InputCapture portal, see that portal's
documentation for details on methods, signals and arguments.

This documentation describes version 1 of this interface.
This documentation describes version 2 of this interface.
-->
<interface name="org.freedesktop.impl.portal.InputCapture">
<!--
Expand All @@ -50,6 +50,47 @@
SupportedCapabilities property. This value is required.
</para></listitem>
</varlistentry>
<varlistentry>
<term>restore_data (suv)</term>
<listitem><para>
The data to restore from a previous session.
</para>
<para>
If the stored session cannot be restored, this value is ignored
and the user will be prompted normally. This may happen when, for
example, the session contains a monitor or a window that is not
available anymore, or when the stored permissions are withdrawn.
</para>
<para>
The restore data is composed of the vendor name (e.g. "GNOME" or
"KDE"), the version of the implementation-specific private data,
and the implementation-specific private data itself.
</para>
<para>
This option was added in version 2 of this interface.
</para></listitem>
</varlistentry>
<varlistentry>
<term>persist_mode u</term>
<listitem><para>
How this session should persist. Default is 0. Accepted values are:
</para>
<para>
<simplelist>
<member>0: Do not persist (default)</member>
<member>1: Permissions persist as long as the application is running</member>
<member>2: Permissions persist until explicitly revoked</member>
</simplelist>
</para>
<para>
If the permission for the session to persist is granted, "restore_data"
will be returned via the #org.freedesktop.portal.Request::Response
signal.
</para>
<para>
This option was added in version 2 of this interface.
</para></listitem>
</varlistentry>
</variablelist>

The following results get returned in the @results vardict:
Expand All @@ -67,6 +108,12 @@
subset of the requested capabilities.
</para></listitem>
</varlistentry>
<varlistentry>
<term>restore_data (suv)</term>
<listitem><para>
The data to restore this session in a future session. See the persist_mode.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="CreateSession">
Expand Down
46 changes: 45 additions & 1 deletion data/org.freedesktop.portal.InputCapture.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
captured. The transport of actual input events is delegated to a
transport layer, specifically libei. See org.freedesktop.portal.InputCapture.ConnectToEIS().

This documentation describes version 1 of this interface.
This documentation describes version 2 of this interface.
-->
<interface name="org.freedesktop.portal.InputCapture">
<!--
Expand Down Expand Up @@ -90,6 +90,40 @@
SupportedCapabilities property. This value is required and must not be zero.
</para></listitem>
</varlistentry>
<varlistentry>
<term>restore_token s</term>
<listitem><para>
The token to restore a previous session.

If the stored session cannot be restored, this value is ignored
and the user will be prompted normally. This may happen when, for
example, the session contains a monitor or a window that is not
available anymore, or when the stored permissions are withdrawn.

The restore token is invalidated after using it once. To restore
the same session again, use the new restore token sent in response
to starting this session.

This option was added in version 2 of this interface.
</para></listitem>
</varlistentry>
<varlistentry>
<term>persist_mode u</term>
<listitem><para>
How this session should persist. Default is 0. Accepted values are:

<simplelist>
<member>0: Do not persist (default)</member>
<member>1: Permissions persist as long as the application is running</member>
<member>2: Permissions persist until explicitly revoked</member>
</simplelist>

If the permission for the session to persist is granted, a restore token will
be returned via the #org.freedesktop.portal.Request::Response signal.

This option was added in version 2 of this interface.
</para></listitem>
</varlistentry>
</variablelist>

The following results get returned via the #org.freedesktop.portal.Request::Response signal:
Expand Down Expand Up @@ -117,6 +151,16 @@
this application may not capture events of that capability.
</para></listitem>
</varlistentry>
<varlistentry>
<term>restore_token s</term>
<listitem><para>
The restore token. This token is a single use token that can later
be used to restore a session. See
org.freedesktop.portal.InputCapture.CreateSession() for details.

This response option was added in version 2 of this interface.
</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="CreateSession">
Expand Down
80 changes: 78 additions & 2 deletions src/input-capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@
#include "session.h"
#include "input-capture.h"
#include "request.h"
#include "restore-token.h"
#include "xdp-dbus.h"
#include "xdp-impl-dbus.h"
#include "xdp-utils.h"

#define VERSION_1 1 /* Makes grep easier */
#define VERSION_2 2

#define INPUT_CAPTURE_TABLE "input-capture"

typedef struct _InputCapture InputCapture;
typedef struct _InputCaptureClass InputCaptureClass;
Expand Down Expand Up @@ -71,6 +75,10 @@ typedef struct _InputCaptureSession
Session parent;

InputCaptureSessionState state;

char *restore_token;
PersistMode persist_mode;
GVariant *restore_data;
} InputCaptureSession;

typedef struct _InputCaptureSessionClass
Expand Down Expand Up @@ -119,6 +127,23 @@ input_capture_session_new (GVariant *options,
return (InputCaptureSession*)session;
}

static gboolean
process_results (Session *session,
GVariant **in_out_results,
GError **error)
{
InputCaptureSession *input_capture_session = (InputCaptureSession*)session;

xdp_session_persistence_replace_restore_data_with_token (session,
INPUT_CAPTURE_TABLE,
in_out_results,
&input_capture_session->persist_mode,
&input_capture_session->restore_token,
&input_capture_session->restore_data);

return TRUE;
}

static void
create_session_done (GObject *source_object,
GAsyncResult *res,
Expand All @@ -129,9 +154,10 @@ create_session_done (GObject *source_object,
GVariantBuilder results_builder;
GVariant *results;
Session *session;
gboolean should_close_session;
gboolean should_close_session = FALSE;
uint32_t capabilities = 0;
uint32_t response = 2;
const char *restore_token;

REQUEST_AUTOLOCK (request);

Expand All @@ -155,6 +181,16 @@ create_session_done (GObject *source_object,

if (request->exported && response == 0)
{
if (!process_results (session, &results, &error))
{
g_warning ("Could not start input-capture session: %s",
error->message);
g_clear_error (&error);
g_clear_pointer (&results, g_variant_unref);
response = 2;
goto out;
}

if (!session_export (session, &error))
{
g_warning ("Failed to export session: %s", error->message);
Expand All @@ -178,6 +214,10 @@ create_session_done (GObject *source_object,
"capabilities", g_variant_new_uint32 (capabilities));
g_variant_builder_add (&results_builder, "{sv}",
"session_handle", g_variant_new ("o", session->id));

if (g_variant_lookup (results, "restore_token", "s", &restore_token))
g_variant_builder_add (&results_builder, "{sv}",
"restore_token", g_variant_new_string (restore_token));
}
else
{
Expand Down Expand Up @@ -221,8 +261,33 @@ validate_capabilities (const char *key,

static XdpOptionKey input_capture_create_session_options[] = {
{ "capabilities", G_VARIANT_TYPE_UINT32, validate_capabilities },
{ "restore_token", G_VARIANT_TYPE_STRING, xdp_session_persistence_validate_restore_token },
{ "persist_mode", G_VARIANT_TYPE_UINT32, xdp_session_persistence_validate_persist_mode },
};

static gboolean
replace_input_capture_restore_token_with_data (Session *session,
GVariant **in_out_options,
GError **error)
{
InputCaptureSession *input_capture_session = (InputCaptureSession *) session;
g_autoptr(GVariant) options = NULL;
PersistMode persist_mode;

options = *in_out_options;

if (!g_variant_lookup (options, "persist_mode", "u", &persist_mode))
persist_mode = PERSIST_MODE_NONE;

input_capture_session->persist_mode = persist_mode;
xdp_session_persistence_replace_restore_token_with_data (session,
INPUT_CAPTURE_TABLE,
in_out_options,
&input_capture_session->restore_token);

return TRUE;
}

static gboolean
handle_create_session (XdpDbusInputCapture *object,
GDBusMethodInvocation *invocation,
Expand Down Expand Up @@ -269,8 +334,19 @@ handle_create_session (XdpDbusInputCapture *object,
g_dbus_method_invocation_return_gerror (invocation, error);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

options = g_variant_builder_end (&options_builder);

/* If 'restore_token' is passed, lookup the corresponding data in the
* permission store and / or the GHashTable with transient permissions.
* Portal implementations do not have access to the restore token.
*/
if (!replace_input_capture_restore_token_with_data (session, &options, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

g_object_set_qdata_full (G_OBJECT (request),
quark_request_session,
g_object_ref (session),
Expand Down Expand Up @@ -1118,7 +1194,7 @@ input_capture_init (InputCapture *input_capture)
{
unsigned int supported_capabilities;

xdp_dbus_input_capture_set_version (XDP_DBUS_INPUT_CAPTURE (input_capture), VERSION_1);
xdp_dbus_input_capture_set_version (XDP_DBUS_INPUT_CAPTURE (input_capture), VERSION_2);

supported_capabilities =
xdp_dbus_impl_input_capture_get_supported_capabilities (impl);
Expand Down
44 changes: 2 additions & 42 deletions src/remote-desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,50 +430,10 @@ validate_device_types (const char *key,
return TRUE;
}

static gboolean
validate_restore_token (const char *key,
GVariant *value,
GVariant *options,
GError **error)
{
const char *restore_token = g_variant_get_string (value, NULL);

if (!g_uuid_string_is_valid (restore_token))
{
g_set_error (error,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_INVALID_ARGUMENT,
"Restore token is not a valid UUID string");
return FALSE;
}

return TRUE;
}

static gboolean
validate_persist_mode (const char *key,
GVariant *value,
GVariant *options,
GError **error)
{
uint32_t mode = g_variant_get_uint32 (value);

if (mode > PERSIST_MODE_PERSISTENT)
{
g_set_error (error,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_INVALID_ARGUMENT,
"Invalid persist mode %x", mode);
return FALSE;
}

return TRUE;
}

static XdpOptionKey remote_desktop_select_devices_options[] = {
{ "types", G_VARIANT_TYPE_UINT32, validate_device_types },
{ "restore_token", G_VARIANT_TYPE_STRING, validate_restore_token },
{ "persist_mode", G_VARIANT_TYPE_UINT32, validate_persist_mode },
{ "restore_token", G_VARIANT_TYPE_STRING, xdp_session_persistence_validate_restore_token },
{ "persist_mode", G_VARIANT_TYPE_UINT32, xdp_session_persistence_validate_persist_mode },
};

static gboolean
Expand Down
Loading
Loading