Changeset 150772 in webkit
- Timestamp:
- May 27, 2013 12:51:49 PM (11 years ago)
- Location:
- trunk/Source
- Files:
-
- 1 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r150771 r150772 1 2013-05-27 Xueqing Huang <huangxueqing@baidu.com> 2 3 Move Windows port off legacy clipboard. 4 https://bugs.webkit.org/show_bug.cgi?id=116258 5 6 Reviewed by Darin Adler. 7 8 Clipboard refactor, no new tests. 9 10 * dom/Clipboard.h: 11 * page/win/EventHandlerWin.cpp: 12 (WebCore::EventHandler::createDraggingClipboard): Create Clipboard instead of ClipboardWin. 13 * platform/Pasteboard.h: 14 (WebCore::Pasteboard::dataObject): Get IDataObject by Clipborad. 15 (WebCore::Pasteboard::writableDataObject): Get WCDataObject by Clipborad. 16 * platform/win/ClipboardWin.cpp: 17 (WebCore::Clipboard::createDragImage): Change parameter name loc to dragLocation. 18 (WebCore::Clipboard::declareAndWriteDragImage): Implement declareAndWriteDragImage use WCDataObject exposed by Pasteboard. 19 * platform/win/ClipboardWin.h: Removed. 20 * platform/win/EditorWin.cpp: 21 (WebCore::Editor::newGeneralClipboard): Create Clipboard instead of ClipboardWin. 22 * platform/win/PasteboardWin.cpp: 23 (WebCore::Pasteboard::createForCopyAndPaste): Create a Pasteboard. 24 (WebCore::Pasteboard::createPrivate): Ditto. 25 (WebCore::Pasteboard::createForDragAndDrop): Ditto. 26 (WebCore::Pasteboard::finishCreatingPasteboard): Create Pasteboard use Windows API. 27 (WebCore::Pasteboard::Pasteboard): 28 (WebCore::clipboardTypeFromMIMEType): Copied from ClipboardWin.cpp. 29 (WebCore::Pasteboard::clear): Ditto. 30 (WebCore::Pasteboard::hasData): Ditto. 31 (WebCore::addMimeTypesForFormat): Ditto. 32 (WebCore::Pasteboard::types): Ditto. 33 (WebCore::Pasteboard::readString): Ditto. 34 (WebCore::Pasteboard::readFilenames): Ditto. 35 (WebCore::writeURL): Ditto. 36 (WebCore::Pasteboard::writeString): Ditto. 37 (WebCore::Pasteboard::setDragImage): Ditto. 38 (WebCore::Pasteboard::writeRangeToDataObject): Write range to WCDataObject. 39 (WebCore::Pasteboard::writeSelection): 40 (WebCore::Pasteboard::writePlainTextToDataObject): Write PlainText to WCDataObject. 41 (WebCore::Pasteboard::writePlainText): 42 (WebCore::pathRemoveBadFSCharacters): Copied from ClipboardWin.cpp. 43 (WebCore::filesystemPathFromUrlOrTitle): Ditto. 44 (WebCore::writeFileToDataObject): Ditto. 45 (WebCore::Pasteboard::writeURLToDataObject): Write URL to WCDataObject. 46 (WebCore::Pasteboard::writeURL): Copied from ClipboardWin.cpp. 47 (WebCore::Pasteboard::writePasteboard): Copied from Pasteboard::writeClipboard. 48 (WebCore::Pasteboard::documentFragment): Copied from ClipboardWin.cpp. 49 (WebCore::Pasteboard::setExternalDataObject): Clipboard can set new IDataObject. 50 (WebCore::getCachedImage): Copied from ClipboardWin.cpp. 51 (WebCore::createGlobalImageFileDescriptor): Ditto. 52 (WebCore::createGlobalImageFileContent): Ditto. 53 (WebCore::createGlobalHDropContent): Ditto. 54 (WebCore::Pasteboard::writeImageToDataObject): Expose to make Clipboard implement declareAndWriteDragImage. 55 (WebCore::Pasteboard::writeURLToWritableDataObject): Ditto. 56 1 57 2013-05-27 Tim Horton <timothy_horton@apple.com> 2 58 -
trunk/Source/WebCore/dom/Clipboard.h
r150373 r150772 35 35 // Specifically, the class currently named Pasteboard. The legacy style instead 36 36 // uses this as an abstract base class. 37 #define WTF_USE_LEGACY_STYLE_ABSTRACT_CLIPBOARD_CLASS (PLATFORM(IOS) || PLATFORM(QT) || PLATFORM(WIN))37 #define WTF_USE_LEGACY_STYLE_ABSTRACT_CLIPBOARD_CLASS (PLATFORM(IOS) || PLATFORM(QT)) 38 38 39 39 #if USE(LEGACY_STYLE_ABSTRACT_CLIPBOARD_CLASS) -
trunk/Source/WebCore/page/win/EventHandlerWin.cpp
r145913 r150772 28 28 #include "EventHandler.h" 29 29 30 #include "COMPtr.h" 31 #include "Clipboard.h" 30 32 #include "Cursor.h" 31 33 #include "FloatPoint.h" … … 43 45 #include "WCDataObject.h" 44 46 #include "NotImplemented.h" 45 46 #if OS(WINCE)47 #include "Clipboard.h"48 #else49 #include "ClipboardWin.h"50 #endif51 47 52 48 namespace WebCore { … … 102 98 return 0; 103 99 #else 104 COMPtr<WCDataObject> dataObject; 105 WCDataObject::createInstance(&dataObject); 106 return ClipboardWin::create(Clipboard::DragAndDrop, dataObject.get(), ClipboardWritable, m_frame); 100 return Clipboard::createForDragAndDrop(); 107 101 #endif 108 102 } -
trunk/Source/WebCore/platform/Pasteboard.h
r150334 r150772 39 39 40 40 #if PLATFORM(WIN) 41 #include "COMPtr.h" 42 #include "WCDataObject.h" 43 #include <objidl.h> 41 44 #include <windows.h> 42 45 typedef struct HWND__* HWND; … … 65 68 class DocumentFragment; 66 69 class DragData; 70 class Element; 67 71 class Frame; 68 72 class HitTestResult; … … 154 158 #endif 155 159 160 #if PLATFORM(WIN) 161 COMPtr<IDataObject> dataObject() const { return m_dataObject; } 162 void setExternalDataObject(IDataObject*); 163 void writeURLToWritableDataObject(const KURL&, const String&); 164 COMPtr<WCDataObject> writableDataObject() const { return m_writableDataObject; } 165 void writeImageToDataObject(Element*, const KURL&); 166 #endif 167 156 168 #if PLATFORM(GTK) 157 169 ~Pasteboard(); … … 164 176 Pasteboard(PassRefPtr<DataObjectGtk>); 165 177 Pasteboard(GtkClipboard*); 178 #endif 179 180 #if PLATFORM(WIN) 181 explicit Pasteboard(IDataObject*); 182 explicit Pasteboard(WCDataObject*); 183 explicit Pasteboard(const DragDataMap&); 166 184 #endif 167 185 … … 176 194 177 195 #if PLATFORM(WIN) 196 void finishCreatingPasteboard(); 197 void writeRangeToDataObject(Range*, Frame*); 198 void writeURLToDataObject(const KURL&, const String&, Frame*); 199 void writePlainTextToDataObject(const String&, SmartReplaceOption); 200 178 201 HWND m_owner; 202 COMPtr<IDataObject> m_dataObject; 203 COMPtr<WCDataObject> m_writableDataObject; 204 DragDataMap m_dragDataMap; 179 205 #endif 180 206 -
trunk/Source/WebCore/platform/win/ClipboardWin.cpp
r150373 r150772 1 1 /* 2 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2013 Xueqing Huang <huangxueqing@baidu.com> 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 25 26 26 27 #include "config.h" 27 #include "Clipboard Win.h"28 #include "Clipboard.h" 28 29 29 30 #include "CachedImage.h" 30 31 #include "ClipboardUtilitiesWin.h" 31 32 #include "Document.h" 32 #include "DragData.h"33 #include "Editor.h"34 33 #include "Element.h" 35 #include "EventHandler.h"36 #include "FileList.h"37 34 #include "Frame.h" 38 #include "FrameLoader.h"39 #include "FrameView.h"40 35 #include "HTMLNames.h" 41 36 #include "HTMLParserIdioms.h" 42 #include "Image.h"43 #include "MIMETypeRegistry.h"44 #include "NotImplemented.h"45 #include "Page.h"46 37 #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 38 #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 39 63 40 namespace WebCore { 64 41 65 using namespace HTMLNames; 66 67 // We provide the IE clipboard types (URL and Text), and the clipboard types specified 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, ClipboardDataTypeText, 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& title, 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 = fsPathMaxLengthExcludingNullTerminator - extensionLen; 115 116 if (!title.isEmpty()) { 117 size_t len = min<size_t>(title.length(), fsPathMaxLengthExcludingExtension); 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 last 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.length()); 133 CopyMemory(fsPathBuffer, lastComponent.characters(), len * sizeof(UChar)); 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, SharedBuffer* 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, extension) == -1) 206 return 0; 207 if (!::PathFileExists(filePath)) 208 break; 209 } 210 HANDLE tempFileHandle = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 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().suggestedFilename() : title; 256 String extension = image->image()->filenameExtension(); 257 if (extension.isEmpty()) { 258 // Do not continue processing in the rare and unusual case where a decoded image is not able 259 // to provide a filename extension. Something tricky (like a bait-n-switch) is going on 260 return 0; 261 } 262 extension.insert(".", 0); 263 fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.charactersWithNullTermination(), 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 * sizeof(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 fileDescriptor, 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(), policy, frame); 328 return ClipboardWin::create(DragAndDrop, dragData->dragDataMap(), policy, frame); 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& dataMap, 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 withPlainText, 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/5015941> 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::clearData() 427 { 428 // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> 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::DoNotConvertFilenames) : getURL(&m_dragDataMap, DragData::DoNotConvertFilenames); 448 else if (dataType == ClipboardDataTypeTextHTML) { 449 String data = m_dataObject ? getTextHTML(m_dataObject.get()) : getTextHTML(&m_dragDataMap); 450 if (!data.isEmpty()) 451 return data; 452 return m_dataObject ? getCFHTML(m_dataObject.get()) : getCFHTML(&m_dragDataMap); 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/5015941> 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(ParsedURLString, 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, TRUE))) { 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 == urlWFormat()->cfFormat) { 491 results.add("URL"); 492 results.add("text/uri-list"); 493 } 494 495 if (format.cfFormat == plainTextWFormat()->cfFormat || format.cfFormat == plainTextFormat()->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_dragDataMap.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 USE(CF) 539 RefPtr<FileList> files = FileList::create(); 540 if (!canReadData()) 541 return files.release(); 542 543 if (!m_dataObject && m_dragDataMap.isEmpty()) 544 return files.release(); 545 546 if (m_dataObject) { 547 STGMEDIUM medium; 548 if (FAILED(m_dataObject->GetData(cfHDropFormat(), &medium))) 549 return files.release(); 550 551 HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal)); 552 if (!hdrop) 553 return files.release(); 554 555 WCHAR filename[MAX_PATH]; 556 UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); 557 for (UINT i = 0; i < fileCount; i++) { 558 if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename))) 559 continue; 560 files->append(File::create(reinterpret_cast<UChar*>(filename), File::AllContentTypes)); 561 } 562 563 GlobalUnlock(medium.hGlobal); 564 ReleaseStgMedium(&medium); 565 return files.release(); 566 } 567 if (!m_dragDataMap.contains(cfHDropFormat()->cfFormat)) 568 return files.release(); 569 Vector<String> filesVector = m_dragDataMap.get(cfHDropFormat()->cfFormat); 570 for (Vector<String>::iterator it = filesVector.begin(); it != filesVector.end(); ++it) 571 files->append(File::create(*it)); 572 return files.release(); 573 #else 574 notImplemented(); 575 return 0; 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 42 DragImageRef Clipboard::createDragImage(IntPoint& dragLocation) const 605 43 { 606 44 HBITMAP result = 0; … … 608 46 #if USE(CAIRO) || USE(CG) 609 47 result = createDragImageFromImage(m_dragImage->image()); 610 loc= m_dragLoc;48 dragLocation = m_dragLoc; 611 49 #else 612 50 notImplemented(); … … 615 53 Node* node = m_dragImageElement.get(); 616 54 result = node->document()->frame()->nodeImage(node); 617 loc= m_dragLoc;55 dragLocation = m_dragLoc; 618 56 } 619 57 return result; 620 58 } 621 59 622 static CachedImage* getCachedImage(Element* element) 623 { 624 // Attempt to pull CachedImage from element 625 ASSERT(element); 626 RenderObject* renderer = element->renderer(); 627 if (!renderer || !renderer->isImage()) 628 return 0; 629 630 RenderImage* image = toRenderImage(renderer); 631 if (image->cachedImage() && !image->cachedImage()->errorOccurred()) 632 return image->cachedImage(); 633 634 return 0; 635 } 636 637 static void writeImageToDataObject(IDataObject* dataObject, Element* element, const KURL& url) 638 { 639 // Shove image data into a DataObject for use as a file 640 CachedImage* cachedImage = getCachedImage(element); 641 if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded()) 642 return; 643 644 SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer())->data(); 645 if (!imageBuffer || !imageBuffer->size()) 646 return; 647 648 HGLOBAL imageFileDescriptor = createGlobalImageFileDescriptor(url.string(), element->getAttribute(altAttr), cachedImage); 649 if (!imageFileDescriptor) 650 return; 651 652 HGLOBAL imageFileContent = createGlobalImageFileContent(imageBuffer); 653 if (!imageFileContent) { 654 GlobalFree(imageFileDescriptor); 655 return; 656 } 657 658 String fileName = cachedImage->response().suggestedFilename(); 659 HGLOBAL hDropContent = createGlobalHDropContent(url, fileName, imageBuffer); 660 if (!hDropContent) { 661 GlobalFree(hDropContent); 662 return; 663 } 664 665 writeFileToDataObject(dataObject, imageFileDescriptor, imageFileContent, hDropContent); 666 } 667 668 void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame) 60 void Clipboard::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame) 669 61 { 670 62 // Order is important here for Explorer's sake 671 if (!m_writableDataObject) 672 return; 673 WebCore::writeURL(m_writableDataObject.get(), url, title, true, false); 674 675 writeImageToDataObject(m_writableDataObject.get(), element, url); 676 677 AtomicString imageURL = element->getAttribute(srcAttr); 63 if (!m_pasteboard->writableDataObject()) 64 return; 65 m_pasteboard->writeURLToWritableDataObject(url, title); 66 m_pasteboard->writeImageToDataObject(element, url); 67 AtomicString imageURL = element->getAttribute(HTMLNames::srcAttr); 678 68 if (imageURL.isEmpty()) 679 69 return; … … 689 79 markupToCFHTML(createMarkup(element, IncludeNode, 0, ResolveAllURLs), "", data); 690 80 medium.hGlobal = createGlobalData(data); 691 if (medium.hGlobal && FAILED(m_ writableDataObject->SetData(htmlFormat(), &medium, TRUE)))81 if (medium.hGlobal && FAILED(m_pasteboard->writableDataObject()->SetData(htmlFormat(), &medium, TRUE))) 692 82 ::GlobalFree(medium.hGlobal); 693 83 } 694 84 695 void ClipboardWin::writeURL(const KURL& kurl, const String& titleStr, Frame*)696 {697 if (!m_writableDataObject)698 return;699 WebCore::writeURL(m_writableDataObject.get(), kurl, titleStr, true, true);700 701 String url = kurl.string();702 ASSERT(url.containsOnlyASCII()); // KURL::string() is URL encoded.703 704 String fsPath = filesystemPathFromUrlOrTitle(url, titleStr, L".URL", true);705 String contentString("[InternetShortcut]\r\nURL=" + url + "\r\n");706 CString content = contentString.latin1();707 708 if (fsPath.length() <= 0)709 return;710 711 HGLOBAL urlFileDescriptor = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));712 if (!urlFileDescriptor)713 return;714 715 HGLOBAL urlFileContent = GlobalAlloc(GPTR, content.length());716 if (!urlFileContent) {717 GlobalFree(urlFileDescriptor);718 return;719 }720 721 FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(urlFileDescriptor));722 ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR));723 fgd->cItems = 1;724 fgd->fgd[0].dwFlags = FD_FILESIZE;725 fgd->fgd[0].nFileSizeLow = content.length();726 727 unsigned maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName));728 CopyMemory(fgd->fgd[0].cFileName, fsPath.characters(), maxSize * sizeof(UChar));729 GlobalUnlock(urlFileDescriptor);730 731 char* fileContents = static_cast<char*>(GlobalLock(urlFileContent));732 CopyMemory(fileContents, content.data(), content.length());733 GlobalUnlock(urlFileContent);734 735 writeFileToDataObject(m_writableDataObject.get(), urlFileDescriptor, urlFileContent, 0);736 }737 738 void ClipboardWin::writeRange(Range* selectedRange, Frame* frame)739 {740 ASSERT(selectedRange);741 if (!m_writableDataObject)742 return;743 744 STGMEDIUM medium = {0};745 medium.tymed = TYMED_HGLOBAL;746 747 Vector<char> data;748 markupToCFHTML(createMarkup(selectedRange, 0, AnnotateForInterchange),749 selectedRange->startContainer()->document()->url().string(), data);750 medium.hGlobal = createGlobalData(data);751 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE)))752 ::GlobalFree(medium.hGlobal);753 754 String str = frame->editor().selectedTextForClipboard();755 replaceNewlinesWithWindowsStyleNewlines(str);756 replaceNBSPWithSpace(str);757 medium.hGlobal = createGlobalData(str);758 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE)))759 ::GlobalFree(medium.hGlobal);760 761 medium.hGlobal = 0;762 if (frame->editor().canSmartCopyOrDelete())763 m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE);764 }765 766 void ClipboardWin::writePlainText(const String& text)767 {768 if (!m_writableDataObject)769 return;770 771 STGMEDIUM medium = {0};772 medium.tymed = TYMED_HGLOBAL;773 774 String str = text;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 }783 784 bool ClipboardWin::hasData()785 {786 if (!m_dataObject && m_dragDataMap.isEmpty())787 return false;788 789 if (m_dataObject) {790 COMPtr<IEnumFORMATETC> itr;791 if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))792 return false;793 794 if (!itr)795 return false;796 797 FORMATETC data;798 799 // IEnumFORMATETC::Next returns S_FALSE if there are no more items.800 if (itr->Next(1, &data, 0) == S_OK) {801 // There is at least one item in the IDataObject802 return true;803 }804 805 return false;806 }807 return !m_dragDataMap.isEmpty();808 }809 810 void ClipboardWin::setExternalDataObject(IDataObject *dataObject)811 {812 ASSERT(isForDragAndDrop());813 814 m_writableDataObject = 0;815 m_dataObject = dataObject;816 }817 818 85 } // namespace WebCore -
trunk/Source/WebCore/platform/win/EditorWin.cpp
r144911 r150772 26 26 #include "config.h" 27 27 #include "Editor.h" 28 29 #include "COMPtr.h" 30 #include "Clipboard.h" 31 #include "Document.h" 28 32 #include "EditorClient.h" 29 30 #include "ClipboardWin.h"31 #include "Document.h"32 33 #include "Element.h" 33 34 #include "Frame.h" 34 #include " htmlediting.h"35 #include "Pasteboard.h" 35 36 #include "TextIterator.h" 36 37 #include "VisibleUnits.h" 38 #include "htmlediting.h" 37 39 38 40 #include <windows.h> … … 47 49 clipboardData = 0; 48 50 #endif 49 50 return ClipboardWin::create(Clipboard::CopyAndPaste, clipboardData.get(), policy, frame); 51 RefPtr<Clipboard> clipboard = Clipboard::createForCopyAndPaste(policy); 52 const_cast<Pasteboard&>(clipboard->pasteboard()).setExternalDataObject(clipboardData.get()); 53 return clipboard.release(); 51 54 } 52 55 -
trunk/Source/WebCore/platform/win/PasteboardWin.cpp
r150140 r150772 1 1 /* 2 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2013 Xueqing Huang <huangxueqing@baidu.com> 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 35 36 #include "Element.h" 36 37 #include "Frame.h" 38 #include "HTMLNames.h" 39 #include "HTMLParserIdioms.h" 37 40 #include "HWndDC.h" 38 41 #include "HitTestResult.h" … … 43 46 #include "Range.h" 44 47 #include "RenderImage.h" 48 #include "SharedBuffer.h" 45 49 #include "TextEncoding.h" 46 50 #include "WebCoreInstanceHandle.h" … … 50 54 51 55 namespace WebCore { 56 57 // We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft 58 // see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3 52 59 53 60 static UINT HTMLClipboardFormat = 0; … … 90 97 } 91 98 92 Pasteboard::Pasteboard() 99 PassOwnPtr<Pasteboard> Pasteboard::createForCopyAndPaste() 100 { 101 return adoptPtr(new Pasteboard); 102 } 103 104 PassOwnPtr<Pasteboard> Pasteboard::createPrivate() 105 { 106 // Windows has no "Private pasteboard" concept. 107 return createForCopyAndPaste(); 108 } 109 110 #if ENABLE(DRAG_SUPPORT) 111 PassOwnPtr<Pasteboard> Pasteboard::createForDragAndDrop() 112 { 113 COMPtr<WCDataObject> dataObject; 114 WCDataObject::createInstance(&dataObject); 115 return adoptPtr(new Pasteboard(dataObject.get())); 116 } 117 118 // static 119 PassOwnPtr<Pasteboard> Pasteboard::createForDragAndDrop(const DragData& dragData) 120 { 121 if (dragData.platformData()) 122 return adoptPtr(new Pasteboard(dragData.platformData())); 123 // FIXME: Should add a const overload of dragDataMap so we don't need a const_cast here. 124 return adoptPtr(new Pasteboard(const_cast<DragData&>(dragData).dragDataMap())); 125 } 126 #endif 127 128 void Pasteboard::finishCreatingPasteboard() 93 129 { 94 130 WNDCLASS wc; … … 107 143 } 108 144 145 Pasteboard::Pasteboard() 146 : m_dataObject(0) 147 , m_writableDataObject(0) 148 { 149 finishCreatingPasteboard(); 150 } 151 152 Pasteboard::Pasteboard(IDataObject* dataObject) 153 : m_dataObject(dataObject) 154 , m_writableDataObject(0) 155 { 156 finishCreatingPasteboard(); 157 } 158 159 Pasteboard::Pasteboard(WCDataObject* dataObject) 160 : m_dataObject(dataObject) 161 , m_writableDataObject(dataObject) 162 { 163 finishCreatingPasteboard(); 164 } 165 166 Pasteboard::Pasteboard(const DragDataMap& dataMap) 167 : m_dataObject(0) 168 , m_writableDataObject(0) 169 , m_dragDataMap(dataMap) 170 { 171 finishCreatingPasteboard(); 172 } 173 109 174 void Pasteboard::clear() 110 175 { … … 113 178 ::CloseClipboard(); 114 179 } 180 } 181 182 enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardDataTypeText, ClipboardDataTypeTextHTML }; 183 184 static ClipboardDataType clipboardTypeFromMIMEType(const String& type) 185 { 186 String qType = type.stripWhiteSpace().lower(); 187 188 // two special cases for IE compatibility 189 if (qType == "text" || qType == "text/plain" || qType.startsWith("text/plain;")) 190 return ClipboardDataTypeText; 191 if (qType == "url" || qType == "text/uri-list") 192 return ClipboardDataTypeURL; 193 if (qType == "text/html") 194 return ClipboardDataTypeTextHTML; 195 196 return ClipboardDataTypeNone; 197 } 198 199 void Pasteboard::clear(const String& type) 200 { 201 if (!m_writableDataObject) 202 return; 203 204 ClipboardDataType dataType = clipboardTypeFromMIMEType(type); 205 206 if (dataType == ClipboardDataTypeURL) { 207 m_writableDataObject->clearData(urlWFormat()->cfFormat); 208 m_writableDataObject->clearData(urlFormat()->cfFormat); 209 } 210 if (dataType == ClipboardDataTypeText) { 211 m_writableDataObject->clearData(plainTextFormat()->cfFormat); 212 m_writableDataObject->clearData(plainTextWFormat()->cfFormat); 213 } 214 } 215 216 bool Pasteboard::hasData() 217 { 218 if (!m_dataObject && m_dragDataMap.isEmpty()) 219 return false; 220 221 if (m_dataObject) { 222 COMPtr<IEnumFORMATETC> itr; 223 if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr))) 224 return false; 225 226 if (!itr) 227 return false; 228 229 FORMATETC data; 230 231 // IEnumFORMATETC::Next returns S_FALSE if there are no more items. 232 if (itr->Next(1, &data, 0) == S_OK) { 233 // There is at least one item in the IDataObject 234 return true; 235 } 236 237 return false; 238 } 239 return !m_dragDataMap.isEmpty(); 240 } 241 242 static void addMimeTypesForFormat(ListHashSet<String>& results, const FORMATETC& format) 243 { 244 // URL and Text are provided for compatibility with IE's model 245 if (format.cfFormat == urlFormat()->cfFormat || format.cfFormat == urlWFormat()->cfFormat) { 246 results.add("URL"); 247 results.add("text/uri-list"); 248 } 249 250 if (format.cfFormat == plainTextWFormat()->cfFormat || format.cfFormat == plainTextFormat()->cfFormat) { 251 results.add("Text"); 252 results.add("text/plain"); 253 } 254 } 255 256 ListHashSet<String> Pasteboard::types() 257 { 258 ListHashSet<String> results; 259 260 if (!m_dataObject && m_dragDataMap.isEmpty()) 261 return results; 262 263 if (m_dataObject) { 264 COMPtr<IEnumFORMATETC> itr; 265 266 if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr))) 267 return results; 268 269 if (!itr) 270 return results; 271 272 FORMATETC data; 273 274 // IEnumFORMATETC::Next returns S_FALSE if there are no more items. 275 while (itr->Next(1, &data, 0) == S_OK) 276 addMimeTypesForFormat(results, data); 277 } else { 278 for (DragDataMap::const_iterator it = m_dragDataMap.begin(); it != m_dragDataMap.end(); ++it) { 279 FORMATETC data; 280 data.cfFormat = (*it).key; 281 addMimeTypesForFormat(results, data); 282 } 283 } 284 285 return results; 286 } 287 288 String Pasteboard::readString(const String& type) 289 { 290 if (!m_dataObject && m_dragDataMap.isEmpty()) 291 return ""; 292 293 ClipboardDataType dataType = clipboardTypeFromMIMEType(type); 294 if (dataType == ClipboardDataTypeText) 295 return m_dataObject ? getPlainText(m_dataObject.get()) : getPlainText(&m_dragDataMap); 296 if (dataType == ClipboardDataTypeURL) 297 return m_dataObject ? getURL(m_dataObject.get(), DragData::DoNotConvertFilenames) : getURL(&m_dragDataMap, DragData::DoNotConvertFilenames); 298 if (dataType == ClipboardDataTypeTextHTML) { 299 String data = m_dataObject ? getTextHTML(m_dataObject.get()) : getTextHTML(&m_dragDataMap); 300 if (!data.isEmpty()) 301 return data; 302 return m_dataObject ? getCFHTML(m_dataObject.get()) : getCFHTML(&m_dragDataMap); 303 } 304 305 return ""; 306 } 307 308 Vector<String> Pasteboard::readFilenames() 309 { 310 #if USE(CF) 311 Vector<String> fileNames; 312 313 if (m_dataObject) { 314 STGMEDIUM medium; 315 if (FAILED(m_dataObject->GetData(cfHDropFormat(), &medium))) 316 return fileNames; 317 318 HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal)); 319 if (!hdrop) 320 return fileNames; 321 322 WCHAR filename[MAX_PATH]; 323 UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); 324 for (UINT i = 0; i < fileCount; i++) { 325 if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename))) 326 continue; 327 fileNames.append(filename); 328 } 329 330 GlobalUnlock(medium.hGlobal); 331 ReleaseStgMedium(&medium); 332 return fileNames; 333 } 334 if (!m_dragDataMap.contains(cfHDropFormat()->cfFormat)) 335 return fileNames; 336 return m_dragDataMap.get(cfHDropFormat()->cfFormat); 337 #else 338 notImplemented(); 339 return 0; 340 #endif 341 } 342 343 static bool writeURL(WCDataObject *data, const KURL& url, String title, bool withPlainText, bool withHTML) 344 { 345 ASSERT(data); 346 347 if (url.isEmpty()) 348 return false; 349 350 if (title.isEmpty()) { 351 title = url.lastPathComponent(); 352 if (title.isEmpty()) 353 title = url.host(); 354 } 355 356 STGMEDIUM medium = {0}; 357 medium.tymed = TYMED_HGLOBAL; 358 359 medium.hGlobal = createGlobalData(url, title); 360 bool success = false; 361 if (medium.hGlobal && FAILED(data->SetData(urlWFormat(), &medium, TRUE))) 362 ::GlobalFree(medium.hGlobal); 363 else 364 success = true; 365 366 if (withHTML) { 367 Vector<char> cfhtmlData; 368 markupToCFHTML(urlToMarkup(url, title), "", cfhtmlData); 369 medium.hGlobal = createGlobalData(cfhtmlData); 370 if (medium.hGlobal && FAILED(data->SetData(htmlFormat(), &medium, TRUE))) 371 ::GlobalFree(medium.hGlobal); 372 else 373 success = true; 374 } 375 376 if (withPlainText) { 377 medium.hGlobal = createGlobalData(url.string()); 378 if (medium.hGlobal && FAILED(data->SetData(plainTextWFormat(), &medium, TRUE))) 379 ::GlobalFree(medium.hGlobal); 380 else 381 success = true; 382 } 383 384 return success; 385 } 386 387 bool Pasteboard::writeString(const String& type, const String& data) 388 { 389 if (!m_writableDataObject) 390 return false; 391 392 ClipboardDataType winType = clipboardTypeFromMIMEType(type); 393 394 if (winType == ClipboardDataTypeURL) 395 return WebCore::writeURL(m_writableDataObject.get(), KURL(KURL(), data), String(), false, true); 396 397 if (winType == ClipboardDataTypeText) { 398 STGMEDIUM medium = {0}; 399 medium.tymed = TYMED_HGLOBAL; 400 medium.hGlobal = createGlobalData(data); 401 if (!medium.hGlobal) 402 return false; 403 404 if (FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE))) { 405 ::GlobalFree(medium.hGlobal); 406 return false; 407 } 408 return true; 409 } 410 411 return false; 412 } 413 414 void Pasteboard::setDragImage(DragImageRef, const IntPoint&) 415 { 416 // Do nothing in Windows. 417 } 418 419 void Pasteboard::writeRangeToDataObject(Range* selectedRange, Frame* frame) 420 { 421 ASSERT(selectedRange); 422 if (!m_writableDataObject) 423 return; 424 425 STGMEDIUM medium = {0}; 426 medium.tymed = TYMED_HGLOBAL; 427 428 Vector<char> data; 429 markupToCFHTML(createMarkup(selectedRange, 0, AnnotateForInterchange), 430 selectedRange->startContainer()->document()->url().string(), data); 431 medium.hGlobal = createGlobalData(data); 432 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE))) 433 ::GlobalFree(medium.hGlobal); 434 435 String str = frame->editor().selectedTextForClipboard(); 436 replaceNewlinesWithWindowsStyleNewlines(str); 437 replaceNBSPWithSpace(str); 438 medium.hGlobal = createGlobalData(str); 439 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE))) 440 ::GlobalFree(medium.hGlobal); 441 442 medium.hGlobal = 0; 443 if (frame->editor().canSmartCopyOrDelete()) 444 m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE); 115 445 } 116 446 … … 147 477 ::CloseClipboard(); 148 478 } 149 150 } 479 } 480 481 writeRangeToDataObject(selectedRange, frame); 482 } 483 484 void Pasteboard::writePlainTextToDataObject(const String& text, SmartReplaceOption smartReplaceOption) 485 { 486 if (!m_writableDataObject) 487 return; 488 489 STGMEDIUM medium = {0}; 490 medium.tymed = TYMED_HGLOBAL; 491 492 String str = text; 493 replaceNewlinesWithWindowsStyleNewlines(str); 494 replaceNBSPWithSpace(str); 495 medium.hGlobal = createGlobalData(str); 496 if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE))) 497 ::GlobalFree(medium.hGlobal); 498 499 medium.hGlobal = 0; 151 500 } 152 501 … … 172 521 } 173 522 } 523 524 writePlainTextToDataObject(text, smartReplaceOption); 525 } 526 527 #if !OS(WINCE) 528 static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length) 529 { 530 size_t writeTo = 0; 531 size_t readFrom = 0; 532 while (readFrom < length) { 533 UINT type = PathGetCharType(psz[readFrom]); 534 if (!psz[readFrom] || type & (GCT_LFNCHAR | GCT_SHORTCHAR)) 535 psz[writeTo++] = psz[readFrom]; 536 537 readFrom++; 538 } 539 psz[writeTo] = 0; 540 } 541 #endif 542 543 static String filesystemPathFromUrlOrTitle(const String& url, const String& title, const UChar* extension, bool isLink) 544 { 545 #if OS(WINCE) 546 notImplemented(); 547 return String(); 548 #else 549 static const size_t fsPathMaxLengthExcludingNullTerminator = MAX_PATH - 1; 550 bool usedURL = false; 551 WCHAR fsPathBuffer[MAX_PATH]; 552 fsPathBuffer[0] = 0; 553 int extensionLen = extension ? lstrlen(extension) : 0; 554 int fsPathMaxLengthExcludingExtension = fsPathMaxLengthExcludingNullTerminator - extensionLen; 555 556 if (!title.isEmpty()) { 557 size_t len = std::min<size_t>(title.length(), fsPathMaxLengthExcludingExtension); 558 CopyMemory(fsPathBuffer, title.characters(), len * sizeof(UChar)); 559 fsPathBuffer[len] = 0; 560 pathRemoveBadFSCharacters(fsPathBuffer, len); 561 } 562 563 if (!lstrlen(fsPathBuffer)) { 564 KURL kurl(KURL(), url); 565 usedURL = true; 566 // The filename for any content based drag or file url should be the last element of 567 // the path. If we can't find it, or we're coming up with the name for a link 568 // we just use the entire url. 569 DWORD len = fsPathMaxLengthExcludingExtension; 570 String lastComponent = kurl.lastPathComponent(); 571 if (kurl.isLocalFile() || (!isLink && !lastComponent.isEmpty())) { 572 len = std::min<DWORD>(fsPathMaxLengthExcludingExtension, lastComponent.length()); 573 CopyMemory(fsPathBuffer, lastComponent.characters(), len * sizeof(UChar)); 574 } else { 575 len = std::min<DWORD>(fsPathMaxLengthExcludingExtension, url.length()); 576 CopyMemory(fsPathBuffer, url.characters(), len * sizeof(UChar)); 577 } 578 fsPathBuffer[len] = 0; 579 pathRemoveBadFSCharacters(fsPathBuffer, len); 580 } 581 582 if (!extension) 583 return String(static_cast<UChar*>(fsPathBuffer)); 584 585 if (!isLink && usedURL) { 586 PathRenameExtension(fsPathBuffer, extension); 587 return String(static_cast<UChar*>(fsPathBuffer)); 588 } 589 590 return makeString(static_cast<const UChar*>(fsPathBuffer), extension); 591 #endif 592 } 593 594 // writeFileToDataObject takes ownership of fileDescriptor and fileContent 595 static HRESULT writeFileToDataObject(IDataObject* dataObject, HGLOBAL fileDescriptor, HGLOBAL fileContent, HGLOBAL hDropContent) 596 { 597 HRESULT hr = S_OK; 598 FORMATETC* fe; 599 STGMEDIUM medium = {0}; 600 medium.tymed = TYMED_HGLOBAL; 601 602 if (!fileDescriptor || !fileContent) 603 goto exit; 604 605 // Descriptor 606 fe = fileDescriptorFormat(); 607 608 medium.hGlobal = fileDescriptor; 609 610 if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE))) 611 goto exit; 612 613 // Contents 614 fe = fileContentFormatZero(); 615 medium.hGlobal = fileContent; 616 if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE))) 617 goto exit; 618 619 #if USE(CF) 620 // HDROP 621 if (hDropContent) { 622 medium.hGlobal = hDropContent; 623 hr = dataObject->SetData(cfHDropFormat(), &medium, TRUE); 624 } 625 #endif 626 627 exit: 628 if (FAILED(hr)) { 629 if (fileDescriptor) 630 GlobalFree(fileDescriptor); 631 if (fileContent) 632 GlobalFree(fileContent); 633 if (hDropContent) 634 GlobalFree(hDropContent); 635 } 636 return hr; 637 } 638 639 void Pasteboard::writeURLToDataObject(const KURL& kurl, const String& titleStr, Frame* frame) 640 { 641 if (!m_writableDataObject) 642 return; 643 WebCore::writeURL(m_writableDataObject.get(), kurl, titleStr, true, true); 644 645 String url = kurl.string(); 646 ASSERT(url.containsOnlyASCII()); // KURL::string() is URL encoded. 647 648 String fsPath = filesystemPathFromUrlOrTitle(url, titleStr, L".URL", true); 649 String contentString("[InternetShortcut]\r\nURL=" + url + "\r\n"); 650 CString content = contentString.latin1(); 651 652 if (fsPath.length() <= 0) 653 return; 654 655 HGLOBAL urlFileDescriptor = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); 656 if (!urlFileDescriptor) 657 return; 658 659 HGLOBAL urlFileContent = GlobalAlloc(GPTR, content.length()); 660 if (!urlFileContent) { 661 GlobalFree(urlFileDescriptor); 662 return; 663 } 664 665 FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(urlFileDescriptor)); 666 ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR)); 667 fgd->cItems = 1; 668 fgd->fgd[0].dwFlags = FD_FILESIZE; 669 fgd->fgd[0].nFileSizeLow = content.length(); 670 671 unsigned maxSize = std::min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName)); 672 CopyMemory(fgd->fgd[0].cFileName, fsPath.characters(), maxSize * sizeof(UChar)); 673 GlobalUnlock(urlFileDescriptor); 674 675 char* fileContents = static_cast<char*>(GlobalLock(urlFileContent)); 676 CopyMemory(fileContents, content.data(), content.length()); 677 GlobalUnlock(urlFileContent); 678 679 writeFileToDataObject(m_writableDataObject.get(), urlFileDescriptor, urlFileContent, 0); 174 680 } 175 681 … … 212 718 ::CloseClipboard(); 213 719 } 720 721 writeURLToDataObject(url, titleStr, frame); 214 722 } 215 723 … … 255 763 ::CloseClipboard(); 256 764 } 765 } 766 767 void Pasteboard::writePasteboard(const Pasteboard& sourcePasteboard) 768 { 769 notImplemented(); 257 770 } 258 771 … … 353 866 } 354 867 868 void Pasteboard::setExternalDataObject(IDataObject *dataObject) 869 { 870 m_writableDataObject = 0; 871 m_dataObject = dataObject; 872 } 873 874 static CachedImage* getCachedImage(Element* element) 875 { 876 // Attempt to pull CachedImage from element 877 ASSERT(element); 878 RenderObject* renderer = element->renderer(); 879 if (!renderer || !renderer->isImage()) 880 return 0; 881 882 RenderImage* image = toRenderImage(renderer); 883 if (image->cachedImage() && !image->cachedImage()->errorOccurred()) 884 return image->cachedImage(); 885 886 return 0; 887 } 888 889 static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& title, CachedImage* image) 890 { 891 ASSERT_ARG(image, image); 892 ASSERT(image->image()->data()); 893 894 HRESULT hr = S_OK; 895 HGLOBAL memObj = 0; 896 String fsPath; 897 memObj = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); 898 if (!memObj) 899 return 0; 900 901 FILEGROUPDESCRIPTOR* fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(memObj); 902 memset(fgd, 0, sizeof(FILEGROUPDESCRIPTOR)); 903 fgd->cItems = 1; 904 fgd->fgd[0].dwFlags = FD_FILESIZE; 905 fgd->fgd[0].nFileSizeLow = image->image()->data()->size(); 906 907 const String& preferredTitle = title.isEmpty() ? image->response().suggestedFilename() : title; 908 String extension = image->image()->filenameExtension(); 909 if (extension.isEmpty()) { 910 // Do not continue processing in the rare and unusual case where a decoded image is not able 911 // to provide a filename extension. Something tricky (like a bait-n-switch) is going on 912 return 0; 913 } 914 extension.insert(".", 0); 915 fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.charactersWithNullTermination(), false); 916 917 if (fsPath.length() <= 0) { 918 GlobalUnlock(memObj); 919 GlobalFree(memObj); 920 return 0; 921 } 922 923 int maxSize = std::min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName)); 924 CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * sizeof(UChar)); 925 GlobalUnlock(memObj); 926 927 return memObj; 928 } 929 930 static HGLOBAL createGlobalImageFileContent(SharedBuffer* data) 931 { 932 HGLOBAL memObj = GlobalAlloc(GPTR, data->size()); 933 if (!memObj) 934 return 0; 935 936 char* fileContents = (PSTR)GlobalLock(memObj); 937 938 CopyMemory(fileContents, data->data(), data->size()); 939 940 GlobalUnlock(memObj); 941 942 return memObj; 943 } 944 945 static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, SharedBuffer* data) 946 { 947 if (fileName.isEmpty() || !data) 948 return 0; 949 950 WCHAR filePath[MAX_PATH]; 951 952 if (url.isLocalFile()) { 953 String localPath = decodeURLEscapeSequences(url.path()); 954 // windows does not enjoy a leading slash on paths 955 if (localPath[0] == '/') 956 localPath = localPath.substring(1); 957 LPCWSTR localPathStr = localPath.charactersWithNullTermination(); 958 if (wcslen(localPathStr) + 1 < MAX_PATH) 959 wcscpy_s(filePath, MAX_PATH, localPathStr); 960 else 961 return 0; 962 } else { 963 #if OS(WINCE) 964 notImplemented(); 965 return 0; 966 #else 967 WCHAR tempPath[MAX_PATH]; 968 WCHAR extension[MAX_PATH]; 969 if (!::GetTempPath(WTF_ARRAY_LENGTH(tempPath), tempPath)) 970 return 0; 971 if (!::PathAppend(tempPath, fileName.charactersWithNullTermination())) 972 return 0; 973 LPCWSTR foundExtension = ::PathFindExtension(tempPath); 974 if (foundExtension) { 975 if (wcscpy_s(extension, MAX_PATH, foundExtension)) 976 return 0; 977 } else 978 *extension = 0; 979 ::PathRemoveExtension(tempPath); 980 for (int i = 1; i < 10000; i++) { 981 if (swprintf_s(filePath, MAX_PATH, TEXT("%s-%d%s"), tempPath, i, extension) == -1) 982 return 0; 983 if (!::PathFileExists(filePath)) 984 break; 985 } 986 HANDLE tempFileHandle = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 987 if (tempFileHandle == INVALID_HANDLE_VALUE) 988 return 0; 989 990 // Write the data to this temp file. 991 DWORD written; 992 BOOL tempWriteSucceeded = WriteFile(tempFileHandle, data->data(), data->size(), &written, 0); 993 CloseHandle(tempFileHandle); 994 if (!tempWriteSucceeded) 995 return 0; 996 #endif 997 } 998 999 SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (wcslen(filePath) + 2)); 1000 HGLOBAL memObj = GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize); 1001 if (!memObj) 1002 return 0; 1003 1004 DROPFILES* dropFiles = (DROPFILES*) GlobalLock(memObj); 1005 dropFiles->pFiles = sizeof(DROPFILES); 1006 dropFiles->fWide = TRUE; 1007 wcscpy((LPWSTR)(dropFiles + 1), filePath); 1008 GlobalUnlock(memObj); 1009 1010 return memObj; 1011 } 1012 1013 void Pasteboard::writeImageToDataObject(Element* element, const KURL& url) 1014 { 1015 // Shove image data into a DataObject for use as a file 1016 CachedImage* cachedImage = getCachedImage(element); 1017 if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded()) 1018 return; 1019 1020 SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer())->data(); 1021 if (!imageBuffer || !imageBuffer->size()) 1022 return; 1023 1024 HGLOBAL imageFileDescriptor = createGlobalImageFileDescriptor(url.string(), element->getAttribute(HTMLNames::altAttr), cachedImage); 1025 if (!imageFileDescriptor) 1026 return; 1027 1028 HGLOBAL imageFileContent = createGlobalImageFileContent(imageBuffer); 1029 if (!imageFileContent) { 1030 GlobalFree(imageFileDescriptor); 1031 return; 1032 } 1033 1034 String fileName = cachedImage->response().suggestedFilename(); 1035 HGLOBAL hDropContent = createGlobalHDropContent(url, fileName, imageBuffer); 1036 if (!hDropContent) { 1037 GlobalFree(hDropContent); 1038 return; 1039 } 1040 1041 writeFileToDataObject(m_writableDataObject.get(), imageFileDescriptor, imageFileContent, hDropContent); 1042 } 1043 1044 void Pasteboard::writeURLToWritableDataObject(const KURL& url, const String& title) 1045 { 1046 WebCore::writeURL(m_writableDataObject.get(), url, title, true, false); 1047 } 1048 355 1049 } // namespace WebCore -
trunk/Source/WebKit/win/ChangeLog
r150718 r150772 1 2013-05-27 Xueqing Huang <huangxueqing@baidu.com> 2 3 Move Windows port off legacy clipboard. 4 https://bugs.webkit.org/show_bug.cgi?id=116258 5 6 Reviewed by Darin Adler. 7 8 * WebCoreSupport/WebDragClient.cpp: 9 (WebDragClient::willPerformDragSourceAction): Get IDataObject from Pasteboard instead of Clipboard. 10 (WebDragClient::startDrag): Ditto. 11 1 12 2013-05-26 Antti Koivisto <antti@apple.com> 2 13 -
trunk/Source/WebKit/win/WebCoreSupport/WebDragClient.cpp
r148577 r150772 30 30 #include "WebView.h" 31 31 32 #include <shlobj.h> 33 34 #include <WebCore/ClipboardWin.h> 32 #include <WebCore/Clipboard.h> 35 33 #include <WebCore/DragController.h> 36 34 #include <WebCore/DragData.h> 37 35 #include <WebCore/EventHandler.h> 36 #include <WebCore/Page.h> 37 #include <WebCore/Pasteboard.h> 38 38 #include <WebCore/PlatformMouseEvent.h> 39 39 #include <WebCore/Frame.h> 40 40 #include <WebCore/FrameView.h> 41 41 #include <WebCore/GraphicsContext.h> 42 #include < WebCore/Page.h>42 #include <shlobj.h> 43 43 44 44 using namespace WebCore; … … 104 104 105 105 POINT point = intPoint; 106 COMPtr<IDataObject> dataObject = static_cast<ClipboardWin*>(clipboard)->dataObject();106 COMPtr<IDataObject> dataObject = clipboard->pasteboard().dataObject(); 107 107 108 108 COMPtr<IDataObject> newDataObject; 109 109 HRESULT result = uiDelegate->willPerformDragSourceAction(m_webView, static_cast<WebDragSourceAction>(action), &point, dataObject.get(), &newDataObject); 110 110 if (result == S_OK && newDataObject != dataObject) 111 static_cast<ClipboardWin*>(clipboard)->setExternalDataObject(newDataObject.get());111 const_cast<Pasteboard&>(clipboard->pasteboard()).setExternalDataObject(newDataObject.get()); 112 112 } 113 113 … … 125 125 return; 126 126 127 dataObject = static_cast<ClipboardWin*>(clipboard)->dataObject();127 dataObject = clipboard->pasteboard().dataObject(); 128 128 if (source && (image || dataObject)) { 129 129 if (image) {
Note: See TracChangeset
for help on using the changeset viewer.