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 "ChromiumBridge.h" 35 #include "ClipboardUtilitiesChromium.h" 36 #include "DocumentFragment.h" 37 #include "Document.h" 38 #include "Element.h" 39 #include "Frame.h" 40 #include "HTMLNames.h" 41 #include "Image.h" 42 #include "KURL.h" 43 #include "markup.h" 44 #include "NativeImageSkia.h" 45 #include "Range.h" 46 #include "RenderImage.h" 47 48 #if ENABLE(SVG) 49 #include "SVGNames.h" 50 #include "XLinkNames.h" 51 #endif 52 53 namespace WebCore { 54 55 Pasteboard* Pasteboard::generalPasteboard() 56 { 57 static Pasteboard* pasteboard = new Pasteboard; 58 return pasteboard; 59 } 60 61 Pasteboard::Pasteboard() 62 : m_selectionMode(false) 63 { 64 } 65 66 void Pasteboard::clear() 67 { 68 // The ScopedClipboardWriter class takes care of clearing the clipboard's 69 // previous contents. 70 } 71 72 bool Pasteboard::isSelectionMode() const 73 { 74 return m_selectionMode; 75 } 76 77 void Pasteboard::setSelectionMode(bool selectionMode) 78 { 79 m_selectionMode = selectionMode; 80 } 81 82 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) 83 { 84 String html = createMarkup(selectedRange, 0, AnnotateForInterchange); 85 ExceptionCode ec = 0; 86 KURL url = selectedRange->startContainer(ec)->document()->url(); 87 String plainText = frame->selectedText(); 88 #if OS(WINDOWS) 89 replaceNewlinesWithWindowsStyleNewlines(plainText); 90 #endif 91 replaceNBSPWithSpace(plainText); 92 93 ChromiumBridge::clipboardWriteSelection(html, url, plainText, canSmartCopyOrDelete); 94 } 95 96 void Pasteboard::writePlainText(const String& text) 97 { 98 #if OS(WINDOWS) 99 String plainText(text); 100 replaceNewlinesWithWindowsStyleNewlines(plainText); 101 ChromiumBridge::clipboardWritePlainText(plainText); 102 #else 103 ChromiumBridge::clipboardWritePlainText(text); 104 #endif 105 } 106 107 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) 108 { 109 ASSERT(!url.isEmpty()); 110 111 String title(titleStr); 112 if (title.isEmpty()) { 113 title = url.lastPathComponent(); 114 if (title.isEmpty()) 115 title = url.host(); 116 } 117 118 ChromiumBridge::clipboardWriteURL(url, title); 119 } 120 121 void Pasteboard::writeImage(Node* node, const KURL&, const String& title) 122 { 123 ASSERT(node); 124 ASSERT(node->renderer()); 125 ASSERT(node->renderer()->isImage()); 126 RenderImage* renderer = toRenderImage(node->renderer()); 127 CachedImage* cachedImage = renderer->cachedImage(); 128 ASSERT(cachedImage); 129 Image* image = cachedImage->image(); 130 ASSERT(image); 131 132 // If the image is wrapped in a link, |url| points to the target of the 133 // link. This isn't useful to us, so get the actual image URL. 134 AtomicString urlString; 135 if (node->hasTagName(HTMLNames::imgTag) || node->hasTagName(HTMLNames::inputTag)) 136 urlString = static_cast<Element*>(node)->getAttribute(HTMLNames::srcAttr); 137 #if ENABLE(SVG) 138 else if (node->hasTagName(SVGNames::imageTag)) 139 urlString = static_cast<Element*>(node)->getAttribute(XLinkNames::hrefAttr); 140 #endif 141 else if (node->hasTagName(HTMLNames::embedTag) || node->hasTagName(HTMLNames::objectTag)) { 142 Element* element = static_cast<Element*>(node); 143 urlString = element->getAttribute(element->imageSourceAttributeName()); 144 } 145 KURL url = urlString.isEmpty() ? KURL() : node->document()->completeURL(deprecatedParseURL(urlString)); 146 147 NativeImagePtr bitmap = image->nativeImageForCurrentFrame(); 148 ChromiumBridge::clipboardWriteImage(bitmap, url, title); 149 } 150 151 bool Pasteboard::canSmartReplace() 152 { 153 return ChromiumBridge::clipboardIsFormatAvailable(PasteboardPrivate::WebSmartPasteFormat, m_selectionMode ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer); 154 } 155 156 String Pasteboard::plainText(Frame* frame) 157 { 158 return ChromiumBridge::clipboardReadPlainText(m_selectionMode ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer); 159 } 160 161 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) 162 { 163 chosePlainText = false; 164 PasteboardPrivate::ClipboardBuffer buffer = m_selectionMode ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer; 165 166 if (ChromiumBridge::clipboardIsFormatAvailable(PasteboardPrivate::HTMLFormat, buffer)) { 167 String markup; 168 KURL srcURL; 169 ChromiumBridge::clipboardReadHTML(buffer, &markup, &srcURL); 170 171 RefPtr<DocumentFragment> fragment = 172 createFragmentFromMarkup(frame->document(), markup, srcURL, FragmentScriptingNotAllowed); 173 if (fragment) 174 return fragment.release(); 175 } 176 177 if (allowPlainText) { 178 String markup = ChromiumBridge::clipboardReadPlainText(buffer); 179 if (!markup.isEmpty()) { 180 chosePlainText = true; 181 182 RefPtr<DocumentFragment> fragment = 183 createFragmentFromText(context.get(), markup); 184 if (fragment) 185 return fragment.release(); 186 } 187 } 188 189 return 0; 190 } 191 192 } // namespace WebCore 193