1 /* 2 * Copyright (C) 2007, 2008 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 "DragData.h" 28 29 #include "COMPtr.h" 30 #include "ClipboardUtilitiesWin.h" 31 #include "Frame.h" 32 #include "DocumentFragment.h" 33 #include "PlatformString.h" 34 #include "Markup.h" 35 #include "TextEncoding.h" 36 #include <objidl.h> 37 #include <shlwapi.h> 38 #include <wininet.h> 39 #include <wtf/Forward.h> 40 #include <wtf/Hashmap.h> 41 #include <wtf/PassRefPtr.h> 42 #include <wtf/RefPtr.h> 43 44 namespace WebCore { 45 46 DragData::DragData(const DragDataMap& data, const IntPoint& clientPosition, const IntPoint& globalPosition, 47 DragOperation sourceOperationMask, DragApplicationFlags flags) 48 : m_clientPosition(clientPosition) 49 , m_globalPosition(globalPosition) 50 , m_platformDragData(0) 51 , m_draggingSourceOperationMask(sourceOperationMask) 52 , m_applicationFlags(flags) 53 , m_dragDataMap(data) 54 { 55 } 56 57 bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) const 58 { 59 if (m_platformDragData) 60 return SUCCEEDED(m_platformDragData->QueryGetData(urlWFormat())) 61 || SUCCEEDED(m_platformDragData->QueryGetData(urlFormat())) 62 || (filenamePolicy == ConvertFilenames 63 && (SUCCEEDED(m_platformDragData->QueryGetData(filenameWFormat())) 64 || SUCCEEDED(m_platformDragData->QueryGetData(filenameFormat())))); 65 return m_dragDataMap.contains(urlWFormat()->cfFormat) || m_dragDataMap.contains(urlFormat()->cfFormat) 66 || (filenamePolicy == ConvertFilenames && (m_dragDataMap.contains(filenameWFormat()->cfFormat) || m_dragDataMap.contains(filenameFormat()->cfFormat))); 67 } 68 69 const DragDataMap& DragData::dragDataMap() 70 { 71 if (!m_dragDataMap.isEmpty() || !m_platformDragData) 72 return m_dragDataMap; 73 // Enumerate clipboard content and load it in the map. 74 COMPtr<IEnumFORMATETC> itr; 75 76 if (FAILED(m_platformDragData->EnumFormatEtc(DATADIR_GET, &itr)) || !itr) 77 return m_dragDataMap; 78 79 FORMATETC dataFormat; 80 while (itr->Next(1, &dataFormat, 0) == S_OK) { 81 Vector<String> dataStrings; 82 getClipboardData(m_platformDragData, &dataFormat, dataStrings); 83 if (!dataStrings.isEmpty()) 84 m_dragDataMap.set(dataFormat.cfFormat, dataStrings); 85 } 86 return m_dragDataMap; 87 } 88 89 String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const 90 { 91 bool success; 92 return (m_platformDragData) ? getURL(m_platformDragData, filenamePolicy, success, title) : getURL(&m_dragDataMap, filenamePolicy, title); 93 } 94 95 bool DragData::containsFiles() const 96 { 97 return (m_platformDragData) ? SUCCEEDED(m_platformDragData->QueryGetData(cfHDropFormat())) : m_dragDataMap.contains(cfHDropFormat()->cfFormat); 98 } 99 100 void DragData::asFilenames(Vector<String>& result) const 101 { 102 if (m_platformDragData) { 103 WCHAR filename[MAX_PATH]; 104 105 STGMEDIUM medium; 106 if (FAILED(m_platformDragData->GetData(cfHDropFormat(), &medium))) 107 return; 108 109 HDROP hdrop = (HDROP)GlobalLock(medium.hGlobal); 110 111 if (!hdrop) 112 return; 113 114 const unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0); 115 for (unsigned i = 0; i < numFiles; i++) { 116 if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename))) 117 continue; 118 result.append((UChar*)filename); 119 } 120 121 // Free up memory from drag 122 DragFinish(hdrop); 123 124 GlobalUnlock(medium.hGlobal); 125 return; 126 } 127 result = m_dragDataMap.get(cfHDropFormat()->cfFormat); 128 } 129 130 bool DragData::containsPlainText() const 131 { 132 if (m_platformDragData) 133 return SUCCEEDED(m_platformDragData->QueryGetData(plainTextWFormat())) 134 || SUCCEEDED(m_platformDragData->QueryGetData(plainTextFormat())); 135 return m_dragDataMap.contains(plainTextWFormat()->cfFormat) || m_dragDataMap.contains(plainTextFormat()->cfFormat); 136 } 137 138 String DragData::asPlainText(Frame*) const 139 { 140 bool success; 141 return (m_platformDragData) ? getPlainText(m_platformDragData, success) : getPlainText(&m_dragDataMap); 142 } 143 144 bool DragData::containsColor() const 145 { 146 return false; 147 } 148 149 bool DragData::canSmartReplace() const 150 { 151 if (m_platformDragData) 152 return SUCCEEDED(m_platformDragData->QueryGetData(smartPasteFormat())); 153 return m_dragDataMap.contains(smartPasteFormat()->cfFormat); 154 } 155 156 bool DragData::containsCompatibleContent() const 157 { 158 return containsPlainText() || containsURL(0) 159 || ((m_platformDragData) ? (containsHTML(m_platformDragData) || containsFilenames(m_platformDragData)) 160 : (containsHTML(&m_dragDataMap) || containsFilenames(&m_dragDataMap))) 161 || containsColor(); 162 } 163 164 PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range>, bool, bool&) const 165 { 166 /* 167 * Order is richest format first. On OSX this is: 168 * * Web Archive 169 * * Filenames 170 * * HTML 171 * * RTF 172 * * TIFF 173 * * PICT 174 */ 175 176 if (m_platformDragData) { 177 if (containsFilenames(m_platformDragData)) { 178 if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), m_platformDragData)) 179 return fragment; 180 } 181 182 if (containsHTML(m_platformDragData)) { 183 if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), m_platformDragData)) 184 return fragment; 185 } 186 } else { 187 if (containsFilenames(&m_dragDataMap)) { 188 if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), &m_dragDataMap)) 189 return fragment; 190 } 191 192 if (containsHTML(&m_dragDataMap)) { 193 if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), &m_dragDataMap)) 194 return fragment; 195 } 196 } 197 return 0; 198 } 199 200 Color DragData::asColor() const 201 { 202 return Color(); 203 } 204 205 } 206