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