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