!18736 merge master0321 into master

feat: add URI permission verification mechanism for content URIs

Created-by: dsz2025
Commit-by: duansizhao
Merged-by: openharmony_ci
Description: **IssueNo**: #14797

**Description**:

Add URI permission verification mechanism for content URIs to enhance security and proper authorization checks.

- Add VerifyUriPermission interface in IAbilityManagerCollaborator
- Add VerifyContentUriPermission in UriPermissionManagerStubImpl
- Mark content URIs as authorized for broker calls
- Add ContentUriPermission verification in CheckProxyUriPermission
- Update mock classes for unit testing

**稳定性自检:**
| 自检项 | 自检结果 |
| ------------------------------------------------------------ | -------- |
| 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发 | 待确认 | 修改了敏感文件: *proxy.cpp, *stub.cpp
| 成员变量进行赋值或创建需要排查并发 | 不涉及 |
| 谨慎在lambda表达式中使用引用捕获 | 待确认 | 修改了敏感文件: *.cpp
| 谨慎在未经拷贝的情况下使用外部传入的string、C字符串 | 待确认 | 修改了敏感文件: *.cpp, *.h
| map\vector\list\set等stl模板类使用时需要排查并发 | 待确认 | 修改了敏感文件: *.cpp, *.h
| 谨慎考虑加锁范围 | 待确认 | 修改了敏感文件: *.cpp
| 在IPC通信中谨慎使用同步通信方式 | 不涉及 |
| 禁止传递this指针至其他模块或线程(特别是eventhandler任务) | 不涉及 |
| 禁止将外部传入的裸指针在内部直接构造智能指针 | 不涉及 |
| 禁止多个独立创建的智能指针管理同一地址 | 不涉及 |
| 禁止在析构函数中抛异步任务 | 不涉及 |
| 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁 | 不涉及 |
| 禁止在对外接口中未经判空直接使用外部传入的指针 | 不涉及 |
| 禁止接口返回局部变量引用 | 不涉及 |
| 禁止在信号函数中加锁 | 待确认 | 修改了敏感文件: *.cpp
| 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作 | 不涉及 |
| 禁止将同一个cpp编译在不同的so中 | 不涉及 |

**安全编码自检:**
| 自检项 | 自检结果 |
| -------------------------------------------------------------- | -------- |
| 裸指针避免通过隐式转换构造为sptr | 待确认 | 修改了敏感文件: *.cpp
| json对象在取值之前必须先判断类型,避免类型不匹配 | 待确认 | 修改了敏感文件: *.cpp
| 序列化时必须对传入的数组大小进行校验,避免出现超大数组 | 待确认 | 修改了敏感文件: *.cpp
| 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型 | 不涉及 |
| 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 | 待确认 | 修改了敏感文件: *.cpp
| 指针变量、表示资源描述符的变量、bool变量必须赋初值 | 不涉及 |
| readParcelable获取的对象使用前需要判空 | 待确认 | 修改了敏感文件: *.cpp
| 分配和释放内存的函数需要成对出现 | 不涉及 |
| 申请内存后异常退出前需要及时进行内存释放 | 不涉及 |
| 内存申请前必须对内存大小进行合法性校验 | 不涉及 |
| 内存分配后必须判断是否成功 | 不涉及 |
| 禁止使用realloc、alloca函数 | 不涉及 |
| 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰 | 待确认 | 修改了敏感文件: *.cpp
| 禁止打印内存地址 | 待确认 | 修改了敏感文件: *.cpp
| 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0 | 不涉及 |
| 禁止对有符号整数进行位操作符运算 | 待确认 | 修改了敏感文件: *.cpp
| 禁止对指针进行逻辑或位运算 | 不涉及 |
| 循环次数如果收外部数据控制,需要检验其合法性 | 不涉及 |
| 禁止使用内存操作类危险函数,需要使用安全函数 | 不涉及 |
| 谨慎使用不可重入函数 | 不涉及 |
| 必须检查安全函数的返回值,并进行正确处理 | 不涉及 |
| 禁止仅通过TokenType类型判断绕过权限校验 | 不涉及 |

**TDD Result**:
待确认

**XTS Result**:
待确认

### 是否已执行L0用例
- [ ] 待确认


See merge request: openharmony/ability_ability_runtime!18736
This commit is contained in:
openharmony_ci
2026-03-27 15:00:36 +08:00
19 changed files with 951 additions and 24 deletions
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -197,6 +197,20 @@ public:
return -1;
}
/**
* @brief verify uri permission
* @param uriVec The uri list to verify permission.
* @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION.
* @param tokenId the tokenId of caller application.
* @param checkResults The result of verify uri permission.
* @return 0 when on success or else failed.
*/
virtual int32_t VerifyUriPermission(const std::vector<std::string> &uriVec, uint32_t flag, uint32_t tokenId,
std::vector<bool> &checkResults)
{
return -1;
}
virtual void NotifyMissionBindPid(int32_t missionId, int32_t pid, int32_t userId = CURRENT_USER_ID)
{
return;
@@ -294,7 +308,8 @@ public:
REVOKE_URI_PERMISSION,
NOTIFY_GRANT_URI_PERMISSION_START,
NOTIFY_GRANT_URI_PERMISSION_END,
REMOVE_CALLER_IF_NEED
REMOVE_CALLER_IF_NEED,
VERIFY_URI_PERMISSION,
};
};
} // namespace AAFwk
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -167,6 +167,17 @@ public:
*/
virtual int32_t RevokeUriPermission(uint32_t tokenId) override;
/**
* @brief verify uri permission
* @param uriVec The uri list to verify permission.
* @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION.
* @param tokenId the tokenId of caller application.
* @param checkResults The result of verify uri permission.
* @return 0 when on success or else failed.
*/
virtual int32_t VerifyUriPermission(const std::vector<std::string> &uriVec, uint32_t flag, uint32_t tokenId,
std::vector<bool> &checkResults) override;
virtual void NotifyMissionBindPid(int32_t missionId, int32_t pid, int32_t userId = CURRENT_USER_ID) override;
virtual int32_t CheckStaticCfgPermission(const Want &want, bool isImplicit) override;
+13 -1
View File
@@ -151,10 +151,13 @@ private:
* @brief Internal implementation of URI permission granting
* @param uriVec Vector of URI strings
* @param grantInfo The param for grant uri permission
* @param want Want object containing URI information
* @param isBrokerCall Whether the call is from broker
* @return true if permission was successfully granted, false otherwise
* @note When isBrokerCall is true, content URIs are automatically marked as authorized
*/
bool GrantUriPermissionInner(const std::vector<std::string> &uriVec, const GrantUriPermissionInfo &grantInfo,
Want &want);
Want &want, bool isBrokerCall);
#endif // SUPPORT_UPMS
/**
@@ -260,6 +263,15 @@ private:
bool NotifyGrantUriPermissionEnd(bool isNotifyCollaborator, const std::vector<std::string> &uris,
uint32_t flag, int32_t userId, const std::vector<bool> &checkResults);
/**
* @brief Mark content URIs as authorized for broker call
* @param uriVec Vector of URI strings
* @param checkResults Check results to update
* @param isBrokerCall Whether the call is from broker
*/
void MarkContentUriAuthorizedForBroker(const std::vector<std::string> &uriVec,
std::vector<CheckResult> &checkResults, bool isBrokerCall);
DISALLOW_COPY_AND_MOVE(UriUtils);
};
} // namespace AAFwk
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -538,6 +538,46 @@ int32_t AbilityManagerCollaboratorProxy::RevokeUriPermission(uint32_t tokenId)
return reply.ReadInt32();
}
int32_t AbilityManagerCollaboratorProxy::VerifyUriPermission(const std::vector<std::string> &uriVec, uint32_t flag,
uint32_t tokenId, std::vector<bool> &checkResults)
{
MessageParcel data;
MessageParcel reply;
MessageOption option;
if (!data.WriteInterfaceToken(AbilityManagerCollaboratorProxy::GetDescriptor())) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "write token fail");
return ERR_INVALID_OPERATION;
}
if (!data.WriteStringVector(uriVec)) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "write uriVec fail");
return ERR_INVALID_OPERATION;
}
if (!data.WriteUint32(flag)) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "write flag fail");
return ERR_INVALID_OPERATION;
}
if (!data.WriteUint32(tokenId)) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "write tokenId fail");
return ERR_INVALID_OPERATION;
}
int32_t ret = SendTransactCmd(IAbilityManagerCollaborator::VERIFY_URI_PERMISSION, data, reply, option);
if (ret != NO_ERROR) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "request error:%{public}d", ret);
return ERR_INVALID_OPERATION;
}
ret = reply.ReadInt32();
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "VerifyUriPermission failed:%{public}d", ret);
return ret;
}
if (!reply.ReadBoolVector(&checkResults)) {
TAG_LOGE(AAFwkTag::ABILITYMGR, "read checkResults fail");
return ERR_INVALID_OPERATION;
}
return ERR_OK;
}
void AbilityManagerCollaboratorProxy::NotifyMissionBindPid(int32_t missionId, int32_t pid, int32_t userId)
{
MessageParcel data;
+21 -3
View File
@@ -33,6 +33,7 @@
#include "tokenid_kit.h"
#include "ui_extension_wrapper.h"
#ifdef SUPPORT_UPMS
#include "fud_constants.h"
#include "uri_permission_manager_client.h"
#endif // SUPPORT_UPMS
@@ -312,7 +313,8 @@ bool UriUtils::GrantShellUriPermission(const std::vector<std::string> &strUriVec
for (auto&& str : strUriVec) {
Uri uri(str);
auto&& scheme = uri.GetScheme();
if (scheme != "content") {
if (scheme != FUDConstants::ANCO_SCHEME) {
TAG_LOGI(AAFwkTag::ABILITYMGR, "Non-anco uri found in broker call: %{public}s", scheme.c_str());
return false;
}
uriVec.emplace_back(uri);
@@ -428,7 +430,7 @@ bool UriUtils::GrantUriPermission(Want &want, const GrantUriPermissionInfo &gran
TAG_LOGI(AAFwkTag::ABILITYMGR, "permission to shell");
return true;
}
if (!GrantUriPermissionInner(uriVec, grantInfo, want)) {
if (!GrantUriPermissionInner(uriVec, grantInfo, want, isBrokerCall)) {
return false;
}
// report open file event
@@ -436,6 +438,21 @@ bool UriUtils::GrantUriPermission(Want &want, const GrantUriPermissionInfo &gran
return true;
}
void UriUtils::MarkContentUriAuthorizedForBroker(const std::vector<std::string> &uriVec,
std::vector<CheckResult> &checkResults, bool isBrokerCall)
{
if (!isBrokerCall) {
return;
}
for (size_t i = 0; i < uriVec.size(); i++) {
Uri uri(uriVec[i]);
if (uri.GetScheme() == FUDConstants::ANCO_SCHEME) {
checkResults[i].result = true;
checkResults[i].permissionType = 0;
}
}
}
void UriUtils::ProcessUDMFKey(Want &want)
{
// PARAMS_STREAM and UDMF_DATA_KEY is conflict
@@ -445,12 +462,13 @@ void UriUtils::ProcessUDMFKey(Want &want)
}
bool UriUtils::GrantUriPermissionInner(const std::vector<std::string> &uriVec,
const GrantUriPermissionInfo &grantInfo, Want &want)
const GrantUriPermissionInfo &grantInfo, Want &want, bool isBrokerCall)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
NotifyGrantUriPermissionStart(grantInfo.isNotifyCollaborator, uriVec, grantInfo.flag, grantInfo.userId);
auto checkResults = IN_PROCESS_CALL(UriPermissionManagerClient::GetInstance().CheckUriAuthorizationWithType(
uriVec, grantInfo.flag, grantInfo.callerTokenId));
MarkContentUriAuthorizedForBroker(uriVec, checkResults, isBrokerCall);
auto permissionUris = GetPermissionedUriList(uriVec, checkResults, grantInfo.callerTokenId,
grantInfo.targetBundleName, want);
std::vector<bool> boolResults(checkResults.size(), false);
+4 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024-2025 Huawei Device Co., Ltd.
* Copyright (c) 2024-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -57,6 +57,8 @@ public:
bool SetCheckProxyByPolicyResult(const std::vector<bool> &proxyResultByPolicy);
bool SetCheckProxyByContentUriResult(const std::vector<bool> &contentUriResult);
int32_t GetUriToGrantByMap(std::vector<std::string> &uriVec);
void SelectPermissionedUri(std::vector<Uri> &uris, std::vector<int32_t> &indexs, std::vector<std::string> &uriVec);
@@ -88,6 +90,7 @@ public:
// content uri
std::vector<std::string> contentUris;
std::vector<int32_t> contentIndexes;
// caller's uri
std::vector<PolicyInfo> selfBundlePolicyInfos;
+1 -1
View File
@@ -22,7 +22,7 @@ namespace OHOS {
namespace AAFwk {
namespace FUDConstants {
constexpr const char *FILE_SCHEME = "file";
constexpr const char *CONTENT_SCHEME = "content";
constexpr const char *ANCO_SCHEME = "content";
constexpr const char *DOCS_AUTHORITY = "docs";
constexpr const char *MEDIA_AUTHORITY = "media";
} // FUDConstants
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2025 Huawei Device Co., Ltd.
* Copyright (c) 2022-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -178,6 +178,9 @@ private:
int32_t RevokeContentUriPermission(uint32_t tokenId);
int32_t VerifyContentUriPermission(const std::vector<std::string> &contentUris, uint32_t flag,
uint32_t tokenId, std::vector<bool> &checkResults);
bool IsContentUriGranted(uint32_t tokenId);
void AddContentTokenIdRecord(uint32_t tokenId);
+21 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024-2025 Huawei Device Co., Ltd.
* Copyright (c) 2024-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -40,14 +40,15 @@ int32_t BatchUri::Init(const std::vector<std::string> &uriVec, uint32_t mode, co
if (index == 0) {
TAG_LOGI(AAFwkTag::URIPERMMGR, "uri type: %{public}s.", uriInner.GetAuthority().c_str());
}
if (scheme != FUDConstants::FILE_SCHEME && scheme != FUDConstants::CONTENT_SCHEME) {
if (scheme != FUDConstants::FILE_SCHEME && scheme != FUDConstants::ANCO_SCHEME) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "uri is invalid: %{private}s.", uriInner.ToString().c_str());
continue;
}
validUriCount++;
// content uri
if (scheme == FUDConstants::CONTENT_SCHEME) {
if (scheme == FUDConstants::ANCO_SCHEME) {
contentUris.emplace_back(uriInner.ToString());
contentIndexes.emplace_back(index);
continue;
}
InitFileUriInfo(uriInner, index, mode, callerAlterBundleName, targetAlterBundleName,
@@ -270,5 +271,22 @@ bool BatchUri::IsAllUriPermissioned()
}
return true;
}
bool BatchUri::SetCheckProxyByContentUriResult(const std::vector<bool> &contentUriResult)
{
if (contentUriResult.size() != contentIndexes.size()) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "Invalid contentUriResult:%{public}zu, %{public}zu", contentUriResult.size(),
contentIndexes.size());
return false;
}
for (size_t i = 0; i < contentUriResult.size(); i++) {
auto index = contentIndexes[i];
checkResult[index].result = contentUriResult[i];
if (checkResult[index].result) {
checkResult[index].permissionType = PolicyType::AUTHORIZATION_PATH;
}
}
return true;
}
} // OHOS
} // AAFwk
@@ -332,7 +332,7 @@ bool FUDUtils::IsSandboxApp(uint32_t tokenId)
bool FUDUtils::CheckUriTypeIsValid(Uri &uri)
{
auto &&scheme = uri.GetScheme();
if (scheme != FUDConstants::FILE_SCHEME && scheme != FUDConstants::CONTENT_SCHEME) {
if (scheme != FUDConstants::FILE_SCHEME && scheme != FUDConstants::ANCO_SCHEME) {
TAG_LOGW(AAFwkTag::URIPERMMGR, "uri invalid: %{public}s-%{private}s", scheme.c_str(), uri.ToString().c_str());
return false;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2025 Huawei Device Co., Ltd.
* Copyright (c) 2022-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -537,6 +537,32 @@ int32_t UriPermissionManagerStubImpl::RevokeContentUriPermission(uint32_t tokenI
return ret;
}
int32_t UriPermissionManagerStubImpl::VerifyContentUriPermission(const std::vector<std::string> &contentUris,
uint32_t flag, uint32_t tokenId, std::vector<bool> &checkResults)
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
if (contentUris.empty()) {
return ERR_OK;
}
TAG_LOGI(AAFwkTag::URIPERMMGR, "VerifyContentUriPermission, contentUris: %{public}zu", contentUris.size());
auto abilityClient = AAFwk::AbilityManagerClient::GetInstance();
if (abilityClient == nullptr) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "abilityClient null");
return INNER_ERR;
}
auto collaborator = IN_PROCESS_CALL(abilityClient->GetAbilityManagerCollaborator());
if (collaborator == nullptr) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "collaborator null");
return INNER_ERR;
}
auto ret = collaborator->VerifyUriPermission(contentUris, flag, tokenId, checkResults);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::URIPERMMGR, "VerifyUriPermission failed:%{public}d", ret);
return ret;
}
return ERR_OK;
}
bool UriPermissionManagerStubImpl::IsContentUriGranted(uint32_t tokenId)
{
std::lock_guard<std::mutex> lock(contentTokenIdSetMutex_);
@@ -788,7 +814,7 @@ int32_t UriPermissionManagerStubImpl::GrantUriPermissionPrivilegedInner(const st
}
validUriCount++;
// content and distributed docs uri
if (uriInner.GetScheme() == FUDConstants::CONTENT_SCHEME) {
if (uriInner.GetScheme() == FUDConstants::ANCO_SCHEME) {
batchUris.contentUris.emplace_back(uriInner.ToString());
continue;
}
@@ -1185,6 +1211,15 @@ int32_t UriPermissionManagerStubImpl::CheckProxyUriPermission(BatchUri &batchUri
auto proxyResultByPolicy = VerifyUriPermissionByPolicy(proxyUrisByPolicy, flag, callerTokenId);
batchUri.SetCheckProxyByPolicyResult(proxyResultByPolicy);
}
if (!batchUri.contentUris.empty()) {
std::vector<bool> contentUriResults;
auto ret = VerifyContentUriPermission(batchUri.contentUris, flag, callerTokenId, contentUriResults);
if (ret == ERR_OK) {
batchUri.SetCheckProxyByContentUriResult(contentUriResults);
} else {
TAG_LOGW(AAFwkTag::URIPERMMGR, "VerifyContentUriPermission failed");
}
}
return ERR_OK;
}
@@ -38,6 +38,10 @@ public:
MOCK_METHOD2(NotifyClearMission, int32_t(int32_t missionId, int32_t userId));
MOCK_METHOD3(NotifyRemoveShellProcess, int32_t(int32_t pid, int32_t type, const std::string &reason));
MOCK_METHOD1(UpdateMissionInfo, void(sptr<SessionInfo> &sessionInfo));
MOCK_METHOD3(NotifyGrantUriPermissionStart, int32_t(const std::vector<std::string> &uris, uint32_t flag,
int32_t userId));
MOCK_METHOD4(NotifyGrantUriPermissionEnd, int32_t(const std::vector<std::string> &uris, uint32_t flag,
int32_t userId, const std::vector<bool> &checkResults));
sptr<IRemoteObject> AsObject() override
{
return {};
@@ -53,7 +53,7 @@ HWTEST_F(BatchUriTest, BatchUri_Branch_01, Function | MediumTest | Level1)
/**
* @tc.number: BatchUri_Branch_02
* @tc.name: Init_SpecialSchemes
* @tc.desc: Coverage: 1. CONTENT_SCHEME; 2. MEDIA_AUTHORITY.
* @tc.desc: Coverage: 1. ANCO_SCHEME; 2. MEDIA_AUTHORITY.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_02, Function | MediumTest | Level1)
{
@@ -375,5 +375,173 @@ HWTEST_F(BatchUriTest, BatchUri_Branch_22, Function | MediumTest | Level1)
EXPECT_EQ(batchUri.GetUriToGrantByPolicy(d, b), 2);
}
/**
* @tc.number: BatchUri_Branch_23
* @tc.name: SetCheckProxyByContentUriResult_Mismatch
* @tc.desc: Coverage: SetCheckProxyByContentUriResult size mismatch.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_23, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"content://test/1.txt"});
std::vector<bool> contentUriResult = {true, false}; // Size mismatch
EXPECT_FALSE(batchUri.SetCheckProxyByContentUriResult(contentUriResult));
}
/**
* @tc.number: BatchUri_Branch_24
* @tc.name: SetCheckProxyByContentUriResult_Success
* @tc.desc: Coverage: SetCheckProxyByContentUriResult success path.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_24, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"content://test/1.txt", "content://test/2.txt"});
std::vector<bool> contentUriResult = {true, false};
EXPECT_TRUE(batchUri.SetCheckProxyByContentUriResult(contentUriResult));
EXPECT_TRUE(batchUri.checkResult[0].result);
EXPECT_FALSE(batchUri.checkResult[1].result);
EXPECT_EQ(batchUri.checkResult[0].permissionType, static_cast<int32_t>(PolicyType::AUTHORIZATION_PATH));
}
/**
* @tc.number: BatchUri_Branch_25
* @tc.name: SetCheckProxyByContentUriResult_AllTrue
* @tc.desc: Coverage: SetCheckProxyByContentUriResult all true.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_25, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"content://test/1.txt", "content://test/2.txt"});
std::vector<bool> contentUriResult = {true, true};
EXPECT_TRUE(batchUri.SetCheckProxyByContentUriResult(contentUriResult));
EXPECT_TRUE(batchUri.IsAllUriPermissioned());
}
/**
* @tc.number: BatchUri_Branch_26
* @tc.name: IsAllUriValid_Partial
* @tc.desc: Coverage: IsAllUriValid with some invalid URIs.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_26, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://valid/1.txt", "ftp://invalid/2.txt", "file://valid/3.txt"});
EXPECT_FALSE(batchUri.IsAllUriValid());
EXPECT_EQ(batchUri.validUriCount, 2);
EXPECT_EQ(batchUri.totalUriCount, 3);
}
/**
* @tc.number: BatchUri_Branch_27
* @tc.name: IsAllUriValid_AllValid
* @tc.desc: Coverage: IsAllUriValid all URIs valid.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_27, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://valid/1.txt", "file://valid/2.txt"});
EXPECT_TRUE(batchUri.IsAllUriValid());
}
/**
* @tc.number: BatchUri_Branch_28
* @tc.name: GetPermissionedUriCount_All
* @tc.desc: Coverage: GetPermissionedUriCount all permissioned.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_28, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://1.txt", "file://2.txt", "file://3.txt"});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
batchUri.checkResult[0].result = true;
batchUri.checkResult[1].result = true;
batchUri.checkResult[2].result = true;
EXPECT_EQ(batchUri.GetPermissionedUriCount(), 3);
}
/**
* @tc.number: BatchUri_Branch_29
* @tc.name: GetPermissionedUriCount_None
* @tc.desc: Coverage: GetPermissionedUriCount none permissioned.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_29, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://1.txt", "file://2.txt"});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
EXPECT_EQ(batchUri.GetPermissionedUriCount(), 0);
}
/**
* @tc.number: BatchUri_Branch_30
* @tc.name: Init_ContentUri_Mixed
* @tc.desc: Coverage: Init with content URIs mixed with file URIs.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_30, Function | MediumTest | Level1)
{
BatchUri batchUri;
std::vector<std::string> uris = {
"content://test/1.txt",
"file://media/2.txt",
"content://test/3.txt",
"file://docs/4.txt"
};
EXPECT_EQ(batchUri.Init(uris), 4);
EXPECT_EQ(batchUri.contentUris.size(), 2);
EXPECT_EQ(batchUri.mediaUris.size(), 1);
EXPECT_EQ(batchUri.otherUris.size(), 1);
}
/**
* @tc.number: BatchUri_Branch_31
* @tc.name: SetCheckProxyByPolicyResult_TargetBundleTrue
* @tc.desc: Coverage: SetCheckProxyByPolicyResult with target bundle true.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_31, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://target/1.txt"}, 0, "", "target", false);
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
std::vector<PolicyInfo> proxyUris;
batchUri.GetNeedCheckProxyPermissionURI(proxyUris);
EXPECT_TRUE(batchUri.SetCheckProxyByPolicyResult({true}));
EXPECT_EQ(batchUri.targetBundleUriCount, 1);
}
/**
* @tc.number: BatchUri_Branch_32
* @tc.name: GetUriToGrantByPolicy2_EmptySelfBundle
* @tc.desc: Coverage: GetUriToGrantByPolicy2 with empty selfBundlePolicyInfos.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_32, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://docs/1.txt"});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
batchUri.checkResult[0].result = true;
std::vector<PolicyInfo> policyVec;
EXPECT_TRUE(batchUri.GetUriToGrantByPolicy(policyVec));
EXPECT_EQ(policyVec.size(), 1);
}
/**
* @tc.number: BatchUri_Branch_33
* @tc.name: GetUriToGrantByPolicy2_OnlySelfBundle
* @tc.desc: Coverage: GetUriToGrantByPolicy2 with only self bundle URIs.
*/
HWTEST_F(BatchUriTest, BatchUri_Branch_33, Function | MediumTest | Level1)
{
BatchUri batchUri;
batchUri.Init({"file://caller/1.txt"}, 1, "caller", "", false);
batchUri.checkResult[0].result = true;
std::vector<PolicyInfo> policyVec;
EXPECT_TRUE(batchUri.GetUriToGrantByPolicy(policyVec));
EXPECT_EQ(policyVec.size(), 1);
}
} // AAFwk
} // OHOS
@@ -128,6 +128,7 @@ ohos_unittest("uri_permission_manager_stub_impl_test") {
"mock/src/mock_file_uri_distribution_utils.cpp",
"mock/src/mock_my_flag.cpp",
"mock/src/mock_iability_manager_collaborator.cpp",
"mock/src/mock_permission_verification.cpp",
"uri_permission_manager_stub_impl_test.cpp",
]
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Copyright (c) 2025-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -29,9 +29,15 @@ public:
int32_t GrantUriPermission(const std::vector<std::string> &uriVec, uint32_t flag, uint32_t targetTokenId,
const std::string &targetBundleName);
int32_t RevokeUriPermission(uint32_t tokenId);
int32_t VerifyUriPermission(const std::vector<std::string> &uriVec, uint32_t flag, uint32_t tokenId,
std::vector<bool> &checkResults);
int32_t NotifyGrantUriPermissionStart(const std::vector<std::string> &uris, uint32_t flag, int32_t userId);
int32_t NotifyGrantUriPermissionEnd(const std::vector<std::string> &uris, uint32_t flag, int32_t userId,
const std::vector<bool> &checkResults);
public:
static int32_t grantResult;
static int32_t revokeResult;
static int32_t verifyResult;
};
} // namespace AAFwk
} // namespace OHOS
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Copyright (c) 2025-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -42,7 +42,30 @@ int32_t IAbilityManagerCollaborator::RevokeUriPermission(uint32_t tokenId)
return revokeResult;
}
int32_t IAbilityManagerCollaborator::VerifyUriPermission(const std::vector<std::string> &uriVec, uint32_t flag,
uint32_t tokenId, std::vector<bool> &checkResults)
{
TAG_LOGI(AAFwkTag::URIPERMMGR, "VerifyUriPermission: %{public}d", verifyResult);
checkResults.resize(uriVec.size(), true);
return verifyResult;
}
int32_t IAbilityManagerCollaborator::NotifyGrantUriPermissionStart(const std::vector<std::string> &uris, uint32_t flag,
int32_t userId)
{
TAG_LOGI(AAFwkTag::URIPERMMGR, "NotifyGrantUriPermissionStart: %{public}d", grantResult);
return grantResult;
}
int32_t IAbilityManagerCollaborator::NotifyGrantUriPermissionEnd(const std::vector<std::string> &uris, uint32_t flag,
int32_t userId, const std::vector<bool> &checkResults)
{
TAG_LOGI(AAFwkTag::URIPERMMGR, "NotifyGrantUriPermissionEnd: %{public}d", grantResult);
return grantResult;
}
int32_t IAbilityManagerCollaborator::grantResult = 0;
int32_t IAbilityManagerCollaborator::revokeResult = 0;
int32_t IAbilityManagerCollaborator::verifyResult = 0;
} // namespace AAFwk
} // namespace OHOS
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2025 Huawei Device Co., Ltd.
* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -17,6 +17,7 @@
#include "ability_manager_client.h"
#include "mock_my_flag.h"
#include "batch_uri.h"
#define private public
#define protected public
@@ -47,7 +48,11 @@ void UriPermissionManagerStubImplTest::SetUpTestCase() {}
void UriPermissionManagerStubImplTest::TearDownTestCase() {}
void UriPermissionManagerStubImplTest::SetUp() {}
void UriPermissionManagerStubImplTest::SetUp()
{
MyFlag::Init();
IAbilityManagerCollaborator::verifyResult = 0;
}
void UriPermissionManagerStubImplTest::TearDown() {}
@@ -699,5 +704,79 @@ HWTEST_F(UriPermissionManagerStubImplTest, Upmsi_RawDataToPolicyInfo_001, TestSi
EXPECT_EQ(result, INVALID_PARAMETERS_ERR);
#endif
}
/*
* Feature: UriPermissionManagerService
* Function: VerifyContentUriPermission
* SubFunction: NA
* FunctionPoints: VerifyContentUriPermission with empty contentUris
*/
HWTEST_F(UriPermissionManagerStubImplTest, VerifyContentUriPermission_001, TestSize.Level1)
{
auto upmsi = std::make_shared<UriPermissionManagerStubImpl>();
std::vector<std::string> contentUris; // Empty
uint32_t flag = 1;
uint32_t tokenId = 1;
std::vector<bool> checkResults;
auto result = upmsi->VerifyContentUriPermission(contentUris, flag, tokenId, checkResults);
EXPECT_EQ(result, ERR_OK);
}
/*
* Feature: UriPermissionManagerService
* Function: CheckProxyUriPermission
* SubFunction: NA
* FunctionPoints: CheckProxyUriPermission without proxy authorization permission
*/
HWTEST_F(UriPermissionManagerStubImplTest, CheckProxyUriPermission_001, TestSize.Level1)
{
auto upmsi = std::make_shared<UriPermissionManagerStubImpl>();
MyFlag::permissionProxyAuthorization_ = false;
BatchUri batchUri;
batchUri.Init({"file://test/file.txt"});
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
uint32_t callerTokenId = 1;
uint32_t flag = 1;
auto result = upmsi->CheckProxyUriPermission(batchUri, callerTokenId, flag);
EXPECT_EQ(result, CHECK_PERMISSION_FAILED);
}
/*
* Feature: UriPermissionManagerService
* Function: CheckProxyUriPermission
* SubFunction: NA
* FunctionPoints: CheckProxyUriPermission with empty proxyUrisByPolicy and empty contentUris
*/
HWTEST_F(UriPermissionManagerStubImplTest, CheckProxyUriPermission_002, TestSize.Level1)
{
auto upmsi = std::make_shared<UriPermissionManagerStubImpl>();
MyFlag::permissionProxyAuthorization_ = true;
BatchUri batchUri;
batchUri.Init({"file://caller/file.txt"}, 0, "caller", "", false);
uint32_t callerTokenId = 1;
uint32_t flag = 1;
auto result = upmsi->CheckProxyUriPermission(batchUri, callerTokenId, flag);
EXPECT_EQ(result, ERR_OK);
}
/*
* Feature: UriPermissionManagerService
* Function: CheckProxyUriPermission
* SubFunction: NA
* FunctionPoints: CheckProxyUriPermission with proxyUrisByPolicy
*/
HWTEST_F(UriPermissionManagerStubImplTest, CheckProxyUriPermission_003, TestSize.Level1)
{
auto upmsi = std::make_shared<UriPermissionManagerStubImpl>();
MyFlag::permissionProxyAuthorization_ = true;
BatchUri batchUri;
batchUri.Init({"file://docs/file.txt"}, 0, "", "target", false);
batchUri.otherPolicyInfos.emplace_back(PolicyInfo{});
uint32_t callerTokenId = 1;
uint32_t flag = 1;
auto result = upmsi->CheckProxyUriPermission(batchUri, callerTokenId, flag);
EXPECT_EQ(result, ERR_OK);
}
} // namespace AAFwk
} // namespace OHOS
@@ -194,5 +194,72 @@ HWTEST_F(UriUtilsSecondTest, IsSandboxApp_002, TestSize.Level1)
bool ret = UriUtils::GetInstance().IsSandboxApp(tokenId);
EXPECT_TRUE(ret);
}
/*
* Feature: UriUtils
* Function: IsSandboxApp
* SubFunction: NA
* FunctionPoints: UriUtils IsSandboxApp with hap token.
*/
HWTEST_F(UriUtilsSecondTest, IsSandboxApp_003, TestSize.Level1)
{
MyFlag::flag_ = 1;
MyFlag::bundleName_ = "bundleName";
uint32_t tokenId = 1001;
bool ret = UriUtils::GetInstance().IsSandboxApp(tokenId);
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: PublishFileOpenEvent
* SubFunction: NA
* FunctionPoints: PublishFileOpenEvent with non-file scheme.
*/
HWTEST_F(UriUtilsSecondTest, PublishFileOpenEvent_004, TestSize.Level1)
{
Want want;
want.SetUri("content://test/file.txt");
GrantUriPermissionInfo grantInfo;
grantInfo.targetBundleName = "com.example.test";
grantInfo.targetAbilityName = "MainAbility";
grantInfo.userId = 100;
grantInfo.callerUid = 20010080;
UriUtils::GetInstance().PublishFileOpenEvent(want, grantInfo);
// Should not publish event for non-file scheme
// Verify the URI is set correctly and scheme is content (not file)
std::string uri = want.GetUri().ToString();
EXPECT_FALSE(uri.empty());
EXPECT_NE(uri.find("content://"), std::string::npos);
}
/*
* Feature: UriUtils
* Function: IsDmsCall
* SubFunction: NA
* FunctionPoints: IsDmsCall with non-native token.
*/
HWTEST_F(UriUtilsSecondTest, IsDmsCall_005, TestSize.Level1)
{
MyFlag::flag_ = 2; // HAP type
uint32_t fromTokenId = TOKEN_ID;
bool ret = UriUtils::GetInstance().IsDmsCall(fromTokenId);
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: IsDmsCall
* SubFunction: NA
* FunctionPoints: IsDmsCall with get native info failed.
*/
HWTEST_F(UriUtilsSecondTest, IsDmsCall_006, TestSize.Level1)
{
MyFlag::flag_ = 3; // Native type but get info fails
uint32_t fromTokenId = TOKEN_ID;
bool ret = UriUtils::GetInstance().IsDmsCall(fromTokenId);
EXPECT_FALSE(ret);
}
}
}
+426 -2
View File
@@ -703,7 +703,7 @@ HWTEST_F(UriUtilsTest, GrantUriPermissionInner_001, TestSize.Level1)
grantInfo.appIndex = 0;
grantInfo.targetBundleName = "com.example.tsapplication";
grantInfo.isNotifyCollaborator = false;
bool res = UriUtils::GetInstance().GrantUriPermissionInner(uriVec, grantInfo, want);
bool res = UriUtils::GetInstance().GrantUriPermissionInner(uriVec, grantInfo, want, false);
EXPECT_EQ(res, false);
}
#endif // SUPPORT_UPMS
@@ -1071,7 +1071,7 @@ HWTEST_F(UriUtilsTest, NotifyGrantUriPermissionEnd_001, TestSize.Level1)
auto ret = UriUtils::GetInstance().NotifyGrantUriPermissionEnd(isNotifyCollaborator, uris, userId, flag,
checkResults);
EXPECT_EQ(ret, true);
isNotifyCollaborator = true;
AbilityManagerClient::isNullInstance_ = true;
ret = UriUtils::GetInstance().NotifyGrantUriPermissionEnd(isNotifyCollaborator, uris, userId, flag,
@@ -1089,5 +1089,429 @@ HWTEST_F(UriUtilsTest, NotifyGrantUriPermissionEnd_001, TestSize.Level1)
checkResults);
EXPECT_EQ(ret, true);
}
/*
* Feature: UriUtils
* Function: IsServiceExtensionType
* SubFunction: NA
* FunctionPoints: IsServiceExtensionType UI_SERVICE branch.
*/
HWTEST_F(UriUtilsTest, IsServiceExtensionType_001, TestSize.Level1)
{
auto ret = UriUtils::GetInstance().IsServiceExtensionType(
AppExecFwk::ExtensionAbilityType::UI_SERVICE);
EXPECT_EQ(ret, true);
ret = UriUtils::GetInstance().IsServiceExtensionType(
AppExecFwk::ExtensionAbilityType::FORM);
EXPECT_EQ(ret, false);
ret = UriUtils::GetInstance().IsServiceExtensionType(
AppExecFwk::ExtensionAbilityType::SERVICE);
EXPECT_EQ(ret, true);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWant
* SubFunction: NA
* FunctionPoints: GetUriListFromWant with both uri and paramStream.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWant_002, TestSize.Level1)
{
Want want;
std::string uri = "file://data/test.txt";
want.SetUri(uri);
std::vector<std::string> paramStreamUris = {"file://data/test2.txt"};
want.SetParam("ability.params.stream", paramStreamUris);
std::vector<std::string> uriVec;
bool ret = UriUtils::GetInstance().GetUriListFromWant(want, uriVec);
EXPECT_EQ(ret, true);
EXPECT_EQ(uriVec.size(), 2);
EXPECT_EQ(uriVec[0], uri);
EXPECT_EQ(uriVec[1], paramStreamUris[0]);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWant
* SubFunction: NA
* FunctionPoints: GetUriListFromWant with only uri.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWant_003, TestSize.Level1)
{
Want want;
std::string uri = "file://data/test.txt";
want.SetUri(uri);
std::vector<std::string> uriVec;
bool ret = UriUtils::GetInstance().GetUriListFromWant(want, uriVec);
EXPECT_EQ(ret, true);
EXPECT_EQ(uriVec.size(), 1);
EXPECT_EQ(uriVec[0], uri);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWant
* SubFunction: NA
* FunctionPoints: GetUriListFromWant with only paramStream.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWant_004, TestSize.Level1)
{
Want want;
std::vector<std::string> paramStreamUris = {"file://data/test.txt"};
want.SetParam("ability.params.stream", paramStreamUris);
std::vector<std::string> uriVec;
bool ret = UriUtils::GetInstance().GetUriListFromWant(want, uriVec);
EXPECT_EQ(ret, true);
EXPECT_EQ(uriVec.size(), 1);
EXPECT_EQ(uriVec[0], paramStreamUris[0]);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWant
* SubFunction: NA
* FunctionPoints: GetUriListFromWant resize paramStream when uri empty.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWant_005, TestSize.Level1)
{
Want want;
std::vector<std::string> paramStreamUris;
for (int i = 0; i < BEYOND_MAX_URI_COUNT; i++) {
paramStreamUris.push_back("file://data/test.txt");
}
want.SetParam("ability.params.stream", paramStreamUris);
std::vector<std::string> uriVec;
bool ret = UriUtils::GetInstance().GetUriListFromWant(want, uriVec);
EXPECT_EQ(ret, true);
EXPECT_EQ(uriVec.size(), MAX_URI_COUNT);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWant
* SubFunction: NA
* FunctionPoints: GetUriListFromWant resize paramStream when uri present.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWant_006, TestSize.Level1)
{
Want want;
want.SetUri("file://data/test.txt");
std::vector<std::string> paramStreamUris;
for (int i = 0; i < MAX_URI_COUNT; i++) {
paramStreamUris.push_back("file://data/test.txt");
}
want.SetParam("ability.params.stream", paramStreamUris);
std::vector<std::string> uriVec;
bool ret = UriUtils::GetInstance().GetUriListFromWant(want, uriVec);
EXPECT_EQ(ret, true);
EXPECT_EQ(uriVec.size(), MAX_URI_COUNT);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWantDms
* SubFunction: NA
* FunctionPoints: GetUriListFromWantDms non-existent file uri.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWantDms_002, TestSize.Level1)
{
Want want;
std::vector<std::string> uriStrVec = {"file://data/storage/el2/distributedfiles/test.txt"};
want.SetParam("ability.verify.uri", uriStrVec);
auto uriList = UriUtils::GetInstance().GetUriListFromWantDms(want);
// Expected 0 because the file path doesn't exist in test environment,
// causing realpath to fail and skip this URI
EXPECT_EQ(uriList.size(), 0);
}
/*
* Feature: UriUtils
* Function: GetUriListFromWantDms
* SubFunction: NA
* FunctionPoints: GetUriListFromWantDms non-file uri.
*/
HWTEST_F(UriUtilsTest, GetUriListFromWantDms_003, TestSize.Level1)
{
Want want;
std::vector<std::string> uriStrVec = {"content://test/file.txt"};
want.SetParam("ability.verify.uri", uriStrVec);
auto uriList = UriUtils::GetInstance().GetUriListFromWantDms(want);
EXPECT_EQ(uriList.size(), 0);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission with vector.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_Vector_001, TestSize.Level1)
{
std::vector<std::string> uriVec = {"file://data/test.txt"};
int32_t flag = 1;
std::string targetBundleName = "com.example.test";
int32_t appIndex = 0;
uint32_t initiatorTokenId = 1001;
// This is a void function, verify it executes without exception
UriUtils::GetInstance().GrantUriPermission(uriVec, flag, targetBundleName, appIndex, initiatorTokenId);
EXPECT_EQ(uriVec.size(), 1u); // Verify input state remains unchanged
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission with empty vector.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_Vector_002, TestSize.Level1)
{
std::vector<std::string> uriVec;
int32_t flag = 1;
std::string targetBundleName = "com.example.test";
int32_t appIndex = 0;
uint32_t initiatorTokenId = 1001;
UriUtils::GetInstance().GrantUriPermission(uriVec, flag, targetBundleName, appIndex, initiatorTokenId);
EXPECT_TRUE(uriVec.empty()); // Verify empty vector remains empty
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission collaborator broker rejection.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_Collaborator_001, TestSize.Level1)
{
Want want;
want.SetFlags(1);
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 1;
grantInfo.targetBundleName = "com.ohos.broker";
grantInfo.callerTokenId = 1001;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
grantInfo.isSandboxApp = false;
want.SetUri("file://data/test.txt");
// Mock the broker delegate bundle name
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
// Should be rejected because collaboratorType is OTHERS_TYPE
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermissionInner
* SubFunction: NA
* FunctionPoints: GrantUriPermissionInner isBrokerCall marks content uri.
*/
HWTEST_F(UriUtilsTest, GrantUriPermissionInner_Broker_001, TestSize.Level1)
{
std::vector<std::string> uriVec = {"content://test/file.txt"};
Want want;
GrantUriPermissionInfo grantInfo;
grantInfo.callerTokenId = 1001;
grantInfo.flag = 1;
grantInfo.appIndex = 0;
grantInfo.targetBundleName = "com.example.test";
grantInfo.isNotifyCollaborator = false;
auto ret = UriUtils::GetInstance().GrantUriPermissionInner(uriVec, grantInfo, want, true);
// GrantUriPermissionInner returns bool, check the result
// Since CheckUriAuthorizationWithType is mocked, we expect it to return the mock result
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission DMS call path.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_DMS_001, TestSize.Level1)
{
Want want;
std::vector<std::string> uriStrVec = {"file://data/storage/el2/distributedfiles/test.txt"};
want.SetParam("ability.verify.uri", uriStrVec);
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 1;
grantInfo.targetBundleName = "com.example.test";
grantInfo.callerTokenId = 1001;
grantInfo.appIndex = 0;
grantInfo.isSandboxApp = false;
grantInfo.isNotifyCollaborator = false;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
// Mock DMS call
AccessTokenKit::getTokenTypeFlagRet = ATokenTypeEnum::TOKEN_NATIVE;
AccessTokenKit::getNativeTokenInfoRet = 0;
AccessTokenKit::nativeTokenInfo.processName = "distributedsched";
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
// Should call GrantDmsUriPermission and return success
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission broker call path.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_Broker_001, TestSize.Level1)
{
Want want;
want.SetUri("content://test/file.txt");
want.SetParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME, std::string("com.ohos.broker"));
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 1;
grantInfo.targetBundleName = "com.example.test";
grantInfo.callerTokenId = 1001;
grantInfo.appIndex = 0;
grantInfo.isSandboxApp = false;
grantInfo.isNotifyCollaborator = false;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
// Should call GrantShellUriPermission and return success
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission normal grant path with no uri.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_NoUri_001, TestSize.Level1)
{
Want want;
// Don't set any URI
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 1;
grantInfo.targetBundleName = "com.example.test";
grantInfo.callerTokenId = 1001;
grantInfo.appIndex = 0;
grantInfo.isSandboxApp = false;
grantInfo.isNotifyCollaborator = false;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission with invalid flag.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_InvalidFlag_001, TestSize.Level1)
{
Want want;
want.SetUri("file://data/test.txt");
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 0; // Invalid flag
grantInfo.targetBundleName = "com.example.test";
grantInfo.callerTokenId = 1001;
grantInfo.appIndex = 0;
grantInfo.isSandboxApp = false;
grantInfo.isNotifyCollaborator = false;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission with empty target bundle name.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_EmptyTarget_001, TestSize.Level1)
{
Want want;
want.SetUri("file://data/test.txt");
want.SetFlags(1);
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 1;
grantInfo.targetBundleName = ""; // Empty target bundle
grantInfo.callerTokenId = 1001;
grantInfo.appIndex = 0;
grantInfo.isSandboxApp = false;
grantInfo.isNotifyCollaborator = false;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermission
* SubFunction: NA
* FunctionPoints: GrantUriPermission with zero caller token id.
*/
HWTEST_F(UriUtilsTest, GrantUriPermission_ZeroToken_001, TestSize.Level1)
{
Want want;
want.SetUri("file://data/test.txt");
want.SetFlags(1);
GrantUriPermissionInfo grantInfo;
grantInfo.flag = 1;
grantInfo.targetBundleName = "com.example.test";
grantInfo.callerTokenId = 0; // Zero token id
grantInfo.appIndex = 0;
grantInfo.isSandboxApp = false;
grantInfo.isNotifyCollaborator = false;
grantInfo.collaboratorType = CollaboratorType::OTHERS_TYPE;
auto ret = UriUtils::GetInstance().GrantUriPermission(want, grantInfo);
EXPECT_FALSE(ret);
}
/*
* Feature: UriUtils
* Function: GrantUriPermissionInner
* SubFunction: NA
* FunctionPoints: GrantUriPermissionInner notify collaborator.
*/
HWTEST_F(UriUtilsTest, GrantUriPermissionInner_Notify_001, TestSize.Level1)
{
std::vector<std::string> uriVec = {"file://data/test.txt"};
Want want;
GrantUriPermissionInfo grantInfo;
grantInfo.callerTokenId = 1001;
grantInfo.flag = 1;
grantInfo.appIndex = 0;
grantInfo.targetBundleName = "com.example.test";
grantInfo.isNotifyCollaborator = true;
grantInfo.userId = 100;
AbilityManagerClient::collaborator_ = std::make_shared<MockAbilityManagerCollaborator>();
auto ret = UriUtils::GetInstance().GrantUriPermissionInner(uriVec, grantInfo, want, false);
// Should notify collaborator and return success
EXPECT_FALSE(ret);
}
}
}