~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/dndcp/dndGuest/guestDnDSrc.cc

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2010 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @guestDnDSrc.cc --
 
21
 *
 
22
 * Implementation of common layer GuestDnDSrc object for guest.
 
23
 */
 
24
 
 
25
#include "guestDnD.hh"
 
26
 
 
27
extern "C" {
 
28
   #include "dndClipboard.h"
 
29
   #include "util.h"
 
30
   #include "debug.h"
 
31
   #include "file.h"
 
32
   #include "cpNameUtil.h"
 
33
   #include "str.h"
 
34
}
 
35
 
 
36
 
 
37
/**
 
38
 * Constructor.
 
39
 *
 
40
 * @param[in] mgr guest DnD manager
 
41
 */
 
42
 
 
43
GuestDnDSrc::GuestDnDSrc(GuestDnDMgr *mgr)
 
44
 : mMgr(mgr)
 
45
{
 
46
   ASSERT(mMgr);
 
47
   mMgr->GetRpc()->srcDropChanged.connect(
 
48
      sigc::mem_fun(this, &GuestDnDSrc::OnRpcDrop));
 
49
   mMgr->GetRpc()->srcCancelChanged.connect(
 
50
      sigc::mem_fun(this, &GuestDnDSrc::OnRpcCancel));
 
51
   mMgr->GetRpc()->getFilesDoneChanged.connect(
 
52
      sigc::mem_fun(this, &GuestDnDSrc::OnRpcGetFilesDone));
 
53
 
 
54
   CPClipboard_Init(&mClipboard);
 
55
}
 
56
 
 
57
 
 
58
/**
 
59
 * Destructor.
 
60
 */
 
61
 
 
62
GuestDnDSrc::~GuestDnDSrc(void)
 
63
{
 
64
   ASSERT(mMgr);
 
65
   CPClipboard_Destroy(&mClipboard);
 
66
   /* Reset current session id after finished. */
 
67
   mMgr->SetSessionId(0);
 
68
}
 
69
 
 
70
 
 
71
/**
 
72
 * Rpc got dragBegin with valid data. Ask UI to show the detection window and
 
73
 * start host->guest DnD inside guest.
 
74
 *
 
75
 * @param[in] clip cross-platform clipboard data.
 
76
 */
 
77
 
 
78
void
 
79
GuestDnDSrc::OnRpcDragBegin(const CPClipboard *clip)
 
80
{
 
81
   ASSERT(mMgr);
 
82
   ASSERT(clip);
 
83
 
 
84
   Debug("%s: state is %d\n", __FUNCTION__, mMgr->GetState());
 
85
   /* Setup staging directory. */
 
86
   mStagingDir = SetupDestDir("");
 
87
   if (mStagingDir.empty()) {
 
88
      Debug("%s: SetupDestDir failed.\n", __FUNCTION__);
 
89
      return;
 
90
   }
 
91
 
 
92
   /* Show detection window in (0, 0). */
 
93
   mMgr->ShowDetWnd(0, 0);
 
94
 
 
95
   CPClipboard_Clear(&mClipboard);
 
96
   CPClipboard_Copy(&mClipboard, clip);
 
97
 
 
98
   mMgr->SetState(GUEST_DND_SRC_DRAGBEGIN_PENDING);
 
99
   Debug("%s: state changed to DRAGBEGIN_PENDING\n", __FUNCTION__);
 
100
 
 
101
   mMgr->srcDragBeginChanged.emit(&mClipboard, mStagingDir);
 
102
}
 
103
 
 
104
 
 
105
/**
 
106
 * Guest UI got dragBeginDone. Send dragBeginDone cmd to controller.
 
107
 */
 
108
 
 
109
void
 
110
GuestDnDSrc::UIDragBeginDone(void)
 
111
{
 
112
   ASSERT(mMgr);
 
113
 
 
114
   Debug("%s: state is %d\n", __FUNCTION__, mMgr->GetState());
 
115
   if (mMgr->GetState() != GUEST_DND_SRC_DRAGBEGIN_PENDING) {
 
116
      /* Reset DnD for any wrong state. */
 
117
      Debug("%s: Bad state: %d\n", __FUNCTION__, mMgr->GetState());
 
118
      goto error;
 
119
   }
 
120
 
 
121
   if (!mMgr->GetRpc()->SrcDragBeginDone(mMgr->GetSessionId())) {
 
122
      Debug("%s: SrcDragBeginDone failed\n", __FUNCTION__);
 
123
      goto error;
 
124
   }
 
125
 
 
126
   mMgr->SetState(GUEST_DND_SRC_DRAGGING);
 
127
   Debug("%s: state changed to DRAGGING\n", __FUNCTION__);
 
128
   return;
 
129
 
 
130
error:
 
131
   mMgr->ResetDnD();
 
132
}
 
133
 
 
134
 
 
135
/**
 
136
 * Guest UI got DnD feedback. Send updateFeedback cmd to controller.
 
137
 *
 
138
 * @param[in] feedback
 
139
 */
 
140
 
 
141
void
 
142
GuestDnDSrc::UIUpdateFeedback(DND_DROPEFFECT feedback)
 
143
{
 
144
   ASSERT(mMgr);
 
145
 
 
146
   Debug("%s: state is %d\n", __FUNCTION__, mMgr->GetState());
 
147
 
 
148
   /* This operation needs a valid session id from controller. */
 
149
   if (0 == mMgr->GetSessionId()) {
 
150
      Debug("%s: can not get a valid session id from controller.\n",
 
151
            __FUNCTION__);
 
152
      return;
 
153
   }
 
154
   if (!mMgr->GetRpc()->UpdateFeedback(mMgr->GetSessionId(), feedback)) {
 
155
      Debug("%s: UpdateFeedback failed\n", __FUNCTION__);
 
156
      mMgr->ResetDnD();
 
157
   }
 
158
}
 
159
 
 
160
 
 
161
/**
 
162
 * Got drop cmd from rpc. Ask UI to simulate the drop at (x, y).
 
163
 *
 
164
 * @param[in] sessionId active DnD session id
 
165
 * @param[in] x mouse position x.
 
166
 * @param[in] y mouse position y.
 
167
 */
 
168
 
 
169
void
 
170
GuestDnDSrc::OnRpcDrop(uint32 sessionId,
 
171
                       int32 x,
 
172
                       int32 y)
 
173
{
 
174
   char cpName[FILE_MAXPATH];
 
175
   int32 cpNameSize;
 
176
 
 
177
   ASSERT(mMgr);
 
178
 
 
179
   Debug("%s: state is %d\n", __FUNCTION__, mMgr->GetState());
 
180
   if (mMgr->GetState() != GUEST_DND_SRC_DRAGGING) {
 
181
      /* Reset DnD for any wrong state. */
 
182
      Debug("%s: Bad state: %d\n", __FUNCTION__, mMgr->GetState());
 
183
      goto error;
 
184
   }
 
185
   mMgr->srcDropChanged.emit();
 
186
 
 
187
   if (CPClipboard_ItemExists(&mClipboard, CPFORMAT_FILELIST)) {
 
188
      /* Convert staging name to CP format. */
 
189
      cpNameSize = CPNameUtil_ConvertToRoot(mStagingDir.c_str(),
 
190
                                            sizeof cpName,
 
191
                                            cpName);
 
192
      if (cpNameSize < 0) {
 
193
         Debug("%s: Error, could not convert to CPName.\n", __FUNCTION__);
 
194
         goto error;
 
195
      }
 
196
 
 
197
      if (!mMgr->GetRpc()->SrcDropDone(sessionId,
 
198
                                       (const uint8 *)cpName,
 
199
                                       cpNameSize)) {
 
200
         Debug("%s: SrcDropDone failed\n", __FUNCTION__);
 
201
         goto error;
 
202
      }
 
203
   } else {
 
204
      /* For non-file formats, the DnD is done. Hide detection window. */
 
205
      mMgr->HideDetWnd();
 
206
      mMgr->SetState(GUEST_DND_READY);
 
207
      Debug("%s: state changed to READY\n", __FUNCTION__);
 
208
   }
 
209
   return;
 
210
 
 
211
error:
 
212
   mMgr->ResetDnD();
 
213
}
 
214
 
 
215
 
 
216
/**
 
217
 * Got cancel cmd from rpc. Ask UI to cancel the DnD as source.
 
218
 *
 
219
 * @param[in] sessionId active DnD session id
 
220
 */
 
221
 
 
222
void
 
223
GuestDnDSrc::OnRpcCancel(uint32 sessionId)
 
224
{
 
225
   ASSERT(mMgr);
 
226
 
 
227
   Debug("%s: state is %d\n", __FUNCTION__, mMgr->GetState());
 
228
   mMgr->srcCancelChanged.emit();
 
229
   mMgr->DelayHideDetWnd();
 
230
   mMgr->SetState(GUEST_DND_READY);
 
231
   Debug("%s: state changed to READY\n", __FUNCTION__);
 
232
}
 
233
 
 
234
 
 
235
/**
 
236
 * Got getFileDone cmd from rpc. Reset state machine and hide detection window.
 
237
 *
 
238
 * @param[in] sessionId active DnD session id
 
239
 * @param[in] success if the file transfer is successful or not
 
240
 * @param[in] stagingCP staging dir name in cross-platform format
 
241
 * @param[in] sz the staging dir name size
 
242
 */
 
243
 
 
244
void
 
245
GuestDnDSrc::OnRpcGetFilesDone(uint32 sessionId,
 
246
                               bool success,
 
247
                               const uint8 *stagingDirCP,
 
248
                               uint32 sz)
 
249
{
 
250
   if (!success && !mStagingDir.empty()) {
 
251
      /* Delete all files if host canceled the file transfer. */
 
252
      DnD_DeleteStagingFiles(mStagingDir.c_str(), FALSE);
 
253
      mStagingDir.clear();
 
254
   }
 
255
   /* UI should remove block with this signal. */
 
256
   mMgr->getFilesDoneChanged.emit(success);
 
257
   mMgr->HideDetWnd();
 
258
   mMgr->SetState(GUEST_DND_READY);
 
259
   Debug("%s: state changed to READY\n", __FUNCTION__);
 
260
}
 
261
 
 
262
 
 
263
/**
 
264
 * Creates a directory for file transfer. If the destination dir is provided,
 
265
 * we will attempt to copy files to that directory.
 
266
 *
 
267
 * @param[in] destDir the preferred destination directory
 
268
 *
 
269
 * @return the destination directory on success, an empty string on failure.
 
270
 */
 
271
 
 
272
const std::string &
 
273
GuestDnDSrc::SetupDestDir(const std::string &destDir)
 
274
{
 
275
   mStagingDir = "";
 
276
 
 
277
   if (!destDir.empty() && File_Exists(destDir.c_str())) {
 
278
      mStagingDir = destDir;
 
279
      const char *lastSep = Str_Strrchr(mStagingDir.c_str(), DIRSEPC);
 
280
      if (lastSep && lastSep[1] != '\0') {
 
281
         mStagingDir += DIRSEPS;
 
282
      }
 
283
 
 
284
      return mStagingDir;
 
285
   } else {
 
286
      char *newDir;
 
287
 
 
288
      newDir = DnD_CreateStagingDirectory();
 
289
      if (newDir != NULL) {
 
290
         mStagingDir = newDir;
 
291
 
 
292
         char *lastSep = Str_Strrchr(newDir, DIRSEPC);
 
293
         if (lastSep && lastSep[1] != '\0') {
 
294
            mStagingDir += DIRSEPS;
 
295
         }
 
296
         free(newDir);
 
297
         Debug("%s: destdir: %s", __FUNCTION__, mStagingDir.c_str());
 
298
 
 
299
         return mStagingDir;
 
300
      } else {
 
301
         Debug("%s: destdir not created", __FUNCTION__);
 
302
         return mStagingDir;
 
303
      }
 
304
   }
 
305
}
 
306
 
 
307