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.
4
5 #include "ui/base/clipboard/scoped_clipboard_writer.h"
6
7 #include "base/pickle.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "net/base/escape.h"
10 #include "ui/base/clipboard/clipboard_format_type.h"
11 #include "ui/gfx/geometry/size.h"
12
13 // Documentation on the format of the parameters for each clipboard target can
14 // be found in clipboard.h.
15 namespace ui {
16
ScopedClipboardWriter(ClipboardBuffer buffer)17 ScopedClipboardWriter::ScopedClipboardWriter(ClipboardBuffer buffer)
18 : buffer_(buffer) {}
19
~ScopedClipboardWriter()20 ScopedClipboardWriter::~ScopedClipboardWriter() {
21 static constexpr size_t kMaxRepresentations = 1 << 12;
22 DCHECK(objects_.empty() || platform_representations_.empty())
23 << "Portable and Platform representations should not be written on the "
24 "same write.";
25 DCHECK(platform_representations_.size() < kMaxRepresentations);
26 if (!objects_.empty()) {
27 Clipboard::GetForCurrentThread()->WritePortableRepresentations(buffer_,
28 objects_);
29 }
30 if (!platform_representations_.empty()) {
31 Clipboard::GetForCurrentThread()->WritePlatformRepresentations(
32 buffer_, std::move(platform_representations_));
33 }
34 }
35
WriteText(const base::string16 & text)36 void ScopedClipboardWriter::WriteText(const base::string16& text) {
37 std::string utf8_text = base::UTF16ToUTF8(text);
38
39 Clipboard::ObjectMapParams parameters;
40 parameters.push_back(
41 Clipboard::ObjectMapParam(utf8_text.begin(), utf8_text.end()));
42 objects_[Clipboard::PortableFormat::kText] = parameters;
43 }
44
WriteHTML(const base::string16 & markup,const std::string & source_url)45 void ScopedClipboardWriter::WriteHTML(const base::string16& markup,
46 const std::string& source_url) {
47 std::string utf8_markup = base::UTF16ToUTF8(markup);
48
49 Clipboard::ObjectMapParams parameters;
50 parameters.push_back(
51 Clipboard::ObjectMapParam(utf8_markup.begin(),
52 utf8_markup.end()));
53 if (!source_url.empty()) {
54 parameters.push_back(Clipboard::ObjectMapParam(source_url.begin(),
55 source_url.end()));
56 }
57
58 objects_[Clipboard::PortableFormat::kHtml] = parameters;
59 }
60
WriteRTF(const std::string & rtf_data)61 void ScopedClipboardWriter::WriteRTF(const std::string& rtf_data) {
62 Clipboard::ObjectMapParams parameters;
63 parameters.push_back(Clipboard::ObjectMapParam(rtf_data.begin(),
64 rtf_data.end()));
65 objects_[Clipboard::PortableFormat::kRtf] = parameters;
66 }
67
WriteBookmark(const base::string16 & bookmark_title,const std::string & url)68 void ScopedClipboardWriter::WriteBookmark(const base::string16& bookmark_title,
69 const std::string& url) {
70 if (bookmark_title.empty() || url.empty())
71 return;
72
73 std::string utf8_markup = base::UTF16ToUTF8(bookmark_title);
74
75 Clipboard::ObjectMapParams parameters;
76 parameters.push_back(Clipboard::ObjectMapParam(utf8_markup.begin(),
77 utf8_markup.end()));
78 parameters.push_back(Clipboard::ObjectMapParam(url.begin(), url.end()));
79 objects_[Clipboard::PortableFormat::kBookmark] = parameters;
80 }
81
WriteHyperlink(const base::string16 & anchor_text,const std::string & url)82 void ScopedClipboardWriter::WriteHyperlink(const base::string16& anchor_text,
83 const std::string& url) {
84 if (anchor_text.empty() || url.empty())
85 return;
86
87 // Construct the hyperlink.
88 std::string html = "<a href=\"";
89 html += net::EscapeForHTML(url);
90 html += "\">";
91 html += net::EscapeForHTML(base::UTF16ToUTF8(anchor_text));
92 html += "</a>";
93 WriteHTML(base::UTF8ToUTF16(html), std::string());
94 }
95
WriteWebSmartPaste()96 void ScopedClipboardWriter::WriteWebSmartPaste() {
97 objects_[Clipboard::PortableFormat::kWebkit] = Clipboard::ObjectMapParams();
98 }
99
WriteImage(const SkBitmap & bitmap)100 void ScopedClipboardWriter::WriteImage(const SkBitmap& bitmap) {
101 if (bitmap.drawsNothing())
102 return;
103 DCHECK(bitmap.getPixels());
104
105 bitmap_ = bitmap;
106 // TODO(dcheng): This is slightly less horrible than what we used to do, but
107 // only very slightly less.
108 SkBitmap* bitmap_pointer = &bitmap_;
109 Clipboard::ObjectMapParam packed_pointer;
110 packed_pointer.resize(sizeof(bitmap_pointer));
111 *reinterpret_cast<SkBitmap**>(&*packed_pointer.begin()) = bitmap_pointer;
112 Clipboard::ObjectMapParams parameters;
113 parameters.push_back(packed_pointer);
114 objects_[Clipboard::PortableFormat::kBitmap] = parameters;
115 }
116
WritePickledData(const base::Pickle & pickle,const ClipboardFormatType & format)117 void ScopedClipboardWriter::WritePickledData(
118 const base::Pickle& pickle,
119 const ClipboardFormatType& format) {
120 std::string format_string = format.Serialize();
121 Clipboard::ObjectMapParam format_parameter(format_string.begin(),
122 format_string.end());
123 Clipboard::ObjectMapParam data_parameter;
124
125 data_parameter.resize(pickle.size());
126 memcpy(const_cast<char*>(&data_parameter.front()),
127 pickle.data(), pickle.size());
128
129 Clipboard::ObjectMapParams parameters;
130 parameters.push_back(format_parameter);
131 parameters.push_back(data_parameter);
132 objects_[Clipboard::PortableFormat::kData] = parameters;
133 }
134
WriteData(const base::string16 & format,mojo_base::BigBuffer data)135 void ScopedClipboardWriter::WriteData(const base::string16& format,
136 mojo_base::BigBuffer data) {
137 // Conservative limit to maximum format and data string size, to avoid
138 // potential attacks with long strings. Callers should implement similar
139 // checks.
140 constexpr size_t kMaxFormatSize = 1024;
141 constexpr size_t kMaxDataSize = 1 << 30; // 1 GB
142 DCHECK_LT(format.size(), kMaxFormatSize);
143 DCHECK_LT(data.size(), kMaxDataSize);
144
145 platform_representations_.push_back(
146 {base::UTF16ToUTF8(format), std::move(data)});
147 }
148
Reset()149 void ScopedClipboardWriter::Reset() {
150 objects_.clear();
151 platform_representations_.clear();
152 bitmap_.reset();
153 }
154
155 } // namespace ui
156