[PATCH v5 1/3] wayland-server: Add API to control globals visibility

Yong Bakos junk at humanoriented.com
Tue Oct 18 15:54:36 UTC 2016


On Oct 18, 2016, at 7:23 AM, Olivier Fourdan <ofourdan at redhat.com> wrote:
> 
> Add a new API to let compositor decide whether or not a wl_global
> should be advertised to the clients via wl_registry_bind() or
> display_get_registry()
> 
> By using its own filter, the compositor can decide which wl_global would
> be listed to clients.
> 
> Compositors can use this mechanism to hide their own private interfaces
> that regular clients should not use.
> 
> - Hiding interfaces that expose compositor implementation details
>  makes it harder for clients to identify the compositor. Therefore
>  clients are a little less likely to develop compositor-specific
>  workarounds instead of reporting problems upstream.
> 
> - Hiding can be used to diminish the problems from missing namespacing:
>  if two compositors happen to use the same named global with
>  different interfaces for their special-purpose clients, the client
>  expecting the different interface would probably never see it
>  advertised.
> 
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
> Reviewed-by: Jonas Ã…dahl <jadahl at gmail.com>
> Reviewed-by: Yong Bakos <ybakos at humanoriented.com>
> Acked-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

This v remains

Reviewed-by: Yong Bakos <ybakos at humanoriented.com>

yong


> ---
> v2: Follow-up on Jonas' comments on v1:
>     Add global's data as user data in callback filter function
>     Pass wl_global instead of wl_interface in callback filter function
>     Add wl_global_get_interface() to retrieve the wl_interface from the
>     given wl_global
>     Post an error if a client tries to bind a global which is filtered
>     out.
> v3: Follow-up on Jonas' comments on v2:
>     Separate from the other wl_global and test additions
>     Add its own user data to the global filter
>     Rephrase the API doc
>     Other few small changes
> v4: Follow-up on Yong's comments on v3:
>     Rename wl_display_filter_global_func_t as wl_display_global_filter_func_t
>     Document wl_display_global_filter_func_t
>     Rename wl_display_set_filter_global as wl_display_set_global_filter
>     Rename filter_global() as wl_global_is_visible() and add a short
>     explanation in the code
> v5: Rebase against current git master, amend commit message as per
>     Pekka's comment and add Pekka's acked-by
> 
> src/wayland-server-core.h | 25 ++++++++++++++++++
> src/wayland-server.c      | 67 +++++++++++++++++++++++++++++++++++++++++++----
> 2 files changed, 87 insertions(+), 5 deletions(-)
> 
> diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
> index 2c215e4..9ae51dc 100644
> --- a/src/wayland-server-core.h
> +++ b/src/wayland-server-core.h
> @@ -28,6 +28,7 @@
> 
> #include <sys/types.h>
> #include <stdint.h>
> +#include <stdbool.h>
> #include "wayland-util.h"
> #include "wayland-version.h"
> 
> @@ -168,6 +169,30 @@ wl_global_create(struct wl_display *display,
> void
> wl_global_destroy(struct wl_global *global);
> 
> +/** A filter function for wl_global objects
> + *
> + * \param client The client object
> + * \param global The global object to show or hide
> + * \param data   The user data pointer
> + *
> + * A filter function enables the server to decide which globals to
> + * advertise to each client.
> + *
> + * When a wl_global filter is set, the given callback funtion will be
> + * called during wl_global advertisment and binding.
> + *
> + * This function should return true if the global object should be made
> + * visible to the client or false otherwise.
> + */
> +typedef bool (*wl_display_global_filter_func_t)(const struct wl_client *client,
> +						const struct wl_global *global,
> +						void *data);
> +
> +void
> +wl_display_set_global_filter(struct wl_display *display,
> +			     wl_display_global_filter_func_t filter,
> +			     void *data);
> +
> struct wl_client *
> wl_client_create(struct wl_display *display, int fd);
> 
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index 9d7d9c1..893bb56 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -101,6 +101,9 @@ struct wl_display {
> 	struct wl_signal create_client_signal;
> 
> 	struct wl_array additional_shm_formats;
> +
> +	wl_display_global_filter_func_t global_filter;
> +	void *global_filter_data;
> };
> 
> struct wl_global {
> @@ -769,6 +772,21 @@ wl_client_destroy(struct wl_client *client)
> 	free(client);
> }
> 
> +/* Check if a global filter is registered and use it if any.
> + *
> + * If no wl_global filter has been registered, this funtion will
> + * return true, allowing the wl_global to be visible to the wl_client
> + */
> +static bool
> +wl_global_is_visible(const struct wl_client *client,
> +	      const struct wl_global *global)
> +{
> +	struct wl_display *display = client->display;
> +
> +	return (display->global_filter == NULL ||
> +		display->global_filter(client, global, display->global_filter_data));
> +}
> +
> static void
> registry_bind(struct wl_client *client,
> 	      struct wl_resource *resource, uint32_t name,
> @@ -795,6 +813,10 @@ registry_bind(struct wl_client *client,
> 				       WL_DISPLAY_ERROR_INVALID_OBJECT,
> 				       "invalid version for global %s (%d): have %d, wanted %d",
> 				       interface, name, global->version, version);
> +	else if (!wl_global_is_visible(client, global))
> +		wl_resource_post_error(resource,
> +				       WL_DISPLAY_ERROR_INVALID_OBJECT,
> +				       "invalid global %s (%d)", interface, name);
> 	else
> 		global->bind(client, global->data, version, id);
> }
> @@ -850,11 +872,12 @@ display_get_registry(struct wl_client *client,
> 		       &registry_resource->link);
> 
> 	wl_list_for_each(global, &display->global_list, link)
> -		wl_resource_post_event(registry_resource,
> -				       WL_REGISTRY_GLOBAL,
> -				       global->name,
> -				       global->interface->name,
> -				       global->version);
> +		if (wl_global_is_visible(client, global))
> +			wl_resource_post_event(registry_resource,
> +					       WL_REGISTRY_GLOBAL,
> +					       global->name,
> +					       global->interface->name,
> +					       global->version);
> }
> 
> static const struct wl_display_interface display_interface = {
> @@ -925,6 +948,9 @@ wl_display_create(void)
> 	display->id = 1;
> 	display->serial = 0;
> 
> +	display->global_filter = NULL;
> +	display->global_filter_data = NULL;
> +
> 	wl_array_init(&display->additional_shm_formats);
> 
> 	return display;
> @@ -999,6 +1025,37 @@ wl_display_destroy(struct wl_display *display)
> 	free(display);
> }
> 
> +/** Set a filter function for global objects
> + *
> + * \param display The Wayland display object.
> + * \param filter  The global filter funtion.
> + * \param data User data to be associated with the global filter.
> + * \return None.
> + *
> + * Set a filter for the wl_display to advertise or hide global objects
> + * to clients.
> + * The set filter will be used during wl_global advertisment to
> + * determine whether a global object should be advertised to a
> + * given client, and during wl_global binding to determine whether
> + * a given client should be allowed to bind to a global.
> + *
> + * Clients that try to bind to a global that was filtered out will
> + * have an error raised.
> + *
> + * Setting the filter NULL will result in all globals being
> + * advertised to all clients. The default is no filter.
> + *
> + * \memberof wl_display
> + */
> +WL_EXPORT void
> +wl_display_set_global_filter(struct wl_display *display,
> +			     wl_display_global_filter_func_t filter,
> +			     void *data)
> +{
> +	display->global_filter = filter;
> +	display->global_filter_data = data;
> +}
> +
> WL_EXPORT struct wl_global *
> wl_global_create(struct wl_display *display,
> 		 const struct wl_interface *interface, int version,
> -- 
> 2.9.3
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/wayland-devel



More information about the wayland-devel mailing list