diff --git a/interfaces/inner_api/ability_manager/include/iability_manager_collaborator.h b/interfaces/inner_api/ability_manager/include/iability_manager_collaborator.h index e1113a8ffa..1a82c80961 100644 --- a/interfaces/inner_api/ability_manager/include/iability_manager_collaborator.h +++ b/interfaces/inner_api/ability_manager/include/iability_manager_collaborator.h @@ -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 &uriVec, uint32_t flag, uint32_t tokenId, + std::vector &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 diff --git a/services/abilitymgr/include/ability_manager_collaborator_proxy.h b/services/abilitymgr/include/ability_manager_collaborator_proxy.h index 07afbaff10..1fafa4709f 100644 --- a/services/abilitymgr/include/ability_manager_collaborator_proxy.h +++ b/services/abilitymgr/include/ability_manager_collaborator_proxy.h @@ -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 &uriVec, uint32_t flag, uint32_t tokenId, + std::vector &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; diff --git a/services/abilitymgr/include/utils/uri_utils.h b/services/abilitymgr/include/utils/uri_utils.h index 68982a393c..3798d9e153 100644 --- a/services/abilitymgr/include/utils/uri_utils.h +++ b/services/abilitymgr/include/utils/uri_utils.h @@ -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 &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 &uris, uint32_t flag, int32_t userId, const std::vector &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 &uriVec, + std::vector &checkResults, bool isBrokerCall); + DISALLOW_COPY_AND_MOVE(UriUtils); }; } // namespace AAFwk diff --git a/services/abilitymgr/src/ability_manager_collaborator_proxy.cpp b/services/abilitymgr/src/ability_manager_collaborator_proxy.cpp index ef476413a8..a5fe28d4ce 100644 --- a/services/abilitymgr/src/ability_manager_collaborator_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_collaborator_proxy.cpp @@ -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 &uriVec, uint32_t flag, + uint32_t tokenId, std::vector &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; diff --git a/services/abilitymgr/src/utils/uri_utils.cpp b/services/abilitymgr/src/utils/uri_utils.cpp index 7bdbea9e97..d0cf656b24 100644 --- a/services/abilitymgr/src/utils/uri_utils.cpp +++ b/services/abilitymgr/src/utils/uri_utils.cpp @@ -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 &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 &uriVec, + std::vector &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 &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 boolResults(checkResults.size(), false); diff --git a/services/uripermmgr/include/batch_uri.h b/services/uripermmgr/include/batch_uri.h index dfc3da069d..15dd54dc21 100644 --- a/services/uripermmgr/include/batch_uri.h +++ b/services/uripermmgr/include/batch_uri.h @@ -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 &proxyResultByPolicy); + bool SetCheckProxyByContentUriResult(const std::vector &contentUriResult); + int32_t GetUriToGrantByMap(std::vector &uriVec); void SelectPermissionedUri(std::vector &uris, std::vector &indexs, std::vector &uriVec); @@ -88,6 +90,7 @@ public: // content uri std::vector contentUris; + std::vector contentIndexes; // caller's uri std::vector selfBundlePolicyInfos; diff --git a/services/uripermmgr/include/fud_constants.h b/services/uripermmgr/include/fud_constants.h index dadfc1638c..39400331f3 100644 --- a/services/uripermmgr/include/fud_constants.h +++ b/services/uripermmgr/include/fud_constants.h @@ -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 diff --git a/services/uripermmgr/include/uri_permission_manager_stub_impl.h b/services/uripermmgr/include/uri_permission_manager_stub_impl.h index 7cd553e45b..a299e7e193 100644 --- a/services/uripermmgr/include/uri_permission_manager_stub_impl.h +++ b/services/uripermmgr/include/uri_permission_manager_stub_impl.h @@ -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 &contentUris, uint32_t flag, + uint32_t tokenId, std::vector &checkResults); + bool IsContentUriGranted(uint32_t tokenId); void AddContentTokenIdRecord(uint32_t tokenId); diff --git a/services/uripermmgr/src/batch_uri.cpp b/services/uripermmgr/src/batch_uri.cpp index a5dd4241b7..288ee0ff93 100644 --- a/services/uripermmgr/src/batch_uri.cpp +++ b/services/uripermmgr/src/batch_uri.cpp @@ -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 &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 &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 \ No newline at end of file diff --git a/services/uripermmgr/src/file_uri_distribution_utils.cpp b/services/uripermmgr/src/file_uri_distribution_utils.cpp index 36fc2efb1f..0f43cf09eb 100644 --- a/services/uripermmgr/src/file_uri_distribution_utils.cpp +++ b/services/uripermmgr/src/file_uri_distribution_utils.cpp @@ -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; } diff --git a/services/uripermmgr/src/uri_permission_manager_stub_impl.cpp b/services/uripermmgr/src/uri_permission_manager_stub_impl.cpp index c0ef901396..89d3119b98 100644 --- a/services/uripermmgr/src/uri_permission_manager_stub_impl.cpp +++ b/services/uripermmgr/src/uri_permission_manager_stub_impl.cpp @@ -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 &contentUris, + uint32_t flag, uint32_t tokenId, std::vector &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 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 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; } diff --git a/test/mock/ability_manager_collaborator/mock_ability_manager_collaborator.h b/test/mock/ability_manager_collaborator/mock_ability_manager_collaborator.h index afa97f5ded..5f8364ed1b 100644 --- a/test/mock/ability_manager_collaborator/mock_ability_manager_collaborator.h +++ b/test/mock/ability_manager_collaborator/mock_ability_manager_collaborator.h @@ -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)); + MOCK_METHOD3(NotifyGrantUriPermissionStart, int32_t(const std::vector &uris, uint32_t flag, + int32_t userId)); + MOCK_METHOD4(NotifyGrantUriPermissionEnd, int32_t(const std::vector &uris, uint32_t flag, + int32_t userId, const std::vector &checkResults)); sptr AsObject() override { return {}; diff --git a/test/new_test/unit_test/batch_uri_unit_test/batch_uri_unit_test.cpp b/test/new_test/unit_test/batch_uri_unit_test/batch_uri_unit_test.cpp index 52678a27ac..4f813c750c 100644 --- a/test/new_test/unit_test/batch_uri_unit_test/batch_uri_unit_test.cpp +++ b/test/new_test/unit_test/batch_uri_unit_test/batch_uri_unit_test.cpp @@ -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 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 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(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 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 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 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 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 policyVec; + EXPECT_TRUE(batchUri.GetUriToGrantByPolicy(policyVec)); + EXPECT_EQ(policyVec.size(), 1); +} + } // AAFwk } // OHOS diff --git a/test/unittest/uri_permission_impl_test/BUILD.gn b/test/unittest/uri_permission_impl_test/BUILD.gn index 2a8782b63e..86ee60e4b0 100755 --- a/test/unittest/uri_permission_impl_test/BUILD.gn +++ b/test/unittest/uri_permission_impl_test/BUILD.gn @@ -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", ] diff --git a/test/unittest/uri_permission_impl_test/mock/include/mock_iability_manager_collaborator.h b/test/unittest/uri_permission_impl_test/mock/include/mock_iability_manager_collaborator.h index 1e81696be5..e17d0aeef3 100644 --- a/test/unittest/uri_permission_impl_test/mock/include/mock_iability_manager_collaborator.h +++ b/test/unittest/uri_permission_impl_test/mock/include/mock_iability_manager_collaborator.h @@ -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 &uriVec, uint32_t flag, uint32_t targetTokenId, const std::string &targetBundleName); int32_t RevokeUriPermission(uint32_t tokenId); + int32_t VerifyUriPermission(const std::vector &uriVec, uint32_t flag, uint32_t tokenId, + std::vector &checkResults); + int32_t NotifyGrantUriPermissionStart(const std::vector &uris, uint32_t flag, int32_t userId); + int32_t NotifyGrantUriPermissionEnd(const std::vector &uris, uint32_t flag, int32_t userId, + const std::vector &checkResults); public: static int32_t grantResult; static int32_t revokeResult; + static int32_t verifyResult; }; } // namespace AAFwk } // namespace OHOS diff --git a/test/unittest/uri_permission_impl_test/mock/src/mock_iability_manager_collaborator.cpp b/test/unittest/uri_permission_impl_test/mock/src/mock_iability_manager_collaborator.cpp index 57e5124bbe..23087b8295 100644 --- a/test/unittest/uri_permission_impl_test/mock/src/mock_iability_manager_collaborator.cpp +++ b/test/unittest/uri_permission_impl_test/mock/src/mock_iability_manager_collaborator.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 @@ -42,7 +42,30 @@ int32_t IAbilityManagerCollaborator::RevokeUriPermission(uint32_t tokenId) return revokeResult; } +int32_t IAbilityManagerCollaborator::VerifyUriPermission(const std::vector &uriVec, uint32_t flag, + uint32_t tokenId, std::vector &checkResults) +{ + TAG_LOGI(AAFwkTag::URIPERMMGR, "VerifyUriPermission: %{public}d", verifyResult); + checkResults.resize(uriVec.size(), true); + return verifyResult; +} + +int32_t IAbilityManagerCollaborator::NotifyGrantUriPermissionStart(const std::vector &uris, uint32_t flag, + int32_t userId) +{ + TAG_LOGI(AAFwkTag::URIPERMMGR, "NotifyGrantUriPermissionStart: %{public}d", grantResult); + return grantResult; +} + +int32_t IAbilityManagerCollaborator::NotifyGrantUriPermissionEnd(const std::vector &uris, uint32_t flag, + int32_t userId, const std::vector &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 \ No newline at end of file diff --git a/test/unittest/uri_permission_impl_test/uri_permission_manager_stub_impl_test.cpp b/test/unittest/uri_permission_impl_test/uri_permission_manager_stub_impl_test.cpp index b5860166ac..c3f47547c0 100644 --- a/test/unittest/uri_permission_impl_test/uri_permission_manager_stub_impl_test.cpp +++ b/test/unittest/uri_permission_impl_test/uri_permission_manager_stub_impl_test.cpp @@ -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(); + std::vector contentUris; // Empty + uint32_t flag = 1; + uint32_t tokenId = 1; + std::vector 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(); + 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(); + 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(); + 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 \ No newline at end of file diff --git a/test/unittest/uri_utils_second_test/uri_utils_second_test.cpp b/test/unittest/uri_utils_second_test/uri_utils_second_test.cpp index 14eaf603c6..d74805d17c 100644 --- a/test/unittest/uri_utils_second_test/uri_utils_second_test.cpp +++ b/test/unittest/uri_utils_second_test/uri_utils_second_test.cpp @@ -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); +} } } \ No newline at end of file diff --git a/test/unittest/uri_utils_test/uri_utils_test.cpp b/test/unittest/uri_utils_test/uri_utils_test.cpp index f87d6e5c98..faa06041bc 100644 --- a/test/unittest/uri_utils_test/uri_utils_test.cpp +++ b/test/unittest/uri_utils_test/uri_utils_test.cpp @@ -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 paramStreamUris = {"file://data/test2.txt"}; + want.SetParam("ability.params.stream", paramStreamUris); + + std::vector 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 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 paramStreamUris = {"file://data/test.txt"}; + want.SetParam("ability.params.stream", paramStreamUris); + + std::vector 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 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 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 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 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 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 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 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 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 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 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 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(); + + auto ret = UriUtils::GetInstance().GrantUriPermissionInner(uriVec, grantInfo, want, false); + // Should notify collaborator and return success + EXPECT_FALSE(ret); +} + } } \ No newline at end of file