1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "adapter/ohos/capability/clipboard/clipboard_impl.h"
17 #include <vector>
18
19 #include "adapter/ohos/osal/pixel_map_ohos.h"
20 #include "adapter/ohos/capability/html/html_to_span.h"
21 #include "base/log/log_wrapper.h"
22 #include "base/utils/utils.h"
23 #include "core/components_ng/pattern/text/span/span_string.h"
24
25 namespace OHOS::Ace {
26 #ifndef SYSTEM_CLIPBOARD_SUPPORTED
27 namespace {
28 std::string g_clipboard;
29 RefPtr<PixelMap> g_pixmap;
30 } // namespace
31 #endif
32
33 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
TransitionCopyOption(CopyOptions copyOption)34 MiscServices::ShareOption TransitionCopyOption(CopyOptions copyOption)
35 {
36 auto shareOption = MiscServices::ShareOption::InApp;
37 switch (copyOption) {
38 case CopyOptions::InApp:
39 shareOption = MiscServices::ShareOption::InApp;
40 break;
41 case CopyOptions::Local:
42 shareOption = MiscServices::ShareOption::LocalDevice;
43 break;
44 case CopyOptions::Distributed:
45 shareOption = MiscServices::ShareOption::CrossDevice;
46 break;
47 default:
48 break;
49 }
50 return shareOption;
51 }
52
53 const std::string SPAN_STRING_TAG = "openharmony.styled-string";
54 #endif
55
HasData(const std::function<void (bool hasData)> & callback)56 void ClipboardImpl::HasData(const std::function<void(bool hasData)>& callback)
57 {
58 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
59 bool hasData = false;
60 CHECK_NULL_VOID(taskExecutor_);
61 taskExecutor_->PostSyncTask(
62 [&hasData]() { hasData = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData(); },
63 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardHasData");
64 callback(hasData);
65 #endif
66 }
67
HasDataType(const std::function<void (bool hasData)> & callback,const std::vector<std::string> & mimeTypes)68 void ClipboardImpl::HasDataType(
69 const std::function<void(bool hasData)>& callback, const std::vector<std::string>& mimeTypes)
70 {
71 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
72 bool hasData = false;
73 CHECK_NULL_VOID(taskExecutor_);
74 taskExecutor_->PostSyncTask(
75 [&hasData, mimeTypes]() {
76 for (auto mimeType = mimeTypes.begin(); mimeType != mimeTypes.end(); ++mimeType) {
77 hasData = OHOS::MiscServices::PasteboardClient::GetInstance()->HasDataType(*mimeType);
78 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "Clipboard data mimeType %{public}s available ? %{public}d",
79 mimeType->c_str(), hasData);
80 if (hasData) {
81 break;
82 }
83 }
84 },
85 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardHasDataType");
86 callback(hasData);
87 #endif
88 }
89
SetData(const std::string & data,CopyOptions copyOption,bool isDragData)90 void ClipboardImpl::SetData(const std::string& data, CopyOptions copyOption, bool isDragData)
91 {
92 CHECK_NULL_VOID(taskExecutor_);
93 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
94 auto shareOption = TransitionCopyOption(copyOption);
95 taskExecutor_->PostTask(
96 [data, shareOption, isDragData]() {
97 auto pasteData = OHOS::MiscServices::PasteboardClient::GetInstance()->CreatePlainTextData(data);
98 CHECK_NULL_VOID(pasteData);
99 pasteData->SetShareOption(shareOption);
100 pasteData->SetDraggedDataFlag(isDragData);
101 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
102 },
103 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardSetDataWithCopyOption");
104 #else
105 taskExecutor_->PostTask(
106 [data]() { g_clipboard = data; }, TaskExecutor::TaskType::UI, "ArkUIClipboardSetTextPasteData");
107 #endif
108 }
109
SetPixelMapData(const RefPtr<PixelMap> & pixmap,CopyOptions copyOption)110 void ClipboardImpl::SetPixelMapData(const RefPtr<PixelMap>& pixmap, CopyOptions copyOption)
111 {
112 CHECK_NULL_VOID(taskExecutor_);
113 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
114 auto shareOption = TransitionCopyOption(copyOption);
115 taskExecutor_->PostTask(
116 [pixmap, shareOption]() {
117 CHECK_NULL_VOID(pixmap);
118 auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
119 CHECK_NULL_VOID(pixmapOhos);
120 auto pasteData = OHOS::MiscServices::PasteboardClient::GetInstance()->CreatePixelMapData(
121 pixmapOhos->GetPixelMapSharedPtr());
122 CHECK_NULL_VOID(pasteData);
123 pasteData->SetShareOption(shareOption);
124 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "Set pixmap to system clipboard");
125 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
126 },
127 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardSetPixelMapWithCopyOption");
128 #else
129 taskExecutor_->PostTask(
130 [pixmap]() { g_pixmap = pixmap; }, TaskExecutor::TaskType::UI, "ArkUIClipboardSetImagePasteData");
131 #endif
132 }
133
GetData(const std::function<void (const std::string &)> & callback,bool syncMode)134 void ClipboardImpl::GetData(const std::function<void(const std::string&)>& callback, bool syncMode)
135 {
136 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
137 if (!taskExecutor_ || !callback) {
138 return;
139 }
140
141 if (syncMode) {
142 GetDataSync(callback);
143 } else {
144 GetDataAsync(callback);
145 }
146 #else
147 if (syncMode) {
148 callback(g_clipboard);
149 return;
150 }
151 CHECK_NULL_VOID(taskExecutor_);
152 taskExecutor_->PostTask(
153 [callback, taskExecutor = WeakClaim(RawPtr(taskExecutor_)), textData = g_clipboard]() {
154 callback(textData);
155 },
156 TaskExecutor::TaskType::UI, "ArkUIClipboardTextDataCallback");
157 #endif
158 }
159
GetPixelMapData(const std::function<void (const RefPtr<PixelMap> &)> & callback,bool syncMode)160 void ClipboardImpl::GetPixelMapData(const std::function<void(const RefPtr<PixelMap>&)>& callback, bool syncMode)
161 {
162 if (!taskExecutor_ || !callback) {
163 return;
164 }
165 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
166 if (syncMode) {
167 GetPixelMapDataSync(callback);
168 } else {
169 GetPixelMapDataAsync(callback);
170 }
171 #else
172 if (syncMode) {
173 callback(g_pixmap);
174 } else {
175 taskExecutor_->PostTask([callback, taskExecutor = WeakClaim(RawPtr(taskExecutor_)),
176 imageData = g_pixmap]() { callback(imageData); },
177 TaskExecutor::TaskType::UI, "ArkUIClipboardImageDataCallback");
178 }
179 #endif
180 }
181
CreatePasteDataMix()182 RefPtr<PasteDataMix> ClipboardImpl::CreatePasteDataMix()
183 {
184 return AceType::MakeRefPtr<PasteDataImpl>();
185 }
186
AddMultiTypeRecord(const RefPtr<PasteDataMix> & pasteData,const RefPtr<MultiTypeRecordMix> & multiTypeRecord)187 void ClipboardImpl::AddMultiTypeRecord(
188 const RefPtr<PasteDataMix>& pasteData, const RefPtr<MultiTypeRecordMix>& multiTypeRecord)
189 {
190 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
191 CHECK_NULL_VOID(taskExecutor_);
192 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
193 CHECK_NULL_VOID(peData);
194 auto multiTypeRecordImpl = AceType::DynamicCast<MultiTypeRecordImpl>(multiTypeRecord);
195 CHECK_NULL_VOID(multiTypeRecordImpl);
196
197 std::map<std::string, std::shared_ptr<OHOS::MiscServices::EntryValue>> multiTypeDataMap;
198 if (!multiTypeRecordImpl->GetPlainText().empty()) {
199 multiTypeDataMap[OHOS::MiscServices::MIMETYPE_TEXT_PLAIN] =
200 std::make_shared<OHOS::MiscServices::EntryValue>(multiTypeRecordImpl->GetPlainText());
201 }
202 if (!multiTypeRecordImpl->GetUri().empty()) {
203 multiTypeDataMap[OHOS::MiscServices::MIMETYPE_TEXT_URI] =
204 std::make_shared<OHOS::MiscServices::EntryValue>(multiTypeRecordImpl->GetUri());
205 }
206 if (multiTypeRecordImpl->GetPixelMap()) {
207 multiTypeDataMap[OHOS::MiscServices::MIMETYPE_PIXELMAP] =
208 std::make_shared<OHOS::MiscServices::EntryValue>(multiTypeRecordImpl->GetPixelMap());
209 }
210 if (!multiTypeRecordImpl->GetSpanStringBuffer().empty()) {
211 multiTypeDataMap[SPAN_STRING_TAG] =
212 std::make_shared<OHOS::MiscServices::EntryValue>(multiTypeRecordImpl->GetSpanStringBuffer());
213 }
214
215 auto entry =
216 std::make_shared<std::map<std::string, std::shared_ptr<OHOS::MiscServices::EntryValue>>>(multiTypeDataMap);
217 peData->GetPasteDataData()->AddRecord(
218 MiscServices::PasteDataRecord::NewMultiTypeRecord(entry, GetMimeType(multiTypeDataMap)));
219 #endif
220 }
221
222 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
GetMimeType(std::map<std::string,std::shared_ptr<OHOS::MiscServices::EntryValue>> multiTypeDataMap)223 const std::string ClipboardImpl::GetMimeType(
224 std::map<std::string, std::shared_ptr<OHOS::MiscServices::EntryValue>> multiTypeDataMap)
225 {
226 std::string mimeType;
227 if (multiTypeDataMap.find(SPAN_STRING_TAG) != multiTypeDataMap.end()) {
228 mimeType = SPAN_STRING_TAG;
229 }
230 if (multiTypeDataMap.find(OHOS::MiscServices::MIMETYPE_PIXELMAP) != multiTypeDataMap.end()) {
231 mimeType = OHOS::MiscServices::MIMETYPE_PIXELMAP;
232 }
233 if (multiTypeDataMap.find(OHOS::MiscServices::MIMETYPE_TEXT_URI) != multiTypeDataMap.end()) {
234 mimeType = OHOS::MiscServices::MIMETYPE_TEXT_URI;
235 }
236 if (multiTypeDataMap.find(OHOS::MiscServices::MIMETYPE_TEXT_PLAIN) != multiTypeDataMap.end()) {
237 mimeType = OHOS::MiscServices::MIMETYPE_TEXT_PLAIN;
238 }
239 return mimeType;
240 }
241 #endif
242
SetPlainText(const std::string plainText)243 void MultiTypeRecordImpl::SetPlainText(const std::string plainText)
244 {
245 plainText_ = plainText;
246 }
SetUri(const std::string uri)247 void MultiTypeRecordImpl::SetUri(const std::string uri)
248 {
249 uri_ = uri;
250 }
SetPixelMap(RefPtr<PixelMap> pixelMap)251 void MultiTypeRecordImpl::SetPixelMap(RefPtr<PixelMap> pixelMap)
252 {
253 pixelMap_ = pixelMap;
254 }
GetPixelMap()255 const RefPtr<PixelMap> MultiTypeRecordImpl::GetPixelMap()
256 {
257 return pixelMap_;
258 }
GetPlainText()259 const std::string MultiTypeRecordImpl::GetPlainText()
260 {
261 return plainText_;
262 }
GetUri()263 const std::string MultiTypeRecordImpl::GetUri()
264 {
265 return uri_;
266 }
GetSpanStringBuffer()267 std::vector<uint8_t>& MultiTypeRecordImpl::GetSpanStringBuffer()
268 {
269 return spanStringBuffer_;
270 }
271
AddPixelMapRecord(const RefPtr<PasteDataMix> & pasteData,const RefPtr<PixelMap> & pixmap)272 void ClipboardImpl::AddPixelMapRecord(const RefPtr<PasteDataMix>& pasteData, const RefPtr<PixelMap>& pixmap)
273 {
274 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
275 CHECK_NULL_VOID(taskExecutor_);
276 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
277 CHECK_NULL_VOID(peData);
278 auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
279 CHECK_NULL_VOID(pixmapOhos);
280 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add pixelMap record to pasteData");
281 peData->GetPasteDataData()->AddPixelMapRecord(pixmapOhos->GetPixelMapSharedPtr());
282 #endif
283 }
284
AddImageRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & uri)285 void ClipboardImpl::AddImageRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& uri)
286 {
287 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
288 CHECK_NULL_VOID(taskExecutor_);
289 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
290 CHECK_NULL_VOID(peData);
291 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add url %{private}s record to pasteData", uri.c_str());
292 peData->GetPasteDataData()->AddUriRecord(OHOS::Uri(uri));
293 #endif
294 }
295
AddTextRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & selectedStr)296 void ClipboardImpl::AddTextRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& selectedStr)
297 {
298 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
299 CHECK_NULL_VOID(taskExecutor_);
300 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
301 CHECK_NULL_VOID(peData);
302 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add text record to pasteData, length: %{public}d",
303 static_cast<int32_t>(StringUtils::ToWstring(selectedStr).length()));
304 peData->GetPasteDataData()->AddTextRecord(selectedStr);
305 #endif
306 }
307
AddSpanStringRecord(const RefPtr<PasteDataMix> & pasteData,std::vector<uint8_t> & data)308 void ClipboardImpl::AddSpanStringRecord(const RefPtr<PasteDataMix>& pasteData, std::vector<uint8_t>& data)
309 {
310 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
311 CHECK_NULL_VOID(taskExecutor_);
312 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
313 CHECK_NULL_VOID(peData);
314 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add spanstring record to pasteData, length: %{public}d",
315 static_cast<int32_t>(data.size()));
316 peData->GetPasteDataData()->AddKvRecord(SPAN_STRING_TAG, data);
317 #endif
318 }
319
SetData(const RefPtr<PasteDataMix> & pasteData,CopyOptions copyOption)320 void ClipboardImpl::SetData(const RefPtr<PasteDataMix>& pasteData, CopyOptions copyOption)
321 {
322 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
323 auto shareOption = TransitionCopyOption(copyOption);
324 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
325 CHECK_NULL_VOID(peData);
326 taskExecutor_->PostTask(
327 [peData, shareOption]() {
328 auto pasteData = peData->GetPasteDataData();
329 pasteData->SetShareOption(shareOption);
330 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add pasteData to clipboard, shareOption: %{public}d", shareOption);
331 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
332 },
333 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardSetMixDataWithCopyOption");
334 #endif
335 }
336
GetData(const std::function<void (const std::string &,bool isLastRecord)> & textCallback,const std::function<void (const RefPtr<PixelMap> &,bool isLastRecord)> & pixelMapCallback,const std::function<void (const std::string &,bool isLastRecord)> & urlCallback,bool syncMode)337 void ClipboardImpl::GetData(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
338 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
339 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback, bool syncMode)
340 {
341 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
342 if (!taskExecutor_ || !textCallback || !pixelMapCallback || !urlCallback) {
343 return;
344 }
345
346 if (syncMode) {
347 GetDataSync(textCallback, pixelMapCallback, urlCallback);
348 } else {
349 GetDataAsync(textCallback, pixelMapCallback, urlCallback);
350 }
351 #endif
352 }
353
354 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
GetPasteDataData()355 std::shared_ptr<MiscServices::PasteData> PasteDataImpl::GetPasteDataData()
356 {
357 if (pasteData_ == nullptr) {
358 pasteData_ = std::make_shared<MiscServices::PasteData>();
359 }
360 return pasteData_;
361 }
SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)362 void PasteDataImpl::SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)
363 {
364 pasteData_ = pasteData;
365 }
366
GetDataSync(const std::function<void (const std::string &)> & callback)367 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&)>& callback)
368 {
369 std::string result;
370 taskExecutor_->PostSyncTask(
371 [&result]() {
372 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
373 CHECK_NULL_VOID(has);
374 OHOS::MiscServices::PasteData pasteData;
375 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
376 CHECK_NULL_VOID(ok);
377 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
378 if (pasteDataRecord == nullptr) {
379 continue;
380 }
381 if (pasteDataRecord->GetCustomData() != nullptr) {
382 auto customData = pasteDataRecord->GetCustomData();
383 auto itemData = customData->GetItemData();
384 if (itemData.find(SPAN_STRING_TAG) == itemData.end()) {
385 continue;
386 }
387 auto spanStr = SpanString::DecodeTlv(itemData[SPAN_STRING_TAG]);
388 if (spanStr) {
389 result = spanStr->GetString();
390 break;
391 }
392 }
393 if (pasteDataRecord->GetHtmlText() != nullptr) {
394 auto htmlText = pasteDataRecord->GetHtmlText();
395 HtmlToSpan toSpan;
396 auto spanStr = toSpan.ToSpanString(*htmlText, false);
397 if (spanStr) {
398 result = spanStr->GetString();
399 break;
400 }
401 }
402 }
403 if (result.empty()) {
404 auto textData = pasteData.GetPrimaryText();
405 CHECK_NULL_VOID(textData);
406 result = *textData;
407 }
408 },
409 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetTextDataSync");
410 callback(result);
411 }
412
GetDataAsync(const std::function<void (const std::string &)> & callback)413 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&)>& callback)
414 {
415 taskExecutor_->PostTask(
416 [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_)), weak = WeakClaim(this)]() {
417 auto clip = weak.Upgrade();
418 auto taskExecutor = weakExecutor.Upgrade();
419 CHECK_NULL_VOID(taskExecutor);
420 if (!OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData()) {
421 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "SystemKeyboardData is not exist from MiscServices");
422 taskExecutor->PostTask(
423 [callback]() { callback(""); }, TaskExecutor::TaskType::UI, "ArkUIClipboardHasDataFailed");
424 return;
425 }
426 OHOS::MiscServices::PasteData pasteData;
427 if (!OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData)) {
428 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardData fail from MiscServices");
429 taskExecutor->PostTask(
430 [callback]() { callback(""); }, TaskExecutor::TaskType::UI, "ArkUIClipboardGetDataFailed");
431 return;
432 }
433 std::string resText;
434 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
435 if (clip->ProcessPasteDataRecord(pasteDataRecord, resText)) {
436 break;
437 }
438 }
439 if (resText.empty()) {
440 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardTextData fail from MiscServices");
441 taskExecutor->PostTask(
442 [callback]() { callback(""); }, TaskExecutor::TaskType::UI, "ArkUIClipboardGetTextDataFailed");
443 return;
444 }
445 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "resText len:%{public}d", static_cast<int32_t>(resText.length()));
446 auto result = resText;
447 taskExecutor->PostTask(
448 [callback, result]() { callback(result); },
449 TaskExecutor::TaskType::UI, "ArkUIClipboardGetTextDataCallback");
450 },
451 TaskExecutor::TaskType::BACKGROUND, "ArkUIClipboardGetTextDataAsync");
452 }
453
ProcessPasteDataRecord(const std::shared_ptr<MiscServices::PasteDataRecord> & pasteDataRecord,std::string & resText)454 bool ClipboardImpl::ProcessPasteDataRecord(const std::shared_ptr<MiscServices::PasteDataRecord>& pasteDataRecord,
455 std::string& resText)
456 {
457 if (pasteDataRecord == nullptr) {
458 return false;
459 }
460 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "mimeType:%{public}s", pasteDataRecord->GetMimeType().c_str());
461 if (pasteDataRecord->GetHtmlText() != nullptr) {
462 auto htmlText = pasteDataRecord->GetHtmlText();
463 HtmlToSpan toSpan;
464 auto spanStr = toSpan.ToSpanString(*htmlText);
465 if (spanStr) {
466 resText = spanStr->GetString();
467 return true;
468 }
469 }
470 if (pasteDataRecord->GetCustomData() != nullptr) {
471 auto itemData = pasteDataRecord->GetCustomData()->GetItemData();
472 if (itemData.find(SPAN_STRING_TAG) != itemData.end()) {
473 auto spanStr = SpanString::DecodeTlv(itemData[SPAN_STRING_TAG]);
474 if (spanStr) {
475 resText = spanStr->GetString();
476 return true;
477 }
478 }
479 }
480 if (pasteDataRecord->GetPlainText() != nullptr) {
481 auto textData = pasteDataRecord->GetPlainText();
482 resText.append(*textData);
483 }
484 return false;
485 }
486
GetDataSync(const std::function<void (const std::string &,bool isLastRecord)> & textCallback,const std::function<void (const RefPtr<PixelMap> &,bool isLastRecord)> & pixelMapCallback,const std::function<void (const std::string &,bool isLastRecord)> & urlCallback)487 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
488 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
489 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
490 {
491 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "get data from clipboard, sync");
492 OHOS::MiscServices::PasteData pasteData;
493 taskExecutor_->PostSyncTask(
494 [&pasteData]() {
495 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
496 CHECK_NULL_VOID(has);
497 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
498 CHECK_NULL_VOID(ok);
499 },
500 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetPasteDataSync");
501
502 auto count = pasteData.GetRecordCount();
503 size_t index = 0;
504 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
505 index++;
506 if (pasteDataRecord == nullptr) {
507 continue;
508 }
509 bool isLastRecord = index == count;
510 if (pasteDataRecord->GetPlainText() != nullptr) {
511 auto textData = pasteDataRecord->GetPlainText();
512 auto result = *textData;
513 textCallback(result, isLastRecord);
514 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
515 auto imageData = pasteDataRecord->GetPixelMap();
516 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
517 pixelMapCallback(result, isLastRecord);
518 } else if (pasteDataRecord->GetUri() != nullptr) {
519 auto textData = pasteDataRecord->GetUri();
520 auto result = (*textData).ToString();
521 urlCallback(result, isLastRecord);
522 }
523 }
524 }
525
GetDataAsync(const std::function<void (const std::string &,bool isLastRecord)> & textCallback,const std::function<void (const RefPtr<PixelMap> &,bool isLastRecord)> & pixelMapCallback,const std::function<void (const std::string &,bool isLastRecord)> & urlCallback)526 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
527 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
528 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
529 {
530 TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "get data from clipboard, async");
531 taskExecutor_->PostTask(
532 [textCallback, pixelMapCallback, urlCallback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
533 auto taskExecutor = weakExecutor.Upgrade();
534 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
535 CHECK_NULL_VOID(has);
536 OHOS::MiscServices::PasteData pasteData;
537 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
538 CHECK_NULL_VOID(ok);
539 auto count = pasteData.GetRecordCount();
540 size_t index = 0;
541 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
542 index++;
543 if (pasteDataRecord == nullptr) {
544 continue;
545 }
546 bool isLastRecord = index == count;
547 if (pasteDataRecord->GetPlainText() != nullptr) {
548 auto textData = pasteDataRecord->GetPlainText();
549 auto result = *textData;
550 taskExecutor->PostTask(
551 [textCallback, result, isLastRecord]() { textCallback(result, isLastRecord); },
552 TaskExecutor::TaskType::UI, "ArkUIClipboardGetTextCallback");
553 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
554 auto imageData = pasteDataRecord->GetPixelMap();
555 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
556 taskExecutor->PostTask(
557 [pixelMapCallback, result, isLastRecord]() { pixelMapCallback(result, isLastRecord); },
558 TaskExecutor::TaskType::UI, "ArkUIClipboardGetImageCallback");
559 } else if (pasteDataRecord->GetUri() != nullptr) {
560 auto textData = pasteDataRecord->GetUri();
561 auto result = (*textData).ToString();
562 taskExecutor->PostTask([urlCallback, result, isLastRecord]() { urlCallback(result, isLastRecord); },
563 TaskExecutor::TaskType::UI, "ArkUIClipboardGetUrlCallback");
564 }
565 }
566 },
567 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetDataAsync");
568 }
569
GetSpanStringData(const std::function<void (std::vector<std::vector<uint8_t>> &,const std::string &,bool &)> & callback,bool syncMode)570 void ClipboardImpl::GetSpanStringData(
571 const std::function<void(std::vector<std::vector<uint8_t>>&, const std::string&, bool&)>& callback, bool syncMode)
572 {
573 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
574 if (!taskExecutor_ || !callback) {
575 return;
576 }
577
578 GetSpanStringDataHelper(callback, syncMode);
579 #endif
580 }
581
GetSpanStringDataHelper(const std::function<void (std::vector<std::vector<uint8_t>> &,const std::string &,bool &)> & callback,bool syncMode)582 void ClipboardImpl::GetSpanStringDataHelper(
583 const std::function<void(std::vector<std::vector<uint8_t>>&, const std::string&, bool&)>& callback, bool syncMode)
584 {
585 auto task = [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_)), weak = WeakClaim(this)]() {
586 auto clip = weak.Upgrade();
587 CHECK_NULL_VOID(clip);
588 auto taskExecutor = weakExecutor.Upgrade();
589 CHECK_NULL_VOID(taskExecutor);
590 auto hasData = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
591 CHECK_NULL_VOID(hasData);
592 OHOS::MiscServices::PasteData pasteData;
593 auto getDataRes = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
594 CHECK_NULL_VOID(getDataRes);
595 std::vector<std::vector<uint8_t>> arrays;
596 std::string text;
597 bool isMultiTypeRecord = false;
598 clip->ProcessSpanStringData(arrays, pasteData, text, isMultiTypeRecord);
599 auto textData = pasteData.GetPrimaryText();
600 if (textData && text.empty()) {
601 text.append(*textData);
602 }
603 auto result = text;
604 taskExecutor->PostTask(
605 [callback, arrays, result, isMultiTypeRecord]() mutable { callback(arrays, result, isMultiTypeRecord); },
606 TaskExecutor::TaskType::UI, "ArkUIClipboardGetSpanStringDataCallback");
607 };
608 if (syncMode) {
609 taskExecutor_->PostSyncTask(task, TaskExecutor::TaskType::BACKGROUND, "ArkUIClipboardGetSpanStringDataSync");
610 } else {
611 taskExecutor_->PostTask(task, TaskExecutor::TaskType::BACKGROUND, "ArkUIClipboardGetSpanStringDataAsync");
612 }
613 }
614
ProcessSpanStringData(std::vector<std::vector<uint8_t>> & arrays,const OHOS::MiscServices::PasteData & pasteData,std::string & text,bool & isMultiTypeRecord)615 void ClipboardImpl::ProcessSpanStringData(std::vector<std::vector<uint8_t>>& arrays,
616 const OHOS::MiscServices::PasteData& pasteData, std::string& text, bool& isMultiTypeRecord)
617 {
618 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
619 if (pasteDataRecord == nullptr) {
620 continue;
621 }
622 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
623 std::vector<std::string> types = { SPAN_STRING_TAG, OHOS::MiscServices::MIMETYPE_TEXT_URI,
624 OHOS::MiscServices::MIMETYPE_PIXELMAP, OHOS::MiscServices::MIMETYPE_TEXT_PLAIN,
625 OHOS::MiscServices::MIMETYPE_TEXT_HTML };
626 auto validTypes = pasteDataRecord->GetValidMimeTypes(types);
627 if (validTypes.size() > 1) {
628 isMultiTypeRecord = true;
629 }
630 #endif
631 auto hasSpanString = false;
632 auto entryPtr = pasteDataRecord->GetEntryByMimeType(SPAN_STRING_TAG);
633 if (entryPtr) {
634 // entryValue InstanceOf OHOS::MiscServices::EntryValue.
635 auto entryValue = entryPtr->GetValue();
636 auto spanStringBuffer = std::get_if<std::vector<uint8_t>>(&entryValue);
637 arrays.emplace_back(*spanStringBuffer);
638 hasSpanString = true;
639 }
640 if (pasteDataRecord->GetHtmlText() != nullptr && !hasSpanString) {
641 auto htmlText = pasteDataRecord->GetHtmlText();
642 HtmlToSpan toSpan;
643 auto spanStr = toSpan.ToSpanString(*htmlText);
644 if (spanStr) {
645 std::vector<uint8_t> arr;
646 spanStr->EncodeTlv(arr);
647 arrays.emplace_back(arr);
648 }
649 }
650 if (pasteDataRecord->GetPlainText() != nullptr) {
651 auto textData = pasteDataRecord->GetPlainText();
652 text.append(*textData);
653 }
654 }
655 }
656
GetPixelMapDataSync(const std::function<void (const RefPtr<PixelMap> &)> & callback)657 void ClipboardImpl::GetPixelMapDataSync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
658 {
659 RefPtr<PixelMap> pixmap;
660 taskExecutor_->PostSyncTask(
661 [&pixmap]() {
662 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
663 CHECK_NULL_VOID(has);
664 OHOS::MiscServices::PasteData pasteData;
665 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
666 CHECK_NULL_VOID(ok);
667 auto imageData = pasteData.GetPrimaryPixelMap();
668 CHECK_NULL_VOID(imageData);
669 pixmap = AceType::MakeRefPtr<PixelMapOhos>(imageData);
670 },
671 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetImageDataSync");
672 callback(pixmap);
673 }
674
GetPixelMapDataAsync(const std::function<void (const RefPtr<PixelMap> &)> & callback)675 void ClipboardImpl::GetPixelMapDataAsync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
676 {
677 taskExecutor_->PostTask(
678 [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
679 auto taskExecutor = weakExecutor.Upgrade();
680 CHECK_NULL_VOID(taskExecutor);
681 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
682 if (!has) {
683 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "SystemKeyboardData is not exist from MiscServices");
684 taskExecutor->PostTask(
685 [callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI, "ArkUIClipboardHasDataFailed");
686 return;
687 }
688 OHOS::MiscServices::PasteData pasteData;
689 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
690 if (!ok) {
691 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardData fail from MiscServices");
692 taskExecutor->PostTask(
693 [callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI, "ArkUIClipboardGetDataFailed");
694 return;
695 }
696 auto imageData = pasteData.GetPrimaryPixelMap();
697 if (!imageData) {
698 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardImageData fail from MiscServices");
699 taskExecutor->PostTask(
700 [callback]() { callback(nullptr); },
701 TaskExecutor::TaskType::UI, "ArkUIClipboardGetImageDataFailed");
702 return;
703 }
704 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
705 taskExecutor->PostTask(
706 [callback, result]() { callback(result); },
707 TaskExecutor::TaskType::UI, "ArkUIClipboardGetImageDataCallback");
708 },
709 TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetImageDataAsync");
710 }
711 #endif
712
Clear()713 void ClipboardImpl::Clear() {}
714
715 } // namespace OHOS::Ace
716