VirtualBox

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

Last change on this file since 87466 was 86889, checked in by vboxsync, 4 years ago

Shared Clipboard: More (optional) release logging for error diagnosis.

  • 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 86889 2020-11-16 14:23:04Z 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 /** @todo r=andy: BUGBUG: Has been there since forever; needs investigation first before removing. */
207 if (fFormats == VBOX_SHCL_FMT_NONE)
208 {
209 /* This is just an automatism, not a genuine announcement */
210 return VINF_SUCCESS;
211 }
212
213#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
214 if (fFormats & VBOX_SHCL_FMT_URI_LIST) /* No transfer support yet. */
215 return VINF_SUCCESS;
216#endif
217
218 SHCLCONTEXT *pCtx = pClient->State.pCtx;
219 ShClSvcLock();
220
221 /*
222 * Generate a unique flavor string for this format announcement.
223 */
224 uint64_t idFlavor = RTRandU64();
225 pCtx->idGuestOwnership = idFlavor;
226 RTStrPrintf(pCtx->szGuestOwnershipFlavor, sizeof(pCtx->szGuestOwnershipFlavor),
227 "org.virtualbox.sharedclipboard.%RTproc.%RX64", RTProcSelf(), idFlavor);
228
229 /*
230 * Empty the pasteboard and put our ownership indicator flavor there
231 * with the stringified formats as value.
232 */
233 char szValue[32];
234 RTStrPrintf(szValue, sizeof(szValue), "%#x", fFormats);
235
236 takePasteboardOwnership(pCtx->hPasteboard, pCtx->idGuestOwnership, pCtx->szGuestOwnershipFlavor, szValue,
237 &pCtx->hStrOwnershipFlavor);
238
239 ShClSvcUnlock();
240
241 /*
242 * Now, request the data from the guest.
243 */
244 return ShClSvcGuestDataRequest(pClient, fFormats, NULL /* pidEvent */);
245}
246
247int ShClBackendReadData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT fFormat,
248 void *pvData, uint32_t cbData, uint32_t *pcbActual)
249{
250 AssertPtrReturn(pClient, VERR_INVALID_POINTER);
251 AssertPtrReturn(pCmdCtx, VERR_INVALID_POINTER);
252 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
253 AssertPtrReturn(pcbActual, VERR_INVALID_POINTER);
254
255 RT_NOREF(pCmdCtx);
256
257 ShClSvcLock();
258
259 /* Default to no data available. */
260 *pcbActual = 0;
261
262 int rc = readFromPasteboard(pClient->State.pCtx->hPasteboard, fFormat, pvData, cbData, pcbActual);
263 if (RT_FAILURE(rc))
264 LogRel(("Shared Clipboard: Error reading host clipboard data from macOS, rc=%Rrc\n", rc));
265
266 ShClSvcUnlock();
267
268 return rc;
269}
270
271int ShClBackendWriteData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT fFormat, void *pvData, uint32_t cbData)
272{
273 RT_NOREF(pCmdCtx);
274
275 LogFlowFuncEnter();
276
277 ShClSvcLock();
278
279 writeToPasteboard(pClient->State.pCtx->hPasteboard, pClient->State.pCtx->idGuestOwnership, pvData, cbData, fFormat);
280
281 ShClSvcUnlock();
282
283 LogFlowFuncLeaveRC(VINF_SUCCESS);
284 return VINF_SUCCESS;
285}
286
287#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
288
289int ShClBackendTransferReadDir(PSHCLCLIENT pClient, PSHCLDIRDATA pDirData)
290{
291 RT_NOREF(pClient, pDirData);
292 return VERR_NOT_IMPLEMENTED;
293}
294
295int ShClBackendTransferWriteDir(PSHCLCLIENT pClient, PSHCLDIRDATA pDirData)
296{
297 RT_NOREF(pClient, pDirData);
298 return VERR_NOT_IMPLEMENTED;
299}
300
301int ShClBackendTransferReadFileHdr(PSHCLCLIENT pClient, PSHCLFILEHDR pFileHdr)
302{
303 RT_NOREF(pClient, pFileHdr);
304 return VERR_NOT_IMPLEMENTED;
305}
306
307int ShClBackendTransferWriteFileHdr(PSHCLCLIENT pClient, PSHCLFILEHDR pFileHdr)
308{
309 RT_NOREF(pClient, pFileHdr);
310 return VERR_NOT_IMPLEMENTED;
311}
312
313int ShClBackendTransferReadFileData(PSHCLCLIENT pClient, PSHCLFILEDATA pFileData)
314{
315 RT_NOREF(pClient, pFileData);
316 return VERR_NOT_IMPLEMENTED;
317}
318
319int ShClBackendTransferWriteFileData(PSHCLCLIENT pClient, PSHCLFILEDATA pFileData)
320{
321 RT_NOREF(pClient, pFileData);
322 return VERR_NOT_IMPLEMENTED;
323}
324
325#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
326
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