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 { TAG_PROPS = TAG_BUFF + 1, TAG_RECORDS, TAG_DRAGGED_DATA_FLAG, TAG_LOCAL_PASTE_FLAG };
32 enum TAG_PROPERTY : uint16_t {
33 TAG_ADDITIONS = TAG_BUFF + 1,
34 TAG_MIMETYPES,
35 TAG_TAG,
36 TAG_LOCAL_ONLY,
37 TAG_TIMESTAMP,
38 TAG_SHAREOPTION,
39 TAG_TOKENID,
40 TAG_ISREMOTE,
41 TAG_BUNDLENAME,
42 TAG_SETTIME,
43 };
44
45 std::string PasteData::sharePath = "";
46 std::string PasteData::WEBVIEW_PASTEDATA_TAG = "WebviewPasteDataTag";
47 const std::string PasteData::DISTRIBUTEDFILES_TAG = "distributedfiles";
48 const std::string PasteData::PATH_SHARE = "/data/storage/el2/share/r/";
49 const std::string PasteData::FILE_SCHEME_PREFIX = "file://";
50 const std::string PasteData::IMG_LOCAL_URI = "file:///";
51 const std::string PasteData::SHARE_PATH_PREFIX = "/mnt/hmdfs/";
52 const std::string PasteData::SHARE_PATH_PREFIX_ACCOUNT = "/account/merge_view/services/";
53 const std::string PasteData::REMOTE_FILE_SIZE = "remoteFileSize";
54
PasteData()55 PasteData::PasteData()
56 {
57 props_.timestamp = steady_clock::now().time_since_epoch().count();
58 props_.localOnly = false;
59 props_.shareOption = ShareOption::CrossDevice;
60 }
61
PasteData(const PasteData & data)62 PasteData::PasteData(const PasteData &data) : orginAuthority_(data.orginAuthority_), valid_(data.valid_),
63 isDraggedData_(data.isDraggedData_), isLocalPaste_(data.isLocalPaste_)
64 {
65 this->props_ = data.props_;
66 for (const auto &item : data.records_) {
67 this->records_.emplace_back(std::make_shared<PasteDataRecord>(*item));
68 }
69 }
70
PasteData(std::vector<std::shared_ptr<PasteDataRecord>> records)71 PasteData::PasteData(std::vector<std::shared_ptr<PasteDataRecord>> records) : records_{ std::move(records) }
72 {
73 props_.timestamp = steady_clock::now().time_since_epoch().count();
74 props_.localOnly = false;
75 props_.shareOption = ShareOption::CrossDevice;
76 }
77
GetProperty() const78 PasteDataProperty PasteData::GetProperty() const
79 {
80 return props_;
81 }
82
AddHtmlRecord(const std::string & html)83 void PasteData::AddHtmlRecord(const std::string &html)
84 {
85 this->AddRecord(PasteDataRecord::NewHtmlRecord(html));
86 }
87
AddPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)88 void PasteData::AddPixelMapRecord(std::shared_ptr<PixelMap> pixelMap)
89 {
90 this->AddRecord(PasteDataRecord::NewPixelMapRecord(std::move(pixelMap)));
91 }
92
AddWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)93 void PasteData::AddWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)
94 {
95 this->AddRecord(PasteDataRecord::NewWantRecord(std::move(want)));
96 }
97
AddTextRecord(const std::string & text)98 void PasteData::AddTextRecord(const std::string &text)
99 {
100 this->AddRecord(PasteDataRecord::NewPlaintTextRecord(text));
101 }
102
AddUriRecord(const OHOS::Uri & uri)103 void PasteData::AddUriRecord(const OHOS::Uri &uri)
104 {
105 this->AddRecord(PasteDataRecord::NewUriRecord(uri));
106 }
107
AddKvRecord(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)108 void PasteData::AddKvRecord(const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
109 {
110 AddRecord(PasteDataRecord::NewKvRecord(mimeType, arrayBuffer));
111 }
112
AddRecord(std::shared_ptr<PasteDataRecord> record)113 void PasteData::AddRecord(std::shared_ptr<PasteDataRecord> record)
114 {
115 if (record == nullptr) {
116 return;
117 }
118 records_.insert(records_.begin(), std::move(record));
119 RefreshMimeProp();
120 }
121
AddRecord(PasteDataRecord & record)122 void PasteData::AddRecord(PasteDataRecord &record)
123 {
124 this->AddRecord(std::make_shared<PasteDataRecord>(record));
125 RefreshMimeProp();
126 }
127
GetMimeTypes()128 std::vector<std::string> PasteData::GetMimeTypes()
129 {
130 std::vector<std::string> mimeType;
131 for (const auto &item : records_) {
132 mimeType.push_back(item->GetMimeType());
133 }
134 return mimeType;
135 }
136
GetPrimaryHtml()137 std::shared_ptr<std::string> PasteData::GetPrimaryHtml()
138 {
139 for (const auto &item : records_) {
140 if (item->GetHtmlText() != nullptr) {
141 return item->GetHtmlText();
142 }
143 }
144 return nullptr;
145 }
146
GetPrimaryPixelMap()147 std::shared_ptr<PixelMap> PasteData::GetPrimaryPixelMap()
148 {
149 for (const auto &item : records_) {
150 if (item->GetPixelMap() != nullptr) {
151 return item->GetPixelMap();
152 }
153 }
154 return nullptr;
155 }
156
GetPrimaryWant()157 std::shared_ptr<OHOS::AAFwk::Want> PasteData::GetPrimaryWant()
158 {
159 for (const auto &item : records_) {
160 if (item->GetWant() != nullptr) {
161 return item->GetWant();
162 }
163 }
164 return nullptr;
165 }
166
GetPrimaryText()167 std::shared_ptr<std::string> PasteData::GetPrimaryText()
168 {
169 for (const auto &item : records_) {
170 if (item->GetPlainText() != nullptr) {
171 return item->GetPlainText();
172 }
173 }
174 return nullptr;
175 }
176
GetPrimaryUri()177 std::shared_ptr<OHOS::Uri> PasteData::GetPrimaryUri()
178 {
179 for (const auto &item : records_) {
180 if (item->GetUri() != nullptr) {
181 return item->GetUri();
182 }
183 }
184 return nullptr;
185 }
186
GetPrimaryMimeType()187 std::shared_ptr<std::string> PasteData::GetPrimaryMimeType()
188 {
189 if (!records_.empty()) {
190 return std::make_shared<std::string>(records_.front()->GetMimeType());
191 } else {
192 return nullptr;
193 }
194 }
195
GetRecordAt(std::size_t index)196 std::shared_ptr<PasteDataRecord> PasteData::GetRecordAt(std::size_t index)
197 {
198 if (records_.size() > index) {
199 return records_[index];
200 } else {
201 return nullptr;
202 }
203 }
204
GetRecordCount()205 std::size_t PasteData::GetRecordCount()
206 {
207 return records_.size();
208 }
209
GetShareOption()210 ShareOption PasteData::GetShareOption()
211 {
212 return props_.shareOption;
213 }
214
SetShareOption(ShareOption shareOption)215 void PasteData::SetShareOption(ShareOption shareOption)
216 {
217 props_.shareOption = shareOption;
218 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "shareOption = %{public}d.", shareOption);
219 }
220
GetTokenId()221 std::uint32_t PasteData::GetTokenId()
222 {
223 return props_.tokenId;
224 }
225
SetTokenId(uint32_t tokenId)226 void PasteData::SetTokenId(uint32_t tokenId)
227 {
228 props_.tokenId = tokenId;
229 }
230
RemoveRecordAt(std::size_t number)231 bool PasteData::RemoveRecordAt(std::size_t number)
232 {
233 if (records_.size() > number) {
234 records_.erase(records_.begin() + static_cast<std::int64_t>(number));
235 RefreshMimeProp();
236 return true;
237 } else {
238 return false;
239 }
240 }
241
ReplaceRecordAt(std::size_t number,std::shared_ptr<PasteDataRecord> record)242 bool PasteData::ReplaceRecordAt(std::size_t number, std::shared_ptr<PasteDataRecord> record)
243 {
244 if (records_.size() > number) {
245 records_[number] = std::move(record);
246 RefreshMimeProp();
247 return true;
248 } else {
249 return false;
250 }
251 }
252
HasMimeType(const std::string & mimeType)253 bool PasteData::HasMimeType(const std::string &mimeType)
254 {
255 for (auto &item : records_) {
256 if (item->GetMimeType() == mimeType) {
257 return true;
258 }
259 }
260 return false;
261 }
262
AllRecords() const263 std::vector<std::shared_ptr<PasteDataRecord>> PasteData::AllRecords() const
264 {
265 return this->records_;
266 }
267
IsDraggedData() const268 bool PasteData::IsDraggedData() const
269 {
270 return isDraggedData_;
271 }
272
IsLocalPaste() const273 bool PasteData::IsLocalPaste() const
274 {
275 return isLocalPaste_;
276 }
277
SetDraggedDataFlag(bool isDraggedData)278 void PasteData::SetDraggedDataFlag(bool isDraggedData)
279 {
280 isDraggedData_ = isDraggedData;
281 }
282
SetLocalPasteFlag(bool isLocalPaste)283 void PasteData::SetLocalPasteFlag(bool isLocalPaste)
284 {
285 isLocalPaste_ = isLocalPaste;
286 }
287
SetRemote(bool isRemote)288 void PasteData::SetRemote(bool isRemote)
289 {
290 props_.isRemote = isRemote;
291 }
292
IsRemote()293 bool PasteData::IsRemote()
294 {
295 return props_.isRemote;
296 }
297
SetBundleName(const std::string & bundleName)298 void PasteData::SetBundleName(const std::string &bundleName)
299 {
300 props_.bundleName = bundleName;
301 }
302
GetBundleName() const303 std::string PasteData::GetBundleName() const
304 {
305 return props_.bundleName;
306 }
307
SetOrginAuthority(const std::string & bundleName)308 void PasteData::SetOrginAuthority(const std::string &bundleName)
309 {
310 orginAuthority_ = bundleName;
311 }
312
GetOrginAuthority() const313 std::string PasteData::GetOrginAuthority() const
314 {
315 return orginAuthority_;
316 }
317
SetTime(const std::string & setTime)318 void PasteData::SetTime(const std::string &setTime)
319 {
320 props_.setTime = setTime;
321 }
322
GetTime()323 std::string PasteData::GetTime()
324 {
325 return props_.setTime;
326 }
327
SetTag(std::string & tag)328 void PasteData::SetTag(std::string &tag)
329 {
330 props_.tag = tag;
331 }
332
GetTag()333 std::string PasteData::GetTag()
334 {
335 return props_.tag;
336 }
337
SetAdditions(AAFwk::WantParams & additions)338 void PasteData::SetAdditions(AAFwk::WantParams &additions)
339 {
340 props_.additions = additions;
341 }
342
SetAddition(const std::string & key,AAFwk::IInterface * value)343 void PasteData::SetAddition(const std::string &key, AAFwk::IInterface *value)
344 {
345 props_.additions.SetParam(key, value);
346 }
347
SetLocalOnly(bool localOnly)348 void PasteData::SetLocalOnly(bool localOnly)
349 {
350 props_.localOnly = localOnly;
351 }
352
GetLocalOnly()353 bool PasteData::GetLocalOnly()
354 {
355 return props_.localOnly;
356 }
357
RefreshMimeProp()358 void PasteData::RefreshMimeProp()
359 {
360 std::vector<std::string> mimeTypes;
361 for (const auto &record : records_) {
362 if (record == nullptr) {
363 continue;
364 }
365 mimeTypes.insert(mimeTypes.end(), record->GetMimeType());
366 }
367 props_.mimeTypes = mimeTypes;
368 }
369
Encode(std::vector<std::uint8_t> & buffer)370 bool PasteData::Encode(std::vector<std::uint8_t> &buffer)
371 {
372 Init(buffer);
373
374 bool ret = Write(buffer, TAG_PROPS, props_);
375 ret = Write(buffer, TAG_RECORDS, records_) && ret;
376 ret = Write(buffer, TAG_DRAGGED_DATA_FLAG, isDraggedData_) && ret;
377 ret = Write(buffer, TAG_LOCAL_PASTE_FLAG, isLocalPaste_) && ret;
378 return ret;
379 }
380
Decode(const std::vector<std::uint8_t> & buffer)381 bool PasteData::Decode(const std::vector<std::uint8_t> &buffer)
382 {
383 total_ = buffer.size();
384 for (; IsEnough();) {
385 TLVHead head{};
386 bool ret = ReadHead(buffer, head);
387 switch (head.tag) {
388 case TAG_PROPS:
389 ret = ret && ReadValue(buffer, props_, head);
390 break;
391 case TAG_RECORDS: {
392 ret = ret && ReadValue(buffer, records_, head);
393 break;
394 }
395 case TAG_DRAGGED_DATA_FLAG: {
396 ret = ret && ReadValue(buffer, isDraggedData_, head);
397 break;
398 }
399 case TAG_LOCAL_PASTE_FLAG: {
400 ret = ret && ReadValue(buffer, isLocalPaste_, head);
401 break;
402 }
403 default:
404 ret = ret && Skip(head.len, buffer.size());
405 break;
406 }
407 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "read value,tag:%{public}u, len:%{public}u, ret:%{public}d",
408 head.tag, head.len, ret);
409 if (!ret) {
410 return false;
411 }
412 }
413 return true;
414 }
Count()415 size_t PasteData::Count()
416 {
417 size_t expectSize = 0;
418 expectSize += props_.Count() + sizeof(TLVHead);
419 expectSize += TLVObject::Count(records_);
420 expectSize += TLVObject::Count(isDraggedData_);
421 expectSize += TLVObject::Count(isLocalPaste_);
422 return expectSize;
423 }
424
IsValid() const425 bool PasteData::IsValid() const
426 {
427 return valid_;
428 }
429
SetInvalid()430 void PasteData::SetInvalid()
431 {
432 valid_ = false;
433 }
434
PasteDataProperty(const PasteDataProperty & property)435 PasteDataProperty::PasteDataProperty(const PasteDataProperty &property)
436 : tag(property.tag), timestamp(property.timestamp), localOnly(property.localOnly),
437 shareOption(property.shareOption), tokenId(property.tokenId), isRemote(property.isRemote),
438 bundleName(property.bundleName), setTime(property.setTime)
439 {
440 this->additions = property.additions;
441 std::copy(property.mimeTypes.begin(), property.mimeTypes.end(), std::back_inserter(this->mimeTypes));
442 }
443
Encode(std::vector<std::uint8_t> & buffer)444 bool PasteDataProperty::Encode(std::vector<std::uint8_t> &buffer)
445 {
446 bool ret = Write(buffer, TAG_ADDITIONS, ParcelUtil::Parcelable2Raw(&additions));
447 ret = Write(buffer, TAG_MIMETYPES, mimeTypes) && ret;
448 ret = Write(buffer, TAG_TAG, tag) && ret;
449 ret = Write(buffer, TAG_LOCAL_ONLY, localOnly) && ret;
450 ret = Write(buffer, TAG_TIMESTAMP, timestamp) && ret;
451 ret = Write(buffer, TAG_SHAREOPTION, (int32_t &)shareOption) && ret;
452 ret = Write(buffer, TAG_TOKENID, tokenId) && ret;
453 ret = Write(buffer, TAG_ISREMOTE, isRemote) && ret;
454 ret = Write(buffer, TAG_BUNDLENAME, bundleName) && ret;
455 ret = Write(buffer, TAG_SETTIME, setTime) && ret;
456 return ret;
457 }
458
Decode(const std::vector<std::uint8_t> & buffer)459 bool PasteDataProperty::Decode(const std::vector<std::uint8_t> &buffer)
460 {
461 for (; IsEnough();) {
462 if (!DecodeTag(buffer)) {
463 return false;
464 }
465 }
466 return true;
467 }
468
DecodeTag(const std::vector<std::uint8_t> & buffer)469 bool PasteDataProperty::DecodeTag(const std::vector<std::uint8_t> &buffer)
470 {
471 TLVHead head{};
472 bool ret = ReadHead(buffer, head);
473 switch (head.tag) {
474 case TAG_ADDITIONS: {
475 RawMem rawMem{};
476 ret = ret && ReadValue(buffer, rawMem, head);
477 auto buff = ParcelUtil::Raw2Parcelable<AAFwk::WantParams>(rawMem);
478 if (buff != nullptr) {
479 additions = *buff;
480 }
481 break;
482 }
483 case TAG_MIMETYPES:
484 ret = ret && ReadValue(buffer, mimeTypes, head);
485 break;
486 case TAG_TAG:
487 ret = ret && ReadValue(buffer, tag, head);
488 break;
489 case TAG_LOCAL_ONLY:
490 ret = ret && ReadValue(buffer, localOnly, head);
491 break;
492 case TAG_TIMESTAMP:
493 ret = ret && ReadValue(buffer, timestamp, head);
494 break;
495 case TAG_SHAREOPTION:
496 ret = ret && ReadValue(buffer, (int32_t &)shareOption, head);
497 break;
498 case TAG_TOKENID:
499 ret = ret && ReadValue(buffer, tokenId, head);
500 break;
501 case TAG_ISREMOTE:
502 ret = ret && ReadValue(buffer, isRemote, head);
503 break;
504 case TAG_BUNDLENAME:
505 ret = ret && ReadValue(buffer, bundleName, head);
506 break;
507 case TAG_SETTIME:
508 ret = ret && ReadValue(buffer, setTime, head);
509 break;
510 default:
511 ret = ret && Skip(head.len, buffer.size());
512 break;
513 }
514 return ret;
515 }
516
Count()517 size_t PasteDataProperty::Count()
518 {
519 size_t expectedSize = 0;
520 expectedSize += TLVObject::Count(ParcelUtil::Parcelable2Raw(&additions));
521 expectedSize += TLVObject::Count(mimeTypes);
522 expectedSize += TLVObject::Count(tag);
523 expectedSize += TLVObject::Count(localOnly);
524 expectedSize += TLVObject::Count(timestamp);
525 expectedSize += TLVObject::Count(shareOption);
526 expectedSize += TLVObject::Count(tokenId);
527 expectedSize += TLVObject::Count(isRemote);
528 expectedSize += TLVObject::Count(bundleName);
529 expectedSize += TLVObject::Count(setTime);
530 return expectedSize;
531 }
532
WriteUriFd(MessageParcel & parcel,UriHandler & uriHandler,bool isClient)533 bool PasteData::WriteUriFd(MessageParcel &parcel, UriHandler &uriHandler, bool isClient)
534 {
535 std::vector<uint32_t> uriIndexList;
536 for (size_t i = 0; i < GetRecordCount(); ++i) {
537 auto record = GetRecordAt(i);
538 if (record == nullptr) {
539 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "record null");
540 continue;
541 }
542 if (isLocalPaste_) {
543 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "isLocalPaste");
544 continue;
545 }
546 if (record->NeedFd(uriHandler)) {
547 uriIndexList.push_back(i);
548 }
549 }
550 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "write fd vector size:%{public}zu", uriIndexList.size());
551 if (!parcel.WriteUInt32Vector(uriIndexList)) {
552 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write fd index vector");
553 return false;
554 }
555 for (auto index : uriIndexList) {
556 auto record = GetRecordAt(index);
557 if (record == nullptr || !record->WriteFd(parcel, uriHandler, isClient)) {
558 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to write fd");
559 return false;
560 }
561 }
562 return true;
563 }
ReadUriFd(MessageParcel & parcel,UriHandler & uriHandler)564 bool PasteData::ReadUriFd(MessageParcel &parcel, UriHandler &uriHandler)
565 {
566 std::vector<uint32_t> fdRecordMap;
567 if (!parcel.ReadUInt32Vector(&fdRecordMap)) {
568 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to read fd index vector");
569 return false;
570 }
571 for (auto index : fdRecordMap) {
572 auto record = GetRecordAt(index);
573 if (record == nullptr || !record->ReadFd(parcel, uriHandler)) {
574 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to read fd");
575 return false;
576 }
577 }
578 return true;
579 }
ReplaceShareUri(int32_t userId)580 void PasteData::ReplaceShareUri(int32_t userId)
581 {
582 auto count = GetRecordCount();
583 for (size_t i = 0; i < count; ++i) {
584 auto record = GetRecordAt(i);
585 if (record == nullptr) {
586 continue;
587 }
588 record->ReplaceShareUri(userId);
589 }
590 }
591
ShareOptionToString(ShareOption shareOption,std::string & out)592 void PasteData::ShareOptionToString(ShareOption shareOption, std::string &out)
593 {
594 if (shareOption == ShareOption::InApp) {
595 out = "InAPP";
596 } else if (shareOption == ShareOption::LocalDevice) {
597 out = "LocalDevice";
598 } else {
599 out = "CrossDevice";
600 }
601 }
602 } // namespace MiscServices
603 } // namespace OHOS