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 "ProxyDataSubscriberManager"
17
18 #include "proxy_data_subscriber_manager.h"
19
20 #include "dataproxy_handle_common.h"
21 #include "ipc_skeleton.h"
22 #include "log_print.h"
23 #include "proxy_data_manager.h"
24 #include "utils.h"
25 #include "utils/anonymous.h"
26
27 namespace OHOS::DataShare {
GetInstance()28 ProxyDataSubscriberManager &ProxyDataSubscriberManager::GetInstance()
29 {
30 static ProxyDataSubscriberManager manager;
31 return manager;
32 }
33
Add(const ProxyDataKey & key,const sptr<IProxyDataObserver> & observer,const std::string & bundleName,const std::string & callerAppIdentifier,const int32_t & userId)34 DataProxyErrorCode ProxyDataSubscriberManager::Add(const ProxyDataKey &key, const sptr<IProxyDataObserver> &observer,
35 const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId)
36 {
37 auto callerTokenId = IPCSkeleton::GetCallingTokenID();
38 ProxyDataCache_.Compute(
39 key, [&observer, callerTokenId, bundleName, callerAppIdentifier, userId](const ProxyDataKey &key,
40 std::vector<ObserverNode> &value) {
41 ZLOGI("add proxy data subscriber, uri %{public}s",
42 URIUtils::Anonymous(key.uri).c_str());
43 value.emplace_back(observer, callerTokenId, bundleName, callerAppIdentifier, userId);
44 return true;
45 });
46 return SUCCESS;
47 }
48
Delete(const ProxyDataKey & key,const int32_t & userId)49 DataProxyErrorCode ProxyDataSubscriberManager::Delete(const ProxyDataKey &key, const int32_t &userId)
50 {
51 auto callerTokenId = IPCSkeleton::GetCallingTokenID();
52 auto result =
53 ProxyDataCache_.ComputeIfPresent(key, [&userId, callerTokenId](const auto &key,
54 std::vector<ObserverNode> &value) {
55 for (auto it = value.begin(); it != value.end();) {
56 if (it->callerTokenId == callerTokenId && it->userId == userId) {
57 ZLOGI("delete proxy data subscriber, uri %{public}s",
58 URIUtils::Anonymous(key.uri).c_str());
59 it = value.erase(it);
60 } else {
61 it++;
62 }
63 }
64 return !value.empty();
65 });
66 return result ? SUCCESS : URI_NOT_EXIST;
67 }
68
CheckAllowList(const std::vector<std::string> & allowList,const std::string & callerAppIdentifier)69 bool ProxyDataSubscriberManager::CheckAllowList(const std::vector<std::string> &allowList,
70 const std::string &callerAppIdentifier)
71 {
72 for (const auto &item : allowList) {
73 if (callerAppIdentifier == item || item == ALLOW_ALL) {
74 return true;
75 }
76 }
77 return false;
78 }
79
80 // if arg observer is not null, notify that observer only; otherwise notify all observers
Emit(const std::vector<ProxyDataKey> & keys,const std::map<DataShareObserver::ChangeType,std::vector<DataShareProxyData>> & datas,const int32_t & userId)81 void ProxyDataSubscriberManager::Emit(const std::vector<ProxyDataKey> &keys,
82 const std::map<DataShareObserver::ChangeType, std::vector<DataShareProxyData>> &datas, const int32_t &userId)
83 {
84 std::map<sptr<IProxyDataObserver>, std::vector<DataProxyChangeInfo>> callbacks;
85 for (auto typeIt = datas.begin(); typeIt != datas.end(); ++typeIt) {
86 auto type = typeIt->first;
87 for (const auto &data : typeIt->second) {
88 std::string bundleName;
89 URIUtils::GetBundleNameFromProxyURI(data.uri_, bundleName);
90 auto it = ProxyDataCache_.Find(ProxyDataKey(data.uri_, bundleName));
91 if (!it.first) {
92 continue;
93 }
94 auto &observers = it.second;
95 std::for_each(observers.begin(), observers.end(),
96 [&callbacks, data, userId, bundleName, &type, this](const auto &obs) {
97 if ((CheckAllowList(data.allowList_, obs.callerAppIdentifier) ||
98 bundleName == obs.bundleName) && obs.userId == userId) {
99 callbacks[obs.observer].emplace_back(type, data.uri_, data.value_);
100 } else {
101 ZLOGE("no permission to receive notification");
102 }
103 });
104 }
105 }
106 for (auto &[callback, changeInfo] : callbacks) {
107 if (callback != nullptr) {
108 callback->OnChangeFromProxyData(changeInfo);
109 }
110 }
111 }
112
Clear()113 void ProxyDataSubscriberManager::Clear()
114 {
115 ProxyDataCache_.Clear();
116 }
117
ProxyDataKey(const std::string & uri,const std::string & bundle)118 ProxyDataKey::ProxyDataKey(const std::string &uri, const std::string &bundle)
119 : uri(uri), bundleName(bundle)
120 {
121 /* private published data can use key as simple uri */
122 /* etc: datashareproxy://{bundleName}/meeting can use meeting replaced */
123 /* if key is normal uri, bundleName is from uri */
124 if (URIUtils::IsDataProxyURI(uri)) {
125 URIUtils::GetBundleNameFromProxyURI(uri, bundleName);
126 }
127 }
128
operator <(const ProxyDataKey & rhs) const129 bool ProxyDataKey::operator<(const ProxyDataKey &rhs) const
130 {
131 return uri < rhs.uri;
132 }
133
operator >(const ProxyDataKey & rhs) const134 bool ProxyDataKey::operator>(const ProxyDataKey &rhs) const
135 {
136 return rhs < *this;
137 }
138
operator <=(const ProxyDataKey & rhs) const139 bool ProxyDataKey::operator<=(const ProxyDataKey &rhs) const
140 {
141 return !(rhs < *this);
142 }
143
operator >=(const ProxyDataKey & rhs) const144 bool ProxyDataKey::operator>=(const ProxyDataKey &rhs) const
145 {
146 return !(*this < rhs);
147 }
148
operator ==(const ProxyDataKey & rhs) const149 bool ProxyDataKey::operator==(const ProxyDataKey &rhs) const
150 {
151 return uri == rhs.uri && bundleName == rhs.bundleName;
152 }
153
operator !=(const ProxyDataKey & rhs) const154 bool ProxyDataKey::operator!=(const ProxyDataKey &rhs) const
155 {
156 return !(rhs == *this);
157 }
158
ObserverNode(const sptr<IProxyDataObserver> & observer,const uint32_t & callerTokenId,const std::string & bundleName,const std::string & callerAppIdentifier,const int32_t & userId)159 ProxyDataSubscriberManager::ObserverNode::ObserverNode(const sptr<IProxyDataObserver> &observer,
160 const uint32_t &callerTokenId, const std::string &bundleName,
161 const std::string &callerAppIdentifier, const int32_t &userId) : observer(observer),
162 callerTokenId(callerTokenId), bundleName(bundleName), callerAppIdentifier(callerAppIdentifier), userId(userId)
163 {
164 }
165 } // namespace OHOS::DataShare
166