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
DragData(const DragDataMap & data,const IntPoint & clientPosition,const IntPoint & globalPosition,DragOperation sourceOperationMask,DragApplicationFlags flags)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
containsURL(Frame *,FilenameConversionPolicy filenamePolicy) const57 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
dragDataMap()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
asURL(Frame *,FilenameConversionPolicy filenamePolicy,String * title) const89 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
containsFiles() const95 bool DragData::containsFiles() const
96 {
97 return (m_platformDragData) ? SUCCEEDED(m_platformDragData->QueryGetData(cfHDropFormat())) : m_dragDataMap.contains(cfHDropFormat()->cfFormat);
98 }
99
asFilenames(Vector<String> & result) const100 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
containsPlainText() const130 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
asPlainText(Frame *) const138 String DragData::asPlainText(Frame*) const
139 {
140 bool success;
141 return (m_platformDragData) ? getPlainText(m_platformDragData, success) : getPlainText(&m_dragDataMap);
142 }
143
containsColor() const144 bool DragData::containsColor() const
145 {
146 return false;
147 }
148
canSmartReplace() const149 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
containsCompatibleContent() const156 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
asFragment(Frame * frame,PassRefPtr<Range>,bool,bool &) const164 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
asColor() const200 Color DragData::asColor() const
201 {
202 return Color();
203 }
204
205 }
206