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