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

Side by Side Diff: webkit/port/platform/ClipboardWin.cpp

Issue 7419: Move many files that were suffixed Win.cpp to Chromium.cpp, and place them in... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 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 | « webkit/port/platform/ClipboardWin.h ('k') | webkit/port/platform/ContextMenuItemWin.cpp » ('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 /*
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 <shlwapi.h>
28 #include <wininet.h>
29
30 #pragma warning(push, 0)
31 #include "ClipboardWin.h"
32 #include "CachedImage.h"
33 #include "ClipboardUtilitiesWin.h"
34 #include "csshelper.h"
35 #include "CString.h"
36 #include "Document.h"
37 #include "DragData.h"
38 #include "Editor.h"
39 #include "Element.h"
40 #include "EventHandler.h"
41 #include "Frame.h"
42 #include "FrameLoader.h"
43 #include "FrameView.h"
44 #include "HTMLNames.h"
45 #include "Image.h"
46 #include "MIMETypeRegistry.h"
47 #include "markup.h"
48 #include "Page.h"
49 #include "Pasteboard.h"
50 #include "PlatformMouseEvent.h"
51 #include "PlatformString.h"
52 #include "Range.h"
53 #include "RenderImage.h"
54 #include "ResourceResponse.h"
55 #include "StringBuilder.h"
56 #include "StringHash.h"
57 #include "WCDataObject.h"
58 #include <wtf/RefPtr.h>
59 #pragma warning(pop)
60
61 #undef LOG
62 #include "base/clipboard_util.h"
63 #include "base/string_util.h"
64 #include "googleurl/src/gurl.h"
65 #include "webkit/glue/glue_util.h"
66 #include "webkit/glue/webkit_glue.h"
67
68 namespace WebCore {
69
70 using namespace HTMLNames;
71
72 // format string for
73 static const char szShellDotUrlTemplate[] = "[InternetShortcut]\r\nURL=%s\r\n";
74
75 // We provide the IE clipboard types (URL and Text), and the clipboard types spe cified in the WHATWG Web Applications 1.0 draft
76 // see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
77
78 enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardD ataTypeText };
79
80 static ClipboardDataType clipboardTypeFromMIMEType(const String& type)
81 {
82 String qType = type.stripWhiteSpace().lower();
83
84 // two special cases for IE compatibility
85 if (qType == "text" || qType == "text/plain" || qType.startsWith("text/plain ;"))
86 return ClipboardDataTypeText;
87 if (qType == "url" || qType == "text/uri-list")
88 return ClipboardDataTypeURL;
89
90 return ClipboardDataTypeNone;
91 }
92
93 static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length)
94 {
95 size_t writeTo = 0;
96 size_t readFrom = 0;
97 while (readFrom < length) {
98 UINT type = PathGetCharType(psz[readFrom]);
99 if (psz[readFrom] == 0 || type & (GCT_LFNCHAR | GCT_SHORTCHAR)) {
100 psz[writeTo++] = psz[readFrom];
101 }
102
103 readFrom++;
104 }
105 psz[writeTo] = 0;
106 }
107
108 static String filesystemPathFromUrlOrTitle(const String& url, const String& titl e, TCHAR* extension, bool isLink)
109 {
110 bool usedURL = false;
111 WCHAR fsPathBuffer[MAX_PATH];
112 fsPathBuffer[0] = 0;
113 int extensionLen = extension ? min(MAX_PATH - 1, lstrlen(extension)) : 0;
114 String extensionString = extension ? String(extension, extensionLen) : Strin g(L"");
115
116 // We make the filename based on the title only if there's an extension.
117 if (!title.isEmpty() && extension) {
118 size_t len = min<size_t>(title.length(), MAX_PATH - extensionLen - 1);
119 CopyMemory(fsPathBuffer, title.characters(), len * sizeof(UChar));
120 fsPathBuffer[len] = 0;
121 pathRemoveBadFSCharacters(fsPathBuffer, len);
122 }
123
124 if (!lstrlen(fsPathBuffer)) {
125 DWORD len = MAX_PATH - 1;
126 String nullTermURL = url;
127 usedURL = true;
128 if (UrlIsFileUrl((LPCWSTR)nullTermURL.charactersWithNullTermination())
129 && SUCCEEDED(PathCreateFromUrl((LPCWSTR)nullTermURL.charactersWithNu llTermination(), fsPathBuffer, &len, 0))) {
130 // When linking to a file URL we can trivially find the file name
131 PWSTR fn = PathFindFileName(fsPathBuffer);
132 if (fn && fn != fsPathBuffer)
133 lstrcpyn(fsPathBuffer, fn, lstrlen(fn) + 1);
134 } else {
135 // The filename for any content based drag should be the last elemen t of
136 // the path. If we can't find it, or we're coming up with the name for a link
137 // we just use the entire url.
138 KURL kurl(url);
139 String lastComponent;
140 if (!isLink && !(lastComponent = kurl.lastPathComponent()).isEmpty() ) {
141 len = min<DWORD>(MAX_PATH - 1, lastComponent.length());
142 CopyMemory(fsPathBuffer, lastComponent.characters(), len * sizeo f(UChar));
143 } else {
144 len = min<DWORD>(MAX_PATH - 1, nullTermURL.length());
145 CopyMemory(fsPathBuffer, nullTermURL.characters(), len * sizeof( UChar));
146 }
147 fsPathBuffer[len] = 0;
148 pathRemoveBadFSCharacters(fsPathBuffer, len);
149 }
150 }
151
152 if (!extension)
153 return String((UChar*)fsPathBuffer);
154
155 if (!isLink && usedURL) {
156 PathRenameExtension(fsPathBuffer, extensionString.charactersWithNullTerm ination());
157 return String((UChar*)fsPathBuffer);
158 }
159
160 String result((UChar*)fsPathBuffer);
161 result += extensionString;
162 return result.length() >= MAX_PATH ? result.substring(0, MAX_PATH - 1) : res ult;
163 }
164
165 static HGLOBAL createGlobalURLContent(const String& url, int estimatedFileSize)
166 {
167 HRESULT hr = S_OK;
168 HGLOBAL memObj = 0;
169
170 char* fileContents;
171 char ansiUrl[INTERNET_MAX_URL_LENGTH + 1];
172 // Used to generate the buffer. This is null terminated whereas the fileCont ents won't be.
173 char contentGenerationBuffer[INTERNET_MAX_URL_LENGTH + ARRAYSIZE(szShellDotU rlTemplate) + 1];
174
175 if (estimatedFileSize > 0 && estimatedFileSize > ARRAYSIZE(contentGeneration Buffer))
176 return 0;
177
178 int ansiUrlSize = ::WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)url.characters() , url.length(), ansiUrl, ARRAYSIZE(ansiUrl) - 1, 0, 0);
179 if (!ansiUrlSize)
180 return 0;
181
182 ansiUrl[ansiUrlSize] = 0;
183
184 int fileSize = (int) (ansiUrlSize+strlen(szShellDotUrlTemplate)-2); // -2 to remove the %s
185 ASSERT(estimatedFileSize < 0 || fileSize == estimatedFileSize);
186
187 memObj = GlobalAlloc(GPTR, fileSize);
188 if (!memObj)
189 return 0;
190
191 fileContents = (PSTR)GlobalLock(memObj);
192
193 sprintf_s(contentGenerationBuffer, ARRAYSIZE(contentGenerationBuffer), szShe llDotUrlTemplate, ansiUrl);
194 CopyMemory(fileContents, contentGenerationBuffer, fileSize);
195
196 GlobalUnlock(memObj);
197
198 return memObj;
199 }
200
201 static HGLOBAL createGlobalImageFileContent(SharedBuffer* data)
202 {
203 HGLOBAL memObj = GlobalAlloc(GPTR, data->size());
204 if (!memObj)
205 return 0;
206
207 char* fileContents = (PSTR)GlobalLock(memObj);
208
209 CopyMemory(fileContents, data->data(), data->size());
210
211 GlobalUnlock(memObj);
212
213 return memObj;
214 }
215
216 static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share dBuffer* data)
217 {
218 if (fileName.isEmpty() || !data )
219 return 0;
220
221 WCHAR filePath[MAX_PATH];
222
223 if (url.isLocalFile()) {
224 String localPath = url.path();
225 // windows does not enjoy a leading slash on paths
226 if (localPath[0] == '/')
227 localPath = localPath.substring(1);
228 LPCTSTR localPathStr = localPath.charactersWithNullTermination();
229 if (wcslen(localPathStr) + 1 < MAX_PATH)
230 wcscpy_s(filePath, MAX_PATH, localPathStr);
231 else
232 return 0;
233 } else {
234 WCHAR tempPath[MAX_PATH];
235 WCHAR extension[MAX_PATH];
236 if (!::GetTempPath(ARRAYSIZE(tempPath), tempPath))
237 return 0;
238 if (!::PathAppend(tempPath, fileName.charactersWithNullTermination()))
239 return 0;
240 LPCWSTR foundExtension = ::PathFindExtension(tempPath);
241 if (foundExtension) {
242 if (wcscpy_s(extension, MAX_PATH, foundExtension))
243 return 0;
244 } else
245 *extension = 0;
246 ::PathRemoveExtension(tempPath);
247 for (int i = 1; i < 10000; i++) {
248 if (swprintf_s(filePath, MAX_PATH, TEXT("%s-%d%s"), tempPath, i, ext ension) == -1)
249 return 0;
250 if (!::PathFileExists(filePath))
251 break;
252 }
253 HANDLE tempFileHandle = CreateFile(filePath, GENERIC_READ | GENERIC_WRIT E, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
254 if (tempFileHandle == INVALID_HANDLE_VALUE)
255 return 0;
256
257 // Write the data to this temp file.
258 DWORD written;
259 BOOL tempWriteSucceeded = WriteFile(tempFileHandle, data->data(), data-> size(), &written, 0);
260 CloseHandle(tempFileHandle);
261 if (!tempWriteSucceeded)
262 return 0;
263 }
264
265 SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (wcslen(filePath ) + 2));
266 HGLOBAL memObj = GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize);
267 if (!memObj)
268 return 0;
269
270 DROPFILES* dropFiles = (DROPFILES*) GlobalLock(memObj);
271 dropFiles->pFiles = sizeof(DROPFILES);
272 dropFiles->fWide = TRUE;
273 wcscpy((LPWSTR)(dropFiles + 1), filePath);
274 GlobalUnlock(memObj);
275
276 return memObj;
277 }
278
279 static HGLOBAL createGlobalUrlFileDescriptor(const String& url, const String& ti tle, int& /*out*/ estimatedSize)
280 {
281 HRESULT hr = S_OK;
282 HGLOBAL memObj = 0;
283 String fsPath;
284 memObj = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
285 if (!memObj)
286 return 0;
287
288 FILEGROUPDESCRIPTOR* fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(memObj);
289 memset(fgd, 0, sizeof(FILEGROUPDESCRIPTOR));
290 fgd->cItems = 1;
291 fgd->fgd[0].dwFlags = FD_FILESIZE;
292 int fileSize = ::WideCharToMultiByte(CP_ACP, 0, url.characters(), url.length (), 0, 0, 0, 0);
293 fileSize += strlen(szShellDotUrlTemplate) - 2; // -2 is for getting rid of %s in the template string
294 fgd->fgd[0].nFileSizeLow = fileSize;
295 estimatedSize = fileSize;
296 fsPath = filesystemPathFromUrlOrTitle(url, title, L".URL", true);
297
298 if (fsPath.length() <= 0) {
299 GlobalUnlock(memObj);
300 GlobalFree(memObj);
301 return 0;
302 }
303
304 int maxSize = min(fsPath.length(), ARRAYSIZE(fgd->fgd[0].cFileName));
305 CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * si zeof(UChar));
306 GlobalUnlock(memObj);
307
308 return memObj;
309 }
310
311
312 static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& title, CachedImage* image)
313 {
314 ASSERT_ARG(image, image);
315 ASSERT(image->image()->data());
316
317 HRESULT hr = S_OK;
318 HGLOBAL memObj = 0;
319 String fsPath;
320 memObj = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
321 if (!memObj)
322 return 0;
323
324 FILEGROUPDESCRIPTOR* fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(memObj);
325 memset(fgd, 0, sizeof(FILEGROUPDESCRIPTOR));
326 fgd->cItems = 1;
327 fgd->fgd[0].dwFlags = FD_FILESIZE;
328 fgd->fgd[0].nFileSizeLow = image->image()->data()->size();
329
330 String extension(".");
331 extension += WebCore::MIMETypeRegistry::getPreferredExtensionForMIMEType(ima ge->response().mimeType());
332 const String& preferredTitle = title.isEmpty() ? image->response().suggested Filename() : title;
333 fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.isEmpty () ? 0 : (TCHAR*)extension.charactersWithNullTermination(), false);
334
335 if (fsPath.length() <= 0) {
336 GlobalUnlock(memObj);
337 GlobalFree(memObj);
338 return 0;
339 }
340
341 int maxSize = min(fsPath.length(), ARRAYSIZE(fgd->fgd[0].cFileName));
342 CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * si zeof(UChar));
343 GlobalUnlock(memObj);
344
345 return memObj;
346 }
347
348
349 // writeFileToDataObject takes ownership of fileDescriptor and fileContent
350 static HRESULT writeFileToDataObject(IDataObject* dataObject, HGLOBAL fileDescri ptor, HGLOBAL fileContent, HGLOBAL hDropContent)
351 {
352 HRESULT hr = S_OK;
353 FORMATETC* fe;
354 STGMEDIUM medium = {0};
355 medium.tymed = TYMED_HGLOBAL;
356
357 if (!fileDescriptor || !fileContent)
358 goto exit;
359
360 // Descriptor
361 fe = ClipboardUtil::GetFileDescriptorFormat();
362
363 medium.hGlobal = fileDescriptor;
364
365 if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE)))
366 goto exit;
367
368 // Contents
369 fe = ClipboardUtil::GetFileContentFormatZero();
370 medium.hGlobal = fileContent;
371 if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE)))
372 goto exit;
373
374 // HDROP
375 if (hDropContent) {
376 medium.hGlobal = hDropContent;
377 hr = dataObject->SetData(ClipboardUtil::GetCFHDropFormat(), &medium, TRU E);
378 }
379
380 exit:
381 if (FAILED(hr)) {
382 if (fileDescriptor)
383 GlobalFree(fileDescriptor);
384 if (fileContent)
385 GlobalFree(fileContent);
386 if (hDropContent)
387 GlobalFree(hDropContent);
388 }
389 return hr;
390 }
391
392 ClipboardWin::ClipboardWin(bool isForDragging, IDataObject* dataObject, Clipboar dAccessPolicy policy)
393 : Clipboard(policy, isForDragging)
394 , m_dataObject(dataObject)
395 , m_writableDataObject(0)
396 {
397 }
398
399 ClipboardWin::ClipboardWin(bool isForDragging, WCDataObject* dataObject, Clipboa rdAccessPolicy policy)
400 : Clipboard(policy, isForDragging)
401 , m_dataObject(dataObject)
402 , m_writableDataObject(dataObject)
403 {
404 }
405
406 ClipboardWin::~ClipboardWin()
407 {
408 }
409
410 PassRefPtr<ClipboardWin> ClipboardWin::create(bool isForDragging, IDataObject* d ataObject, ClipboardAccessPolicy policy)
411 {
412 return adoptRef(new ClipboardWin(isForDragging, dataObject, policy));
413 }
414
415 PassRefPtr<ClipboardWin> ClipboardWin::create(bool isForDragging, WCDataObject* dataObject, ClipboardAccessPolicy policy)
416 {
417 return adoptRef(new ClipboardWin(isForDragging, dataObject, policy));
418 }
419
420 static bool writeURL(WCDataObject *data, const KURL& url, String title, bool wit hPlainText, bool withHTML)
421 {
422 ASSERT(data);
423
424 if (url.isEmpty())
425 return false;
426
427 if (title.isEmpty()) {
428 title = url.lastPathComponent();
429 if (title.isEmpty())
430 title = url.host();
431 }
432
433 STGMEDIUM medium = {0};
434 medium.tymed = TYMED_HGLOBAL;
435
436 medium.hGlobal = createGlobalData(url, title);
437 bool success = false;
438 if (medium.hGlobal && FAILED(data->SetData(ClipboardUtil::GetUrlWFormat(), & medium, TRUE)))
439 ::GlobalFree(medium.hGlobal);
440 else
441 success = true;
442
443 if (withHTML) {
444 Vector<char> cfhtmlData;
445 markupToCF_HTML(urlToMarkup(url, title), "", cfhtmlData);
446 medium.hGlobal = createGlobalData(cfhtmlData);
447 if (medium.hGlobal && FAILED(data->SetData(htmlFormat(), &medium, TRUE)) )
448 ::GlobalFree(medium.hGlobal);
449 else
450 success = true;
451 }
452
453 if (withPlainText) {
454 medium.hGlobal = createGlobalData(url.string());
455 if (medium.hGlobal && FAILED(data->SetData(ClipboardUtil::GetPlainTextWF ormat(), &medium, TRUE)))
456 ::GlobalFree(medium.hGlobal);
457 else
458 success = true;
459 }
460
461 return success;
462 }
463
464 void ClipboardWin::clearData(const String& type)
465 {
466 //FIXME: Need to be able to write to the system clipboard <rdar://problem/50 15941>
467 ASSERT(isForDragging());
468 if (policy() != ClipboardWritable || !m_writableDataObject)
469 return;
470
471 ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
472
473 if (dataType == ClipboardDataTypeURL) {
474 m_writableDataObject->clearData(ClipboardUtil::GetUrlWFormat()->cfFormat );
475 m_writableDataObject->clearData(ClipboardUtil::GetUrlFormat()->cfFormat) ;
476 }
477 if (dataType == ClipboardDataTypeText) {
478 m_writableDataObject->clearData(ClipboardUtil::GetPlainTextFormat()->cfF ormat);
479 m_writableDataObject->clearData(ClipboardUtil::GetPlainTextWFormat()->cf Format);
480 }
481
482 }
483
484 void ClipboardWin::clearAllData()
485 {
486 //FIXME: Need to be able to write to the system clipboard <rdar://problem/50 15941>
487 ASSERT(isForDragging());
488 if (policy() != ClipboardWritable)
489 return;
490
491 m_writableDataObject = 0;
492 WCDataObject::createInstance(&m_writableDataObject);
493 m_dataObject = m_writableDataObject;
494 }
495
496 String ClipboardWin::getData(const String& type, bool& success) const
497 {
498 success = false;
499 if (policy() != ClipboardReadable || !m_dataObject) {
500 return "";
501 }
502
503 ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
504 if (dataType == ClipboardDataTypeText) {
505 std::wstring text;
506 if (!isForDragging()) {
507 // If this isn't for a drag, it's for a cut/paste event handler.
508 // In this case, we need to use our glue methods to access the
509 // clipboard contents.
510 webkit_glue::ClipboardReadText(&text);
511 if (text.empty()) {
512 std::string asciiText;
513 webkit_glue::ClipboardReadAsciiText(&asciiText);
514 text = ASCIIToWide(asciiText);
515 }
516 success = !text.empty();
517 } else {
518 success = ClipboardUtil::GetPlainText(m_dataObject.get(), &text);
519 }
520 return webkit_glue::StdWStringToString(text);
521 } else if (dataType == ClipboardDataTypeURL) {
522 std::wstring url;
523 std::wstring title;
524 success = ClipboardUtil::GetUrl(m_dataObject.get(), &url, &title);
525 return webkit_glue::StdWStringToString(url);
526 }
527
528 return "";
529 }
530
531 bool ClipboardWin::setData(const String& type, const String& data)
532 {
533 // FIXME: Need to be able to write to the system clipboard <rdar://problem/5 015941>
534 ASSERT(isForDragging());
535 if (policy() != ClipboardWritable || !m_writableDataObject)
536 return false;
537
538 ClipboardDataType winType = clipboardTypeFromMIMEType(type);
539
540 if (winType == ClipboardDataTypeURL)
541 return WebCore::writeURL(m_writableDataObject.get(), KURL(data), String( ), false, true);
542
543 if (winType == ClipboardDataTypeText) {
544 STGMEDIUM medium = {0};
545 medium.tymed = TYMED_HGLOBAL;
546 medium.hGlobal = createGlobalData(data);
547 if (!medium.hGlobal)
548 return false;
549
550 if (FAILED(m_writableDataObject->SetData(ClipboardUtil::GetPlainTextWFor mat(), &medium, TRUE))) {
551 ::GlobalFree(medium.hGlobal);
552 return false;
553 }
554 return true;
555 }
556 return false;
557 }
558
559 static void addMimeTypesForFormat(HashSet<String>& results, FORMATETC& format)
560 {
561 // URL and Text are provided for compatibility with IE's model
562 if (format.cfFormat == ClipboardUtil::GetUrlFormat()->cfFormat ||
563 format.cfFormat == ClipboardUtil::GetUrlWFormat()->cfFormat) {
564 results.add("URL");
565 results.add("text/uri-list");
566 }
567
568 if (format.cfFormat == ClipboardUtil::GetPlainTextWFormat()->cfFormat ||
569 format.cfFormat == ClipboardUtil::GetPlainTextFormat()->cfFormat) {
570 results.add("Text");
571 results.add("text/plain");
572 }
573 }
574
575 // extensions beyond IE's API
576 HashSet<String> ClipboardWin::types() const
577 {
578 HashSet<String> results;
579 if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
580 return results;
581
582 if (!m_dataObject)
583 return results;
584
585 COMPtr<IEnumFORMATETC> itr;
586
587 if (FAILED(m_dataObject->EnumFormatEtc(0, &itr)))
588 return results;
589
590 if (!itr)
591 return results;
592
593 FORMATETC data;
594
595 while (SUCCEEDED(itr->Next(1, &data, 0))) {
596 addMimeTypesForFormat(results, data);
597 }
598
599 return results;
600 }
601
602 void ClipboardWin::setDragImage(CachedImage* image, Node *node, const IntPoint & loc)
603 {
604 if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
605 return;
606
607 if (m_dragImage)
608 m_dragImage->removeClient(this);
609 m_dragImage = image;
610 if (m_dragImage)
611 m_dragImage->addClient(this);
612
613 m_dragLoc = loc;
614 m_dragImageElement = node;
615 }
616
617 void ClipboardWin::setDragImage(CachedImage* img, const IntPoint &loc)
618 {
619 setDragImage(img, 0, loc);
620 }
621
622 void ClipboardWin::setDragImageElement(Node *node, const IntPoint &loc)
623 {
624 setDragImage(0, node, loc);
625 }
626
627 DragImageRef ClipboardWin::createDragImage(IntPoint& loc) const
628 {
629 HBITMAP result = 0;
630 //FIXME: Need to be able to draw element <rdar://problem/5015942>
631 if (m_dragImage) {
632 result = createDragImageFromImage(m_dragImage->image());
633 loc = m_dragLoc;
634 }
635 return result;
636 }
637
638 static String imageToMarkup(const String& url, Element* element)
639 {
640 StringBuilder markup;
641 markup.append("<img src=\"");
642 markup.append(url);
643 markup.append("\"");
644 // Copy over attributes. If we are dragging an image, we expect things like
645 // the id to be copied as well.
646 NamedAttrMap* attrs = element->attributes();
647 unsigned int length = attrs->length();
648 for (unsigned int i = 0; i < length; ++i) {
649 Attribute* attr = attrs->attributeItem(i);
650 if (attr->localName() == "src")
651 continue;
652 markup.append(" ");
653 markup.append(attr->localName());
654 markup.append("=\"");
655 String escapedAttr = attr->value();
656 escapedAttr.replace("\"", "&quot;");
657 markup.append(escapedAttr);
658 markup.append("\"");
659 }
660
661 markup.append("/>");
662 return markup.toString();
663 }
664
665 static CachedImage* getCachedImage(Element* element)
666 {
667 // Attempt to pull CachedImage from element
668 ASSERT(element);
669 RenderObject* renderer = element->renderer();
670 if (!renderer || !renderer->isImage())
671 return 0;
672
673 RenderImage* image = static_cast<RenderImage*>(renderer);
674 if (image->cachedImage() && !image->cachedImage()->errorOccurred())
675 return image->cachedImage();
676
677 return 0;
678 }
679
680 static void writeImageToDataObject(IDataObject* dataObject, Element* element, co nst KURL& url)
681 {
682 // Shove image data into a DataObject for use as a file
683 CachedImage* cachedImage = getCachedImage(element);
684 if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
685 return;
686
687 SharedBuffer* imageBuffer = cachedImage->image()->data();
688 if (!imageBuffer || !imageBuffer->size())
689 return;
690
691 HGLOBAL imageFileDescriptor = createGlobalImageFileDescriptor(url.string(), element->getAttribute(altAttr), cachedImage);
692 if (!imageFileDescriptor)
693 return;
694
695 HGLOBAL imageFileContent = createGlobalImageFileContent(imageBuffer);
696 if (!imageFileContent) {
697 GlobalFree(imageFileDescriptor);
698 return;
699 }
700
701 // When running in the sandbox, it's possible that hDropContent is NULL.
702 // That's ok, we should keep going anyway.
703 String fileName = cachedImage->response().suggestedFilename();
704 HGLOBAL hDropContent = createGlobalHDropContent(url, fileName, imageBuffer);
705
706 writeFileToDataObject(dataObject, imageFileDescriptor, imageFileContent, hDr opContent);
707 }
708
709 void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, c onst String& title, Frame* frame)
710 {
711 // Order is important here for Explorer's sake
712 if (!m_writableDataObject)
713 return;
714 WebCore::writeURL(m_writableDataObject.get(), url, title, true, false);
715
716 writeImageToDataObject(m_writableDataObject.get(), element, url);
717
718 AtomicString imageURL = element->getAttribute(srcAttr);
719 if (imageURL.isEmpty())
720 return;
721
722 String fullURL = frame->document()->completeURL(parseURL(imageURL));
723 if (fullURL.isEmpty())
724 return;
725 STGMEDIUM medium = {0};
726 medium.tymed = TYMED_HGLOBAL;
727 ExceptionCode ec = 0;
728
729 // Put img tag on the clipboard referencing the image
730 Vector<char> data;
731 markupToCF_HTML(imageToMarkup(fullURL, element), "", data);
732 medium.hGlobal = createGlobalData(data);
733 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &me dium, TRUE)))
734 ::GlobalFree(medium.hGlobal);
735 }
736
737 void ClipboardWin::writeURL(const KURL& kurl, const String& titleStr, Frame*)
738 {
739 if (!m_writableDataObject)
740 return;
741 WebCore::writeURL(m_writableDataObject.get(), kurl, titleStr, true, true);
742
743 int estimatedSize = 0;
744 String url = kurl.string();
745
746 HGLOBAL urlFileDescriptor = createGlobalUrlFileDescriptor(url, titleStr, est imatedSize);
747 if (!urlFileDescriptor)
748 return;
749 HGLOBAL urlFileContent = createGlobalURLContent(url, estimatedSize);
750 if (!urlFileContent) {
751 GlobalFree(urlFileDescriptor);
752 return;
753 }
754 writeFileToDataObject(m_writableDataObject.get(), urlFileDescriptor, urlFile Content, 0);
755 }
756
757 void ClipboardWin::writeRange(Range* selectedRange, Frame* frame)
758 {
759 ASSERT(selectedRange);
760 if (!m_writableDataObject)
761 return;
762
763 STGMEDIUM medium = {0};
764 medium.tymed = TYMED_HGLOBAL;
765 ExceptionCode ec = 0;
766
767 Vector<char> data;
768 markupToCF_HTML(createMarkup(selectedRange, 0, AnnotateForInterchange),
769 selectedRange->startContainer(ec)->document()->url().string(), data);
770 medium.hGlobal = createGlobalData(data);
771 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &me dium, TRUE)))
772 ::GlobalFree(medium.hGlobal);
773
774 String str = frame->selectedText();
775 replaceNewlinesWithWindowsStyleNewlines(str);
776 replaceNBSPWithSpace(str);
777 medium.hGlobal = createGlobalData(str);
778 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat( ), &medium, TRUE)))
779 ::GlobalFree(medium.hGlobal);
780
781 medium.hGlobal = 0;
782 if (frame->editor()->canSmartCopyOrDelete())
783 m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE);
784 }
785
786 bool ClipboardWin::hasData()
787 {
788 if (!m_dataObject)
789 return false;
790
791 COMPtr<IEnumFORMATETC> itr;
792 if (FAILED(m_dataObject->EnumFormatEtc(0, &itr)))
793 return false;
794
795 if (!itr)
796 return false;
797
798 FORMATETC data;
799
800 if (SUCCEEDED(itr->Next(1, &data, 0))) {
801 // There is at least one item in the IDataObject
802 return true;
803 }
804
805 return false;
806 }
807
808 } // namespace WebCore
OLDNEW
« no previous file with comments | « webkit/port/platform/ClipboardWin.h ('k') | webkit/port/platform/ContextMenuItemWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698