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