// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_EXO_WAYLAND_CLIENT_TRACKER_H_
#define COMPONENTS_EXO_WAYLAND_CLIENT_TRACKER_H_
#include <memory>
#include <wayland-server-protocol-core.h>
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
struct wl_client;
struct wl_display;
namespace exo::wayland {
// Utility class to keep track of the lifetime of wl_client. This is necessary
// as resources owned by wl_client are freed in the process of destruction, and
// accessing client resources should not happen after this time (see
// crbug.com/1433187). All resources and associated user data are destroyed and
// freed before the wl_client is itself deleted.
class ClientTracker {
public:
explicit ClientTracker(wl_display* wl_display);
virtual ~ClientTracker();
// Returns true if `client` has begun destruction. Client resources should not
// be queried after this point.
bool IsClientDestroyed(wl_client* client) const;
int NumClientsTrackedForTesting() const;
private:
// Listener called when the wl_client has been successfully created for
// `wl_display_` and immediately when the clients begins destruction (before
// associated resources have been freed).
struct ClientListener {
ClientListener(ClientTracker* tracker, wl_notify_func_t notify);
wl_listener listener;
raw_ptr<ClientTracker> tracker;
};
// Called when a wl_client has successfully been created for `wl_display_`.
static void OnClientCreated(struct wl_listener* listener, void* data);
// Called when a wl_client associated with the listener begins destruction.
static void OnClientDestroyed(struct wl_listener* listener, void* data);
// Handles the `OnClientCreated()` event for clients associated with this
// tracker instance.
void HandleClientCreated(wl_client* client);
// Handles the `OnClientDestroyed()` event for clients associated with this
// tracker instance.
void HandleClientDestroyed(wl_client* client);
raw_ptr<wl_display> wl_display_;
ClientListener client_created_listener_;
// Presence in `client_destroyed_listeners_` indicates the client has been
// created and has yet to be destroyed.
base::flat_map<wl_client*, std::unique_ptr<ClientListener>>
client_destroyed_listeners_;
};
} // namespace exo::wayland
#endif // COMPONENTS_EXO_WAYLAND_CLIENT_TRACKER_H_