Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: chrome/common/os_exchange_data.cc

Issue 115012: Move: drag_drop_types, favicon_size, icon_util, insets, path, message_box_fla... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/os_exchange_data.h ('k') | chrome/common/os_exchange_data_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <shlobj.h>
6
7 #include "chrome/common/os_exchange_data.h"
8
9 #include "app/l10n_util.h"
10 #include "base/clipboard_util.h"
11 #include "base/file_util.h"
12 #include "base/logging.h"
13 #include "base/pickle.h"
14 #include "base/scoped_handle.h"
15 #include "base/stl_util-inl.h"
16 #include "base/string_util.h"
17 #include "chrome/common/win_util.h"
18 #include "googleurl/src/gurl.h"
19 #include "grit/generated_resources.h"
20 #include "net/base/net_util.h"
21
22 // Creates a new STGMEDIUM object to hold the specified text. The caller
23 // owns the resulting object. The "Bytes" version does not NULL terminate, the
24 // string version does.
25 static STGMEDIUM* GetStorageForBytes(const char* data, size_t bytes);
26 static STGMEDIUM* GetStorageForWString(const std::wstring& data);
27 static STGMEDIUM* GetStorageForString(const std::string& data);
28 // Creates the contents of an Internet Shortcut file for the given URL.
29 static void GetInternetShortcutFileContents(const GURL& url, std::string* data);
30 // Creates a valid file name given a suggested title and URL.
31 static void CreateValidFileNameFromTitle(const GURL& url,
32 const std::wstring& title,
33 std::wstring* validated);
34 // Creates a File Descriptor for the creation of a file to the given URL and
35 // returns a handle to it.
36 static STGMEDIUM* GetStorageForFileDescriptor(
37 const std::wstring& valid_file_name);
38
39 ///////////////////////////////////////////////////////////////////////////////
40 // FormatEtcEnumerator
41
42 //
43 // This object implements an enumeration interface. The existence of an
44 // implementation of this interface is exposed to clients through
45 // OSExchangeData's EnumFormatEtc method. Our implementation is nobody's
46 // business but our own, so it lives in this file.
47 //
48 // This Windows API is truly a gem. It wants to be an enumerator but assumes
49 // some sort of sequential data (why not just use an array?). See comments
50 // throughout.
51 //
52 class FormatEtcEnumerator : public IEnumFORMATETC {
53 public:
54 FormatEtcEnumerator(OSExchangeData::StoredData::const_iterator begin,
55 OSExchangeData::StoredData::const_iterator end);
56 ~FormatEtcEnumerator();
57
58 // IEnumFORMATETC implementation:
59 HRESULT __stdcall Next(
60 ULONG count, FORMATETC* elements_array, ULONG* elements_fetched);
61 HRESULT __stdcall Skip(ULONG skip_count);
62 HRESULT __stdcall Reset();
63 HRESULT __stdcall Clone(IEnumFORMATETC** clone);
64
65 // IUnknown implementation:
66 HRESULT __stdcall QueryInterface(const IID& iid, void** object);
67 ULONG __stdcall AddRef();
68 ULONG __stdcall Release();
69
70 private:
71 // This can only be called from |CloneFromOther|, since it initializes the
72 // contents_ from the other enumerator's contents.
73 FormatEtcEnumerator() : ref_count_(0) {
74 }
75
76 // Clone a new FormatEtc from another instance of this enumeration.
77 static FormatEtcEnumerator* CloneFromOther(const FormatEtcEnumerator* other);
78
79 private:
80 // We are _forced_ to use a vector as our internal data model as Windows'
81 // retarded IEnumFORMATETC API assumes a deterministic ordering of elements
82 // through methods like Next and Skip. This exposes the underlying data
83 // structure to the user. Bah.
84 std::vector<FORMATETC*> contents_;
85
86 // The cursor of the active enumeration - an index into |contents_|.
87 int cursor_;
88
89 LONG ref_count_;
90
91 DISALLOW_EVIL_CONSTRUCTORS(FormatEtcEnumerator);
92 };
93
94 // Safely makes a copy of all of the relevant bits of a FORMATETC object.
95 static void CloneFormatEtc(FORMATETC* source, FORMATETC* clone) {
96 *clone = *source;
97 if (source->ptd) {
98 source->ptd =
99 static_cast<DVTARGETDEVICE*>(CoTaskMemAlloc(sizeof(DVTARGETDEVICE)));
100 *(clone->ptd) = *(source->ptd);
101 }
102 }
103
104 FormatEtcEnumerator::FormatEtcEnumerator(
105 OSExchangeData::StoredData::const_iterator start,
106 OSExchangeData::StoredData::const_iterator end)
107 : ref_count_(0), cursor_(0) {
108 // Copy FORMATETC data from our source into ourselves.
109 while (start != end) {
110 FORMATETC* format_etc = new FORMATETC;
111 CloneFormatEtc(&(*start)->format_etc, format_etc);
112 contents_.push_back(format_etc);
113 ++start;
114 }
115 }
116
117 FormatEtcEnumerator::~FormatEtcEnumerator() {
118 STLDeleteContainerPointers(contents_.begin(), contents_.end());
119 }
120
121 STDMETHODIMP FormatEtcEnumerator::Next(
122 ULONG count, FORMATETC* elements_array, ULONG* elements_fetched) {
123 // MSDN says |elements_fetched| is allowed to be NULL if count is 1.
124 if (!elements_fetched)
125 DCHECK(count == 1);
126
127 // This method copies count elements into |elements_array|.
128 int index = 0;
129 while (cursor_ < static_cast<int>(contents_.size()) &&
130 static_cast<ULONG>(index) < count) {
131 CloneFormatEtc(contents_.at(cursor_), &elements_array[index]);
132 ++cursor_;
133 ++index;
134 }
135 // The out param is for how many we actually copied.
136 if (elements_fetched)
137 *elements_fetched = index;
138
139 // If the two don't agree, then we fail.
140 return index == count ? S_OK : S_FALSE;
141 }
142
143 STDMETHODIMP FormatEtcEnumerator::Skip(ULONG skip_count) {
144 cursor_ += skip_count;
145 // MSDN implies it's OK to leave the enumerator trashed.
146 // "Whatever you say, boss"
147 return cursor_ <= static_cast<int>(contents_.size()) ? S_OK : S_FALSE;
148 }
149
150 STDMETHODIMP FormatEtcEnumerator::Reset() {
151 cursor_ = 0;
152 return S_OK;
153 }
154
155 STDMETHODIMP FormatEtcEnumerator::Clone(IEnumFORMATETC** clone) {
156 // Clone the current enumerator in its exact state, including cursor.
157 FormatEtcEnumerator* e = CloneFromOther(this);
158 e->AddRef();
159 *clone = e;
160 return S_OK;
161 }
162
163 STDMETHODIMP FormatEtcEnumerator::QueryInterface(const IID& iid,
164 void** object) {
165 *object = NULL;
166 if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IEnumFORMATETC)) {
167 *object = this;
168 } else {
169 return E_NOINTERFACE;
170 }
171 AddRef();
172 return S_OK;
173 }
174
175 ULONG FormatEtcEnumerator::AddRef() {
176 return InterlockedIncrement(&ref_count_);
177 }
178
179 ULONG FormatEtcEnumerator::Release() {
180 if (InterlockedDecrement(&ref_count_) == 0) {
181 ULONG copied_refcnt = ref_count_;
182 delete this;
183 return copied_refcnt;
184 }
185 return ref_count_;
186 }
187
188 // static
189 FormatEtcEnumerator* FormatEtcEnumerator::CloneFromOther(
190 const FormatEtcEnumerator* other) {
191 FormatEtcEnumerator* e = new FormatEtcEnumerator;
192 // Copy FORMATETC data from our source into ourselves.
193 std::vector<FORMATETC*>::const_iterator start = other->contents_.begin();
194 while (start != other->contents_.end()) {
195 FORMATETC* format_etc = new FORMATETC;
196 CloneFormatEtc(*start, format_etc);
197 e->contents_.push_back(format_etc);
198 ++start;
199 }
200 // Carry over
201 e->cursor_ = other->cursor_;
202 return e;
203 }
204
205 ///////////////////////////////////////////////////////////////////////////////
206 // OSExchangeData, public:
207
208 // static
209 bool OSExchangeData::HasPlainTextURL(IDataObject* source) {
210 std::wstring plain_text;
211 return (ClipboardUtil::GetPlainText(source, &plain_text) &&
212 !plain_text.empty() && GURL(plain_text).is_valid());
213 }
214
215 // static
216 bool OSExchangeData::GetPlainTextURL(IDataObject* source, GURL* url) {
217 std::wstring plain_text;
218 if (ClipboardUtil::GetPlainText(source, &plain_text) &&
219 !plain_text.empty()) {
220 GURL gurl(plain_text);
221 if (gurl.is_valid()) {
222 *url = gurl;
223 return true;
224 }
225 }
226 return false;
227 }
228
229 OSExchangeData::OSExchangeData()
230 : ref_count_(0) {
231 }
232
233 OSExchangeData::OSExchangeData(IDataObject* source)
234 : ref_count_(0) {
235 source_object_ = source;
236 }
237
238 OSExchangeData::~OSExchangeData() {
239 STLDeleteContainerPointers(contents_.begin(), contents_.end());
240 }
241
242 void OSExchangeData::SetString(const std::wstring& data) {
243 STGMEDIUM* storage = GetStorageForWString(data);
244 contents_.push_back(new StoredDataInfo(CF_UNICODETEXT, storage));
245
246 // Also add plain text.
247 storage = GetStorageForString(WideToUTF8(data));
248 contents_.push_back(new StoredDataInfo(CF_TEXT, storage));
249 }
250
251 void OSExchangeData::SetURL(const GURL& url, const std::wstring& title) {
252 // NOTE WELL:
253 // Every time you change the order of the first two CLIPFORMATS that get
254 // added here, you need to update the EnumerationViaCOM test case in
255 // the _unittest.cc file to reflect the new arrangement otherwise that test
256 // will fail! It assumes an insertion order.
257
258 // Add text/x-moz-url for drags from Firefox
259 std::wstring x_moz_url_str = UTF8ToWide(url.spec());
260 x_moz_url_str += '\n';
261 x_moz_url_str += title;
262 STGMEDIUM* storage = GetStorageForWString(x_moz_url_str);
263 contents_.push_back(new StoredDataInfo(
264 ClipboardUtil::GetMozUrlFormat()->cfFormat, storage));
265
266 // Add a .URL shortcut file for dragging to Explorer.
267 std::wstring valid_file_name;
268 CreateValidFileNameFromTitle(url, title, &valid_file_name);
269 std::string shortcut_url_file_contents;
270 GetInternetShortcutFileContents(url, &shortcut_url_file_contents);
271 SetFileContents(valid_file_name, shortcut_url_file_contents);
272
273 // Add a UniformResourceLocator link for apps like IE and Word.
274 storage = GetStorageForWString(UTF8ToWide(url.spec()));
275 contents_.push_back(new StoredDataInfo(
276 ClipboardUtil::GetUrlWFormat()->cfFormat, storage));
277 storage = GetStorageForString(url.spec());
278 contents_.push_back(new StoredDataInfo(
279 ClipboardUtil::GetUrlFormat()->cfFormat, storage));
280
281 // TODO(beng): (http://b/1085501) add CF_HTML...
282
283 // Also add text representations (these should be last since they're the
284 // least preferable).
285 storage = GetStorageForWString(UTF8ToWide(url.spec()));
286 contents_.push_back(new StoredDataInfo(CF_UNICODETEXT, storage));
287 storage = GetStorageForString(url.spec());
288 contents_.push_back(new StoredDataInfo(CF_TEXT, storage));
289 }
290
291 void OSExchangeData::SetFilename(const std::wstring& full_path) {
292 const size_t drop_size = sizeof(DROPFILES);
293 const size_t bytes = drop_size + (full_path.length() + 2) * sizeof(wchar_t);
294 HANDLE hdata = ::GlobalAlloc(GMEM_MOVEABLE, bytes);
295 if (!hdata)
296 return;
297
298 ScopedHGlobal<DROPFILES> locked_mem(hdata);
299 DROPFILES* drop_files = locked_mem.get();
300 drop_files->pFiles = sizeof(DROPFILES);
301 drop_files->fWide = TRUE;
302 wchar_t* data = reinterpret_cast<wchar_t*>((BYTE*)(drop_files) + drop_size);
303 const size_t copy_size = (full_path.length() + 1) * sizeof(wchar_t);
304 memcpy(data, full_path.c_str(), copy_size);
305 data[full_path.length() + 1] = L'\0'; // Double NULL
306
307 // Set up the STGMEDIUM
308 STGMEDIUM* storage = new STGMEDIUM;
309 storage->tymed = TYMED_HGLOBAL;
310 storage->hGlobal = drop_files;
311 storage->pUnkForRelease = NULL;
312
313 // Set up the StoredDataInfo
314 StoredDataInfo* info = new StoredDataInfo(CF_HDROP, storage);
315 contents_.push_back(info);
316 }
317
318 void OSExchangeData::SetPickledData(CLIPFORMAT format, const Pickle& data) {
319 STGMEDIUM* storage = GetStorageForString(
320 std::string(static_cast<const char *>(data.data()),
321 static_cast<size_t>(data.size())));
322 contents_.push_back(new StoredDataInfo(format, storage));
323 }
324
325 void OSExchangeData::SetFileContents(const std::wstring& filename,
326 const std::string& file_contents) {
327 // Add CFSTR_FILEDESCRIPTOR
328 STGMEDIUM* storage = GetStorageForFileDescriptor(filename);
329 contents_.push_back(new StoredDataInfo(
330 ClipboardUtil::GetFileDescriptorFormat()->cfFormat, storage));
331
332 // Add CFSTR_FILECONTENTS
333 storage = GetStorageForBytes(file_contents.data(), file_contents.length());
334 contents_.push_back(new StoredDataInfo(
335 ClipboardUtil::GetFileContentFormatZero()->cfFormat, storage));
336 }
337
338 void OSExchangeData::SetHtml(const std::wstring& html, const GURL& base_url) {
339 // Add both MS CF_HTML and text/html format. CF_HTML should be in utf-8.
340 std::string utf8_html = WideToUTF8(html);
341 std::string url = base_url.is_valid() ? base_url.spec() : std::string();
342
343 std::string cf_html = ClipboardUtil::HtmlToCFHtml(utf8_html, url);
344 STGMEDIUM* storage = GetStorageForBytes(cf_html.c_str(), cf_html.size());
345 contents_.push_back(new StoredDataInfo(
346 ClipboardUtil::GetHtmlFormat()->cfFormat, storage));
347
348 STGMEDIUM* storage_plain = GetStorageForBytes(utf8_html.c_str(),
349 utf8_html.size());
350 contents_.push_back(new StoredDataInfo(
351 ClipboardUtil::GetTextHtmlFormat()->cfFormat, storage_plain));
352 }
353
354 bool OSExchangeData::GetString(std::wstring* data) const {
355 return ClipboardUtil::GetPlainText(source_object_, data);
356 }
357
358 bool OSExchangeData::GetURLAndTitle(GURL* url, std::wstring* title) const {
359 std::wstring url_str;
360 bool success = ClipboardUtil::GetUrl(source_object_, &url_str, title);
361 if (success) {
362 GURL test_url(url_str);
363 if (test_url.is_valid()) {
364 *url = test_url;
365 return true;
366 }
367 } else if (GetPlainTextURL(source_object_, url)) {
368 title->clear();
369 return true;
370 }
371 return false;
372 }
373
374 bool OSExchangeData::GetFilename(std::wstring* full_path) const {
375 std::vector<std::wstring> filenames;
376 bool success = ClipboardUtil::GetFilenames(source_object_, &filenames);
377 if (success)
378 full_path->assign(filenames[0]);
379 return success;
380 }
381
382 bool OSExchangeData::GetPickledData(CLIPFORMAT format, Pickle* data) const {
383 DCHECK(data);
384 FORMATETC format_etc =
385 { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
386 bool success = false;
387 STGMEDIUM medium;
388 if (SUCCEEDED(source_object_->GetData(&format_etc, &medium))) {
389 if (medium.tymed & TYMED_HGLOBAL) {
390 ScopedHGlobal<char> c_data(medium.hGlobal);
391 DCHECK(c_data.Size() > 0);
392 // Need to subtract 1 as SetPickledData adds an extra byte to the end.
393 *data = Pickle(c_data.get(), static_cast<int>(c_data.Size() - 1));
394 success = true;
395 }
396 ReleaseStgMedium(&medium);
397 }
398 return success;
399 }
400
401 bool OSExchangeData::GetFileContents(std::wstring* filename,
402 std::string* file_contents) const {
403 return ClipboardUtil::GetFileContents(source_object_, filename,
404 file_contents);
405 }
406
407 bool OSExchangeData::GetHtml(std::wstring* html, GURL* base_url) const {
408 std::string url;
409 bool success = ClipboardUtil::GetHtml(source_object_, html, &url);
410 if (success)
411 *base_url = GURL(url);
412 return success;
413 }
414
415 bool OSExchangeData::HasString() const {
416 return ClipboardUtil::HasPlainText(source_object_);
417 }
418
419 bool OSExchangeData::HasURL() const {
420 return (ClipboardUtil::HasUrl(source_object_) ||
421 HasPlainTextURL(source_object_));
422 }
423
424 bool OSExchangeData::HasFile() const {
425 return ClipboardUtil::HasFilenames(source_object_);
426 }
427
428 bool OSExchangeData::HasFormat(CLIPFORMAT format) const {
429 FORMATETC format_etc =
430 { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
431 return (source_object_->QueryGetData(&format_etc) == S_OK);
432 }
433
434 ///////////////////////////////////////////////////////////////////////////////
435 // OSExchangeData, IDataObject implementation:
436
437 // The following function, DuplicateMedium, is derived from WCDataObject.cpp
438 // in the WebKit source code. This is the license information for the file:
439 /*
440 * Copyright (C) 2007 Apple Inc. All rights reserved.
441 *
442 * Redistribution and use in source and binary forms, with or without
443 * modification, are permitted provided that the following conditions
444 * are met:
445 * 1. Redistributions of source code must retain the above copyright
446 * notice, this list of conditions and the following disclaimer.
447 * 2. Redistributions in binary form must reproduce the above copyright
448 * notice, this list of conditions and the following disclaimer in the
449 * documentation and/or other materials provided with the distribution.
450 *
451 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
452 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
453 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
454 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
455 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
456 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
457 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
458 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
459 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
460 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
461 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
462 */
463 static void DuplicateMedium(CLIPFORMAT source_clipformat,
464 STGMEDIUM* source,
465 STGMEDIUM* destination) {
466 switch (source->tymed) {
467 case TYMED_HGLOBAL:
468 destination->hGlobal =
469 static_cast<HGLOBAL>(OleDuplicateData(
470 source->hGlobal, source_clipformat, 0));
471 break;
472 case TYMED_MFPICT:
473 destination->hMetaFilePict =
474 static_cast<HMETAFILEPICT>(OleDuplicateData(
475 source->hMetaFilePict, source_clipformat, 0));
476 break;
477 case TYMED_GDI:
478 destination->hBitmap =
479 static_cast<HBITMAP>(OleDuplicateData(
480 source->hBitmap, source_clipformat, 0));
481 break;
482 case TYMED_ENHMF:
483 destination->hEnhMetaFile =
484 static_cast<HENHMETAFILE>(OleDuplicateData(
485 source->hEnhMetaFile, source_clipformat, 0));
486 break;
487 case TYMED_FILE:
488 destination->lpszFileName =
489 static_cast<LPOLESTR>(OleDuplicateData(
490 source->lpszFileName, source_clipformat, 0));
491 break;
492 case TYMED_ISTREAM:
493 destination->pstm = source->pstm;
494 destination->pstm->AddRef();
495 break;
496 case TYMED_ISTORAGE:
497 destination->pstg = source->pstg;
498 destination->pstg->AddRef();
499 break;
500 }
501
502 destination->tymed = source->tymed;
503 destination->pUnkForRelease = source->pUnkForRelease;
504 if (destination->pUnkForRelease)
505 destination->pUnkForRelease->AddRef();
506 }
507
508 HRESULT OSExchangeData::GetData(FORMATETC* format_etc, STGMEDIUM* medium) {
509 StoredData::const_iterator iter = contents_.begin();
510 while (iter != contents_.end()) {
511 if ((*iter)->format_etc.cfFormat == format_etc->cfFormat) {
512 DuplicateMedium((*iter)->format_etc.cfFormat, (*iter)->medium, medium);
513 return S_OK;
514 }
515 ++iter;
516 }
517
518 return DV_E_FORMATETC;
519 }
520
521 HRESULT OSExchangeData::GetDataHere(FORMATETC* format_etc, STGMEDIUM* medium) {
522 return DATA_E_FORMATETC;
523 }
524
525 HRESULT OSExchangeData::QueryGetData(FORMATETC* format_etc) {
526 StoredData::const_iterator iter = contents_.begin();
527 while (iter != contents_.end()) {
528 if ((*iter)->format_etc.cfFormat == format_etc->cfFormat)
529 return S_OK;
530 ++iter;
531 }
532 return DV_E_FORMATETC;
533 }
534
535 HRESULT OSExchangeData::GetCanonicalFormatEtc(
536 FORMATETC* format_etc, FORMATETC* result) {
537 format_etc->ptd = NULL;
538 return E_NOTIMPL;
539 }
540
541 HRESULT OSExchangeData::SetData(
542 FORMATETC* format_etc, STGMEDIUM* medium, BOOL should_release) {
543 STGMEDIUM* local_medium = new STGMEDIUM;
544 if (should_release) {
545 *local_medium = *medium;
546 } else {
547 DuplicateMedium(format_etc->cfFormat, medium, local_medium);
548 }
549
550 StoredDataInfo* info =
551 new StoredDataInfo(format_etc->cfFormat, local_medium);
552 info->medium->tymed = format_etc->tymed;
553 info->owns_medium = !!should_release;
554 contents_.push_back(info);
555
556 return S_OK;
557 }
558
559 HRESULT OSExchangeData::EnumFormatEtc(
560 DWORD direction, IEnumFORMATETC** enumerator) {
561 if (direction == DATADIR_GET) {
562 FormatEtcEnumerator* e =
563 new FormatEtcEnumerator(contents_.begin(), contents_.end());
564 e->AddRef();
565 *enumerator = e;
566 return S_OK;
567 }
568 return E_NOTIMPL;
569 }
570
571 HRESULT OSExchangeData::DAdvise(
572 FORMATETC* format_etc, DWORD advf, IAdviseSink* sink, DWORD* connection) {
573 return OLE_E_ADVISENOTSUPPORTED;
574 }
575
576 HRESULT OSExchangeData::DUnadvise(DWORD connection) {
577 return OLE_E_ADVISENOTSUPPORTED;
578 }
579
580 HRESULT OSExchangeData::EnumDAdvise(IEnumSTATDATA** enumerator) {
581 return OLE_E_ADVISENOTSUPPORTED;
582 }
583
584 ///////////////////////////////////////////////////////////////////////////////
585 // OSExchangeData, IUnknown implementation:
586
587 HRESULT OSExchangeData::QueryInterface(const IID& iid, void** object) {
588 *object = NULL;
589 if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDataObject)) {
590 *object = this;
591 } else {
592 return E_NOINTERFACE;
593 }
594 AddRef();
595 return S_OK;
596 }
597
598 ULONG OSExchangeData::AddRef() {
599 return InterlockedIncrement(&ref_count_);
600 }
601
602 ULONG OSExchangeData::Release() {
603 if (InterlockedDecrement(&ref_count_) == 0) {
604 ULONG copied_refcnt = ref_count_;
605 delete this;
606 return copied_refcnt;
607 }
608 return ref_count_;
609 }
610
611 ///////////////////////////////////////////////////////////////////////////////
612 // OSExchangeData, private:
613
614 static STGMEDIUM* GetStorageForBytes(const char* data, size_t bytes) {
615 HANDLE handle = GlobalAlloc(GPTR, static_cast<int>(bytes));
616 ScopedHGlobal<char> scoped(handle);
617 size_t allocated = static_cast<size_t>(GlobalSize(handle));
618 memcpy(scoped.get(), data, allocated);
619
620 STGMEDIUM* storage = new STGMEDIUM;
621 storage->hGlobal = handle;
622 storage->tymed = TYMED_HGLOBAL;
623 storage->pUnkForRelease = NULL;
624 return storage;
625 }
626
627 template<class T>
628 static HGLOBAL CopyStringToGlobalHandle(const T& payload) {
629 int bytes = static_cast<int>(payload.size() + 1) * sizeof(T::value_type);
630 HANDLE handle = GlobalAlloc(GPTR, bytes);
631 void* data = GlobalLock(handle);
632 size_t allocated = static_cast<size_t>(GlobalSize(handle));
633 memcpy(data, payload.c_str(), allocated);
634 static_cast<T::value_type*>(data)[payload.size()] = '\0';
635 GlobalUnlock(handle);
636 return handle;
637 }
638
639 static STGMEDIUM* GetStorageForWString(const std::wstring& data) {
640 STGMEDIUM* storage = new STGMEDIUM;
641 storage->hGlobal = CopyStringToGlobalHandle<std::wstring>(data);
642 storage->tymed = TYMED_HGLOBAL;
643 storage->pUnkForRelease = NULL;
644 return storage;
645 }
646
647 static STGMEDIUM* GetStorageForString(const std::string& data) {
648 STGMEDIUM* storage = new STGMEDIUM;
649 storage->hGlobal = CopyStringToGlobalHandle<std::string>(data);
650 storage->tymed = TYMED_HGLOBAL;
651 storage->pUnkForRelease = NULL;
652 return storage;
653 }
654
655 static void GetInternetShortcutFileContents(const GURL& url,
656 std::string* data) {
657 DCHECK(data);
658 static const std::string kInternetShortcutFileStart =
659 "[InternetShortcut]\r\nURL=";
660 static const std::string kInternetShortcutFileEnd =
661 "\r\n";
662 *data = kInternetShortcutFileStart + url.spec() + kInternetShortcutFileEnd;
663 }
664
665 static void CreateValidFileNameFromTitle(const GURL& url,
666 const std::wstring& title,
667 std::wstring* validated) {
668 if (title.empty()) {
669 if (url.is_valid()) {
670 *validated = net::GetSuggestedFilename(
671 url, std::string(), std::string(), std::wstring());
672 } else {
673 // Nothing else can be done, just use a default.
674 *validated = l10n_util::GetString(IDS_UNTITLED_SHORTCUT_FILE_NAME);
675 }
676 } else {
677 *validated = title;
678 file_util::ReplaceIllegalCharacters(validated, '-');
679 }
680 static const wchar_t extension[] = L".url";
681 static const size_t max_length = MAX_PATH - arraysize(extension);
682 if (validated->size() > max_length)
683 validated->erase(max_length);
684 *validated += extension;
685 }
686
687 static STGMEDIUM* GetStorageForFileDescriptor(
688 const std::wstring& valid_file_name) {
689 DCHECK(!valid_file_name.empty() && valid_file_name.size() + 1 <= MAX_PATH);
690 HANDLE handle = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
691 FILEGROUPDESCRIPTOR* descriptor =
692 reinterpret_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(handle));
693
694 descriptor->cItems = 1;
695 wcscpy_s(descriptor->fgd[0].cFileName,
696 valid_file_name.size() + 1,
697 valid_file_name.c_str());
698 descriptor->fgd[0].dwFlags = FD_LINKUI;
699
700 GlobalUnlock(handle);
701
702 STGMEDIUM* storage = new STGMEDIUM;
703 storage->hGlobal = handle;
704 storage->tymed = TYMED_HGLOBAL;
705 storage->pUnkForRelease = NULL;
706 return storage;
707 }
OLDNEW
« no previous file with comments | « chrome/common/os_exchange_data.h ('k') | chrome/common/os_exchange_data_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698