• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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