Home | History | Annotate | Download | only in renderer
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/webclipboard_impl.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/pickle.h"
      9 #include "base/strings/string_util.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "content/common/clipboard_format.h"
     12 #include "content/public/common/drop_data.h"
     13 #include "content/renderer/clipboard_utils.h"
     14 #include "content/renderer/drop_data_builder.h"
     15 #include "content/renderer/scoped_clipboard_writer_glue.h"
     16 #include "third_party/WebKit/public/platform/WebData.h"
     17 #include "third_party/WebKit/public/platform/WebDragData.h"
     18 #include "third_party/WebKit/public/platform/WebImage.h"
     19 #include "third_party/WebKit/public/platform/WebSize.h"
     20 #include "third_party/WebKit/public/platform/WebString.h"
     21 #include "third_party/WebKit/public/platform/WebURL.h"
     22 #include "third_party/WebKit/public/platform/WebVector.h"
     23 #include "third_party/skia/include/core/SkBitmap.h"
     24 #include "ui/base/clipboard/clipboard.h"
     25 #include "ui/base/clipboard/custom_data_helper.h"
     26 #include "url/gurl.h"
     27 
     28 using blink::WebClipboard;
     29 using blink::WebData;
     30 using blink::WebDragData;
     31 using blink::WebImage;
     32 using blink::WebString;
     33 using blink::WebURL;
     34 using blink::WebVector;
     35 
     36 namespace content {
     37 
     38 WebClipboardImpl::WebClipboardImpl(ClipboardClient* client)
     39     : client_(client) {
     40 }
     41 
     42 WebClipboardImpl::~WebClipboardImpl() {
     43 }
     44 
     45 uint64 WebClipboardImpl::sequenceNumber(Buffer buffer) {
     46   ui::ClipboardType clipboard_type;
     47   if (!ConvertBufferType(buffer, &clipboard_type))
     48     return 0;
     49 
     50   return client_->GetSequenceNumber(clipboard_type);
     51 }
     52 
     53 bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
     54   ui::ClipboardType clipboard_type = ui::CLIPBOARD_TYPE_COPY_PASTE;
     55 
     56   if (!ConvertBufferType(buffer, &clipboard_type))
     57     return false;
     58 
     59   switch (format) {
     60     case FormatPlainText:
     61       return client_->IsFormatAvailable(CLIPBOARD_FORMAT_PLAINTEXT,
     62                                         clipboard_type);
     63     case FormatHTML:
     64       return client_->IsFormatAvailable(CLIPBOARD_FORMAT_HTML, clipboard_type);
     65     case FormatSmartPaste:
     66       return client_->IsFormatAvailable(CLIPBOARD_FORMAT_SMART_PASTE,
     67                                         clipboard_type);
     68     case FormatBookmark:
     69       return client_->IsFormatAvailable(CLIPBOARD_FORMAT_BOOKMARK,
     70                                         clipboard_type);
     71     default:
     72       NOTREACHED();
     73   }
     74 
     75   return false;
     76 }
     77 
     78 WebVector<WebString> WebClipboardImpl::readAvailableTypes(
     79     Buffer buffer, bool* contains_filenames) {
     80   ui::ClipboardType clipboard_type;
     81   std::vector<base::string16> types;
     82   if (ConvertBufferType(buffer, &clipboard_type)) {
     83     client_->ReadAvailableTypes(clipboard_type, &types, contains_filenames);
     84   }
     85   return types;
     86 }
     87 
     88 WebString WebClipboardImpl::readPlainText(Buffer buffer) {
     89   ui::ClipboardType clipboard_type;
     90   if (!ConvertBufferType(buffer, &clipboard_type))
     91     return WebString();
     92 
     93   base::string16 text;
     94   client_->ReadText(clipboard_type, &text);
     95   return text;
     96 }
     97 
     98 WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
     99                                      unsigned* fragment_start,
    100                                      unsigned* fragment_end) {
    101   ui::ClipboardType clipboard_type;
    102   if (!ConvertBufferType(buffer, &clipboard_type))
    103     return WebString();
    104 
    105   base::string16 html_stdstr;
    106   GURL gurl;
    107   client_->ReadHTML(clipboard_type, &html_stdstr, &gurl,
    108                     static_cast<uint32*>(fragment_start),
    109                     static_cast<uint32*>(fragment_end));
    110   *source_url = gurl;
    111   return html_stdstr;
    112 }
    113 
    114 WebData WebClipboardImpl::readImage(Buffer buffer) {
    115   ui::ClipboardType clipboard_type;
    116   if (!ConvertBufferType(buffer, &clipboard_type))
    117     return WebData();
    118 
    119   std::string png_data;
    120   client_->ReadImage(clipboard_type, &png_data);
    121   return WebData(png_data);
    122 }
    123 
    124 WebString WebClipboardImpl::readCustomData(Buffer buffer,
    125                                            const WebString& type) {
    126   ui::ClipboardType clipboard_type;
    127   if (!ConvertBufferType(buffer, &clipboard_type))
    128     return WebString();
    129 
    130   base::string16 data;
    131   client_->ReadCustomData(clipboard_type, type, &data);
    132   return data;
    133 }
    134 
    135 void WebClipboardImpl::writePlainText(const WebString& plain_text) {
    136   ScopedClipboardWriterGlue scw(client_);
    137   scw.WriteText(plain_text);
    138 }
    139 
    140 void WebClipboardImpl::writeHTML(
    141     const WebString& html_text, const WebURL& source_url,
    142     const WebString& plain_text, bool write_smart_paste) {
    143   ScopedClipboardWriterGlue scw(client_);
    144   scw.WriteHTML(html_text, source_url.spec());
    145   scw.WriteText(plain_text);
    146 
    147   if (write_smart_paste)
    148     scw.WriteWebSmartPaste();
    149 }
    150 
    151 void WebClipboardImpl::writeImage(const WebImage& image,
    152                                   const WebURL& url,
    153                                   const WebString& title) {
    154   ScopedClipboardWriterGlue scw(client_);
    155 
    156   if (!image.isNull()) {
    157     const SkBitmap& bitmap = image.getSkBitmap();
    158     // WriteBitmapFromPixels expects 32-bit data.
    159     DCHECK_EQ(bitmap.colorType(), kN32_SkColorType);
    160 
    161     SkAutoLockPixels locked(bitmap);
    162     void *pixels = bitmap.getPixels();
    163     // TODO(piman): this should not be NULL, but it is. crbug.com/369621
    164     if (!pixels)
    165       return;
    166     scw.WriteBitmapFromPixels(pixels, image.size());
    167   }
    168 
    169   if (!url.isEmpty()) {
    170     scw.WriteBookmark(title, url.spec());
    171 #if !defined(OS_MACOSX)
    172     // When writing the image, we also write the image markup so that pasting
    173     // into rich text editors, such as Gmail, reveals the image. We also don't
    174     // want to call writeText(), since some applications (WordPad) don't pick
    175     // the image if there is also a text format on the clipboard.
    176     // We also don't want to write HTML on a Mac, since Mail.app prefers to use
    177     // the image markup over attaching the actual image. See
    178     // http://crbug.com/33016 for details.
    179     scw.WriteHTML(base::UTF8ToUTF16(URLToImageMarkup(url, title)),
    180                   std::string());
    181 #endif
    182   }
    183 }
    184 
    185 void WebClipboardImpl::writeDataObject(const WebDragData& data) {
    186   ScopedClipboardWriterGlue scw(client_);
    187 
    188   const DropData& data_object = DropDataBuilder::Build(data);
    189   // TODO(dcheng): Properly support text/uri-list here.
    190   if (!data_object.text.is_null())
    191     scw.WriteText(data_object.text.string());
    192   if (!data_object.html.is_null())
    193     scw.WriteHTML(data_object.html.string(), std::string());
    194   // If there is no custom data, avoid calling WritePickledData. This ensures
    195   // that ScopedClipboardWriterGlue's dtor remains a no-op if the page didn't
    196   // modify the DataTransfer object, which is important to avoid stomping on
    197   // any clipboard contents written by extension functions such as
    198   // chrome.bookmarkManagerPrivate.copy.
    199   if (!data_object.custom_data.empty()) {
    200     Pickle pickle;
    201     ui::WriteCustomDataToPickle(data_object.custom_data, &pickle);
    202     scw.WritePickledData(pickle, ui::Clipboard::GetWebCustomDataFormatType());
    203   }
    204 }
    205 
    206 bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
    207                                          ui::ClipboardType* result) {
    208   *result = ui::CLIPBOARD_TYPE_COPY_PASTE;
    209   switch (buffer) {
    210     case BufferStandard:
    211       break;
    212     case BufferSelection:
    213 #if defined(USE_X11) && !defined(OS_CHROMEOS)
    214       *result = ui::CLIPBOARD_TYPE_SELECTION;
    215       break;
    216 #else
    217       // Chrome OS and non-X11 unix builds do not support
    218       // the X selection clipboad.
    219       // TODO: remove the need for this case, see http://crbug.com/361753
    220       return false;
    221 #endif
    222     default:
    223       NOTREACHED();
    224       return false;
    225   }
    226   return true;
    227 }
    228 
    229 }  // namespace content
    230