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