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 #define LOG_TAG "DataShareHelper"
16
17 #include "datashare_helper.h"
18 #include "datashare_helper_impl.h"
19
20 #include "adaptor.h"
21 #include "dataobs_mgr_client.h"
22 #include "datashare_errno.h"
23 #include "datashare_log.h"
24 #include "datashare_string_utils.h"
25
26 namespace OHOS {
27 namespace DataShare {
28 using namespace AppExecFwk;
29 namespace {
30 static constexpr const char *DATA_SHARE_PREFIX = "datashare:///";
31 static constexpr const char *FILE_PREFIX = "file://";
32 } // namespace
33
34 ConcurrentMap<DataShareObserver *, ObserverImpl::ObserverParam> ObserverImpl::observers_;
35
TransferUriPrefix(const std::string & originPrefix,const std::string & replacedPrefix,const std::string & originUriStr)36 std::string DataShareHelper::TransferUriPrefix(const std::string &originPrefix, const std::string &replacedPrefix,
37 const std::string &originUriStr)
38 {
39 if (originUriStr.find(originPrefix) != 0) {
40 return originUriStr;
41 }
42 return replacedPrefix + originUriStr.substr(originPrefix.length());
43 }
44
45 /**
46 * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
47 * between the ability using the Data template (data share for short) and the associated client process in
48 * a DataShareHelper instance.
49 *
50 * @param token Indicates the System token.
51 * @param strUri Indicates the database table or disk file to operate.
52 *
53 * @return Returns the created DataShareHelper instance.
54 */
Creator(const sptr<IRemoteObject> & token,const std::string & strUri,const std::string & extUri,const int waitTime,bool isSystem)55 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(const sptr<IRemoteObject> &token, const std::string &strUri,
56 const std::string &extUri, const int waitTime, bool isSystem)
57 {
58 DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__));
59 if (token == nullptr) {
60 LOG_ERROR("token == nullptr");
61 return nullptr;
62 }
63 std::string replacedUriStr = TransferUriPrefix(FILE_PREFIX, DATA_SHARE_PREFIX, strUri);
64 Uri uri(replacedUriStr);
65 std::shared_ptr<DataShareHelper> helper = nullptr;
66 if (uri.GetQuery().find("Proxy=true") != std::string::npos) {
67 auto result = CreateServiceHelper(extUri, "", isSystem);
68 if (result != nullptr && GetSilentProxyStatus(strUri, isSystem) == E_OK) {
69 return result;
70 }
71 if (extUri.empty()) {
72 return nullptr;
73 }
74 Uri ext(extUri);
75 helper = CreateExtHelper(ext, token, waitTime, isSystem);
76 } else {
77 helper = CreateExtHelper(uri, token, waitTime, isSystem);
78 }
79 return helper;
80 }
81
Creator(const string & strUri,const CreateOptions & options,const std::string & bundleName,const int waitTime,bool isSystem)82 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(const string &strUri, const CreateOptions &options,
83 const std::string &bundleName, const int waitTime, bool isSystem)
84 {
85 DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__));
86 Uri uri(strUri);
87 if (!options.isProxy_ && options.token_ == nullptr) {
88 LOG_ERROR("token is nullptr");
89 return nullptr;
90 }
91 if (options.isProxy_) {
92 int ret = GetSilentProxyStatus(strUri, isSystem);
93 return (ret == E_OK || ret == E_METADATA_NOT_EXISTS) ? CreateServiceHelper("", bundleName, isSystem) : nullptr;
94 } else {
95 return CreateExtHelper(uri, options.token_, waitTime, isSystem);
96 }
97 }
98
Create(const sptr<IRemoteObject> & token,const std::string & strUri,const std::string & extUri,const int waitTime)99 std::pair<int, std::shared_ptr<DataShareHelper>> DataShareHelper::Create(const sptr<IRemoteObject> &token,
100 const std::string &strUri, const std::string &extUri, const int waitTime)
101 {
102 DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__));
103 if (token == nullptr) {
104 LOG_ERROR("Create helper failed, err: %{public}d", E_TOKEN_EMPTY);
105 return std::make_pair(E_TOKEN_EMPTY, nullptr);
106 }
107 Uri uri(strUri);
108 if (IsProxy(uri)) {
109 auto [ret, helper] = CreateProxyHelper(strUri, extUri);
110 if (helper != nullptr) {
111 return std::make_pair(E_OK, helper);
112 }
113 if (ret == E_BMS_NOT_READY) {
114 LOG_ERROR("BMS not ready, uri:%{publish}s", DataShareStringUtils::Change(strUri).c_str());
115 return std::make_pair(E_DATA_SHARE_NOT_READY, nullptr);
116 }
117 if (ret == E_BUNDLE_NAME_NOT_EXIST) {
118 LOG_ERROR("BundleName not exist, uri:%{publish}s", DataShareStringUtils::Change(strUri).c_str());
119 return std::make_pair(E_BUNDLE_NAME_NOT_EXIST, nullptr);
120 }
121 if (extUri.empty()) {
122 LOG_ERROR("Ext uri empty, err: %{public}d", E_EXT_URI_INVALID);
123 return std::make_pair(E_EXT_URI_INVALID, nullptr);
124 }
125 uri = Uri(extUri);
126 }
127 // this create func is inner api, do not check system permission
128 auto helper = CreateExtHelper(uri, token, waitTime, false);
129 if (helper != nullptr) {
130 return std::make_pair(E_OK, helper);
131 }
132 return std::make_pair(E_ERROR, nullptr);
133 }
134
CreateServiceHelper(const std::string & extUri,const std::string & bundleName,bool isSystem)135 std::shared_ptr<DataShareHelper> DataShareHelper::CreateServiceHelper(const std::string &extUri,
136 const std::string &bundleName, bool isSystem)
137 {
138 auto manager = DataShareManagerImpl::GetInstance();
139 if (manager == nullptr) {
140 LOG_ERROR("Manager is nullptr");
141 return nullptr;
142 }
143 manager->SetBundleName(bundleName);
144 if (DataShareManagerImpl::GetServiceProxy() == nullptr) {
145 LOG_ERROR("Service proxy is nullptr.");
146 return nullptr;
147 }
148 return std::make_shared<DataShareHelperImpl>(extUri, isSystem);
149 }
150
GetSilentProxyStatus(const std::string & uri,bool isSystem)151 int DataShareHelper::GetSilentProxyStatus(const std::string &uri, bool isSystem)
152 {
153 auto proxy = DataShareManagerImpl::GetServiceProxy();
154 if (proxy == nullptr) {
155 LOG_ERROR("Service proxy is nullptr.");
156 return E_ERROR;
157 }
158 DataShareServiceProxy::SetSystem(isSystem);
159 auto res = proxy->GetSilentProxyStatus(uri);
160 DataShareServiceProxy::CleanSystem();
161 return res;
162 }
163
CreateExtHelper(Uri & uri,const sptr<IRemoteObject> & token,const int waitTime,bool isSystem)164 std::shared_ptr<DataShareHelper> DataShareHelper::CreateExtHelper(Uri &uri, const sptr<IRemoteObject> &token,
165 const int waitTime, bool isSystem)
166 {
167 if (uri.GetQuery().find("appIndex=") != std::string::npos) {
168 LOG_ERROR("ExtHelper do not support appIndex. Uri:%{public}s",
169 DataShareStringUtils::Anonymous(uri.ToString()).c_str());
170 return nullptr;
171 }
172 sptr<DataShareConnection> connection = new (std::nothrow) DataShareConnection(uri, token, waitTime);
173 if (connection == nullptr) {
174 LOG_ERROR("Create DataShareConnection failed.");
175 return nullptr;
176 }
177 auto dataShareConnection =
178 std::shared_ptr<DataShareConnection>(connection.GetRefPtr(), [holder = connection](const auto *) {
179 holder->SetConnectInvalid();
180 holder->DisconnectDataShareExtAbility();
181 });
182 auto manager = DataShareManagerImpl::GetInstance();
183 if (manager == nullptr) {
184 LOG_ERROR("Manager is nullptr");
185 return nullptr;
186 }
187 manager->SetCallCount(__FUNCTION__, uri.ToString());
188 if (dataShareConnection->GetDataShareProxy(uri, token) == nullptr) {
189 LOG_ERROR("connect failed");
190 return nullptr;
191 }
192 return std::make_shared<DataShareHelperImpl>(uri, token, dataShareConnection, isSystem);
193 }
194
195 /**
196 * Registers an observer to DataObsMgr specified by the given Uri.
197 *
198 * @param uri, Indicates the path of the data to operate.
199 * @param dataObserver, Indicates the DataShareObserver object.
200 * @param isDescendants, Indicates the Whether to note the change of descendants.
201 */
RegisterObserverExt(const Uri & uri,std::shared_ptr<DataShareObserver> dataObserver,bool isDescendants,bool isSystem)202 void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver,
203 bool isDescendants, bool isSystem)
204 {
205 if (dataObserver == nullptr) {
206 LOG_ERROR("dataObserver is nullptr");
207 return;
208 }
209 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
210 if (obsMgrClient == nullptr) {
211 LOG_ERROR("get DataObsMgrClient failed");
212 return;
213 }
214 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
215 if (obs == nullptr) {
216 LOG_ERROR("new ObserverImpl failed");
217 return;
218 }
219 ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants, AAFwk::DataObsOption(isSystem));
220 if (ret != ERR_OK) {
221 ObserverImpl::DeleteObserver(uri, dataObserver);
222 }
223 LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s",
224 ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
225 }
226
227 /**
228 * Deregisters an observer used for DataObsMgr specified by the given Uri.
229 *
230 * @param uri, Indicates the path of the data to operate.
231 * @param dataObserver, Indicates the DataShareObserver object.
232 */
UnregisterObserverExt(const Uri & uri,std::shared_ptr<DataShareObserver> dataObserver,bool isSystem)233 void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver,
234 bool isSystem)
235 {
236 if (dataObserver == nullptr) {
237 LOG_ERROR("dataObserver is nullptr");
238 return;
239 }
240 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
241 if (obsMgrClient == nullptr) {
242 LOG_ERROR("get DataObsMgrClient failed");
243 return;
244 }
245
246 if (!ObserverImpl::FindObserver(uri, dataObserver)) {
247 LOG_ERROR("observer not exit!");
248 return;
249 }
250
251 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
252 if (obs == nullptr) {
253 LOG_ERROR("new ObserverImpl failed");
254 return;
255 }
256 ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs, AAFwk::DataObsOption(isSystem));
257 LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s",
258 ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
259 if (ret != ERR_OK) {
260 return;
261 }
262 ObserverImpl::DeleteObserver(uri, dataObserver);
263 }
264
265 /**
266 * Notifies the registered observers of a change to the data resource specified by Uris.
267 *
268 * @param changeInfo Indicates the info of the data to operate.
269 */
NotifyChangeExt(const DataShareObserver::ChangeInfo & changeInfo,bool isSystem)270 void DataShareHelper::NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo, bool isSystem)
271 {
272 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
273 if (obsMgrClient == nullptr) {
274 LOG_ERROR("get DataObsMgrClient failed");
275 return;
276 }
277
278 ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo),
279 AAFwk::DataObsOption(isSystem));
280 LOG_INFO("Notify changeExt, ret:%{public}d", ret);
281 }
282
OnChange()283 void ObserverImpl::OnChange() {}
284
OnChangeExt(const AAFwk::ChangeInfo & info)285 void ObserverImpl::OnChangeExt(const AAFwk::ChangeInfo &info)
286 {
287 dataShareObserver_->OnChange(ConvertInfo(info));
288 }
289
ConvertInfo(const AAFwk::ChangeInfo & info)290 DataShareObserver::ChangeInfo ObserverImpl::ConvertInfo(const AAFwk::ChangeInfo &info)
291 {
292 DataShareObserver::ChangeInfo changeInfo;
293 changeInfo.changeType_ = static_cast<const DataShareObserver::ChangeType>(info.changeType_);
294 changeInfo.uris_ = std::move(info.uris_);
295 changeInfo.data_ = info.data_;
296 changeInfo.size_ = info.size_;
297 changeInfo.valueBuckets_ = std::move(info.valueBuckets_);
298 return changeInfo;
299 }
300
ConvertInfo(const DataShareObserver::ChangeInfo & info)301 AAFwk::ChangeInfo ObserverImpl::ConvertInfo(const DataShareObserver::ChangeInfo &info)
302 {
303 AAFwk::ChangeInfo changeInfo;
304 changeInfo.changeType_ = static_cast<const AAFwk::ChangeInfo::ChangeType>(info.changeType_);
305 changeInfo.uris_ = std::move(info.uris_);
306 changeInfo.data_ = const_cast<void*>(info.data_);
307 changeInfo.size_ = info.size_;
308 changeInfo.valueBuckets_ =std::move(info.valueBuckets_);
309 return changeInfo;
310 }
311
GetObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)312 sptr<ObserverImpl> ObserverImpl::GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
313 {
314 sptr<ObserverImpl> result = nullptr;
315 observers_.Compute(observer.get(), [&result, &uri, &observer](const auto &key, auto &value) {
316 if (value.obs_ == nullptr) {
317 value.obs_ = new (std::nothrow) ObserverImpl(observer);
318 value.uris_.push_back(uri);
319 } else {
320 auto it = std::find(value.uris_.begin(), value.uris_.end(), uri);
321 if (it == value.uris_.end()) {
322 value.uris_.push_back(uri);
323 }
324 }
325
326 result = value.obs_;
327 return result != nullptr;
328 });
329
330 return result;
331 }
332
FindObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)333 bool ObserverImpl::FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
334 {
335 auto result = observers_.Find(observer.get());
336 if (result.first) {
337 auto it = std::find(result.second.uris_.begin(), result.second.uris_.end(), uri);
338 if (it == result.second.uris_.end()) {
339 return false;
340 }
341 }
342 return result.first;
343 }
344
DeleteObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)345 bool ObserverImpl::DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
346 {
347 return observers_.ComputeIfPresent(observer.get(), [&uri](auto &key, auto &value) {
348 value.uris_.remove_if([&uri](const auto &value) {
349 return uri == value;
350 });
351 return !value.uris_.empty();
352 });
353 }
354
SetSilentSwitch(Uri & uri,bool enable,bool isSystem)355 int DataShareHelper::SetSilentSwitch(Uri &uri, bool enable, bool isSystem)
356 {
357 auto proxy = DataShareManagerImpl::GetServiceProxy();
358 if (proxy == nullptr) {
359 LOG_ERROR("proxy is nullptr");
360 return DATA_SHARE_ERROR;
361 }
362 DataShareServiceProxy::SetSystem(isSystem);
363 auto res = proxy->SetSilentSwitch(uri, enable);
364 DataShareServiceProxy::CleanSystem();
365 return res;
366 }
367
IsProxy(Uri & uri)368 bool DataShareHelper::IsProxy(Uri &uri)
369 {
370 return (uri.GetQuery().find("Proxy=true") != std::string::npos || uri.GetScheme() == "datashareproxy");
371 }
372
CreateProxyHelper(const std::string & strUri,const std::string & extUri)373 std::pair<int, std::shared_ptr<DataShareHelper>> DataShareHelper::CreateProxyHelper(const std::string &strUri,
374 const std::string &extUri)
375 {
376 int ret = GetSilentProxyStatus(strUri, false);
377 auto helper = ret == E_OK ? CreateServiceHelper(extUri) : nullptr;
378 return std::make_pair(ret, helper);
379 }
380
InsertEx(Uri & uri,const DataShareValuesBucket & value)381 std::pair<int32_t, int32_t> DataShareHelper::InsertEx(Uri &uri, const DataShareValuesBucket &value)
382 {
383 return std::make_pair(0, 0);
384 }
385
DeleteEx(Uri & uri,const DataSharePredicates & predicates)386 std::pair<int32_t, int32_t> DataShareHelper::DeleteEx(Uri &uri, const DataSharePredicates &predicates)
387 {
388 return std::make_pair(0, 0);
389 }
390
UpdateEx(Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)391 std::pair<int32_t, int32_t> DataShareHelper::UpdateEx(Uri &uri, const DataSharePredicates &predicates,
392 const DataShareValuesBucket &value)
393 {
394 return std::make_pair(0, 0);
395 }
396
UserDefineFunc(MessageParcel & data,MessageParcel & reply,MessageOption & option)397 int32_t DataShareHelper::UserDefineFunc(MessageParcel &data, MessageParcel &reply, MessageOption &option)
398 {
399 return 0;
400 }
401 } // namespace DataShare
402 } // namespace OHOS