• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2025 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_web_controller.h"
17 
18 #include <regex>
19 
20 #include "file_uri.h"
21 #include "pasteboard_common.h"
22 #include "uri_permission_manager_client.h"
23 #include "pasteboard_hilog.h"
24 
25 namespace {
26 constexpr const char *IMG_TAG_PATTERN = "<img.*?>";
27 constexpr const char *IMG_TAG_SRC_PATTERN = "src=(['\"])(.*?)\\1";
28 constexpr const char *IMG_TAG_SRC_HEAD = "src=\"";
29 constexpr const char *IMG_LOCAL_URI = "file:///";
30 constexpr const char *IMG_LOCAL_PATH = "://";
31 constexpr const char *FILE_SCHEME_PREFIX = "file://";
32 
33 constexpr uint32_t FOUR_BYTES = 4;
34 constexpr uint32_t EIGHT_BIT = 8;
35 constexpr int32_t DOCS_LOCAL_PATH_SUBSTR_START_INDEX = 1;
36 
37 struct Cmp {
operator ()__anon8401e5a50111::Cmp38     bool operator()(const uint32_t &lhs, const uint32_t &rhs) const
39     {
40         return lhs > rhs;
41     }
42 };
43 } // namespace
44 
45 namespace OHOS {
46 namespace MiscServices {
47 
48 // static
GetInstance()49 PasteboardWebController &PasteboardWebController::GetInstance()
50 {
51     static PasteboardWebController instance;
52     return instance;
53 }
54 
SplitWebviewPasteData(PasteData & pasteData)55 bool PasteboardWebController::SplitWebviewPasteData(PasteData &pasteData)
56 {
57     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "start");
58     auto hasExtraRecord = false;
59     for (const auto &record : pasteData.AllRecords()) {
60         if (record->GetRecordId() == record->GetFrom()) {
61             continue;
62         }
63         auto htmlEntry = record->GetEntryByMimeType(MIMETYPE_TEXT_HTML);
64         if (htmlEntry == nullptr) {
65             continue;
66         }
67         std::shared_ptr<std::string> html = htmlEntry->ConvertToHtml();
68         if (html == nullptr || html->empty()) {
69             continue;
70         }
71         std::vector<std::shared_ptr<PasteDataRecord>> extraUriRecords = SplitHtml2Records(html, record->GetRecordId());
72         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "split html, recordId=%{public}u, uri count=%{public}zu",
73             record->GetRecordId(), extraUriRecords.size());
74         if (extraUriRecords.empty()) {
75             continue;
76         }
77         hasExtraRecord = true;
78         for (const auto &item : extraUriRecords) {
79             pasteData.AddRecord(item);
80         }
81         record->SetFrom(record->GetRecordId());
82     }
83     if (hasExtraRecord) {
84         pasteData.SetTag(PasteData::WEBVIEW_PASTEDATA_TAG);
85     }
86     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "end");
87     return hasExtraRecord;
88 }
89 
SetWebviewPasteData(PasteData & pasteData,const std::string & bundleName)90 void PasteboardWebController::SetWebviewPasteData(PasteData &pasteData, const std::string &bundleName)
91 {
92     if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG) {
93         return;
94     }
95     for (auto &item : pasteData.AllRecords()) {
96         if (item->GetUri() == nullptr || item->GetFrom() == 0 || item->GetRecordId() == item->GetFrom()) {
97             continue;
98         }
99         std::shared_ptr<Uri> uri = item->GetUri();
100         std::string puri = uri->ToString();
101         if (puri.substr(0, strlen(IMG_LOCAL_URI)) == PasteData::IMG_LOCAL_URI &&
102             puri.find(FILE_SCHEME_PREFIX + PasteData::PATH_SHARE) == std::string::npos) {
103             std::string path = uri->GetPath();
104             std::string newUriStr = "";
105             if (path.substr(0, PasteData::DOCS_LOCAL_TAG.size()) == PasteData::DOCS_LOCAL_TAG) {
106                 newUriStr = FILE_SCHEME_PREFIX;
107                 newUriStr += path.substr(DOCS_LOCAL_PATH_SUBSTR_START_INDEX);
108             } else {
109                 newUriStr = FILE_SCHEME_PREFIX;
110                 newUriStr += bundleName + path;
111             }
112             item->SetUri(std::make_shared<OHOS::Uri>(newUriStr));
113             PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "uri: %{private}s -> %{private}s", puri.c_str(),
114                 newUriStr.c_str());
115         }
116     }
117 }
118 
CheckAppUriPermission(PasteData & pasteData)119 void PasteboardWebController::CheckAppUriPermission(PasteData &pasteData)
120 {
121     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "enter");
122     std::vector<std::string> uris;
123     std::vector<size_t> indexs;
124     std::vector<bool> checkResults;
125     for (size_t i = 0; i < pasteData.GetRecordCount(); i++) {
126         auto item = pasteData.GetRecordAt(i);
127         if (item == nullptr || item->GetOriginUri() == nullptr) {
128             continue;
129         }
130         auto uri = item->GetOriginUri()->ToString();
131         uris.emplace_back(uri);
132         indexs.emplace_back(i);
133     }
134     if (uris.empty()) {
135         return;
136     }
137     size_t offset = 0;
138     size_t length = uris.size();
139     size_t count = PasteData::URI_BATCH_SIZE;
140     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "loop for CheckUriAuthorization, uri count=%{public}zu", uris.size());
141     while (length > offset) {
142         if (length - offset < PasteData::URI_BATCH_SIZE) {
143             count = length - offset;
144         }
145         auto sendValues = std::vector<std::string>(uris.begin() + offset, uris.begin() + offset + count);
146         std::vector<bool> ret = AAFwk::UriPermissionManagerClient::GetInstance().CheckUriAuthorization(
147             sendValues, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, pasteData.GetTokenId());
148         checkResults.insert(checkResults.end(), ret.begin(), ret.end());
149         offset += count;
150     }
151     if (checkResults.size() != indexs.size()) {
152         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "check uri authorization fail");
153         return;
154     }
155     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "loop for SetGrantUriPermission");
156     for (size_t i = 0; i < indexs.size(); i++) {
157         auto item = pasteData.GetRecordAt(indexs[i]);
158         if (item == nullptr || item->GetOriginUri() == nullptr) {
159             continue;
160         }
161         item->SetGrantUriPermission(checkResults[i]);
162     }
163     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "leave");
164 }
165 
RefreshUri(std::shared_ptr<PasteDataRecord> & record,const std::string & targetBundle)166 void PasteboardWebController::RefreshUri(std::shared_ptr<PasteDataRecord> &record, const std::string &targetBundle)
167 {
168     PASTEBOARD_CHECK_AND_RETURN_LOGD(record->GetUri() != nullptr, PASTEBOARD_MODULE_COMMON,
169         "id=%{public}u, uri is null", record->GetRecordId());
170     PASTEBOARD_CHECK_AND_RETURN_LOGD(record->GetFrom() != 0 && record->GetFrom() != record->GetRecordId(),
171         PASTEBOARD_MODULE_COMMON, "id=%{public}u, from=%{public}u", record->GetRecordId(), record->GetFrom());
172 
173     std::shared_ptr<Uri> uri = record->GetUri();
174     std::string puri = uri->ToString();
175     std::string realUri = puri;
176     if (puri.substr(0, strlen(FILE_SCHEME_PREFIX)) == FILE_SCHEME_PREFIX) {
177         AppFileService::ModuleFileUri::FileUri fileUri(puri);
178         std::string realPath = PasteBoardCommon::IsPasteboardService() ? fileUri.GetRealPathBySA(targetBundle) :
179             fileUri.GetRealPath();
180         realUri = FILE_SCHEME_PREFIX;
181         realUri += realPath;
182         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "uri: %{private}s -> %{private}s", puri.c_str(), realUri.c_str());
183     }
184     if (realUri.find(PasteData::DISTRIBUTEDFILES_TAG) != std::string::npos) {
185         record->SetConvertUri(realUri);
186     } else {
187         record->SetUri(std::make_shared<OHOS::Uri>(realUri));
188     }
189 }
190 
RetainUri(PasteData & pasteData)191 void PasteboardWebController::RetainUri(PasteData &pasteData)
192 {
193     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "start");
194     if (!pasteData.IsLocalPaste()) {
195         return;
196     }
197     // clear convert uri
198     for (size_t i = 0; i < pasteData.GetRecordCount(); ++i) {
199         auto record = pasteData.GetRecordAt(i);
200         if (record != nullptr) {
201             record->SetConvertUri("");
202         }
203     }
204     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "end");
205 }
206 
RebuildWebviewPasteData(PasteData & pasteData,const std::string & targetBundle)207 void PasteboardWebController::RebuildWebviewPasteData(PasteData &pasteData, const std::string &targetBundle)
208 {
209     if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG) {
210         return;
211     }
212     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_COMMON, "rebuild start, record count=%{public}zu", pasteData.GetRecordCount());
213     auto justSplitHtml = false;
214     auto details = std::make_shared<Details>();
215     std::string textContent;
216     for (auto &item : pasteData.AllRecords()) {
217         justSplitHtml = justSplitHtml || item->GetFrom() > 0;
218         if (!item->GetTextContent().empty() && textContent.empty()) {
219             details = item->GetDetails();
220             textContent = item->GetTextContent();
221         }
222         RefreshUri(item, targetBundle);
223     }
224     if (justSplitHtml) {
225         MergeExtraUris2Html(pasteData);
226         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "Rebuild webview PasteData end, merged uris into html.");
227         return;
228     }
229     if (pasteData.GetPrimaryHtml() == nullptr) {
230         return;
231     }
232 
233     auto webData = std::make_shared<PasteData>(pasteData);
234     RebuildHtml(webData);
235     PasteDataRecord::Builder builder(MIMETYPE_TEXT_HTML);
236     std::shared_ptr<PasteDataRecord> pasteDataRecord = builder.SetMimeType(MIMETYPE_TEXT_HTML).
237         SetPlainText(pasteData.GetPrimaryText()).SetHtmlText(webData->GetPrimaryHtml()).Build();
238     if (details) {
239         pasteDataRecord->SetDetails(*details);
240     }
241     pasteDataRecord->SetUDType(UDMF::HTML);
242     pasteDataRecord->SetTextContent(textContent);
243     webData->AddRecord(pasteDataRecord);
244     std::size_t recordCnt = webData->GetRecordCount();
245     if (recordCnt >= 1) {
246         webData->RemoveRecordAt(recordCnt - 1);
247     }
248     pasteData = *webData;
249     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "Rebuild end, record count=%{public}zu", pasteData.GetRecordCount());
250 }
251 
SplitHtml2Records(const std::shared_ptr<std::string> & html,uint32_t recordId)252 std::vector<std::shared_ptr<PasteDataRecord>> PasteboardWebController::SplitHtml2Records(
253     const std::shared_ptr<std::string> &html, uint32_t recordId) noexcept
254 {
255     std::vector<std::pair<std::string, uint32_t>> matchVec = SplitHtmlWithImgLabel(html);
256     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "matchVec size: %{public}zu", matchVec.size());
257     if (matchVec.empty()) {
258         return {};
259     }
260     std::map<std::string, std::vector<uint8_t>> imgSrcMap = SplitHtmlWithImgSrcLabel(matchVec);
261     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "imgSrcMap size: %{public}zu", imgSrcMap.size());
262     return BuildPasteDataRecords(imgSrcMap, recordId);
263 }
264 
MergeExtraUris2Html(PasteData & data)265 void PasteboardWebController::MergeExtraUris2Html(PasteData &data)
266 {
267     auto recordGroups = GroupRecordWithFrom(data);
268     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "recordGroups size: %{public}zu", recordGroups.size());
269     for (auto &recordGroup : recordGroups) {
270         ReplaceHtmlRecordContentByExtraUris(recordGroup.second);
271     }
272     RemoveExtraUris(data);
273 }
274 
RebuildHtml(std::shared_ptr<PasteData> pasteData)275 std::shared_ptr<std::string> PasteboardWebController::RebuildHtml(std::shared_ptr<PasteData> pasteData) noexcept
276 {
277     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(pasteData != nullptr, nullptr, PASTEBOARD_MODULE_COMMON, "pasteData is null");
278     std::vector<std::shared_ptr<PasteDataRecord>> pasteDataRecords = pasteData->AllRecords();
279     std::shared_ptr<std::string> htmlData;
280     std::map<uint32_t, std::pair<std::string, std::string>, Cmp> replaceUris;
281 
282     for (const auto &item : pasteDataRecords) {
283         PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(item != nullptr, nullptr,
284                                              PASTEBOARD_MODULE_COMMON, "item is null");
285         std::shared_ptr<std::string> html = item->GetHtmlText();
286         if (html != nullptr) {
287             htmlData = html;
288         }
289         std::shared_ptr<OHOS::Uri> uri = item->GetUri();
290         std::shared_ptr<MiscServices::MineCustomData> customData = item->GetCustomData();
291         if (uri == nullptr || customData == nullptr) {
292             continue;
293         }
294         std::map<std::string, std::vector<uint8_t>> customItemData = customData->GetItemData();
295         for (const auto &itemData : customItemData) {
296             for (uint32_t i = 0; i < itemData.second.size(); i += FOUR_BYTES) {
297                 uint32_t offset = static_cast<uint32_t>(itemData.second[i]) |
298                                   static_cast<uint32_t>(itemData.second[i + 1] << 8) |
299                                   static_cast<uint32_t>(itemData.second[i + 2] << 16) |
300                                   static_cast<uint32_t>(itemData.second[i + 3] << 24);
301                 replaceUris[offset] = std::make_pair(uri->ToString(), itemData.first);
302             }
303         }
304     }
305 
306     RemoveAllRecord(pasteData);
307     for (auto &replaceUri : replaceUris) {
308         htmlData->replace(replaceUri.first, replaceUri.second.second.size(), replaceUri.second.first);
309     }
310     pasteData->AddHtmlRecord(*htmlData);
311     return htmlData;
312 }
313 
SplitHtmlWithImgLabel(const std::shared_ptr<std::string> html)314 std::vector<std::pair<std::string, uint32_t>> PasteboardWebController::SplitHtmlWithImgLabel(
315     const std::shared_ptr<std::string> html) noexcept
316 {
317     std::smatch results;
318     std::string pattern(IMG_TAG_PATTERN);
319     std::regex reg(pattern);
320     std::string::const_iterator iterStart = html->begin();
321     std::string::const_iterator iterEnd = html->end();
322     std::vector<std::pair<std::string, uint32_t>> matchVec;
323 
324     try {
325         while (std::regex_search(iterStart, iterEnd, results, reg)) {
326             std::string tmp = results[0];
327             iterStart = results[0].second;
328             uint32_t offset = static_cast<uint32_t>(results[0].first - html->begin());
329 
330             matchVec.emplace_back(tmp, offset);
331         }
332     } catch (std::regex_error &e) {
333         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "Regex error !");
334     }
335 
336     return matchVec;
337 }
338 
SplitHtmlWithImgSrcLabel(const std::vector<std::pair<std::string,uint32_t>> & matchVec)339 std::map<std::string, std::vector<uint8_t>> PasteboardWebController::SplitHtmlWithImgSrcLabel(
340     const std::vector<std::pair<std::string, uint32_t>> &matchVec) noexcept
341 {
342     std::map<std::string, std::vector<uint8_t>> res;
343     std::smatch match;
344     std::regex re(IMG_TAG_SRC_PATTERN);
345     for (const auto &node : matchVec) {
346         std::string::const_iterator iterStart = node.first.begin();
347         std::string::const_iterator iterEnd = node.first.end();
348 
349         while (std::regex_search(iterStart, iterEnd, match, re)) {
350             std::string tmp = match[0];
351             iterStart = match[0].second;
352             uint32_t offset = static_cast<uint32_t>(match[0].first - node.first.begin());
353             tmp = tmp.substr(strlen(IMG_TAG_SRC_HEAD));
354             tmp.pop_back();
355             if (!IsLocalURI(tmp)) {
356                 continue;
357             }
358             offset += strlen(IMG_TAG_SRC_HEAD) + node.second;
359             for (uint32_t i = 0; i < FOUR_BYTES; i++) {
360                 res[tmp].emplace_back((offset >> (EIGHT_BIT * i)) & 0xff);
361             }
362         }
363     }
364     return res;
365 }
366 
BuildPasteDataRecords(const std::map<std::string,std::vector<uint8_t>> & imgSrcMap,uint32_t recordId)367 std::vector<std::shared_ptr<PasteDataRecord>> PasteboardWebController::BuildPasteDataRecords(
368     const std::map<std::string, std::vector<uint8_t>> &imgSrcMap, uint32_t recordId) noexcept
369 {
370     std::vector<std::shared_ptr<PasteDataRecord>> records;
371     for (const auto &item : imgSrcMap) {
372         PasteDataRecord::Builder builder(MiscServices::MIMETYPE_TEXT_URI);
373         auto uri = std::make_shared<OHOS::Uri>(item.first);
374         builder.SetUri(uri);
375         auto customData = std::make_shared<MiscServices::MineCustomData>();
376         customData->AddItemData(item.first, item.second);
377         builder.SetCustomData(customData);
378         auto record = builder.Build();
379         record->SetFrom(recordId);
380         records.push_back(record);
381     }
382     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "Build extra records size: %{public}zu", records.size());
383     return records;
384 }
385 
RemoveRecordById(PasteData & pasteData,uint32_t recordId)386 void PasteboardWebController::RemoveRecordById(PasteData &pasteData, uint32_t recordId) noexcept
387 {
388     for (uint32_t i = 0; i < pasteData.GetRecordCount(); i++) {
389         if (pasteData.GetRecordAt(i)->GetRecordId() == recordId) {
390             if (pasteData.RemoveRecordAt(i)) {
391                 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON,
392                     "WebClipboardController RemoveRecord success, i=%{public}u", i);
393                 return;
394             }
395             PASTEBOARD_HILOGW(PASTEBOARD_MODULE_COMMON,
396                               "WebClipboardController RemoveRecord failed, i=%{public}u", i);
397         }
398     }
399 }
400 
RemoveAllRecord(std::shared_ptr<PasteData> pasteData)401 void PasteboardWebController::RemoveAllRecord(std::shared_ptr<PasteData> pasteData) noexcept
402 {
403     PASTEBOARD_CHECK_AND_RETURN_LOGE(pasteData != nullptr, PASTEBOARD_MODULE_COMMON, "pasteData is null");
404     std::size_t recordCount = pasteData->GetRecordCount();
405     for (uint32_t i = 0; i < recordCount; i++) {
406         if (!pasteData->RemoveRecordAt(0)) {
407             PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "WebClipboardController RemoveRecord failed, i=%{public}u", i);
408         }
409     }
410 }
411 
IsLocalURI(std::string & uri)412 bool PasteboardWebController::IsLocalURI(std::string &uri) noexcept
413 {
414     return uri.substr(0, strlen(IMG_LOCAL_URI)) == std::string(IMG_LOCAL_URI) ||
415         uri.find(IMG_LOCAL_PATH) == std::string::npos;
416 }
417 
UpdateHtmlRecord(std::shared_ptr<PasteDataRecord> & htmlRecord,std::shared_ptr<std::string> & htmlData)418 void PasteboardWebController::UpdateHtmlRecord(
419     std::shared_ptr<PasteDataRecord> &htmlRecord, std::shared_ptr<std::string> &htmlData)
420 {
421     if (htmlRecord == nullptr || htmlData == nullptr) {
422         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "htmlRecord or htmlData is null");
423         return;
424     }
425     auto entry = htmlRecord->GetEntryByMimeType(MIMETYPE_TEXT_HTML);
426     if (entry == nullptr) {
427         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_COMMON, "entry is null");
428         return;
429     }
430     auto entryValue = entry->GetValue();
431     if (std::holds_alternative<std::string>(entryValue)) {
432         entry->SetValue(*htmlData);
433     } else if (std::holds_alternative<std::shared_ptr<Object>>(entryValue)) {
434         auto object = std::get<std::shared_ptr<Object>>(entryValue);
435         auto newObject = std::make_shared<Object>();
436         newObject->value_ = object->value_;
437         newObject->value_[UDMF::HTML_CONTENT] = *htmlData;
438         entry->SetValue(newObject);
439     }
440     htmlRecord->AddEntryByMimeType(MIMETYPE_TEXT_HTML, entry);
441     htmlRecord->SetFrom(0);
442 }
443 
ReplaceHtmlRecordContentByExtraUris(std::vector<std::shared_ptr<PasteDataRecord>> & records)444 void PasteboardWebController::ReplaceHtmlRecordContentByExtraUris(
445     std::vector<std::shared_ptr<PasteDataRecord>> &records)
446 {
447     std::shared_ptr<PasteDataRecord> htmlRecord = nullptr;
448     std::shared_ptr<std::string> htmlData;
449     std::map<uint32_t, std::pair<std::string, std::string>, Cmp> replaceUris;
450     for (const auto &item : records) {
451         auto htmlEntry = item->GetEntryByMimeType(MIMETYPE_TEXT_HTML);
452         if (htmlEntry != nullptr) {
453             auto html = htmlEntry->ConvertToHtml();
454             if (html != nullptr && !html->empty()) {
455                 htmlData = html;
456                 htmlRecord = item;
457                 continue;
458             }
459         }
460         std::shared_ptr<OHOS::Uri> uri = item->GetUri();
461         std::shared_ptr<MiscServices::MineCustomData> customData = item->GetCustomData();
462         if (!uri || !customData) {
463             continue;
464         }
465         std::map<std::string, std::vector<uint8_t>> customItemData = customData->GetItemData();
466         for (auto &itemData : customItemData) {
467             for (uint32_t i = 0; i < itemData.second.size(); i += FOUR_BYTES) {
468                 uint32_t offset = static_cast<uint32_t>(itemData.second[i]) |
469                                   static_cast<uint32_t>(itemData.second[i + 1] << 8) |
470                                   static_cast<uint32_t>(itemData.second[i + 2] << 16) |
471                                   static_cast<uint32_t>(itemData.second[i + 3] << 24);
472                 replaceUris[offset] = std::make_pair(uri->ToString(), itemData.first);
473             }
474         }
475     }
476     if (htmlData == nullptr) {
477         PASTEBOARD_HILOGW(PASTEBOARD_MODULE_COMMON, "htmlData is nullptr");
478         return;
479     }
480 
481     for (const auto &replaceUri : replaceUris) {
482         htmlData->replace(replaceUri.first, replaceUri.second.second.size(), replaceUri.second.first);
483     }
484     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "replace uri count: %{public}zu", replaceUris.size());
485     if (htmlRecord != nullptr) {
486         UpdateHtmlRecord(htmlRecord, htmlData);
487     }
488 }
489 
GroupRecordWithFrom(PasteData & data)490 std::map<std::uint32_t, std::vector<std::shared_ptr<PasteDataRecord>>> PasteboardWebController::GroupRecordWithFrom(
491     PasteData &data)
492 {
493     std::map<std::uint32_t, std::vector<std::shared_ptr<PasteDataRecord>>> groupMap;
494     for (const auto &record : data.AllRecords()) {
495         if (record->GetFrom() == 0) {
496             continue;
497         }
498         auto item = groupMap.find(record->GetFrom());
499         auto value = item != groupMap.end() ? item->second : std::vector<std::shared_ptr<PasteDataRecord>>();
500         value.emplace_back(record);
501         groupMap.insert_or_assign(record->GetFrom(), value);
502     }
503     return groupMap;
504 }
505 
RemoveExtraUris(PasteData & data)506 void PasteboardWebController::RemoveExtraUris(PasteData &data)
507 {
508     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "Before remove record count: %{public}zu", data.AllRecords().size());
509     for (const auto &record : data.AllRecords()) {
510         if (record->GetFrom() > 0 && record->GetMimeType() == MIMETYPE_TEXT_URI) {
511             RemoveRecordById(data, record->GetRecordId());
512         }
513     }
514     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_COMMON, "After remove record count: %{public}zu", data.AllRecords().size());
515 }
516 } // namespace MiscServices
517 } // namespace OHOS
518