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

Side by Side Diff: Source/WebCore/platform/win/ClipboardWin.cpp

Issue 13642009: WebCore: Remove PLATFORM(WIN) files we do not use. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 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
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "ClipboardWin.h"
28
29 #include "CachedImage.h"
30 #include "ClipboardUtilitiesWin.h"
31 #include "Document.h"
32 #include "DragData.h"
33 #include "Editor.h"
34 #include "Element.h"
35 #include "EventHandler.h"
36 #include "FileList.h"
37 #include "Frame.h"
38 #include "FrameLoader.h"
39 #include "FrameView.h"
40 #include "HTMLNames.h"
41 #include "HTMLParserIdioms.h"
42 #include "Image.h"
43 #include "MIMETypeRegistry.h"
44 #include "NotImplemented.h"
45 #include "Page.h"
46 #include "Pasteboard.h"
47 #include "PlatformMouseEvent.h"
48 #include "Range.h"
49 #include "RenderImage.h"
50 #include "ResourceResponse.h"
51 #include "SharedBuffer.h"
52 #include "WCDataObject.h"
53 #include "markup.h"
54 #include <shlwapi.h>
55 #include <wininet.h>
56 #include <wtf/RefPtr.h>
57 #include <wtf/text/CString.h>
58 #include <wtf/text/WTFString.h>
59 #include <wtf/text/StringHash.h>
60
61 using namespace std;
62
63 namespace WebCore {
64
65 using namespace HTMLNames;
66
67 // We provide the IE clipboard types (URL and Text), and the clipboard types spe cified in the WHATWG Web Applications 1.0 draft
68 // see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
69
70 enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardD ataTypeText, ClipboardDataTypeTextHTML };
71
72 static ClipboardDataType clipboardTypeFromMIMEType(const String& type)
73 {
74 String qType = type.stripWhiteSpace().lower();
75
76 // two special cases for IE compatibility
77 if (qType == "text" || qType == "text/plain" || qType.startsWith("text/plain ;"))
78 return ClipboardDataTypeText;
79 if (qType == "url" || qType == "text/uri-list")
80 return ClipboardDataTypeURL;
81 if (qType == "text/html")
82 return ClipboardDataTypeTextHTML;
83
84 return ClipboardDataTypeNone;
85 }
86
87 #if !OS(WINCE)
88 static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length)
89 {
90 size_t writeTo = 0;
91 size_t readFrom = 0;
92 while (readFrom < length) {
93 UINT type = PathGetCharType(psz[readFrom]);
94 if (!psz[readFrom] || type & (GCT_LFNCHAR | GCT_SHORTCHAR))
95 psz[writeTo++] = psz[readFrom];
96
97 readFrom++;
98 }
99 psz[writeTo] = 0;
100 }
101 #endif
102
103 static String filesystemPathFromUrlOrTitle(const String& url, const String& titl e, const UChar* extension, bool isLink)
104 {
105 #if OS(WINCE)
106 notImplemented();
107 return String();
108 #else
109 static const size_t fsPathMaxLengthExcludingNullTerminator = MAX_PATH - 1;
110 bool usedURL = false;
111 WCHAR fsPathBuffer[MAX_PATH];
112 fsPathBuffer[0] = 0;
113 int extensionLen = extension ? lstrlen(extension) : 0;
114 int fsPathMaxLengthExcludingExtension = fsPathMaxLengthExcludingNullTerminat or - extensionLen;
115
116 if (!title.isEmpty()) {
117 size_t len = min<size_t>(title.length(), fsPathMaxLengthExcludingExtensi on);
118 CopyMemory(fsPathBuffer, title.characters(), len * sizeof(UChar));
119 fsPathBuffer[len] = 0;
120 pathRemoveBadFSCharacters(fsPathBuffer, len);
121 }
122
123 if (!lstrlen(fsPathBuffer)) {
124 KURL kurl(ParsedURLString, url);
125 usedURL = true;
126 // The filename for any content based drag or file url should be the las t element of
127 // the path. If we can't find it, or we're coming up with the name for a link
128 // we just use the entire url.
129 DWORD len = fsPathMaxLengthExcludingExtension;
130 String lastComponent = kurl.lastPathComponent();
131 if (kurl.isLocalFile() || (!isLink && !lastComponent.isEmpty())) {
132 len = min<DWORD>(fsPathMaxLengthExcludingExtension, lastComponent.le ngth());
133 CopyMemory(fsPathBuffer, lastComponent.characters(), len * sizeof(UC har));
134 } else {
135 len = min<DWORD>(fsPathMaxLengthExcludingExtension, url.length());
136 CopyMemory(fsPathBuffer, url.characters(), len * sizeof(UChar));
137 }
138 fsPathBuffer[len] = 0;
139 pathRemoveBadFSCharacters(fsPathBuffer, len);
140 }
141
142 if (!extension)
143 return String(static_cast<UChar*>(fsPathBuffer));
144
145 if (!isLink && usedURL) {
146 PathRenameExtension(fsPathBuffer, extension);
147 return String(static_cast<UChar*>(fsPathBuffer));
148 }
149
150 return makeString(static_cast<const UChar*>(fsPathBuffer), extension);
151 #endif
152 }
153
154 static HGLOBAL createGlobalImageFileContent(SharedBuffer* data)
155 {
156 HGLOBAL memObj = GlobalAlloc(GPTR, data->size());
157 if (!memObj)
158 return 0;
159
160 char* fileContents = (PSTR)GlobalLock(memObj);
161
162 CopyMemory(fileContents, data->data(), data->size());
163
164 GlobalUnlock(memObj);
165
166 return memObj;
167 }
168
169 static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share dBuffer* data)
170 {
171 if (fileName.isEmpty() || !data)
172 return 0;
173
174 WCHAR filePath[MAX_PATH];
175
176 if (url.isLocalFile()) {
177 String localPath = decodeURLEscapeSequences(url.path());
178 // windows does not enjoy a leading slash on paths
179 if (localPath[0] == '/')
180 localPath = localPath.substring(1);
181 LPCWSTR localPathStr = localPath.charactersWithNullTermination();
182 if (wcslen(localPathStr) + 1 < MAX_PATH)
183 wcscpy_s(filePath, MAX_PATH, localPathStr);
184 else
185 return 0;
186 } else {
187 #if OS(WINCE)
188 notImplemented();
189 return 0;
190 #else
191 WCHAR tempPath[MAX_PATH];
192 WCHAR extension[MAX_PATH];
193 if (!::GetTempPath(WTF_ARRAY_LENGTH(tempPath), tempPath))
194 return 0;
195 if (!::PathAppend(tempPath, fileName.charactersWithNullTermination()))
196 return 0;
197 LPCWSTR foundExtension = ::PathFindExtension(tempPath);
198 if (foundExtension) {
199 if (wcscpy_s(extension, MAX_PATH, foundExtension))
200 return 0;
201 } else
202 *extension = 0;
203 ::PathRemoveExtension(tempPath);
204 for (int i = 1; i < 10000; i++) {
205 if (swprintf_s(filePath, MAX_PATH, TEXT("%s-%d%s"), tempPath, i, ext ension) == -1)
206 return 0;
207 if (!::PathFileExists(filePath))
208 break;
209 }
210 HANDLE tempFileHandle = CreateFile(filePath, GENERIC_READ | GENERIC_WRIT E, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
211 if (tempFileHandle == INVALID_HANDLE_VALUE)
212 return 0;
213
214 // Write the data to this temp file.
215 DWORD written;
216 BOOL tempWriteSucceeded = WriteFile(tempFileHandle, data->data(), data-> size(), &written, 0);
217 CloseHandle(tempFileHandle);
218 if (!tempWriteSucceeded)
219 return 0;
220 #endif
221 }
222
223 SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (wcslen(filePath ) + 2));
224 HGLOBAL memObj = GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize);
225 if (!memObj)
226 return 0;
227
228 DROPFILES* dropFiles = (DROPFILES*) GlobalLock(memObj);
229 dropFiles->pFiles = sizeof(DROPFILES);
230 dropFiles->fWide = TRUE;
231 wcscpy((LPWSTR)(dropFiles + 1), filePath);
232 GlobalUnlock(memObj);
233
234 return memObj;
235 }
236
237 static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& title, CachedImage* image)
238 {
239 ASSERT_ARG(image, image);
240 ASSERT(image->image()->data());
241
242 HRESULT hr = S_OK;
243 HGLOBAL memObj = 0;
244 String fsPath;
245 memObj = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
246 if (!memObj)
247 return 0;
248
249 FILEGROUPDESCRIPTOR* fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(memObj);
250 memset(fgd, 0, sizeof(FILEGROUPDESCRIPTOR));
251 fgd->cItems = 1;
252 fgd->fgd[0].dwFlags = FD_FILESIZE;
253 fgd->fgd[0].nFileSizeLow = image->image()->data()->size();
254
255 const String& preferredTitle = title.isEmpty() ? image->response().suggested Filename() : title;
256 String extension = image->image()->filenameExtension();
257 if (extension.isEmpty()) {
258 // Do not continue processing in the rare and unusual case where a decod ed image is not able
259 // to provide a filename extension. Something tricky (like a bait-n-swit ch) is going on
260 return 0;
261 }
262 extension.insert(".", 0);
263 fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.charact ersWithNullTermination(), false);
264
265 if (fsPath.length() <= 0) {
266 GlobalUnlock(memObj);
267 GlobalFree(memObj);
268 return 0;
269 }
270
271 int maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName));
272 CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * si zeof(UChar));
273 GlobalUnlock(memObj);
274
275 return memObj;
276 }
277
278
279 // writeFileToDataObject takes ownership of fileDescriptor and fileContent
280 static HRESULT writeFileToDataObject(IDataObject* dataObject, HGLOBAL fileDescri ptor, HGLOBAL fileContent, HGLOBAL hDropContent)
281 {
282 HRESULT hr = S_OK;
283 FORMATETC* fe;
284 STGMEDIUM medium = {0};
285 medium.tymed = TYMED_HGLOBAL;
286
287 if (!fileDescriptor || !fileContent)
288 goto exit;
289
290 // Descriptor
291 fe = fileDescriptorFormat();
292
293 medium.hGlobal = fileDescriptor;
294
295 if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE)))
296 goto exit;
297
298 // Contents
299 fe = fileContentFormatZero();
300 medium.hGlobal = fileContent;
301 if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE)))
302 goto exit;
303
304 #if USE(CF)
305 // HDROP
306 if (hDropContent) {
307 medium.hGlobal = hDropContent;
308 hr = dataObject->SetData(cfHDropFormat(), &medium, TRUE);
309 }
310 #endif
311
312 exit:
313 if (FAILED(hr)) {
314 if (fileDescriptor)
315 GlobalFree(fileDescriptor);
316 if (fileContent)
317 GlobalFree(fileContent);
318 if (hDropContent)
319 GlobalFree(hDropContent);
320 }
321 return hr;
322 }
323
324 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
325 {
326 if (dragData->platformData())
327 return ClipboardWin::create(DragAndDrop, dragData->platformData(), polic y, frame);
328 return ClipboardWin::create(DragAndDrop, dragData->dragDataMap(), policy, fr ame);
329 }
330
331 ClipboardWin::ClipboardWin(ClipboardType clipboardType, IDataObject* dataObject, ClipboardAccessPolicy policy, Frame* frame)
332 : Clipboard(policy, clipboardType)
333 , m_dataObject(dataObject)
334 , m_writableDataObject(0)
335 , m_frame(frame)
336 {
337 }
338
339 ClipboardWin::ClipboardWin(ClipboardType clipboardType, WCDataObject* dataObject , ClipboardAccessPolicy policy, Frame* frame)
340 : Clipboard(policy, clipboardType)
341 , m_dataObject(dataObject)
342 , m_writableDataObject(dataObject)
343 , m_frame(frame)
344 {
345 }
346
347 ClipboardWin::ClipboardWin(ClipboardType clipboardType, const DragDataMap& dataM ap, ClipboardAccessPolicy policy, Frame* frame)
348 : Clipboard(policy, clipboardType)
349 , m_dataObject(0)
350 , m_writableDataObject(0)
351 , m_frame(frame)
352 , m_dragDataMap(dataMap)
353 {
354 }
355
356 ClipboardWin::~ClipboardWin()
357 {
358 if (m_dragImage)
359 m_dragImage->removeClient(this);
360 }
361
362 static bool writeURL(WCDataObject *data, const KURL& url, String title, bool wit hPlainText, bool withHTML)
363 {
364 ASSERT(data);
365
366 if (url.isEmpty())
367 return false;
368
369 if (title.isEmpty()) {
370 title = url.lastPathComponent();
371 if (title.isEmpty())
372 title = url.host();
373 }
374
375 STGMEDIUM medium = {0};
376 medium.tymed = TYMED_HGLOBAL;
377
378 medium.hGlobal = createGlobalData(url, title);
379 bool success = false;
380 if (medium.hGlobal && FAILED(data->SetData(urlWFormat(), &medium, TRUE)))
381 ::GlobalFree(medium.hGlobal);
382 else
383 success = true;
384
385 if (withHTML) {
386 Vector<char> cfhtmlData;
387 markupToCFHTML(urlToMarkup(url, title), "", cfhtmlData);
388 medium.hGlobal = createGlobalData(cfhtmlData);
389 if (medium.hGlobal && FAILED(data->SetData(htmlFormat(), &medium, TRUE)) )
390 ::GlobalFree(medium.hGlobal);
391 else
392 success = true;
393 }
394
395 if (withPlainText) {
396 medium.hGlobal = createGlobalData(url.string());
397 if (medium.hGlobal && FAILED(data->SetData(plainTextWFormat(), &medium, TRUE)))
398 ::GlobalFree(medium.hGlobal);
399 else
400 success = true;
401 }
402
403 return success;
404 }
405
406 void ClipboardWin::clearData(const String& type)
407 {
408 // FIXME: Need to be able to write to the system clipboard <rdar://problem/5 015941>
409 ASSERT(isForDragAndDrop());
410 if (!canWriteData() || !m_writableDataObject)
411 return;
412
413 ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
414
415 if (dataType == ClipboardDataTypeURL) {
416 m_writableDataObject->clearData(urlWFormat()->cfFormat);
417 m_writableDataObject->clearData(urlFormat()->cfFormat);
418 }
419 if (dataType == ClipboardDataTypeText) {
420 m_writableDataObject->clearData(plainTextFormat()->cfFormat);
421 m_writableDataObject->clearData(plainTextWFormat()->cfFormat);
422 }
423
424 }
425
426 void ClipboardWin::clearAllData()
427 {
428 // FIXME: Need to be able to write to the system clipboard <rdar://problem/5 015941>
429 ASSERT(isForDragAndDrop());
430 if (!canWriteData())
431 return;
432
433 m_writableDataObject = 0;
434 WCDataObject::createInstance(&m_writableDataObject);
435 m_dataObject = m_writableDataObject;
436 }
437
438 String ClipboardWin::getData(const String& type) const
439 {
440 if (!canReadData() || (!m_dataObject && m_dragDataMap.isEmpty()))
441 return "";
442
443 ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
444 if (dataType == ClipboardDataTypeText)
445 return m_dataObject ? getPlainText(m_dataObject.get()) : getPlainText(&m _dragDataMap);
446 if (dataType == ClipboardDataTypeURL)
447 return m_dataObject ? getURL(m_dataObject.get(), DragData::DoNotConvertF ilenames) : getURL(&m_dragDataMap, DragData::DoNotConvertFilenames);
448 else if (dataType == ClipboardDataTypeTextHTML) {
449 String data = m_dataObject ? getTextHTML(m_dataObject.get()) : getTextHT ML(&m_dragDataMap);
450 if (!data.isEmpty())
451 return data;
452 return m_dataObject ? getCFHTML(m_dataObject.get()) : getCFHTML(&m_dragD ataMap);
453 }
454
455 return "";
456 }
457
458 bool ClipboardWin::setData(const String& type, const String& data)
459 {
460 // FIXME: Need to be able to write to the system clipboard <rdar://problem/5 015941>
461 ASSERT(isForDragAndDrop());
462 if (!canWriteData() || !m_writableDataObject)
463 return false;
464
465 ClipboardDataType winType = clipboardTypeFromMIMEType(type);
466
467 if (winType == ClipboardDataTypeURL)
468 return WebCore::writeURL(m_writableDataObject.get(), KURL(ParsedURLStrin g, data), String(), false, true);
469
470 if (winType == ClipboardDataTypeText) {
471 STGMEDIUM medium = {0};
472 medium.tymed = TYMED_HGLOBAL;
473 medium.hGlobal = createGlobalData(data);
474 if (!medium.hGlobal)
475 return false;
476
477 if (FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TR UE))) {
478 ::GlobalFree(medium.hGlobal);
479 return false;
480 }
481 return true;
482 }
483
484 return false;
485 }
486
487 static void addMimeTypesForFormat(ListHashSet<String>& results, const FORMATETC& format)
488 {
489 // URL and Text are provided for compatibility with IE's model
490 if (format.cfFormat == urlFormat()->cfFormat || format.cfFormat == urlWForma t()->cfFormat) {
491 results.add("URL");
492 results.add("text/uri-list");
493 }
494
495 if (format.cfFormat == plainTextWFormat()->cfFormat || format.cfFormat == pl ainTextFormat()->cfFormat) {
496 results.add("Text");
497 results.add("text/plain");
498 }
499 }
500
501 // extensions beyond IE's API
502 ListHashSet<String> ClipboardWin::types() const
503 {
504 ListHashSet<String> results;
505 if (!canReadTypes())
506 return results;
507
508 if (!m_dataObject && m_dragDataMap.isEmpty())
509 return results;
510
511 if (m_dataObject) {
512 COMPtr<IEnumFORMATETC> itr;
513
514 if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
515 return results;
516
517 if (!itr)
518 return results;
519
520 FORMATETC data;
521
522 // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
523 while (itr->Next(1, &data, 0) == S_OK)
524 addMimeTypesForFormat(results, data);
525 } else {
526 for (DragDataMap::const_iterator it = m_dragDataMap.begin(); it != m_dra gDataMap.end(); ++it) {
527 FORMATETC data;
528 data.cfFormat = (*it).key;
529 addMimeTypesForFormat(results, data);
530 }
531 }
532
533 return results;
534 }
535
536 PassRefPtr<FileList> ClipboardWin::files() const
537 {
538 #if OS(WINCE)
539 notImplemented();
540 return 0;
541 #else
542 RefPtr<FileList> files = FileList::create();
543 if (!canReadData())
544 return files.release();
545
546 if (!m_dataObject && m_dragDataMap.isEmpty())
547 return files.release();
548
549 if (m_dataObject) {
550 STGMEDIUM medium;
551 if (FAILED(m_dataObject->GetData(cfHDropFormat(), &medium)))
552 return files.release();
553
554 HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal));
555 if (!hdrop)
556 return files.release();
557
558 WCHAR filename[MAX_PATH];
559 UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
560 for (UINT i = 0; i < fileCount; i++) {
561 if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
562 continue;
563 files->append(File::create(reinterpret_cast<UChar*>(filename), File: :AllContentTypes));
564 }
565
566 GlobalUnlock(medium.hGlobal);
567 ReleaseStgMedium(&medium);
568 return files.release();
569 }
570 if (!m_dragDataMap.contains(cfHDropFormat()->cfFormat))
571 return files.release();
572 Vector<String> filesVector = m_dragDataMap.get(cfHDropFormat()->cfFormat);
573 for (Vector<String>::iterator it = filesVector.begin(); it != filesVector.en d(); ++it)
574 files->append(File::create(*it));
575 return files.release();
576 #endif
577 }
578
579 void ClipboardWin::setDragImage(CachedImage* image, Node *node, const IntPoint & loc)
580 {
581 if (!canSetDragImage())
582 return;
583
584 if (m_dragImage)
585 m_dragImage->removeClient(this);
586 m_dragImage = image;
587 if (m_dragImage)
588 m_dragImage->addClient(this);
589
590 m_dragLoc = loc;
591 m_dragImageElement = node;
592 }
593
594 void ClipboardWin::setDragImage(CachedImage* img, const IntPoint &loc)
595 {
596 setDragImage(img, 0, loc);
597 }
598
599 void ClipboardWin::setDragImageElement(Node *node, const IntPoint &loc)
600 {
601 setDragImage(0, node, loc);
602 }
603
604 DragImageRef ClipboardWin::createDragImage(IntPoint& loc) const
605 {
606 HBITMAP result = 0;
607 if (m_dragImage) {
608 result = createDragImageFromImage(m_dragImage->image());
609 loc = m_dragLoc;
610 } else if (m_dragImageElement) {
611 Node* node = m_dragImageElement.get();
612 result = node->document()->frame()->nodeImage(node);
613 loc = m_dragLoc;
614 }
615 return result;
616 }
617
618 static CachedImage* getCachedImage(Element* element)
619 {
620 // Attempt to pull CachedImage from element
621 ASSERT(element);
622 RenderObject* renderer = element->renderer();
623 if (!renderer || !renderer->isImage())
624 return 0;
625
626 RenderImage* image = toRenderImage(renderer);
627 if (image->cachedImage() && !image->cachedImage()->errorOccurred())
628 return image->cachedImage();
629
630 return 0;
631 }
632
633 static void writeImageToDataObject(IDataObject* dataObject, Element* element, co nst KURL& url)
634 {
635 // Shove image data into a DataObject for use as a file
636 CachedImage* cachedImage = getCachedImage(element);
637 if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || ! cachedImage->isLoaded())
638 return;
639
640 SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer( ))->data();
641 if (!imageBuffer || !imageBuffer->size())
642 return;
643
644 HGLOBAL imageFileDescriptor = createGlobalImageFileDescriptor(url.string(), element->getAttribute(altAttr), cachedImage);
645 if (!imageFileDescriptor)
646 return;
647
648 HGLOBAL imageFileContent = createGlobalImageFileContent(imageBuffer);
649 if (!imageFileContent) {
650 GlobalFree(imageFileDescriptor);
651 return;
652 }
653
654 String fileName = cachedImage->response().suggestedFilename();
655 HGLOBAL hDropContent = createGlobalHDropContent(url, fileName, imageBuffer);
656 if (!hDropContent) {
657 GlobalFree(hDropContent);
658 return;
659 }
660
661 writeFileToDataObject(dataObject, imageFileDescriptor, imageFileContent, hDr opContent);
662 }
663
664 void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, c onst String& title, Frame* frame)
665 {
666 // Order is important here for Explorer's sake
667 if (!m_writableDataObject)
668 return;
669 WebCore::writeURL(m_writableDataObject.get(), url, title, true, false);
670
671 writeImageToDataObject(m_writableDataObject.get(), element, url);
672
673 AtomicString imageURL = element->getAttribute(srcAttr);
674 if (imageURL.isEmpty())
675 return;
676
677 KURL fullURL = frame->document()->completeURL(stripLeadingAndTrailingHTMLSpa ces(imageURL));
678 if (fullURL.isEmpty())
679 return;
680 STGMEDIUM medium = {0};
681 medium.tymed = TYMED_HGLOBAL;
682
683 // Put img tag on the clipboard referencing the image
684 Vector<char> data;
685 markupToCFHTML(createMarkup(element, IncludeNode, 0, ResolveAllURLs), "", da ta);
686 medium.hGlobal = createGlobalData(data);
687 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &me dium, TRUE)))
688 ::GlobalFree(medium.hGlobal);
689 }
690
691 void ClipboardWin::writeURL(const KURL& kurl, const String& titleStr, Frame*)
692 {
693 if (!m_writableDataObject)
694 return;
695 WebCore::writeURL(m_writableDataObject.get(), kurl, titleStr, true, true);
696
697 String url = kurl.string();
698 ASSERT(url.containsOnlyASCII()); // KURL::string() is URL encoded.
699
700 String fsPath = filesystemPathFromUrlOrTitle(url, titleStr, L".URL", true);
701 String contentString("[InternetShortcut]\r\nURL=" + url + "\r\n");
702 CString content = contentString.latin1();
703
704 if (fsPath.length() <= 0)
705 return;
706
707 HGLOBAL urlFileDescriptor = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
708 if (!urlFileDescriptor)
709 return;
710
711 HGLOBAL urlFileContent = GlobalAlloc(GPTR, content.length());
712 if (!urlFileContent) {
713 GlobalFree(urlFileDescriptor);
714 return;
715 }
716
717 FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(urlF ileDescriptor));
718 ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR));
719 fgd->cItems = 1;
720 fgd->fgd[0].dwFlags = FD_FILESIZE;
721 fgd->fgd[0].nFileSizeLow = content.length();
722
723 unsigned maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileNa me));
724 CopyMemory(fgd->fgd[0].cFileName, fsPath.characters(), maxSize * sizeof(UCha r));
725 GlobalUnlock(urlFileDescriptor);
726
727 char* fileContents = static_cast<char*>(GlobalLock(urlFileContent));
728 CopyMemory(fileContents, content.data(), content.length());
729 GlobalUnlock(urlFileContent);
730
731 writeFileToDataObject(m_writableDataObject.get(), urlFileDescriptor, urlFile Content, 0);
732 }
733
734 void ClipboardWin::writeRange(Range* selectedRange, Frame* frame)
735 {
736 ASSERT(selectedRange);
737 if (!m_writableDataObject)
738 return;
739
740 STGMEDIUM medium = {0};
741 medium.tymed = TYMED_HGLOBAL;
742
743 Vector<char> data;
744 markupToCFHTML(createMarkup(selectedRange, 0, AnnotateForInterchange),
745 selectedRange->startContainer()->document()->url().string(), data);
746 medium.hGlobal = createGlobalData(data);
747 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &me dium, TRUE)))
748 ::GlobalFree(medium.hGlobal);
749
750 String str = frame->editor()->selectedTextForClipboard();
751 replaceNewlinesWithWindowsStyleNewlines(str);
752 replaceNBSPWithSpace(str);
753 medium.hGlobal = createGlobalData(str);
754 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat( ), &medium, TRUE)))
755 ::GlobalFree(medium.hGlobal);
756
757 medium.hGlobal = 0;
758 if (frame->editor()->canSmartCopyOrDelete())
759 m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE);
760 }
761
762 void ClipboardWin::writePlainText(const String& text)
763 {
764 if (!m_writableDataObject)
765 return;
766
767 STGMEDIUM medium = {0};
768 medium.tymed = TYMED_HGLOBAL;
769
770 String str = text;
771 replaceNewlinesWithWindowsStyleNewlines(str);
772 replaceNBSPWithSpace(str);
773 medium.hGlobal = createGlobalData(str);
774 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat( ), &medium, TRUE)))
775 ::GlobalFree(medium.hGlobal);
776
777 medium.hGlobal = 0;
778 }
779
780 bool ClipboardWin::hasData()
781 {
782 if (!m_dataObject && m_dragDataMap.isEmpty())
783 return false;
784
785 if (m_dataObject) {
786 COMPtr<IEnumFORMATETC> itr;
787 if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
788 return false;
789
790 if (!itr)
791 return false;
792
793 FORMATETC data;
794
795 // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
796 if (itr->Next(1, &data, 0) == S_OK) {
797 // There is at least one item in the IDataObject
798 return true;
799 }
800
801 return false;
802 }
803 return !m_dragDataMap.isEmpty();
804 }
805
806 void ClipboardWin::setExternalDataObject(IDataObject *dataObject)
807 {
808 ASSERT(isForDragAndDrop());
809
810 m_writableDataObject = 0;
811 m_dataObject = dataObject;
812 }
813
814 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/WebCore/platform/win/ClipboardWin.h ('k') | Source/WebCore/platform/win/ContextMenuItemWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698