Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2011 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/chromium/ChromiumDataObjectItem.h"
     33 
     34 #include "core/dom/DataTransferItem.h"
     35 #include "core/dom/StringCallback.h"
     36 #include "core/fileapi/Blob.h"
     37 #include "core/fileapi/File.h"
     38 #include "core/platform/SharedBuffer.h"
     39 #include "core/platform/chromium/ClipboardMimeTypes.h"
     40 #include "core/platform/chromium/ClipboardUtilitiesChromium.h"
     41 
     42 #include "public/platform/Platform.h"
     43 #include "public/platform/WebClipboard.h"
     44 
     45 namespace WebCore {
     46 
     47 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromString(const String& type, const String& data)
     48 {
     49     RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, type));
     50     item->m_data = data;
     51     return item.release();
     52 }
     53 
     54 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromFile(PassRefPtr<File> file)
     55 {
     56     RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindFile, file->type()));
     57     item->m_file = file;
     58     return item.release();
     59 }
     60 
     61 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromURL(const String& url, const String& title)
     62 {
     63     RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, mimeTypeTextURIList));
     64     item->m_data = url;
     65     item->m_title = title;
     66     return item.release();
     67 }
     68 
     69 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromHTML(const String& html, const KURL& baseURL)
     70 {
     71     RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, mimeTypeTextHTML));
     72     item->m_data = html;
     73     item->m_baseURL = baseURL;
     74     return item.release();
     75 }
     76 
     77 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromSharedBuffer(const String& name, PassRefPtr<SharedBuffer> buffer)
     78 {
     79     RefPtr<ChromiumDataObjectItem> item = adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindFile, String()));
     80     item->m_sharedBuffer = buffer;
     81     item->m_title = name;
     82     return item.release();
     83 }
     84 
     85 PassRefPtr<ChromiumDataObjectItem> ChromiumDataObjectItem::createFromPasteboard(const String& type, uint64_t sequenceNumber)
     86 {
     87     if (type == mimeTypeImagePng)
     88         return adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindFile, type, sequenceNumber));
     89     return adoptRef(new ChromiumDataObjectItem(DataTransferItem::kindString, type, sequenceNumber));
     90 }
     91 
     92 ChromiumDataObjectItem::ChromiumDataObjectItem(const String& kind, const String& type)
     93     : m_source(InternalSource)
     94     , m_kind(kind)
     95     , m_type(type)
     96     , m_sequenceNumber(0)
     97 {
     98 }
     99 
    100 ChromiumDataObjectItem::ChromiumDataObjectItem(const String& kind, const String& type, uint64_t sequenceNumber)
    101     : m_source(PasteboardSource)
    102     , m_kind(kind)
    103     , m_type(type)
    104     , m_sequenceNumber(sequenceNumber)
    105 {
    106 }
    107 
    108 void ChromiumDataObjectItem::getAsString(PassRefPtr<StringCallback> callback, ScriptExecutionContext* context) const
    109 {
    110     if (!callback || kind() != DataTransferItem::kindString)
    111         return;
    112 
    113     callback->scheduleCallback(context, internalGetAsString());
    114 }
    115 
    116 PassRefPtr<Blob> ChromiumDataObjectItem::getAsFile() const
    117 {
    118     if (kind() != DataTransferItem::kindFile)
    119         return 0;
    120 
    121     if (m_source == InternalSource) {
    122         if (m_file)
    123             return m_file;
    124         ASSERT(m_sharedBuffer);
    125         // FIXME: This code is currently impossible--we never populate m_sharedBuffer when dragging
    126         // in. At some point though, we may need to support correctly converting a shared buffer
    127         // into a file.
    128         return 0;
    129     }
    130 
    131     ASSERT(m_source == PasteboardSource);
    132     if (type() == mimeTypeImagePng) {
    133         // FIXME: This is pretty inefficient. We copy the data from the browser
    134         // to the renderer. We then place it in a blob in WebKit, which
    135         // registers it and copies it *back* to the browser. When a consumer
    136         // wants to read the data, we then copy the data back into the renderer.
    137         // https://bugs.webkit.org/show_bug.cgi?id=58107 has been filed to track
    138         // improvements to this code (in particular, add a registerClipboardBlob
    139         // method to the blob registry; that way the data is only copied over
    140         // into the renderer when it's actually read, not when the blob is
    141         // initially constructed).
    142         RefPtr<SharedBuffer> data = static_cast<PassRefPtr<SharedBuffer> >(WebKit::Platform::current()->clipboard()->readImage(WebKit::WebClipboard::BufferStandard));
    143         RefPtr<RawData> rawData = RawData::create();
    144         rawData->mutableData()->append(data->data(), data->size());
    145         OwnPtr<BlobData> blobData = BlobData::create();
    146         blobData->appendData(rawData, 0, -1);
    147         blobData->setContentType(mimeTypeImagePng);
    148         return Blob::create(blobData.release(), data->size());
    149     }
    150 
    151     return 0;
    152 }
    153 
    154 String ChromiumDataObjectItem::internalGetAsString() const
    155 {
    156     ASSERT(m_kind == DataTransferItem::kindString);
    157 
    158     if (m_source == InternalSource)
    159         return m_data;
    160 
    161     ASSERT(m_source == PasteboardSource);
    162 
    163     String data;
    164     // This is ugly but there's no real alternative.
    165     if (m_type == mimeTypeTextPlain)
    166         data = WebKit::Platform::current()->clipboard()->readPlainText(currentPasteboardBuffer());
    167     else if (m_type == mimeTypeTextHTML) {
    168         WebKit::WebURL ignoredSourceURL;
    169         unsigned ignored;
    170         data = WebKit::Platform::current()->clipboard()->readHTML(currentPasteboardBuffer(), &ignoredSourceURL, &ignored, &ignored);
    171     } else
    172         data = WebKit::Platform::current()->clipboard()->readCustomData(currentPasteboardBuffer(), m_type);
    173 
    174     return WebKit::Platform::current()->clipboard()->sequenceNumber(currentPasteboardBuffer()) == m_sequenceNumber ? data : String();
    175 }
    176 
    177 bool ChromiumDataObjectItem::isFilename() const
    178 {
    179     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=81261: When we properly support File dragout,
    180     // we'll need to make sure this works as expected for DragDataChromium.
    181     return m_kind == DataTransferItem::kindFile && m_file;
    182 }
    183 
    184 } // namespace WebCore
    185 
    186