1/* 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2012 Baidu Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "DragData.h" 29 30#include "COMPtr.h" 31#include "ClipboardUtilitiesWin.h" 32#include "Frame.h" 33#include "DocumentFragment.h" 34#include "Markup.h" 35#include "Range.h" 36#include "TextEncoding.h" 37#include <objidl.h> 38#include <shlwapi.h> 39#include <wininet.h> 40#include <wtf/Forward.h> 41#include <wtf/Hashmap.h> 42#include <wtf/PassRefPtr.h> 43#include <wtf/RefPtr.h> 44#include <wtf/text/WTFString.h> 45 46namespace WebCore { 47 48DragData::DragData(const DragDataMap& data, const IntPoint& clientPosition, const IntPoint& globalPosition, 49 DragOperation sourceOperationMask, DragApplicationFlags flags) 50 : m_clientPosition(clientPosition) 51 , m_globalPosition(globalPosition) 52 , m_platformDragData(0) 53 , m_draggingSourceOperationMask(sourceOperationMask) 54 , m_applicationFlags(flags) 55 , m_dragDataMap(data) 56{ 57} 58 59bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) const 60{ 61 if (m_platformDragData) 62 return SUCCEEDED(m_platformDragData->QueryGetData(urlWFormat())) 63 || SUCCEEDED(m_platformDragData->QueryGetData(urlFormat())) 64 || (filenamePolicy == ConvertFilenames 65 && (SUCCEEDED(m_platformDragData->QueryGetData(filenameWFormat())) 66 || SUCCEEDED(m_platformDragData->QueryGetData(filenameFormat())))); 67 return m_dragDataMap.contains(urlWFormat()->cfFormat) || m_dragDataMap.contains(urlFormat()->cfFormat) 68 || (filenamePolicy == ConvertFilenames && (m_dragDataMap.contains(filenameWFormat()->cfFormat) || m_dragDataMap.contains(filenameFormat()->cfFormat))); 69} 70 71const DragDataMap& DragData::dragDataMap() 72{ 73 if (!m_dragDataMap.isEmpty() || !m_platformDragData) 74 return m_dragDataMap; 75 // Enumerate clipboard content and load it in the map. 76 COMPtr<IEnumFORMATETC> itr; 77 78 if (FAILED(m_platformDragData->EnumFormatEtc(DATADIR_GET, &itr)) || !itr) 79 return m_dragDataMap; 80 81 FORMATETC dataFormat; 82 while (itr->Next(1, &dataFormat, 0) == S_OK) { 83 Vector<String> dataStrings; 84 getClipboardData(m_platformDragData, &dataFormat, dataStrings); 85 if (!dataStrings.isEmpty()) 86 m_dragDataMap.set(dataFormat.cfFormat, dataStrings); 87 } 88 return m_dragDataMap; 89} 90 91void DragData::getDragFileDescriptorData(int& size, String& pathname) 92{ 93 size = 0; 94 if (m_platformDragData) 95 getFileDescriptorData(m_platformDragData, size, pathname); 96} 97 98void DragData::getDragFileContentData(int size, void* dataBlob) 99{ 100 if (m_platformDragData) 101 getFileContentData(m_platformDragData, size, dataBlob); 102} 103 104String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const 105{ 106 return (m_platformDragData) ? getURL(m_platformDragData, filenamePolicy, title) : getURL(&m_dragDataMap, filenamePolicy, title); 107} 108 109bool DragData::containsFiles() const 110{ 111#if USE(CF) 112 return (m_platformDragData) ? SUCCEEDED(m_platformDragData->QueryGetData(cfHDropFormat())) : m_dragDataMap.contains(cfHDropFormat()->cfFormat); 113#else 114 return false; 115#endif 116} 117 118unsigned DragData::numberOfFiles() const 119{ 120#if USE(CF) 121 if (!m_platformDragData) 122 return 0; 123 124 STGMEDIUM medium; 125 if (FAILED(m_platformDragData->GetData(cfHDropFormat(), &medium))) 126 return 0; 127 128 HDROP hdrop = static_cast<HDROP>(GlobalLock(medium.hGlobal)); 129 130 if (!hdrop) 131 return 0; 132 133 unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); 134 135 DragFinish(hdrop); 136 GlobalUnlock(medium.hGlobal); 137 138 return numFiles; 139#else 140 return 0; 141#endif 142} 143 144void DragData::asFilenames(Vector<String>& result) const 145{ 146#if USE(CF) 147 if (m_platformDragData) { 148 WCHAR filename[MAX_PATH]; 149 150 STGMEDIUM medium; 151 if (FAILED(m_platformDragData->GetData(cfHDropFormat(), &medium))) 152 return; 153 154 HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal)); 155 156 if (!hdrop) 157 return; 158 159 const unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); 160 for (unsigned i = 0; i < numFiles; i++) { 161 if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename))) 162 continue; 163 result.append(static_cast<UChar*>(filename)); 164 } 165 166 // Free up memory from drag 167 DragFinish(hdrop); 168 169 GlobalUnlock(medium.hGlobal); 170 return; 171 } 172 result = m_dragDataMap.get(cfHDropFormat()->cfFormat); 173#endif 174} 175 176bool DragData::containsPlainText() const 177{ 178 if (m_platformDragData) 179 return SUCCEEDED(m_platformDragData->QueryGetData(plainTextWFormat())) 180 || SUCCEEDED(m_platformDragData->QueryGetData(plainTextFormat())); 181 return m_dragDataMap.contains(plainTextWFormat()->cfFormat) || m_dragDataMap.contains(plainTextFormat()->cfFormat); 182} 183 184String DragData::asPlainText(Frame*) const 185{ 186 return (m_platformDragData) ? getPlainText(m_platformDragData) : getPlainText(&m_dragDataMap); 187} 188 189bool DragData::containsColor() const 190{ 191 return false; 192} 193 194bool DragData::canSmartReplace() const 195{ 196 if (m_platformDragData) 197 return SUCCEEDED(m_platformDragData->QueryGetData(smartPasteFormat())); 198 return m_dragDataMap.contains(smartPasteFormat()->cfFormat); 199} 200 201bool DragData::containsCompatibleContent() const 202{ 203 return containsPlainText() || containsURL(0) 204 || ((m_platformDragData) ? (containsHTML(m_platformDragData) || containsFilenames(m_platformDragData)) 205 : (containsHTML(&m_dragDataMap) || containsFilenames(&m_dragDataMap))) 206 || containsColor(); 207} 208 209PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, Range&, bool, bool&) const 210{ 211 /* 212 * Order is richest format first. On OSX this is: 213 * * Web Archive 214 * * Filenames 215 * * HTML 216 * * RTF 217 * * TIFF 218 * * PICT 219 */ 220 221 if (m_platformDragData) { 222 if (containsFilenames(m_platformDragData)) { 223 if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), m_platformDragData)) 224 return fragment; 225 } 226 227 if (containsHTML(m_platformDragData)) { 228 if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), m_platformDragData)) 229 return fragment; 230 } 231 } else { 232 if (containsFilenames(&m_dragDataMap)) { 233 if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), &m_dragDataMap)) 234 return fragment; 235 } 236 237 if (containsHTML(&m_dragDataMap)) { 238 if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), &m_dragDataMap)) 239 return fragment; 240 } 241 } 242 return 0; 243} 244 245Color DragData::asColor() const 246{ 247 return Color(); 248} 249 250} 251