1 | /* |
2 | * Copyright (C) 2007 Holger Hans Peter Freyther |
3 | * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library; if not, write to the Free Software |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | */ |
19 | |
20 | #include "config.h" |
21 | #include "Pasteboard.h" |
22 | |
23 | #include "Color.h" |
24 | #include "DragData.h" |
25 | #include "Image.h" |
26 | #include "NotImplemented.h" |
27 | #include "PasteboardStrategy.h" |
28 | #include "PlatformStrategies.h" |
29 | #include "SelectionData.h" |
30 | #include <wtf/NeverDestroyed.h> |
31 | #include <wtf/URL.h> |
32 | |
33 | namespace WebCore { |
34 | |
35 | enum ClipboardDataType { |
36 | ClipboardDataTypeText, |
37 | ClipboardDataTypeMarkup, |
38 | ClipboardDataTypeURIList, |
39 | ClipboardDataTypeURL, |
40 | ClipboardDataTypeImage, |
41 | ClipboardDataTypeUnknown |
42 | }; |
43 | |
44 | std::unique_ptr<Pasteboard> Pasteboard::createForCopyAndPaste() |
45 | { |
46 | return std::make_unique<Pasteboard>("CLIPBOARD" ); |
47 | } |
48 | |
49 | std::unique_ptr<Pasteboard> Pasteboard::createForGlobalSelection() |
50 | { |
51 | return std::make_unique<Pasteboard>("PRIMARY" ); |
52 | } |
53 | |
54 | #if ENABLE(DRAG_SUPPORT) |
55 | std::unique_ptr<Pasteboard> Pasteboard::createForDragAndDrop() |
56 | { |
57 | return std::make_unique<Pasteboard>(SelectionData::create()); |
58 | } |
59 | |
60 | std::unique_ptr<Pasteboard> Pasteboard::createForDragAndDrop(const DragData& dragData) |
61 | { |
62 | ASSERT(dragData.platformData()); |
63 | return std::make_unique<Pasteboard>(*dragData.platformData()); |
64 | } |
65 | #endif |
66 | |
67 | Pasteboard::Pasteboard(SelectionData& selectionData) |
68 | : m_selectionData(selectionData) |
69 | { |
70 | } |
71 | |
72 | Pasteboard::Pasteboard(const String& name) |
73 | : m_selectionData(SelectionData::create()) |
74 | , m_name(name) |
75 | { |
76 | } |
77 | |
78 | Pasteboard::Pasteboard() |
79 | : m_selectionData(SelectionData::create()) |
80 | { |
81 | } |
82 | |
83 | Pasteboard::~Pasteboard() = default; |
84 | |
85 | const SelectionData& Pasteboard::selectionData() const |
86 | { |
87 | return m_selectionData.get(); |
88 | } |
89 | |
90 | static ClipboardDataType selectionDataTypeFromHTMLClipboardType(const String& type) |
91 | { |
92 | // From the Mac port: Ignore any trailing charset - JS strings are |
93 | // Unicode, which encapsulates the charset issue. |
94 | if (type == "text/plain" ) |
95 | return ClipboardDataTypeText; |
96 | if (type == "text/html" ) |
97 | return ClipboardDataTypeMarkup; |
98 | if (type == "Files" || type == "text/uri-list" ) |
99 | return ClipboardDataTypeURIList; |
100 | |
101 | // Not a known type, so just default to using the text portion. |
102 | return ClipboardDataTypeUnknown; |
103 | } |
104 | |
105 | void Pasteboard::writeToClipboard() |
106 | { |
107 | if (m_name.isNull()) |
108 | return; |
109 | |
110 | platformStrategies()->pasteboardStrategy()->writeToClipboard(m_name, m_selectionData); |
111 | } |
112 | |
113 | void Pasteboard::readFromClipboard() |
114 | { |
115 | if (m_name.isNull()) |
116 | return; |
117 | m_selectionData = platformStrategies()->pasteboardStrategy()->readFromClipboard(m_name); |
118 | } |
119 | |
120 | void Pasteboard::writeString(const String& type, const String& data) |
121 | { |
122 | switch (selectionDataTypeFromHTMLClipboardType(type)) { |
123 | case ClipboardDataTypeURIList: |
124 | case ClipboardDataTypeURL: |
125 | m_selectionData->setURIList(data); |
126 | break; |
127 | case ClipboardDataTypeMarkup: |
128 | m_selectionData->setMarkup(data); |
129 | break; |
130 | case ClipboardDataTypeText: |
131 | m_selectionData->setText(data); |
132 | break; |
133 | case ClipboardDataTypeUnknown: |
134 | m_selectionData->setUnknownTypeData(type, data); |
135 | break; |
136 | case ClipboardDataTypeImage: |
137 | break; |
138 | } |
139 | writeToClipboard(); |
140 | } |
141 | |
142 | void Pasteboard::writePlainText(const String& text, SmartReplaceOption smartReplaceOption) |
143 | { |
144 | m_selectionData->clearAll(); |
145 | m_selectionData->setText(text); |
146 | m_selectionData->setCanSmartReplace(smartReplaceOption == CanSmartReplace); |
147 | |
148 | writeToClipboard(); |
149 | } |
150 | |
151 | void Pasteboard::write(const PasteboardURL& pasteboardURL) |
152 | { |
153 | ASSERT(!pasteboardURL.url.isEmpty()); |
154 | |
155 | m_selectionData->clearAll(); |
156 | m_selectionData->setURL(pasteboardURL.url, pasteboardURL.title); |
157 | |
158 | writeToClipboard(); |
159 | } |
160 | |
161 | void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&) |
162 | { |
163 | notImplemented(); |
164 | } |
165 | |
166 | void Pasteboard::write(const PasteboardImage& pasteboardImage) |
167 | { |
168 | m_selectionData->clearAll(); |
169 | if (!pasteboardImage.url.url.isEmpty()) { |
170 | m_selectionData->setURL(pasteboardImage.url.url, pasteboardImage.url.title); |
171 | m_selectionData->setMarkup(pasteboardImage.url.markup); |
172 | } |
173 | m_selectionData->setImage(pasteboardImage.image.get()); |
174 | |
175 | writeToClipboard(); |
176 | } |
177 | |
178 | void Pasteboard::write(const PasteboardWebContent& pasteboardContent) |
179 | { |
180 | m_selectionData->clearAll(); |
181 | m_selectionData->setText(pasteboardContent.text); |
182 | m_selectionData->setMarkup(pasteboardContent.markup); |
183 | m_selectionData->setCanSmartReplace(pasteboardContent.canSmartCopyOrDelete); |
184 | |
185 | writeToClipboard(); |
186 | } |
187 | |
188 | void Pasteboard::clear() |
189 | { |
190 | // We do not clear filenames. According to the spec: "The clearData() method |
191 | // does not affect whether any files were included in the drag, so the types |
192 | // attribute's list might still not be empty after calling clearData() (it would |
193 | // still contain the "Files" string if any files were included in the drag)." |
194 | m_selectionData->clearAllExceptFilenames(); |
195 | writeToClipboard(); |
196 | } |
197 | |
198 | void Pasteboard::clear(const String& type) |
199 | { |
200 | switch (selectionDataTypeFromHTMLClipboardType(type)) { |
201 | case ClipboardDataTypeURIList: |
202 | case ClipboardDataTypeURL: |
203 | m_selectionData->clearURIList(); |
204 | break; |
205 | case ClipboardDataTypeMarkup: |
206 | m_selectionData->clearMarkup(); |
207 | break; |
208 | case ClipboardDataTypeText: |
209 | m_selectionData->clearText(); |
210 | break; |
211 | case ClipboardDataTypeImage: |
212 | m_selectionData->clearImage(); |
213 | break; |
214 | case ClipboardDataTypeUnknown: |
215 | m_selectionData->clearAll(); |
216 | break; |
217 | } |
218 | |
219 | writeToClipboard(); |
220 | } |
221 | |
222 | bool Pasteboard::canSmartReplace() |
223 | { |
224 | readFromClipboard(); |
225 | return m_selectionData->canSmartReplace(); |
226 | } |
227 | |
228 | #if ENABLE(DRAG_SUPPORT) |
229 | void Pasteboard::setDragImage(DragImage, const IntPoint&) |
230 | { |
231 | } |
232 | #endif |
233 | |
234 | void Pasteboard::read(PasteboardPlainText& text) |
235 | { |
236 | readFromClipboard(); |
237 | text.text = m_selectionData->text(); |
238 | } |
239 | |
240 | void Pasteboard::read(PasteboardWebContentReader&, WebContentReadingPolicy) |
241 | { |
242 | } |
243 | |
244 | void Pasteboard::read(PasteboardFileReader& reader) |
245 | { |
246 | readFromClipboard(); |
247 | for (auto& filename : m_selectionData->filenames()) |
248 | reader.readFilename(filename); |
249 | } |
250 | |
251 | bool Pasteboard::hasData() |
252 | { |
253 | readFromClipboard(); |
254 | return m_selectionData->hasText() || m_selectionData->hasMarkup() || m_selectionData->hasURIList() || m_selectionData->hasImage() || m_selectionData->hasUnknownTypeData(); |
255 | } |
256 | |
257 | Vector<String> Pasteboard::typesSafeForBindings(const String&) |
258 | { |
259 | notImplemented(); // webkit.org/b/177633: [GTK] Move to new Pasteboard API |
260 | return { }; |
261 | } |
262 | |
263 | Vector<String> Pasteboard::typesForLegacyUnsafeBindings() |
264 | { |
265 | readFromClipboard(); |
266 | |
267 | Vector<String> types; |
268 | if (m_selectionData->hasText()) { |
269 | types.append("text/plain"_s ); |
270 | types.append("Text"_s ); |
271 | types.append("text"_s ); |
272 | } |
273 | |
274 | if (m_selectionData->hasMarkup()) |
275 | types.append("text/html"_s ); |
276 | |
277 | if (m_selectionData->hasURIList()) { |
278 | types.append("text/uri-list"_s ); |
279 | types.append("URL"_s ); |
280 | } |
281 | |
282 | for (auto& key : m_selectionData->unknownTypes().keys()) |
283 | types.append(key); |
284 | |
285 | return types; |
286 | } |
287 | |
288 | String Pasteboard::readOrigin() |
289 | { |
290 | notImplemented(); // webkit.org/b/177633: [GTK] Move to new Pasteboard API |
291 | return { }; |
292 | } |
293 | |
294 | String Pasteboard::readString(const String& type) |
295 | { |
296 | readFromClipboard(); |
297 | |
298 | switch (selectionDataTypeFromHTMLClipboardType(type)) { |
299 | case ClipboardDataTypeURIList: |
300 | return m_selectionData->uriList(); |
301 | case ClipboardDataTypeURL: |
302 | return m_selectionData->url(); |
303 | case ClipboardDataTypeMarkup: |
304 | return m_selectionData->markup(); |
305 | case ClipboardDataTypeText: |
306 | return m_selectionData->text(); |
307 | case ClipboardDataTypeUnknown: |
308 | return m_selectionData->unknownTypeData(type); |
309 | case ClipboardDataTypeImage: |
310 | break; |
311 | } |
312 | |
313 | return String(); |
314 | } |
315 | |
316 | String Pasteboard::readStringInCustomData(const String&) |
317 | { |
318 | notImplemented(); // webkit.org/b/177633: [GTK] Move to new Pasteboard API |
319 | return { }; |
320 | } |
321 | |
322 | Pasteboard::FileContentState Pasteboard::fileContentState() |
323 | { |
324 | readFromClipboard(); |
325 | return m_selectionData->filenames().isEmpty() ? FileContentState::NoFileOrImageData : FileContentState::MayContainFilePaths; |
326 | } |
327 | |
328 | void Pasteboard::writeMarkup(const String&) |
329 | { |
330 | } |
331 | |
332 | void Pasteboard::writeCustomData(const PasteboardCustomData&) |
333 | { |
334 | } |
335 | |
336 | void Pasteboard::write(const Color&) |
337 | { |
338 | } |
339 | |
340 | } |
341 | |