1 /*
2 * Copyright (c) 2021-2024 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
16 #include "data_ability_impl.h"
17
18 #include "abs_shared_result_set.h"
19 #include "accesstoken_kit.h"
20 #include "data_ability_operation.h"
21 #include "data_ability_predicates.h"
22 #include "hilog_tag_wrapper.h"
23 #include "ipc_skeleton.h"
24 #include "values_bucket.h"
25
26 namespace OHOS {
27 namespace AppExecFwk {
28 namespace {
29 const std::string READ = "r";
30 const std::string WRITE = "w";
31 }
32 using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient;
33 using OHOS::Security::AccessToken::AccessTokenKit;
HandleAbilityTransaction(const Want & want,const AAFwk::LifeCycleStateInfo & targetState,sptr<AAFwk::SessionInfo> sessionInfo)34 void DataAbilityImpl::HandleAbilityTransaction(const Want &want, const AAFwk::LifeCycleStateInfo &targetState,
35 sptr<AAFwk::SessionInfo> sessionInfo)
36 {
37 TAG_LOGI(AAFwkTag::DATA_ABILITY,
38 "sourceState:%{public}d; targetState:%{public}d; isNewWant:%{public}d", lifecycleState_,
39 targetState.state, targetState.isNewWant);
40 if ((lifecycleState_ == targetState.state) && !targetState.isNewWant) {
41 TAG_LOGE(AAFwkTag::DATA_ABILITY, "lifeCycleState equals");
42 return;
43 }
44
45 switch (targetState.state) {
46 case AAFwk::ABILITY_STATE_ACTIVE: {
47 if (lifecycleState_ == AAFwk::ABILITY_STATE_INITIAL) {
48 SetUriString(targetState.caller.deviceId + "/" + targetState.caller.bundleName + "/" +
49 targetState.caller.abilityName);
50 Start(want);
51 } else {
52 return;
53 }
54 break;
55 }
56 default: {
57 TAG_LOGE(AAFwkTag::DATA_ABILITY, "state error");
58 return;
59 }
60 }
61
62 AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, targetState.state, GetRestoreData());
63 }
64
65 /**
66 * @brief Obtains the MIME types of files supported.
67 *
68 * @param uri Indicates the path of the files to obtain.
69 * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null.
70 *
71 * @return Returns the matched MIME types. If there is no match, null is returned.
72 */
GetFileTypes(const Uri & uri,const std::string & mimeTypeFilter)73 std::vector<std::string> DataAbilityImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter)
74 {
75 std::vector<std::string> types;
76 if (ability_ == nullptr) {
77 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
78 return types;
79 }
80
81 types = ability_->GetFileTypes(uri, mimeTypeFilter);
82 return types;
83 }
84
85 /**
86 * @brief Opens a file in a specified remote path.
87 *
88 * @param uri Indicates the path of the file to open.
89 * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
90 * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
91 * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data,
92 * or "rwt" for read and write access that truncates any existing file.
93 *
94 * @return Returns the file descriptor.
95 */
OpenFile(const Uri & uri,const std::string & mode)96 int DataAbilityImpl::OpenFile(const Uri &uri, const std::string &mode)
97 {
98 int fd = -1;
99 if (ability_ == nullptr) {
100 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
101 return fd;
102 }
103
104 if (!CheckOpenFilePermission(mode)) {
105 return fd;
106 }
107
108 fd = ability_->OpenFile(uri, mode);
109 return fd;
110 }
111
112 /**
113 * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets
114 * inside of their .hap.
115 *
116 * @param uri Indicates the path of the file to open.
117 * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
118 * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
119 * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing
120 * data, or "rwt" for read and write access that truncates any existing file.
121 *
122 * @return Returns the RawFileDescriptor object containing file descriptor.
123 */
OpenRawFile(const Uri & uri,const std::string & mode)124 int DataAbilityImpl::OpenRawFile(const Uri &uri, const std::string &mode)
125 {
126 int fd = -1;
127 if (ability_ == nullptr) {
128 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
129 return fd;
130 }
131
132 if (!CheckOpenFilePermission(mode)) {
133 return fd;
134 }
135
136 fd = ability_->OpenRawFile(uri, mode);
137 return fd;
138 }
139
140 /**
141 * @brief Inserts a single data record into the database.
142 *
143 * @param uri Indicates the path of the data to operate.
144 * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted.
145 *
146 * @return Returns the index of the inserted data record.
147 */
Insert(const Uri & uri,const NativeRdb::ValuesBucket & value)148 int DataAbilityImpl::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value)
149 {
150 int index = -1;
151 if (ability_ == nullptr) {
152 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
153 return index;
154 }
155
156 if (!CheckReadAndWritePermission(WRITE)) {
157 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no write permission");
158 return index;
159 }
160
161 index = ability_->Insert(uri, value);
162 return index;
163 }
164
165 /**
166 * @brief Updates data records in the database.
167 *
168 * @param uri Indicates the path of data to update.
169 * @param value Indicates the data to update. This parameter can be null.
170 * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
171 *
172 * @return Returns the number of data records updated.
173 */
Update(const Uri & uri,const NativeRdb::ValuesBucket & value,const NativeRdb::DataAbilityPredicates & predicates)174 int DataAbilityImpl::Update(
175 const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates)
176 {
177 int index = -1;
178 if (ability_ == nullptr) {
179 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
180 return index;
181 }
182
183 if (!CheckReadAndWritePermission(WRITE)) {
184 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no write permission");
185 return index;
186 }
187
188 index = ability_->Update(uri, value, predicates);
189 return index;
190 }
191
192 /**
193 * @brief Deletes one or more data records from the database.
194 *
195 * @param uri Indicates the path of the data to operate.
196 * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
197 *
198 * @return Returns the number of data records deleted.
199 */
Delete(const Uri & uri,const NativeRdb::DataAbilityPredicates & predicates)200 int DataAbilityImpl::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates)
201 {
202 int index = -1;
203 if (ability_ == nullptr) {
204 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
205 return index;
206 }
207
208 if (!CheckReadAndWritePermission(WRITE)) {
209 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no write permission");
210 return index;
211 }
212
213 index = ability_->Delete(uri, predicates);
214 return index;
215 }
216
217 /**
218 * @brief Deletes one or more data records from the database.
219 *
220 * @param uri Indicates the path of data to query.
221 * @param columns Indicates the columns to query. If this parameter is null, all columns are queried.
222 * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
223 *
224 * @return Returns the query result.
225 */
Query(const Uri & uri,std::vector<std::string> & columns,const NativeRdb::DataAbilityPredicates & predicates)226 std::shared_ptr<NativeRdb::AbsSharedResultSet> DataAbilityImpl::Query(
227 const Uri &uri, std::vector<std::string> &columns, const NativeRdb::DataAbilityPredicates &predicates)
228 {
229 if (ability_ == nullptr) {
230 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
231 return nullptr;
232 }
233
234 if (!CheckReadAndWritePermission(READ)) {
235 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no read permission");
236 return nullptr;
237 }
238
239 return ability_->Query(uri, columns, predicates);
240 }
241
Call(const Uri & uri,const std::string & method,const std::string & arg,const AppExecFwk::PacMap & pacMap)242 std::shared_ptr<AppExecFwk::PacMap> DataAbilityImpl::Call(
243 const Uri &uri, const std::string &method, const std::string &arg, const AppExecFwk::PacMap &pacMap)
244 {
245 if (ability_ == nullptr) {
246 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
247 return nullptr;
248 }
249
250 return ability_->Call(uri, method, arg, pacMap);
251 }
252
253 /**
254 * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be
255 * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG.
256 *
257 * @param uri Indicates the URI of the data.
258 *
259 * @return Returns the MIME type that matches the data specified by uri.
260 */
GetType(const Uri & uri)261 std::string DataAbilityImpl::GetType(const Uri &uri)
262 {
263 std::string type;
264 if (ability_ == nullptr) {
265 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
266 return type;
267 }
268 type = ability_->GetType(uri);
269 return type;
270 }
271
272 /**
273 * @brief Reloads data in the database.
274 *
275 * @param uri Indicates the position where the data is to reload. This parameter is mandatory.
276 * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This
277 * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across
278 * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object.
279 *
280 * @return Returns true if the data is successfully reloaded; returns false otherwise.
281 */
Reload(const Uri & uri,const PacMap & extras)282 bool DataAbilityImpl::Reload(const Uri &uri, const PacMap &extras)
283 {
284 bool ret = false;
285 if (ability_ == nullptr) {
286 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
287 return ret;
288 }
289 ret = ability_->Reload(uri, extras);
290 return ret;
291 }
292
293 /**
294 * @brief Inserts multiple data records into the database.
295 *
296 * @param uri Indicates the path of the data to operate.
297 * @param values Indicates the data records to insert.
298 *
299 * @return Returns the number of data records inserted.
300 */
BatchInsert(const Uri & uri,const std::vector<NativeRdb::ValuesBucket> & values)301 int DataAbilityImpl::BatchInsert(const Uri &uri, const std::vector<NativeRdb::ValuesBucket> &values)
302 {
303 int ret = -1;
304 if (ability_ == nullptr) {
305 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
306 return ret;
307 }
308
309 if (!CheckReadAndWritePermission(WRITE)) {
310 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no write permission");
311 return ret;
312 }
313
314 ret = ability_->BatchInsert(uri, values);
315 return ret;
316 }
317 /**
318 * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used
319 * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the
320 * context has changed. If you implement URI normalization for a Data ability, you must also implement
321 * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any
322 * method that is called on the Data ability must require normalization verification and denormalization. The default
323 * implementation of this method returns null, indicating that this Data ability does not support URI normalization.
324 *
325 * @param uri Indicates the Uri object to normalize.
326 *
327 * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise.
328 */
NormalizeUri(const Uri & uri)329 Uri DataAbilityImpl::NormalizeUri(const Uri &uri)
330 {
331 Uri urivalue("");
332 if (ability_ == nullptr) {
333 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
334 return urivalue;
335 }
336
337 if (!CheckReadAndWritePermission(READ)) {
338 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no read permission");
339 return urivalue;
340 }
341
342 urivalue = ability_->NormalizeUri(uri);
343 return urivalue;
344 }
345
346 /**
347 * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used
348 * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the
349 * context has changed. If you implement URI normalization for a Data ability, you must also implement
350 * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any
351 * method that is called on the Data ability must require normalization verification and denormalization. The default
352 * implementation of this method returns null, indicating that this Data ability does not support URI normalization.
353 *
354 * @param uri Indicates the Uri object to normalize.
355 *
356 * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise.
357 */
DenormalizeUri(const Uri & uri)358 Uri DataAbilityImpl::DenormalizeUri(const Uri &uri)
359 {
360 Uri urivalue("");
361 if (ability_ == nullptr) {
362 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
363 return urivalue;
364 }
365
366 if (!CheckReadAndWritePermission(READ)) {
367 TAG_LOGE(AAFwkTag::DATA_ABILITY, "no read permission");
368 return urivalue;
369 }
370
371 urivalue = ability_->DenormalizeUri(uri);
372 return urivalue;
373 }
374
ExecuteBatch(const std::vector<std::shared_ptr<DataAbilityOperation>> & operations)375 std::vector<std::shared_ptr<DataAbilityResult>> DataAbilityImpl::ExecuteBatch(
376 const std::vector<std::shared_ptr<DataAbilityOperation>> &operations)
377 {
378 TAG_LOGI(AAFwkTag::DATA_ABILITY, "start");
379 std::vector<std::shared_ptr<DataAbilityResult>> results;
380 if (ability_ == nullptr) {
381 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null ability_");
382 results.clear();
383 return results;
384 }
385
386 if (!CheckExecuteBatchPermission(operations)) {
387 results.clear();
388 return results;
389 }
390
391 results = ability_->ExecuteBatch(operations);
392 TAG_LOGI(AAFwkTag::DATA_ABILITY, "end, results size:%{public}zu", results.size());
393 return results;
394 }
395
CheckExecuteBatchPermission(const std::vector<std::shared_ptr<DataAbilityOperation>> & operations) const396 bool DataAbilityImpl::CheckExecuteBatchPermission(
397 const std::vector<std::shared_ptr<DataAbilityOperation>> &operations) const
398 {
399 bool needCheckReadPermission = false;
400 bool needCheckWritePermission = false;
401
402 size_t size = operations.size();
403 for (size_t i = 0; i < size; i++) {
404 std::shared_ptr<DataAbilityOperation> operation = operations[i];
405 if (operation == nullptr) {
406 TAG_LOGE(AAFwkTag::DATA_ABILITY, "null operation, index: %{public}d", static_cast<int32_t>(i));
407 return false;
408 }
409 if (operation->IsInsertOperation() || operation->IsUpdateOperation() || operation->IsDeleteOperation()) {
410 needCheckWritePermission = true;
411 } else if (operation->IsAssertOperation()) {
412 needCheckReadPermission = true;
413 }
414 if (needCheckReadPermission && needCheckWritePermission) {
415 break;
416 }
417 }
418
419 if (needCheckReadPermission) {
420 if (!CheckReadAndWritePermission(READ)) {
421 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no read permission");
422 return false;
423 }
424 }
425
426 if (needCheckWritePermission) {
427 if (!CheckReadAndWritePermission(WRITE)) {
428 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no write permission");
429 return false;
430 }
431 }
432
433 return true;
434 }
435
CheckOpenFilePermission(const std::string & mode) const436 bool DataAbilityImpl::CheckOpenFilePermission(const std::string &mode) const
437 {
438 if (mode.find(READ) != string::npos) {
439 if (!CheckReadAndWritePermission(READ)) {
440 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no read permission");
441 return false;
442 }
443 } else if (mode.find(WRITE) != string::npos) {
444 if (!CheckReadAndWritePermission(WRITE)) {
445 TAG_LOGW(AAFwkTag::DATA_ABILITY, "no write permission");
446 return false;
447 }
448 }
449
450 return true;
451 }
452
CheckReadAndWritePermission(const std::string & permissionType) const453 bool DataAbilityImpl::CheckReadAndWritePermission(const std::string &permissionType) const
454 {
455 std::string permission = GetPermissionInfo(permissionType);
456 if (permission.empty()) {
457 TAG_LOGD(AAFwkTag::DATA_ABILITY, "empty permission");
458 return true;
459 }
460
461 auto tokenId = IPCSkeleton::GetCallingTokenID();
462 int checkReadPermission = AccessTokenKit::VerifyAccessToken(tokenId, permission);
463 if (checkReadPermission != ERR_OK) {
464 std::shared_ptr<AbilityInfo> abilityInfo = ability_->GetAbilityInfo();
465 TAG_LOGD(AAFwkTag::DATA_ABILITY, "no permission, bundleName: %{public}s", abilityInfo->bundleName.c_str());
466 return false;
467 }
468
469 return true;
470 }
471
GetPermissionInfo(const std::string & permissionType) const472 std::string DataAbilityImpl::GetPermissionInfo(const std::string &permissionType) const
473 {
474 TAG_LOGD(AAFwkTag::DATA_ABILITY, "permissionType:%{public}s", permissionType.c_str());
475 std::shared_ptr<AbilityInfo> abilityInfo = ability_->GetAbilityInfo();
476 if (abilityInfo == nullptr) {
477 TAG_LOGW(AAFwkTag::DATA_ABILITY, "null abilityInfo");
478 return "";
479 }
480 if (permissionType == READ) {
481 return abilityInfo->readPermission;
482 } else if (permissionType == WRITE) {
483 return abilityInfo->writePermission;
484 } else {
485 TAG_LOGI(AAFwkTag::DATA_ABILITY, "invalid permissionType:%{public}s", permissionType.c_str());
486 return "";
487 }
488 }
489 } // namespace AppExecFwk
490 } // namespace OHOS
491