[Spice-devel] [PATCH spice 09/17] Keep track of clipboard ownership
Arnon Gilboa
agilboa at redhat.com
Mon Oct 4 07:11:09 PDT 2010
Hans de Goede wrote:
> Given that all clipboard handling is async, it is possible to for
> example receive a request for clipboard data from the agent
> while the client no longer owns the clipboard (ie a
> VD_AGENT_CLIPBOARD_RELEASE message is in transit to the agent).
>
> Thus it is necessary to keep track of our notion of clipboard ownership
> and check received clipboard messages (both from other apps on the client
> machine and from the agent) to see if they match our notion and if not
> drop, or in case were a counter message is expected nack the clipboard
> message.
> ---
> client/platform.h | 9 +++++++++
> client/red_client.cpp | 37 +++++++++++++++++++++++++++++++++++++
> client/red_client.h | 1 +
> client/windows/platform.cpp | 13 +++++++++++++
> client/x11/platform.cpp | 13 +++++++++++++
> 5 files changed, 73 insertions(+), 0 deletions(-)
>
> diff --git a/client/platform.h b/client/platform.h
> index ff6f38d..af4a0f6 100644
> --- a/client/platform.h
> +++ b/client/platform.h
> @@ -125,6 +125,14 @@ public:
> static bool on_clipboard_notify(uint32_t type, const uint8_t* data, int32_t size);
> static bool on_clipboard_request(uint32_t type);
> static void on_clipboard_release();
> +
> + enum { owner_none, owner_guest, owner_client };
> +
> + static void set_clipboard_owner(int new_owner);
> + static int get_clipboard_owner() { return _clipboard_owner; }
> +
> +private:
> + static int _clipboard_owner;
> };
>
> class Platform::EventListener {
> @@ -141,6 +149,7 @@ public:
> virtual void on_clipboard_grab(uint32_t *types, uint32_t type_count) = 0;
> virtual void on_clipboard_request(uint32_t type) = 0;
> virtual void on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size) = 0;
> + virtual void on_clipboard_release() = 0;
> };
>
> class Platform::RecordClient {
> diff --git a/client/red_client.cpp b/client/red_client.cpp
> index 3f01fb1..a022499 100644
> --- a/client/red_client.cpp
> +++ b/client/red_client.cpp
> @@ -85,10 +85,17 @@ void ClipboardGrabEvent::response(AbstractProcessLoop& events_loop)
> {
> static_cast<RedClient*>(events_loop.get_owner())->send_agent_clipboard_message(
> VD_AGENT_CLIPBOARD_GRAB, _type_count * sizeof(uint32_t), _types);
> + Platform::set_clipboard_owner(Platform::owner_client);
> }
>
> void ClipboardRequestEvent::response(AbstractProcessLoop& events_loop)
> {
> + if (Platform::get_clipboard_owner() != Platform::owner_guest) {
> + LOG_WARN("received clipboard req from client while clipboard is not owned by guest");
> + Platform::on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0);
> + return;
> + }
> +
> VDAgentClipboardRequest request = {_type};
> static_cast<RedClient*>(events_loop.get_owner())->send_agent_clipboard_message(
> VD_AGENT_CLIPBOARD_REQUEST, sizeof(request), &request);
> @@ -865,6 +872,11 @@ void RedClient::on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size)
> DBG(0, "clipboard change is already pending");
> return;
> }
> + if (Platform::get_clipboard_owner() != Platform::owner_client) {
> + LOG_WARN("received clipboard data from client while clipboard is not owned by client");
> + type = VD_AGENT_CLIPBOARD_NONE;
> + size = 0;
> + }
> _agent_out_msg_pos = 0;
> _agent_out_msg_size = sizeof(VDAgentMessage) + sizeof(VDAgentClipboard) + size;
> _agent_out_msg = (VDAgentMessage*)new uint8_t[_agent_out_msg_size];
> @@ -880,6 +892,12 @@ void RedClient::on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size)
> }
> }
>
> +void RedClient::on_clipboard_release()
> +{
> + if (Platform::get_clipboard_owner() == Platform::owner_client)
> + send_agent_clipboard_message(VD_AGENT_CLIPBOARD_RELEASE, 0, NULL);
> +}
> +
> void RedClient::set_mouse_mode(uint32_t supported_modes, uint32_t current_mode)
> {
> if (current_mode != _mouse_mode) {
> @@ -1086,6 +1104,12 @@ void RedClient::dispatch_agent_message(VDAgentMessage* msg, void* data)
> break;
> }
> case VD_AGENT_CLIPBOARD: {
> + if (Platform::get_clipboard_owner() != Platform::owner_guest) {
> + LOG_WARN("received clipboard data from guest while clipboard is not owned by guest");
> + Platform::on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0);
> + break;
> + }
> +
> VDAgentClipboard* clipboard = (VDAgentClipboard*)data;
> Platform::on_clipboard_notify(clipboard->type, clipboard->data,
> msg->size - sizeof(VDAgentClipboard));
> @@ -1094,14 +1118,27 @@ void RedClient::dispatch_agent_message(VDAgentMessage* msg, void* data)
> case VD_AGENT_CLIPBOARD_GRAB:
> Platform::on_clipboard_grab((uint32_t *)data,
> msg->size / sizeof(uint32_t));
> + Platform::set_clipboard_owner(Platform::owner_guest);
> break;
> case VD_AGENT_CLIPBOARD_REQUEST:
> + if (Platform::get_clipboard_owner() != Platform::owner_client) {
> + LOG_WARN("received clipboard req from guest while clipboard is not owned by client");
> + on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0);
> + break;
> + }
> +
> if (!Platform::on_clipboard_request(((VDAgentClipboardRequest*)data)->type)) {
> on_clipboard_notify(VD_AGENT_CLIPBOARD_NONE, NULL, 0);
> }
> break;
> case VD_AGENT_CLIPBOARD_RELEASE:
> + if (Platform::get_clipboard_owner() != Platform::owner_guest) {
> + LOG_WARN("received clipboard release from guest while clipboard is not owned by guest");
> + break;
> + }
> +
> Platform::on_clipboard_release();
> + Platform::set_clipboard_owner(Platform::owner_none);
> break;
> default:
> DBG(0, "Unsupported message type %u size %u", msg->type, msg->size);
> diff --git a/client/red_client.h b/client/red_client.h
> index 2cfce49..15f0617 100644
> --- a/client/red_client.h
> +++ b/client/red_client.h
> @@ -221,6 +221,7 @@ public:
> void on_clipboard_grab(uint32_t *types, uint32_t type_count);
> void on_clipboard_request(uint32_t type);
> void on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size);
> + void on_clipboard_release();
>
> void for_each_channel(ForEachChannelFunc& func);
> void on_mouse_capture_trigger(RedScreen& screen);
> diff --git a/client/windows/platform.cpp b/client/windows/platform.cpp
> index db6d18a..db47079 100644
> --- a/client/windows/platform.cpp
> +++ b/client/windows/platform.cpp
> @@ -54,6 +54,7 @@ public:
> virtual void on_clipboard_grab(uint32_t *types, uint32_t type_count) {}
> virtual void on_clipboard_request(uint32_t type) {}
> virtual void on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size) {}
> + virtual void on_clipboard_release() {}
> };
>
> static DefaultClipboardListener default_clipboard_listener;
> @@ -856,6 +857,18 @@ void WinPlatform::exit_modal_loop()
> modal_loop_active = false;
> }
>
> +int Platform::_clipboard_owner = Platform::owner_none;
> +
> +void Platform::set_clipboard_owner(int new_owner)
> +{
> + if (new_owner == owner_none) {
> + clipboard_listener->on_clipboard_release();
> +
> + /* FIXME clear cached clipboard type info and data */
> + }
> + _clipboard_owner = new_owner;
> +}
> +
> bool Platform::on_clipboard_grab(uint32_t *types, uint32_t type_count)
> {
> /* FIXME use all types rather then just the first one */
> diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
> index b7216eb..832374a 100644
> --- a/client/x11/platform.cpp
> +++ b/client/x11/platform.cpp
> @@ -154,6 +154,7 @@ public:
> void on_clipboard_grab(uint32_t *types, uint32_t type_count) {}
> void on_clipboard_request(uint32_t type) {}
> void on_clipboard_notify(uint32_t type, uint8_t* data, int32_t size) {}
> + void on_clipboard_release() {}
> };
>
> static DefaultClipboardListener default_clipboard_listener;
> @@ -3161,6 +3162,18 @@ bool Platform::on_clipboard_grab(uint32_t *types, uint32_t type_count)
> return true;
> }
>
> +int Platform::_clipboard_owner = Platform::owner_none;
> +
> +void Platform::set_clipboard_owner(int new_owner)
> +{
> + if (new_owner == owner_none) {
> + clipboard_listener->on_clipboard_release();
> +
> + /* FIXME clear cached clipboard type info and data */
> + }
> + _clipboard_owner = new_owner;
> +}
> +
> void Platform::set_clipboard_listener(ClipboardListener* listener)
> {
> clipboard_listener = listener ? listener : &default_clipboard_listener;
>
Ack
More information about the Spice-devel
mailing list