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