VirtualBox

Changeset 69635 in vbox for trunk


Ignore:
Timestamp:
Nov 10, 2017 10:03:06 AM (7 years ago)
Author:
vboxsync
Message:

HostServices/SharedClipboard: allow hosts to request data in multiple formats.
bugref:9041: clipboard sharing on macOS host is brittle, Guest->Host direction

When a guest announces clipboard data available in multiple formats, the
Darwin host clipboard sends a request for data with all formats combined,
but the Additions can only service a request for a single format. This
change makes the service code split the combined request up into several
single format requests.

Location:
trunk/src/VBox/HostServices/SharedClipboard
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/service.cpp

    r69500 r69635  
    197197    else if (pClient->fMsgReadData)
    198198    {
     199        uint32_t fFormat;
     200
    199201        LogRelFlow(("vboxSvcClipboardReturnMsg: ReadData %02X\n", pClient->u32RequestedFormat));
     202        if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     203            fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
     204        else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     205            fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
     206        else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_HTML)
     207            fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
     208        else
     209            AssertStmt(pClient->u32RequestedFormat == 0, pClient->u32RequestedFormat = 0);
     210        pClient->u32RequestedFormat &= ~fFormat;
    200211        VBoxHGCMParmUInt32Set (&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
    201         VBoxHGCMParmUInt32Set (&paParms[1], pClient->u32RequestedFormat);
    202         pClient->fMsgReadData = false;
     212        VBoxHGCMParmUInt32Set (&paParms[1], fFormat);
     213        if (pClient->u32RequestedFormat == 0)
     214            pClient->fMsgReadData = false;
    203215    }
    204216    else if (pClient->fMsgFormats)
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp

    r69500 r69635  
    2626extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
    2727
     28static VBOXCLIPBOARDCLIENTDATA g_Client;
     29static VBOXHGCMSVCHELPERS g_Helpers = { NULL };
     30
     31/** Simple call handle structure for the guest call completion callback */
     32struct VBOXHGCMCALLHANDLE_TYPEDEF
     33{
     34    /** Where to store the result code */
     35    int32_t rc;
     36};
     37
     38/** Call completion callback for guest calls. */
     39static DECLCALLBACK(void) callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
     40{
     41    callHandle->rc = rc;
     42}
     43
    2844static int setupTable(VBOXHGCMSVCFNTABLE *pTable)
    2945{
    3046    pTable->cbSize = sizeof(*pTable);
    3147    pTable->u32Version = VBOX_HGCM_SVC_VERSION;
     48    g_Helpers.pfnCallComplete = callComplete;
     49    pTable->pHelpers = &g_Helpers;
    3250    return VBoxHGCMSvcLoad(pTable);
    3351}
     
    7593    RTTESTI_CHECK_MSG(u32Mode == VBOX_SHARED_CLIPBOARD_MODE_OFF,
    7694                      ("u32Mode=%u\n", (unsigned) u32Mode));
     95}
     96
     97static void testGetHostMsg(void)
     98{
     99    struct VBOXHGCMSVCPARM parms[2];
     100    VBOXHGCMSVCFNTABLE table;
     101    VBOXHGCMCALLHANDLE_TYPEDEF call;
     102    int rc;
     103
     104    RTTestISub("Setting up VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG test");
     105    rc = setupTable(&table);
     106    RTTESTI_CHECK_MSG_RETV(RT_SUCCESS(rc), ("rc=%Rrc\n", rc));
     107    /* Unless we are bidirectional the host message requests will be dropped. */
     108    parms[0].setUInt32(VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL);
     109    rc = table.pfnHostCall(NULL, VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE,
     110                           1, parms);
     111    RTTESTI_CHECK_RC_OK(rc);
     112
     113    RTTestISub("Testing VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, one format, waiting guest call.");
     114    RT_ZERO(g_Client);
     115    parms[0].setUInt32(0);
     116    parms[1].setUInt32(0);
     117    call.rc = VERR_TRY_AGAIN;
     118    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     119                  2, parms);
     120    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This should get updated only when the guest call completes. */
     121    vboxSvcClipboardReportMsg (&g_Client, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
     122                               VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
     123    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     124    RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
     125    RTTESTI_CHECK_RC_OK(call.rc);
     126    call.rc = VERR_TRY_AGAIN;
     127    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     128                  2, parms);
     129    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
     130
     131    RTTestISub("Testing VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, one format, no waiting guest calls.");
     132    RT_ZERO(g_Client);
     133    vboxSvcClipboardReportMsg (&g_Client, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
     134                               VBOX_SHARED_CLIPBOARD_FMT_HTML);
     135    parms[0].setUInt32(0);
     136    parms[1].setUInt32(0);
     137    call.rc = VERR_TRY_AGAIN;
     138    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     139                  2, parms);
     140    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     141    RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHARED_CLIPBOARD_FMT_HTML);
     142    RTTESTI_CHECK_RC_OK(call.rc);
     143    call.rc = VERR_TRY_AGAIN;
     144    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     145                  2, parms);
     146    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
     147
     148    RTTestISub("Testing VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, two formats, waiting guest call.");
     149    RT_ZERO(g_Client);
     150    parms[0].setUInt32(0);
     151    parms[1].setUInt32(0);
     152    call.rc = VERR_TRY_AGAIN;
     153    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     154                  2, parms);
     155    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This should get updated only when the guest call completes. */
     156    vboxSvcClipboardReportMsg (&g_Client, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
     157                               VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT | VBOX_SHARED_CLIPBOARD_FMT_HTML);
     158    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     159    RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
     160    RTTESTI_CHECK_RC_OK(call.rc);
     161    call.rc = VERR_TRY_AGAIN;
     162    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     163                  2, parms);
     164    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     165    RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHARED_CLIPBOARD_FMT_HTML);
     166    RTTESTI_CHECK_RC_OK(call.rc);
     167    call.rc = VERR_TRY_AGAIN;
     168    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     169                  2, parms);
     170    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
     171
     172    RTTestISub("Testing VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, two formats, no waiting guest calls.");
     173    RT_ZERO(g_Client);
     174    vboxSvcClipboardReportMsg (&g_Client, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
     175                               VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT | VBOX_SHARED_CLIPBOARD_FMT_HTML);
     176    parms[0].setUInt32(0);
     177    parms[1].setUInt32(0);
     178    call.rc = VERR_TRY_AGAIN;
     179    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     180                  2, parms);
     181    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     182    RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
     183    RTTESTI_CHECK_RC_OK(call.rc);
     184    call.rc = VERR_TRY_AGAIN;
     185    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     186                  2, parms);
     187    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     188    RTTESTI_CHECK(parms[1].u.uint32 == VBOX_SHARED_CLIPBOARD_FMT_HTML);
     189    RTTESTI_CHECK_RC_OK(call.rc);
     190    call.rc = VERR_TRY_AGAIN;
     191    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG,
     192                  2, parms);
     193    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
    77194}
    78195
     
    144261     */
    145262    testHostCall();
     263    testGetHostMsg();
    146264
    147265    /*
Note: See TracChangeset for help on using the changeset viewer.

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