VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-darwin.cpp@ 85959

Last change on this file since 85959 was 85763, checked in by vboxsync, 4 years ago

Shared Clipboard: Some more assertions for ShClBackendReadData() implementations.

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-darwin.cpp 85763 2020-08-14 11:03:34Z vboxsync $ */
2/** @file
3 * Shared Clipboard Service - Mac OS X host.
4 */
5
6/*
7 * Copyright (C) 2008-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
23#include <VBox/HostServices/VBoxClipboardSvc.h>
24
25#include <iprt/assert.h>
26#include <iprt/asm.h>
27#include <iprt/process.h>
28#include <iprt/rand.h>
29#include <iprt/string.h>
30#include <iprt/thread.h>
31
32#include "VBoxSharedClipboardSvc-internal.h"
33#include "darwin-pasteboard.h"
34
35
36/*********************************************************************************************************************************
37* Structures and Typedefs *
38*********************************************************************************************************************************/
39/** Global clipboard context information */
40typedef struct SHCLCONTEXT
41{
42 /** We have a separate thread to poll for new clipboard content. */
43 RTTHREAD hThread;
44 /** Termination indicator. */
45 bool volatile fTerminate;
46 /** The reference to the current pasteboard */
47 PasteboardRef hPasteboard;
48 /** Shared clipboard client. */
49 PSHCLCLIENT pClient;
50 /** Random 64-bit number embedded into szGuestOwnershipFlavor. */
51 uint64_t idGuestOwnership;
52 /** Ownership flavor CFStringRef returned by takePasteboardOwnership().
53 * This is the same a szGuestOwnershipFlavor only in core foundation terms. */
54 void *hStrOwnershipFlavor;
55 /** The guest ownership flavor (type) string. */
56 char szGuestOwnershipFlavor[64];
57} SHCLCONTEXT;
58
59
60/*********************************************************************************************************************************
61* Global Variables *
62*********************************************************************************************************************************/
63/** Only one client is supported. There seems to be no need for more clients. */
64static SHCLCONTEXT g_ctx;
65
66
67/**
68 * Checks if something is present on the clipboard and calls shclSvcReportMsg.
69 *
70 * @returns IPRT status code (ignored).
71 * @param pCtx The context.
72 *
73 * @note Call must own lock.
74 */
75static int vboxClipboardChanged(SHCLCONTEXT *pCtx)
76{
77 if (pCtx->pClient == NULL)
78 return VINF_SUCCESS;
79
80 /* Retrieve the formats currently in the clipboard and supported by vbox */
81 uint32_t fFormats = 0;
82 bool fChanged = false;
83 int rc = queryNewPasteboardFormats(pCtx->hPasteboard, pCtx->idGuestOwnership, pCtx->hStrOwnershipFlavor,
84 &fFormats, &fChanged);
85 if ( RT_SUCCESS(rc)
86 && fChanged)
87 rc = ShClSvcHostReportFormats(pCtx->pClient, fFormats);
88
89 LogFlowFuncLeaveRC(rc);
90 return rc;
91}
92
93/**
94 * @callback_method_impl{FNRTTHREAD, The poller thread.
95 *
96 * This thread will check for the arrival of new data on the clipboard.}
97 */
98static DECLCALLBACK(int) vboxClipboardThread(RTTHREAD ThreadSelf, void *pvUser)
99{
100 SHCLCONTEXT *pCtx = (SHCLCONTEXT *)pvUser;
101 AssertPtr(pCtx);
102 LogFlowFuncEnter();
103
104 while (!pCtx->fTerminate)
105 {
106 /* call this behind the lock because we don't know if the api is
107 thread safe and in any case we're calling several methods. */
108 ShClSvcLock();
109 vboxClipboardChanged(pCtx);
110 ShClSvcUnlock();
111
112 /* Sleep for 200 msecs before next poll */
113 RTThreadUserWait(ThreadSelf, 200);
114 }
115
116 LogFlowFuncLeaveRC(VINF_SUCCESS);
117 return VINF_SUCCESS;
118}
119
120
121int ShClBackendInit(void)
122{
123 g_ctx.fTerminate = false;
124
125 int rc = initPasteboard(&g_ctx.hPasteboard);
126 AssertRCReturn(rc, rc);
127
128 rc = RTThreadCreate(&g_ctx.hThread, vboxClipboardThread, &g_ctx, 0,
129 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
130 if (RT_FAILURE(rc))
131 {
132 g_ctx.hThread = NIL_RTTHREAD;
133 destroyPasteboard(&g_ctx.hPasteboard);
134 }
135
136 return rc;
137}
138
139void ShClBackendDestroy(void)
140{
141 /*
142 * Signal the termination of the polling thread and wait for it to respond.
143 */
144 ASMAtomicWriteBool(&g_ctx.fTerminate, true);
145 int rc = RTThreadUserSignal(g_ctx.hThread);
146 AssertRC(rc);
147 rc = RTThreadWait(g_ctx.hThread, RT_INDEFINITE_WAIT, NULL);
148 AssertRC(rc);
149
150 /*
151 * Destroy the hPasteboard and uninitialize the global context record.
152 */
153 destroyPasteboard(&g_ctx.hPasteboard);
154 g_ctx.hThread = NIL_RTTHREAD;
155 g_ctx.pClient = NULL;
156}
157
158int ShClBackendConnect(PSHCLCLIENT pClient, bool fHeadless)
159{
160 RT_NOREF(fHeadless);
161
162 if (g_ctx.pClient != NULL)
163 {
164 /* One client only. */
165 return VERR_NOT_SUPPORTED;
166 }
167
168 ShClSvcLock();
169
170 pClient->State.pCtx = &g_ctx;
171 pClient->State.pCtx->pClient = pClient;
172
173 ShClSvcUnlock();
174
175 return VINF_SUCCESS;
176}
177
178int ShClBackendSync(PSHCLCLIENT pClient)
179{
180 /* Sync the host clipboard content with the client. */
181 ShClSvcLock();
182
183 int rc = vboxClipboardChanged(pClient->State.pCtx);
184
185 ShClSvcUnlock();
186
187 return rc;
188}
189
190int ShClBackendDisconnect(PSHCLCLIENT pClient)
191{
192 ShClSvcLock();
193
194 pClient->State.pCtx->pClient = NULL;
195
196 ShClSvcUnlock();
197
198 return VINF_SUCCESS;
199}
200
201int ShClBackendFormatAnnounce(PSHCLCLIENT pClient, SHCLFORMATS fFormats)
202{
203 LogFlowFunc(("fFormats=%02X\n", fFormats));
204
205 /** @todo r=bird: BUGBUG: The following is probably a mistake. */
206 if (fFormats == VBOX_SHCL_FMT_NONE)
207 {
208 /* This is just an automatism, not a genuine announcement */
209 return VINF_SUCCESS;
210 }
211
212#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
213 if (fFormats & VBOX_SHCL_FMT_URI_LIST) /* No transfer support yet. */
214 return VINF_SUCCESS;
215#endif
216
217 SHCLCONTEXT *pCtx = pClient->State.pCtx;
218 ShClSvcLock();
219
220 /*
221 * Generate a unique flavor string for this format announcement.
222 */
223 uint64_t idFlavor = RTRandU64();
224 pCtx->idGuestOwnership = idFlavor;
225 RTStrPrintf(pCtx->szGuestOwnershipFlavor, sizeof(pCtx->szGuestOwnershipFlavor),
226 "org.virtualbox.sharedclipboard.%RTproc.%RX64", RTProcSelf(), idFlavor);
227
228 /*
229 * Empty the pasteboard and put our ownership indicator flavor there
230 * with the stringified formats as value.
231 */
232 char szValue[32];
233 RTStrPrintf(szValue, sizeof(szValue), "%#x", fFormats);
234
235 takePasteboardOwnership(pCtx->hPasteboard, pCtx->idGuestOwnership, pCtx->szGuestOwnershipFlavor, szValue,
236 &pCtx->hStrOwnershipFlavor);
237
238 ShClSvcUnlock();
239
240 /*
241 * Now, request the data from the guest.
242 */
243 return ShClSvcDataReadRequest(pClient, fFormats, NULL /* pidEvent */);
244}
245
246int ShClBackendReadData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT fFormat,
247 void *pvData, uint32_t cbData, uint32_t *pcbActual)
248{
249 AssertPtrReturn(pClient, VERR_INVALID_POINTER);
250 AssertPtrReturn(pCmdCtx, VERR_INVALID_POINTER);
251 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
252 AssertPtrReturn(pcbActual, VERR_INVALID_POINTER);
253
254 RT_NOREF(pCmdCtx);
255
256 ShClSvcLock();
257
258 /* Default to no data available. */
259 *pcbActual = 0;
260
261 int rc = readFromPasteboard(pClient->State.pCtx->hPasteboard, fFormat, pvData, cbData, pcbActual);
262
263 ShClSvcUnlock();
264
265 return rc;
266}
267
268int ShClBackendWriteData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT fFormat, void *pvData, uint32_t cbData)
269{
270 RT_NOREF(pCmdCtx);
271
272 ShClSvcLock();
273
274 writeToPasteboard(pClient->State.pCtx->hPasteboard, pClient->State.pCtx->idGuestOwnership, pvData, cbData, fFormat);
275
276 ShClSvcUnlock();
277
278 return VINF_SUCCESS;
279}
280
281#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
282
283int ShClBackendTransferReadDir(PSHCLCLIENT pClient, PSHCLDIRDATA pDirData)
284{
285 RT_NOREF(pClient, pDirData);
286 return VERR_NOT_IMPLEMENTED;
287}
288
289int ShClBackendTransferWriteDir(PSHCLCLIENT pClient, PSHCLDIRDATA pDirData)
290{
291 RT_NOREF(pClient, pDirData);
292 return VERR_NOT_IMPLEMENTED;
293}
294
295int ShClBackendTransferReadFileHdr(PSHCLCLIENT pClient, PSHCLFILEHDR pFileHdr)
296{
297 RT_NOREF(pClient, pFileHdr);
298 return VERR_NOT_IMPLEMENTED;
299}
300
301int ShClBackendTransferWriteFileHdr(PSHCLCLIENT pClient, PSHCLFILEHDR pFileHdr)
302{
303 RT_NOREF(pClient, pFileHdr);
304 return VERR_NOT_IMPLEMENTED;
305}
306
307int ShClBackendTransferReadFileData(PSHCLCLIENT pClient, PSHCLFILEDATA pFileData)
308{
309 RT_NOREF(pClient, pFileData);
310 return VERR_NOT_IMPLEMENTED;
311}
312
313int ShClBackendTransferWriteFileData(PSHCLCLIENT pClient, PSHCLFILEDATA pFileData)
314{
315 RT_NOREF(pClient, pFileData);
316 return VERR_NOT_IMPLEMENTED;
317}
318
319#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
320
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette