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