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     sptr<DataShareConnection> connection = new (std::nothrow) DataShareConnection(uri, token, waitTime);
182     if (connection == nullptr) {
183         LOG_ERROR("Create DataShareConnection failed.");
184         return nullptr;
185     }
186     auto dataShareConnection =
187         std::shared_ptr<DataShareConnection>(connection.GetRefPtr(), [holder = connection](const auto *) {
188             holder->SetConnectInvalid();
189             holder->DisconnectDataShareExtAbility();
190         });
191     auto manager = DataShareManagerImpl::GetInstance();
192     if (manager == nullptr) {
193         LOG_ERROR("Manager is nullptr");
194         return nullptr;
195     }
196     manager->SetCallCount(__FUNCTION__, uri.ToString());
197     if (dataShareConnection->GetDataShareProxy(uri, token) == nullptr) {
198         LOG_ERROR("connect failed");
199         return nullptr;
200     }
201     return std::make_shared<DataShareHelperImpl>(uri, token, dataShareConnection);
202 }
203 
204 /**
205  * Registers an observer to DataObsMgr specified by the given Uri.
206  *
207  * @param uri, Indicates the path of the data to operate.
208  * @param dataObserver, Indicates the DataShareObserver object.
209  * @param isDescendants, Indicates the Whether to note the change of descendants.
210  */
RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver, bool isDescendants)211 void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver,
212     bool isDescendants)
213 {
214     if (dataObserver == nullptr) {
215         LOG_ERROR("dataObserver is nullptr");
216         return;
217     }
218     auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
219     if (obsMgrClient == nullptr) {
220         LOG_ERROR("get DataObsMgrClient failed");
221         return;
222     }
223     sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
224     if (obs == nullptr) {
225         LOG_ERROR("new ObserverImpl failed");
226         return;
227     }
228     ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants);
229     if (ret != ERR_OK) {
230         ObserverImpl::DeleteObserver(uri, dataObserver);
231     }
232     LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s",
233         ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
234 }
235 
236 /**
237  * Deregisters an observer used for DataObsMgr specified by the given Uri.
238  *
239  * @param uri, Indicates the path of the data to operate.
240  * @param dataObserver, Indicates the DataShareObserver object.
241  */
UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver)242 void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver)
243 {
244     if (dataObserver == nullptr) {
245         LOG_ERROR("dataObserver is nullptr");
246         return;
247     }
248     auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
249     if (obsMgrClient == nullptr) {
250         LOG_ERROR("get DataObsMgrClient failed");
251         return;
252     }
253 
254     if (!ObserverImpl::FindObserver(uri, dataObserver)) {
255         LOG_ERROR("observer not exit!");
256         return;
257     }
258 
259     sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
260     if (obs == nullptr) {
261         LOG_ERROR("new ObserverImpl failed");
262         return;
263     }
264     ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs);
265     LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s",
266         ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
267     if (ret != ERR_OK) {
268         return;
269     }
270     ObserverImpl::DeleteObserver(uri, dataObserver);
271 }
272 
273 /**
274  * Notifies the registered observers of a change to the data resource specified by Uris.
275  *
276  * @param changeInfo Indicates the info of the data to operate.
277  */
NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo)278 void DataShareHelper::NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo)
279 {
280     auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
281     if (obsMgrClient == nullptr) {
282         LOG_ERROR("get DataObsMgrClient failed");
283         return;
284     }
285 
286     ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo));
287     LOG_INFO("Notify changeExt, ret:%{public}d", ret);
288 }
289 
OnChange()290 void ObserverImpl::OnChange() {}
291 
OnChangeExt(const AAFwk::ChangeInfo &info)292 void ObserverImpl::OnChangeExt(const AAFwk::ChangeInfo &info)
293 {
294     dataShareObserver_->OnChange(ConvertInfo(info));
295 }
296 
ConvertInfo(const AAFwk::ChangeInfo &info)297 DataShareObserver::ChangeInfo ObserverImpl::ConvertInfo(const AAFwk::ChangeInfo &info)
298 {
299     DataShareObserver::ChangeInfo changeInfo;
300     changeInfo.changeType_ = static_cast<const DataShareObserver::ChangeType>(info.changeType_);
301     changeInfo.uris_ = std::move(info.uris_);
302     changeInfo.data_ = info.data_;
303     changeInfo.size_ = info.size_;
304     changeInfo.valueBuckets_ = std::move(info.valueBuckets_);
305     return changeInfo;
306 }
307 
ConvertInfo(const DataShareObserver::ChangeInfo &info)308 AAFwk::ChangeInfo ObserverImpl::ConvertInfo(const DataShareObserver::ChangeInfo &info)
309 {
310     AAFwk::ChangeInfo changeInfo;
311     changeInfo.changeType_ = static_cast<const AAFwk::ChangeInfo::ChangeType>(info.changeType_);
312     changeInfo.uris_ = std::move(info.uris_);
313     changeInfo.data_ = const_cast<void*>(info.data_);
314     changeInfo.size_ = info.size_;
315     changeInfo.valueBuckets_ =std::move(info.valueBuckets_);
316     return changeInfo;
317 }
318 
GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)319 sptr<ObserverImpl> ObserverImpl::GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
320 {
321     sptr<ObserverImpl> result = nullptr;
322     observers_.Compute(observer.get(), [&result, &uri, &observer](const auto &key, auto &value) {
323         if (value.obs_ == nullptr) {
324             value.obs_ = new (std::nothrow) ObserverImpl(observer);
325             value.uris_.push_back(uri);
326         } else {
327             auto it = std::find(value.uris_.begin(), value.uris_.end(), uri);
328             if (it == value.uris_.end()) {
329                 value.uris_.push_back(uri);
330             }
331         }
332 
333         result = value.obs_;
334         return result != nullptr;
335     });
336 
337     return result;
338 }
339 
FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)340 bool ObserverImpl::FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
341 {
342     auto result = observers_.Find(observer.get());
343     if (result.first) {
344         auto it = std::find(result.second.uris_.begin(), result.second.uris_.end(), uri);
345         if (it == result.second.uris_.end()) {
346             return false;
347         }
348     }
349     return result.first;
350 }
351 
DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)352 bool ObserverImpl::DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
353 {
354     return observers_.ComputeIfPresent(observer.get(), [&uri](auto &key, auto &value) {
355         value.uris_.remove_if([&uri](const auto &value) {
356             return uri == value;
357         });
358         return !value.uris_.empty();
359     });
360 }
361 
SetSilentSwitch(Uri &uri, bool enable)362 int DataShareHelper::SetSilentSwitch(Uri &uri, bool enable)
363 {
364     auto proxy = DataShareManagerImpl::GetServiceProxy();
365     if (proxy == nullptr) {
366         LOG_ERROR("proxy is nullptr");
367         return DATA_SHARE_ERROR;
368     }
369     return proxy->SetSilentSwitch(uri, enable);
370 }
371 
IsProxy(Uri &uri)372 bool DataShareHelper::IsProxy(Uri &uri)
373 {
374     return (uri.GetQuery().find("Proxy=true") != std::string::npos || uri.GetScheme() == "datashareproxy");
375 }
376 
CreateProxyHelper(const std::string &strUri, const std::string &extUri)377 std::pair<int, std::shared_ptr<DataShareHelper>> DataShareHelper::CreateProxyHelper(const std::string &strUri,
378     const std::string &extUri)
379 {
380     int ret = GetSilentProxyStatus(strUri);
381     auto helper = ret == E_OK ? CreateServiceHelper(extUri) : nullptr;
382     return std::make_pair(ret, helper);
383 }
384 
InsertEx(Uri &uri, const DataShareValuesBucket &value)385 std::pair<int32_t, int32_t> DataShareHelper::InsertEx(Uri &uri, const DataShareValuesBucket &value)
386 {
387     return std::make_pair(0, 0);
388 }
389 
DeleteEx(Uri &uri, const DataSharePredicates &predicates)390 std::pair<int32_t, int32_t> DataShareHelper::DeleteEx(Uri &uri, const DataSharePredicates &predicates)
391 {
392     return std::make_pair(0, 0);
393 }
394 
UpdateEx(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value)395 std::pair<int32_t, int32_t> DataShareHelper::UpdateEx(Uri &uri, const DataSharePredicates &predicates,
396     const DataShareValuesBucket &value)
397 {
398     return std::make_pair(0, 0);
399 }
400 
401 } // namespace DataShare
402 } // namespace OHOS