• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 MLOG_TAG "Extension"
16 
17 #include "media_datashare_ext_ability.h"
18 
19 #include "ability_info.h"
20 #include "dataobs_mgr_client.h"
21 #include "media_datashare_stub_impl.h"
22 #include "hilog_wrapper.h"
23 #include "ipc_skeleton.h"
24 #include "datashare_ext_ability_context.h"
25 #include "runtime.h"
26 #include "napi/native_api.h"
27 #include "napi/native_node_api.h"
28 #include "medialibrary_data_manager.h"
29 #include "medialibrary_errno.h"
30 #include "medialibrary_subscriber.h"
31 #include "medialibrary_uripermission_operations.h"
32 #include "media_scanner_manager.h"
33 #include "media_log.h"
34 #include "system_ability_definition.h"
35 #include "permission_utils.h"
36 
37 using namespace std;
38 using namespace OHOS::AppExecFwk;
39 using namespace OHOS::NativeRdb;
40 using namespace OHOS::DistributedKv;
41 using namespace OHOS::Media;
42 using namespace OHOS::DataShare;
43 
44 namespace OHOS {
45 namespace AbilityRuntime {
46 using namespace OHOS::AppExecFwk;
47 using DataObsMgrClient = OHOS::AAFwk::DataObsMgrClient;
48 constexpr int INVALID_VALUE = -1;
49 
Create(const std::unique_ptr<Runtime> & runtime)50 MediaDataShareExtAbility* MediaDataShareExtAbility::Create(const std::unique_ptr<Runtime>& runtime)
51 {
52     return new MediaDataShareExtAbility(static_cast<Runtime&>(*runtime));
53 }
54 
MediaDataShareExtAbility(Runtime & runtime)55 MediaDataShareExtAbility::MediaDataShareExtAbility(Runtime& runtime) : DataShareExtAbility(), runtime_(runtime) {}
56 
~MediaDataShareExtAbility()57 MediaDataShareExtAbility::~MediaDataShareExtAbility()
58 {
59 }
60 
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)61 void MediaDataShareExtAbility::Init(const std::shared_ptr<AbilityLocalRecord> &record,
62     const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
63     const sptr<IRemoteObject> &token)
64 {
65     DataShareExtAbility::Init(record, application, handler, token);
66     auto context = AbilityRuntime::Context::GetApplicationContext();
67     if (context == nullptr) {
68         MEDIA_ERR_LOG("Failed to get context");
69         return;
70     }
71     MEDIA_INFO_LOG("%{public}s runtime language  %{public}d", __func__, runtime_.GetLanguage());
72 
73     auto dataManager = MediaLibraryDataManager::GetInstance();
74     if (dataManager != nullptr) {
75         auto extensionContext = GetContext();
76         dataManager->InitMediaLibraryMgr(context, extensionContext);
77         dataManager->SetOwner(static_pointer_cast<MediaDataShareExtAbility>(shared_from_this()));
78     }
79 
80     auto scannerManager = MediaScannerManager::GetInstance();
81     if (scannerManager != nullptr) {
82         scannerManager->Start();
83     }
84 }
85 
OnStart(const AAFwk::Want & want)86 void MediaDataShareExtAbility::OnStart(const AAFwk::Want &want)
87 {
88     MEDIA_INFO_LOG("%{public}s begin.", __func__);
89     Extension::OnStart(want);
90     Media::MedialibrarySubscriber::Subscribe();
91     MEDIA_INFO_LOG("%{public}s end.", __func__);
92 }
93 
OnStop()94 void MediaDataShareExtAbility::OnStop()
95 {
96     MEDIA_INFO_LOG("%{public}s begin.", __func__);
97     auto scannerManager = MediaScannerManager::GetInstance();
98     if (scannerManager != nullptr) {
99         scannerManager->Stop();
100     }
101     MediaLibraryDataManager::GetInstance()->ClearMediaLibraryMgr();
102     MEDIA_INFO_LOG("%{public}s end.", __func__);
103 }
104 
OnConnect(const AAFwk::Want & want)105 sptr<IRemoteObject> MediaDataShareExtAbility::OnConnect(const AAFwk::Want &want)
106 {
107     MEDIA_INFO_LOG("%{public}s begin. ", __func__);
108     Extension::OnConnect(want);
109     sptr<MediaDataShareStubImpl> remoteObject = new (std::nothrow) MediaDataShareStubImpl(
110         std::static_pointer_cast<MediaDataShareExtAbility>(shared_from_this()),
111         nullptr);
112     if (remoteObject == nullptr) {
113         MEDIA_ERR_LOG("%{public}s No memory allocated for DataShareStubImpl", __func__);
114         return nullptr;
115     }
116     MEDIA_INFO_LOG("%{public}s end.", __func__);
117     return remoteObject->AsObject();
118 }
119 
TypeMaskStringToInteger(const std::string & typeMask)120 static uint32_t TypeMaskStringToInteger(const std::string &typeMask)
121 {
122     uint32_t mask = 0;
123     for (auto &item : MEDIA_TYPE_TUPLE_VEC) {
124         if (typeMask[std::get<POS_TYPE_MASK_STRING_INDEX>(item)] == TYPE_MASK_BIT_SET) {
125             mask |= static_cast<uint32_t>(std::get<POS_TYPE_MASK_INTEGER>(item));
126         }
127     }
128     return mask;
129 }
130 
131 // Parse uri(eg. datashare::///media/image/10#key1:value1#key2:value2#key3:value3) to key-value pairs
GetKeyValueFromUri(const std::string & uri,std::vector<std::pair<std::string,std::string>> & pairs)132 static int32_t GetKeyValueFromUri(const std::string &uri, std::vector<std::pair<std::string, std::string>> &pairs)
133 {
134     constexpr size_t SHARP_POS = 1;
135     size_t nextPairIndex = uri.find('#');
136     if (nextPairIndex == std::string::npos) {
137         return E_SUCCESS;
138     }
139     std::string keyValueString;
140     for (std::string remain = uri.substr(nextPairIndex); nextPairIndex != std::string::npos;) {
141         nextPairIndex = remain.find('#', SHARP_POS);
142         if (nextPairIndex == std::string::npos) {
143             keyValueString = remain.substr(SHARP_POS);
144         } else {
145             keyValueString = remain.substr(SHARP_POS, nextPairIndex - 1);
146             remain = remain.substr(nextPairIndex);
147         }
148         size_t splitIndex = keyValueString.find(':');
149         if (splitIndex == std::string::npos) {
150             MEDIA_ERR_LOG("Key-Value string should have format: #key:value");
151             return -EINVAL;
152         }
153         pairs.push_back(std::make_pair(keyValueString.substr(0, splitIndex), keyValueString.substr(splitIndex + 1)));
154     }
155     return E_SUCCESS;
156 }
157 
ShouldCheckTypePermission(const std::string & uri,bool & shouldCheckType,std::string & typeMask)158 static int32_t ShouldCheckTypePermission(const std::string &uri, bool &shouldCheckType, std::string &typeMask)
159 {
160     typeMask.resize(TYPE_MASK_STRING_SIZE, TYPE_MASK_BIT_DEFAULT);
161     shouldCheckType = false;
162     size_t paramIndex = uri.rfind('#');
163     if (paramIndex == string::npos) {
164         return E_SUCCESS;
165     }
166 
167     std::vector<std::pair<std::string, std::string>> pairs;
168     int err = GetKeyValueFromUri(uri, pairs);
169     if (err < 0) {
170         MEDIA_ERR_LOG("Failed to parse key value pair from uri: %{public}s, err: %{public}d", uri.c_str(), err);
171         return err;
172     }
173 
174     for (auto &item : pairs) {
175         if (item.first == URI_PARAM_KEY_TYPE) {
176             typeMask = item.second;
177             shouldCheckType = true;
178             return E_SUCCESS;
179         }
180     }
181     return E_SUCCESS;
182 }
183 
CheckPerms(bool shouldCheckType,bool isWrite,const std::string & typeMask)184 static bool CheckPerms(bool shouldCheckType, bool isWrite, const std::string &typeMask)
185 {
186     if (!shouldCheckType) {
187         string perm = isWrite ? PERMISSION_NAME_WRITE_MEDIA : PERMISSION_NAME_READ_MEDIA;
188         if (PermissionUtils::CheckCallerPermission(perm)) {
189             return true;
190         }
191         return false;
192     }
193 
194     if (PermissionUtils::CheckCallerPermission((isWrite ? WRITE_PERMS : READ_PERMS),
195         TypeMaskStringToInteger(typeMask))) {
196         return true;
197     }
198     return false;
199 }
200 
GetFileTypes(const Uri & uri,const std::string & mimeTypeFilter)201 std::vector<std::string> MediaDataShareExtAbility::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter)
202 {
203     std::vector<std::string> ret;
204     return ret;
205 }
206 
CheckOpenFilePermission(string & uri,string & mode)207 static int CheckOpenFilePermission(string &uri, string &mode)
208 {
209     bool shouldCheckType = false;
210     string typeMask;
211     int err = ShouldCheckTypePermission(uri, shouldCheckType, typeMask);
212     if (err < 0) {
213         return err;
214     }
215     if (shouldCheckType) {
216         uri = uri.substr(0, uri.find('#'));
217     }
218 
219     size_t rPos = mode.find('r');
220     if (rPos != string::npos) {
221         bool checkReadResult = CheckPerms(shouldCheckType, false, typeMask);
222         if (!checkReadResult) {
223             return E_PERMISSION_DENIED;
224         }
225     }
226     size_t wPos = mode.find('w');
227     if (wPos != string::npos) {
228         bool checkWriteResult = CheckPerms(shouldCheckType, true, typeMask);
229         if (!checkWriteResult) {
230             return E_PERMISSION_DENIED;
231         }
232     }
233     if ((rPos == string::npos) && (wPos == string::npos)) {
234         MEDIA_INFO_LOG("Mode is invalid: %{public}s, return err: %{public}d", mode.c_str(), E_PERMISSION_DENIED);
235         return E_PERMISSION_DENIED;
236     }
237 
238     return E_SUCCESS;
239 }
240 
CheckPermFromUri(std::string & uri,bool isWrite)241 static bool CheckPermFromUri(std::string &uri, bool isWrite)
242 {
243     bool shouldCheckType = false;
244     string typeMask;
245     if (ShouldCheckTypePermission(uri, shouldCheckType, typeMask) < 0) {
246         return false;
247     }
248     if (shouldCheckType) {
249         /* position of '#' should not be string::npos here */
250         uri = uri.substr(0, uri.find('#'));
251     }
252     return CheckPerms(shouldCheckType, isWrite, typeMask);
253 }
254 
OpenFile(const Uri & uri,const std::string & mode)255 int MediaDataShareExtAbility::OpenFile(const Uri &uri, const std::string &mode)
256 {
257     string uriStr = uri.ToString();
258     string unifyMode = mode;
259     transform(unifyMode.begin(), unifyMode.end(), unifyMode.begin(), ::tolower);
260 
261     int err = CheckOpenFilePermission(uriStr, unifyMode);
262     if (err == E_PERMISSION_DENIED) {
263         err = UriPermissionOperations::CheckUriPermission(uriStr, unifyMode);
264         if (err != E_OK) {
265             MEDIA_ERR_LOG("Permission Denied! err = %{public}d", err);
266             return err;
267         }
268     } else if (err < 0) {
269         return err;
270     }
271 
272     return MediaLibraryDataManager::GetInstance()->OpenFile(Uri(uriStr), unifyMode);
273 }
274 
OpenRawFile(const Uri & uri,const std::string & mode)275 int MediaDataShareExtAbility::OpenRawFile(const Uri &uri, const std::string &mode)
276 {
277     return 0;
278 }
279 
Insert(const Uri & uri,const DataShareValuesBucket & value)280 int MediaDataShareExtAbility::Insert(const Uri &uri, const DataShareValuesBucket &value)
281 {
282     string closeUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET;
283     string insertUri = uri.ToString();
284     bool isWrite = (insertUri == closeUri) ? false : true;
285     if ((insertUri.find(DISTRIBUTE_THU_OPRN_CREATE) == string::npos) &&
286         !CheckPermFromUri(insertUri, isWrite)) {
287         return E_PERMISSION_DENIED;
288     }
289 
290     return MediaLibraryDataManager::GetInstance()->Insert(Uri(insertUri), value);
291 }
292 
Update(const Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)293 int MediaDataShareExtAbility::Update(const Uri &uri, const DataSharePredicates &predicates,
294     const DataShareValuesBucket &value)
295 {
296     string updateUri = uri.ToString();
297     if (!CheckPermFromUri(updateUri, true)) {
298         return E_PERMISSION_DENIED;
299     }
300 
301     return MediaLibraryDataManager::GetInstance()->Update(Uri(updateUri), value, predicates);
302 }
303 
Delete(const Uri & uri,const DataSharePredicates & predicates)304 int MediaDataShareExtAbility::Delete(const Uri &uri, const DataSharePredicates &predicates)
305 {
306     string uriStr = uri.ToString();
307     int err = CheckPermFromUri(uriStr, true);
308     if (err < 0) {
309         return err;
310     }
311 
312     return MediaLibraryDataManager::GetInstance()->Delete(Uri(uriStr), predicates);
313 }
314 
Query(const Uri & uri,const DataSharePredicates & predicates,std::vector<std::string> & columns)315 std::shared_ptr<DataShareResultSet> MediaDataShareExtAbility::Query(const Uri &uri,
316     const DataSharePredicates &predicates, std::vector<std::string> &columns)
317 {
318     const static set<string> noPermissionCheck = {
319         MEDIALIBRARY_DIRECTORY_URI,
320         MEDIALIBRARY_DATA_URI + "/" + MEDIA_DEVICE_QUERYACTIVEDEVICE,
321         MEDIALIBRARY_DATA_URI + "/" + MEDIA_DEVICE_QUERYALLDEVICE
322     };
323 
324     string uriStr = uri.ToString();
325     if ((noPermissionCheck.find(uriStr) == noPermissionCheck.end()) && !CheckPermFromUri(uriStr, false)) {
326         return nullptr;
327     }
328     auto queryResultSet = MediaLibraryDataManager::GetInstance()->Query(Uri(uriStr), columns, predicates);
329     if (queryResultSet == nullptr) {
330         return nullptr;
331     }
332     std::shared_ptr<DataShareResultSet> resultSet = std::make_shared<DataShareResultSet>(queryResultSet);
333     return resultSet;
334 }
335 
GetType(const Uri & uri)336 std::string MediaDataShareExtAbility::GetType(const Uri &uri)
337 {
338     MEDIA_INFO_LOG("%{public}s begin.", __func__);
339     auto ret = MediaLibraryDataManager::GetInstance()->GetType(uri);
340     MEDIA_INFO_LOG("%{public}s end.", __func__);
341     return ret;
342 }
343 
BatchInsert(const Uri & uri,const std::vector<DataShareValuesBucket> & values)344 int MediaDataShareExtAbility::BatchInsert(const Uri &uri, const std::vector<DataShareValuesBucket> &values)
345 {
346     MEDIA_INFO_LOG("%{public}s begin.", __func__);
347     int ret = INVALID_VALUE;
348     if (!PermissionUtils::CheckCallerPermission(PERMISSION_NAME_WRITE_MEDIA)) {
349         MEDIA_ERR_LOG("%{public}s Check calling permission failed.", __func__);
350         return ret;
351     }
352 
353     MEDIA_INFO_LOG("%{public}s end.", __func__);
354     return ret;
355 }
356 
RegisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)357 bool MediaDataShareExtAbility::RegisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
358 {
359     MEDIA_INFO_LOG("%{public}s begin.", __func__);
360     auto obsMgrClient = DataObsMgrClient::GetInstance();
361     if (obsMgrClient == nullptr) {
362         MEDIA_ERR_LOG("%{public}s obsMgrClient is nullptr", __func__);
363         return false;
364     }
365 
366     ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver);
367     if (ret != ERR_OK) {
368         MEDIA_ERR_LOG("%{public}s obsMgrClient->RegisterObserver error return %{public}d", __func__, ret);
369         return false;
370     }
371     MEDIA_INFO_LOG("%{public}s end.", __func__);
372     return true;
373 }
374 
UnregisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)375 bool MediaDataShareExtAbility::UnregisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
376 {
377     MEDIA_INFO_LOG("%{public}s begin.", __func__);
378     auto obsMgrClient = DataObsMgrClient::GetInstance();
379     if (obsMgrClient == nullptr) {
380         MEDIA_ERR_LOG("%{public}s obsMgrClient is nullptr", __func__);
381         return false;
382     }
383 
384     ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver);
385     if (ret != ERR_OK) {
386         MEDIA_ERR_LOG("%{public}s obsMgrClient->UnregisterObserver error return %{public}d", __func__, ret);
387         return false;
388     }
389     MEDIA_INFO_LOG("%{public}s end.", __func__);
390     return true;
391 }
392 
NotifyChange(const Uri & uri)393 bool MediaDataShareExtAbility::NotifyChange(const Uri &uri)
394 {
395     MEDIA_INFO_LOG("%{public}s begin.", __func__);
396     auto obsMgrClient = DataObsMgrClient::GetInstance();
397     if (obsMgrClient == nullptr) {
398         MEDIA_ERR_LOG("%{public}s obsMgrClient is nullptr", __func__);
399         return false;
400     }
401 
402     ErrCode ret = obsMgrClient->NotifyChange(uri);
403     if (ret != ERR_OK) {
404         MEDIA_ERR_LOG("%{public}s obsMgrClient->NotifyChange error return %{public}d", __func__, ret);
405         return false;
406     }
407     MEDIA_INFO_LOG("%{public}s end.", __func__);
408     return true;
409 }
410 
NormalizeUri(const Uri & uri)411 Uri MediaDataShareExtAbility::NormalizeUri(const Uri &uri)
412 {
413     MEDIA_INFO_LOG("%{public}s begin.", __func__);
414     auto ret = uri;
415     MEDIA_INFO_LOG("%{public}s end.", __func__);
416     return ret;
417 }
418 
DenormalizeUri(const Uri & uri)419 Uri MediaDataShareExtAbility::DenormalizeUri(const Uri &uri)
420 {
421     MEDIA_INFO_LOG("%{public}s begin.", __func__);
422     auto ret = uri;
423     MEDIA_INFO_LOG("%{public}s end.", __func__);
424     return ret;
425 }
426 } // namespace AbilityRuntime
427 } // namespace OHOS
428