1 // Copyright (c) 2012 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.
5 #include "ui/base/clipboard/clipboard.h"
9 #include "base/basictypes.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/stl_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 #include "ui/base/clipboard/custom_data_helper.h"
17 #include "ui/gfx/size.h"
22 const char kMimeTypeFilename[] = "chromium/filename";
23 const char kMimeTypeBitmap[] = "image/bmp";
24 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data";
25 const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
26 const size_t kMaxClipboardSize = 1;
28 // Clipboard data format used by AuraClipboard.
29 enum AuraClipboardFormat {
39 // ClipboardData contains data copied to the Clipboard for a variety of formats.
40 // It mostly just provides APIs to cleanly access and manipulate this data.
45 web_smart_paste_(false),
48 virtual ~ClipboardData() {}
50 // Bitmask of AuraClipboardFormat types.
51 const int format() const { return format_; }
53 const std::string& text() const { return text_; }
54 void set_text(const std::string& text) {
59 const std::string& markup_data() const { return markup_data_; }
60 void set_markup_data(const std::string& markup_data) {
61 markup_data_ = markup_data;
65 const std::string& rtf_data() const { return rtf_data_; }
66 void SetRTFData(const std::string& rtf_data) {
71 const std::string& url() const { return url_; }
72 void set_url(const std::string& url) {
77 const std::string& bookmark_title() const { return bookmark_title_; }
78 void set_bookmark_title(const std::string& bookmark_title) {
79 bookmark_title_ = bookmark_title;
83 const std::string& bookmark_url() const { return bookmark_url_; }
84 void set_bookmark_url(const std::string& bookmark_url) {
85 bookmark_url_ = bookmark_url;
89 uint8_t* bitmap_data() const { return bitmap_data_.get(); }
90 const gfx::Size& bitmap_size() const { return bitmap_size_; }
91 void SetBitmapData(const char* pixel_data, const char* size_data) {
92 bitmap_size_ = *reinterpret_cast<const gfx::Size*>(size_data);
94 // We assume 4-byte pixel data.
95 size_t bitmap_data_len = 4 * bitmap_size_.width() * bitmap_size_.height();
96 bitmap_data_.reset(new uint8_t[bitmap_data_len]);
97 memcpy(bitmap_data_.get(), pixel_data, bitmap_data_len);
101 const std::string& custom_data_format() const { return custom_data_format_; }
102 const std::string& custom_data_data() const { return custom_data_data_; }
103 void SetCustomData(const std::string& data_format,
104 const std::string& data_data) {
105 if (data_data.size() == 0) {
106 custom_data_data_.clear();
107 custom_data_format_.clear();
110 custom_data_data_ = data_data;
111 custom_data_format_ = data_format;
115 bool web_smart_paste() const { return web_smart_paste_; }
116 void set_web_smart_paste(bool web_smart_paste) {
117 web_smart_paste_ = web_smart_paste;
122 // Plain text in UTF8 format.
125 // HTML markup data in UTF8 format.
126 std::string markup_data_;
130 std::string rtf_data_;
132 // Bookmark title in UTF8 format.
133 std::string bookmark_title_;
134 std::string bookmark_url_;
137 std::vector<std::string> files_;
140 scoped_ptr<uint8_t[]> bitmap_data_;
141 gfx::Size bitmap_size_;
143 // Data with custom format.
144 std::string custom_data_format_;
145 std::string custom_data_data_;
147 // WebKit smart paste data.
148 bool web_smart_paste_;
152 DISALLOW_COPY_AND_ASSIGN(ClipboardData);
155 // Platform clipboard implementation for Aura. This handles things like format
156 // conversion, versioning of clipboard items etc. The goal is to roughly provide
157 // a substitute to platform clipboards on other platforms such as GtkClipboard
158 // on gtk or winapi clipboard on win.
159 class AuraClipboard {
168 STLDeleteContainerPointers(data_list_.begin(), data_list_.end());
172 // Returns the number of entries currently in the clipboard stack.
173 size_t GetNumClipboardEntries() {
174 return data_list_.size();
177 // Returns the data currently on the top of the clipboard stack, NULL if the
178 // clipboard stack is empty.
179 const ClipboardData* GetData() const {
180 if (data_list_.empty())
182 return data_list_.front();
185 // Returns true if the data on top of the clipboard stack has format |format|
186 // or another format that can be converted to |format|.
187 bool IsFormatAvailable(AuraClipboardFormat format) const {
190 return HasFormat(TEXT) || HasFormat(BOOKMARK);
192 return HasFormat(format);
196 // Reads text from the data at the top of clipboard stack.
197 void ReadText(string16* result) const {
198 std::string utf8_result;
199 ReadAsciiText(&utf8_result);
200 *result = UTF8ToUTF16(utf8_result);
203 // Reads ascii text from the data at the top of clipboard stack.
204 void ReadAsciiText(std::string* result) const {
206 const ClipboardData* data = GetData();
210 *result = data->text();
211 else if (HasFormat(HTML))
212 *result = data->markup_data();
213 else if (HasFormat(BOOKMARK))
214 *result = data->bookmark_url();
217 // Reads HTML from the data at the top of clipboard stack.
218 void ReadHTML(string16* markup,
219 std::string* src_url,
220 uint32* fragment_start,
221 uint32* fragment_end) const {
228 if (!HasFormat(HTML))
231 const ClipboardData* data = GetData();
232 *markup = UTF8ToUTF16(data->markup_data());
233 *src_url = data->url();
236 DCHECK_LE(markup->length(), kuint32max);
237 *fragment_end = static_cast<uint32>(markup->length());
240 // Reads RTF from the data at the top of clipboard stack.
241 void ReadRTF(std::string* result) const {
243 const ClipboardData* data = GetData();
247 *result = data->rtf_data();
250 // Reads image from the data at the top of clipboard stack.
251 SkBitmap ReadImage() const {
253 if (!HasFormat(BITMAP))
256 const ClipboardData* data = GetData();
257 const gfx::Size size = data->bitmap_size();
258 uint8_t* bitmap = data->bitmap_data();
259 img.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height(), 0);
261 img.eraseARGB(0, 0, 0, 0);
262 memcpy(img.getPixels(), bitmap, size.width() * size.height() * 4);
266 // Reads data of type |type| from the data at the top of clipboard stack.
267 void ReadCustomData(const string16& type, string16* result) const {
269 const ClipboardData* data = GetData();
270 if (!HasFormat(CUSTOM))
273 ui::ReadCustomDataForType(data->custom_data_data().c_str(),
274 data->custom_data_data().size(),
278 // Reads bookmark from the data at the top of clipboard stack.
279 void ReadBookmark(string16* title, std::string* url) const {
282 if (!HasFormat(BOOKMARK))
285 const ClipboardData* data = GetData();
286 *title = UTF8ToUTF16(data->bookmark_title());
287 *url = data->bookmark_url();
290 void ReadData(const std::string& type, std::string* result) const {
292 const ClipboardData* data = GetData();
293 if (!HasFormat(CUSTOM) || type != data->custom_data_format())
296 *result = data->custom_data_data();
299 // Writes |data| to the top of the clipboard stack.
300 void WriteData(ClipboardData* data) {
302 AddToListEnsuringSize(data);
306 // True if the data on top of the clipboard stack has format |format|.
307 bool HasFormat(AuraClipboardFormat format) const {
308 const ClipboardData* data = GetData();
312 return data->format() & format;
315 void AddToListEnsuringSize(ClipboardData* data) {
317 data_list_.push_front(data);
319 // If the size of list becomes more than the maximum allowed, we delete the
321 if (data_list_.size() > kMaxClipboardSize) {
322 ClipboardData* last = data_list_.back();
323 data_list_.pop_back();
328 // Stack containing various versions of ClipboardData.
329 std::list<ClipboardData*> data_list_;
331 DISALLOW_COPY_AND_ASSIGN(AuraClipboard);
334 AuraClipboard* aura_clipboard = NULL;
336 AuraClipboard* GetClipboard() {
338 aura_clipboard = new AuraClipboard();
339 return aura_clipboard;
342 void DeleteClipboard() {
344 delete aura_clipboard;
345 aura_clipboard = NULL;
348 // Helper class to build a ClipboardData object and write it to clipboard.
349 class ClipboardDataBuilder {
351 static void CommitToClipboard() {
352 DCHECK(current_data_);
353 GetClipboard()->WriteData(current_data_);
354 current_data_ = NULL;
357 static void WriteText(const char* text_data, size_t text_len) {
358 ClipboardData* data = GetCurrentData();
359 data->set_text(std::string(text_data, text_len));
362 static void WriteHTML(const char* markup_data,
364 const char* url_data,
366 ClipboardData* data = GetCurrentData();
367 data->set_markup_data(std::string(markup_data, markup_len));
368 data->set_url(std::string(url_data, url_len));
371 static void WriteRTF(const char* rtf_data, size_t rtf_len) {
372 ClipboardData* data = GetCurrentData();
373 data->SetRTFData(std::string(rtf_data, rtf_len));
376 static void WriteBookmark(const char* title_data,
378 const char* url_data,
380 ClipboardData* data = GetCurrentData();
381 data->set_bookmark_title(std::string(title_data, title_len));
382 data->set_bookmark_url(std::string(url_data, url_len));
385 static void WriteWebSmartPaste() {
386 ClipboardData* data = GetCurrentData();
387 data->set_web_smart_paste(true);
390 static void WriteBitmap(const char* pixel_data, const char* size_data) {
391 ClipboardData* data = GetCurrentData();
392 data->SetBitmapData(pixel_data, size_data);
395 static void WriteData(const std::string& format,
396 const char* data_data,
398 ClipboardData* data = GetCurrentData();
399 data->SetCustomData(format, std::string(data_data, data_len));
403 static ClipboardData* GetCurrentData() {
405 current_data_ = new ClipboardData;
406 return current_data_;
409 static ClipboardData* current_data_;
412 ClipboardData* ClipboardDataBuilder::current_data_ = NULL;
416 Clipboard::FormatType::FormatType() {
419 Clipboard::FormatType::FormatType(const std::string& native_format)
420 : data_(native_format) {
423 Clipboard::FormatType::~FormatType() {
426 std::string Clipboard::FormatType::Serialize() const {
431 Clipboard::FormatType Clipboard::FormatType::Deserialize(
432 const std::string& serialization) {
433 return FormatType(serialization);
436 bool Clipboard::FormatType::operator<(const FormatType& other) const {
437 return data_ < other.data_;
440 bool Clipboard::FormatType::Equals(const FormatType& other) const {
441 return data_ == other.data_;
444 Clipboard::Clipboard() {
445 DCHECK(CalledOnValidThread());
446 // Make sure clipboard is created.
450 Clipboard::~Clipboard() {
451 DCHECK(CalledOnValidThread());
455 void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) {
456 DCHECK(CalledOnValidThread());
457 DCHECK(IsSupportedClipboardType(type));
458 for (ObjectMap::const_iterator iter = objects.begin();
459 iter != objects.end(); ++iter) {
460 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
462 ClipboardDataBuilder::CommitToClipboard();
465 bool Clipboard::IsFormatAvailable(const FormatType& format,
466 ClipboardType type) const {
467 DCHECK(CalledOnValidThread());
468 DCHECK(IsSupportedClipboardType(type));
469 AuraClipboard* clipboard = GetClipboard();
470 if (GetPlainTextFormatType().Equals(format) ||
471 GetUrlFormatType().Equals(format))
472 return clipboard->IsFormatAvailable(TEXT);
473 else if (GetHtmlFormatType().Equals(format))
474 return clipboard->IsFormatAvailable(HTML);
475 else if (GetRtfFormatType().Equals(format))
476 return clipboard->IsFormatAvailable(RTF);
477 else if (GetBitmapFormatType().Equals(format))
478 return clipboard->IsFormatAvailable(BITMAP);
479 else if (GetWebKitSmartPasteFormatType().Equals(format))
480 return clipboard->IsFormatAvailable(WEB);
482 const ClipboardData* data = clipboard->GetData();
483 if (data && data->custom_data_format() == format.ToString())
489 void Clipboard::Clear(ClipboardType type) {
490 DCHECK(CalledOnValidThread());
491 DCHECK(IsSupportedClipboardType(type));
492 AuraClipboard* clipboard = GetClipboard();
496 void Clipboard::ReadAvailableTypes(ClipboardType type,
497 std::vector<string16>* types,
498 bool* contains_filenames) const {
499 DCHECK(CalledOnValidThread());
500 if (!types || !contains_filenames) {
506 *contains_filenames = false;
507 if (IsFormatAvailable(GetPlainTextFormatType(), type))
508 types->push_back(UTF8ToUTF16(GetPlainTextFormatType().ToString()));
509 if (IsFormatAvailable(GetHtmlFormatType(), type))
510 types->push_back(UTF8ToUTF16(GetHtmlFormatType().ToString()));
511 if (IsFormatAvailable(GetRtfFormatType(), type))
512 types->push_back(UTF8ToUTF16(GetRtfFormatType().ToString()));
513 if (IsFormatAvailable(GetBitmapFormatType(), type))
514 types->push_back(UTF8ToUTF16(kMimeTypePNG));
516 AuraClipboard* clipboard = GetClipboard();
517 if (clipboard->IsFormatAvailable(CUSTOM) && clipboard->GetData()) {
518 ui::ReadCustomDataTypes(clipboard->GetData()->custom_data_data().c_str(),
519 clipboard->GetData()->custom_data_data().size(), types);
523 void Clipboard::ReadText(ClipboardType type, string16* result) const {
524 DCHECK(CalledOnValidThread());
525 GetClipboard()->ReadText(result);
528 void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const {
529 DCHECK(CalledOnValidThread());
530 GetClipboard()->ReadAsciiText(result);
533 void Clipboard::ReadHTML(ClipboardType type,
535 std::string* src_url,
536 uint32* fragment_start,
537 uint32* fragment_end) const {
538 DCHECK(CalledOnValidThread());
539 GetClipboard()->ReadHTML(markup, src_url, fragment_start, fragment_end);
542 void Clipboard::ReadRTF(ClipboardType type, std::string* result) const {
543 DCHECK(CalledOnValidThread());
544 GetClipboard()->ReadRTF(result);
547 SkBitmap Clipboard::ReadImage(ClipboardType type) const {
548 DCHECK(CalledOnValidThread());
549 return GetClipboard()->ReadImage();
552 void Clipboard::ReadCustomData(ClipboardType clipboard_type,
553 const string16& type,
554 string16* result) const {
555 DCHECK(CalledOnValidThread());
556 GetClipboard()->ReadCustomData(type, result);
559 void Clipboard::ReadBookmark(string16* title, std::string* url) const {
560 DCHECK(CalledOnValidThread());
561 GetClipboard()->ReadBookmark(title, url);
564 void Clipboard::ReadData(const FormatType& format, std::string* result) const {
565 DCHECK(CalledOnValidThread());
566 GetClipboard()->ReadData(format.ToString(), result);
569 uint64 Clipboard::GetSequenceNumber(ClipboardType type) {
570 DCHECK(CalledOnValidThread());
571 return GetClipboard()->GetNumClipboardEntries();
574 void Clipboard::WriteText(const char* text_data, size_t text_len) {
575 ClipboardDataBuilder::WriteText(text_data, text_len);
578 void Clipboard::WriteHTML(const char* markup_data,
580 const char* url_data,
582 ClipboardDataBuilder::WriteHTML(markup_data, markup_len, url_data, url_len);
585 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
586 ClipboardDataBuilder::WriteRTF(rtf_data, data_len);
589 void Clipboard::WriteBookmark(const char* title_data,
591 const char* url_data,
593 ClipboardDataBuilder::WriteBookmark(title_data, title_len, url_data, url_len);
596 void Clipboard::WriteWebSmartPaste() {
597 ClipboardDataBuilder::WriteWebSmartPaste();
600 void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
601 ClipboardDataBuilder::WriteBitmap(pixel_data, size_data);
604 void Clipboard::WriteData(const FormatType& format,
605 const char* data_data,
607 ClipboardDataBuilder::WriteData(format.ToString(), data_data, data_len);
611 Clipboard::FormatType Clipboard::GetFormatType(
612 const std::string& format_string) {
613 return FormatType::Deserialize(format_string);
617 const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
618 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeURIList));
623 const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
624 return GetUrlFormatType();
628 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
629 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText));
634 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
635 return GetPlainTextFormatType();
639 const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
640 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeFilename));
645 const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
646 return Clipboard::GetFilenameFormatType();
650 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
651 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML));
656 const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
657 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF));
662 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
663 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap));
668 const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
669 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste));
674 const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
675 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
680 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
681 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));