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 "pasteboard_client_adapter_impl.h"
17 
18 #include <mutex>
19 #include <securec.h>
20 
21 #include "hisysevent_adapter.h"
22 #include "media_errors.h"
23 #include "nweb_log.h"
24 #include "ohos_adapter_helper.h"
25 #include "pasteboard_error.h"
26 #include "remote_uri.h"
27 
28 using namespace OHOS::MiscServices;
29 using namespace OHOS::DistributedFS::ModuleRemoteUri;
30 
31 namespace OHOS::NWeb {
32 constexpr char PASTE_BOARD_ERROR[] = "PASTE_BOARD_ERROR";
33 constexpr char ERROR_CODE[] = "ERROR_CODE";
34 constexpr char RECORD_SIZE[] = "RECORD_SIZE";
35 constexpr char DATA_TYPE[] = "DATA_TYPE";
36 constexpr char MIMETYPE_HYBRID[] = "hybrid";
37 constexpr char MIMETYPE_NULL[] = "null";
38 constexpr char SPAN_STRING_TAG[] = "openharmony.styled-string";
39 constexpr char CUSTOM_DATA_TAG[] = "openharmony.arkweb.custom-data";
40 constexpr char CUSTOM_DATA_TAG2[] = "ohos/custom-data";
41 
PasteboardObserverAdapterImpl(std::shared_ptr<PasteboardObserverAdapter> observer)42 PasteboardObserverAdapterImpl::PasteboardObserverAdapterImpl(
43     std::shared_ptr<PasteboardObserverAdapter> observer)
44     : observer_(observer) {}
45 
OnPasteboardChanged()46 void PasteboardObserverAdapterImpl::OnPasteboardChanged()
47 {
48     if (observer_) {
49         observer_->OnPasteboardChanged();
50     }
51 }
52 
PasteDataRecordAdapterImpl()53 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl()
54 {
55     record_ = std::make_shared<PasteDataRecord>();
56 }
57 
PasteDataRecordAdapterImpl(std::shared_ptr<PasteDataRecord> record)58 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl(
59     std::shared_ptr<PasteDataRecord> record)
60     : record_(record) {}
61 
PasteDataRecordAdapterImpl(const std::string & mimeType)62 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl(
63     const std::string& mimeType)
64 {
65     builder_ = std::make_shared<PasteDataRecord::Builder>(mimeType);
66     if (builder_) {
67         record_ = builder_->Build();
68     }
69 }
70 
PasteDataRecordAdapterImpl(const std::string & mimeType,std::shared_ptr<std::string> htmlText,std::shared_ptr<std::string> plainText)71 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl(
72     const std::string& mimeType,
73     std::shared_ptr<std::string> htmlText,
74     std::shared_ptr<std::string> plainText)
75 {
76     record_ = std::make_shared<PasteDataRecord>(mimeType,
77                                                 htmlText,
78                                                 nullptr,
79                                                 plainText,
80                                                 nullptr);
81 }
82 
NewRecord(const std::string & mimeType)83 std::shared_ptr<PasteDataRecordAdapter> PasteDataRecordAdapter::NewRecord(
84     const std::string& mimeType)
85 {
86     // To adapt to multiple entries, the mime type of the record will be specified when writing the first data.
87     (void)mimeType;
88     return std::make_shared<PasteDataRecordAdapterImpl>();
89 }
90 
NewRecord(const std::string & mimeType,std::shared_ptr<std::string> htmlText,std::shared_ptr<std::string> plainText)91 std::shared_ptr<PasteDataRecordAdapter> PasteDataRecordAdapter::NewRecord(
92     const std::string& mimeType,
93     std::shared_ptr<std::string> htmlText,
94     std::shared_ptr<std::string> plainText)
95 {
96     return std::make_shared<PasteDataRecordAdapterImpl>(mimeType,
97                                                         htmlText,
98                                                         plainText);
99 }
100 
SetHtmlText(std::shared_ptr<std::string> htmlText)101 bool PasteDataRecordAdapterImpl::SetHtmlText(std::shared_ptr<std::string> htmlText)
102 {
103     return SetHtmlText(htmlText, nullptr);
104 }
105 
SetHtmlText(std::shared_ptr<std::string> htmlText,std::shared_ptr<std::string> plainText)106 bool PasteDataRecordAdapterImpl::SetHtmlText(
107     std::shared_ptr<std::string> htmlText, std::shared_ptr<std::string> plainText)
108 {
109     if (!record_ || !htmlText) {
110         WVLOG_E("record_ or htmlText is null");
111         return false;
112     }
113     auto utdId = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::HTML);
114     auto object = std::make_shared<Object>();
115     if (!object) {
116         WVLOG_E("udmf object create failed");
117         return false;
118     }
119     object->value_[UDMF::UNIFORM_DATA_TYPE] = utdId;
120     object->value_[UDMF::HTML_CONTENT] = *htmlText;
121     if (plainText) {
122         object->value_[UDMF::PLAIN_CONTENT] = *plainText;
123     }
124     record_->AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, object));
125     return true;
126 }
127 
SetPlainText(std::shared_ptr<std::string> plainText)128 bool PasteDataRecordAdapterImpl::SetPlainText(std::shared_ptr<std::string> plainText)
129 {
130     if (!record_ || !plainText) {
131         WVLOG_E("record_ or plainText is null");
132         return false;
133     }
134     if (auto htmlText = record_->GetHtmlText(); htmlText && !htmlText->empty()) {
135         SetHtmlText(htmlText, plainText);
136     }
137     auto utdId = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::PLAIN_TEXT);
138     auto object = std::make_shared<Object>();
139     if (!object) {
140         WVLOG_E("udmf object create failed");
141         return false;
142     }
143     object->value_[UDMF::UNIFORM_DATA_TYPE] = utdId;
144     object->value_[UDMF::CONTENT] = *plainText;
145     record_->AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, object));
146     return true;
147 }
148 
SetUri(const std::string & uriString)149 bool PasteDataRecordAdapterImpl::SetUri(const std::string& uriString)
150 {
151     if (!record_ || uriString.empty()) {
152         WVLOG_E("record_ or uriString is null");
153         return false;
154     }
155     auto utdId = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::FILE_URI);
156     record_->AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, uriString));
157     return true;
158 }
159 
SetCustomData(PasteCustomData & data)160 bool PasteDataRecordAdapterImpl::SetCustomData(PasteCustomData& data)
161 {
162     if (!record_ || data.empty()) {
163         WVLOG_E("custom data is empty or record_ is null");
164         return false;
165     }
166     for (PasteCustomData::iterator iter = data.begin(); iter != data.end(); ++iter) {
167         record_->AddEntry(iter->first, std::make_shared<PasteDataEntry>(iter->first, iter->second));
168     }
169     return true;
170 }
171 
ImageToClipboardAlphaType(const Media::ImageInfo & imgInfo)172 ClipBoardImageAlphaType PasteDataRecordAdapterImpl::ImageToClipboardAlphaType
173     (const Media::ImageInfo &imgInfo)
174 {
175     switch (imgInfo.alphaType) {
176         case Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN :
177             return ClipBoardImageAlphaType::ALPHA_TYPE_UNKNOWN;
178         case Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE :
179             return ClipBoardImageAlphaType::ALPHA_TYPE_OPAQUE;
180         case Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL :
181             return ClipBoardImageAlphaType::ALPHA_TYPE_PREMULTIPLIED;
182         default :
183             return ClipBoardImageAlphaType::ALPHA_TYPE_UNKNOWN;
184     }
185 }
186 
ImageToClipboardColorType(const Media::ImageInfo & imgInfo)187 ClipBoardImageColorType PasteDataRecordAdapterImpl::ImageToClipboardColorType
188     (const Media::ImageInfo &imgInfo)
189 {
190     switch (imgInfo.pixelFormat) {
191         case Media::PixelFormat::RGBA_8888 :
192             return ClipBoardImageColorType::COLOR_TYPE_RGBA_8888;
193         case Media::PixelFormat::BGRA_8888 :
194             return ClipBoardImageColorType::COLOR_TYPE_BGRA_8888;
195         default :
196             return ClipBoardImageColorType::COLOR_TYPE_UNKNOWN;
197     }
198 }
199 
ClipboardToImageAlphaType(ClipBoardImageAlphaType alphaType)200 Media::AlphaType PasteDataRecordAdapterImpl::ClipboardToImageAlphaType
201     (ClipBoardImageAlphaType alphaType)
202 {
203     switch (alphaType) {
204         case ClipBoardImageAlphaType::ALPHA_TYPE_UNKNOWN :
205             return Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
206         case ClipBoardImageAlphaType::ALPHA_TYPE_OPAQUE :
207             return Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
208         case ClipBoardImageAlphaType::ALPHA_TYPE_PREMULTIPLIED :
209             return Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
210         default :
211             return Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
212     }
213 }
214 
ClipboardToImageColorType(ClipBoardImageColorType colorType)215 Media::PixelFormat PasteDataRecordAdapterImpl::ClipboardToImageColorType
216     (ClipBoardImageColorType colorType)
217 {
218     switch (colorType) {
219         case ClipBoardImageColorType::COLOR_TYPE_RGBA_8888 :
220             return Media::PixelFormat::RGBA_8888;
221         case ClipBoardImageColorType::COLOR_TYPE_BGRA_8888 :
222             return Media::PixelFormat::BGRA_8888;
223         default :
224             return Media::PixelFormat::UNKNOWN;
225     }
226 }
227 
SetImgData(std::shared_ptr<ClipBoardImageDataAdapter> imageData)228 bool PasteDataRecordAdapterImpl::SetImgData(std::shared_ptr<ClipBoardImageDataAdapter> imageData)
229 {
230     if (imageData == nullptr) {
231         WVLOG_E("imageData is null");
232         return false;
233     }
234     Media::InitializationOptions opt;
235     opt.size.width = imageData->GetWidth();
236     opt.size.height = imageData->GetHeight();
237     opt.pixelFormat = ClipboardToImageColorType(imageData->GetColorType());
238     opt.alphaType = ClipboardToImageAlphaType(imageData->GetAlphaType());
239     opt.editable = true;
240     std::unique_ptr<Media::PixelMap> pixelMap = Media::PixelMap::Create(opt);
241     if (pixelMap == nullptr) {
242         WVLOG_E("create pixel map failed");
243         return false;
244     }
245     uint64_t stride = static_cast<uint64_t>(imageData->GetWidth()) << 2;
246     uint64_t bufferSize = stride * static_cast<uint64_t>(imageData->GetHeight());
247     uint32_t ret = pixelMap->WritePixels(reinterpret_cast<const uint8_t *>(imageData->GetData()), bufferSize);
248     if (ret != Media::SUCCESS) {
249         WVLOG_E("write pixel map failed %{public}u", ret);
250         return false;
251     }
252 
253     std::shared_ptr<Media::PixelMap> pixelMapIn = move(pixelMap);
254 
255     if (!record_) {
256         WVLOG_E("record_ is null");
257         return false;
258     }
259     auto utdId = UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::SYSTEM_DEFINED_PIXEL_MAP);
260     auto object = std::make_shared<Object>();
261     if (!object) {
262         WVLOG_E("udmf object create failed");
263         return false;
264     }
265     object->value_[UDMF::UNIFORM_DATA_TYPE] = utdId;
266     object->value_[UDMF::PIXEL_MAP] = pixelMapIn;
267     record_->AddEntry(utdId, std::make_shared<PasteDataEntry>(utdId, object));
268     return true;
269 }
270 
GetMimeType()271 std::string PasteDataRecordAdapterImpl::GetMimeType()
272 {
273     return (record_ != nullptr) ? record_->GetMimeType() : "";
274 }
275 
GetHtmlText()276 std::shared_ptr<std::string> PasteDataRecordAdapterImpl::GetHtmlText()
277 {
278     if (!record_) {
279         WVLOG_E("record_ is null");
280         return nullptr;
281     }
282     auto entry = record_->GetEntry(UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::HTML));
283     return (entry ? entry->ConvertToHtml() : nullptr);
284 }
285 
GetPlainText()286 std::shared_ptr<std::string> PasteDataRecordAdapterImpl::GetPlainText()
287 {
288     if (!record_) {
289         WVLOG_E("record_ is null");
290         return nullptr;
291     }
292     auto entry = record_->GetEntry(UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::PLAIN_TEXT));
293     if (entry) {
294         return entry->ConvertToPlianText();
295     }
296     auto tempPlainText = record_->GetPlainText();
297     if (tempPlainText && !tempPlainText->empty()) {
298         WVLOG_I("Compatibility adaptation with old versions of read plainText");
299         return tempPlainText;
300     }
301     return nullptr;
302 }
303 
GetPixelMap()304 std::shared_ptr<Media::PixelMap> PasteDataRecordAdapterImpl::GetPixelMap()
305 {
306     if (record_ == nullptr) {
307         WVLOG_E("record_ is null");
308         return nullptr;
309     }
310 
311     std::shared_ptr<Media::PixelMap> pixelMap = nullptr;
312     auto entry = record_->GetEntry(UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::SYSTEM_DEFINED_PIXEL_MAP));
313     if (entry) {
314         pixelMap = entry->ConvertToPixelMap();
315     }
316     if (pixelMap == nullptr) {
317         pixelMap = record_->GetPixelMap();
318         if (pixelMap) {
319             WVLOG_I("Compatibility adaptation with old versions of read pixelMap");
320         }
321     }
322     return pixelMap;
323 }
324 
GetImgData(std::shared_ptr<ClipBoardImageDataAdapter> imageData)325 bool PasteDataRecordAdapterImpl::GetImgData(std::shared_ptr<ClipBoardImageDataAdapter> imageData)
326 {
327     if (record_ == nullptr) {
328         WVLOG_E("record_ is null");
329         return false;
330     }
331 
332     if (imageData == nullptr) {
333         WVLOG_E("imageData is null");
334         return false;
335     }
336 
337     std::shared_ptr<Media::PixelMap> pixelMap = GetPixelMap();
338     if (pixelMap == nullptr) {
339         WVLOG_E("pixelMap is null");
340         return false;
341     }
342 
343     Media::ImageInfo imgInfo;
344     ClearImgBuffer();
345     bufferSize_ = pixelMap->GetCapacity();
346     if ((bufferSize_ == 0) || (pixelMap->GetPixels() == nullptr)) {
347         WVLOG_E("data in pixel map is empty");
348         return false;
349     }
350 
351     imgBuffer_ = static_cast<uint8_t *>(calloc(static_cast<size_t>(bufferSize_), sizeof(uint8_t)));
352     if (imgBuffer_ == nullptr) {
353         WVLOG_E("calloc imgbuffer failed");
354         return false;
355     }
356 
357     if (memcpy_s(imgBuffer_, bufferSize_, pixelMap->GetPixels(), bufferSize_)) {
358         WVLOG_E("memcpy imgbuffer failed");
359         ClearImgBuffer();
360         return false;
361     }
362 
363     int32_t width = pixelMap->GetWidth();
364     int32_t height = pixelMap->GetHeight();
365     pixelMap->GetImageInfo(imgInfo);
366     int32_t rowBytes = pixelMap->GetRowBytes();
367 
368     imageData->SetColorType(ImageToClipboardColorType(imgInfo));
369     imageData->SetAlphaType(ImageToClipboardAlphaType(imgInfo));
370     imageData->SetData((uint32_t *)(imgBuffer_));
371     imageData->SetDataSize(static_cast<size_t>(bufferSize_));
372     imageData->SetWidth(width);
373     imageData->SetHeight(height);
374     imageData->SetRowBytes(static_cast<size_t>(rowBytes));
375     return true;
376 }
377 
GetUri()378 std::shared_ptr<std::string> PasteDataRecordAdapterImpl::GetUri()
379 {
380     if (record_ == nullptr) {
381         WVLOG_E("record_ is null");
382         return nullptr;
383     }
384     auto entry = record_->GetEntry(UDMF::UtdUtils::GetUtdIdFromUtdEnum(UDMF::FILE_URI));
385     if (entry == nullptr) {
386         return nullptr;
387     }
388     auto uri = entry->ConvertToUri();
389     if (uri == nullptr) {
390         return nullptr;
391     }
392     return std::make_shared<std::string>(uri->ToString());
393 }
394 
GetCustomData()395 std::shared_ptr<PasteCustomData> PasteDataRecordAdapterImpl::GetCustomData()
396 {
397     if (record_ == nullptr) {
398         WVLOG_E("record_ is null");
399         return nullptr;
400     }
401     auto customData = std::make_shared<PasteCustomData>();
402     if (customData == nullptr) {
403         WVLOG_E("customData create failed");
404         return nullptr;
405     }
406     for (auto type : { SPAN_STRING_TAG, CUSTOM_DATA_TAG, CUSTOM_DATA_TAG2 }) {
407         auto entry = record_->GetEntry(type);
408         if (!entry) {
409             continue;
410         }
411         auto data = entry->ConvertToCustomData();
412         if (!data) {
413             continue;
414         }
415         for (const auto& [key, value] : data->GetItemData()) {
416             customData->emplace(key, value);
417         }
418     }
419     // Compatibility adaptation with old versions of read customData
420     if (record_->GetCustomData()) {
421         for (const auto& [key, value] : record_->GetCustomData()->GetItemData()) {
422             customData->emplace(key, value);
423         }
424     }
425 
426     return (customData->empty() ? nullptr : customData);
427 }
428 
ClearImgBuffer()429 void PasteDataRecordAdapterImpl::ClearImgBuffer()
430 {
431     if (imgBuffer_) {
432         free(imgBuffer_);
433         imgBuffer_ = nullptr;
434         bufferSize_ = 0;
435     }
436 }
437 
Clear()438 void PasteDataRecordAdapterImpl::Clear()
439 {
440     ClearImgBuffer();
441 }
442 
GetRecord()443 std::shared_ptr<PasteDataRecord> PasteDataRecordAdapterImpl::GetRecord()
444 {
445     return record_;
446 }
447 
PasteDataAdapterImpl()448 PasteDataAdapterImpl::PasteDataAdapterImpl()
449     : data_(std::make_shared<PasteData>()) {}
450 
PasteDataAdapterImpl(std::shared_ptr<PasteData> data)451 PasteDataAdapterImpl::PasteDataAdapterImpl(
452     std::shared_ptr<PasteData> data) : data_(data) {}
453 
AddHtmlRecord(const std::string & html)454 void PasteDataAdapterImpl::AddHtmlRecord(const std::string& html)
455 {
456     if (data_ != nullptr) {
457         data_->AddHtmlRecord(html);
458     }
459 }
460 
AddTextRecord(const std::string & text)461 void PasteDataAdapterImpl::AddTextRecord(const std::string& text)
462 {
463     if (data_ != nullptr) {
464         data_->AddTextRecord(text);
465     }
466 }
467 
GetMimeTypes()468 std::vector<std::string> PasteDataAdapterImpl::GetMimeTypes()
469 {
470     return (data_ != nullptr) ? data_->GetMimeTypes() :
471                                 std::vector<std::string>();
472 }
473 
GetPrimaryHtml()474 std::shared_ptr<std::string> PasteDataAdapterImpl::GetPrimaryHtml()
475 {
476     return (data_ != nullptr) ? data_->GetPrimaryHtml() : nullptr;
477 }
478 
GetPrimaryText()479 std::shared_ptr<std::string> PasteDataAdapterImpl::GetPrimaryText()
480 {
481     return (data_ != nullptr) ? data_->GetPrimaryText() : nullptr;
482 }
483 
GetPrimaryMimeType()484 std::shared_ptr<std::string> PasteDataAdapterImpl::GetPrimaryMimeType()
485 {
486     return (data_ != nullptr) ? data_->GetPrimaryMimeType() : nullptr;
487 }
488 
GetRecordAt(std::size_t index)489 std::shared_ptr<PasteDataRecordAdapter> PasteDataAdapterImpl::GetRecordAt(
490     std::size_t index)
491 {
492     if (data_ == nullptr || data_->GetRecordCount() <= index) {
493         return nullptr;
494     }
495     return std::make_shared<PasteDataRecordAdapterImpl>(data_->GetRecordAt(index));
496 }
497 
GetRecordCount()498 std::size_t PasteDataAdapterImpl::GetRecordCount()
499 {
500     return (data_ != nullptr) ? data_->GetRecordCount() : 0;
501 }
502 
AllRecords()503 PasteRecordVector PasteDataAdapterImpl::AllRecords()
504 {
505     if (data_ == nullptr) {
506         return PasteRecordVector();
507     }
508     PasteRecordVector result;
509     for (auto& record: data_->AllRecords()) {
510         result.push_back(std::make_shared<PasteDataRecordAdapterImpl>(record));
511     }
512     return result;
513 }
514 
GetInstance()515 PasteBoardClientAdapterImpl& PasteBoardClientAdapterImpl::GetInstance()
516 {
517     static PasteBoardClientAdapterImpl instance;
518     return instance;
519 }
520 
TransitionCopyOption(CopyOptionMode copyOption)521 MiscServices::ShareOption PasteBoardClientAdapterImpl::TransitionCopyOption(CopyOptionMode copyOption)
522 {
523     auto shareOption = MiscServices::ShareOption::CrossDevice;
524     switch (copyOption) {
525         case CopyOptionMode::IN_APP:
526             shareOption = MiscServices::ShareOption::InApp;
527             break;
528         case CopyOptionMode::LOCAL_DEVICE:
529             shareOption = MiscServices::ShareOption::LocalDevice;
530             break;
531         case CopyOptionMode::CROSS_DEVICE:
532             shareOption = MiscServices::ShareOption::CrossDevice;
533             break;
534         default:
535             break;
536     }
537     return shareOption;
538 }
539 
ReportPasteboardErrorEvent(int32_t errorCode,int32_t recordSize,const std::string & dataType)540 void ReportPasteboardErrorEvent(int32_t errorCode, int32_t recordSize, const std::string &dataType)
541 {
542     OhosAdapterHelper::GetInstance().GetHiSysEventAdapterInstance().Write(PASTE_BOARD_ERROR,
543         HiSysEventAdapter::EventType::FAULT, { ERROR_CODE, std::to_string(errorCode),
544             RECORD_SIZE, std::to_string(recordSize), DATA_TYPE, dataType });
545 }
546 
GetPasteMimeTypeExtention(const PasteRecordVector & data)547 std::string GetPasteMimeTypeExtention(const PasteRecordVector& data)
548 {
549     if (data.empty()) {
550         return MIMETYPE_NULL;
551     }
552     bool isHybrid = false;
553     std::string primaryMimeType = data.front()->GetMimeType();
554     for (auto &item : data) {
555         if (primaryMimeType != item->GetMimeType()) {
556             isHybrid = true;
557             break;
558         }
559     }
560     if (isHybrid) {
561         return MIMETYPE_HYBRID;
562     }
563     return primaryMimeType;
564 }
565 
GetPasteData(PasteRecordVector & data)566 bool PasteBoardClientAdapterImpl::GetPasteData(PasteRecordVector& data)
567 {
568     PasteData pData;
569     if (!PasteboardClient::GetInstance()->HasPasteData() ||
570         PasteboardClient::GetInstance()->GetPasteData(pData) != static_cast<int32_t>(PasteboardError::E_OK)) {
571         WVLOG_E("no data to paste or get data from clipboard failed");
572         ReportPasteboardErrorEvent(PasteboardClient::GetInstance()->GetPasteData(pData),
573             pData.AllRecords().size(), GetPasteMimeTypeExtention(data));
574         isLocalPaste_ = false;
575         tokenId_ = 0;
576         return false;
577     }
578     for (auto& record: pData.AllRecords()) {
579         data.push_back(std::make_shared<PasteDataRecordAdapterImpl>(record));
580     }
581     tokenId_ = pData.GetTokenId();
582     isLocalPaste_ = pData.IsLocalPaste();
583     return true;
584 }
585 
SetPasteData(const PasteRecordVector & data,CopyOptionMode copyOption)586 void PasteBoardClientAdapterImpl::SetPasteData(const PasteRecordVector& data, CopyOptionMode copyOption)
587 {
588     if (copyOption == CopyOptionMode::NONE) {
589         WVLOG_E("SetPasteData failed, copy option mode is 'NONE'");
590         return;
591     }
592     std::vector<std::shared_ptr<PasteDataRecord>> recordList;
593     for (auto& record: data) {
594         PasteDataRecordAdapterImpl* rawRecord =
595             reinterpret_cast<PasteDataRecordAdapterImpl*>(record.get());
596         if (rawRecord == nullptr) {
597             continue;
598         }
599         recordList.push_back(rawRecord->GetRecord());
600     }
601     PasteData pData(recordList);
602     auto shareOption = TransitionCopyOption(copyOption);
603     pData.SetShareOption(shareOption);
604     int32_t ret = PasteboardClient::GetInstance()->SetPasteData(pData);
605     if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
606         WVLOG_E("set paste data to clipboard failed");
607         ReportPasteboardErrorEvent(ret, pData.AllRecords().size(), GetPasteMimeTypeExtention(data));
608     }
609 }
610 
HasPasteData()611 bool PasteBoardClientAdapterImpl::HasPasteData()
612 {
613     return PasteboardClient::GetInstance()->HasPasteData();
614 }
615 
Clear()616 void PasteBoardClientAdapterImpl::Clear()
617 {
618     PasteRecordVector recordVector;
619     if (!GetPasteData(recordVector)) {
620         WVLOG_E("get paste data failed while clear");
621         PasteboardClient::GetInstance()->Clear();
622         return;
623     }
624     for (auto& record: recordVector) {
625         PasteDataRecordAdapterImpl* rawRecord =
626             reinterpret_cast<PasteDataRecordAdapterImpl*>(record.get());
627         if (rawRecord == nullptr) {
628             continue;
629         }
630         rawRecord->Clear();
631     }
632     PasteboardClient::GetInstance()->Clear();
633 }
634 
OpenRemoteUri(const std::string & path)635 int32_t PasteBoardClientAdapterImpl::OpenRemoteUri(const std::string& path)
636 {
637     return RemoteUri::OpenRemoteUri(path);
638 }
639 
IsLocalPaste()640 bool PasteBoardClientAdapterImpl::IsLocalPaste()
641 {
642     return isLocalPaste_;
643 }
644 
GetTokenId()645 uint32_t PasteBoardClientAdapterImpl::GetTokenId()
646 {
647     return tokenId_;
648 }
649 
AddPasteboardChangedObserver(std::shared_ptr<PasteboardObserverAdapter> callback)650 int32_t PasteBoardClientAdapterImpl::AddPasteboardChangedObserver(
651     std::shared_ptr<PasteboardObserverAdapter> callback)
652 {
653     static int32_t count = 0;
654     int32_t id = -1;
655     if (callback) {
656         sptr<PasteboardObserver> observer;
657         {
658             std::lock_guard<std::mutex> lock(mutex_);
659             observer = new (std::nothrow) PasteboardObserverAdapterImpl(callback);
660             if (!observer) {
661                 return -1;
662             }
663 
664             id = count++;
665             if (count < 0) {
666                 count = 0;
667             }
668             reg_.emplace(std::make_pair(id, observer));
669         }
670         PasteboardClient::GetInstance()->AddPasteboardChangedObserver(observer);
671     }
672     return id;
673 }
674 
RemovePasteboardChangedObserver(int32_t callbackId)675 void PasteBoardClientAdapterImpl::RemovePasteboardChangedObserver(
676     int32_t callbackId)
677 {
678     sptr<PasteboardObserver> observer;
679     {
680         std::lock_guard<std::mutex> lock(mutex_);
681         ObserverMap::iterator iter = reg_.find(callbackId);
682         if (iter == reg_.end()) {
683             return;
684         }
685         observer = iter->second;
686         reg_.erase(iter);
687     }
688     PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(observer);
689 }
690 } // namespace OHOS::NWeb
691