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