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