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 "media_errors.h"
22 #include "nweb_log.h"
23 #include "remote_uri.h"
24
25 using namespace OHOS::MiscServices;
26 using namespace OHOS::DistributedFS::ModuleRemoteUri;
27
28 namespace OHOS::NWeb {
PasteboardObserverAdapterImpl(std::shared_ptr<PasteboardObserverAdapter> observer)29 PasteboardObserverAdapterImpl::PasteboardObserverAdapterImpl(
30 std::shared_ptr<PasteboardObserverAdapter> observer)
31 : observer_(observer) {}
32
OnPasteboardChanged()33 void PasteboardObserverAdapterImpl::OnPasteboardChanged()
34 {
35 if (observer_) {
36 observer_->OnPasteboardChanged();
37 }
38 }
39
PasteDataRecordAdapterImpl(std::shared_ptr<PasteDataRecord> record)40 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl(
41 std::shared_ptr<PasteDataRecord> record)
42 : record_(record) {}
43
PasteDataRecordAdapterImpl(const std::string & mimeType)44 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl(
45 const std::string& mimeType)
46 {
47 builder_ = std::make_shared<PasteDataRecord::Builder>(mimeType);
48 if (builder_) {
49 record_ = builder_->Build();
50 }
51 }
52
PasteDataRecordAdapterImpl(const std::string & mimeType,std::shared_ptr<std::string> htmlText,std::shared_ptr<std::string> plainText)53 PasteDataRecordAdapterImpl::PasteDataRecordAdapterImpl(
54 const std::string& mimeType,
55 std::shared_ptr<std::string> htmlText,
56 std::shared_ptr<std::string> plainText)
57 {
58 record_ = std::make_shared<PasteDataRecord>(mimeType,
59 htmlText,
60 nullptr,
61 plainText,
62 nullptr);
63 }
64
NewRecord(const std::string & mimeType)65 std::shared_ptr<PasteDataRecordAdapter> PasteDataRecordAdapter::NewRecord(
66 const std::string& mimeType)
67 {
68 return std::make_shared<PasteDataRecordAdapterImpl>(mimeType);
69 }
70
NewRecord(const std::string & mimeType,std::shared_ptr<std::string> htmlText,std::shared_ptr<std::string> plainText)71 std::shared_ptr<PasteDataRecordAdapter> PasteDataRecordAdapter::NewRecord(
72 const std::string& mimeType,
73 std::shared_ptr<std::string> htmlText,
74 std::shared_ptr<std::string> plainText)
75 {
76 return std::make_shared<PasteDataRecordAdapterImpl>(mimeType,
77 htmlText,
78 plainText);
79 }
80
SetHtmlText(std::shared_ptr<std::string> htmlText)81 bool PasteDataRecordAdapterImpl::SetHtmlText(std::shared_ptr<std::string> htmlText)
82 {
83 if (builder_) {
84 record_ = builder_->SetHtmlText(htmlText).Build();
85 return true;
86 }
87 WVLOG_E("record_ is null");
88 return false;
89 }
90
SetPlainText(std::shared_ptr<std::string> plainText)91 bool PasteDataRecordAdapterImpl::SetPlainText(std::shared_ptr<std::string> plainText)
92 {
93 if (builder_) {
94 record_ = builder_->SetPlainText(plainText).Build();
95 return true;
96 }
97 WVLOG_E("record_ is null");
98 return false;
99 }
100
SetUri(const std::string & uriString)101 bool PasteDataRecordAdapterImpl::SetUri(const std::string& uriString)
102 {
103 if (uriString.empty() || !builder_) {
104 WVLOG_E("record_ or uriString is null");
105 return false;
106 }
107 std::shared_ptr<OHOS::Uri> uri = std::make_shared<OHOS::Uri>(uriString);
108 record_ = builder_->SetUri(uri).Build();
109 return true;
110 }
111
SetCustomData(PasteCustomData & data)112 bool PasteDataRecordAdapterImpl::SetCustomData(PasteCustomData& data)
113 {
114 if (data.empty() || !builder_) {
115 WVLOG_E("custom data is empty or builder_ is null");
116 return false;
117 }
118 std::shared_ptr<MineCustomData> customData =
119 std::make_shared<MineCustomData>();
120 for (PasteCustomData::iterator iter = data.begin(); iter != data.end(); ++iter) {
121 customData->AddItemData(iter->first, iter->second);
122 }
123 record_ = builder_->SetCustomData(customData).Build();
124 return true;
125 }
126
ImageToClipboardAlphaType(const Media::ImageInfo & imgInfo)127 ClipBoardImageAlphaType PasteDataRecordAdapterImpl::ImageToClipboardAlphaType
128 (const Media::ImageInfo &imgInfo)
129 {
130 switch (imgInfo.alphaType) {
131 case Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN :
132 return ClipBoardImageAlphaType::ALPHA_TYPE_UNKNOWN;
133 case Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE :
134 return ClipBoardImageAlphaType::ALPHA_TYPE_OPAQUE;
135 case Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL :
136 return ClipBoardImageAlphaType::ALPHA_TYPE_PREMULTIPLIED;
137 default :
138 return ClipBoardImageAlphaType::ALPHA_TYPE_UNKNOWN;
139 }
140 }
141
ImageToClipboardColorType(const Media::ImageInfo & imgInfo)142 ClipBoardImageColorType PasteDataRecordAdapterImpl::ImageToClipboardColorType
143 (const Media::ImageInfo &imgInfo)
144 {
145 switch (imgInfo.pixelFormat) {
146 case Media::PixelFormat::RGBA_8888 :
147 return ClipBoardImageColorType::COLOR_TYPE_RGBA_8888;
148 case Media::PixelFormat::BGRA_8888 :
149 return ClipBoardImageColorType::COLOR_TYPE_BGRA_8888;
150 default :
151 return ClipBoardImageColorType::COLOR_TYPE_UNKNOWN;
152 }
153 }
154
ClipboardToImageAlphaType(ClipBoardImageAlphaType alphaType)155 Media::AlphaType PasteDataRecordAdapterImpl::ClipboardToImageAlphaType
156 (ClipBoardImageAlphaType alphaType)
157 {
158 switch (alphaType) {
159 case ClipBoardImageAlphaType::ALPHA_TYPE_UNKNOWN :
160 return Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
161 case ClipBoardImageAlphaType::ALPHA_TYPE_OPAQUE :
162 return Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
163 case ClipBoardImageAlphaType::ALPHA_TYPE_PREMULTIPLIED :
164 return Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
165 default :
166 return Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
167 }
168 }
169
ClipboardToImageColorType(ClipBoardImageColorType colorType)170 Media::PixelFormat PasteDataRecordAdapterImpl::ClipboardToImageColorType
171 (ClipBoardImageColorType colorType)
172 {
173 switch (colorType) {
174 case ClipBoardImageColorType::COLOR_TYPE_RGBA_8888 :
175 return Media::PixelFormat::RGBA_8888;
176 case ClipBoardImageColorType::COLOR_TYPE_BGRA_8888 :
177 return Media::PixelFormat::BGRA_8888;
178 default :
179 return Media::PixelFormat::UNKNOWN;
180 }
181 }
182
SetImgData(std::shared_ptr<ClipBoardImageData> imageData)183 bool PasteDataRecordAdapterImpl::SetImgData(std::shared_ptr<ClipBoardImageData> imageData)
184 {
185 if (imageData == nullptr) {
186 WVLOG_E("imageData is null");
187 return false;
188 }
189 Media::InitializationOptions opt;
190 opt.size.width = imageData->width;
191 opt.size.height = imageData->height;
192 opt.pixelFormat = ClipboardToImageColorType(imageData->colorType);
193 opt.alphaType = ClipboardToImageAlphaType(imageData->alphaType);
194 opt.editable = true;
195 std::unique_ptr<Media::PixelMap> pixelMap = Media::PixelMap::Create(opt);
196 if (pixelMap == nullptr) {
197 WVLOG_E("create pixel map failed");
198 return false;
199 }
200 uint64_t stride = static_cast<uint64_t>(imageData->width) << 2;
201 uint64_t bufferSize = stride * static_cast<uint64_t>(imageData->height);
202 uint32_t ret = pixelMap->WritePixels(reinterpret_cast<const uint8_t *>(imageData->data), bufferSize);
203 if (ret != Media::SUCCESS) {
204 WVLOG_E("write pixel map failed %{public}u", ret);
205 return false;
206 }
207
208 std::shared_ptr<Media::PixelMap> pixelMapIn = move(pixelMap);
209
210 if (!builder_) {
211 WVLOG_E("record_ is null");
212 return false;
213 }
214 record_ = builder_->SetPixelMap(pixelMapIn).Build();
215 return true;
216 }
217
GetMimeType()218 std::string PasteDataRecordAdapterImpl::GetMimeType()
219 {
220 return (record_ != nullptr) ? record_->GetMimeType() : "";
221 }
222
GetHtmlText()223 std::shared_ptr<std::string> PasteDataRecordAdapterImpl::GetHtmlText()
224 {
225 return (record_ != nullptr) ? record_->GetHtmlText() : nullptr;
226 }
227
GetPlainText()228 std::shared_ptr<std::string> PasteDataRecordAdapterImpl::GetPlainText()
229 {
230 return (record_ != nullptr) ? record_->GetPlainText() : nullptr;
231 }
232
GetImgData(ClipBoardImageData & imageData)233 bool PasteDataRecordAdapterImpl::GetImgData(ClipBoardImageData &imageData)
234 {
235 if (record_ == nullptr) {
236 WVLOG_E("record_ is null");
237 return false;
238 }
239 std::shared_ptr<Media::PixelMap> pixelMap = record_->GetPixelMap();
240 if (pixelMap == nullptr) {
241 WVLOG_E("pixelMap is null");
242 return false;
243 }
244
245 Media::ImageInfo imgInfo;
246 ClearImgBuffer();
247 bufferSize_ = pixelMap->GetCapacity();
248 if ((bufferSize_ == 0) || (pixelMap->GetPixels() == nullptr)) {
249 WVLOG_E("data in pixel map is empty");
250 return false;
251 }
252
253 imgBuffer_ = static_cast<uint8_t *>(calloc(static_cast<size_t>(bufferSize_), sizeof(uint8_t)));
254 if (imgBuffer_ == nullptr) {
255 WVLOG_E("calloc imgbuffer failed");
256 return false;
257 }
258
259 if (memcpy_s(imgBuffer_, bufferSize_, pixelMap->GetPixels(), bufferSize_)) {
260 WVLOG_E("memcpy imgbuffer failed");
261 ClearImgBuffer();
262 return false;
263 }
264
265 int32_t width = pixelMap->GetWidth();
266 int32_t height = pixelMap->GetHeight();
267 pixelMap->GetImageInfo(imgInfo);
268 int32_t rowBytes = pixelMap->GetRowBytes();
269
270 imageData.colorType = ImageToClipboardColorType(imgInfo);
271 imageData.alphaType = ImageToClipboardAlphaType(imgInfo);
272 imageData.data = (uint32_t *)(imgBuffer_);
273 imageData.dataSize = static_cast<size_t>(bufferSize_);
274 imageData.width = width;
275 imageData.height = height;
276 imageData.rowBytes = static_cast<size_t>(rowBytes);
277 return true;
278 }
279
GetUri()280 std::shared_ptr<std::string> PasteDataRecordAdapterImpl::GetUri()
281 {
282 if (record_ == nullptr) {
283 return nullptr;
284 }
285 auto uri = record_->GetUri();
286 if (uri == nullptr) {
287 return nullptr;
288 }
289 return std::make_shared<std::string>(uri->ToString());
290 }
291
GetCustomData()292 std::shared_ptr<PasteCustomData> PasteDataRecordAdapterImpl::GetCustomData()
293 {
294 if (record_ == nullptr) {
295 return nullptr;
296 }
297 auto customData = record_->GetCustomData();
298 if (customData == nullptr) {
299 return nullptr;
300 }
301 return std::make_shared<PasteCustomData>(customData->GetItemData());
302 }
303
ClearImgBuffer()304 void PasteDataRecordAdapterImpl::ClearImgBuffer()
305 {
306 if (imgBuffer_) {
307 free(imgBuffer_);
308 imgBuffer_ = nullptr;
309 bufferSize_ = 0;
310 }
311 }
312
Clear()313 void PasteDataRecordAdapterImpl::Clear()
314 {
315 ClearImgBuffer();
316 }
317
GetRecord()318 std::shared_ptr<PasteDataRecord> PasteDataRecordAdapterImpl::GetRecord()
319 {
320 return record_;
321 }
322
PasteDataAdapterImpl()323 PasteDataAdapterImpl::PasteDataAdapterImpl()
324 : data_(std::make_shared<PasteData>()) {}
325
PasteDataAdapterImpl(std::shared_ptr<PasteData> data)326 PasteDataAdapterImpl::PasteDataAdapterImpl(
327 std::shared_ptr<PasteData> data) : data_(data) {}
328
AddHtmlRecord(const std::string & html)329 void PasteDataAdapterImpl::AddHtmlRecord(const std::string& html)
330 {
331 if (data_ != nullptr) {
332 data_->AddHtmlRecord(html);
333 }
334 }
335
AddTextRecord(const std::string & text)336 void PasteDataAdapterImpl::AddTextRecord(const std::string& text)
337 {
338 if (data_ != nullptr) {
339 data_->AddTextRecord(text);
340 }
341 }
342
GetMimeTypes()343 std::vector<std::string> PasteDataAdapterImpl::GetMimeTypes()
344 {
345 return (data_ != nullptr) ? data_->GetMimeTypes() :
346 std::vector<std::string>();
347 }
348
GetPrimaryHtml()349 std::shared_ptr<std::string> PasteDataAdapterImpl::GetPrimaryHtml()
350 {
351 return (data_ != nullptr) ? data_->GetPrimaryHtml() : nullptr;
352 }
353
GetPrimaryText()354 std::shared_ptr<std::string> PasteDataAdapterImpl::GetPrimaryText()
355 {
356 return (data_ != nullptr) ? data_->GetPrimaryText() : nullptr;
357 }
358
GetPrimaryMimeType()359 std::shared_ptr<std::string> PasteDataAdapterImpl::GetPrimaryMimeType()
360 {
361 return (data_ != nullptr) ? data_->GetPrimaryMimeType() : nullptr;
362 }
363
GetRecordAt(std::size_t index)364 std::shared_ptr<PasteDataRecordAdapter> PasteDataAdapterImpl::GetRecordAt(
365 std::size_t index)
366 {
367 if (data_ == nullptr || data_->GetRecordCount() <= index) {
368 return nullptr;
369 }
370 return std::make_shared<PasteDataRecordAdapterImpl>(data_->GetRecordAt(index));
371 }
372
GetRecordCount()373 std::size_t PasteDataAdapterImpl::GetRecordCount()
374 {
375 return (data_ != nullptr) ? data_->GetRecordCount() : 0;
376 }
377
AllRecords() const378 PasteRecordList PasteDataAdapterImpl::AllRecords() const
379 {
380 if (data_ == nullptr) {
381 return PasteRecordList();
382 }
383 PasteRecordList result;
384 for (auto& record: data_->AllRecords()) {
385 result.push_back(std::make_shared<PasteDataRecordAdapterImpl>(record));
386 }
387 return result;
388 }
389
GetInstance()390 PasteBoardClientAdapterImpl& PasteBoardClientAdapterImpl::GetInstance()
391 {
392 static PasteBoardClientAdapterImpl instance;
393 return instance;
394 }
395
GetPasteData(PasteRecordList & data)396 bool PasteBoardClientAdapterImpl::GetPasteData(PasteRecordList& data)
397 {
398 PasteData pData;
399 if (!PasteboardClient::GetInstance()->HasPasteData() ||
400 !PasteboardClient::GetInstance()->GetPasteData(pData)) {
401 isLocalPaste_ = false;
402 tokenId_ = 0;
403 return false;
404 }
405 for (auto& record: pData.AllRecords()) {
406 data.push_back(std::make_shared<PasteDataRecordAdapterImpl>(record));
407 }
408 tokenId_ = pData.GetTokenId();
409 isLocalPaste_ = pData.IsLocalPaste();
410 return true;
411 }
412
SetPasteData(const PasteRecordList & data)413 void PasteBoardClientAdapterImpl::SetPasteData(const PasteRecordList& data)
414 {
415 std::vector<std::shared_ptr<PasteDataRecord>> recordList;
416 for (auto& record: data) {
417 PasteDataRecordAdapterImpl* rawRecord =
418 reinterpret_cast<PasteDataRecordAdapterImpl*>(record.get());
419 if (rawRecord == nullptr) {
420 continue;
421 }
422 recordList.push_back(rawRecord->GetRecord());
423 }
424 PasteData pData(recordList);
425 PasteboardClient::GetInstance()->SetPasteData(pData);
426 }
427
HasPasteData()428 bool PasteBoardClientAdapterImpl::HasPasteData()
429 {
430 return PasteboardClient::GetInstance()->HasPasteData();
431 }
432
Clear()433 void PasteBoardClientAdapterImpl::Clear()
434 {
435 PasteRecordList recordList;
436 if (!GetPasteData(recordList)) {
437 WVLOG_E("get paste data failed while clear");
438 PasteboardClient::GetInstance()->Clear();
439 return;
440 }
441 for (auto& record: recordList) {
442 PasteDataRecordAdapterImpl* rawRecord =
443 reinterpret_cast<PasteDataRecordAdapterImpl*>(record.get());
444 if (rawRecord == nullptr) {
445 continue;
446 }
447 rawRecord->Clear();
448 }
449 PasteboardClient::GetInstance()->Clear();
450 }
451
OpenRemoteUri(const std::string & path)452 int32_t PasteBoardClientAdapterImpl::OpenRemoteUri(const std::string& path)
453 {
454 return RemoteUri::OpenRemoteUri(path);
455 }
456
IsLocalPaste() const457 bool PasteBoardClientAdapterImpl::IsLocalPaste() const
458 {
459 return isLocalPaste_;
460 }
461
GetTokenId() const462 uint32_t PasteBoardClientAdapterImpl::GetTokenId() const
463 {
464 return tokenId_;
465 }
466
AddPasteboardChangedObserver(std::shared_ptr<PasteboardObserverAdapter> callback)467 void PasteBoardClientAdapterImpl::AddPasteboardChangedObserver(
468 std::shared_ptr<PasteboardObserverAdapter> callback)
469 {
470 if (callback) {
471 sptr<PasteboardObserver> observer;
472 {
473 std::lock_guard<std::mutex> lock(mutex_);
474 ObserverMap::iterator iter = reg_.find(callback.get());
475 if (iter != reg_.end()) {
476 return;
477 }
478 observer = new (std::nothrow) PasteboardObserverAdapterImpl(callback);
479 if (!observer) {
480 return;
481 }
482 reg_.emplace(std::make_pair(callback.get(), observer));
483 }
484 PasteboardClient::GetInstance()->AddPasteboardChangedObserver(observer);
485 }
486 }
487
RemovePasteboardChangedObserver(std::shared_ptr<PasteboardObserverAdapter> callback)488 void PasteBoardClientAdapterImpl::RemovePasteboardChangedObserver(
489 std::shared_ptr<PasteboardObserverAdapter> callback)
490 {
491 if (callback) {
492 sptr<PasteboardObserver> observer;
493 {
494 std::lock_guard<std::mutex> lock(mutex_);
495 ObserverMap::iterator iter = reg_.find(callback.get());
496 if (iter == reg_.end()) {
497 return;
498 }
499 observer = iter->second;
500 reg_.erase(iter);
501 }
502 PasteboardClient::GetInstance()->RemovePasteboardChangedObserver(observer);
503 }
504 }
505 } // namespace OHOS::NWeb
506