1 /*
2  * Copyright (c) 2023 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 "form_data_proxy_record.h"
17 
18 #include <cstddef>
19 #include <string>
20 #include <vector>
21 
22 #include "fms_log_wrapper.h"
23 #include "form_bms_helper.h"
24 #include "form_data_mgr.h"
25 #include "form_mgr_adapter.h"
26 #include "form_mgr_errors.h"
27 #include "form_provider_mgr.h"
28 #include "form_util.h"
29 #include "ipc_skeleton.h"
30 #include "accesstoken_kit.h"
31 #include "form_event_report.h"
32 
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace {
36 const std::string KEY_DELIMITER = "?"; // the delimiter between key and uid
37 } // namespace
38 
39 class PermissionCustomizeListener : public Security::AccessToken::PermStateChangeCallbackCustomize {
40     public:
41         std::weak_ptr<FormDataProxyRecord> formDataProxyRecord_;
PermissionCustomizeListener(const Security::AccessToken::PermStateChangeScope & scopeInfo,std::weak_ptr<FormDataProxyRecord> formDataProxyRecord)42         PermissionCustomizeListener(const Security::AccessToken::PermStateChangeScope &scopeInfo,
43             std::weak_ptr<FormDataProxyRecord> formDataProxyRecord)
44             : Security::AccessToken::PermStateChangeCallbackCustomize(scopeInfo)
45         {
46             formDataProxyRecord_ = formDataProxyRecord;
47         }
48 
PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo & result)49         virtual void PermStateChangeCallback(Security::AccessToken::PermStateChangeInfo& result)
50         {
51             HILOG_INFO("PermStateChangeCallback type:%{public}d, permissionName:%{public}s",
52                 result.permStateChangeType, result.permissionName.c_str());
53             auto formDataProxyRecord = formDataProxyRecord_.lock();
54             if (formDataProxyRecord == nullptr) {
55                 HILOG_INFO("formDataPrxyRecord is nullptr");
56                 return;
57             }
58             formDataProxyRecord->PermStateChangeCallback(result.permStateChangeType, result.permissionName);
59         }
60 };
61 
PermStateChangeCallback(const int32_t permStateChangeType,const std::string permissionName)62 void FormDataProxyRecord::PermStateChangeCallback(const int32_t permStateChangeType, const std::string permissionName)
63 {
64     HILOG_DEBUG("Permission has been changed, form id:%{public}" PRId64 ", permission name:%{public}s", formId_,
65         permissionName.c_str());
66     auto search = formDataPermissionProxyMap_.find(permissionName);
67     if (search == formDataPermissionProxyMap_.end()) {
68         HILOG_ERROR("no permission data proxy, permissionName :%{public}s", permissionName.c_str());
69         return;
70     }
71     std::vector<FormDataProxy> formDataProxies = search->second;
72     std::vector<FormDataProxy> subscribeFormDataProxies;
73     std::vector<FormDataProxy> unSubscribeFormDataProxies;
74     for (const auto &formDataProxy : formDataProxies) {
75         GetSubscribeFormDataProxies(formDataProxy, subscribeFormDataProxies, unSubscribeFormDataProxies);
76     }
77 
78     bool isAuthorized = permStateChangeType == PERMISSION_GRANTED_OPER;
79     SubscribeMap rdbSubscribeMap;
80     SubscribeMap publishSubscribeMap;
81     if (isAuthorized) {
82         if (!subscribeFormDataProxies.empty()) {
83             SubscribeFormData(subscribeFormDataProxies, rdbSubscribeMap, publishSubscribeMap);
84         }
85     } else {
86         if (!unSubscribeFormDataProxies.empty()) {
87             ParseFormDataProxies(unSubscribeFormDataProxies, rdbSubscribeMap, publishSubscribeMap);
88             UnsubscribeFormData(rdbSubscribeMap, publishSubscribeMap);
89         }
90     }
91     Want newWant(wantCache_);
92     newWant.SetParam(Constants::FORM_PERMISSION_NAME_KEY, permissionName);
93     newWant.SetParam(Constants::FORM_PERMISSION_GRANTED_KEY, isAuthorized);
94     if (FormProviderMgr::GetInstance().ConnectAmsForRefreshPermission(formId_, newWant) != ERR_OK) {
95         HILOG_ERROR(
96             "ConnectAmsForRefreshPermission failed, permission name:%{public}s, isAuthorized:%{public}d",
97             permissionName.c_str(), isAuthorized);
98         return;
99     }
100 }
101 
SetWant(const AAFwk::Want & want)102 void FormDataProxyRecord::SetWant(const AAFwk::Want &want)
103 {
104     wantCache_ = want;
105 }
106 
GetSubscribeFormDataProxies(const FormDataProxy formDataProxy,std::vector<FormDataProxy> & subscribeFormDataProxies,std::vector<FormDataProxy> & unSubscribeFormDataProxies)107 void FormDataProxyRecord::GetSubscribeFormDataProxies(const FormDataProxy formDataProxy,
108     std::vector<FormDataProxy> &subscribeFormDataProxies, std::vector<FormDataProxy> &unSubscribeFormDataProxies)
109 {
110     std::string userId = std::to_string(FormUtil::GetCurrentAccountId());
111     std::string token = std::to_string(tokenId_);
112     std::string uri = formDataProxy.key + "?" + "user=" + userId + "&srcToken=" + token +
113         "&dstBundleName=" + bundleName_;
114     auto rdbSubscribeResult = rdbSubscribeResultMap_.find(uri);
115     if (rdbSubscribeResult != rdbSubscribeResultMap_.end()) {
116         int64_t subscriberId = formId_;
117         if (!FormUtil::ConvertStringToInt64(formDataProxy.subscribeId, subscriberId)) {
118             HILOG_WARN("Convert string subscribe[%{public}s] to int64 failed, change to default value "
119                 "formId[%{public}s].", formDataProxy.subscribeId.c_str(), std::to_string(formId_).c_str());
120         }
121         auto subscribeResultRecord = rdbSubscribeResult->second.find(subscriberId);
122         if (subscribeResultRecord != rdbSubscribeResult->second.end()) {
123             if (subscribeResultRecord->second.ret != 0) {
124                 subscribeFormDataProxies.emplace_back(formDataProxy);
125             } else {
126                 unSubscribeFormDataProxies.emplace_back(formDataProxy);
127             }
128         }
129     } else {
130         subscribeFormDataProxies.emplace_back(formDataProxy);
131     }
132 }
133 
UnRegisterPermissionListener()134 void FormDataProxyRecord::UnRegisterPermissionListener()
135 {
136     if (callbackPtr_ != nullptr) {
137         int32_t accessTokenKit = Security::AccessToken::AccessTokenKit::UnRegisterPermStateChangeCallback(callbackPtr_);
138         callbackPtr_ = nullptr;
139     }
140 }
141 
RegisterPermissionListener(const std::vector<FormDataProxy> & formDataProxies)142 void FormDataProxyRecord::RegisterPermissionListener(const std::vector<FormDataProxy> &formDataProxies)
143 {
144     std::vector<ProxyData> proxyData;
145     std::vector<std::string> permList;
146     FormBmsHelper::GetInstance().GetAllProxyDataInfos(FormUtil::GetCurrentAccountId(), proxyData);
147     if (proxyData.empty() || !formDataPermissionProxyMap_.empty()) {
148         return;
149     }
150     for (const auto &formDataProxy : formDataProxies) {
151         for (const auto &data : proxyData) {
152             if (formDataProxy.key != data.uri) {
153                 continue;
154             }
155             auto search = formDataPermissionProxyMap_.find(data.requiredReadPermission);
156             std::vector<FormDataProxy> proxies;
157             if (search != formDataPermissionProxyMap_.end()) {
158                 proxies = search->second;
159             }
160             permList.emplace_back(data.requiredReadPermission);
161             proxies.emplace_back(formDataProxy);
162             formDataPermissionProxyMap_[data.requiredReadPermission] = proxies;
163             break;
164         }
165     }
166     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
167     Security::AccessToken::PermStateChangeScope scopeInfo;
168     scopeInfo.permList = {permList};
169     scopeInfo.tokenIDs = {tokenId_};
170     callbackPtr_ = std::make_shared<PermissionCustomizeListener>(scopeInfo, weak_from_this());
171     int32_t accessTokenKit = Security::AccessToken::AccessTokenKit::RegisterPermStateChangeCallback(callbackPtr_);
172     IPCSkeleton::SetCallingIdentity(callingIdentity);
173     HILOG_INFO("formId:%{public}s", std::to_string(formId_).c_str());
174     if (accessTokenKit != 0) {
175         formDataPermissionProxyMap_.clear();
176     }
177 }
178 
179 
OnRdbDataChange(const DataShare::RdbChangeNode & changeNode)180 void FormDataProxyRecord::OnRdbDataChange(const DataShare::RdbChangeNode &changeNode)
181 {
182     HILOG_INFO("rdb change. data size is %{public}zu", changeNode.data_.size());
183     if (changeNode.data_.size() == 0) {
184         return;
185     }
186     UpdateRdbDataForm(changeNode.data_);
187 }
188 
OnPublishedDataChange(const DataShare::PublishedDataChangeNode & changeNode)189 void FormDataProxyRecord::OnPublishedDataChange(const DataShare::PublishedDataChangeNode &changeNode)
190 {
191     HILOG_DEBUG("on published data change. data size is %{public}zu", changeNode.datas_.size());
192     UpdatePublishedDataForm(changeNode.datas_);
193 }
194 
FormDataProxyRecord(int64_t formId,const std::string & bundleName,FormType uiSyntax,uint32_t tokenId,int32_t uid)195 FormDataProxyRecord::FormDataProxyRecord(int64_t formId, const std::string &bundleName, FormType uiSyntax,
196     uint32_t tokenId, int32_t uid) : formId_(formId), bundleName_(bundleName), uiSyntax_(uiSyntax),
197     tokenId_(tokenId), uid_(uid)
198 {
199     HILOG_INFO("create formId:%{public}s, bundleName:%{public}s",
200         std::to_string(formId).c_str(), bundleName.c_str());
201     std::string uri = "datashareproxy://" + bundleName;
202     DataShare::CreateOptions options;
203     options.isProxy_ = true;
204     dataShareHelper_ = DataShare::DataShareHelper::Creator(uri, options);
205 }
206 
~FormDataProxyRecord()207 FormDataProxyRecord::~FormDataProxyRecord()
208 {
209     HILOG_INFO("destroy formId:%{public}s, bundleName:%{public}s",
210         std::to_string(formId_).c_str(), bundleName_.c_str());
211     UnRegisterPermissionListener();
212     if (dataShareHelper_ != nullptr) {
213         dataShareHelper_->Release();
214     }
215 }
216 
SubscribeFormData(const std::vector<FormDataProxy> & formDataProxies)217 ErrCode FormDataProxyRecord::SubscribeFormData(const std::vector<FormDataProxy> &formDataProxies)
218 {
219     RegisterPermissionListener(formDataProxies);
220     return SubscribeFormData(formDataProxies, rdbSubscribeMap_, publishSubscribeMap_);
221 }
222 
SubscribeFormData(const std::vector<FormDataProxy> & formDataProxies,SubscribeMap & rdbSubscribeMap,SubscribeMap & publishSubscribeMap)223 ErrCode FormDataProxyRecord::SubscribeFormData(const std::vector<FormDataProxy> &formDataProxies,
224     SubscribeMap &rdbSubscribeMap, SubscribeMap &publishSubscribeMap)
225 {
226     HILOG_INFO("subscribe form data, formDataProxies size:%{public}zu", formDataProxies.size());
227     ParseFormDataProxies(formDataProxies, rdbSubscribeMap, publishSubscribeMap);
228     ErrCode ret = ERR_OK;
229     ret = SubscribeRdbFormData(rdbSubscribeMap);
230     if (ret != ERR_OK) {
231         HILOG_ERROR("subscribe rdb form data failed");
232         return ret;
233     }
234     ret = SubscribePublishFormData(publishSubscribeMap);
235     if (ret != ERR_OK) {
236         HILOG_ERROR("subscribe publish form data failed");
237         return ret;
238     }
239     return ret;
240 }
241 
SubscribeRdbFormData(const SubscribeMap & rdbSubscribeMap)242 ErrCode FormDataProxyRecord::SubscribeRdbFormData(const SubscribeMap &rdbSubscribeMap)
243 {
244     HILOG_INFO("SubscribeRdbFormData");
245     if (dataShareHelper_ == nullptr) {
246         HILOG_ERROR("null dataShareHelper");
247         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
248     }
249 
250     if (rdbSubscribeMap.empty()) {
251         HILOG_ERROR("empty rdbSubscribeMap");
252         return ERR_OK;
253     }
254 
255     std::vector<FormDataProxyRequest> formDataProxyRequests;
256     ConvertSubscribeMapToRequests(rdbSubscribeMap, formDataProxyRequests);
257 
258     std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
259     auto rdbTask = [weak](const DataShare::RdbChangeNode &changeNode) {
260         auto formDataRecord = weak.lock();
261         if (formDataRecord == nullptr) {
262             HILOG_ERROR("null formDataRecord");
263             return;
264         }
265         formDataRecord->OnRdbDataChange(changeNode);
266     };
267     for (const auto &search : formDataProxyRequests) {
268         DataShare::TemplateId templateId;
269         templateId.subscriberId_ = search.subscribeId;
270         templateId.bundleName_ = bundleName_;
271         auto ret = dataShareHelper_->SubscribeRdbData(search.uris, templateId, rdbTask);
272         uint32_t failNum = 0;
273         for (const auto &iter : ret) {
274             SubscribeResultRecord record{iter.key_, search.subscribeId, iter.errCode_, false, 0};
275             AddSubscribeResultRecord(record, true);
276             if (iter.errCode_ != 0) {
277                 HILOG_ERROR("subscribe rdb data failed. uri:%{public}s, errCode:%{public}d",
278                     iter.key_.c_str(), iter.errCode_);
279                 failNum++;
280             }
281         }
282         HILOG_DEBUG("subscribe rdb data. subscribeId:%{public}s, failNum:%{public}d, totalNum:%{public}zu",
283             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
284     }
285 
286     return ERR_OK;
287 }
288 
SubscribePublishFormData(const SubscribeMap & publishSubscribeMap)289 ErrCode FormDataProxyRecord::SubscribePublishFormData(const SubscribeMap &publishSubscribeMap)
290 {
291     HILOG_INFO("SubscribePublishFormData");
292     if (dataShareHelper_ == nullptr) {
293         HILOG_ERROR("null dataShareHelper");
294         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
295     }
296 
297     if (publishSubscribeMap.empty()) {
298         HILOG_ERROR("null publishSubscribeMap");
299         return ERR_OK;
300     }
301 
302     std::vector<FormDataProxyRequest> formDataProxyRequests;
303     ConvertSubscribeMapToRequests(publishSubscribeMap, formDataProxyRequests);
304 
305     std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
306     auto publishedTask = [weak](const DataShare::PublishedDataChangeNode &changeNode) {
307         auto formDataRecord = weak.lock();
308         if (formDataRecord == nullptr) {
309             HILOG_ERROR("null formDataRecord");
310             return;
311         }
312         formDataRecord->OnPublishedDataChange(changeNode);
313     };
314     for (const auto &search : formDataProxyRequests) {
315         auto ret = dataShareHelper_->SubscribePublishedData(search.uris, search.subscribeId, publishedTask);
316         uint32_t failNum = 0;
317         for (const auto &iter : ret) {
318             SubscribeResultRecord record{iter.key_, search.subscribeId, iter.errCode_, false, 0};
319             AddSubscribeResultRecord(record, false);
320             if (iter.errCode_ != 0) {
321                 HILOG_ERROR("subscribe published data failed. uri:%{public}s, errCode:%{public}d",
322                     iter.key_.c_str(), iter.errCode_);
323                 failNum++;
324             }
325         }
326         HILOG_DEBUG("subscribe published data. subscribeId:%{public}s, failNum:%{public}d, totalNum:%{public}zu",
327             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
328     }
329 
330     return ERR_OK;
331 }
332 
UnsubscribeFormData()333 ErrCode FormDataProxyRecord::UnsubscribeFormData()
334 {
335     return UnsubscribeFormData(rdbSubscribeMap_, publishSubscribeMap_);
336 }
337 
UnsubscribeFormData(SubscribeMap & rdbSubscribeMap,SubscribeMap & publishSubscribeMap)338 ErrCode FormDataProxyRecord::UnsubscribeFormData(SubscribeMap &rdbSubscribeMap, SubscribeMap &publishSubscribeMap)
339 {
340     if (dataShareHelper_ == nullptr) {
341         HILOG_ERROR("null dataShareHelper");
342         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
343     }
344 
345     std::vector<FormDataProxyRequest> rdbRequests;
346     ConvertSubscribeMapToRequests(rdbSubscribeMap, rdbRequests);
347     for (const auto &search : rdbRequests) {
348         DataShare::TemplateId templateId;
349         templateId.subscriberId_ = search.subscribeId;
350         templateId.bundleName_ = bundleName_;
351         dataShareHelper_->UnsubscribeRdbData(search.uris, templateId);
352         for (const auto &uri : search.uris) {
353             RemoveSubscribeResultRecord(uri, search.subscribeId, true);
354         }
355     }
356     rdbSubscribeMap.clear();
357 
358     std::vector<FormDataProxyRequest> publishRequests;
359     ConvertSubscribeMapToRequests(publishSubscribeMap, publishRequests);
360     for (const auto &search : publishRequests) {
361         dataShareHelper_->UnsubscribePublishedData(search.uris, search.subscribeId);
362         for (const auto &uri : search.uris) {
363             RemoveSubscribeResultRecord(uri, search.subscribeId, false);
364         }
365     }
366     publishSubscribeMap.clear();
367     return ERR_OK;
368 }
369 
ParseFormDataProxies(const std::vector<FormDataProxy> & formDataProxies,SubscribeMap & rdbSubscribeMap,SubscribeMap & publishSubscribeMap)370 void FormDataProxyRecord::ParseFormDataProxies(const std::vector<FormDataProxy> &formDataProxies,
371     SubscribeMap &rdbSubscribeMap, SubscribeMap &publishSubscribeMap)
372 {
373     std::vector<ProxyData> proxyData;
374     FormBmsHelper::GetInstance().GetAllProxyDataInfos(FormUtil::GetCurrentAccountId(), proxyData);
375     HILOG_INFO("size:%{public}zu", proxyData.size());
376     for (size_t i = 0; i < proxyData.size(); ++i) {
377         HILOG_INFO("proxyData[%{public}zu].uri:%{public}s", i, proxyData[i].uri.c_str());
378     }
379 
380     std::unordered_set<std::string> expectedKeys;
381     for (auto &data : proxyData) {
382         expectedKeys.emplace(data.uri);
383     }
384 
385     HILOG_INFO("subscribe rdb data");
386     ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(formDataProxies, expectedKeys, true, rdbSubscribeMap);
387     HILOG_INFO("subscribe publish data");
388     ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(formDataProxies, expectedKeys, false, publishSubscribeMap);
389 }
390 
ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(const std::vector<FormDataProxy> & formDataProxies,const std::unordered_set<std::string> & expectedKeys,bool keyCheckingNeeded,SubscribeMap & subscribeMap)391 void FormDataProxyRecord::ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(
392     const std::vector<FormDataProxy> &formDataProxies, const std::unordered_set<std::string> &expectedKeys,
393     bool keyCheckingNeeded, SubscribeMap &subscribeMap)
394 {
395     subscribeMap.clear();
396     for (const auto &formDataProxy : formDataProxies) {
397         if (keyCheckingNeeded && expectedKeys.find(formDataProxy.key) == expectedKeys.end()) {
398             continue;
399         }
400         auto subscribe = formDataProxy.subscribeId.empty() ? std::to_string(formId_) : formDataProxy.subscribeId;
401         auto it = subscribeMap.find(formDataProxy.key);
402         if (it == subscribeMap.end()) {
403             std::unordered_set<std::string> subscribeIds;
404             subscribeIds.emplace(subscribe);
405             subscribeMap.emplace(formDataProxy.key, subscribeIds);
406         } else {
407             it->second.emplace(subscribe);
408         }
409         HILOG_INFO("parse subscribe, key:%{public}s, subscribeId:%{public}s",
410             formDataProxy.key.c_str(), subscribe.c_str());
411     }
412 }
413 
ConvertSubscribeMapToRequests(const SubscribeMap & subscribeMap,std::vector<FormDataProxyRequest> & formDataProxyRequests)414 void FormDataProxyRecord::ConvertSubscribeMapToRequests(
415     const SubscribeMap &subscribeMap, std::vector<FormDataProxyRequest> &formDataProxyRequests)
416 {
417     formDataProxyRequests.clear();
418     std::string userId = std::to_string(FormUtil::GetCurrentAccountId());
419     std::string token = std::to_string(tokenId_);
420     std::unordered_map<int64_t, std::vector<std::string>> subscribeId2UrisMap;
421 
422     for (const auto &record : subscribeMap) {
423         const auto &key = record.first;
424         for (const auto &subscribe : record.second) {
425             int64_t subscriberId = formId_;
426             if (!FormUtil::ConvertStringToInt64(subscribe, subscriberId)) {
427                 HILOG_WARN("Convert string subscribe[%{public}s] to int64 failed, change to default value "
428                     "formId[%{public}s].", subscribe.c_str(), std::to_string(formId_).c_str());
429             }
430 
431             std::string uri = key + "?" + "user=" + userId + "&srcToken=" + token + "&dstBundleName=" + bundleName_;
432             auto it = subscribeId2UrisMap.find(subscriberId);
433             if (it == subscribeId2UrisMap.end()) {
434                 std::vector<std::string> uris;
435                 uris.push_back(uri);
436                 subscribeId2UrisMap.emplace(subscriberId, uris);
437             } else {
438                 it->second.push_back(uri);
439             }
440         }
441     }
442 
443     for (auto &record : subscribeId2UrisMap) {
444         FormDataProxyRequest request{record.first, std::move(record.second)};
445         formDataProxyRequests.push_back(request);
446     }
447 }
448 
UpdatePublishedDataForm(const std::vector<DataShare::PublishedDataItem> & data)449 void FormDataProxyRecord::UpdatePublishedDataForm(const std::vector<DataShare::PublishedDataItem> &data)
450 {
451     std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> imageDataMap;
452     nlohmann::json object;
453     std::string formDataKeysStr = "";
454     for (const auto& iter : data) {
455         if (iter.key_.empty()) {
456             HILOG_ERROR("empty key");
457             continue;
458         }
459         if (iter.IsAshmem()) {
460             PrepareImageData(iter, object, imageDataMap);
461         } else {
462             auto value = std::get<std::string>(iter.value_);
463             nlohmann::json dataObject = nlohmann::json::parse(value, nullptr, false);
464             if (dataObject.is_discarded()) {
465                 HILOG_ERROR("fail parse data:%{public}s", value.c_str());
466                 continue;
467             }
468             object[iter.key_] = dataObject;
469             std::string newKeyStr = formDataKeysStr.empty() ? iter.key_ : (", " + iter.key_);
470             formDataKeysStr += newKeyStr;
471         }
472     }
473     std::string formDataStr = object.empty() ? "" : object.dump();
474     std::string subStr = formDataStr.substr(0, std::min((int)formDataStr.length(), 30));
475     HILOG_INFO("[formId:%{public}s] update published data. formDataStr[len:%{public}zu]: %{private}s, "
476         "formDataKeysStr:%{public}s, imageDataMap size:%{public}zu", std::to_string(formId_).c_str(),
477         formDataStr.length(), subStr.c_str(), formDataKeysStr.c_str(), imageDataMap.size());
478 
479     FormProviderData formProviderData;
480     formProviderData.SetDataString(formDataStr);
481     if (!imageDataMap.empty()) {
482         formProviderData.SetImageDataState(FormProviderData::IMAGE_DATA_STATE_ADDED);
483         formProviderData.SetImageDataMap(imageDataMap);
484     }
485     auto ret = FormMgrAdapter::GetInstance().UpdateForm(formId_, uid_, formProviderData);
486     NewFormEventInfo eventInfo;
487     eventInfo.formId = formId_;
488     eventInfo.bundleName = bundleName_;
489     FormEventReport::SendFourthFormEvent(FormEventName::PROXY_UPDATE_FORM,
490         HiSysEventType::STATISTIC, eventInfo, wantCache_);
491     if (ret == ERR_OK && receivedDataCount_ < INT32_MAX) {
492         receivedDataCount_ += 1;
493     }
494 }
495 
UpdateRdbDataForm(const std::vector<std::string> & data)496 void FormDataProxyRecord::UpdateRdbDataForm(const std::vector<std::string> &data)
497 {
498     nlohmann::json object;
499     for (const auto& iter : data) {
500         HILOG_DEBUG("iter: %{private}s.", iter.c_str());
501         nlohmann::json dataObject = nlohmann::json::parse(iter, nullptr, false);
502         if (dataObject.is_discarded()) {
503             HILOG_ERROR("fail parse data:%{public}s", iter.c_str());
504             continue;
505         }
506         object.merge_patch(dataObject);
507     }
508 
509     std::string formDataStr = object.empty() ? "" : object.dump();
510     std::string subStr = formDataStr.substr(0, std::min((int)formDataStr.size(), 30));
511     HILOG_INFO("[formId:%{public}s] update rdb data. formDataStr[len:%{public}zu]: %{private}s.",
512         std::to_string(formId_).c_str(), formDataStr.length(), subStr.c_str());
513 
514     FormProviderData formProviderData;
515     formProviderData.SetDataString(formDataStr);
516     auto ret = FormMgrAdapter::GetInstance().UpdateForm(formId_, uid_, formProviderData);
517     if (ret == ERR_OK && receivedDataCount_ < INT32_MAX) {
518         receivedDataCount_ += 1;
519     }
520 }
521 
UpdateSubscribeFormData(const std::vector<FormDataProxy> & formDataProxies)522 void FormDataProxyRecord::UpdateSubscribeFormData(const std::vector<FormDataProxy> &formDataProxies)
523 {
524     HILOG_INFO("call");
525     SubscribeMap originRdbMap;
526     SubscribeMap newRdbMap;
527     SubscribeMap originPublishMap;
528     SubscribeMap newPublishMap;
529     UpdateSubscribeMap(formDataProxies, originRdbMap, newRdbMap, originPublishMap, newPublishMap);
530     UnsubscribeFormData(originRdbMap, originPublishMap);
531     SubscribeRdbFormData(newRdbMap);
532     SubscribePublishFormData(newPublishMap);
533 }
534 
UpdateSubscribeMap(const std::vector<FormDataProxy> & formDataProxies,SubscribeMap & originRdbMap,SubscribeMap & newRdbMap,SubscribeMap & originPublishMap,SubscribeMap & newPublishMap)535 void FormDataProxyRecord::UpdateSubscribeMap(const std::vector<FormDataProxy> &formDataProxies,
536     SubscribeMap &originRdbMap, SubscribeMap &newRdbMap, SubscribeMap &originPublishMap, SubscribeMap &newPublishMap)
537 {
538     SubscribeMap updateMap;
539     std::unordered_set<std::string> expectedKeys;
540     ParseFormDataProxiesIntoSubscribeMapWithExpectedKeys(formDataProxies, expectedKeys, false, updateMap);
541     for (const auto &record : updateMap) {
542         const auto &key = record.first;
543         const auto &newSubscribeIds = record.second;
544         auto it = rdbSubscribeMap_.find(key);
545         if (it != rdbSubscribeMap_.end()) {
546             originRdbMap[key] = it->second;
547             newRdbMap[key] = newSubscribeIds;
548             rdbSubscribeMap_[key] = newSubscribeIds;
549         }
550         it = publishSubscribeMap_.find(key);
551         if (it != publishSubscribeMap_.end()) {
552             originPublishMap[key] = it->second;
553             newPublishMap[key] = newSubscribeIds;
554             publishSubscribeMap_[key] = newSubscribeIds;
555         }
556     }
557 }
558 
EnableSubscribeFormData()559 void FormDataProxyRecord::EnableSubscribeFormData()
560 {
561     HILOG_INFO("enable subscribe form, formId:%{public}s, rdbSize:%{public}zu, publishSize:%{public}zu",
562         std::to_string(formId_).c_str(), rdbSubscribeMap_.size(), publishSubscribeMap_.size());
563     SetRdbSubsState(rdbSubscribeMap_, true);
564     SetPublishSubsState(publishSubscribeMap_, true);
565 }
566 
DisableSubscribeFormData()567 void FormDataProxyRecord::DisableSubscribeFormData()
568 {
569     HILOG_DEBUG("disable subscribe form, formId:%{public}s", std::to_string(formId_).c_str());
570     SetRdbSubsState(rdbSubscribeMap_, false);
571     SetPublishSubsState(publishSubscribeMap_, false);
572 }
573 
RetryFailureSubscribes()574 void FormDataProxyRecord::RetryFailureSubscribes()
575 {
576     HILOG_INFO("formId:%{public}s", std::to_string(formId_).c_str());
577     if (dataShareHelper_ == nullptr) {
578         HILOG_ERROR("null dataShareHelper");
579         return;
580     }
581 
582     for (auto& result : rdbSubscribeResultMap_) {
583         for (auto& records : result.second) {
584             auto& record = records.second;
585             RetryFailureRdbSubscribes(record);
586         }
587     }
588 
589     for (auto& result : publishSubscribeResultMap_) {
590         for (auto& records : result.second) {
591             auto& record = records.second;
592             RetryFailurePublishedSubscribes(record);
593         }
594     }
595 }
596 
GetFormSubscribeInfo(std::vector<std::string> & subscribedKeys,int32_t & count)597 void FormDataProxyRecord::GetFormSubscribeInfo(std::vector<std::string> &subscribedKeys, int32_t &count)
598 {
599     GetFormSubscribeKeys(subscribedKeys, true);
600     GetFormSubscribeKeys(subscribedKeys, false);
601     count = receivedDataCount_;
602 }
603 
SetRdbSubsState(const SubscribeMap & rdbSubscribeMap,bool subsState)604 ErrCode FormDataProxyRecord::SetRdbSubsState(const SubscribeMap &rdbSubscribeMap, bool subsState)
605 {
606     if (dataShareHelper_ == nullptr) {
607         HILOG_ERROR("null dataShareHelper");
608         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
609     }
610 
611     if (rdbSubscribeMap.empty()) {
612         HILOG_DEBUG("empty rdbSubscribeMap");
613         return ERR_OK;
614     }
615 
616     std::vector<FormDataProxyRequest> formDataProxyRequests;
617     ConvertSubscribeMapToRequests(rdbSubscribeMap, formDataProxyRequests);
618 
619     for (const auto &search : formDataProxyRequests) {
620         DataShare::TemplateId templateId;
621         templateId.subscriberId_ = search.subscribeId;
622         templateId.bundleName_ = bundleName_;
623         std::vector<DataShare::OperationResult> ret;
624         if (subsState) {
625             ret = dataShareHelper_->EnableRdbSubs(search.uris, templateId);
626         } else {
627             ret = dataShareHelper_->DisableRdbSubs(search.uris, templateId);
628         }
629         uint32_t failNum = 0;
630         for (const auto &iter : ret) {
631             if (iter.errCode_ != 0) {
632                 PrintSubscribeState(iter.key_, search.subscribeId, true);
633                 failNum++;
634             }
635         }
636         HILOG_DEBUG("set rdb state. subscribeId:%{public}s, failNum:%{public}d, totalNum:%{public}zu",
637             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
638     }
639 
640     return ERR_OK;
641 }
642 
SetPublishSubsState(const SubscribeMap & publishSubscribeMap,bool subsState)643 ErrCode FormDataProxyRecord::SetPublishSubsState(const SubscribeMap &publishSubscribeMap,
644     bool subsState)
645 {
646     if (dataShareHelper_ == nullptr) {
647         HILOG_ERROR("null dataShareHelper");
648         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
649     }
650 
651     if (publishSubscribeMap.empty()) {
652         HILOG_DEBUG("null publishSubscribeMap");
653         return ERR_OK;
654     }
655 
656     std::vector<FormDataProxyRequest> formDataProxyRequests;
657     ConvertSubscribeMapToRequests(publishSubscribeMap, formDataProxyRequests);
658 
659     for (const auto &search : formDataProxyRequests) {
660         std::vector<DataShare::OperationResult> ret;
661         if (subsState) {
662             ret = dataShareHelper_->EnablePubSubs(search.uris, search.subscribeId);
663         } else {
664             ret = dataShareHelper_->DisablePubSubs(search.uris, search.subscribeId);
665         }
666         uint32_t failNum = 0;
667         for (const auto &iter : ret) {
668             if (iter.errCode_ != 0) {
669                 PrintSubscribeState(iter.key_, search.subscribeId, false);
670                 failNum++;
671             }
672         }
673         HILOG_DEBUG("set published state. subscribeId:%{public}s, failNum:%{public}d, totalNum:%{public}zu",
674             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
675     }
676 
677     return ERR_OK;
678 }
679 
680 /*
681  * we need to automatically produce image names due to differences in usage between image publishing and rendering
682  */
PrepareImageData(const DataShare::PublishedDataItem & data,nlohmann::json & jsonObj,std::map<std::string,std::pair<sptr<FormAshmem>,int32_t>> & imageDataMap)683 bool FormDataProxyRecord::PrepareImageData(const DataShare::PublishedDataItem &data, nlohmann::json &jsonObj,
684     std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> &imageDataMap)
685 {
686     auto node = std::get<DataShare::AshmemNode>(data.value_);
687     if (node.ashmem == nullptr) {
688         HILOG_ERROR("null node.ashmem");
689         return false;
690     }
691     sptr<FormAshmem> formAshmem = new (std::nothrow) FormAshmem();
692     if (formAshmem == nullptr) {
693         HILOG_ERROR("alloc shmem failed");
694         return false;
695     }
696     auto size = node.ashmem->GetAshmemSize();
697     auto imageName = data.key_ + std::to_string(FormUtil::GetCurrentNanosecond());
698     if (!formAshmem->WriteToAshmem(imageName, (char *)node.ashmem->ReadFromAshmem(size, 0), size)) {
699         HILOG_ERROR("write to shmem failed");
700         return false;
701     }
702 
703     jsonObj[data.key_] = imageName;
704     if (uiSyntax_ == FormType::JS) {
705         jsonObj[data.key_] = "memory://" + imageName; // adapt memory image uri for js card
706     }
707 
708     std::pair<sptr<FormAshmem>, int32_t> imageDataRecord = std::make_pair(formAshmem, sizeof(formAshmem));
709     imageDataMap[imageName] = imageDataRecord;
710     return true;
711 }
712 
AddSubscribeResultRecord(SubscribeResultRecord record,bool isRdbType)713 void FormDataProxyRecord::AddSubscribeResultRecord(SubscribeResultRecord record, bool isRdbType)
714 {
715     std::map<std::string, std::map<int64_t, SubscribeResultRecord>>* resultMap =
716         isRdbType ? &rdbSubscribeResultMap_ : &publishSubscribeResultMap_;
717     auto mapIter = resultMap->find(record.uri);
718     if (mapIter == resultMap->end()) {
719         std::map<int64_t, SubscribeResultRecord> records;
720         records.emplace(record.subscribeId, record);
721         resultMap->emplace(record.uri, records);
722     } else {
723         mapIter->second[record.subscribeId] = record;
724     }
725 }
726 
RemoveSubscribeResultRecord(const std::string & uri,int64_t subscribeId,bool isRdbType)727 void FormDataProxyRecord::RemoveSubscribeResultRecord(const std::string &uri, int64_t subscribeId, bool isRdbType)
728 {
729     std::map<std::string, std::map<int64_t, SubscribeResultRecord>>* resultMap =
730         isRdbType ? &rdbSubscribeResultMap_ : &publishSubscribeResultMap_;
731     auto mapIter = resultMap->find(uri);
732     if (mapIter == resultMap->end()) {
733         return;
734     }
735     auto it = mapIter->second.find(subscribeId);
736     if (it != mapIter->second.end()) {
737         mapIter->second.erase(it);
738     }
739     if (mapIter->second.empty()) {
740         resultMap->erase(mapIter);
741     }
742 }
743 
PrintSubscribeState(const std::string & uri,int64_t subscribeId,bool isRdbType)744 void FormDataProxyRecord::PrintSubscribeState(const std::string &uri, int64_t subscribeId, bool isRdbType)
745 {
746     std::string type = isRdbType ? "rdb" : "published";
747     std::map<std::string, std::map<int64_t, SubscribeResultRecord>>* resultMap =
748         isRdbType ? &rdbSubscribeResultMap_ : &publishSubscribeResultMap_;
749     bool alreadySubscribed = true;
750     auto mapIter = resultMap->find(uri);
751     if (mapIter == resultMap->end()) {
752         alreadySubscribed = false;
753     } else {
754         auto it = mapIter->second.find(subscribeId);
755         if (it == mapIter->second.end()) {
756             alreadySubscribed = false;
757         } else {
758             HILOG_ERROR("subscribe state, type:%{public}s, uri:%{public}s, subscriberId:%{public}s, "
759                 "ret:%{public}d, retry:%{public}s, retryRet:%{public}d", type.c_str(), uri.c_str(),
760                 std::to_string(subscribeId).c_str(), it->second.ret, (it->second.retry ? "yes" : "no"),
761                 it->second.retryRet);
762         }
763     }
764     if (!alreadySubscribed) {
765         HILOG_ERROR("fail find subscribe record, type:%{public}s uri:%{public}s, subscriberId:%{public}s",
766             type.c_str(), uri.c_str(), std::to_string(subscribeId).c_str());
767     }
768 }
769 
RetryFailureRdbSubscribes(SubscribeResultRecord & record)770 void FormDataProxyRecord::RetryFailureRdbSubscribes(SubscribeResultRecord &record)
771 {
772     // ok or already retry
773     if (record.ret == 0 || record.retry) {
774         return;
775     }
776 
777     std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
778     auto rdbTask = [weak](const DataShare::RdbChangeNode &changeNode) {
779         auto formDataRecord = weak.lock();
780         if (formDataRecord == nullptr) {
781             HILOG_ERROR("null formDataRecord");
782             return;
783         }
784         formDataRecord->OnRdbDataChange(changeNode);
785     };
786 
787     record.retry = true;
788     std::vector<std::string> uris{record.uri};
789     DataShare::TemplateId templateId;
790     templateId.subscriberId_ = record.subscribeId;
791     templateId.bundleName_ = bundleName_;
792     auto ret = dataShareHelper_->SubscribeRdbData(uris, templateId, rdbTask);
793     for (const auto &iter : ret) {
794         if (iter.errCode_ != 0) {
795             HILOG_ERROR("retry subscribe rdb data failed, uri:%{public}s, subscriberId:%{public}s, "
796                 "errCode:%{public}d", iter.key_.c_str(), std::to_string(record.subscribeId).c_str(), iter.errCode_);
797         } else {
798             HILOG_INFO("success, uri:%{public}s, subscriberId:%{public}s",
799                 iter.key_.c_str(), std::to_string(record.subscribeId).c_str());
800         }
801         record.retryRet = iter.errCode_;
802     }
803 }
804 
RetryFailurePublishedSubscribes(SubscribeResultRecord & record)805 void FormDataProxyRecord::RetryFailurePublishedSubscribes(SubscribeResultRecord &record)
806 {
807     // ok or already retry
808     if (record.ret == 0 || record.retry) {
809         return;
810     }
811 
812     std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
813     auto publishedTask = [weak](const DataShare::PublishedDataChangeNode &changeNode) {
814         auto formDataRecord = weak.lock();
815         if (formDataRecord == nullptr) {
816             HILOG_ERROR("null formDataRecord");
817             return;
818         }
819         formDataRecord->OnPublishedDataChange(changeNode);
820     };
821 
822     record.retry = true;
823     std::vector<std::string> uris{record.uri};
824     auto ret = dataShareHelper_->SubscribePublishedData(uris, record.subscribeId, publishedTask);
825     for (const auto &iter : ret) {
826         if (iter.errCode_ != 0) {
827             HILOG_ERROR("retry subscribe published data failed, uri:%{public}s, subscriberId:%{public}s, "
828                 "errCode:%{public}d", iter.key_.c_str(), std::to_string(record.subscribeId).c_str(), iter.errCode_);
829         } else {
830             HILOG_INFO("success, uri:%{public}s, subscriberId:%{public}s",
831                 iter.key_.c_str(), std::to_string(record.subscribeId).c_str());
832         }
833         record.retryRet = iter.errCode_;
834     }
835 }
836 
GetFormSubscribeKeys(std::vector<std::string> & subscribedKeys,bool isRdbType)837 void FormDataProxyRecord::GetFormSubscribeKeys(std::vector<std::string> &subscribedKeys, bool isRdbType)
838 {
839     auto resultMap = isRdbType ? rdbSubscribeResultMap_ : publishSubscribeResultMap_;
840     for (auto &result : resultMap) {
841         for (auto &records : result.second) {
842             auto &record = records.second;
843             if (record.ret != 0) {
844                 continue;
845             }
846             auto uri = record.uri;
847             auto index = uri.find(KEY_DELIMITER);
848             if (index == std::string::npos) {
849                 return;
850             }
851             auto subscribeKey = uri.substr(0, index);
852             auto search = std::find(subscribedKeys.begin(), subscribedKeys.end(), subscribeKey);
853             if (search == subscribedKeys.end()) {
854                 subscribedKeys.emplace_back(subscribeKey);
855             }
856         }
857     }
858 }
859 } // namespace AppExecFwk
860 } // namespace OHOS