• 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/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 
AddPixelMapRecord(const RefPtr<PasteDataMix> & pasteData,const RefPtr<PixelMap> & pixmap)187 void ClipboardImpl::AddPixelMapRecord(const RefPtr<PasteDataMix>& pasteData, const RefPtr<PixelMap>& pixmap)
188 {
189 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
190     CHECK_NULL_VOID(taskExecutor_);
191     auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
192     CHECK_NULL_VOID(peData);
193     auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
194     CHECK_NULL_VOID(pixmapOhos);
195     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add pixelMap record to pasteData");
196     peData->GetPasteDataData()->AddPixelMapRecord(pixmapOhos->GetPixelMapSharedPtr());
197 #endif
198 }
199 
AddImageRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & uri)200 void ClipboardImpl::AddImageRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& uri)
201 {
202 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
203     CHECK_NULL_VOID(taskExecutor_);
204     auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
205     CHECK_NULL_VOID(peData);
206     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add url %{private}s record to pasteData", uri.c_str());
207     peData->GetPasteDataData()->AddUriRecord(OHOS::Uri(uri));
208 #endif
209 }
210 
AddTextRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & selectedStr)211 void ClipboardImpl::AddTextRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& selectedStr)
212 {
213 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
214     CHECK_NULL_VOID(taskExecutor_);
215     auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
216     CHECK_NULL_VOID(peData);
217     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add text record to pasteData, length: %{public}d",
218         static_cast<int32_t>(StringUtils::ToWstring(selectedStr).length()));
219     peData->GetPasteDataData()->AddTextRecord(selectedStr);
220 #endif
221 }
222 
AddSpanStringRecord(const RefPtr<PasteDataMix> & pasteData,std::vector<uint8_t> & data)223 void ClipboardImpl::AddSpanStringRecord(const RefPtr<PasteDataMix>& pasteData, std::vector<uint8_t>& data)
224 {
225 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
226     CHECK_NULL_VOID(taskExecutor_);
227     auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
228     CHECK_NULL_VOID(peData);
229     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add spanstring record to pasteData, length: %{public}d",
230         static_cast<int32_t>(data.size()));
231     peData->GetPasteDataData()->AddKvRecord(SPAN_STRING_TAG, data);
232 #endif
233 }
234 
SetData(const RefPtr<PasteDataMix> & pasteData,CopyOptions copyOption)235 void ClipboardImpl::SetData(const RefPtr<PasteDataMix>& pasteData, CopyOptions copyOption)
236 {
237 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
238     auto shareOption = TransitionCopyOption(copyOption);
239     auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
240     CHECK_NULL_VOID(peData);
241     taskExecutor_->PostTask(
242         [peData, shareOption]() {
243             auto pasteData = peData->GetPasteDataData();
244             pasteData->SetShareOption(shareOption);
245             TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "add pasteData to clipboard, shareOption:  %{public}d", shareOption);
246             OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
247         },
248         TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardSetMixDataWithCopyOption");
249 #endif
250 }
251 
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)252 void ClipboardImpl::GetData(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
253     const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
254     const std::function<void(const std::string&, bool isLastRecord)>& urlCallback, bool syncMode)
255 {
256 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
257     if (!taskExecutor_ || !textCallback || !pixelMapCallback || !urlCallback) {
258         return;
259     }
260 
261     if (syncMode) {
262         GetDataSync(textCallback, pixelMapCallback, urlCallback);
263     } else {
264         GetDataAsync(textCallback, pixelMapCallback, urlCallback);
265     }
266 #endif
267 }
268 
269 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
GetPasteDataData()270 std::shared_ptr<MiscServices::PasteData> PasteDataImpl::GetPasteDataData()
271 {
272     if (pasteData_ == nullptr) {
273         pasteData_ = std::make_shared<MiscServices::PasteData>();
274     }
275     return pasteData_;
276 }
SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)277 void PasteDataImpl::SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)
278 {
279     pasteData_ = pasteData;
280 }
281 
GetDataSync(const std::function<void (const std::string &)> & callback)282 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&)>& callback)
283 {
284     std::string result;
285     taskExecutor_->PostSyncTask(
286         [&result]() {
287             auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
288             CHECK_NULL_VOID(has);
289             OHOS::MiscServices::PasteData pasteData;
290             auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
291             CHECK_NULL_VOID(ok);
292             for (const auto& pasteDataRecord : pasteData.AllRecords()) {
293                 if (pasteDataRecord == nullptr) {
294                     continue;
295                 }
296                 if (pasteDataRecord->GetCustomData() != nullptr) {
297                     auto customData = pasteDataRecord->GetCustomData();
298                     auto itemData = customData->GetItemData();
299                     if (itemData.find(SPAN_STRING_TAG) == itemData.end()) {
300                         continue;
301                     }
302                     auto spanStr = SpanString::DecodeTlv(itemData[SPAN_STRING_TAG]);
303                     if (spanStr) {
304                         result = spanStr->GetString();
305                         break;
306                     }
307                 }
308                 if (pasteDataRecord->GetHtmlText() != nullptr) {
309                     auto htmlText = pasteDataRecord->GetHtmlText();
310                     HtmlToSpan toSpan;
311                     auto spanStr = toSpan.ToSpanString(*htmlText, false);
312                     if (spanStr) {
313                         result = spanStr->GetString();
314                         break;
315                     }
316                 }
317             }
318             if (result.empty()) {
319                 auto textData = pasteData.GetPrimaryText();
320                 CHECK_NULL_VOID(textData);
321                 result = *textData;
322             }
323         },
324         TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetTextDataSync");
325     callback(result);
326 }
327 
GetDataAsync(const std::function<void (const std::string &)> & callback)328 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&)>& callback)
329 {
330     taskExecutor_->PostTask(
331         [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_)), weak = WeakClaim(this)]() {
332             auto clip = weak.Upgrade();
333             auto taskExecutor = weakExecutor.Upgrade();
334             CHECK_NULL_VOID(taskExecutor);
335             if (!OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData()) {
336                 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "SystemKeyboardData is not exist from MiscServices");
337                 taskExecutor->PostTask(
338                     [callback]() { callback(""); }, TaskExecutor::TaskType::UI, "ArkUIClipboardHasDataFailed");
339                 return;
340             }
341             OHOS::MiscServices::PasteData pasteData;
342             if (!OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData)) {
343                 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardData fail from MiscServices");
344                 taskExecutor->PostTask(
345                     [callback]() { callback(""); }, TaskExecutor::TaskType::UI, "ArkUIClipboardGetDataFailed");
346                 return;
347             }
348             std::string resText;
349             for (const auto& pasteDataRecord : pasteData.AllRecords()) {
350                 if (clip->ProcessPasteDataRecord(pasteDataRecord, resText)) {
351                     break;
352                 }
353             }
354             if (resText.empty()) {
355                 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardTextData fail from MiscServices");
356                 taskExecutor->PostTask(
357                     [callback]() { callback(""); }, TaskExecutor::TaskType::UI, "ArkUIClipboardGetTextDataFailed");
358                 return;
359             }
360             TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "resText len:%{public}d", static_cast<int32_t>(resText.length()));
361             auto result = resText;
362             taskExecutor->PostTask(
363                 [callback, result]() { callback(result); },
364                 TaskExecutor::TaskType::UI, "ArkUIClipboardGetTextDataCallback");
365         },
366         TaskExecutor::TaskType::BACKGROUND, "ArkUIClipboardGetTextDataAsync");
367 }
368 
ProcessPasteDataRecord(const std::shared_ptr<MiscServices::PasteDataRecord> & pasteDataRecord,std::string & resText)369 bool ClipboardImpl::ProcessPasteDataRecord(const std::shared_ptr<MiscServices::PasteDataRecord>& pasteDataRecord,
370     std::string& resText)
371 {
372     if (pasteDataRecord == nullptr) {
373         return false;
374     }
375     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "mimeType:%{public}s", pasteDataRecord->GetMimeType().c_str());
376     if (pasteDataRecord->GetHtmlText() != nullptr) {
377         auto htmlText = pasteDataRecord->GetHtmlText();
378         HtmlToSpan toSpan;
379         auto spanStr = toSpan.ToSpanString(*htmlText);
380         if (spanStr) {
381             resText = spanStr->GetString();
382             return true;
383         }
384     }
385     if (pasteDataRecord->GetCustomData() != nullptr) {
386         auto itemData = pasteDataRecord->GetCustomData()->GetItemData();
387         if (itemData.find(SPAN_STRING_TAG) != itemData.end()) {
388             auto spanStr = SpanString::DecodeTlv(itemData[SPAN_STRING_TAG]);
389             if (spanStr) {
390                 resText = spanStr->GetString();
391                 return true;
392             }
393         }
394     }
395     if (pasteDataRecord->GetPlainText() != nullptr) {
396         auto textData = pasteDataRecord->GetPlainText();
397         resText.append(*textData);
398     }
399     return false;
400 }
401 
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)402 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
403     const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
404     const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
405 {
406     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "get data from clipboard, sync");
407     OHOS::MiscServices::PasteData pasteData;
408     taskExecutor_->PostSyncTask(
409         [&pasteData]() {
410             auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
411             CHECK_NULL_VOID(has);
412             auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
413             CHECK_NULL_VOID(ok);
414         },
415         TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetPasteDataSync");
416 
417     auto count = pasteData.GetRecordCount();
418     size_t index = 0;
419     for (const auto& pasteDataRecord : pasteData.AllRecords()) {
420         index++;
421         if (pasteDataRecord == nullptr) {
422             continue;
423         }
424         bool isLastRecord = index == count;
425         if (pasteDataRecord->GetPlainText() != nullptr) {
426             auto textData = pasteDataRecord->GetPlainText();
427             auto result = *textData;
428             textCallback(result, isLastRecord);
429         } else if (pasteDataRecord->GetPixelMap() != nullptr) {
430             auto imageData = pasteDataRecord->GetPixelMap();
431             auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
432             pixelMapCallback(result, isLastRecord);
433         } else if (pasteDataRecord->GetUri() != nullptr) {
434             auto textData = pasteDataRecord->GetUri();
435             auto result = (*textData).ToString();
436             urlCallback(result, isLastRecord);
437         }
438     }
439 }
440 
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)441 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
442     const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
443     const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
444 {
445     TAG_LOGI(AceLogTag::ACE_CLIPBOARD, "get data from clipboard, async");
446     taskExecutor_->PostTask(
447         [textCallback, pixelMapCallback, urlCallback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
448             auto taskExecutor = weakExecutor.Upgrade();
449             auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
450             CHECK_NULL_VOID(has);
451             OHOS::MiscServices::PasteData pasteData;
452             auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
453             CHECK_NULL_VOID(ok);
454             auto count = pasteData.GetRecordCount();
455             size_t index = 0;
456             for (const auto& pasteDataRecord : pasteData.AllRecords()) {
457                 index++;
458                 if (pasteDataRecord == nullptr) {
459                     continue;
460                 }
461                 bool isLastRecord = index == count;
462                 if (pasteDataRecord->GetPlainText() != nullptr) {
463                     auto textData = pasteDataRecord->GetPlainText();
464                     auto result = *textData;
465                     taskExecutor->PostTask(
466                         [textCallback, result, isLastRecord]() { textCallback(result, isLastRecord); },
467                         TaskExecutor::TaskType::UI, "ArkUIClipboardGetTextCallback");
468                 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
469                     auto imageData = pasteDataRecord->GetPixelMap();
470                     auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
471                     taskExecutor->PostTask(
472                         [pixelMapCallback, result, isLastRecord]() { pixelMapCallback(result, isLastRecord); },
473                         TaskExecutor::TaskType::UI, "ArkUIClipboardGetImageCallback");
474                 } else if (pasteDataRecord->GetUri() != nullptr) {
475                     auto textData = pasteDataRecord->GetUri();
476                     auto result = (*textData).ToString();
477                     taskExecutor->PostTask([urlCallback, result, isLastRecord]() { urlCallback(result, isLastRecord); },
478                         TaskExecutor::TaskType::UI, "ArkUIClipboardGetUrlCallback");
479                 }
480             }
481         },
482         TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetDataAsync");
483 }
484 
GetSpanStringData(const std::function<void (std::vector<uint8_t> &,const std::string &)> & callback,bool syncMode)485 void ClipboardImpl::GetSpanStringData(
486     const std::function<void(std::vector<uint8_t>&, const std::string&)>& callback, bool syncMode)
487 {
488 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
489     if (!taskExecutor_ || !callback) {
490         return;
491     }
492 
493     GetSpanStringDataHelper(callback, syncMode);
494 #endif
495 }
496 
GetSpanStringDataHelper(const std::function<void (std::vector<uint8_t> &,const std::string &)> & callback,bool syncMode)497 void ClipboardImpl::GetSpanStringDataHelper(
498     const std::function<void(std::vector<uint8_t>&, const std::string&)>& callback, bool syncMode)
499 {
500     auto task = [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_)), weak = WeakClaim(this)]() {
501         auto clip = weak.Upgrade();
502         CHECK_NULL_VOID(clip);
503         auto taskExecutor = weakExecutor.Upgrade();
504         CHECK_NULL_VOID(taskExecutor);
505         auto hasData = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
506         CHECK_NULL_VOID(hasData);
507         OHOS::MiscServices::PasteData pasteData;
508         auto getDataRes = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
509         CHECK_NULL_VOID(getDataRes);
510         std::vector<uint8_t> arr;
511         std::string text;
512         clip->ProcessSpanStringData(arr, pasteData, text);
513         auto textData = pasteData.GetPrimaryText();
514         if (textData && text.empty()) {
515             text.append(*textData);
516         }
517         auto result = text;
518         taskExecutor->PostTask(
519             [callback, arr, result]() mutable { callback(arr, result); },
520             TaskExecutor::TaskType::UI, "ArkUIClipboardGetSpanStringDataCallback");
521     };
522     if (syncMode) {
523         taskExecutor_->PostSyncTask(task, TaskExecutor::TaskType::BACKGROUND, "ArkUIClipboardGetSpanStringDataSync");
524     } else {
525         taskExecutor_->PostTask(task, TaskExecutor::TaskType::BACKGROUND, "ArkUIClipboardGetSpanStringDataAsync");
526     }
527 }
528 
ProcessSpanStringData(std::vector<uint8_t> & arr,const OHOS::MiscServices::PasteData & pasteData,std::string & text)529 void ClipboardImpl::ProcessSpanStringData(
530     std::vector<uint8_t>& arr, const OHOS::MiscServices::PasteData& pasteData, std::string& text)
531 {
532     for (const auto& pasteDataRecord : pasteData.AllRecords()) {
533         if (pasteDataRecord == nullptr) {
534             continue;
535         }
536         if (pasteDataRecord->GetCustomData() != nullptr) {
537             auto itemData = pasteDataRecord->GetCustomData()->GetItemData();
538             if (itemData.find(SPAN_STRING_TAG) != itemData.end()) {
539                 arr = itemData[SPAN_STRING_TAG];
540                 return;
541             }
542         }
543         if (pasteDataRecord->GetHtmlText() != nullptr) {
544             auto htmlText = pasteDataRecord->GetHtmlText();
545             HtmlToSpan toSpan;
546             auto spanStr = toSpan.ToSpanString(*htmlText);
547             if (spanStr) {
548                 spanStr->EncodeTlv(arr);
549                 return;
550             }
551         }
552         if (pasteDataRecord->GetPlainText() != nullptr) {
553             auto textData = pasteDataRecord->GetPlainText();
554             text.append(*textData);
555         }
556     }
557 }
558 
GetPixelMapDataSync(const std::function<void (const RefPtr<PixelMap> &)> & callback)559 void ClipboardImpl::GetPixelMapDataSync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
560 {
561     RefPtr<PixelMap> pixmap;
562     taskExecutor_->PostSyncTask(
563         [&pixmap]() {
564             auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
565             CHECK_NULL_VOID(has);
566             OHOS::MiscServices::PasteData pasteData;
567             auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
568             CHECK_NULL_VOID(ok);
569             auto imageData = pasteData.GetPrimaryPixelMap();
570             CHECK_NULL_VOID(imageData);
571             pixmap = AceType::MakeRefPtr<PixelMapOhos>(imageData);
572         },
573         TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetImageDataSync");
574     callback(pixmap);
575 }
576 
GetPixelMapDataAsync(const std::function<void (const RefPtr<PixelMap> &)> & callback)577 void ClipboardImpl::GetPixelMapDataAsync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
578 {
579     taskExecutor_->PostTask(
580         [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
581             auto taskExecutor = weakExecutor.Upgrade();
582             CHECK_NULL_VOID(taskExecutor);
583             auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
584             if (!has) {
585                 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "SystemKeyboardData is not exist from MiscServices");
586                 taskExecutor->PostTask(
587                     [callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI, "ArkUIClipboardHasDataFailed");
588                 return;
589             }
590             OHOS::MiscServices::PasteData pasteData;
591             auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
592             if (!ok) {
593                 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardData fail from MiscServices");
594                 taskExecutor->PostTask(
595                     [callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI, "ArkUIClipboardGetDataFailed");
596                 return;
597             }
598             auto imageData = pasteData.GetPrimaryPixelMap();
599             if (!imageData) {
600                 TAG_LOGW(AceLogTag::ACE_CLIPBOARD, "Get SystemKeyboardImageData fail from MiscServices");
601                 taskExecutor->PostTask(
602                     [callback]() { callback(nullptr); },
603                     TaskExecutor::TaskType::UI, "ArkUIClipboardGetImageDataFailed");
604                 return;
605             }
606             auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
607             taskExecutor->PostTask(
608                 [callback, result]() { callback(result); },
609                 TaskExecutor::TaskType::UI, "ArkUIClipboardGetImageDataCallback");
610         },
611         TaskExecutor::TaskType::PLATFORM, "ArkUIClipboardGetImageDataAsync");
612 }
613 #endif
614 
Clear()615 void ClipboardImpl::Clear() {}
616 
617 } // namespace OHOS::Ace
618