Home | History | Annotate | Download | only in chromium
      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 "core/platform/Pasteboard.h"
     33 
     34 #include "HTMLNames.h"
     35 #include "SVGNames.h"
     36 #include "XLinkNames.h"
     37 #include "core/dom/Document.h"
     38 #include "core/dom/DocumentFragment.h"
     39 #include "core/dom/Element.h"
     40 #include "core/dom/Range.h"
     41 #include "core/editing/markup.h"
     42 #include "core/html/parser/HTMLParserIdioms.h"
     43 #include "core/loader/cache/ImageResource.h"
     44 #include "core/page/Frame.h"
     45 #include "core/platform/chromium/ClipboardChromium.h"
     46 #include "core/platform/chromium/ClipboardUtilitiesChromium.h"
     47 #include "core/platform/graphics/Image.h"
     48 #include "core/platform/graphics/skia/NativeImageSkia.h"
     49 #include "core/rendering/RenderImage.h"
     50 #include "public/platform/Platform.h"
     51 #include "public/platform/WebClipboard.h"
     52 #include "public/platform/WebDragData.h"
     53 #include "weborigin/KURL.h"
     54 
     55 namespace WebCore {
     56 
     57 Pasteboard* Pasteboard::generalPasteboard()
     58 {
     59     static Pasteboard* pasteboard = new Pasteboard;
     60     return pasteboard;
     61 }
     62 
     63 Pasteboard::Pasteboard()
     64     : m_selectionMode(false)
     65 {
     66 }
     67 
     68 void Pasteboard::clear()
     69 {
     70     // The ScopedClipboardWriter class takes care of clearing the clipboard's
     71     // previous contents.
     72 }
     73 
     74 bool Pasteboard::isSelectionMode() const
     75 {
     76     return m_selectionMode;
     77 }
     78 
     79 void Pasteboard::setSelectionMode(bool selectionMode)
     80 {
     81     m_selectionMode = selectionMode;
     82 }
     83 
     84 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame, ShouldSerializeSelectedTextForClipboard shouldSerializeSelectedTextForClipboard)
     85 {
     86     String html = createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
     87     KURL url = selectedRange->startContainer()->document()->url();
     88     String plainText = shouldSerializeSelectedTextForClipboard == IncludeImageAltTextForClipboard ? frame->selectedTextForClipboard() : frame->selectedText();
     89 #if OS(WINDOWS)
     90     replaceNewlinesWithWindowsStyleNewlines(plainText);
     91 #endif
     92     replaceNBSPWithSpace(plainText);
     93 
     94     WebKit::Platform::current()->clipboard()->writeHTML(html, url, plainText, canSmartCopyOrDelete);
     95 }
     96 
     97 void Pasteboard::writePlainText(const String& text, SmartReplaceOption)
     98 {
     99     // FIXME: add support for smart replace
    100 #if OS(WINDOWS)
    101     String plainText(text);
    102     replaceNewlinesWithWindowsStyleNewlines(plainText);
    103     WebKit::Platform::current()->clipboard()->writePlainText(plainText);
    104 #else
    105     WebKit::Platform::current()->clipboard()->writePlainText(text);
    106 #endif
    107 }
    108 
    109 void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
    110 {
    111     ASSERT(!url.isEmpty());
    112 
    113     String title(titleStr);
    114     if (title.isEmpty()) {
    115         title = url.lastPathComponent();
    116         if (title.isEmpty())
    117             title = url.host();
    118     }
    119 
    120     WebKit::Platform::current()->clipboard()->writeURL(url, title);
    121 }
    122 
    123 void Pasteboard::writeImage(Node* node, const KURL&, const String& title)
    124 {
    125     ASSERT(node);
    126 
    127     if (!(node->renderer() && node->renderer()->isImage()))
    128         return;
    129 
    130     RenderImage* renderer = toRenderImage(node->renderer());
    131     ImageResource* cachedImage = renderer->cachedImage();
    132     if (!cachedImage || cachedImage->errorOccurred())
    133         return;
    134     Image* image = cachedImage->imageForRenderer(renderer);
    135     ASSERT(image);
    136 
    137     RefPtr<NativeImageSkia> bitmap = image->nativeImageForCurrentFrame();
    138     if (!bitmap)
    139         return;
    140 
    141     // If the image is wrapped in a link, |url| points to the target of the
    142     // link.  This isn't useful to us, so get the actual image URL.
    143     AtomicString urlString;
    144     if (node->hasTagName(HTMLNames::imgTag) || node->hasTagName(HTMLNames::inputTag))
    145         urlString = toElement(node)->getAttribute(HTMLNames::srcAttr);
    146     else if (node->hasTagName(SVGNames::imageTag))
    147         urlString = toElement(node)->getAttribute(XLinkNames::hrefAttr);
    148     else if (node->hasTagName(HTMLNames::embedTag) || node->hasTagName(HTMLNames::objectTag)) {
    149         Element* element = toElement(node);
    150         urlString = element->imageSourceURL();
    151     }
    152     KURL url = urlString.isEmpty() ? KURL() : node->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(urlString));
    153     WebKit::WebImage webImage = bitmap->bitmap();
    154     WebKit::Platform::current()->clipboard()->writeImage(webImage, WebKit::WebURL(url), WebKit::WebString(title));
    155 }
    156 
    157 void Pasteboard::writeClipboard(Clipboard* clipboard)
    158 {
    159     WebKit::WebDragData dragData = static_cast<ClipboardChromium*>(clipboard)->dataObject();
    160     WebKit::Platform::current()->clipboard()->writeDataObject(dragData);
    161 }
    162 
    163 bool Pasteboard::canSmartReplace()
    164 {
    165     return WebKit::Platform::current()->clipboard()->isFormatAvailable(WebKit::WebClipboard::FormatSmartPaste, m_selectionMode ? WebKit::WebClipboard::BufferSelection : WebKit::WebClipboard::BufferStandard);
    166 }
    167 
    168 String Pasteboard::plainText(Frame* frame)
    169 {
    170     return WebKit::Platform::current()->clipboard()->readPlainText(m_selectionMode ? WebKit::WebClipboard::BufferSelection : WebKit::WebClipboard::BufferStandard);
    171 }
    172 
    173 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText)
    174 {
    175     chosePlainText = false;
    176     WebKit::WebClipboard::Buffer buffer = m_selectionMode ? WebKit::WebClipboard::BufferSelection : WebKit::WebClipboard::BufferStandard;
    177 
    178     if (WebKit::Platform::current()->clipboard()->isFormatAvailable(WebKit::WebClipboard::FormatHTML, buffer)) {
    179         unsigned fragmentStart = 0;
    180         unsigned fragmentEnd = 0;
    181         WebKit::WebURL url;
    182         WebKit::WebString markup = WebKit::Platform::current()->clipboard()->readHTML(buffer, &url, &fragmentStart, &fragmentEnd);
    183         if (!markup.isEmpty()) {
    184             if (RefPtr<DocumentFragment> fragment = createFragmentFromMarkupWithContext(frame->document(), markup, fragmentStart, fragmentEnd, KURL(url), DisallowScriptingAndPluginContent))
    185                 return fragment.release();
    186         }
    187     }
    188 
    189     if (allowPlainText) {
    190         String markup = WebKit::Platform::current()->clipboard()->readPlainText(buffer);
    191         if (!markup.isEmpty()) {
    192             chosePlainText = true;
    193             if (RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), markup))
    194                 return fragment.release();
    195         }
    196     }
    197 
    198     return 0;
    199 }
    200 
    201 } // namespace WebCore
    202