1 /* 2 * Copyright (c) 2008, 2009, Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "Pasteboard.h" 33 34 #include "ClipboardUtilitiesChromium.h" 35 #include "Document.h" 36 #include "DocumentFragment.h" 37 #include "Element.h" 38 #include "Frame.h" 39 #include "HTMLNames.h" 40 #include "HTMLParserIdioms.h" 41 #include "Image.h" 42 #include "KURL.h" 43 #include "NativeImageSkia.h" 44 #include "PlatformBridge.h" 45 #include "Range.h" 46 #include "RenderImage.h" 47 #include "markup.h" 48 49 #if ENABLE(SVG) 50 #include "SVGNames.h" 51 #include "XLinkNames.h" 52 #endif 53 54 namespace WebCore { 55 56 Pasteboard* Pasteboard::generalPasteboard() 57 { 58 static Pasteboard* pasteboard = new Pasteboard; 59 return pasteboard; 60 } 61 62 Pasteboard::Pasteboard() 63 : m_selectionMode(false) 64 { 65 } 66 67 void Pasteboard::clear() 68 { 69 // The ScopedClipboardWriter class takes care of clearing the clipboard's 70 // previous contents. 71 } 72 73 bool Pasteboard::isSelectionMode() const 74 { 75 return m_selectionMode; 76 } 77 78 void Pasteboard::setSelectionMode(bool selectionMode) 79 { 80 m_selectionMode = selectionMode; 81 } 82 83 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) 84 { 85 String html = createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs); 86 ExceptionCode ec = 0; 87 KURL url = selectedRange->startContainer(ec)->document()->url(); 88 String plainText = frame->editor()->selectedText(); 89 #if OS(WINDOWS) 90 replaceNewlinesWithWindowsStyleNewlines(plainText); 91 #endif 92 replaceNBSPWithSpace(plainText); 93 94 PlatformBridge::clipboardWriteSelection(html, url, plainText, canSmartCopyOrDelete); 95 } 96 97 void Pasteboard::writePlainText(const String& text) 98 { 99 #if OS(WINDOWS) 100 String plainText(text); 101 replaceNewlinesWithWindowsStyleNewlines(plainText); 102 PlatformBridge::clipboardWritePlainText(plainText); 103 #else 104 PlatformBridge::clipboardWritePlainText(text); 105 #endif 106 } 107 108 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) 109 { 110 ASSERT(!url.isEmpty()); 111 112 String title(titleStr); 113 if (title.isEmpty()) { 114 title = url.lastPathComponent(); 115 if (title.isEmpty()) 116 title = url.host(); 117 } 118 119 PlatformBridge::clipboardWriteURL(url, title); 120 } 121 122 void Pasteboard::writeImage(Node* node, const KURL&, const String& title) 123 { 124 ASSERT(node); 125 ASSERT(node->renderer()); 126 ASSERT(node->renderer()->isImage()); 127 RenderImage* renderer = toRenderImage(node->renderer()); 128 CachedImage* cachedImage = renderer->cachedImage(); 129 if (!cachedImage || cachedImage->errorOccurred()) 130 return; 131 Image* image = cachedImage->image(); 132 ASSERT(image); 133 134 NativeImagePtr bitmap = image->nativeImageForCurrentFrame(); 135 if (!bitmap) 136 return; 137 138 // If the image is wrapped in a link, |url| points to the target of the 139 // link. This isn't useful to us, so get the actual image URL. 140 AtomicString urlString; 141 if (node->hasTagName(HTMLNames::imgTag) || node->hasTagName(HTMLNames::inputTag)) 142 urlString = static_cast<Element*>(node)->getAttribute(HTMLNames::srcAttr); 143 #if ENABLE(SVG) 144 else if (node->hasTagName(SVGNames::imageTag)) 145 urlString = static_cast<Element*>(node)->getAttribute(XLinkNames::hrefAttr); 146 #endif 147 else if (node->hasTagName(HTMLNames::embedTag) || node->hasTagName(HTMLNames::objectTag)) { 148 Element* element = static_cast<Element*>(node); 149 urlString = element->getAttribute(element->imageSourceAttributeName()); 150 } 151 KURL url = urlString.isEmpty() ? KURL() : node->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(urlString)); 152 153 PlatformBridge::clipboardWriteImage(bitmap, url, title); 154 } 155 156 bool Pasteboard::canSmartReplace() 157 { 158 return PlatformBridge::clipboardIsFormatAvailable(PasteboardPrivate::WebSmartPasteFormat, m_selectionMode ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer); 159 } 160 161 String Pasteboard::plainText(Frame* frame) 162 { 163 return PlatformBridge::clipboardReadPlainText(m_selectionMode ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer); 164 } 165 166 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) 167 { 168 chosePlainText = false; 169 PasteboardPrivate::ClipboardBuffer buffer = m_selectionMode ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer; 170 171 if (PlatformBridge::clipboardIsFormatAvailable(PasteboardPrivate::HTMLFormat, buffer)) { 172 String markup; 173 KURL srcURL; 174 PlatformBridge::clipboardReadHTML(buffer, &markup, &srcURL); 175 176 RefPtr<DocumentFragment> fragment = 177 createFragmentFromMarkup(frame->document(), markup, srcURL, FragmentScriptingNotAllowed); 178 if (fragment) 179 return fragment.release(); 180 } 181 182 if (allowPlainText) { 183 String markup = PlatformBridge::clipboardReadPlainText(buffer); 184 if (!markup.isEmpty()) { 185 chosePlainText = true; 186 187 RefPtr<DocumentFragment> fragment = 188 createFragmentFromText(context.get(), markup); 189 if (fragment) 190 return fragment.release(); 191 } 192 } 193 194 return 0; 195 } 196 197 } // namespace WebCore 198