1
2 /*
3 * Copyright (C) 2021 Huawei Device Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "paste_data.h"
18
19 #include <new>
20
21 #include "parcel_util.h"
22 #include "paste_data_record.h"
23 #include "pasteboard_hilog.h"
24 #include "type_traits"
25
26 using namespace std::chrono;
27 using namespace OHOS::Media;
28
29 namespace OHOS {
30 namespace MiscServices {
31 enum TAG_PASTEBOARD : uint16_t {
32 TAG_PROPS = TAG_BUFF + 1,
33 TAG_RECORDS,
34 TAG_DRAGGED_DATA_FLAG,
35 TAG_LOCAL_PASTE_FLAG
36 };
37 enum TAG_PROPERTY : uint16_t {
38 TAG_ADDITIONS = TAG_BUFF + 1,
39 TAG_MIMETYPES,
40 TAG_TAG,
41 TAG_TIMESTAMP,
42 TAG_SHAREOPTION,
43 TAG_TOKENID,
44 TAG_ISREMOTE,
45 TAG_BUNDLENAME,
46 TAG_SETTIME,
47 };
48
49 std::string PasteData::sharePath = "";
50 const std::string PasteData::SHARE_PATH_PREFIX = "/mnt/hmdfs/";
51 const std::string PasteData::SHARE_PATH_PREFIX_ACCOUNT = "/account/merge_view/services/";
52
PasteData(std::vector<std::shared_ptr<PasteDataRecord>> records)53 PasteData::PasteData(std::vector<std::shared_ptr<PasteDataRecord>> records) : records_{ std::move(records) }
54 {
55 props_.timestamp = steady_clock::now().time_since_epoch().count();
56 props_.localOnly = false;
57 props_.shareOption = ShareOption::CrossDevice;
58 }
59
PasteData()60 PasteData::PasteData()
61 {
62 props_.timestamp = steady_clock::now().time_since_epoch().count();
63 props_.localOnly = false;
64 props_.shareOption = ShareOption::CrossDevice;
65 }
66
GetProperty() const67 PasteDataProperty PasteData::GetProperty() const
68 {
69 return props_;
70 }
71
AddHtmlRecord(const std::string & html)72 void PasteData::AddHtmlRecord(const std::string &html)
73 {
74 this->AddRecord(PasteDataRecord::NewHtmlRecord(html));
75 }
76
AddPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)77 void PasteData::AddPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)
78 {
79 this->AddRecord(PasteDataRecord::NewPixelMapRecord(std::move(pixelMap)));
80 }
81
AddWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)82 void PasteData::AddWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)
83 {
84 this->AddRecord(PasteDataRecord::NewWantRecord(std::move(want)));
85 }
86
AddTextRecord(const std::string & text)87 void PasteData::AddTextRecord(const std::string &text)
88 {
89 this->AddRecord(PasteDataRecord::NewPlaintTextRecord(text));
90 }
91
AddUriRecord(const OHOS::Uri & uri)92 void PasteData::AddUriRecord(const OHOS::Uri &uri)
93 {
94 this->AddRecord(PasteDataRecord::NewUriRecord(uri));
95 }
96
AddKvRecord(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)97 void PasteData::AddKvRecord(const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
98 {
99 AddRecord(PasteDataRecord::NewKvRecord(mimeType, arrayBuffer));
100 }
101
AddRecord(std::shared_ptr<PasteDataRecord> record)102 void PasteData::AddRecord(std::shared_ptr<PasteDataRecord> record)
103 {
104 if (record == nullptr) {
105 return;
106 }
107 records_.insert(records_.begin(), std::move(record));
108 if (records_.size() > MAX_RECORD_NUM) {
109 std::vector<std::shared_ptr<PasteDataRecord>> new_records(records_.begin(), records_.end() - 1);
110 this->records_ = new_records;
111 }
112 RefreshMimeProp();
113 }
114
AddRecord(PasteDataRecord & record)115 void PasteData::AddRecord(PasteDataRecord &record)
116 {
117 this->AddRecord(std::make_shared<PasteDataRecord>(record));
118 RefreshMimeProp();
119 }
120
GetMimeTypes()121 std::vector<std::string> PasteData::GetMimeTypes()
122 {
123 std::vector<std::string> mimeType;
124 for (const auto &item : records_) {
125 mimeType.push_back(item->GetMimeType());
126 }
127 return mimeType;
128 }
129
GetPrimaryHtml()130 std::shared_ptr<std::string> PasteData::GetPrimaryHtml()
131 {
132 for (const auto &item : records_) {
133 if (item->GetHtmlText() != nullptr) {
134 return item->GetHtmlText();
135 }
136 }
137 return nullptr;
138 }
139
GetPrimaryPixelMap()140 std::shared_ptr<PixelMap> PasteData::GetPrimaryPixelMap()
141 {
142 for (const auto &item : records_) {
143 if (item->GetPixelMap() != nullptr) {
144 return item->GetPixelMap();
145 }
146 }
147 return nullptr;
148 }
149
GetPrimaryWant()150 std::shared_ptr<OHOS::AAFwk::Want> PasteData::GetPrimaryWant()
151 {
152 for (const auto &item : records_) {
153 if (item->GetWant() != nullptr) {
154 return item->GetWant();
155 }
156 }
157 return nullptr;
158 }
159
GetPrimaryText()160 std::shared_ptr<std::string> PasteData::GetPrimaryText()
161 {
162 for (const auto &item : records_) {
163 if (item->GetPlainText() != nullptr) {
164 return item->GetPlainText();
165 }
166 }
167 return nullptr;
168 }
169
GetPrimaryUri()170 std::shared_ptr<OHOS::Uri> PasteData::GetPrimaryUri()
171 {
172 for (const auto &item : records_) {
173 if (item->GetUri() != nullptr) {
174 return item->GetUri();
175 }
176 }
177 return nullptr;
178 }
179
GetPrimaryMimeType()180 std::shared_ptr<std::string> PasteData::GetPrimaryMimeType()
181 {
182 if (!records_.empty()) {
183 return std::make_shared<std::string>(records_.front()->GetMimeType());
184 } else {
185 return nullptr;
186 }
187 }
188
GetRecordAt(std::size_t index)189 std::shared_ptr<PasteDataRecord> PasteData::GetRecordAt(std::size_t index)
190 {
191 if (records_.size() > index) {
192 return records_[index];
193 } else {
194 return nullptr;
195 }
196 }
197
GetRecordCount()198 std::size_t PasteData::GetRecordCount()
199 {
200 return records_.size();
201 }
202
GetShareOption()203 ShareOption PasteData::GetShareOption()
204 {
205 return props_.shareOption;
206 }
207
SetShareOption(ShareOption shareOption)208 void PasteData::SetShareOption(ShareOption shareOption)
209 {
210 props_.shareOption = shareOption;
211 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "shareOption = %{public}d.", shareOption);
212 }
213
GetTokenId()214 std::uint32_t PasteData::GetTokenId()
215 {
216 return props_.tokenId;
217 }
218
SetTokenId(uint32_t tokenId)219 void PasteData::SetTokenId(uint32_t tokenId)
220 {
221 props_.tokenId = tokenId;
222 }
223
RemoveRecordAt(std::size_t number)224 bool PasteData::RemoveRecordAt(std::size_t number)
225 {
226 if (records_.size() > number) {
227 records_.erase(records_.begin() + static_cast<std::int64_t>(number));
228 RefreshMimeProp();
229 return true;
230 } else {
231 return false;
232 }
233 }
234
ReplaceRecordAt(std::size_t number,std::shared_ptr<PasteDataRecord> record)235 bool PasteData::ReplaceRecordAt(std::size_t number, std::shared_ptr<PasteDataRecord> record)
236 {
237 if (records_.size() > number) {
238 records_[number] = std::move(record);
239 RefreshMimeProp();
240 return true;
241 } else {
242 return false;
243 }
244 }
245
HasMimeType(const std::string & mimeType)246 bool PasteData::HasMimeType(const std::string &mimeType)
247 {
248 for (auto &item : records_) {
249 if (item->GetMimeType() == mimeType) {
250 return true;
251 }
252 }
253 return false;
254 }
255
AllRecords() const256 std::vector<std::shared_ptr<PasteDataRecord>> PasteData::AllRecords() const
257 {
258 return this->records_;
259 }
260
IsDraggedData() const261 bool PasteData::IsDraggedData() const
262 {
263 return isDraggedData_;
264 }
265
IsLocalPaste() const266 bool PasteData::IsLocalPaste() const
267 {
268 return isLocalPaste_;
269 }
270
SetDraggedDataFlag(bool isDraggedData)271 void PasteData::SetDraggedDataFlag(bool isDraggedData)
272 {
273 isDraggedData_ = isDraggedData;
274 }
275
SetLocalPasteFlag(bool isLocalPaste)276 void PasteData::SetLocalPasteFlag(bool isLocalPaste)
277 {
278 isLocalPaste_ = isLocalPaste;
279 }
280
SetRemote(bool isRemote)281 void PasteData::SetRemote(bool isRemote)
282 {
283 props_.isRemote = isRemote;
284 }
285
SetBundleName(const std::string & bundleName)286 void PasteData::SetBundleName(const std::string &bundleName)
287 {
288 props_.bundleName = bundleName;
289 }
290
SetTime(const std::string & setTime)291 void PasteData::SetTime(const std::string &setTime)
292 {
293 props_.setTime = setTime;
294 }
295
SetTag(std::string & tag)296 void PasteData::SetTag(std::string &tag)
297 {
298 props_.tag = tag;
299 }
GetTag()300 std::string PasteData::GetTag()
301 {
302 return props_.tag;
303 }
SetAdditions(AAFwk::WantParams & additions)304 void PasteData::SetAdditions(AAFwk::WantParams &additions)
305 {
306 props_.additions = additions;
307 }
308
RefreshMimeProp()309 void PasteData::RefreshMimeProp()
310 {
311 std::vector<std::string> mimeTypes;
312 for (const auto &record : records_) {
313 if (record == nullptr) {
314 continue;
315 }
316 mimeTypes.insert(mimeTypes.end(), record->GetMimeType());
317 }
318 props_.mimeTypes = mimeTypes;
319 }
320
MarshallingProps(Parcel & parcel) const321 bool PasteData::MarshallingProps(Parcel &parcel) const
322 {
323 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "props.shareOption = %{public}d.", props_.shareOption);
324 return parcel.WriteParcelable(&props_.additions) && parcel.WriteStringVector(props_.mimeTypes) &&
325 parcel.WriteString(props_.tag) && parcel.WriteInt64(props_.timestamp) &&
326 parcel.WriteInt32(static_cast<int32_t>(props_.shareOption));
327 }
328
UnMarshalling(Parcel & parcel,PasteDataProperty & props)329 bool PasteData::UnMarshalling(Parcel &parcel, PasteDataProperty &props)
330 {
331 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start.");
332
333 std::shared_ptr<AAFwk::WantParams> wantParams(parcel.ReadParcelable<AAFwk::WantParams>());
334 if (wantParams != nullptr) {
335 props.additions = *wantParams;
336 }
337 if (!parcel.ReadStringVector(&props.mimeTypes)) {
338 return false;
339 }
340 props.tag = parcel.ReadString();
341 props.timestamp = parcel.ReadInt64();
342 props.shareOption = static_cast<ShareOption>(parcel.ReadInt32());
343 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "props.shareOption = %{public}d.", props.shareOption);
344 return true;
345 }
346
Marshalling(Parcel & parcel) const347 bool PasteData::Marshalling(Parcel &parcel) const
348 {
349 auto length = records_.size();
350 if (length == 0) {
351 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "length == 0.");
352 return false;
353 }
354 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "start, length = %{public}zu.", length);
355 if (!parcel.WriteUint32(static_cast<uint32_t>(length))) {
356 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "write length failed.");
357 return false;
358 }
359
360 for (const auto &item : records_) {
361 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "for.");
362 if (!parcel.WriteParcelable(item.get())) {
363 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "WriteParcelable failed.");
364 return false;
365 }
366 }
367
368 auto ret = MarshallingProps(parcel);
369 if (!ret) {
370 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "MarshallingProps failed.");
371 return false;
372 }
373
374 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "end.");
375 return true;
376 }
377
Unmarshalling(Parcel & parcel)378 PasteData *PasteData::Unmarshalling(Parcel &parcel)
379 {
380 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "start.");
381 auto *pasteData = new (std::nothrow) PasteData();
382 if (pasteData == nullptr) {
383 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "pasteData is nullptr.");
384 return pasteData;
385 }
386
387 auto length = parcel.ReadUint32();
388 if (length <= 0) {
389 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "length error.");
390 delete pasteData;
391 pasteData = nullptr;
392 return pasteData;
393 }
394 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "length = %{public}u.", length);
395
396 uint32_t failedNum = 0;
397 for (uint32_t i = 0; i < length; i++) {
398 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "for.");
399 std::unique_ptr<PasteDataRecord> record(parcel.ReadParcelable<PasteDataRecord>());
400 if (!record) {
401 failedNum++;
402 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "ReadParcelable failed, i = %{public}d.", i);
403 continue;
404 }
405 pasteData->AddRecord(*record);
406 }
407 if (failedNum == length) {
408 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "all failed.");
409 delete pasteData;
410 pasteData = nullptr;
411 return pasteData;
412 }
413
414 auto ret = UnMarshalling(parcel, pasteData->props_);
415 if (!ret) {
416 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "UnMarshallingProps failed.");
417 delete pasteData;
418 pasteData = nullptr;
419 }
420
421 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "end.");
422 return pasteData;
423 }
424
Encode(std::vector<std::uint8_t> & buffer)425 bool PasteData::Encode(std::vector<std::uint8_t> &buffer)
426 {
427 Init(buffer);
428
429 bool ret = Write(buffer, TAG_PROPS, props_);
430 ret = Write(buffer, TAG_RECORDS, records_) && ret;
431 ret = Write(buffer, TAG_DRAGGED_DATA_FLAG, isDraggedData_) && ret;
432 ret = Write(buffer, TAG_LOCAL_PASTE_FLAG, isLocalPaste_) && ret;
433 return ret;
434 }
435
Decode(const std::vector<std::uint8_t> & buffer)436 bool PasteData::Decode(const std::vector<std::uint8_t> &buffer)
437 {
438 total_ = buffer.size();
439 for (; IsEnough();) {
440 TLVHead head{};
441 bool ret = ReadHead(buffer, head);
442 switch (head.tag) {
443 case TAG_PROPS:
444 ret = ret && ReadValue(buffer, props_, head);
445 break;
446 case TAG_RECORDS: {
447 ret = ret && ReadValue(buffer, records_, head);
448 break;
449 }
450 case TAG_DRAGGED_DATA_FLAG: {
451 ret = ret && ReadValue(buffer, isDraggedData_, head);
452 break;
453 }
454 case TAG_LOCAL_PASTE_FLAG: {
455 ret = ret && ReadValue(buffer, isLocalPaste_, head);
456 break;
457 }
458 default:
459 ret = ret && Skip(head.len, buffer.size());
460 break;
461 }
462 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u, ret:%{public}d",
463 head.tag, head.len, ret);
464 if (!ret) {
465 return false;
466 }
467 }
468 return true;
469 }
Count()470 size_t PasteData::Count()
471 {
472 size_t expectSize = 0;
473 expectSize += props_.Count() + sizeof(TLVHead);
474 expectSize += TLVObject::Count(records_);
475 expectSize += TLVObject::Count(isDraggedData_);
476 expectSize += TLVObject::Count(isLocalPaste_);
477 return expectSize;
478 }
479
IsValid() const480 bool PasteData::IsValid() const
481 {
482 return valid_;
483 }
484
SetInvalid()485 void PasteData::SetInvalid()
486 {
487 valid_ = false;
488 }
489
Encode(std::vector<std::uint8_t> & buffer)490 bool PasteDataProperty::Encode(std::vector<std::uint8_t> &buffer)
491 {
492 bool ret = Write(buffer, TAG_ADDITIONS, ParcelUtil::Parcelable2Raw(&additions));
493 ret = Write(buffer, TAG_MIMETYPES, mimeTypes) && ret;
494 ret = Write(buffer, TAG_TAG, tag) && ret;
495 ret = Write(buffer, TAG_TIMESTAMP, timestamp) && ret;
496 ret = Write(buffer, TAG_SHAREOPTION, (int32_t &)shareOption) && ret;
497 ret = Write(buffer, TAG_TOKENID, tokenId) && ret;
498 ret = Write(buffer, TAG_ISREMOTE, isRemote) && ret;
499 ret = Write(buffer, TAG_BUNDLENAME, bundleName) && ret;
500 ret = Write(buffer, TAG_SETTIME, setTime) && ret;
501 return ret;
502 }
Decode(const std::vector<std::uint8_t> & buffer)503 bool PasteDataProperty::Decode(const std::vector<std::uint8_t> &buffer)
504 {
505 for (; IsEnough();) {
506 TLVHead head{};
507 bool ret = ReadHead(buffer, head);
508 switch (head.tag) {
509 case TAG_ADDITIONS: {
510 RawMem rawMem{};
511 ret = ret && ReadValue(buffer, rawMem, head);
512 auto buff = ParcelUtil::Raw2Parcelable<AAFwk::WantParams>(rawMem);
513 if (buff != nullptr) {
514 additions = *buff;
515 }
516 break;
517 }
518 case TAG_MIMETYPES:
519 ret = ret && ReadValue(buffer, mimeTypes, head);
520 break;
521 case TAG_TAG:
522 ret = ret && ReadValue(buffer, tag, head);
523 break;
524 case TAG_TIMESTAMP:
525 ret = ret && ReadValue(buffer, timestamp, head);
526 break;
527 case TAG_SHAREOPTION:
528 ret = ret && ReadValue(buffer, (int32_t &)shareOption, head);
529 break;
530 case TAG_TOKENID:
531 ret = ret && ReadValue(buffer, tokenId, head);
532 break;
533 case TAG_ISREMOTE:
534 ret = ret && ReadValue(buffer, isRemote, head);
535 break;
536 case TAG_BUNDLENAME:
537 ret = ret && ReadValue(buffer, bundleName, head);
538 break;
539 case TAG_SETTIME:
540 ret = ret && ReadValue(buffer, setTime, head);
541 break;
542 default:
543 ret = ret && Skip(head.len, buffer.size());
544 break;
545 }
546 if (!ret) {
547 return false;
548 }
549 }
550 return true;
551 }
Count()552 size_t PasteDataProperty::Count()
553 {
554 size_t expectedSize = 0;
555 expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(&additions));
556 expectedSize += TLVObject::Count(mimeTypes);
557 expectedSize += TLVObject::Count(tag);
558 expectedSize += TLVObject::Count(timestamp);
559 expectedSize += TLVObject::Count(shareOption);
560 expectedSize += TLVObject::Count(tokenId);
561 expectedSize += TLVObject::Count(isRemote);
562 expectedSize += TLVObject::Count(bundleName);
563 expectedSize += TLVObject::Count(setTime);
564 return expectedSize;
565 }
566
WriteUriFd(MessageParcel & parcel,UriHandler & uriHandler,bool isClient)567 bool PasteData::WriteUriFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient)
568 {
569 std::vector<uint32_t> uriIndexList;
570 for (size_t i = 0; i < GetRecordCount(); ++i) {
571 auto record = GetRecordAt(i);
572 if (record == nullptr) {
573 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "record null");
574 continue;
575 }
576 if (isLocalPaste_) {
577 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "isLocalPaste");
578 continue;
579 }
580 if (record->NeedFd(uriHandler)) {
581 uriIndexList.push_back(i);
582 }
583 }
584 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "write fd vector size:%{public}zu", uriIndexList.size());
585 if (!parcel.WriteUInt32Vector(uriIndexList)) {
586 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write fd index vector");
587 return false;
588 }
589 for (auto index : uriIndexList) {
590 auto record = GetRecordAt(index);
591 if (record == nullptr || !record->WriteFd(parcel, uriHandler, isClient)) {
592 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write fd");
593 return false;
594 }
595 }
596 return true;
597 }
ReadUriFd(MessageParcel & parcel,UriHandler & uriHandler)598 bool PasteData::ReadUriFd(MessageParcel &parcel, UriHandler &uriHandler)
599 {
600 std::vector<uint32_t> fdRecordMap;
601 if (!parcel.ReadUInt32Vector(&fdRecordMap)) {
602 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to read fd index vector");
603 return false;
604 }
605 for (auto index : fdRecordMap) {
606 auto record = GetRecordAt(index);
607 if (record == nullptr || !record->ReadFd(parcel, uriHandler)) {
608 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to read fd");
609 return false;
610 }
611 }
612 return true;
613 }
ReplaceShareUri(int32_t userId)614 void PasteData::ReplaceShareUri(int32_t userId)
615 {
616 auto count = GetRecordCount();
617 for (size_t i = 0; i < count; ++i) {
618 auto record = GetRecordAt(i);
619 if (record == nullptr) {
620 continue;
621 }
622 record->ReplaceShareUri(userId);
623 }
624 }
625 } // namespace MiscServices
626 } // namespace OHOS