1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "datashare_helper.h"
17 #include "datashare_helper_impl.h"
18
19 #include "concurrent_map.h"
20 #include "data_ability_observer_interface.h"
21 #include "data_ability_observer_stub.h"
22 #include "dataobs_mgr_client.h"
23 #include "datashare_log.h"
24
25 namespace OHOS {
26 namespace DataShare {
27 using namespace AppExecFwk;
28 namespace {
29 static constexpr const char *SCHEME_DATASHARE = "datashare";
30 static constexpr const char *SCHEME_DATASHARE_PROXY = "datashareproxy";
31 static constexpr const char *DATA_SHARE_PREFIX = "datashare:///";
32 static constexpr const char *FILE_PREFIX = "file://";
33 } // namespace
34 class ObserverImpl : public AAFwk::DataAbilityObserverStub {
35 public:
ObserverImpl(const std::shared_ptr<DataShareObserver> dataShareObserver)36 explicit ObserverImpl(const std::shared_ptr<DataShareObserver> dataShareObserver)
37 : dataShareObserver_(dataShareObserver){};
38 void OnChange();
39 void OnChangeExt(const AAFwk::ChangeInfo &info);
40 static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info);
41 static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info);
42 static sptr<ObserverImpl> GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer);
43 static bool FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer);
44 static bool DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer);
45 private:
46 struct ObserverParam {
47 sptr<ObserverImpl> obs_;
48 std::list<Uri> uris_;
49 };
50 std::shared_ptr<DataShareObserver> dataShareObserver_;
51 static ConcurrentMap<DataShareObserver *, ObserverParam> observers_;
52 };
53
54 ConcurrentMap<DataShareObserver *, ObserverImpl::ObserverParam> ObserverImpl::observers_;
55
TransferUriPrefix(const std::string & originPrefix,const std::string & replacedPrefix,const std::string & originUriStr)56 std::string DataShareHelper::TransferUriPrefix(const std::string &originPrefix, const std::string &replacedPrefix,
57 const std::string &originUriStr)
58 {
59 if (originUriStr.find(originPrefix) != 0) {
60 return originUriStr;
61 }
62 return replacedPrefix + originUriStr.substr(originPrefix.length());
63 }
64
65 /**
66 * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
67 * between the ability using the Data template (data share for short) and the associated client process in
68 * a DataShareHelper instance.
69 *
70 * @param token Indicates the System token.
71 * @param strUri Indicates the database table or disk file to operate.
72 *
73 * @return Returns the created DataShareHelper instance.
74 */
Creator(const sptr<IRemoteObject> & token,const std::string & strUri)75 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(const sptr<IRemoteObject> &token, const std::string &strUri)
76 {
77 if (token == nullptr) {
78 LOG_ERROR("token == nullptr");
79 return nullptr;
80 }
81
82 std::string replacedUriStr = TransferUriPrefix(FILE_PREFIX, DATA_SHARE_PREFIX, strUri);
83 Uri uri(replacedUriStr);
84
85 if (uri.GetScheme() != SCHEME_DATASHARE) {
86 LOG_ERROR("the Scheme is not datashare, Scheme: %{public}s", uri.GetScheme().c_str());
87 return nullptr;
88 }
89
90 if (uri.GetQuery().find("Proxy=true") != std::string::npos) {
91 return CreateServiceHelper();
92 }
93 return CreateExtHelper(uri, token);
94 }
95
Creator(const string & strUri,const CreateOptions & options,const std::string & bundleName)96 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(const string &strUri, const CreateOptions &options,
97 const std::string &bundleName)
98 {
99 Uri uri(strUri);
100 if (!options.isProxy_ && options.token_ == nullptr) {
101 LOG_ERROR("token is nullptr");
102 return nullptr;
103 }
104 if (uri.GetScheme() != SCHEME_DATASHARE_PROXY) {
105 LOG_ERROR("the Scheme is not datashareproxy, Scheme: %{public}s", uri.GetScheme().c_str());
106 return nullptr;
107 }
108 if (options.isProxy_) {
109 return CreateServiceHelper(bundleName);
110 }
111 return CreateExtHelper(uri, options.token_);
112 }
113
CreateServiceHelper(const std::string & bundleName)114 std::shared_ptr<DataShareHelper> DataShareHelper::CreateServiceHelper(const std::string &bundleName)
115 {
116 DataShareManagerImpl::GetInstance().SetBundleName(bundleName);
117 if (DataShareManagerImpl::GetInstance().GetServiceProxy() == nullptr) {
118 LOG_ERROR("service proxy is nullptr.");
119 return nullptr;
120 }
121 return std::make_shared<DataShareHelperImpl>();
122 }
123
CreateExtHelper(Uri & uri,const sptr<IRemoteObject> & token)124 std::shared_ptr<DataShareHelper> DataShareHelper::CreateExtHelper(Uri &uri, const sptr<IRemoteObject> &token)
125 {
126 sptr<DataShareConnection> connection = new (std::nothrow) DataShareConnection(uri, token);
127 if (connection == nullptr) {
128 LOG_ERROR("Create DataShareConnection failed.");
129 return nullptr;
130 }
131 auto dataShareConnection =
132 std::shared_ptr<DataShareConnection>(connection.GetRefPtr(), [holder = connection](const auto *) {
133 holder->DisconnectDataShareExtAbility();
134 });
135 if (dataShareConnection->GetDataShareProxy(uri, token) == nullptr) {
136 LOG_ERROR("connect failed");
137 return nullptr;
138 }
139 return std::make_shared<DataShareHelperImpl>(uri, token, dataShareConnection);
140 }
141
142 /**
143 * Registers an observer to DataObsMgr specified by the given Uri.
144 *
145 * @param uri, Indicates the path of the data to operate.
146 * @param dataObserver, Indicates the DataShareObserver object.
147 * @param isDescendants, Indicates the Whether to note the change of descendants.
148 */
RegisterObserverExt(const Uri & uri,std::shared_ptr<DataShareObserver> dataObserver,bool isDescendants)149 void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver,
150 bool isDescendants)
151 {
152 LOG_INFO("Start");
153 if (dataObserver == nullptr) {
154 LOG_ERROR("dataObserver is nullptr");
155 return;
156 }
157 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
158 if (obsMgrClient == nullptr) {
159 LOG_ERROR("get DataObsMgrClient failed");
160 return;
161 }
162 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
163 if (obs == nullptr) {
164 LOG_ERROR("new ObserverImpl failed");
165 return;
166 }
167 ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants);
168 if (ret != ERR_OK) {
169 ObserverImpl::DeleteObserver(uri, dataObserver);
170 LOG_ERROR("RegisterObserverExt failed");
171 }
172 }
173
174 /**
175 * Deregisters an observer used for DataObsMgr specified by the given Uri.
176 *
177 * @param uri, Indicates the path of the data to operate.
178 * @param dataObserver, Indicates the DataShareObserver object.
179 */
UnregisterObserverExt(const Uri & uri,std::shared_ptr<DataShareObserver> dataObserver)180 void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver)
181 {
182 LOG_INFO("Start");
183 if (dataObserver == nullptr) {
184 LOG_ERROR("dataObserver is nullptr");
185 return;
186 }
187 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
188 if (obsMgrClient == nullptr) {
189 LOG_ERROR("get DataObsMgrClient failed");
190 return;
191 }
192
193 if (!ObserverImpl::FindObserver(uri, dataObserver)) {
194 LOG_ERROR("observer not exit!");
195 return;
196 }
197
198 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
199 if (obs == nullptr) {
200 LOG_ERROR("new ObserverImpl failed");
201 return;
202 }
203 ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs);
204 if (ret != ERR_OK) {
205 LOG_ERROR("UnregisterObserverExt failed");
206 return;
207 }
208 ObserverImpl::DeleteObserver(uri, dataObserver);
209 }
210
211 /**
212 * Notifies the registered observers of a change to the data resource specified by Uris.
213 *
214 * @param changeInfo Indicates the info of the data to operate.
215 */
NotifyChangeExt(const DataShareObserver::ChangeInfo & changeInfo)216 void DataShareHelper::NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo)
217 {
218 LOG_INFO("Start");
219
220 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
221 if (obsMgrClient == nullptr) {
222 LOG_ERROR("get DataObsMgrClient failed");
223 return;
224 }
225
226 ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo));
227 if (ret != ERR_OK) {
228 LOG_ERROR("NotifyChangeExt failed");
229 }
230 }
231
OnChange()232 void ObserverImpl::OnChange() {}
233
OnChangeExt(const AAFwk::ChangeInfo & info)234 void ObserverImpl::OnChangeExt(const AAFwk::ChangeInfo &info)
235 {
236 dataShareObserver_->OnChange(ConvertInfo(info));
237 }
238
ConvertInfo(const AAFwk::ChangeInfo & info)239 DataShareObserver::ChangeInfo ObserverImpl::ConvertInfo(const AAFwk::ChangeInfo &info)
240 {
241 DataShareObserver::ChangeInfo changeInfo;
242 changeInfo.changeType_ = static_cast<const DataShareObserver::ChangeType>(info.changeType_);
243 changeInfo.uris_ = std::move(info.uris_);
244 changeInfo.data_ = info.data_;
245 changeInfo.size_ = info.size_;
246 return changeInfo;
247 }
248
ConvertInfo(const DataShareObserver::ChangeInfo & info)249 AAFwk::ChangeInfo ObserverImpl::ConvertInfo(const DataShareObserver::ChangeInfo &info)
250 {
251 AAFwk::ChangeInfo changeInfo;
252 changeInfo.changeType_ = static_cast<const AAFwk::ChangeInfo::ChangeType>(info.changeType_);
253 changeInfo.uris_ = std::move(info.uris_);
254 changeInfo.data_ = const_cast<void*>(info.data_);
255 changeInfo.size_ = info.size_;
256 return changeInfo;
257 }
258
GetObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)259 sptr<ObserverImpl> ObserverImpl::GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
260 {
261 sptr<ObserverImpl> result = nullptr;
262 observers_.Compute(observer.get(), [&result, &uri, &observer](const auto &key, auto &value) {
263 if (value.obs_ == nullptr) {
264 value.obs_ = new (std::nothrow) ObserverImpl(observer);
265 value.uris_.push_back(uri);
266 } else {
267 auto it = std::find(value.uris_.begin(), value.uris_.end(), uri);
268 if (it == value.uris_.end()) {
269 value.uris_.push_back(uri);
270 }
271 }
272
273 result = value.obs_;
274 return result != nullptr;
275 });
276
277 return result;
278 }
279
FindObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)280 bool ObserverImpl::FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
281 {
282 auto result = observers_.Find(observer.get());
283 if (result.first) {
284 auto it = std::find(result.second.uris_.begin(), result.second.uris_.end(), uri);
285 if (it == result.second.uris_.end()) {
286 return false;
287 }
288 }
289 return result.first;
290 }
291
DeleteObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)292 bool ObserverImpl::DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
293 {
294 return observers_.ComputeIfPresent(observer.get(), [&uri](auto &key, auto &value) {
295 value.uris_.remove_if([&uri](const auto &value) {
296 return uri == value;
297 });
298 return !value.uris_.empty();
299 });
300 }
301 } // namespace DataShare
302 } // namespace OHOS