From f33f70d766aae7c47e6169c10e715c635b6606e6 Mon Sep 17 00:00:00 2001 From: czy Date: Mon, 16 Jun 2025 17:08:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BA=94=E7=94=A8=E9=97=B4=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=85=B1=E4=BA=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: czy Change-Id: Ida0e528bce1fefd1853deac50d06effa776a690c --- .../service/data_share/BUILD.gn | 2 + .../data_share/common/bundle_mgr_proxy.cpp | 1 + .../data_share/common/bundle_mgr_proxy.h | 14 + .../service/data_share/common/db_delegate.h | 1 + .../service/data_share/common/kv_delegate.cpp | 9 + .../data_share/common/proxy_data_manager.cpp | 284 ++++++++++++++++++ .../data_share/common/proxy_data_manager.h | 74 +++++ .../data_share/data/published_data.cpp | 10 +- .../service/data_share/data_proxy_observer.h | 7 + .../data_share/data_share_obs_proxy.cpp | 23 ++ .../service/data_share/data_share_obs_proxy.h | 11 + .../data_share/data_share_profile_config.cpp | 53 +++- .../data_share/data_share_profile_config.h | 22 ++ .../data_share/data_share_service_impl.cpp | 125 ++++++++ .../data_share/data_share_service_impl.h | 11 + .../data_share/data_share_service_stub.cpp | 88 ++++++ .../data_share/data_share_service_stub.h | 12 +- .../service/data_share/idata_share_service.h | 18 +- .../proxy_data_subscriber_manager.cpp | 161 ++++++++++ .../proxy_data_subscriber_manager.h | 63 ++++ .../data_share/sys_event_subscriber.cpp | 44 ++- .../service/data_share/sys_event_subscriber.h | 10 + .../service/test/BUILD.gn | 2 + .../datashareservicestub_fuzzer/BUILD.gn | 2 + 24 files changed, 1036 insertions(+), 11 deletions(-) create mode 100644 services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp create mode 100644 services/distributeddataservice/service/data_share/common/proxy_data_manager.h create mode 100644 services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp create mode 100644 services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h diff --git a/services/distributeddataservice/service/data_share/BUILD.gn b/services/distributeddataservice/service/data_share/BUILD.gn index 74ab6cf29..68e54c60c 100644 --- a/services/distributeddataservice/service/data_share/BUILD.gn +++ b/services/distributeddataservice/service/data_share/BUILD.gn @@ -56,6 +56,7 @@ ohos_source_set("data_share_service") { "common/extension_connect_adaptor.cpp", "common/extension_mgr_proxy.cpp", "common/kv_delegate.cpp", + "common/proxy_data_manager.cpp", "common/rdb_delegate.cpp", "common/scheduler_manager.cpp", "common/seq_strategy.cpp", @@ -87,6 +88,7 @@ ohos_source_set("data_share_service") { "strategies/rdb_notify_strategy.cpp", "strategies/subscribe_strategy.cpp", "strategies/template_strategy.cpp", + "subscriber_managers/proxy_data_subscriber_manager.cpp", "subscriber_managers/published_data_subscriber_manager.cpp", "subscriber_managers/rdb_subscriber_manager.cpp", "sys_event_subscriber.cpp", diff --git a/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp b/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp index 360724f83..267a66c32 100644 --- a/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp +++ b/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp @@ -262,6 +262,7 @@ std::pair> BundleMgrProxy::ConvertHapModuleInfo( hapModuleInfo.resourcePath = std::move(item.resourcePath); hapModuleInfo.hapPath = std::move(item.hapPath); hapModuleInfo.moduleName = std::move(item.moduleName); + hapModuleInfo.crossAppSharedConfig.resourcePath = std::move(item.crossAppSharedConfig); std::vector proxyDatas; for (auto &proxyData : item.proxyDatas) { ProxyData data; diff --git a/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h b/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h index bc432d62c..7198715f1 100644 --- a/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h +++ b/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h @@ -37,11 +37,17 @@ struct ProxyData { ProfileConfig profileInfo; }; +struct CrossAppSharedConfig { + std::string resourcePath; + ProxyDataProfileInfo profile; +}; + struct HapModuleInfo { std::string resourcePath; std::string hapPath; std::string moduleName; std::vector proxyDatas; + CrossAppSharedConfig crossAppSharedConfig; }; struct ExtensionAbilityInfo { @@ -62,6 +68,14 @@ struct BundleConfig { std::vector extensionInfos; }; +struct BundleInfo { + std::string bundleName; + std::string appIdentifier; + int32_t userId; + int32_t appIndex; + uint32_t tokenId; +}; + class BundleMgrProxy final : public std::enable_shared_from_this { public: BundleMgrProxy() = default; diff --git a/services/distributeddataservice/service/data_share/common/db_delegate.h b/services/distributeddataservice/service/data_share/common/db_delegate.h index b5b51aec1..a59a516c4 100644 --- a/services/distributeddataservice/service/data_share/common/db_delegate.h +++ b/services/distributeddataservice/service/data_share/common/db_delegate.h @@ -127,6 +127,7 @@ class KvDBDelegate { public: static constexpr const char *TEMPLATE_TABLE = "template_"; static constexpr const char *DATA_TABLE = "data_"; + static constexpr const char *PROXYDATA_TABLE = "proxydata_"; static std::shared_ptr GetInstance( bool reInit = false, const std::string &dir = "", const std::shared_ptr &executors = nullptr); virtual ~KvDBDelegate() = default; diff --git a/services/distributeddataservice/service/data_share/common/kv_delegate.cpp b/services/distributeddataservice/service/data_share/common/kv_delegate.cpp index be360b40b..8afa880df 100644 --- a/services/distributeddataservice/service/data_share/common/kv_delegate.cpp +++ b/services/distributeddataservice/service/data_share/common/kv_delegate.cpp @@ -225,6 +225,15 @@ bool KvDelegate::Init() RestoreIfNeed(status); return false; } + + status = GRD_CreateCollection(db_, PROXYDATA_TABLE, nullptr, 0); + if (status != GRD_OK) { + // If opeaning db succeeds, it is rare to fail to create tables + ZLOGE("GRD_CreateCollection data table failed,status %{public}d", status); + RestoreIfNeed(status); + return false; + } + isInitDone_ = true; return true; } diff --git a/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp b/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp new file mode 100644 index 000000000..59bfbf8c9 --- /dev/null +++ b/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ProxyDataManager" + +#include "datashare_observer.h" +#include "data_share_profile_config.h" +#include "dataproxy_handle_common.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "uri_utils.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { + +ProxyDataManager &ProxyDataManager::GetInstance() +{ + static ProxyDataManager instance; + return instance; +} + +PublishedProxyData::PublishedProxyData(const ProxyDataNode &node) + : KvData(Id(node.proxyData.uri, node.userId)), value(node) +{ +} + +bool PublishedProxyData::HasVersion() const +{ + return true; +} + +int PublishedProxyData::GetVersion() const +{ + return value.GetVersion(); +} + +std::string PublishedProxyData::GetValue() const +{ + return DistributedData::Serializable::Marshall(value); +} + +ProxyDataNode::ProxyDataNode() : VersionData(-1) {} + +bool ProxyDataNode::Marshal(DistributedData::Serializable::json &node) const +{ + bool ret = SetValue(node[GET_NAME(proxyData)], proxyData); + ret = ret && SetValue(node[GET_NAME(bundleName)], bundleName); + ret = ret && SetValue(node[GET_NAME(userId)], userId); + ret = ret && SetValue(node[GET_NAME(appIndex)], appIndex); + ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId); + return ret && VersionData::Marshal(node); +} + +bool ProxyDataNode::Unmarshal(const DistributedData::Serializable::json &node) +{ + bool ret = GetValue(node, GET_NAME(proxyData), proxyData); + ret = ret && GetValue(node, GET_NAME(bundleName), bundleName); + ret = ret && GetValue(node, GET_NAME(userId), userId); + ret = ret && GetValue(node, GET_NAME(appIndex), appIndex); + return ret && GetValue(node, GET_NAME(tokenId), tokenId); +} + +bool PublishedProxyData::VerifySelfAccess(const BundleInfo &callerBundleInfo, + const ProxyDataNode &data, bool isInstallEvent) +{ + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(data.proxyData.uri, bundleName); + if (callerBundleInfo.bundleName == bundleName && callerBundleInfo.appIndex == data.appIndex && + callerBundleInfo.userId == data.userId) { + return true; + } + ZLOGE("only allow to modify the proxyData of self bundle"); + return false; +} + +bool PublishedProxyData::VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data) +{ + if (VerifySelfAccess(callerBundleInfo, data)) { + return true; + } + + for (const auto &item : data.proxyData.allowList) { + if (callerBundleInfo.appIdentifier == item || item == ALLOW_ALL) { + return true; + } + } + return false; +} + +int32_t PublishedProxyData::Query(const std::string &uri, const BundleInfo &callerBundleInfo, + DataShareProxyData &proxyData) +{ + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + std::string filter = Id(uri, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + return URI_NOT_EXIST; + } + ProxyDataNode data; + if (!ProxyDataNode::Unmarshall(queryResult, data)) { + ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + return INNER_ERROR; + } + DataShareProxyData tempProxyData(data.proxyData.uri, data.proxyData.value, data.proxyData.allowList); + if (!VerifySelfAccess(callerBundleInfo, data)) { + tempProxyData.allowList_ = {}; + } + if (!VerifyPermission(callerBundleInfo, data)) { + return NO_PERMISSION; + } + + proxyData = tempProxyData; + return SUCCESS; +} + +int32_t PublishedProxyData::Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo, + DataShareObserver::ChangeType &type, bool isInstallEvent) +{ + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + type = DataShareObserver::ChangeType::INVAILD; + return INNER_ERROR; + } + + std::string filter = Id(proxyData.uri_, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + + if (queryResult.empty()) { + type = DataShareObserver::ChangeType::INSERT; + std::string modifyBundle; + URIUtils::GetBundleNameFromProxyURI(proxyData.uri_, modifyBundle); + if (modifyBundle != callerBundleInfo.bundleName) { + ZLOGE("only allowed to modify the proxyData of self bundle"); + return NO_PERMISSION; + } + } else { + ProxyDataNode oldData; + if (!ProxyDataNode::Unmarshall(queryResult, oldData)) { + ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + return INNER_ERROR; + } + if (!VerifySelfAccess(callerBundleInfo, oldData, isInstallEvent)) { + return NO_PERMISSION; + } + } + SerialDataShareProxyData serialProxyData(proxyData.uri_, proxyData.value_, proxyData.allowList_); + auto [status, count] = delegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, PublishedProxyData(ProxyDataNode( + serialProxyData, callerBundleInfo.bundleName, callerBundleInfo.userId, + callerBundleInfo.appIndex, callerBundleInfo.tokenId))); + if (status != E_OK) { + ZLOGE("db Upsert failed, %{public}s %{public}d", + DistributedData::Anonymous::Change(proxyData.uri_).c_str(), status); + type = DataShareObserver::ChangeType::INVAILD; + return INNER_ERROR; + } + type = DataShareObserver::ChangeType::UPDATE; + return SUCCESS; +} + +int32_t PublishedProxyData::Delete(const std::string &uri, const BundleInfo &callerBundleInfo, + DataShareProxyData &oldProxyData, DataShareObserver::ChangeType &type, bool isInstallEvent) +{ + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(uri, bundleName); + if (callerBundleInfo.bundleName != bundleName) { + return NO_PERMISSION; + } + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + type = DataShareObserver::ChangeType::INVAILD; + return INNER_ERROR; + } + + std::string filter = Id(uri, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + return URI_NOT_EXIST; + } + + ProxyDataNode oldData; + if (!ProxyDataNode::Unmarshall(queryResult, oldData)) { + ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + return INNER_ERROR; + } + if (!VerifySelfAccess(callerBundleInfo, oldData, isInstallEvent)) { + return NO_PERMISSION; + } + oldProxyData.uri_ = oldData.proxyData.uri; + oldProxyData.value_ = oldData.proxyData.value; + oldProxyData.allowList_ = oldData.proxyData.allowList; + auto [status, count] = delegate->Delete(KvDBDelegate::PROXYDATA_TABLE, filter); + if (status != E_OK) { + ZLOGE("db Delete failed, %{public}s %{public}d", filter.c_str(), status); + type = DataShareObserver::ChangeType::INVAILD; + return INNER_ERROR; + } + type = DataShareObserver::ChangeType::DELETE; + return SUCCESS; +} + +bool ProxyDataManager::GetCrossAppSharedConfig(const std::string &bundleName, int32_t user, + int32_t index, std::vector &proxyDatas) +{ + BundleConfig bundleConfig; + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(bundleName, user, bundleConfig, index); + if (ret != E_OK) { + ZLOGE("Get bundleInfo falied, ret : %{public}d", ret); + return false; + } + std::vector resourcePath; + std::vector datas; + std::for_each(bundleConfig.hapModuleInfos.begin(), + bundleConfig.hapModuleInfos.end(), [&datas](const HapModuleInfo hapModuleInfo) { + if (!hapModuleInfo.crossAppSharedConfig.resourcePath.empty()) { + auto [ret, data] = DataShareProfileConfig::GetCrossAppSharedConfig( + hapModuleInfo.crossAppSharedConfig.resourcePath, hapModuleInfo.resourcePath, hapModuleInfo.hapPath); + if (ret == SUCCESS) { + datas.insert(datas.end(), data.begin(), data.end()); + } else { + ZLOGE("get shareConfig failed, err: %{public}d", ret); + } + } + }); + std::for_each(datas.begin(), datas.end(), [&proxyDatas](auto &data) { + proxyDatas.emplace_back(std::move(data.uri), std::move(data.value), std::move(data.allowList)); + }); + return true; +} + +void ProxyDataManager::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + std::vector proxyDatas; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) { + ZLOGE("GetCrossAppSharedConfig after install failed"); + return; + } + DataShareObserver::ChangeType type; + std::for_each(proxyDatas.begin(), proxyDatas.end(), + [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) { + PublishedProxyData::Upsert(proxyData, callerBundleInfo, type, true); + }); +} + +void ProxyDataManager::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + std::vector proxyDatas; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + DataShareObserver::ChangeType type; + std::for_each(proxyDatas.begin(), proxyDatas.end(), + [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) { + PublishedProxyData::Upsert(proxyData, callerBundleInfo, type, true); + }); +} +} // namespace OHOS::DataShare \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/common/proxy_data_manager.h b/services/distributeddataservice/service/data_share/common/proxy_data_manager.h new file mode 100644 index 000000000..3fe7db492 --- /dev/null +++ b/services/distributeddataservice/service/data_share/common/proxy_data_manager.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATASHARESERVICE_PROXY_DATA_MANAGER_H +#define DATASHARESERVICE_PROXY_DATA_MANAGER_H + +#include "bundle_mgr_proxy.h" +#include "dataproxy_handle_common.h" +#include "db_delegate.h" + +namespace OHOS::DataShare { + +class ProxyDataNode final : public VersionData { +public: + ProxyDataNode(); + ProxyDataNode(const SerialDataShareProxyData proxyData, const std::string bundleName, + const int32_t userId, const int32_t &appIndex, const uint32_t tokenId) + : VersionData(0), proxyData(proxyData), bundleName(bundleName), + userId(userId), appIndex(appIndex), tokenId(tokenId) {} + ~ProxyDataNode() = default; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + SerialDataShareProxyData proxyData; + std::string bundleName; + int32_t userId = Id::INVALID_USER; + int32_t appIndex = 0; + uint32_t tokenId; +}; + +class PublishedProxyData final : public KvData { +public: + explicit PublishedProxyData(const ProxyDataNode &node); + ~PublishedProxyData() = default; + static int32_t Query(const std::string &uri, const BundleInfo &callerBundleInfo, DataShareProxyData &proxyData); + static int32_t Delete(const std::string &uri, const BundleInfo &callerBundleInfo, DataShareProxyData &oldProxyData, + DataShareObserver::ChangeType &type, bool isInstallEvent = false); + static int32_t Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo, + DataShareObserver::ChangeType &type, bool isInstallEvent = false); + static bool VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data); + static bool VerifySelfAccess(const BundleInfo &callerBundleInfo, + const ProxyDataNode &data, bool isInstallEvent = false); + bool HasVersion() const override; + int GetVersion() const override; + std::string GetValue() const override; + +private: + static bool CheckAllowList(const std::string callerBundleName, DataShareProxyData proxyData); + ProxyDataNode value; +}; + +class ProxyDataManager { +public: + static ProxyDataManager &GetInstance(); + void OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + void OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + +private: + bool GetCrossAppSharedConfig(const std::string &bundleName, int32_t user, int32_t index, + std::vector &proxyDatas); +}; +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_PROXY_DATA_MANAGER_H diff --git a/services/distributeddataservice/service/data_share/data/published_data.cpp b/services/distributeddataservice/service/data_share/data/published_data.cpp index 0e73d871a..359db675e 100644 --- a/services/distributeddataservice/service/data_share/data/published_data.cpp +++ b/services/distributeddataservice/service/data_share/data/published_data.cpp @@ -170,7 +170,7 @@ void PublishedData::Delete(const std::string &bundleName, const int32_t userId) ZLOGE("db open failed"); return; } - auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, + auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, "{\"bundleName\":\"" + bundleName + "\", \"userId\": " + std::to_string(userId) + "}"); if (status != E_OK) { ZLOGE("db Delete failed, %{public}s %{public}d", bundleName.c_str(), status); @@ -209,9 +209,9 @@ void PublishedData::ClearAging() } if (data.timestamp < lastValidTime && PublishedDataSubscriberManager::GetInstance() .GetCount(PublishedDataKey(data.key, data.bundleName, data.subscriberId)) == 0) { - auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, + auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, Id(PublishedData::GenId(data.key, data.bundleName, data.subscriberId), data.userId)); - if (errorCode != E_OK) { + if (errorCode != E_OK) { ZLOGE("db Delete failed, %{public}s %{public}s", data.key.c_str(), data.bundleName.c_str()); } agingSize++; @@ -249,8 +249,8 @@ void PublishedData::UpdateTimestamp( return; } data.timestamp = now; - auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); - if (errorCode == E_OK) { + auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); + if (errorCode == E_OK) { ZLOGI("update timestamp %{private}s", data.key.c_str()); } } diff --git a/services/distributeddataservice/service/data_share/data_proxy_observer.h b/services/distributeddataservice/service/data_share/data_proxy_observer.h index 10a71f531..3c361f367 100644 --- a/services/distributeddataservice/service/data_share/data_proxy_observer.h +++ b/services/distributeddataservice/service/data_share/data_proxy_observer.h @@ -18,6 +18,7 @@ #include #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { @@ -32,6 +33,12 @@ public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataProxyPublishedDataObserver"); virtual void OnChangeFromPublishedData(PublishedDataChangeNode &changeNode) = 0; }; + +class IProxyDataObserver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IProxyDataObserver"); + virtual void OnChangeFromProxyData(std::vector &changeNode) = 0; +}; } // namespace DataShare } // namespace OHOS #endif // DATA_PROXY_OBSERVER_H diff --git a/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp b/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp index 9364e4ae2..db021d14d 100644 --- a/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp +++ b/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "ObserverProxy" #include "data_share_obs_proxy.h" #include "datashare_errno.h" +#include "dataproxy_handle_common.h" #include "itypes_util.h" #include "datashare_itypes_utils.h" @@ -198,6 +199,28 @@ void PublishedDataObserverProxy::OnChangeFromPublishedData(PublishedDataChangeNo return; } + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option); + if (result != ERR_NONE) { + ZLOGE("SendRequest error, result=%{public}d", result); + return; + } + ZLOGD("SendRequest ok, retval is %{public}d", reply.ReadInt32()); +} + +void ProxyDataObserverProxy::OnChangeFromProxyData(std::vector &changeInfo) +{ + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(PublishedDataObserverProxy::GetDescriptor())) { + return; + } + + if (!ITypesUtil::Marshal(parcel, changeInfo)) { + ZLOGE("failed to WriteParcelable changeNode "); + return; + } + MessageParcel reply; MessageOption option; int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option); diff --git a/services/distributeddataservice/service/data_share/data_share_obs_proxy.h b/services/distributeddataservice/service/data_share/data_share_obs_proxy.h index c6726d591..81846c1cc 100644 --- a/services/distributeddataservice/service/data_share/data_share_obs_proxy.h +++ b/services/distributeddataservice/service/data_share/data_share_obs_proxy.h @@ -45,5 +45,16 @@ public: private: static inline BrokerDelegator delegator_; }; + +class ProxyDataObserverProxy : public IRemoteProxy { +public: + explicit ProxyDataObserverProxy(const sptr& remote) + : IRemoteProxy(remote) {} + virtual ~ProxyDataObserverProxy() {} + void OnChangeFromProxyData(std::vector &changeNode) override; + +private: + static inline BrokerDelegator delegator_; +}; } // namespace OHOS::DataShare #endif // DATA_SHARE_OBS_PROXY_H diff --git a/services/distributeddataservice/service/data_share/data_share_profile_config.cpp b/services/distributeddataservice/service/data_share/data_share_profile_config.cpp index 623c11223..f8fe35004 100644 --- a/services/distributeddataservice/service/data_share/data_share_profile_config.cpp +++ b/services/distributeddataservice/service/data_share/data_share_profile_config.cpp @@ -134,6 +134,34 @@ bool ProfileInfo::Unmarshal(const json &node) return true; } +bool SerialDataShareProxyData::Marshal(json &node) const +{ + SetValue(node[GET_NAME(uri)], uri); + SetValue(node[GET_NAME(value)], value); + SetValue(node[GET_NAME(allowList)], allowList); + return true; +} + +bool SerialDataShareProxyData::Unmarshal(const json &node) +{ + bool ret = GetValue(node, GET_NAME(uri), uri); + GetValue(node, GET_NAME(value), value); + GetValue(node, GET_NAME(allowList), allowList); + return ret; +} + +bool ProxyDataProfileInfo::Marshal(json &node) const +{ + SetValue(node[GET_NAME(crossAppSharedConfig)], dataShareProxyDatas); + return true; +} + +bool ProxyDataProfileInfo::Unmarshal(const json &node) +{ + bool ret = GetValue(node, GET_NAME(crossAppSharedConfig), dataShareProxyDatas); + return ret; +} + std::pair DataShareProfileConfig::GetDataProperties( const std::vector &metadata, const std::string &resPath, const std::string &hapPath, const std::string &name) @@ -150,6 +178,27 @@ std::pair DataShareProfileConfig::GetDataProperties( return std::make_pair(SUCCESS, profileInfo); } +std::pair> DataShareProfileConfig::GetCrossAppSharedConfig( + const std::string &resource, const std::string &resPath, const std::string &hapPath) +{ + std::vector serialProxyDatas; + ProxyDataProfileInfo profileInfo; + std::string resourcePath = !hapPath.empty() ? hapPath : resPath; + + std::shared_ptr resMgr = InitResMgr(resourcePath); + if (resMgr == nullptr) { + return std::make_pair(ERROR, serialProxyDatas); + } + std::string info = GetResFromResMgr(resource, *resMgr, hapPath); + if (info.empty()) { + return std::make_pair(NOT_FOUND, serialProxyDatas); + } + if (!profileInfo.Unmarshall(info)) { + return std::make_pair(ERROR, serialProxyDatas); + } + return std::make_pair(SUCCESS, profileInfo.dataShareProxyDatas); +} + std::string DataShareProfileConfig::GetProfileInfoByMetadata(const std::vector &metadata, const std::string &resourcePath, const std::string &hapPath, const std::string &name) { @@ -207,7 +256,7 @@ std::string DataShareProfileConfig::GetResFromResMgr( std::unique_ptr fileContent = nullptr; size_t len = 0; RState ret = resMgr.GetProfileDataByName(profileName.c_str(), len, fileContent); - if (ret != SUCCESS || fileContent == nullptr) { + if (ret != RState::SUCCESS || fileContent == nullptr) { ZLOGE("failed, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); return profileInfo; } @@ -225,7 +274,7 @@ std::string DataShareProfileConfig::GetResFromResMgr( // hap is decompressed status, get file path then read file. std::string resPath; RState ret = resMgr.GetProfileByName(profileName.c_str(), resPath); - if (ret != SUCCESS) { + if (ret != RState::SUCCESS) { ZLOGE("profileName not found, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); return profileInfo; } diff --git a/services/distributeddataservice/service/data_share/data_share_profile_config.h b/services/distributeddataservice/service/data_share/data_share_profile_config.h index 781cd5f34..7f7d04459 100644 --- a/services/distributeddataservice/service/data_share/data_share_profile_config.h +++ b/services/distributeddataservice/service/data_share/data_share_profile_config.h @@ -22,6 +22,7 @@ #include #include "bundle_info.h" +#include "dataproxy_handle_common.h" #include "resource_manager.h" #include "serializable/serializable.h" @@ -68,6 +69,25 @@ struct ProfileInfo : public DistributedData::Serializable { bool Unmarshal(const json &node) override; }; +struct SerialDataShareProxyData : public DistributedData::Serializable { + SerialDataShareProxyData() = default; + SerialDataShareProxyData(const std::string &uri, const DataProxyValue &value, + const std::vector &allowList) + : uri(uri), value(value), allowList(allowList) {} + virtual ~SerialDataShareProxyData() = default; + std::string uri; + DataProxyValue value; + std::vector allowList; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + +struct ProxyDataProfileInfo : public DistributedData::Serializable { + std::vector dataShareProxyDatas; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + enum AccessCrossMode : uint8_t { USER_UNDEFINED, USER_SHARED, @@ -86,6 +106,8 @@ public: std::map &profileInfos); static std::pair GetDataProperties(const std::vector &metadata, const std::string &resPath, const std::string &hapPath, const std::string &name); + static std::pair> GetCrossAppSharedConfig(const std::string &resource, + const std::string &resPath, const std::string &hapPath); static AccessCrossMode GetAccessCrossMode(const ProfileInfo &profileInfo, const std::string &tableUri, const std::string &storeUri); private: diff --git a/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index 97757d4da..ae0f308d0 100644 --- a/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -59,6 +59,10 @@ #include "xcollie.h" #include "log_debug.h" #include "parameters.h" +#include "dataproxy_handle_common.h" +#include "proxy_data_manager.h" +#include "datashare_observer.h" +#include "subscriber_managers/proxy_data_subscriber_manager.h" namespace OHOS::DataShare { using FeatureSystem = DistributedData::FeatureSystem; @@ -977,6 +981,125 @@ int32_t DataShareServiceImpl::UnregisterObserver(const std::string &uri, return ERROR; } +bool DataShareServiceImpl::GetCallerBundleInfo(BundleInfo &callerBundleInfo) +{ + GetCallerInfo(callerBundleInfo.bundleName, callerBundleInfo.appIndex); + callerBundleInfo.userId = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + callerBundleInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [ret, callerAppIdentifier] = BundleMgrProxy::GetInstance()->GetCallerAppIdentifier( + callerBundleInfo.bundleName, callerBundleInfo.userId); + if (ret != 0) { + ZLOGE("Get caller appIdentifier failed, callerBundleName is %{public}s", callerBundleInfo.bundleName.c_str()); + return false; + } + callerBundleInfo.appIdentifier = callerAppIdentifier; + return true; +} + +std::vector DataShareServiceImpl::PublishProxyData(const std::vector &proxyDatas, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + std::vector keys; + std::map> datas; + for (const auto &data : proxyDatas) { + DataShareObserver::ChangeType type; + auto ret = PublishedProxyData::Upsert(data, callerBundleInfo, type); + result.emplace_back(data.uri_, static_cast(ret)); + if (ret == SUCCESS && + (type == DataShareObserver::ChangeType::INSERT || type == DataShareObserver::ChangeType::UPDATE)) { + keys.emplace_back(data.uri_, callerBundleInfo.bundleName); + datas[type].emplace_back(data); + } + } + ProxyDataSubscriberManager::GetInstance().Emit(keys, datas, callerBundleInfo.userId); + return result; +} + +std::vector DataShareServiceImpl::DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + std::vector keys; + std::map> datas; + for (const auto &uri : uris) { + DataShareProxyData oldProxyData; + DataShareObserver::ChangeType type; + auto ret = PublishedProxyData::Delete(uri, callerBundleInfo, oldProxyData, type); + result.emplace_back(uri, static_cast(ret)); + if (ret == SUCCESS && type == DataShareObserver::ChangeType::DELETE) { + keys.emplace_back(uri, callerBundleInfo.bundleName); + datas[type].emplace_back(oldProxyData); + } + } + ProxyDataSubscriberManager::GetInstance().Emit(keys, datas, callerBundleInfo.userId); + return result; +} + +std::vector DataShareServiceImpl::GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + DataShareProxyData proxyData; + for (const auto &uri : uris) { + auto ret = PublishedProxyData::Query(uri, callerBundleInfo, proxyData); + result.emplace_back(uri, static_cast(ret), proxyData.value_, proxyData.allowList_); + } + return result; +} + +std::vector DataShareServiceImpl::SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) +{ + std::vector results = {}; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return results; + } + for (const auto &uri : uris) { + DataShareProxyData proxyData; + DataProxyErrorCode ret = + static_cast(PublishedProxyData::Query(uri, callerBundleInfo, proxyData)); + if (ret == SUCCESS) { + ret = ProxyDataSubscriberManager::GetInstance().Add( + ProxyDataKey(uri, callerBundleInfo.bundleName), observer, callerBundleInfo.bundleName, + callerBundleInfo.appIdentifier, callerBundleInfo.userId); + } + results.emplace_back(uri, ret); + } + return results; +} + +std::vector DataShareServiceImpl::UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::string bundleName; + GetCallerBundleName(bundleName); + int32_t userId = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + std::vector result = {}; + for (const auto &uri : uris) { + auto ret = ProxyDataSubscriberManager::GetInstance().Delete(ProxyDataKey(uri, bundleName), userId); + result.emplace_back(uri, ret); + } + return result; +} + bool DataShareServiceImpl::VerifyAcrossAccountsPermission(int32_t currentUserId, int32_t visitedUserId, const std::string &acrossAccountsPermission, uint32_t callerTokenId) { @@ -1104,6 +1227,8 @@ void DataShareServiceImpl::InitSubEvent() } EventFwk::MatchingSkills matchingSkills; matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON); auto sysEventSubscriber = std::make_shared(subscribeInfo); diff --git a/services/distributeddataservice/service/data_share/data_share_service_impl.h b/services/distributeddataservice/service/data_share/data_share_service_impl.h index 8cc9ca889..d39912924 100644 --- a/services/distributeddataservice/service/data_share/data_share_service_impl.h +++ b/services/distributeddataservice/service/data_share/data_share_service_impl.h @@ -91,6 +91,16 @@ public: const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) override; std::pair DeleteEx(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicate) override; + std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) override; + std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + std::vector GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + std::vector SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) override; + std::vector UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; private: class SystemAbilityStatusChangeListener; using StaticActs = DistributedData::StaticActs; @@ -142,6 +152,7 @@ private: const std::vector &allowLists); bool VerifyPermission(const std::string &bundleName, const std::string &permission, bool isFromExtension, const int32_t tokenId); + bool GetCallerBundleInfo(BundleInfo &callerBundleInfo); static Factory factory_; static constexpr int32_t ERROR = -1; static constexpr int32_t ERROR_PERMISSION_DENIED = -2; diff --git a/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index cd73d4328..7ebf32f0e 100644 --- a/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "datashare_errno.h" #define LOG_TAG "DataShareServiceStub" #include "data_share_service_stub.h" @@ -29,6 +30,7 @@ #include "qos.h" #include "uri_utils.h" #include "utils/anonymous.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { @@ -457,5 +459,91 @@ void DataShareServiceStub::SetServiceReady() { isReady_.store(true); } + +int32_t DataShareServiceStub::OnPublishProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector proxyDatas; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, proxyDatas, config)) { + ZLOGE("OnPublishProxyData unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = PublishProxyData(proxyDatas, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnDeleteProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris, config)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = DeleteProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnGetProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris, config)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = GetProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnSubscribeProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + auto remoteObj = data.ReadRemoteObject(); + sptr observer = new (std::nothrow)ProxyDataObserverProxy(remoteObj); + if (observer == nullptr) { + ZLOGE("observer is nullptr"); + return DATA_SHARE_ERROR; + } + std::vector results = SubscribeProxyData(uris, config, observer); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("ITypesUtil::Marshal(reply, results) failed"); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return 0; +} + +int32_t DataShareServiceStub::OnUnsubscribeProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = UnsubscribeProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("ITypesUtil::Marshal(reply, results) failed"); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return 0; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/data_share_service_stub.h b/services/distributeddataservice/service/data_share/data_share_service_stub.h index 47603e959..27f1690ff 100644 --- a/services/distributeddataservice/service/data_share/data_share_service_stub.h +++ b/services/distributeddataservice/service/data_share/data_share_service_stub.h @@ -52,6 +52,11 @@ private: int32_t OnInsertEx(MessageParcel& data, MessageParcel& reply); int32_t OnUpdateEx(MessageParcel& data, MessageParcel& reply); int32_t OnDeleteEx(MessageParcel& data, MessageParcel& reply); + int32_t OnPublishProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnDeleteProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnGetProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnSubscribeProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnUnsubscribeProxyData(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (DataShareServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[DATA_SHARE_SERVICE_CMD_MAX] = { &DataShareServiceStub::OnQuery, @@ -75,7 +80,12 @@ private: &DataShareServiceStub::OnUnregisterObserver, &DataShareServiceStub::OnInsertEx, &DataShareServiceStub::OnDeleteEx, - &DataShareServiceStub::OnUpdateEx}; + &DataShareServiceStub::OnUpdateEx, + &DataShareServiceStub::OnPublishProxyData, + &DataShareServiceStub::OnDeleteProxyData, + &DataShareServiceStub::OnGetProxyData, + &DataShareServiceStub::OnSubscribeProxyData, + &DataShareServiceStub::OnUnsubscribeProxyData}; static constexpr int SLEEP_TIME = 300; static constexpr int TRY_TIMES = 5; std::atomic isReady_ = false; diff --git a/services/distributeddataservice/service/data_share/idata_share_service.h b/services/distributeddataservice/service/data_share/idata_share_service.h index 05e1fd155..9f08d74c5 100644 --- a/services/distributeddataservice/service/data_share/idata_share_service.h +++ b/services/distributeddataservice/service/data_share/idata_share_service.h @@ -25,6 +25,7 @@ #include "datashare_template.h" #include "data_proxy_observer.h" #include "iremote_object.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { class IDataShareService { @@ -53,6 +54,11 @@ public: DATA_SHARE_SERVICE_CMD_INSERTEX, DATA_SHARE_SERVICE_CMD_DELETEEX, DATA_SHARE_SERVICE_CMD_UPDATEEX, + DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH, + DATA_SHARE_SERVICE_CMD_PROXY_DELETE, + DATA_SHARE_SERVICE_CMD_PROXY_GET, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA, DATA_SHARE_SERVICE_CMD_MAX, DATA_SHARE_SERVICE_CMD_QUERY_SYSTEM = DATA_SHARE_CMD_SYSTEM_CODE, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE_SYSTEM, @@ -117,6 +123,16 @@ public: const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) = 0; virtual std::pair DeleteEx(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicate) = 0; -}; + virtual std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) = 0; + virtual std::vector UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + }; } // namespace OHOS::DataShare #endif // DISTRIBUTEDDATAFWK_IDATA_SHARE_SERVICE_H diff --git a/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp b/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp new file mode 100644 index 000000000..85a854797 --- /dev/null +++ b/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ProxyDataSubscriberManager" + +#include "proxy_data_subscriber_manager.h" + +#include "dataproxy_handle_common.h" +#include "ipc_skeleton.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "uri_utils.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { +ProxyDataSubscriberManager &ProxyDataSubscriberManager::GetInstance() +{ + static ProxyDataSubscriberManager manager; + return manager; +} + +DataProxyErrorCode ProxyDataSubscriberManager::Add(const ProxyDataKey &key, const sptr &observer, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId) +{ + ProxyDataCache_.Compute( + key, [&observer, bundleName, callerAppIdentifier, userId](const ProxyDataKey &key, + std::vector &value) { + ZLOGI("add proxy data subscriber, uri %{public}s", + DistributedData::Anonymous::Change(key.uri).c_str()); + value.emplace_back(observer, IPCSkeleton::GetCallingTokenID(), bundleName, callerAppIdentifier, userId); + return true; + }); + return SUCCESS; +} + +DataProxyErrorCode ProxyDataSubscriberManager::Delete(const ProxyDataKey &key, const int32_t &userId) +{ + auto result = + ProxyDataCache_.ComputeIfPresent(key, [&userId](const auto &key, + std::vector &value) { + for (auto it = value.begin(); it != value.end();) { + if (it->callerTokenId == IPCSkeleton::GetCallingTokenID() && it->userId == userId) { + ZLOGI("delete proxy data subscriber, uri %{public}s", + DistributedData::Anonymous::Change(key.uri).c_str()); + it = value.erase(it); + } + } + return !value.empty(); + }); + return result ? SUCCESS : URI_NOT_EXIST; +} + +bool ProxyDataSubscriberManager::CheckAllowList(const std::vector &allowList, + const std::string &callerAppIdentifier) +{ + for (const auto &item : allowList) { + if (callerAppIdentifier == item || item == ALLOW_ALL) { + return true; + } + } + return false; +} + +// if arg observer is not null, notify that observer only; otherwise notify all observers +void ProxyDataSubscriberManager::Emit(const std::vector &keys, + const std::map> &datas, const int32_t &userId) +{ + std::map, std::vector> callbacks; + for (auto typeIt = datas.begin(); typeIt != datas.end(); ++typeIt) { + auto type = typeIt->first; + for (const auto &data : typeIt->second) { + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(data.uri_, bundleName); + auto it = ProxyDataCache_.Find(ProxyDataKey(data.uri_, bundleName)); + if (!it.first) { + continue; + } + auto &observers = it.second; + std::for_each(observers.begin(), observers.end(), + [&callbacks, data, userId, bundleName, &type, this](const auto &obs) { + if ((CheckAllowList(data.allowList_, obs.callerAppIdentifier) || + bundleName == obs.bundleName) && obs.userId == userId) { + callbacks[obs.observer].emplace_back(type, data.uri_, data.value_); + } else { + ZLOGE("no permission to receive notification"); + } + }); + } + } + for (auto &[callback, changeInfo] : callbacks) { + if (callback != nullptr) { + callback->OnChangeFromProxyData(changeInfo); + } + } +} + +void ProxyDataSubscriberManager::Clear() +{ + ProxyDataCache_.Clear(); +} + +ProxyDataKey::ProxyDataKey(const std::string &uri, const std::string &bundle) + : uri(uri), bundleName(bundle) +{ + /* private published data can use key as simple uri */ + /* etc: datashareproxy://{bundleName}/meeting can use meeting replaced */ + /* if key is normal uri, bundleName is from uri */ + if (URIUtils::IsDataProxyURI(uri)) { + URIUtils::GetBundleNameFromProxyURI(uri, bundleName); + } +} + +bool ProxyDataKey::operator<(const ProxyDataKey &rhs) const +{ + return uri < rhs.uri; +} + +bool ProxyDataKey::operator>(const ProxyDataKey &rhs) const +{ + return rhs < *this; +} + +bool ProxyDataKey::operator<=(const ProxyDataKey &rhs) const +{ + return !(rhs < *this); +} + +bool ProxyDataKey::operator>=(const ProxyDataKey &rhs) const +{ + return !(*this < rhs); +} + +bool ProxyDataKey::operator==(const ProxyDataKey &rhs) const +{ + return uri == rhs.uri && bundleName == rhs.bundleName; +} + +bool ProxyDataKey::operator!=(const ProxyDataKey &rhs) const +{ + return !(rhs == *this); +} + +ProxyDataSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, + const uint32_t &callerTokenId, const std::string &bundleName, + const std::string &callerAppIdentifier, const int32_t &userId) : observer(observer), + callerTokenId(callerTokenId), bundleName(bundleName), callerAppIdentifier(callerAppIdentifier), userId(userId) +{ +} +} // namespace OHOS::DataShare diff --git a/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h b/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h new file mode 100644 index 000000000..e2e7135ff --- /dev/null +++ b/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H +#define DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H + +#include "concurrent_map.h" +#include "data_proxy_observer.h" +#include "dataproxy_handle_common.h" + +namespace OHOS::DataShare { +struct ProxyDataKey { + ProxyDataKey(const std::string &uri, const std::string &bundleName); + bool operator<(const ProxyDataKey &rhs) const; + bool operator>(const ProxyDataKey &rhs) const; + bool operator<=(const ProxyDataKey &rhs) const; + bool operator>=(const ProxyDataKey &rhs) const; + bool operator==(const ProxyDataKey &rhs) const; + bool operator!=(const ProxyDataKey &rhs) const; + std::string uri; + std::string bundleName; +}; + +class ProxyDataSubscriberManager { +public: + static ProxyDataSubscriberManager &GetInstance(); + DataProxyErrorCode Add(const ProxyDataKey &key, const sptr &observer, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId); + DataProxyErrorCode Delete(const ProxyDataKey &key, const int32_t &userId); + void Emit(const std::vector &keys, const std::map> &datas, const int32_t &userId); + void Clear(); + +private: +struct ObserverNode { + ObserverNode(const sptr &observer, const uint32_t &callerTokenId, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId = 0); + sptr observer; + uint32_t callerTokenId; + std::string bundleName; + std::string callerAppIdentifier; + int32_t userId = 0; + }; + + bool CheckAllowList(const std::vector &allowList, + const std::string &callerAppIdentifier); + ProxyDataSubscriberManager() = default; + ConcurrentMap> ProxyDataCache_; +}; +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H diff --git a/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp b/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp index b0fe15ee2..bade5009a 100644 --- a/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp +++ b/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp @@ -18,19 +18,41 @@ #include "common_event_manager.h" #include "common_event_support.h" #include "log_print.h" +#include "proxy_data_manager.h" namespace OHOS::DataShare { SysEventSubscriber::SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo& info) : CommonEventSubscriber(info) { - callbacks_ = { { EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, - &SysEventSubscriber::OnBMSReady } }; + callbacks_ = { + { EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, + &SysEventSubscriber::OnBMSReady } + }; + installCallbacks_ = { + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED, + &SysEventSubscriber::OnAppInstall }, + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, + &SysEventSubscriber::OnAppUninstall } + }; } void SysEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& event) { EventFwk::Want want = event.GetWant(); std::string action = want.GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED || + action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED) { + std::string bundleName = want.GetElement().GetBundleName(); + int32_t userId = want.GetIntParam(USER_ID, -1); + int32_t appIndex = want.GetIntParam(APP_INDEX, 0); + bool isCrossAppSharedConfig = want.GetBoolParam(CROSS_APP_SHARED_CONFIG, false); + ZLOGI("bundleName:%{public}s, user:%{public}d, appIndex:%{public}d, isCrossAppSharedConfig:%{public}d", + bundleName.c_str(), userId, appIndex, isCrossAppSharedConfig); + auto installEvent = installCallbacks_.find(action); + if (installEvent != installCallbacks_.end()) { + (this->*(installEvent->second))(bundleName, userId, appIndex, isCrossAppSharedConfig); + } + } auto it = callbacks_.find(action); if (it != callbacks_.end()) { (this->*(it->second))(); @@ -42,6 +64,24 @@ void SysEventSubscriber::OnBMSReady() NotifyDataShareReady(); } +void SysEventSubscriber::OnAppInstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s installed, userId: %{public}d, appIndex: %{public}d", bundleName.c_str(), userId, appIndex); + uint32_t tokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex); + if (isCrossAppSharedConfig) { + ProxyDataManager::GetInstance().OnAppInstall(bundleName, userId, appIndex, tokenId); + } +} + +void SysEventSubscriber::OnAppUninstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s uninstalled, userId: %{public}d, appIndex: %{public}d", bundleName.c_str(), userId, appIndex); + uint32_t tokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex); + ProxyDataManager::GetInstance().OnAppUninstall(bundleName, userId, appIndex, tokenId); +} + void SysEventSubscriber::NotifyDataShareReady() { AAFwk::Want want; diff --git a/services/distributeddataservice/service/data_share/sys_event_subscriber.h b/services/distributeddataservice/service/data_share/sys_event_subscriber.h index b266387cc..214f575d8 100644 --- a/services/distributeddataservice/service/data_share/sys_event_subscriber.h +++ b/services/distributeddataservice/service/data_share/sys_event_subscriber.h @@ -23,14 +23,24 @@ namespace OHOS::DataShare { class SysEventSubscriber : public EventFwk::CommonEventSubscriber { public: using SysEventCallback = void (SysEventSubscriber::*)(); + using InstallEventCallback = void (SysEventSubscriber::*)(const std::string &bundleName, + int32_t userId, int32_t appIndex, bool isCrossAppSharedConfig); explicit SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info); ~SysEventSubscriber() {} void OnReceiveEvent(const EventFwk::CommonEventData& event) override; void OnBMSReady(); + void OnAppInstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, bool isCrossAppSharedConfig); + void OnAppUninstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, bool isCrossAppSharedConfig); private: void NotifyDataShareReady(); std::map callbacks_; + std::map installCallbacks_; + static constexpr const char *USER_ID = "userId"; + static constexpr const char *APP_INDEX = "appIndex"; + static constexpr const char* CROSS_APP_SHARED_CONFIG = "crossAppSharedConfig"; }; } #endif \ No newline at end of file diff --git a/services/distributeddataservice/service/test/BUILD.gn b/services/distributeddataservice/service/test/BUILD.gn index 2fbe7f6eb..5926d2cd9 100644 --- a/services/distributeddataservice/service/test/BUILD.gn +++ b/services/distributeddataservice/service/test/BUILD.gn @@ -939,6 +939,7 @@ ohos_unittest("DataShareServiceImplTest") { "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", "${data_service_path}/service/data_share/common/kv_delegate.cpp", "${data_service_path}/service/data_share/common/rdb_delegate.cpp", "${data_service_path}/service/data_share/common/scheduler_manager.cpp", @@ -971,6 +972,7 @@ ohos_unittest("DataShareServiceImplTest") { "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", "${data_service_path}/service/data_share/sys_event_subscriber.cpp", diff --git a/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn b/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn index d365536bd..227596c5f 100644 --- a/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn +++ b/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn @@ -59,6 +59,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", "${data_service_path}/service/data_share/common/rdb_delegate.cpp", "${data_service_path}/service/data_share/common/scheduler_manager.cpp", "${data_service_path}/service/data_share/common/seq_strategy.cpp", @@ -90,6 +91,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", "${data_service_path}/service/data_share/sys_event_subscriber.cpp", -- Gitee