• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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