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 28using blink::WebClipboard; 29using blink::WebData; 30using blink::WebDragData; 31using blink::WebImage; 32using blink::WebString; 33using blink::WebURL; 34using blink::WebVector; 35 36namespace content { 37 38WebClipboardImpl::WebClipboardImpl(ClipboardClient* client) 39 : client_(client) { 40} 41 42WebClipboardImpl::~WebClipboardImpl() { 43} 44 45uint64 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 53bool 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 78WebVector<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 88WebString 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 98WebString 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 114WebData 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 124WebString 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 135void WebClipboardImpl::writePlainText(const WebString& plain_text) { 136 ScopedClipboardWriterGlue scw(client_); 137 scw.WriteText(plain_text); 138} 139 140void 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 151void 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 185void 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 206bool 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