On Oct 18, 2016, at 7:23 AM, Olivier Fourdan <ofour...@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 <ofour...@redhat.com> > Reviewed-by: Jonas Ã…dahl <jad...@gmail.com> > Reviewed-by: Yong Bakos <yba...@humanoriented.com> > Acked-by: Pekka Paalanen <pekka.paala...@collabora.co.uk>
This v remains Reviewed-by: Yong Bakos <yba...@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, > ®istry_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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel