• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
4  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5  * Copyright (C) 2010 Sencha, Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 #include "ClipboardQt.h"
31 
32 #include "CachedImage.h"
33 #include "Document.h"
34 #include "DragData.h"
35 #include "Element.h"
36 #include "FileList.h"
37 #include "Frame.h"
38 #include "HTMLNames.h"
39 #include "HTMLParserIdioms.h"
40 #include "Image.h"
41 #include "IntPoint.h"
42 #include "KURL.h"
43 #include "NotImplemented.h"
44 #include "PlatformString.h"
45 #include "Range.h"
46 #include "RenderImage.h"
47 #include "markup.h"
48 #include <wtf/text/StringHash.h>
49 
50 #include <QApplication>
51 #include <QClipboard>
52 #include <QList>
53 #include <QMimeData>
54 #include <QStringList>
55 #include <QTextCodec>
56 #include <QUrl>
57 #include <qdebug.h>
58 
59 #define methodDebug() qDebug("ClipboardQt: %s", __FUNCTION__)
60 
61 namespace WebCore {
62 
isTextMimeType(const String & type)63 static bool isTextMimeType(const String& type)
64 {
65     return type == "text/plain" || type.startsWith("text/plain;");
66 }
67 
isHtmlMimeType(const String & type)68 static bool isHtmlMimeType(const String& type)
69 {
70     return type == "text/html" || type.startsWith("text/html;");
71 }
72 
create(ClipboardAccessPolicy policy,DragData * dragData,Frame *)73 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame*)
74 {
75     return ClipboardQt::create(policy, dragData->platformData());
76 }
77 
ClipboardQt(ClipboardAccessPolicy policy,const QMimeData * readableClipboard)78 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, const QMimeData* readableClipboard)
79     : Clipboard(policy, DragAndDrop)
80     , m_readableData(readableClipboard)
81     , m_writableData(0)
82 {
83     Q_ASSERT(policy == ClipboardReadable || policy == ClipboardTypesReadable);
84 }
85 
ClipboardQt(ClipboardAccessPolicy policy,ClipboardType clipboardType)86 ClipboardQt::ClipboardQt(ClipboardAccessPolicy policy, ClipboardType clipboardType)
87     : Clipboard(policy, clipboardType)
88     , m_readableData(0)
89     , m_writableData(0)
90 {
91     Q_ASSERT(policy == ClipboardReadable || policy == ClipboardWritable || policy == ClipboardNumb);
92 
93 #ifndef QT_NO_CLIPBOARD
94     if (policy != ClipboardWritable) {
95         Q_ASSERT(isForCopyAndPaste());
96         m_readableData = QApplication::clipboard()->mimeData();
97     }
98 #endif
99 }
100 
~ClipboardQt()101 ClipboardQt::~ClipboardQt()
102 {
103     if (m_writableData && isForCopyAndPaste())
104         m_writableData = 0;
105     else
106         delete m_writableData;
107     m_readableData = 0;
108 }
109 
clearData(const String & type)110 void ClipboardQt::clearData(const String& type)
111 {
112     if (policy() != ClipboardWritable)
113         return;
114 
115     if (m_writableData) {
116         m_writableData->removeFormat(type);
117         if (m_writableData->formats().isEmpty()) {
118             if (isForDragAndDrop())
119                 delete m_writableData;
120             m_writableData = 0;
121         }
122     }
123 #ifndef QT_NO_CLIPBOARD
124     if (isForCopyAndPaste())
125         QApplication::clipboard()->setMimeData(m_writableData);
126 #endif
127 }
128 
clearAllData()129 void ClipboardQt::clearAllData()
130 {
131     if (policy() != ClipboardWritable)
132         return;
133 
134 #ifndef QT_NO_CLIPBOARD
135     if (isForCopyAndPaste())
136         QApplication::clipboard()->setMimeData(0);
137     else
138 #endif
139         delete m_writableData;
140     m_writableData = 0;
141 }
142 
getData(const String & type,bool & success) const143 String ClipboardQt::getData(const String& type, bool& success) const
144 {
145 
146     if (policy() != ClipboardReadable) {
147         success = false;
148         return String();
149     }
150 
151     if (isHtmlMimeType(type) && m_readableData->hasHtml()) {
152         success = true;
153         return m_readableData->html();
154     }
155 
156     if (isTextMimeType(type) && m_readableData->hasText()) {
157         success = true;
158         return m_readableData->text();
159     }
160 
161     ASSERT(m_readableData);
162     QByteArray rawData = m_readableData->data(type);
163     QString data = QTextCodec::codecForName("UTF-16")->toUnicode(rawData);
164     success = !data.isEmpty();
165     return data;
166 }
167 
setData(const String & type,const String & data)168 bool ClipboardQt::setData(const String& type, const String& data)
169 {
170     if (policy() != ClipboardWritable)
171         return false;
172 
173     if (!m_writableData)
174         m_writableData = new QMimeData;
175 
176     if (isTextMimeType(type))
177         m_writableData->setText(QString(data));
178     else if (isHtmlMimeType(type))
179         m_writableData->setHtml(QString(data));
180     else {
181         QByteArray array(reinterpret_cast<const char*>(data.characters()), data.length() * 2);
182         m_writableData->setData(QString(type), array);
183     }
184 
185 #ifndef QT_NO_CLIPBOARD
186     if (isForCopyAndPaste())
187         QApplication::clipboard()->setMimeData(m_writableData);
188 #endif
189     return true;
190 }
191 
192 // extensions beyond IE's API
types() const193 HashSet<String> ClipboardQt::types() const
194 {
195     if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
196         return HashSet<String>();
197 
198     ASSERT(m_readableData);
199     HashSet<String> result;
200     QStringList formats = m_readableData->formats();
201     for (int i = 0; i < formats.count(); ++i)
202         result.add(formats.at(i));
203     return result;
204 }
205 
files() const206 PassRefPtr<FileList> ClipboardQt::files() const
207 {
208     if (policy() != ClipboardReadable || !m_readableData->hasUrls())
209         return FileList::create();
210 
211     RefPtr<FileList> fileList = FileList::create();
212     QList<QUrl> urls = m_readableData->urls();
213 
214     for (int i = 0; i < urls.size(); i++) {
215         QUrl url = urls[i];
216         if (url.scheme() != QLatin1String("file"))
217             continue;
218         fileList->append(File::create(url.toLocalFile()));
219     }
220 
221     return fileList.release();
222 }
223 
setDragImage(CachedImage * image,const IntPoint & point)224 void ClipboardQt::setDragImage(CachedImage* image, const IntPoint& point)
225 {
226     setDragImage(image, 0, point);
227 }
228 
setDragImageElement(Node * node,const IntPoint & point)229 void ClipboardQt::setDragImageElement(Node* node, const IntPoint& point)
230 {
231     setDragImage(0, node, point);
232 }
233 
setDragImage(CachedImage * image,Node * node,const IntPoint & loc)234 void ClipboardQt::setDragImage(CachedImage* image, Node *node, const IntPoint &loc)
235 {
236     if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
237         return;
238 
239     if (m_dragImage)
240         m_dragImage->removeClient(this);
241     m_dragImage = image;
242     if (m_dragImage)
243         m_dragImage->addClient(this);
244 
245     m_dragLoc = loc;
246     m_dragImageElement = node;
247 }
248 
createDragImage(IntPoint & dragLoc) const249 DragImageRef ClipboardQt::createDragImage(IntPoint& dragLoc) const
250 {
251     if (!m_dragImage)
252         return 0;
253     dragLoc = m_dragLoc;
254     return m_dragImage->image()->nativeImageForCurrentFrame();
255 }
256 
257 
getCachedImage(Element * element)258 static CachedImage* getCachedImage(Element* element)
259 {
260     // Attempt to pull CachedImage from element
261     ASSERT(element);
262     RenderObject* renderer = element->renderer();
263     if (!renderer || !renderer->isImage())
264         return 0;
265 
266     RenderImage* image = toRenderImage(renderer);
267     if (image->cachedImage() && !image->cachedImage()->errorOccurred())
268         return image->cachedImage();
269 
270     return 0;
271 }
272 
declareAndWriteDragImage(Element * element,const KURL & url,const String & title,Frame * frame)273 void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
274 {
275     ASSERT(frame);
276 
277     // WebCore::writeURL(m_writableDataObject.get(), url, title, true, false);
278     if (!m_writableData)
279         m_writableData = new QMimeData;
280 
281     CachedImage* cachedImage = getCachedImage(element);
282     if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
283         return;
284     QPixmap* pixmap = cachedImage->image()->nativeImageForCurrentFrame();
285     if (pixmap)
286         m_writableData->setImageData(*pixmap);
287 
288     AtomicString imageURL = element->getAttribute(HTMLNames::srcAttr);
289     if (imageURL.isEmpty())
290         return;
291 
292     KURL fullURL = frame->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(imageURL));
293     if (fullURL.isEmpty())
294         return;
295 
296     QList<QUrl> urls;
297     urls.append(url);
298     urls.append(fullURL);
299 
300     m_writableData->setText(title);
301     m_writableData->setUrls(urls);
302     m_writableData->setHtml(createMarkup(element, IncludeNode, 0, AbsoluteURLs));
303 #ifndef QT_NO_CLIPBOARD
304     if (isForCopyAndPaste())
305         QApplication::clipboard()->setMimeData(m_writableData);
306 #endif
307 }
308 
writeURL(const KURL & url,const String & title,Frame * frame)309 void ClipboardQt::writeURL(const KURL& url, const String& title, Frame* frame)
310 {
311     ASSERT(frame);
312 
313     QList<QUrl> urls;
314     urls.append(frame->document()->completeURL(url.string()));
315     if (!m_writableData)
316         m_writableData = new QMimeData;
317     m_writableData->setUrls(urls);
318     m_writableData->setText(title);
319 #ifndef QT_NO_CLIPBOARD
320     if (isForCopyAndPaste())
321         QApplication::clipboard()->setMimeData(m_writableData);
322 #endif
323 }
324 
writeRange(Range * range,Frame * frame)325 void ClipboardQt::writeRange(Range* range, Frame* frame)
326 {
327     ASSERT(range);
328     ASSERT(frame);
329 
330     if (!m_writableData)
331         m_writableData = new QMimeData;
332     QString text = frame->editor()->selectedText();
333     text.replace(QChar(0xa0), QLatin1Char(' '));
334     m_writableData->setText(text);
335     m_writableData->setHtml(createMarkup(range, 0, AnnotateForInterchange, false, AbsoluteURLs));
336 #ifndef QT_NO_CLIPBOARD
337     if (isForCopyAndPaste())
338         QApplication::clipboard()->setMimeData(m_writableData);
339 #endif
340 }
341 
writePlainText(const String & str)342 void ClipboardQt::writePlainText(const String& str)
343 {
344     if (!m_writableData)
345         m_writableData = new QMimeData;
346     QString text = str;
347     text.replace(QChar(0xa0), QLatin1Char(' '));
348     m_writableData->setText(text);
349 #ifndef QT_NO_CLIPBOARD
350     if (isForCopyAndPaste())
351         QApplication::clipboard()->setMimeData(m_writableData);
352 #endif
353 }
354 
hasData()355 bool ClipboardQt::hasData()
356 {
357     const QMimeData *data = m_readableData ? m_readableData : m_writableData;
358     if (!data)
359         return false;
360     return data->formats().count() > 0;
361 }
362 
363 }
364