VirtualBox

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

Last change on this file since 91683 was 90238, checked in by vboxsync, 3 years ago

HGCM,HostServices: Extended VBOXHGCMSVCFNTABLE with client and call limits. Tried to pick reasonable values for all services. bugref:9379

  • 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.8 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-darwin.cpp 90238 2021-07-19 13:48:09Z 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(VBOXHGCMSVCFNTABLE *pTable)
122{
123 RT_NOREF(pTable);
124 g_ctx.fTerminate = false;
125
126 int rc = initPasteboard(&g_ctx.hPasteboard);
127 AssertRCReturn(rc, rc);
128
129 rc = RTThreadCreate(&g_ctx.hThread, vboxClipboardThread, &g_ctx, 0,
130 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
131 if (RT_FAILURE(rc))
132 {
133 g_ctx.hThread = NIL_RTTHREAD;
134 destroyPasteboard(&g_ctx.hPasteboard);
135 }
136
137 return rc;
138}
139
140void ShClBackendDestroy(void)
141{
142 /*
143 * Signal the termination of the polling thread and wait for it to respond.
144 */
145 ASMAtomicWriteBool(&g_ctx.fTerminate, true);
146 int rc = RTThreadUserSignal(g_ctx.hThread);
147 AssertRC(rc);
148 rc = RTThreadWait(g_ctx.hThread, RT_INDEFINITE_WAIT, NULL);
149 AssertRC(rc);
150
151 /*
152 * Destroy the hPasteboard and uninitialize the global context record.
153 */
154 destroyPasteboard(&g_ctx.hPasteboard);
155 g_ctx.hThread = NIL_RTTHREAD;
156 g_ctx.pClient = NULL;
157}
158
159int ShClBackendConnect(PSHCLCLIENT pClient, bool fHeadless)
160{
161 RT_NOREF(fHeadless);
162
163 if (g_ctx.pClient != NULL)
164 {
165 /* One client only. */
166 return VERR_NOT_SUPPORTED;
167 }
168
169 ShClSvcLock();
170
171 pClient->State.pCtx = &g_ctx;
172 pClient->State.pCtx->pClient = pClient;
173
174 ShClSvcUnlock();
175
176 return VINF_SUCCESS;
177}
178
179int ShClBackendSync(PSHCLCLIENT pClient)
180{
181 /* Sync the host clipboard content with the client. */
182 ShClSvcLock();
183
184 int rc = vboxClipboardChanged(pClient->State.pCtx);
185
186 ShClSvcUnlock();
187
188 return rc;
189}
190
191int ShClBackendDisconnect(PSHCLCLIENT pClient)
192{
193 ShClSvcLock();
194
195 pClient->State.pCtx->pClient = NULL;
196
197 ShClSvcUnlock();
198
199 return VINF_SUCCESS;
200}
201
202int ShClBackendFormatAnnounce(PSHCLCLIENT pClient, SHCLFORMATS fFormats)
203{
204 LogFlowFunc(("fFormats=%02X\n", fFormats));
205
206 /** @todo r=bird: BUGBUG: The following is probably a mistake. */
207 /** @todo r=andy: BUGBUG: Has been there since forever; needs investigation first before removing. */
208 if (fFormats == VBOX_SHCL_FMT_NONE)
209 {
210 /* This is just an automatism, not a genuine announcement */
211 return VINF_SUCCESS;
212 }
213
214#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
215 if (fFormats & VBOX_SHCL_FMT_URI_LIST) /* No transfer support yet. */
216 return VINF_SUCCESS;
217#endif
218
219 SHCLCONTEXT *pCtx = pClient->State.pCtx;
220 ShClSvcLock();
221
222 /*
223 * Generate a unique flavor string for this format announcement.
224 */
225 uint64_t idFlavor = RTRandU64();
226 pCtx->idGuestOwnership = idFlavor;
227 RTStrPrintf(pCtx->szGuestOwnershipFlavor, sizeof(pCtx->szGuestOwnershipFlavor),
228 "org.virtualbox.sharedclipboard.%RTproc.%RX64", RTProcSelf(), idFlavor);
229
230 /*
231 * Empty the pasteboard and put our ownership indicator flavor there
232 * with the stringified formats as value.
233 */
234 char szValue[32];
235 RTStrPrintf(szValue, sizeof(szValue), "%#x", fFormats);
236
237 takePasteboardOwnership(pCtx->hPasteboard, pCtx->idGuestOwnership, pCtx->szGuestOwnershipFlavor, szValue,
238 &pCtx->hStrOwnershipFlavor);
239
240 ShClSvcUnlock();
241
242 /*
243 * Now, request the data from the guest.
244 */
245 return ShClSvcGuestDataRequest(pClient, fFormats, NULL /* pidEvent */);
246}
247
248int ShClBackendReadData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT fFormat,
249 void *pvData, uint32_t cbData, uint32_t *pcbActual)
250{
251 AssertPtrReturn(pClient, VERR_INVALID_POINTER);
252 AssertPtrReturn(pCmdCtx, VERR_INVALID_POINTER);
253 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
254 AssertPtrReturn(pcbActual, VERR_INVALID_POINTER);
255
256 RT_NOREF(pCmdCtx);
257
258 ShClSvcLock();
259
260 /* Default to no data available. */
261 *pcbActual = 0;
262
263 int rc = readFromPasteboard(pClient->State.pCtx->hPasteboard, fFormat, pvData, cbData, pcbActual);
264 if (RT_FAILURE(rc))
265 LogRel(("Shared Clipboard: Error reading host clipboard data from macOS, rc=%Rrc\n", rc));
266
267 ShClSvcUnlock();
268
269 return rc;
270}
271
272int ShClBackendWriteData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT fFormat, void *pvData, uint32_t cbData)
273{
274 RT_NOREF(pCmdCtx);
275
276 LogFlowFuncEnter();
277
278 ShClSvcLock();
279
280 writeToPasteboard(pClient->State.pCtx->hPasteboard, pClient->State.pCtx->idGuestOwnership, pvData, cbData, fFormat);
281
282 ShClSvcUnlock();
283
284 LogFlowFuncLeaveRC(VINF_SUCCESS);
285 return VINF_SUCCESS;
286}
287
288#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
289
290int ShClBackendTransferReadDir(PSHCLCLIENT pClient, PSHCLDIRDATA pDirData)
291{
292 RT_NOREF(pClient, pDirData);
293 return VERR_NOT_IMPLEMENTED;
294}
295
296int ShClBackendTransferWriteDir(PSHCLCLIENT pClient, PSHCLDIRDATA pDirData)
297{
298 RT_NOREF(pClient, pDirData);
299 return VERR_NOT_IMPLEMENTED;
300}
301
302int ShClBackendTransferReadFileHdr(PSHCLCLIENT pClient, PSHCLFILEHDR pFileHdr)
303{
304 RT_NOREF(pClient, pFileHdr);
305 return VERR_NOT_IMPLEMENTED;
306}
307
308int ShClBackendTransferWriteFileHdr(PSHCLCLIENT pClient, PSHCLFILEHDR pFileHdr)
309{
310 RT_NOREF(pClient, pFileHdr);
311 return VERR_NOT_IMPLEMENTED;
312}
313
314int ShClBackendTransferReadFileData(PSHCLCLIENT pClient, PSHCLFILEDATA pFileData)
315{
316 RT_NOREF(pClient, pFileData);
317 return VERR_NOT_IMPLEMENTED;
318}
319
320int ShClBackendTransferWriteFileData(PSHCLCLIENT pClient, PSHCLFILEDATA pFileData)
321{
322 RT_NOREF(pClient, pFileData);
323 return VERR_NOT_IMPLEMENTED;
324}
325
326#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
327
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