VirtualBox

Changeset 59842 in vbox


Ignore:
Timestamp:
Feb 26, 2016 10:50:00 AM (9 years ago)
Author:
vboxsync
Message:

DnD/Main: Fixes for raw data transfers and cancellation logic.

Location:
trunk/src/VBox/Main/src-client
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp

    r58330 r59842  
    66
    77/*
    8  * Copyright (C) 2011-2015 Oracle Corporation
     8 * Copyright (C) 2011-2016 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    641641    for (size_t i = 0; i < lstFormatsWanted.size(); i++)
    642642    {
    643         /* Only keep allowed format types. */
     643        /* Only keep supported format types. */
    644644        if (std::find(lstFormatsSupported.begin(),
    645645                      lstFormatsSupported.end(), lstFormatsWanted.at(i)) != lstFormatsSupported.end())
     
    927927int GuestDnDBase::sendCancel(void)
    928928{
    929     int rc;
    930     try
    931     {
    932         GuestDnDMsg *pMsgCancel = new GuestDnDMsg();
    933         pMsgCancel->setType(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL);
    934 
    935         rc = msgQueueAdd(pMsgCancel);
    936     }
    937     catch(std::bad_alloc & /*e*/)
    938     {
    939         rc = VERR_NO_MEMORY;
    940     }
     929    int rc = GuestDnDInst()->hostCall(HOST_DND_HG_EVT_CANCEL,
     930                                      0 /* cParms */, NULL /* paParms */);
    941931
    942932    LogFlowFunc(("Generated cancelling request, rc=%Rrc\n", rc));
     
    975965
    976966    int rc;
     967
     968    LogFlowFunc(("msTimeout=%RU32\n", msTimeout));
    977969
    978970    uint64_t tsStart = RTTimeMilliTS();
  • trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp

    r58519 r59842  
    55
    66/*
    7  * Copyright (C) 2014-2015 Oracle Corporation
     7 * Copyright (C) 2014-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    257257
    258258    /* Default is ignoring the action. */
    259     DnDAction_T defaultAction = DnDAction_Ignore;
     259    if (aDefaultAction)
     260        *aDefaultAction = DnDAction_Ignore;
    260261
    261262    HRESULT hr = S_OK;
     
    275276        bool fFetchResult = true;
    276277
    277         rc = pResp->waitForGuestResponse(5000 /* Timeout in ms */);
     278        rc = pResp->waitForGuestResponse(100 /* Timeout in ms */);
    278279        if (RT_FAILURE(rc))
    279280            fFetchResult = false;
     
    286287        if (fFetchResult)
    287288        {
    288             defaultAction   = GuestDnD::toMainAction(pResp->defAction());
    289             aAllowedActions = GuestDnD::toMainActions(pResp->allActions());
    290 
    291289            /*
    292290             * In the GuestDnDSource case the source formats are from the guest,
     
    295293             * which are not supported by the host.
    296294             */
    297             aFormats        = GuestDnD::toFilteredFormatList(m_lstFmtSupported, pResp->formats());
    298 
    299             /* Save the (filtered) formats. */
    300             m_lstFmtOffered = aFormats;
    301 
    302             if (m_lstFmtOffered.size())
     295            GuestDnDMIMEList lstFiltered  = GuestDnD::toFilteredFormatList(m_lstFmtSupported, pResp->formats());
     296            if (lstFiltered.size())
    303297            {
    304                 LogRelMax(3, ("DnD: Offered formats:\n"));
    305                 for (size_t i = 0; i < m_lstFmtOffered.size(); i++)
    306                     LogRelMax(3, ("DnD:\tFormat #%zu: %s\n", i, m_lstFmtOffered.at(i).c_str()));
     298                LogRel3(("DnD: Host offered the following formats:\n"));
     299                for (size_t i = 0; i < lstFiltered.size(); i++)
     300                    LogRel3(("DnD:\tFormat #%zu: %s\n", i, lstFiltered.at(i).c_str()));
     301
     302                aFormats            = lstFiltered;
     303                aAllowedActions     = GuestDnD::toMainActions(pResp->allActions());
     304                if (aDefaultAction)
     305                    *aDefaultAction = GuestDnD::toMainAction(pResp->defAction());
     306
     307                /* Apply the (filtered) formats list. */
     308                m_lstFmtOffered     = lstFiltered;
    307309            }
    308310            else
    309                 LogRelMax(3, ("DnD: No compatible format between guest and host found, drag and drop to host not possible\n"));
    310         }
    311 
    312         LogFlowFunc(("fFetchResult=%RTbool, defaultAction=0x%x, allActions=0x%x\n",
    313                      fFetchResult, defaultAction, pResp->allActions()));
    314 
    315         if (aDefaultAction)
    316             *aDefaultAction = defaultAction;
     311                LogRel2(("DnD: Negotiation of formats between guest and host failed, drag and drop to host not possible\n"));
     312        }
     313
     314        LogFlowFunc(("fFetchResult=%RTbool, allActions=0x%x\n", fFetchResult, pResp->allActions()));
    317315    }
    318316
     
    330328    AutoCaller autoCaller(this);
    331329    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     330
     331    LogFunc(("aFormat=%s, aAction=%RU32\n", aFormat.c_str(), aAction));
    332332
    333333    /* Input validation. */
     
    379379        }
    380380
    381         //this function delete pTask in case of exceptions, so there is no need in the call of delete operator
     381        /* This function delete pTask in case of exceptions,
     382         * so there is no need in the call of delete operator. */
    382383        hr = pTask->createThread(&threadRcv);
    383384
     
    651652                    }
    652653                }
     654                else /* Raw data. */
     655                    rc = updateProgress(pData, pCtx->mpResp, cbData);
    653656            }
    654657        }
     
    790793            }
    791794        }
    792 
    793         /*
    794          * Create new intermediate object to work with.
    795          */
    796         rc = objCtx.createIntermediate();
     795        else
     796        {
     797            /*
     798             * Create new intermediate object to work with.
     799             */
     800            rc = objCtx.createIntermediate();
     801        }
     802
    797803        if (RT_SUCCESS(rc))
    798804        {
    799805            pObj = objCtx.getObj();
     806            AssertPtr(pObj);
    800807
    801808            const char *pszDroppedFilesDir = pCtx->mURI.getDroppedFiles().GetDirAbs();
     809            AssertPtr(pszDroppedFilesDir);
    802810
    803811            char pszPathAbs[RTPATH_MAX];
     
    963971     * Do we need to receive a different format than initially requested?
    964972     *
    965      * For example, receiving a file link as "text/plain"  requires still to receive
     973     * For example, receiving a file link as "text/plain" requires still to receive
    966974     * the file from the guest as "text/uri-list" first, then pointing to
    967975     * the file path on the host in the "text/plain" data returned.
    968976     */
    969977
    970     /* Plain text needed? */
    971     if (pCtx->mFmtReq.equalsIgnoreCase("text/plain"))
     978    bool fFoundFormat = true; /* Whether we've found a common format between host + guest. */
     979
     980    LogFlowFunc(("mFmtReq=%s, mFmtRecv=%s, mAction=0x%x\n",
     981                 pCtx->mFmtReq.c_str(), pCtx->mFmtRecv.c_str(), pCtx->mAction));
     982
     983    /* Plain text wanted? */
     984    if (   pCtx->mFmtReq.equalsIgnoreCase("text/plain")
     985        || pCtx->mFmtReq.equalsIgnoreCase("text/plain;charset=utf-8"))
    972986    {
    973987        /* Did the guest offer a file? Receive a file instead. */
    974988        if (GuestDnD::isFormatInFormatList("text/uri-list", pCtx->mFmtOffered))
    975989            pCtx->mFmtRecv = "text/uri-list";
     990        /* Guest only offers (plain) text. */
     991        else
     992            pCtx->mFmtRecv = "text/plain;charset=utf-8";
    976993
    977994        /** @todo Add more conversions here. */
    978995    }
    979 
    980     if (pCtx->mFmtRecv.isEmpty())
    981         pCtx->mFmtRecv = pCtx->mFmtReq;
    982 
    983     if (!pCtx->mFmtRecv.equals(pCtx->mFmtReq))
    984         LogRel3(("DnD: Requested data in format '%s', receiving in intermediate format '%s' now\n",
    985                  pCtx->mFmtReq.c_str(), pCtx->mFmtRecv.c_str()));
    986 
    987     /*
    988      * Call the appropriate receive handler based on the data format to handle.
    989      */
    990     bool fHasURIList = DnDMIMENeedsDropDir(pCtx->mFmtRecv.c_str(), pCtx->mFmtRecv.length());
    991     LogFlowFunc(("strFormatReq=%s, strFormatRecv=%s, uAction=0x%x, fHasURIList=%RTbool\n",
    992                  pCtx->mFmtReq.c_str(), pCtx->mFmtRecv.c_str(), pCtx->mAction, fHasURIList));
    993 
    994     if (fHasURIList)
    995     {
    996         rc = i_receiveURIData(pCtx, msTimeout);
    997     }
    998     else
    999     {
    1000         rc = i_receiveRawData(pCtx, msTimeout);
     996    /* File(s) wanted? */
     997    else if (pCtx->mFmtReq.equalsIgnoreCase("text/uri-list"))
     998    {
     999        /* Does the guest support sending files? */
     1000        if (GuestDnD::isFormatInFormatList("text/uri-list", pCtx->mFmtOffered))
     1001            pCtx->mFmtRecv = "text/uri-list";
     1002        else /* Bail out. */
     1003            fFoundFormat = false;
     1004    }
     1005
     1006    if (fFoundFormat)
     1007    {
     1008        Assert(!pCtx->mFmtReq.isEmpty());
     1009        Assert(!pCtx->mFmtRecv.isEmpty());
     1010
     1011        if (!pCtx->mFmtRecv.equals(pCtx->mFmtReq))
     1012            LogRel3(("DnD: Requested data in format '%s', receiving in intermediate format '%s' now\n",
     1013                     pCtx->mFmtReq.c_str(), pCtx->mFmtRecv.c_str()));
     1014
     1015        /*
     1016         * Call the appropriate receive handler based on the data format to handle.
     1017         */
     1018        bool fURIData = DnDMIMENeedsDropDir(pCtx->mFmtRecv.c_str(), pCtx->mFmtRecv.length());
     1019        if (fURIData)
     1020        {
     1021            rc = i_receiveURIData(pCtx, msTimeout);
     1022        }
     1023        else
     1024        {
     1025            rc = i_receiveRawData(pCtx, msTimeout);
     1026        }
     1027    }
     1028    else /* Just inform the user (if verbose release logging is enabled). */
     1029    {
     1030        LogRel2(("DnD: The guest does not support format '%s':\n", pCtx->mFmtReq.c_str()));
     1031        LogRel2(("DnD: Guest offered the following formats:\n"));
     1032        for (size_t i = 0; i < pCtx->mFmtOffered.size(); i++)
     1033            LogRel2(("DnD:\tFormat #%zu: %s\n", i, pCtx->mFmtOffered.at(i).c_str()));
    10011034    }
    10021035
     
    10401073
    10411074    int rc;
     1075
     1076    LogFlowFuncEnter();
    10421077
    10431078    GuestDnDResponse *pResp = pCtx->mpResp;
     
    10531088        return rc;
    10541089
    1055 #define UNREGISTER_CALLBACK(x) \
    1056     rc = pCtx->mpResp->setCallback(x, NULL); \
    1057     AssertRC(rc);
     1090#define UNREGISTER_CALLBACK(x)                                  \
     1091    {                                                           \
     1092        int rc2 = pResp->setCallback(x, NULL);                  \
     1093        AssertRC(rc2);                                          \
     1094    }
    10581095
    10591096    /*
     
    10631100    REGISTER_CALLBACK(GUEST_DND_DISCONNECT);
    10641101    REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR);
     1102    if (mDataBase.m_uProtocolVersion >= 3)
     1103        REGISTER_CALLBACK(GUEST_DND_GH_SND_DATA_HDR);
    10651104    REGISTER_CALLBACK(GUEST_DND_GH_SND_DATA);
    10661105
     
    10961135    UNREGISTER_CALLBACK(GUEST_DND_DISCONNECT);
    10971136    UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR);
     1137    if (mDataBase.m_uProtocolVersion >= 3)
     1138        UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA_HDR);
    10981139    UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA);
    10991140
     
    11051146        if (rc == VERR_CANCELLED)
    11061147        {
    1107             int rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS);
     1148            int rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED);
    11081149            AssertRC(rc2);
    11091150
     
    11271168
    11281169    int rc;
     1170
     1171    LogFlowFuncEnter();
    11291172
    11301173    GuestDnDResponse *pResp = pCtx->mpResp;
     
    12201263        if (rc == VERR_CANCELLED)
    12211264        {
    1222             rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS);
     1265            rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED);
    12231266            AssertRC(rc2);
    12241267
     
    12601303
    12611304    int rcCallback = VINF_SUCCESS; /* rc for the callback. */
    1262     bool fNotify = false;
     1305    bool fNotify   = false;
    12631306
    12641307    switch (uMsg)
     
    13031346
    13041347            if (RT_SUCCESS(pCBData->rc))
     1348            {
     1349                AssertMsgFailed(("Received guest error with no error code set\n"));
    13051350                pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */
    1306 
    1307             rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc,
    1308                                            GuestDnDSource::i_guestErrorToString(pCBData->rc));
     1351            }
     1352            else if (pCBData->rc == VERR_WRONG_ORDER)
     1353            {
     1354                rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED);
     1355            }
     1356            else
     1357                rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc,
     1358                                               GuestDnDSource::i_guestErrorToString(pCBData->rc));
     1359
     1360            LogRel3(("DnD: Guest reported data transfer error: %Rrc\n", pCBData->rc));
     1361
    13091362            if (RT_SUCCESS(rc))
    13101363                rcCallback = VERR_GSTDND_GUEST_ERROR;
     
    13171370    }
    13181371
     1372    if (   RT_FAILURE(rc)
     1373        || RT_FAILURE(rcCallback))
     1374    {
     1375        fNotify = true;
     1376        if (RT_SUCCESS(rcCallback))
     1377            rcCallback = rc;
     1378    }
     1379
    13191380    if (RT_FAILURE(rc))
    13201381    {
    1321         int rc2 = pCtx->mCBEvent.Notify(rc);
     1382        switch (rc)
     1383        {
     1384            case VERR_NO_DATA:
     1385                LogRel2(("DnD: Data transfer to host complete\n"));
     1386                break;
     1387
     1388            case VERR_CANCELLED:
     1389                LogRel2(("DnD: Data transfer to host canceled\n"));
     1390                break;
     1391
     1392            default:
     1393                LogRel(("DnD: Error %Rrc occurred, aborting data transfer to host\n", rc));
     1394                break;
     1395        }
     1396
     1397        /* Unregister this callback. */
     1398        AssertPtr(pCtx->mpResp);
     1399        int rc2 = pCtx->mpResp->setCallback(uMsg, NULL /* PFNGUESTDNDCALLBACK */);
     1400        AssertRC(rc2);
     1401    }
     1402
     1403    /* All data processed? */
     1404    if (pCtx->mData.isComplete())
     1405        fNotify = true;
     1406
     1407    LogFlowFunc(("cbProcessed=%RU64, cbToProcess=%RU64, fNotify=%RTbool, rcCallback=%Rrc, rc=%Rrc\n",
     1408                 pCtx->mData.getProcessed(), pCtx->mData.getTotal(), fNotify, rcCallback, rc));
     1409
     1410    if (fNotify)
     1411    {
     1412        int rc2 = pCtx->mCBEvent.Notify(rcCallback);
    13221413        AssertRC(rc2);
    13231414    }
     
    14301521
    14311522            if (RT_SUCCESS(pCBData->rc))
     1523            {
     1524                AssertMsgFailed(("Received guest error with no error code set\n"));
    14321525                pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */
    1433 
    1434             rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc,
    1435                                            GuestDnDSource::i_guestErrorToString(pCBData->rc));
     1526            }
     1527            else if (pCBData->rc == VERR_WRONG_ORDER)
     1528            {
     1529                rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED);
     1530            }
     1531            else
     1532                rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc,
     1533                                               GuestDnDSource::i_guestErrorToString(pCBData->rc));
     1534
     1535            LogRel3(("DnD: Guest reported file transfer error: %Rrc\n", pCBData->rc));
     1536
    14361537            if (RT_SUCCESS(rc))
    14371538                rcCallback = VERR_GSTDND_GUEST_ERROR;
     
    14571558        {
    14581559            case VERR_NO_DATA:
    1459                 LogRel2(("DnD: Transfer to host complete\n"));
     1560                LogRel2(("DnD: File transfer to host complete\n"));
    14601561                break;
    14611562
    14621563            case VERR_CANCELLED:
    1463                 LogRel2(("DnD: Transfer to host canceled\n"));
     1564                LogRel2(("DnD: File transfer to host canceled\n"));
    14641565                break;
    14651566
    14661567            default:
    1467                 LogRel(("DnD: Error %Rrc occurred, aborting transfer to host\n", rc));
     1568                LogRel(("DnD: Error %Rrc occurred, aborting file transfer to host\n", rc));
    14681569                break;
    14691570        }
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