OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebCore / platform / gtk / ClipboardGtk.cpp
1 /*
2  *  This library is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU Lesser General Public
4  *  License as published by the Free Software Foundation; either
5  *  version 2 of the License, or (at your option) any later version.
6  *
7  *  This library is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  Lesser General Public License for more details.
11  *
12  *  You should have received a copy of the GNU Lesser General Public
13  *  License along with this library; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
15  */
16
17 #include "config.h"
18 #include "ClipboardGtk.h"
19
20 #include "CachedImage.h"
21 #include "DragData.h"
22 #include "Editor.h"
23 #include "Element.h"
24 #include "FileList.h"
25 #include "Frame.h"
26 #include "HTMLNames.h"
27 #include "Image.h"
28 #include "NotImplemented.h"
29 #include "Pasteboard.h"
30 #include "PasteboardHelper.h"
31 #include "RenderImage.h"
32 #include "ScriptExecutionContext.h"
33 #include "markup.h"
34 #include <wtf/text/CString.h>
35 #include <wtf/text/StringHash.h>
36 #include <gtk/gtk.h>
37
38 namespace WebCore {
39
40 enum ClipboardDataType {
41     ClipboardDataTypeText,
42     ClipboardDataTypeMarkup,
43     ClipboardDataTypeURIList,
44     ClipboardDataTypeURL,
45     ClipboardDataTypeImage,
46     ClipboardDataTypeUnknown
47 };
48
49 PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy, Frame* frame)
50 {
51     return ClipboardGtk::create(policy, gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD), frame);
52 }
53
54 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
55 {
56     return ClipboardGtk::create(policy, dragData->platformData(), DragAndDrop, frame);
57 }
58
59 ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, GtkClipboard* clipboard, Frame* frame)
60     : Clipboard(policy, CopyAndPaste)
61     , m_dataObject(DataObjectGtk::forClipboard(clipboard))
62     , m_clipboard(clipboard)
63     , m_helper(Pasteboard::generalPasteboard()->helper())
64     , m_frame(frame)
65 {
66 }
67
68 ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGtk> dataObject, ClipboardType clipboardType, Frame* frame)
69     : Clipboard(policy, clipboardType)
70     , m_dataObject(dataObject)
71     , m_clipboard(0)
72     , m_helper(Pasteboard::generalPasteboard()->helper())
73     , m_frame(frame)
74 {
75 }
76
77 ClipboardGtk::~ClipboardGtk()
78 {
79 }
80
81 static ClipboardDataType dataObjectTypeFromHTMLClipboardType(const String& rawType)
82 {
83     String type(rawType.stripWhiteSpace());
84
85     // Two special cases for IE compatibility
86     if (type == "Text" || type == "text")
87         return ClipboardDataTypeText;
88     if (type == "URL")
89         return ClipboardDataTypeURL;
90
91     // From the Mac port: Ignore any trailing charset - JS strings are
92     // Unicode, which encapsulates the charset issue.
93     if (type == "text/plain" || type.startsWith("text/plain;"))
94         return ClipboardDataTypeText;
95     if (type == "text/html" || type.startsWith("text/html;"))
96         return ClipboardDataTypeMarkup;
97     if (type == "Files" || type == "text/uri-list" || type.startsWith("text/uri-list;"))
98         return ClipboardDataTypeURIList;
99
100     // Not a known type, so just default to using the text portion.
101     return ClipboardDataTypeUnknown;
102 }
103
104 void ClipboardGtk::clearData(const String& typeString)
105 {
106     if (policy() != ClipboardWritable)
107         return;
108
109     ClipboardDataType type = dataObjectTypeFromHTMLClipboardType(typeString);
110     switch (type) {
111     case ClipboardDataTypeURIList:
112     case ClipboardDataTypeURL:
113         m_dataObject->clearURIList();
114         break;
115     case ClipboardDataTypeMarkup:
116         m_dataObject->clearMarkup();
117         break;
118     case ClipboardDataTypeText:
119         m_dataObject->clearText();
120         break;
121     case ClipboardDataTypeUnknown:
122     default:
123         m_dataObject->clear();
124     }
125
126     if (m_clipboard)
127         m_helper->writeClipboardContents(m_clipboard);
128 }
129
130
131 void ClipboardGtk::clearAllData()
132 {
133     if (policy() != ClipboardWritable)
134         return;
135
136     m_dataObject->clear();
137
138     if (m_clipboard)
139         m_helper->writeClipboardContents(m_clipboard);
140 }
141
142 String ClipboardGtk::getData(const String& typeString, bool& success) const
143 {
144     success = true; // According to http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html
145     // "The getData(format) method must return the data that is associated with the type format converted
146     // to ASCII lowercase, if any, and must return the empty string otherwise." Since success == false 
147     // results in an 'undefined' return value, we always want to return success == true. This parameter
148     // should eventually be removed.
149     if (policy() != ClipboardReadable || !m_dataObject)
150         return String();
151
152     if (m_clipboard)
153         m_helper->getClipboardContents(m_clipboard);
154
155     ClipboardDataType type = dataObjectTypeFromHTMLClipboardType(typeString);
156     if (type == ClipboardDataTypeURIList)
157         return m_dataObject->uriList();
158     if (type == ClipboardDataTypeURL)
159         return m_dataObject->url();
160     if (type == ClipboardDataTypeMarkup)
161         return m_dataObject->markup();
162     if (type == ClipboardDataTypeText)
163         return m_dataObject->text();
164
165     return String();
166 }
167
168 bool ClipboardGtk::setData(const String& typeString, const String& data)
169 {
170     if (policy() != ClipboardWritable)
171         return false;
172
173     bool success = false;
174     ClipboardDataType type = dataObjectTypeFromHTMLClipboardType(typeString);
175     if (type == ClipboardDataTypeURIList || type == ClipboardDataTypeURL) {
176         m_dataObject->setURIList(data);
177         success = true;
178     } else if (type == ClipboardDataTypeMarkup) {
179         m_dataObject->setMarkup(data);
180         success = true;
181     } else if (type == ClipboardDataTypeText) {
182         m_dataObject->setText(data);
183         success = true;
184     }
185
186     if (success && m_clipboard)
187         m_helper->writeClipboardContents(m_clipboard);
188
189     return success;
190 }
191
192 HashSet<String> ClipboardGtk::types() const
193 {
194     if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
195         return HashSet<String>();
196
197     if (m_clipboard)
198         m_helper->getClipboardContents(m_clipboard);
199
200     HashSet<String> types;
201     if (m_dataObject->hasText()) {
202         types.add("text/plain");
203         types.add("Text");
204         types.add("text");
205     }
206
207     if (m_dataObject->hasMarkup())
208         types.add("text/html");
209
210     if (m_dataObject->hasURIList()) {
211         types.add("text/uri-list");
212         types.add("URL");
213     }
214
215     if (m_dataObject->hasFilenames())
216         types.add("Files");
217
218     return types;
219 }
220
221 PassRefPtr<FileList> ClipboardGtk::files() const
222 {
223     if (policy() != ClipboardReadable)
224         return FileList::create();
225
226     if (m_clipboard)
227         m_helper->getClipboardContents(m_clipboard);
228
229     RefPtr<FileList> fileList = FileList::create();
230     const Vector<String>& filenames = m_dataObject->filenames();
231     for (size_t i = 0; i < filenames.size(); i++)
232         fileList->append(File::create(filenames[i]));
233     return fileList.release();
234 }
235
236 void ClipboardGtk::setDragImage(CachedImage* image, const IntPoint& location)
237 {
238     setDragImage(image, 0, location);
239 }
240
241 void ClipboardGtk::setDragImageElement(Node* element, const IntPoint& location)
242 {
243     setDragImage(0, element, location);
244 }
245
246 void ClipboardGtk::setDragImage(CachedImage* image, Node* element, const IntPoint& location)
247 {
248     if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
249         return;
250
251     if (m_dragImage)
252         m_dragImage->removeClient(this);
253     m_dragImage = image;
254     if (m_dragImage)
255         m_dragImage->addClient(this);
256
257     m_dragLoc = location;
258     m_dragImageElement = element;
259 }
260
261 DragImageRef ClipboardGtk::createDragImage(IntPoint& location) const
262 {
263     location = m_dragLoc;
264     if (!m_dragImage)
265         return 0;
266
267     return createDragImageFromImage(m_dragImage->image());
268 }
269
270 static CachedImage* getCachedImage(Element* element)
271 {
272     // Attempt to pull CachedImage from element
273     ASSERT(element);
274     RenderObject* renderer = element->renderer();
275     if (!renderer || !renderer->isImage())
276         return 0;
277
278     RenderImage* image = static_cast<RenderImage*>(renderer);
279     if (image->cachedImage() && !image->cachedImage()->errorOccurred())
280         return image->cachedImage();
281
282     return 0;
283 }
284
285 void ClipboardGtk::declareAndWriteDragImage(Element* element, const KURL& url, const String& label, Frame* frame)
286 {
287     m_dataObject->setURL(url, label);
288     m_dataObject->setMarkup(createMarkup(element, IncludeNode, 0, AbsoluteURLs));
289
290     CachedImage* image = getCachedImage(element);
291     if (!image || !image->isLoaded())
292         return;
293
294     GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->image()->getGdkPixbuf());
295     if (!pixbuf)
296         return;
297
298     m_dataObject->setImage(pixbuf.get());
299 }
300
301 void ClipboardGtk::writeURL(const KURL& url, const String& label, Frame*)
302 {
303     m_dataObject->setURL(url, label);
304     if (m_clipboard)
305         m_helper->writeClipboardContents(m_clipboard);
306 }
307
308 void ClipboardGtk::writeRange(Range* range, Frame* frame)
309 {
310     ASSERT(range);
311
312     m_dataObject->setText(frame->editor()->selectedText());
313     m_dataObject->setMarkup(createMarkup(range, 0, AnnotateForInterchange, false, AbsoluteURLs));
314
315     if (m_clipboard)
316         m_helper->writeClipboardContents(m_clipboard);
317 }
318
319 void ClipboardGtk::writePlainText(const String& text)
320 {
321     m_dataObject->setText(text);
322
323     if (m_clipboard)
324         m_helper->writeClipboardContents(m_clipboard);
325 }
326
327 bool ClipboardGtk::hasData()
328 {
329     if (m_clipboard)
330         m_helper->getClipboardContents(m_clipboard);
331
332     return m_dataObject->hasText() || m_dataObject->hasMarkup()
333         || m_dataObject->hasURIList() || m_dataObject->hasImage();
334 }
335
336 }