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