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