2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2009 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "ClipboardChromium.h"
30 #include "CachedImage.h"
31 #include "ChromiumDataObject.h"
32 #include "ClipboardMimeTypes.h"
33 #include "ClipboardUtilitiesChromium.h"
34 #include "DataTransferItemListChromium.h"
40 #include "HTMLNames.h"
41 #include "HTMLParserIdioms.h"
43 #include "MIMETypeRegistry.h"
44 #include "NamedNodeMap.h"
45 #include "PlatformSupport.h"
47 #include "RenderImage.h"
48 #include "ScriptExecutionContext.h"
51 #include <wtf/text/StringBuilder.h>
52 #include <wtf/text/WTFString.h>
56 using namespace HTMLNames;
58 // We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft
59 // see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
61 static String normalizeType(const String& type)
63 String cleanType = type.stripWhiteSpace().lower();
64 if (cleanType == mimeTypeText || cleanType.startsWith(mimeTypeTextPlainEtc))
65 return mimeTypeTextPlain;
69 PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
71 return ClipboardChromium::create(DragAndDrop, dragData->platformData(), policy, frame);
74 ClipboardChromium::ClipboardChromium(ClipboardType clipboardType,
75 PassRefPtr<ChromiumDataObject> dataObject,
76 ClipboardAccessPolicy policy,
78 : Clipboard(policy, clipboardType)
79 , m_dataObject(dataObject)
81 , m_originalSequenceNumber(PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()))
85 PassRefPtr<ClipboardChromium> ClipboardChromium::create(ClipboardType clipboardType,
86 PassRefPtr<ChromiumDataObject> dataObject, ClipboardAccessPolicy policy, Frame* frame)
88 return adoptRef(new ClipboardChromium(clipboardType, dataObject, policy, frame));
91 void ClipboardChromium::clearData(const String& type)
93 if (policy() != ClipboardWritable || !m_dataObject)
96 m_dataObject->clearData(normalizeType(type));
101 void ClipboardChromium::clearAllData()
103 if (policy() != ClipboardWritable)
106 m_dataObject->clearAll();
109 String ClipboardChromium::getData(const String& type, bool& success) const
112 if (policy() != ClipboardReadable || !m_dataObject)
115 if (isForCopyAndPaste() && platformClipboardChanged())
118 return m_dataObject->getData(normalizeType(type), success);
121 bool ClipboardChromium::setData(const String& type, const String& data)
123 if (policy() != ClipboardWritable)
126 return m_dataObject->setData(normalizeType(type), data);
129 bool ClipboardChromium::platformClipboardChanged() const
131 return PlatformSupport::clipboardSequenceNumber(currentPasteboardBuffer()) != m_originalSequenceNumber;
134 // extensions beyond IE's API
135 HashSet<String> ClipboardChromium::types() const
137 HashSet<String> results;
138 if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
144 results = m_dataObject->types();
146 if (m_dataObject->containsFilenames())
147 results.add(mimeTypeFiles);
152 PassRefPtr<FileList> ClipboardChromium::files() const
154 if (policy() != ClipboardReadable)
155 return FileList::create();
158 return FileList::create();
160 const Vector<String>& filenames = m_dataObject->filenames();
161 RefPtr<FileList> fileList = FileList::create();
162 for (size_t i = 0; i < filenames.size(); ++i)
163 fileList->append(File::create(filenames.at(i)));
165 return fileList.release();
168 void ClipboardChromium::setDragImage(CachedImage* image, Node* node, const IntPoint& loc)
170 if (policy() != ClipboardImageWritable && policy() != ClipboardWritable)
174 m_dragImage->removeClient(this);
177 m_dragImage->addClient(this);
180 m_dragImageElement = node;
183 void ClipboardChromium::setDragImage(CachedImage* img, const IntPoint& loc)
185 setDragImage(img, 0, loc);
188 void ClipboardChromium::setDragImageElement(Node* node, const IntPoint& loc)
190 setDragImage(0, node, loc);
193 DragImageRef ClipboardChromium::createDragImage(IntPoint& loc) const
195 DragImageRef result = 0;
196 if (m_dragImageElement) {
198 result = m_frame->nodeImage(m_dragImageElement.get());
201 } else if (m_dragImage) {
202 result = createDragImageFromImage(m_dragImage->image());
208 static CachedImage* getCachedImage(Element* element)
210 // Attempt to pull CachedImage from element
212 RenderObject* renderer = element->renderer();
213 if (!renderer || !renderer->isImage())
216 RenderImage* image = toRenderImage(renderer);
217 if (image->cachedImage() && !image->cachedImage()->errorOccurred())
218 return image->cachedImage();
223 static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* element,
226 // Shove image data into a DataObject for use as a file
227 CachedImage* cachedImage = getCachedImage(element);
228 if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded())
231 SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer())->data();
232 if (!imageBuffer || !imageBuffer->size())
235 dataObject->setFileContent(imageBuffer);
237 // Determine the filename for the file contents of the image.
238 String filename = cachedImage->response().suggestedFilename();
239 if (filename.isEmpty())
240 filename = url.lastPathComponent();
241 if (filename.isEmpty())
242 filename = element->getAttribute(altAttr);
244 // Strip any existing extension. Assume that alt text is usually not a filename.
245 int extensionIndex = filename.reverseFind('.');
246 if (extensionIndex != -1)
247 filename.truncate(extensionIndex);
249 filename = ClipboardChromium::validateFileName(filename, dataObject);
251 String extension = MIMETypeRegistry::getPreferredExtensionForMIMEType(
252 cachedImage->response().mimeType());
253 dataObject->setFileExtension(extension.isEmpty() ? emptyString() : "." + extension);
255 dataObject->setFileContentFilename(filename + dataObject->fileExtension());
258 void ClipboardChromium::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
263 m_dataObject->setData(mimeTypeURL, url);
264 m_dataObject->setUrlTitle(title);
266 // Write the bytes in the image to the file format.
267 writeImageToDataObject(m_dataObject.get(), element, url);
269 // Put img tag on the clipboard referencing the image
270 m_dataObject->setData(mimeTypeTextHTML, createMarkup(element, IncludeNode, 0, ResolveAllURLs));
273 void ClipboardChromium::writeURL(const KURL& url, const String& title, Frame*)
277 ASSERT(!url.isEmpty());
278 m_dataObject->setData(mimeTypeURL, url);
279 m_dataObject->setUrlTitle(title);
281 // The URL can also be used as plain text.
282 m_dataObject->setData(mimeTypeTextPlain, url.string());
284 // The URL can also be used as an HTML fragment.
285 m_dataObject->setData(mimeTypeTextHTML, urlToMarkup(url, title));
286 m_dataObject->setHtmlBaseUrl(url);
289 void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
291 ASSERT(selectedRange);
295 m_dataObject->setData(mimeTypeTextHTML, createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs));
296 m_dataObject->setHtmlBaseUrl(frame->document()->url());
298 String str = frame->editor()->selectedText();
300 replaceNewlinesWithWindowsStyleNewlines(str);
302 replaceNBSPWithSpace(str);
303 m_dataObject->setData(mimeTypeTextPlain, str);
306 void ClipboardChromium::writePlainText(const String& text)
313 replaceNewlinesWithWindowsStyleNewlines(str);
315 replaceNBSPWithSpace(str);
316 m_dataObject->setData(mimeTypeTextPlain, str);
319 bool ClipboardChromium::hasData()
321 ASSERT(isForDragAndDrop());
325 return m_dataObject->hasData();
328 #if ENABLE(DATA_TRANSFER_ITEMS)
329 PassRefPtr<DataTransferItemList> ClipboardChromium::items()
331 RefPtr<DataTransferItemListChromium> items = DataTransferItemListChromium::create(this, m_frame->document()->scriptExecutionContext());
336 if (isForCopyAndPaste() && policy() == ClipboardReadable) {
337 // Iterate through the types and add them.
338 HashSet<String> types = m_dataObject->types();
339 for (HashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it)
340 items->addPasteboardItem(*it);
346 } // namespace WebCore