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_aura.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/geometry/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.
44 : web_smart_paste_(false),
47 virtual ~ClipboardData() {}
49 // Bitmask of AuraClipboardFormat types.
50 int format() const { return format_
; }
52 const std::string
& text() const { return text_
; }
53 void set_text(const std::string
& text
) {
58 const std::string
& markup_data() const { return markup_data_
; }
59 void set_markup_data(const std::string
& markup_data
) {
60 markup_data_
= markup_data
;
64 const std::string
& rtf_data() const { return rtf_data_
; }
65 void SetRTFData(const std::string
& rtf_data
) {
70 const std::string
& url() const { return url_
; }
71 void set_url(const std::string
& url
) {
76 const std::string
& bookmark_title() const { return bookmark_title_
; }
77 void set_bookmark_title(const std::string
& bookmark_title
) {
78 bookmark_title_
= bookmark_title
;
82 const std::string
& bookmark_url() const { return bookmark_url_
; }
83 void set_bookmark_url(const std::string
& bookmark_url
) {
84 bookmark_url_
= bookmark_url
;
88 const SkBitmap
& bitmap() const { return bitmap_
; }
89 void SetBitmapData(const SkBitmap
& bitmap
) {
90 bitmap
.copyTo(&bitmap_
);
94 const std::string
& custom_data_format() const { return custom_data_format_
; }
95 const std::string
& custom_data_data() const { return custom_data_data_
; }
96 void SetCustomData(const std::string
& data_format
,
97 const std::string
& data_data
) {
98 if (data_data
.size() == 0) {
99 custom_data_data_
.clear();
100 custom_data_format_
.clear();
103 custom_data_data_
= data_data
;
104 custom_data_format_
= data_format
;
108 bool web_smart_paste() const { return web_smart_paste_
; }
109 void set_web_smart_paste(bool web_smart_paste
) {
110 web_smart_paste_
= web_smart_paste
;
115 // Plain text in UTF8 format.
118 // HTML markup data in UTF8 format.
119 std::string markup_data_
;
123 std::string rtf_data_
;
125 // Bookmark title in UTF8 format.
126 std::string bookmark_title_
;
127 std::string bookmark_url_
;
130 std::vector
<std::string
> files_
;
135 // Data with custom format.
136 std::string custom_data_format_
;
137 std::string custom_data_data_
;
139 // WebKit smart paste data.
140 bool web_smart_paste_
;
144 DISALLOW_COPY_AND_ASSIGN(ClipboardData
);
147 // Platform clipboard implementation for Aura. This handles things like format
148 // conversion, versioning of clipboard items etc. The goal is to roughly provide
149 // a substitute to platform clipboards on other platforms such as GtkClipboard
150 // on gtk or winapi clipboard on win.
151 class AuraClipboard
{
153 AuraClipboard() : sequence_number_(0) {
162 STLDeleteContainerPointers(data_list_
.begin(), data_list_
.end());
166 uint64_t sequence_number() const {
167 return sequence_number_
;
170 // Returns the data currently on the top of the clipboard stack, NULL if the
171 // clipboard stack is empty.
172 const ClipboardData
* GetData() const {
173 if (data_list_
.empty())
175 return data_list_
.front();
178 // Returns true if the data on top of the clipboard stack has format |format|
179 // or another format that can be converted to |format|.
180 bool IsFormatAvailable(AuraClipboardFormat format
) const {
183 return HasFormat(TEXT
) || HasFormat(BOOKMARK
);
185 return HasFormat(format
);
189 // Reads text from the data at the top of clipboard stack.
190 void ReadText(base::string16
* result
) const {
191 std::string utf8_result
;
192 ReadAsciiText(&utf8_result
);
193 *result
= base::UTF8ToUTF16(utf8_result
);
196 // Reads ascii text from the data at the top of clipboard stack.
197 void ReadAsciiText(std::string
* result
) const {
199 const ClipboardData
* data
= GetData();
203 *result
= data
->text();
204 else if (HasFormat(HTML
))
205 *result
= data
->markup_data();
206 else if (HasFormat(BOOKMARK
))
207 *result
= data
->bookmark_url();
210 // Reads HTML from the data at the top of clipboard stack.
211 void ReadHTML(base::string16
* markup
,
212 std::string
* src_url
,
213 uint32
* fragment_start
,
214 uint32
* fragment_end
) const {
221 if (!HasFormat(HTML
))
224 const ClipboardData
* data
= GetData();
225 *markup
= base::UTF8ToUTF16(data
->markup_data());
226 *src_url
= data
->url();
229 DCHECK_LE(markup
->length(), kuint32max
);
230 *fragment_end
= static_cast<uint32
>(markup
->length());
233 // Reads RTF from the data at the top of clipboard stack.
234 void ReadRTF(std::string
* result
) const {
236 const ClipboardData
* data
= GetData();
240 *result
= data
->rtf_data();
243 // Reads image from the data at the top of clipboard stack.
244 SkBitmap
ReadImage() const {
246 if (!HasFormat(BITMAP
))
249 // A shallow copy should be fine here, but just to be safe...
250 const SkBitmap
& clipboard_bitmap
= GetData()->bitmap();
251 clipboard_bitmap
.copyTo(&img
);
255 // Reads data of type |type| from the data at the top of clipboard stack.
256 void ReadCustomData(const base::string16
& type
,
257 base::string16
* result
) const {
259 const ClipboardData
* data
= GetData();
260 if (!HasFormat(CUSTOM
))
263 ui::ReadCustomDataForType(data
->custom_data_data().c_str(),
264 data
->custom_data_data().size(),
268 // Reads bookmark from the data at the top of clipboard stack.
269 void ReadBookmark(base::string16
* title
, std::string
* url
) const {
272 if (!HasFormat(BOOKMARK
))
275 const ClipboardData
* data
= GetData();
276 *title
= base::UTF8ToUTF16(data
->bookmark_title());
277 *url
= data
->bookmark_url();
280 void ReadData(const std::string
& type
, std::string
* result
) const {
282 const ClipboardData
* data
= GetData();
283 if (!HasFormat(CUSTOM
) || type
!= data
->custom_data_format())
286 *result
= data
->custom_data_data();
289 // Writes |data| to the top of the clipboard stack.
290 void WriteData(ClipboardData
* data
) {
292 AddToListEnsuringSize(data
);
296 // True if the data on top of the clipboard stack has format |format|.
297 bool HasFormat(AuraClipboardFormat format
) const {
298 const ClipboardData
* data
= GetData();
302 return data
->format() & format
;
305 void AddToListEnsuringSize(ClipboardData
* data
) {
308 data_list_
.push_front(data
);
310 // If the size of list becomes more than the maximum allowed, we delete the
312 if (data_list_
.size() > kMaxClipboardSize
) {
313 ClipboardData
* last
= data_list_
.back();
314 data_list_
.pop_back();
319 // Stack containing various versions of ClipboardData.
320 std::list
<ClipboardData
*> data_list_
;
322 // Sequence number uniquely identifying clipboard state.
323 uint64_t sequence_number_
;
325 DISALLOW_COPY_AND_ASSIGN(AuraClipboard
);
328 AuraClipboard
* aura_clipboard
= NULL
;
330 AuraClipboard
* GetClipboard() {
332 aura_clipboard
= new AuraClipboard();
333 return aura_clipboard
;
336 void DeleteClipboard() {
338 delete aura_clipboard
;
339 aura_clipboard
= NULL
;
342 // Helper class to build a ClipboardData object and write it to clipboard.
343 class ClipboardDataBuilder
{
345 static void CommitToClipboard() {
346 GetClipboard()->WriteData(GetCurrentData());
347 current_data_
= NULL
;
350 static void WriteText(const char* text_data
, size_t text_len
) {
351 ClipboardData
* data
= GetCurrentData();
352 data
->set_text(std::string(text_data
, text_len
));
355 static void WriteHTML(const char* markup_data
,
357 const char* url_data
,
359 ClipboardData
* data
= GetCurrentData();
360 data
->set_markup_data(std::string(markup_data
, markup_len
));
361 data
->set_url(std::string(url_data
, url_len
));
364 static void WriteRTF(const char* rtf_data
, size_t rtf_len
) {
365 ClipboardData
* data
= GetCurrentData();
366 data
->SetRTFData(std::string(rtf_data
, rtf_len
));
369 static void WriteBookmark(const char* title_data
,
371 const char* url_data
,
373 ClipboardData
* data
= GetCurrentData();
374 data
->set_bookmark_title(std::string(title_data
, title_len
));
375 data
->set_bookmark_url(std::string(url_data
, url_len
));
378 static void WriteWebSmartPaste() {
379 ClipboardData
* data
= GetCurrentData();
380 data
->set_web_smart_paste(true);
383 static void WriteBitmap(const SkBitmap
& bitmap
) {
384 ClipboardData
* data
= GetCurrentData();
385 data
->SetBitmapData(bitmap
);
388 static void WriteData(const std::string
& format
,
389 const char* data_data
,
391 ClipboardData
* data
= GetCurrentData();
392 data
->SetCustomData(format
, std::string(data_data
, data_len
));
396 static ClipboardData
* GetCurrentData() {
398 current_data_
= new ClipboardData
;
399 return current_data_
;
402 static ClipboardData
* current_data_
;
405 ClipboardData
* ClipboardDataBuilder::current_data_
= NULL
;
409 // Clipboard::FormatType implementation.
410 Clipboard::FormatType::FormatType() {
413 Clipboard::FormatType::FormatType(const std::string
& native_format
)
414 : data_(native_format
) {
417 Clipboard::FormatType::~FormatType() {
420 std::string
Clipboard::FormatType::Serialize() const {
425 Clipboard::FormatType
Clipboard::FormatType::Deserialize(
426 const std::string
& serialization
) {
427 return FormatType(serialization
);
430 bool Clipboard::FormatType::operator<(const FormatType
& other
) const {
431 return data_
< other
.data_
;
434 bool Clipboard::FormatType::Equals(const FormatType
& other
) const {
435 return data_
== other
.data_
;
438 // Various predefined FormatTypes.
440 Clipboard::FormatType
Clipboard::GetFormatType(
441 const std::string
& format_string
) {
442 return FormatType::Deserialize(format_string
);
446 const Clipboard::FormatType
& Clipboard::GetUrlFormatType() {
447 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeURIList
));
452 const Clipboard::FormatType
& Clipboard::GetUrlWFormatType() {
453 return GetUrlFormatType();
457 const Clipboard::FormatType
& Clipboard::GetPlainTextFormatType() {
458 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeText
));
463 const Clipboard::FormatType
& Clipboard::GetPlainTextWFormatType() {
464 return GetPlainTextFormatType();
468 const Clipboard::FormatType
& Clipboard::GetFilenameFormatType() {
469 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeFilename
));
474 const Clipboard::FormatType
& Clipboard::GetFilenameWFormatType() {
475 return Clipboard::GetFilenameFormatType();
479 const Clipboard::FormatType
& Clipboard::GetHtmlFormatType() {
480 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeHTML
));
485 const Clipboard::FormatType
& Clipboard::GetRtfFormatType() {
486 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeRTF
));
491 const Clipboard::FormatType
& Clipboard::GetBitmapFormatType() {
492 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeBitmap
));
497 const Clipboard::FormatType
& Clipboard::GetWebKitSmartPasteFormatType() {
498 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeWebkitSmartPaste
));
503 const Clipboard::FormatType
& Clipboard::GetWebCustomDataFormatType() {
504 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypeWebCustomData
));
509 const Clipboard::FormatType
& Clipboard::GetPepperCustomDataFormatType() {
510 CR_DEFINE_STATIC_LOCAL(FormatType
, type
, (kMimeTypePepperCustomData
));
514 // Clipboard factory method.
515 Clipboard
* Clipboard::Create() {
516 return new ClipboardAura
;
519 // ClipboardAura implementation.
520 ClipboardAura::ClipboardAura() {
521 DCHECK(CalledOnValidThread());
522 // Make sure clipboard is created.
526 ClipboardAura::~ClipboardAura() {
527 DCHECK(CalledOnValidThread());
531 uint64
ClipboardAura::GetSequenceNumber(ClipboardType type
) const {
532 DCHECK(CalledOnValidThread());
533 return GetClipboard()->sequence_number();
536 bool ClipboardAura::IsFormatAvailable(const FormatType
& format
,
537 ClipboardType type
) const {
538 DCHECK(CalledOnValidThread());
539 DCHECK(IsSupportedClipboardType(type
));
540 AuraClipboard
* clipboard
= GetClipboard();
541 if (GetPlainTextFormatType().Equals(format
) ||
542 GetUrlFormatType().Equals(format
))
543 return clipboard
->IsFormatAvailable(TEXT
);
544 else if (GetHtmlFormatType().Equals(format
))
545 return clipboard
->IsFormatAvailable(HTML
);
546 else if (GetRtfFormatType().Equals(format
))
547 return clipboard
->IsFormatAvailable(RTF
);
548 else if (GetBitmapFormatType().Equals(format
))
549 return clipboard
->IsFormatAvailable(BITMAP
);
550 else if (GetWebKitSmartPasteFormatType().Equals(format
))
551 return clipboard
->IsFormatAvailable(WEB
);
553 const ClipboardData
* data
= clipboard
->GetData();
554 if (data
&& data
->custom_data_format() == format
.ToString())
560 void ClipboardAura::Clear(ClipboardType type
) {
561 DCHECK(CalledOnValidThread());
562 DCHECK(IsSupportedClipboardType(type
));
563 AuraClipboard
* clipboard
= GetClipboard();
567 void ClipboardAura::ReadAvailableTypes(ClipboardType type
,
568 std::vector
<base::string16
>* types
,
569 bool* contains_filenames
) const {
570 DCHECK(CalledOnValidThread());
571 if (!types
|| !contains_filenames
) {
577 *contains_filenames
= false;
578 if (IsFormatAvailable(GetPlainTextFormatType(), type
))
579 types
->push_back(base::UTF8ToUTF16(GetPlainTextFormatType().ToString()));
580 if (IsFormatAvailable(GetHtmlFormatType(), type
))
581 types
->push_back(base::UTF8ToUTF16(GetHtmlFormatType().ToString()));
582 if (IsFormatAvailable(GetRtfFormatType(), type
))
583 types
->push_back(base::UTF8ToUTF16(GetRtfFormatType().ToString()));
584 if (IsFormatAvailable(GetBitmapFormatType(), type
))
585 types
->push_back(base::UTF8ToUTF16(kMimeTypePNG
));
587 AuraClipboard
* clipboard
= GetClipboard();
588 if (clipboard
->IsFormatAvailable(CUSTOM
) && clipboard
->GetData()) {
589 ui::ReadCustomDataTypes(clipboard
->GetData()->custom_data_data().c_str(),
590 clipboard
->GetData()->custom_data_data().size(), types
);
594 void ClipboardAura::ReadText(ClipboardType type
, base::string16
* result
) const {
595 DCHECK(CalledOnValidThread());
596 GetClipboard()->ReadText(result
);
599 void ClipboardAura::ReadAsciiText(ClipboardType type
,
600 std::string
* result
) const {
601 DCHECK(CalledOnValidThread());
602 GetClipboard()->ReadAsciiText(result
);
605 void ClipboardAura::ReadHTML(ClipboardType type
,
606 base::string16
* markup
,
607 std::string
* src_url
,
608 uint32
* fragment_start
,
609 uint32
* fragment_end
) const {
610 DCHECK(CalledOnValidThread());
611 GetClipboard()->ReadHTML(markup
, src_url
, fragment_start
, fragment_end
);
614 void ClipboardAura::ReadRTF(ClipboardType type
, std::string
* result
) const {
615 DCHECK(CalledOnValidThread());
616 GetClipboard()->ReadRTF(result
);
619 SkBitmap
ClipboardAura::ReadImage(ClipboardType type
) const {
620 DCHECK(CalledOnValidThread());
621 return GetClipboard()->ReadImage();
624 void ClipboardAura::ReadCustomData(ClipboardType clipboard_type
,
625 const base::string16
& type
,
626 base::string16
* result
) const {
627 DCHECK(CalledOnValidThread());
628 GetClipboard()->ReadCustomData(type
, result
);
631 void ClipboardAura::ReadBookmark(base::string16
* title
,
632 std::string
* url
) const {
633 DCHECK(CalledOnValidThread());
634 GetClipboard()->ReadBookmark(title
, url
);
637 void ClipboardAura::ReadData(const FormatType
& format
,
638 std::string
* result
) const {
639 DCHECK(CalledOnValidThread());
640 GetClipboard()->ReadData(format
.ToString(), result
);
643 void ClipboardAura::WriteObjects(ClipboardType type
, const ObjectMap
& objects
) {
644 DCHECK(CalledOnValidThread());
645 DCHECK(IsSupportedClipboardType(type
));
646 for (ObjectMap::const_iterator iter
= objects
.begin(); iter
!= objects
.end();
648 DispatchObject(static_cast<ObjectType
>(iter
->first
), iter
->second
);
650 ClipboardDataBuilder::CommitToClipboard();
653 void ClipboardAura::WriteText(const char* text_data
, size_t text_len
) {
654 ClipboardDataBuilder::WriteText(text_data
, text_len
);
657 void ClipboardAura::WriteHTML(const char* markup_data
,
659 const char* url_data
,
661 ClipboardDataBuilder::WriteHTML(markup_data
, markup_len
, url_data
, url_len
);
664 void ClipboardAura::WriteRTF(const char* rtf_data
, size_t data_len
) {
665 ClipboardDataBuilder::WriteRTF(rtf_data
, data_len
);
668 void ClipboardAura::WriteBookmark(const char* title_data
,
670 const char* url_data
,
672 ClipboardDataBuilder::WriteBookmark(title_data
, title_len
, url_data
, url_len
);
675 void ClipboardAura::WriteWebSmartPaste() {
676 ClipboardDataBuilder::WriteWebSmartPaste();
679 void ClipboardAura::WriteBitmap(const SkBitmap
& bitmap
) {
680 ClipboardDataBuilder::WriteBitmap(bitmap
);
683 void ClipboardAura::WriteData(const FormatType
& format
,
684 const char* data_data
,
686 ClipboardDataBuilder::WriteData(format
.ToString(), data_data
, data_len
);