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