1 // Copyright 2017 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 "headless/lib/browser/headless_clipboard.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "ui/base/clipboard/clipboard_constants.h"
11
12 namespace headless {
13
HeadlessClipboard()14 HeadlessClipboard::HeadlessClipboard()
15 : default_store_buffer_(ui::ClipboardBuffer::kCopyPaste) {}
16
17 HeadlessClipboard::~HeadlessClipboard() = default;
18
OnPreShutdown()19 void HeadlessClipboard::OnPreShutdown() {}
20
GetSequenceNumber(ui::ClipboardBuffer buffer) const21 uint64_t HeadlessClipboard::GetSequenceNumber(
22 ui::ClipboardBuffer buffer) const {
23 return GetStore(buffer).sequence_number;
24 }
25
IsFormatAvailable(const ui::ClipboardFormatType & format,ui::ClipboardBuffer buffer) const26 bool HeadlessClipboard::IsFormatAvailable(const ui::ClipboardFormatType& format,
27 ui::ClipboardBuffer buffer) const {
28 return base::Contains(GetStore(buffer).data, format);
29 }
30
Clear(ui::ClipboardBuffer buffer)31 void HeadlessClipboard::Clear(ui::ClipboardBuffer buffer) {
32 GetStore(buffer).Clear();
33 }
34
ReadAvailableTypes(ui::ClipboardBuffer buffer,std::vector<base::string16> * types,bool * contains_filenames) const35 void HeadlessClipboard::ReadAvailableTypes(ui::ClipboardBuffer buffer,
36 std::vector<base::string16>* types,
37 bool* contains_filenames) const {
38 types->clear();
39
40 if (IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(), buffer))
41 types->push_back(base::UTF8ToUTF16(ui::kMimeTypeText));
42 if (IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(), buffer))
43 types->push_back(base::UTF8ToUTF16(ui::kMimeTypeHTML));
44
45 if (IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(), buffer))
46 types->push_back(base::UTF8ToUTF16(ui::kMimeTypeRTF));
47 if (IsFormatAvailable(ui::ClipboardFormatType::GetBitmapType(), buffer))
48 types->push_back(base::UTF8ToUTF16(ui::kMimeTypePNG));
49
50 *contains_filenames = false;
51 }
52
53 std::vector<base::string16>
ReadAvailablePlatformSpecificFormatNames(ui::ClipboardBuffer buffer) const54 HeadlessClipboard::ReadAvailablePlatformSpecificFormatNames(
55 ui::ClipboardBuffer buffer) const {
56 const auto& data = GetStore(buffer).data;
57 std::vector<base::string16> types;
58 types.reserve(data.size());
59 for (const auto& it : data) {
60 base::string16 type = base::UTF8ToUTF16(it.first.GetName());
61 types.push_back(type);
62 }
63
64 return types;
65 }
66
ReadText(ui::ClipboardBuffer buffer,base::string16 * result) const67 void HeadlessClipboard::ReadText(ui::ClipboardBuffer buffer,
68 base::string16* result) const {
69 std::string result8;
70 ReadAsciiText(buffer, &result8);
71 *result = base::UTF8ToUTF16(result8);
72 }
73
ReadAsciiText(ui::ClipboardBuffer buffer,std::string * result) const74 void HeadlessClipboard::ReadAsciiText(ui::ClipboardBuffer buffer,
75 std::string* result) const {
76 result->clear();
77 const DataStore& store = GetStore(buffer);
78 auto it = store.data.find(ui::ClipboardFormatType::GetPlainTextType());
79 if (it != store.data.end())
80 *result = it->second;
81 }
82
ReadHTML(ui::ClipboardBuffer buffer,base::string16 * markup,std::string * src_url,uint32_t * fragment_start,uint32_t * fragment_end) const83 void HeadlessClipboard::ReadHTML(ui::ClipboardBuffer buffer,
84 base::string16* markup,
85 std::string* src_url,
86 uint32_t* fragment_start,
87 uint32_t* fragment_end) const {
88 markup->clear();
89 src_url->clear();
90 const DataStore& store = GetStore(buffer);
91 auto it = store.data.find(ui::ClipboardFormatType::GetHtmlType());
92 if (it != store.data.end())
93 *markup = base::UTF8ToUTF16(it->second);
94 *src_url = store.html_src_url;
95 *fragment_start = 0;
96 *fragment_end = base::checked_cast<uint32_t>(markup->size());
97 }
98
ReadRTF(ui::ClipboardBuffer buffer,std::string * result) const99 void HeadlessClipboard::ReadRTF(ui::ClipboardBuffer buffer,
100 std::string* result) const {
101 result->clear();
102 const DataStore& store = GetStore(buffer);
103 auto it = store.data.find(ui::ClipboardFormatType::GetRtfType());
104 if (it != store.data.end())
105 *result = it->second;
106 }
107
ReadImage(ui::ClipboardBuffer buffer,ReadImageCallback callback) const108 void HeadlessClipboard::ReadImage(ui::ClipboardBuffer buffer,
109 ReadImageCallback callback) const {
110 std::move(callback).Run(GetStore(buffer).image);
111 }
112
ReadCustomData(ui::ClipboardBuffer clipboard_buffer,const base::string16 & type,base::string16 * result) const113 void HeadlessClipboard::ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
114 const base::string16& type,
115 base::string16* result) const {}
116
ReadBookmark(base::string16 * title,std::string * url) const117 void HeadlessClipboard::ReadBookmark(base::string16* title,
118 std::string* url) const {
119 const DataStore& store = GetDefaultStore();
120 auto it = store.data.find(ui::ClipboardFormatType::GetUrlType());
121 if (it != store.data.end())
122 *url = it->second;
123 *title = base::UTF8ToUTF16(store.url_title);
124 }
125
ReadData(const ui::ClipboardFormatType & format,std::string * result) const126 void HeadlessClipboard::ReadData(const ui::ClipboardFormatType& format,
127 std::string* result) const {
128 result->clear();
129 const DataStore& store = GetDefaultStore();
130 auto it = store.data.find(format);
131 if (it != store.data.end())
132 *result = it->second;
133 }
134
WritePortableRepresentations(ui::ClipboardBuffer buffer,const ObjectMap & objects)135 void HeadlessClipboard::WritePortableRepresentations(ui::ClipboardBuffer buffer,
136 const ObjectMap& objects) {
137 Clear(buffer);
138 default_store_buffer_ = buffer;
139 for (const auto& kv : objects)
140 DispatchPortableRepresentation(kv.first, kv.second);
141 default_store_buffer_ = ui::ClipboardBuffer::kCopyPaste;
142 }
143
WritePlatformRepresentations(ui::ClipboardBuffer buffer,std::vector<Clipboard::PlatformRepresentation> platform_representations)144 void HeadlessClipboard::WritePlatformRepresentations(
145 ui::ClipboardBuffer buffer,
146 std::vector<Clipboard::PlatformRepresentation> platform_representations) {
147 Clear(buffer);
148 default_store_buffer_ = buffer;
149 DispatchPlatformRepresentations(std::move(platform_representations));
150 default_store_buffer_ = ui::ClipboardBuffer::kCopyPaste;
151 }
152
WriteText(const char * text_data,size_t text_len)153 void HeadlessClipboard::WriteText(const char* text_data, size_t text_len) {
154 std::string text(text_data, text_len);
155 GetDefaultStore().data[ui::ClipboardFormatType::GetPlainTextType()] = text;
156 if (IsSupportedClipboardBuffer(ui::ClipboardBuffer::kSelection)) {
157 GetStore(ui::ClipboardBuffer::kSelection)
158 .data[ui::ClipboardFormatType::GetPlainTextType()] = text;
159 }
160 }
161
WriteHTML(const char * markup_data,size_t markup_len,const char * url_data,size_t url_len)162 void HeadlessClipboard::WriteHTML(const char* markup_data,
163 size_t markup_len,
164 const char* url_data,
165 size_t url_len) {
166 base::string16 markup;
167 base::UTF8ToUTF16(markup_data, markup_len, &markup);
168 GetDefaultStore().data[ui::ClipboardFormatType::GetHtmlType()] =
169 base::UTF16ToUTF8(markup);
170 GetDefaultStore().html_src_url = std::string(url_data, url_len);
171 }
172
WriteRTF(const char * rtf_data,size_t data_len)173 void HeadlessClipboard::WriteRTF(const char* rtf_data, size_t data_len) {
174 GetDefaultStore().data[ui::ClipboardFormatType::GetRtfType()] =
175 std::string(rtf_data, data_len);
176 }
177
WriteBookmark(const char * title_data,size_t title_len,const char * url_data,size_t url_len)178 void HeadlessClipboard::WriteBookmark(const char* title_data,
179 size_t title_len,
180 const char* url_data,
181 size_t url_len) {
182 GetDefaultStore().data[ui::ClipboardFormatType::GetUrlType()] =
183 std::string(url_data, url_len);
184 GetDefaultStore().url_title = std::string(title_data, title_len);
185 }
186
WriteWebSmartPaste()187 void HeadlessClipboard::WriteWebSmartPaste() {
188 // Create a dummy entry.
189 GetDefaultStore().data[ui::ClipboardFormatType::GetWebKitSmartPasteType()];
190 }
191
WriteBitmap(const SkBitmap & bitmap)192 void HeadlessClipboard::WriteBitmap(const SkBitmap& bitmap) {
193 // Create a dummy entry.
194 GetDefaultStore().data[ui::ClipboardFormatType::GetBitmapType()];
195 SkBitmap& dst = GetDefaultStore().image;
196 if (dst.tryAllocPixels(bitmap.info())) {
197 bitmap.readPixels(dst.info(), dst.getPixels(), dst.rowBytes(), 0, 0);
198 }
199 }
200
WriteData(const ui::ClipboardFormatType & format,const char * data_data,size_t data_len)201 void HeadlessClipboard::WriteData(const ui::ClipboardFormatType& format,
202 const char* data_data,
203 size_t data_len) {
204 GetDefaultStore().data[format] = std::string(data_data, data_len);
205 }
206
DataStore()207 HeadlessClipboard::DataStore::DataStore() : sequence_number(0) {}
208
209 HeadlessClipboard::DataStore::DataStore(const DataStore& other) = default;
210
211 HeadlessClipboard::DataStore::~DataStore() = default;
212
Clear()213 void HeadlessClipboard::DataStore::Clear() {
214 data.clear();
215 url_title.clear();
216 html_src_url.clear();
217 image = SkBitmap();
218 }
219
GetStore(ui::ClipboardBuffer buffer) const220 const HeadlessClipboard::DataStore& HeadlessClipboard::GetStore(
221 ui::ClipboardBuffer buffer) const {
222 CHECK(IsSupportedClipboardBuffer(buffer));
223 return stores_[buffer];
224 }
225
GetStore(ui::ClipboardBuffer buffer)226 HeadlessClipboard::DataStore& HeadlessClipboard::GetStore(
227 ui::ClipboardBuffer buffer) {
228 CHECK(IsSupportedClipboardBuffer(buffer));
229 DataStore& store = stores_[buffer];
230 ++store.sequence_number;
231 return store;
232 }
233
GetDefaultStore() const234 const HeadlessClipboard::DataStore& HeadlessClipboard::GetDefaultStore() const {
235 return GetStore(default_store_buffer_);
236 }
237
GetDefaultStore()238 HeadlessClipboard::DataStore& HeadlessClipboard::GetDefaultStore() {
239 return GetStore(default_store_buffer_);
240 }
241
242 } // namespace headless
243