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