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