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