• 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 <vector>
19 
20 #ifdef SUPPORT_ERMS
21 #include "erms_mgr_param.h"
22 #endif
23 #include "fms_log_wrapper.h"
24 #include "form_bms_helper.h"
25 #include "form_data_mgr.h"
26 #include "form_mgr_adapter.h"
27 #include "form_mgr_errors.h"
28 #include "form_util.h"
29 #include "ipc_skeleton.h"
30 
31 namespace OHOS {
32 namespace AppExecFwk {
OnRdbDataChange(const DataShare::RdbChangeNode & changeNode)33 void FormDataProxyRecord::OnRdbDataChange(const DataShare::RdbChangeNode &changeNode)
34 {
35     HILOG_INFO("on rdb data change. data size is %{public}zu", changeNode.data_.size());
36     UpdateRdbDataForm(changeNode.data_);
37 }
38 
OnPublishedDataChange(const DataShare::PublishedDataChangeNode & changeNode)39 void FormDataProxyRecord::OnPublishedDataChange(const DataShare::PublishedDataChangeNode &changeNode)
40 {
41     HILOG_INFO("on published data change. data size is %{public}zu", changeNode.datas_.size());
42     UpdatePublishedDataForm(changeNode.datas_);
43 }
44 
FormDataProxyRecord(int64_t formId,const std::string & bundleName,FormType uiSyntax,uint32_t tokenId)45 FormDataProxyRecord::FormDataProxyRecord(int64_t formId, const std::string &bundleName, FormType uiSyntax,
46     uint32_t tokenId) : formId_(formId), bundleName_(bundleName), uiSyntax_(uiSyntax), tokenId_(tokenId)
47 {
48     std::string uri = "datashareproxy://" + bundleName;
49     DataShare::CreateOptions options;
50     options.isProxy_ = true;
51     dataShareHelper_ = DataShare::DataShareHelper::Creator(uri, options);
52 }
53 
~FormDataProxyRecord()54 FormDataProxyRecord::~FormDataProxyRecord()
55 {
56     if (dataShareHelper_ != nullptr) {
57         dataShareHelper_->Release();
58     }
59 }
60 
SubscribeFormData(const std::vector<FormDataProxy> & formDataProxies)61 ErrCode FormDataProxyRecord::SubscribeFormData(const std::vector<FormDataProxy> &formDataProxies)
62 {
63     HILOG_DEBUG("subscribe form data.");
64     ParseFormDataProxies(formDataProxies);
65     ErrCode ret = ERR_OK;
66     ret = SubscribeRdbFormData(rdbSubscribeMap_);
67     if (ret != ERR_OK) {
68         HILOG_ERROR("subscribe rdb form data failed.");
69         return ret;
70     }
71     ret = SubscribePublishFormData(publishSubscribeMap_);
72     if (ret != ERR_OK) {
73         HILOG_ERROR("subscribe publish form data failed.");
74         return ret;
75     }
76     return ret;
77 }
78 
SubscribeRdbFormData(std::map<std::string,std::string> & rdbSubscribeMap)79 ErrCode FormDataProxyRecord::SubscribeRdbFormData(std::map<std::string, std::string> &rdbSubscribeMap)
80 {
81     if (dataShareHelper_ == nullptr) {
82         HILOG_ERROR("dataShareHelper is nullptr.");
83         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
84     }
85 
86     if (rdbSubscribeMap.empty()) {
87         HILOG_DEBUG("rdbSubscribeMap is empty.");
88         return ERR_OK;
89     }
90 
91     std::vector<FormDataProxyRequest> formDataProxyRequests;
92     ConvertSubscribeMapToRequests(rdbSubscribeMap, formDataProxyRequests);
93 
94     std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
95     auto rdbTask = [weak](const DataShare::RdbChangeNode &changeNode) {
96         auto formDataRecord = weak.lock();
97         if (formDataRecord == nullptr) {
98             HILOG_ERROR("formDataRecord is nullptr.");
99             return;
100         }
101         formDataRecord->OnRdbDataChange(changeNode);
102     };
103     for (const auto &search : formDataProxyRequests) {
104         DataShare::TemplateId templateId;
105         templateId.subscriberId_ = search.subscribeId;
106         templateId.bundleName_ = bundleName_;
107         auto ret = dataShareHelper_->SubscribeRdbData(search.uris, templateId, rdbTask);
108         uint32_t failNum = 0;
109         for (const auto &iter : ret) {
110             if (iter.errCode_ != 0) {
111                 HILOG_ERROR("subscribe rdb data failed. %{public}s", iter.key_.c_str());
112                 failNum++;
113             }
114         }
115         HILOG_DEBUG("subscribe rdb data. subscribeId: %{public}s, failNum: %{public}d, totalNum: %{public}zu",
116             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
117     }
118 
119     return ERR_OK;
120 }
121 
SubscribePublishFormData(std::map<std::string,std::string> & publishSubscribeMap)122 ErrCode FormDataProxyRecord::SubscribePublishFormData(std::map<std::string, std::string> &publishSubscribeMap)
123 {
124     if (dataShareHelper_ == nullptr) {
125         HILOG_ERROR("dataShareHelper is nullptr.");
126         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
127     }
128 
129     if (publishSubscribeMap.empty()) {
130         HILOG_DEBUG("publishSubscribeMap is nullptr.");
131         return ERR_OK;
132     }
133 
134     std::vector<FormDataProxyRequest> formDataProxyRequests;
135     ConvertSubscribeMapToRequests(publishSubscribeMap, formDataProxyRequests);
136 
137     std::weak_ptr<FormDataProxyRecord> weak(shared_from_this());
138     auto publishedTask = [weak](const DataShare::PublishedDataChangeNode &changeNode) {
139         auto formDataRecord = weak.lock();
140         if (formDataRecord == nullptr) {
141             HILOG_ERROR("formDataRecord is nullptr.");
142             return;
143         }
144         formDataRecord->OnPublishedDataChange(changeNode);
145     };
146     for (const auto &search : formDataProxyRequests) {
147         auto ret = dataShareHelper_->SubscribePublishedData(search.uris, search.subscribeId, publishedTask);
148         uint32_t failNum = 0;
149         for (const auto &iter : ret) {
150             if (iter.errCode_ != 0) {
151                 HILOG_ERROR("subscribe published data failed. %{public}s", iter.key_.c_str());
152                 failNum++;
153             }
154         }
155         HILOG_DEBUG("subscribe published data. subscribeId: %{public}s, failNum: %{public}d, totalNum: %{public}zu",
156             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
157     }
158 
159     return ERR_OK;
160 }
161 
UnsubscribeFormData()162 ErrCode FormDataProxyRecord::UnsubscribeFormData()
163 {
164     return UnsubscribeFormData(rdbSubscribeMap_, publishSubscribeMap_);
165 }
166 
UnsubscribeFormData(std::map<std::string,std::string> & rdbSubscribeMap,std::map<std::string,std::string> & publishSubscribeMap)167 ErrCode FormDataProxyRecord::UnsubscribeFormData(std::map<std::string, std::string> &rdbSubscribeMap,
168     std::map<std::string, std::string> &publishSubscribeMap)
169 {
170     if (dataShareHelper_ == nullptr) {
171         HILOG_ERROR("dataShareHelper is nullptr.");
172         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
173     }
174 
175     std::vector<FormDataProxyRequest> rdbRequests;
176     ConvertSubscribeMapToRequests(rdbSubscribeMap, rdbRequests);
177     for (const auto &search : rdbRequests) {
178         DataShare::TemplateId templateId;
179         templateId.subscriberId_ = search.subscribeId;
180         templateId.bundleName_ = bundleName_;
181         dataShareHelper_->UnsubscribeRdbData(search.uris, templateId);
182     }
183     rdbSubscribeMap.clear();
184 
185     std::vector<FormDataProxyRequest> publishRequests;
186     ConvertSubscribeMapToRequests(publishSubscribeMap, publishRequests);
187     for (const auto &search : publishRequests) {
188         dataShareHelper_->UnsubscribePublishedData(search.uris, search.subscribeId);
189     }
190     publishSubscribeMap.clear();
191     return ERR_OK;
192 }
193 
ParseFormDataProxies(const std::vector<FormDataProxy> & formDataProxies)194 void FormDataProxyRecord::ParseFormDataProxies(const std::vector<FormDataProxy> &formDataProxies)
195 {
196     std::vector<ProxyData> proxyData;
197     FormBmsHelper::GetInstance().GetAllProxyDataInfos(FormUtil::GetCurrentAccountId(), proxyData);
198 
199     for (const auto& formDataProxy : formDataProxies) {
200         auto subscribe = formDataProxy.subscribeId.empty() ? std::to_string(formId_) : formDataProxy.subscribeId;
201         for (const auto& iter : proxyData) {
202             if (formDataProxy.key == iter.uri) {
203                 rdbSubscribeMap_[formDataProxy.key] = subscribe;
204                 HILOG_DEBUG("subscribe rdb data. key: %{public}s, subscribeId: %{public}s",
205                     formDataProxy.key.c_str(), subscribe.c_str());
206                 break;
207             }
208         }
209         publishSubscribeMap_[formDataProxy.key] = subscribe;
210         HILOG_DEBUG("subscribe publish data. key: %{public}s, subscribeId: %{public}s",
211             formDataProxy.key.c_str(), subscribe.c_str());
212     }
213 }
214 
ConvertSubscribeMapToRequests(std::map<std::string,std::string> & subscribeMap,std::vector<FormDataProxyRequest> & formDataProxyRequests)215 void FormDataProxyRecord::ConvertSubscribeMapToRequests(std::map<std::string, std::string> &subscribeMap,
216     std::vector<FormDataProxyRequest> &formDataProxyRequests)
217 {
218     std::string userId = std::to_string(FormUtil::GetCurrentAccountId());
219     for (const auto &subscribe : subscribeMap) {
220         int64_t subscriberId = formId_;
221         if (!FormUtil::ConvertStringToInt64(subscribe.second, subscriberId)) {
222             HILOG_WARN("Convert string to int64 failed, change to default value formId.");
223         }
224         bool isNewSubscriberId = true;
225         std::string uri;
226         for (auto &search : formDataProxyRequests) {
227             if (search.subscribeId == subscriberId) {
228                 uri = subscribe.first + "?" + "user=" + userId + "&srcToken=" + std::to_string(tokenId_) +
229                     "&dstBundleName=" + bundleName_;
230                 search.uris.push_back(uri);
231                 isNewSubscriberId = false;
232                 break;
233             }
234         }
235         if (isNewSubscriberId == true) {
236             FormDataProxyRequest formDataProxyRequest;
237             formDataProxyRequest.subscribeId = subscriberId;
238             uri = subscribe.first + "?" + "user=" + userId + "&srcToken=" + std::to_string(tokenId_) +
239                 "&dstBundleName=" + bundleName_;
240             formDataProxyRequest.uris.emplace_back(uri);
241             formDataProxyRequests.push_back(formDataProxyRequest);
242         }
243     }
244 }
245 
UpdatePublishedDataForm(const std::vector<DataShare::PublishedDataItem> & data)246 void FormDataProxyRecord::UpdatePublishedDataForm(const std::vector<DataShare::PublishedDataItem> &data)
247 {
248     std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> imageDataMap;
249     nlohmann::json object;
250     for (const auto& iter : data) {
251         if (iter.key_.empty()) {
252             HILOG_ERROR("key is empty.");
253             continue;
254         }
255         if (iter.IsAshmem()) {
256             PrepareImageData(iter, object, imageDataMap);
257         } else {
258             auto value = std::get<std::string>(iter.value_);
259             nlohmann::json dataObject = nlohmann::json::parse(value, nullptr, false);
260             if (dataObject.is_discarded()) {
261                 HILOG_ERROR("failed to parse data: %{public}s.", value.c_str());
262                 continue;
263             }
264             object[iter.key_] = dataObject;
265         }
266     }
267     std::string formDataStr = object.empty() ? "" : object.dump();
268     HILOG_INFO("update published data. formDataStr: %{private}s, imageDataMap size: %{publish}zu.",
269         formDataStr.c_str(), imageDataMap.size());
270     FormProviderData formProviderData;
271     formProviderData.SetDataString(formDataStr);
272     if (!imageDataMap.empty()) {
273         formProviderData.SetImageDataState(FormProviderData::IMAGE_DATA_STATE_ADDED);
274         formProviderData.SetImageDataMap(imageDataMap);
275     }
276     FormMgrAdapter::GetInstance().UpdateForm(formId_, bundleName_, formProviderData);
277 }
278 
UpdateRdbDataForm(const std::vector<std::string> & data)279 void FormDataProxyRecord::UpdateRdbDataForm(const std::vector<std::string> &data)
280 {
281     nlohmann::json object;
282     for (const auto& iter : data) {
283         HILOG_DEBUG("iter: %{private}s.", iter.c_str());
284         nlohmann::json dataObject = nlohmann::json::parse(iter, nullptr, false);
285         if (dataObject.is_discarded()) {
286             HILOG_ERROR("failed to parse data: %{public}s.", iter.c_str());
287             continue;
288         }
289         object.merge_patch(dataObject);
290     }
291 
292     std::string formDataStr = object.empty() ? "" : object.dump();
293     HILOG_INFO("update rdb data. formDataStr: %{private}s.", formDataStr.c_str());
294     FormProviderData formProviderData;
295     formProviderData.SetDataString(formDataStr);
296     FormMgrAdapter::GetInstance().UpdateForm(formId_, bundleName_, formProviderData);
297 }
298 
UpdateSubscribeFormData(const std::vector<FormDataProxy> & formDataProxies)299 void FormDataProxyRecord::UpdateSubscribeFormData(const std::vector<FormDataProxy> &formDataProxies)
300 {
301     std::map<std::string, std::string> originRdbMap;
302     std::map<std::string, std::string> newRdbMap;
303     std::map<std::string, std::string> originPublishMap;
304     std::map<std::string, std::string> newPublishMap;
305     UpdateSubscribeMap(formDataProxies, originRdbMap, newRdbMap, originPublishMap, newPublishMap);
306     UnsubscribeFormData(originRdbMap, originPublishMap);
307     SubscribeRdbFormData(newRdbMap);
308     SubscribePublishFormData(newPublishMap);
309 }
310 
UpdateSubscribeMap(const std::vector<FormDataProxy> & formDataProxies,std::map<std::string,std::string> & originRdbMap,std::map<std::string,std::string> & newRdbMap,std::map<std::string,std::string> & originPublishMap,std::map<std::string,std::string> & newPublishMap)311 void FormDataProxyRecord::UpdateSubscribeMap(const std::vector<FormDataProxy> &formDataProxies,
312     std::map<std::string, std::string> &originRdbMap,
313     std::map<std::string, std::string> &newRdbMap,
314     std::map<std::string, std::string> &originPublishMap,
315     std::map<std::string, std::string> &newPublishMap)
316 {
317     for (const auto &formDataProxy : formDataProxies) {
318         std::string key = formDataProxy.key;
319         std::string subscribe = formDataProxy.subscribeId.empty() ? std::to_string(formId_) : formDataProxy.subscribeId;
320         auto iter = rdbSubscribeMap_.find(key);
321         if (iter != rdbSubscribeMap_.end() && iter->second != subscribe) {
322             originRdbMap[key] = iter->second;
323             newRdbMap[key] = subscribe;
324             rdbSubscribeMap_[key] = subscribe;
325             continue;
326         }
327         iter = publishSubscribeMap_.find(key);
328         if (iter != publishSubscribeMap_.end() && iter->second != subscribe) {
329             originPublishMap[key] = iter->second;
330             newPublishMap[key] = subscribe;
331             publishSubscribeMap_[key] = subscribe;
332         }
333     }
334 }
335 
EnableSubscribeFormData()336 void FormDataProxyRecord::EnableSubscribeFormData()
337 {
338     HILOG_DEBUG("enable subscribe form, formId: %{public}s.", std::to_string(formId_).c_str());
339     SetRdbSubsState(rdbSubscribeMap_, true);
340     SetPublishSubsState(publishSubscribeMap_, true);
341 }
342 
DisableSubscribeFormData()343 void FormDataProxyRecord::DisableSubscribeFormData()
344 {
345     HILOG_DEBUG("disable subscribe form, formId: %{public}s.", std::to_string(formId_).c_str());
346     SetRdbSubsState(rdbSubscribeMap_, false);
347     SetPublishSubsState(publishSubscribeMap_, false);
348 }
349 
SetRdbSubsState(std::map<std::string,std::string> & rdbSubscribeMap,bool subsState)350 ErrCode FormDataProxyRecord::SetRdbSubsState(std::map<std::string, std::string> &rdbSubscribeMap, bool subsState)
351 {
352     if (dataShareHelper_ == nullptr) {
353         HILOG_ERROR("dataShareHelper is nullptr.");
354         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
355     }
356 
357     if (rdbSubscribeMap.empty()) {
358         HILOG_DEBUG("rdbSubscribeMap is empty.");
359         return ERR_OK;
360     }
361 
362     std::vector<FormDataProxyRequest> formDataProxyRequests;
363     ConvertSubscribeMapToRequests(rdbSubscribeMap, formDataProxyRequests);
364 
365     for (const auto &search : formDataProxyRequests) {
366         DataShare::TemplateId templateId;
367         templateId.subscriberId_ = search.subscribeId;
368         templateId.bundleName_ = bundleName_;
369         std::vector<DataShare::OperationResult> ret;
370         if (subsState) {
371             ret = dataShareHelper_->EnableRdbSubs(search.uris, templateId);
372         } else {
373             ret = dataShareHelper_->DisableRdbSubs(search.uris, templateId);
374         }
375         uint32_t failNum = 0;
376         for (const auto &iter : ret) {
377             if (iter.errCode_ != 0) {
378                 HILOG_ERROR("set rdb state failed. %{public}s", iter.key_.c_str());
379                 failNum++;
380             }
381         }
382         HILOG_DEBUG("set rdb state. subscribeId: %{public}s, failNum: %{public}d, totalNum: %{public}zu",
383             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
384     }
385 
386     return ERR_OK;
387 }
388 
SetPublishSubsState(std::map<std::string,std::string> & publishSubscribeMap,bool subsState)389 ErrCode FormDataProxyRecord::SetPublishSubsState(std::map<std::string, std::string> &publishSubscribeMap,
390     bool subsState)
391 {
392     if (dataShareHelper_ == nullptr) {
393         HILOG_ERROR("dataShareHelper is nullptr.");
394         return ERR_APPEXECFWK_FORM_INVALID_PARAM;
395     }
396 
397     if (publishSubscribeMap.empty()) {
398         HILOG_DEBUG("publishSubscribeMap is nullptr.");
399         return ERR_OK;
400     }
401 
402     std::vector<FormDataProxyRequest> formDataProxyRequests;
403     ConvertSubscribeMapToRequests(publishSubscribeMap, formDataProxyRequests);
404 
405     for (const auto &search : formDataProxyRequests) {
406         std::vector<DataShare::OperationResult> ret;
407         if (subsState) {
408             ret = dataShareHelper_->EnablePubSubs(search.uris, search.subscribeId);
409         } else {
410             ret = dataShareHelper_->DisablePubSubs(search.uris, search.subscribeId);
411         }
412         uint32_t failNum = 0;
413         for (const auto &iter : ret) {
414             if (iter.errCode_ != 0) {
415                 HILOG_ERROR("set published state failed. %{public}s", iter.key_.c_str());
416                 failNum++;
417             }
418         }
419         HILOG_DEBUG("set published state. subscribeId: %{public}s, failNum: %{public}d, totalNum: %{public}zu",
420             std::to_string(search.subscribeId).c_str(), failNum, search.uris.size());
421     }
422 
423     return ERR_OK;
424 }
425 
426 /*
427  * we need to automatically produce image names due to differences in usage between image publishing and rendering
428  */
PrepareImageData(const DataShare::PublishedDataItem & data,nlohmann::json & jsonObj,std::map<std::string,std::pair<sptr<FormAshmem>,int32_t>> & imageDataMap)429 bool FormDataProxyRecord::PrepareImageData(const DataShare::PublishedDataItem &data, nlohmann::json &jsonObj,
430     std::map<std::string, std::pair<sptr<FormAshmem>, int32_t>> &imageDataMap)
431 {
432     auto node = std::get<DataShare::AshmemNode>(data.value_);
433     if (node.ashmem == nullptr) {
434         HILOG_ERROR("ashmem form data share is nullptr.");
435         return false;
436     }
437     sptr<FormAshmem> formAshmem = new (std::nothrow) FormAshmem();
438     if (formAshmem == nullptr) {
439         HILOG_ERROR("alloc shmem failed");
440         return false;
441     }
442     auto size = node.ashmem->GetAshmemSize();
443     auto imageName = data.key_ + std::to_string(FormUtil::GetCurrentNanosecond());
444     if (!formAshmem->WriteToAshmem(imageName, (char *)node.ashmem->ReadFromAshmem(size, 0), size)) {
445         HILOG_ERROR("write to shmem failed");
446         return false;
447     }
448 
449     jsonObj[data.key_] = imageName;
450     if (uiSyntax_ == FormType::JS) {
451         jsonObj[data.key_] = "memory://" + imageName; // adapt memory image uri for js card
452     }
453 
454     std::pair<sptr<FormAshmem>, int32_t> imageDataRecord = std::make_pair(formAshmem, sizeof(formAshmem));
455     imageDataMap[imageName] = imageDataRecord;
456     return true;
457 }
458 } // namespace AppExecFwk
459 } // namespace OHOS