• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define LOG_TAG "ProxyDataManager"
17 
18 #include "datashare_observer.h"
19 #include "data_share_profile_config.h"
20 #include "dataproxy_handle_common.h"
21 #include "log_print.h"
22 #include "proxy_data_manager.h"
23 #include "utils.h"
24 #include "utils/anonymous.h"
25 
26 namespace OHOS::DataShare {
27 
GetInstance()28 ProxyDataManager &ProxyDataManager::GetInstance()
29 {
30     static ProxyDataManager instance;
31     return instance;
32 }
33 
ProxyDataList(const ProxyDataListNode & node)34 ProxyDataList::ProxyDataList(const ProxyDataListNode &node)
35     : KvData(Id(std::to_string(node.tokenId), node.userId)), value(node)
36 {
37 }
38 
HasVersion() const39 bool ProxyDataList::HasVersion() const
40 {
41     return true;
42 }
43 
GetVersion() const44 int ProxyDataList::GetVersion() const
45 {
46     return value.GetVersion();
47 }
48 
GetValue() const49 std::string ProxyDataList::GetValue() const
50 {
51     return DistributedData::Serializable::Marshall(value);
52 }
53 
PublishedProxyData(const ProxyDataNode & node)54 PublishedProxyData::PublishedProxyData(const ProxyDataNode &node)
55     : KvData(Id(node.proxyData.uri, node.userId)), value(node)
56 {
57 }
58 
HasVersion() const59 bool PublishedProxyData::HasVersion() const
60 {
61     return true;
62 }
63 
GetVersion() const64 int PublishedProxyData::GetVersion() const
65 {
66     return value.GetVersion();
67 }
68 
GetValue() const69 std::string PublishedProxyData::GetValue() const
70 {
71     return DistributedData::Serializable::Marshall(value);
72 }
73 
ProxyDataListNode()74 ProxyDataListNode::ProxyDataListNode() : VersionData(-1) {}
75 
ProxyDataNode()76 ProxyDataNode::ProxyDataNode() : VersionData(-1) {}
77 
Marshal(DistributedData::Serializable::json & node) const78 bool ProxyDataNode::Marshal(DistributedData::Serializable::json &node) const
79 {
80     bool ret = SetValue(node[GET_NAME(proxyData)], proxyData);
81     ret = ret && SetValue(node[GET_NAME(userId)], userId);
82     ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId);
83     return ret && VersionData::Marshal(node);
84 }
85 
Unmarshal(const DistributedData::Serializable::json & node)86 bool ProxyDataNode::Unmarshal(const DistributedData::Serializable::json &node)
87 {
88     bool ret = GetValue(node, GET_NAME(proxyData), proxyData);
89     ret = ret && GetValue(node, GET_NAME(userId), userId);
90     return ret && GetValue(node, GET_NAME(tokenId), tokenId);
91 }
92 
Marshal(DistributedData::Serializable::json & node) const93 bool ProxyDataListNode::Marshal(DistributedData::Serializable::json &node) const
94 {
95     bool ret = SetValue(node[GET_NAME(uris)], uris);
96     ret = ret && SetValue(node[GET_NAME(userId)], userId);
97     ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId);
98     return ret && VersionData::Marshal(node);
99 }
100 
Unmarshal(const DistributedData::Serializable::json & node)101 bool ProxyDataListNode::Unmarshal(const DistributedData::Serializable::json &node)
102 {
103     bool ret = GetValue(node, GET_NAME(uris), uris);
104     ret = ret && GetValue(node, GET_NAME(userId), userId);
105     ret = ret && GetValue(node, GET_NAME(tokenId), tokenId);
106     return ret;
107 }
108 
VerifyPermission(const BundleInfo & callerBundleInfo,const ProxyDataNode & data)109 bool PublishedProxyData::VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data)
110 {
111     if (callerBundleInfo.tokenId == data.tokenId) {
112         return true;
113     }
114 
115     for (const auto &item : data.proxyData.allowList) {
116         if (callerBundleInfo.appIdentifier == item) {
117             return true;
118         }
119     }
120     return false;
121 }
122 
CheckAndCorrectProxyData(DataShareProxyData & proxyData)123 bool PublishedProxyData::CheckAndCorrectProxyData(DataShareProxyData &proxyData)
124 {
125     // the upper limit of value is 4096 bytes, only string type is possible to exceed the limit
126     if (proxyData.value_.index() == DataProxyValueType::VALUE_STRING) {
127         std::string valueStr = std::get<std::string>(proxyData.value_);
128         if (valueStr.size() > VALUE_MAX_SIZE) {
129             ZLOGE("value of proxyData %{public}s is over limit, size %{public}zu",
130                 URIUtils::Anonymous(proxyData.uri_).c_str(), valueStr.size());
131             return false;
132         }
133     }
134     if (proxyData.uri_.size() > URI_MAX_SIZE) {
135         ZLOGE("uri of proxyData %{public}s is over limit, size %{public}zu",
136             URIUtils::Anonymous(proxyData.uri_).c_str(), proxyData.uri_.size());
137         return false;
138     }
139     int32_t allowListCount = 1;
140     auto it = proxyData.allowList_.begin();
141     while (it != proxyData.allowList_.end()) {
142         if (it->size() > APPIDENTIFIER_MAX_SIZE) {
143             ZLOGW("appidentifier of proxyData %{public}s is over limit, size %{public}zu",
144                 URIUtils::Anonymous(proxyData.uri_).c_str(), it->size());
145             it = proxyData.allowList_.erase(it);
146         } else {
147             if (allowListCount++ > ALLOW_LIST_MAX_COUNT) {
148                 break;
149             }
150             it++;
151         }
152     }
153     if (proxyData.allowList_.size() > ALLOW_LIST_MAX_COUNT) {
154         ZLOGW("allowList of proxyData %{public}s is over limit, size %{public}zu",
155             URIUtils::Anonymous(proxyData.uri_).c_str(), proxyData.allowList_.size());
156         proxyData.allowList_.resize(ALLOW_LIST_MAX_COUNT);
157     }
158     return true;
159 }
160 
PutIntoTable(std::shared_ptr<KvDBDelegate> kvDelegate,int32_t user,uint32_t tokenId,const std::vector<std::string> & proxyDataList,const DataShareProxyData & proxyData)161 int32_t PublishedProxyData::PutIntoTable(std::shared_ptr<KvDBDelegate> kvDelegate, int32_t user,
162     uint32_t tokenId, const std::vector<std::string> &proxyDataList, const DataShareProxyData &proxyData)
163 {
164     if (kvDelegate == nullptr) {
165         ZLOGE("kv delegate is null!");
166         return INNER_ERROR;
167     }
168 
169     SerialDataShareProxyData serialProxyData(proxyData.uri_, proxyData.value_, proxyData.allowList_);
170     auto ret = kvDelegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, PublishedProxyData(ProxyDataNode(
171         serialProxyData, user, tokenId)));
172     if (ret.first != E_OK) {
173         ZLOGE("db Upsert failed, %{public}s %{public}d",
174             URIUtils::Anonymous(proxyData.uri_).c_str(), ret.first);
175         return INNER_ERROR;
176     }
177 
178     if (!proxyDataList.empty()) {
179         auto value = ProxyDataList(ProxyDataListNode(
180             proxyDataList, user, tokenId));
181         ret = kvDelegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, value);
182         if (ret.first != E_OK) {
183             ZLOGE("db Upsert failed, %{public}x %{public}d", tokenId, user);
184             return INNER_ERROR;
185         }
186     }
187     return SUCCESS;
188 }
189 
InsertProxyData(std::shared_ptr<KvDBDelegate> kvDelegate,const std::string & bundleName,const int32_t & user,const uint32_t & tokenId,const DataShareProxyData & proxyData)190 int32_t PublishedProxyData::InsertProxyData(std::shared_ptr<KvDBDelegate> kvDelegate, const std::string &bundleName,
191     const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData)
192 {
193     if (kvDelegate == nullptr) {
194         ZLOGE("kv delegate is null!");
195         return INNER_ERROR;
196     }
197 
198     ProxyDataListNode proxyDataList;
199     std::string listFilter = Id(std::to_string(tokenId), user);
200     std::string listQueryResult;
201     kvDelegate->Get(KvDBDelegate::PROXYDATA_TABLE, listFilter, "{}", listQueryResult);
202     if (!listQueryResult.empty()) {
203         if (!ProxyDataListNode::Unmarshall(listQueryResult, proxyDataList)) {
204             ZLOGE("ProxyDataListNode unmarshall failed, %{public}s",
205                 StringUtils::GeneralAnonymous(listQueryResult).c_str());
206             return INNER_ERROR;
207         }
208     }
209     if (proxyDataList.uris.size() >= PROXY_DATA_MAX_COUNT) {
210         return OVER_LIMIT;
211     }
212 
213     std::string modifyBundle;
214     URIUtils::GetBundleNameFromProxyURI(proxyData.uri_, modifyBundle);
215     if (modifyBundle != bundleName) {
216         ZLOGE("only allowed to publish the proxyData of self bundle %{public}s, dest bundle %{public}s",
217             bundleName.c_str(), modifyBundle.c_str());
218         return NO_PERMISSION;
219     }
220 
221     auto it = std::find(proxyDataList.uris.begin(), proxyDataList.uris.end(), proxyData.uri_);
222     if (it == proxyDataList.uris.end()) {
223         proxyDataList.uris.emplace_back(proxyData.uri_);
224     }
225     return PutIntoTable(kvDelegate, user, tokenId, proxyDataList.uris, proxyData);
226 }
227 
UpdateProxyData(std::shared_ptr<KvDBDelegate> kvDelegate,const std::string & bundleName,const int32_t & user,const uint32_t & tokenId,const DataShareProxyData & proxyData)228 int32_t PublishedProxyData::UpdateProxyData(std::shared_ptr<KvDBDelegate> kvDelegate, const std::string &bundleName,
229     const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData)
230 {
231     if (kvDelegate == nullptr) {
232         ZLOGE("kv delegate is null!");
233         return INNER_ERROR;
234     }
235     std::vector<std::string> proxyDataList;
236     return PutIntoTable(kvDelegate, user, tokenId, proxyDataList, proxyData);
237 }
238 
Query(const std::string & uri,const BundleInfo & callerBundleInfo,DataShareProxyData & proxyData)239 int32_t PublishedProxyData::Query(const std::string &uri, const BundleInfo &callerBundleInfo,
240     DataShareProxyData &proxyData)
241 {
242     auto delegate = KvDBDelegate::GetInstance();
243     if (delegate == nullptr) {
244         ZLOGE("db open failed");
245         return INNER_ERROR;
246     }
247     std::string filter = Id(uri, callerBundleInfo.userId);
248     std::string queryResult;
249     delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult);
250     if (queryResult.empty()) {
251         return URI_NOT_EXIST;
252     }
253     ProxyDataNode data;
254     if (!ProxyDataNode::Unmarshall(queryResult, data)) {
255         ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str());
256         return INNER_ERROR;
257     }
258     DataShareProxyData tempProxyData(data.proxyData.uri, data.proxyData.value, data.proxyData.allowList);
259     if (callerBundleInfo.tokenId != data.tokenId) {
260         tempProxyData.allowList_ = {};
261     }
262     if (!VerifyPermission(callerBundleInfo, data)) {
263         return NO_PERMISSION;
264     }
265 
266     proxyData = tempProxyData;
267     return SUCCESS;
268 }
269 
Upsert(const DataShareProxyData & proxyData,const BundleInfo & callerBundleInfo,DataShareObserver::ChangeType & type)270 int32_t PublishedProxyData::Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo,
271     DataShareObserver::ChangeType &type)
272 {
273     type = DataShareObserver::ChangeType::INVAILD;
274     auto delegate = KvDBDelegate::GetInstance();
275     if (delegate == nullptr) {
276         ZLOGE("db open failed");
277         return INNER_ERROR;
278     }
279 
280     auto data = proxyData;
281     if (!CheckAndCorrectProxyData(data)) {
282         return OVER_LIMIT;
283     }
284     std::string filter = Id(data.uri_, callerBundleInfo.userId);
285     std::string queryResult;
286     delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult);
287     if (queryResult.empty()) {
288         type = DataShareObserver::ChangeType::INSERT;
289         return InsertProxyData(delegate, callerBundleInfo.bundleName,
290             callerBundleInfo.userId, callerBundleInfo.tokenId, data);
291     } else {
292         ProxyDataNode oldData;
293         if (!ProxyDataNode::Unmarshall(queryResult, oldData)) {
294             ZLOGE("ProxyDataNode unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str());
295             return INNER_ERROR;
296         }
297         if (callerBundleInfo.tokenId != oldData.tokenId) {
298             ZLOGE("only allow to modify the proxyData of self bundle %{public}d, dest bundle %{public}d",
299                 callerBundleInfo.tokenId, oldData.tokenId);
300             return NO_PERMISSION;
301         }
302         if (data.isValueUndefined) {
303             data.value_ = oldData.proxyData.value;
304         }
305         if (data.isAllowListUndefined) {
306             data.allowList_ = oldData.proxyData.allowList;
307         }
308         // only when value changed is need notify
309         if (oldData.proxyData.value != data.value_) {
310             type = DataShareObserver::ChangeType::UPDATE;
311         }
312         return UpdateProxyData(delegate, callerBundleInfo.bundleName,
313             callerBundleInfo.userId, callerBundleInfo.tokenId, data);
314     }
315 }
316 
Delete(const std::string & uri,const BundleInfo & callerBundleInfo,DataShareProxyData & oldProxyData,DataShareObserver::ChangeType & type)317 int32_t PublishedProxyData::Delete(const std::string &uri, const BundleInfo &callerBundleInfo,
318     DataShareProxyData &oldProxyData, DataShareObserver::ChangeType &type)
319 {
320     type = DataShareObserver::ChangeType::INVAILD;
321     auto delegate = KvDBDelegate::GetInstance();
322     if (delegate == nullptr) {
323         ZLOGE("db open failed");
324         return INNER_ERROR;
325     }
326 
327     std::string bundleName;
328     URIUtils::GetBundleNameFromProxyURI(uri, bundleName);
329     if (callerBundleInfo.bundleName != bundleName) {
330         return NO_PERMISSION;
331     }
332     std::string queryResult;
333     delegate->Get(KvDBDelegate::PROXYDATA_TABLE, Id(uri, callerBundleInfo.userId), "{}", queryResult);
334     if (queryResult.empty()) {
335         return URI_NOT_EXIST;
336     }
337 
338     ProxyDataNode oldData;
339     if (!ProxyDataNode::Unmarshall(queryResult, oldData)) {
340         ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str());
341         return INNER_ERROR;
342     }
343     if (callerBundleInfo.tokenId != oldData.tokenId) {
344         return NO_PERMISSION;
345     }
346     auto ret = delegate->Delete(KvDBDelegate::PROXYDATA_TABLE, Id(uri, callerBundleInfo.userId));
347     if (ret.first != E_OK) {
348         ZLOGE("db Delete failed, %{public}s %{public}d", URIUtils::Anonymous(uri).c_str(), ret.first);
349         return INNER_ERROR;
350     }
351     std::vector<std::string> uris;
352     auto count = ProxyDataList::Query(callerBundleInfo.tokenId, callerBundleInfo.userId, uris);
353     if (count <= 0) {
354         ZLOGI("get bundle %{public}s's proxyData failed", callerBundleInfo.bundleName.c_str());
355         return INNER_ERROR;
356     }
357     auto it = std::find(uris.begin(), uris.end(), uri);
358     if (it != uris.end()) {
359         uris.erase(it);
360     }
361     ret = delegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, ProxyDataList(ProxyDataListNode(
362         uris, callerBundleInfo.userId, callerBundleInfo.tokenId)));
363     if (ret.first != E_OK) {
364         ZLOGE("db Upsert failed, %{public}x %{public}d", callerBundleInfo.tokenId, ret.first);
365         return INNER_ERROR;
366     }
367     oldProxyData = DataShareProxyData(oldData.proxyData.uri, oldData.proxyData.value, oldData.proxyData.allowList);
368     type = DataShareObserver::ChangeType::DELETE;
369     return SUCCESS;
370 }
371 
Query(uint32_t tokenId,int32_t userId,std::vector<std::string> & proxyDataList)372 int32_t ProxyDataList::Query(uint32_t tokenId, int32_t userId, std::vector<std::string> &proxyDataList)
373 {
374     int32_t invalidNum = -1;
375     auto delegate = KvDBDelegate::GetInstance();
376     if (delegate == nullptr) {
377         ZLOGE("db open failed");
378         return invalidNum;
379     }
380     std::string filter = Id(std::to_string(tokenId), userId);
381     std::string queryResult;
382     delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult);
383     if (queryResult.empty()) {
384         return invalidNum;
385     }
386     ProxyDataListNode data;
387     if (!ProxyDataListNode::Unmarshall(queryResult, data)) {
388         ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str());
389         return invalidNum;
390     }
391 
392     proxyDataList = std::move(data.uris);
393     return proxyDataList.size();
394 }
395 
GetCrossAppSharedConfig(const std::string & bundleName,int32_t user,int32_t index,std::vector<DataShareProxyData> & proxyDatas)396 bool ProxyDataManager::GetCrossAppSharedConfig(const std::string &bundleName, int32_t user,
397     int32_t index, std::vector<DataShareProxyData> &proxyDatas)
398 {
399     BundleConfig bundleConfig;
400     auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(bundleName, user, bundleConfig, index);
401     if (ret != E_OK) {
402         ZLOGE("Get bundleInfo falied, ret : %{public}d", ret);
403         return false;
404     }
405     std::vector<std::string> resourcePath;
406     std::vector<SerialDataShareProxyData> datas;
407     std::for_each(bundleConfig.hapModuleInfos.begin(),
408         bundleConfig.hapModuleInfos.end(), [&datas](const HapModuleInfo hapModuleInfo) {
409         if (!hapModuleInfo.crossAppSharedConfig.resourcePath.empty()) {
410             auto [ret, data] = DataShareProfileConfig::GetCrossAppSharedConfig(
411                 hapModuleInfo.crossAppSharedConfig.resourcePath, hapModuleInfo.resourcePath, hapModuleInfo.hapPath);
412             if (ret == SUCCESS) {
413                 datas.insert(datas.end(), data.begin(), data.end());
414             } else {
415                 ZLOGE("get shareConfig failed, err: %{public}d", ret);
416             }
417         }
418     });
419     std::for_each(datas.begin(), datas.end(), [&proxyDatas](auto &data) {
420         proxyDatas.emplace_back(std::move(data.uri), std::move(data.value), std::move(data.allowList));
421     });
422     return true;
423 }
424 
OnAppInstall(const std::string & bundleName,int32_t user,int32_t index,uint32_t tokenId)425 void ProxyDataManager::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId)
426 {
427     std::vector<DataShareProxyData> proxyDatas;
428     BundleInfo callerBundleInfo;
429     callerBundleInfo.bundleName = bundleName;
430     callerBundleInfo.userId = user;
431     callerBundleInfo.appIndex = index;
432     callerBundleInfo.tokenId = tokenId;
433     if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) {
434         ZLOGE("GetCrossAppSharedConfig after install failed");
435         return;
436     }
437     DataShareObserver::ChangeType type;
438     std::for_each(proxyDatas.begin(), proxyDatas.end(),
439         [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) {
440         PublishedProxyData::Upsert(proxyData, callerBundleInfo, type);
441     });
442 }
443 
OnAppUpdate(const std::string & bundleName,int32_t user,int32_t index,uint32_t tokenId)444 void ProxyDataManager::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId)
445 {
446     std::vector<DataShareProxyData> proxyDatas;
447     BundleInfo callerBundleInfo;
448     callerBundleInfo.bundleName = bundleName;
449     callerBundleInfo.userId = user;
450     callerBundleInfo.appIndex = index;
451     callerBundleInfo.tokenId = tokenId;
452     DataShareObserver::ChangeType type;
453     if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) {
454         ZLOGE("GetCrossAppSharedConfig after install failed");
455         return;
456     }
457     std::vector<std::string> uris;
458     auto count = ProxyDataList::Query(tokenId, user, uris);
459     if (count <= 0) {
460         ZLOGI("bundle %{public}s has no proxyData", bundleName.c_str());
461     }
462     DataShareProxyData oldProxyData;
463     for (const auto &uri : uris) {
464         PublishedProxyData::Delete(uri, callerBundleInfo, oldProxyData, type);
465     }
466     std::for_each(proxyDatas.begin(), proxyDatas.end(),
467         [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) {
468         PublishedProxyData::Upsert(proxyData, callerBundleInfo, type);
469     });
470 }
471 
OnAppUninstall(const std::string & bundleName,int32_t user,int32_t index,uint32_t tokenId)472 void ProxyDataManager::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId)
473 {
474     DataShareProxyData proxyData;
475     BundleInfo callerBundleInfo;
476     callerBundleInfo.bundleName = bundleName;
477     callerBundleInfo.userId = user;
478     callerBundleInfo.appIndex = index;
479     callerBundleInfo.tokenId = tokenId;
480     DataShareObserver::ChangeType type;
481     std::vector<std::string> uris;
482     auto count = ProxyDataList::Query(tokenId, user, uris);
483     if (count <= 0) {
484         ZLOGI("bundle %{public}s has no proxyData", bundleName.c_str());
485     }
486     for (const auto &uri : uris) {
487         PublishedProxyData::Delete(uri, callerBundleInfo, proxyData, type);
488     }
489 }
490 } // namespace OHOS::DataShare