From 3d5e0a264595193b91c394980a774073a46cf1f4 Mon Sep 17 00:00:00 2001 From: lanhaoyu Date: Tue, 18 Mar 2025 17:41:10 +0800 Subject: [PATCH] add code Signed-off-by: lanhaoyu --- access_token.gni | 6 - bundle.json | 2 +- frameworks/ets/ani/BUILD.gn | 25 ++ frameworks/ets/ani/accesstoken/BUILD.gn | 69 ++++++ .../ets/@ohos.abilityAccessCtrl.ets | 114 ++++++++++ .../accesstoken/src/ability_access_ctrl.cpp | 138 +++++++++++ frameworks/ets/ani/common/BUILD.gn | 42 ++++ frameworks/ets/ani/common/include/ani_error.h | 67 ++++++ frameworks/ets/ani/common/src/ani_error.cpp | 214 ++++++++++++++++++ frameworks/ets/ani/privacy/BUILD.gn | 70 ++++++ .../ani/privacy/ets/@ohos.privacyManager.ets | 94 ++++++++ .../ets/ani/privacy/src/privacy_manager.cpp | 140 ++++++++++++ 12 files changed, 974 insertions(+), 7 deletions(-) create mode 100644 frameworks/ets/ani/BUILD.gn create mode 100644 frameworks/ets/ani/accesstoken/BUILD.gn create mode 100644 frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets create mode 100644 frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp create mode 100644 frameworks/ets/ani/common/BUILD.gn create mode 100644 frameworks/ets/ani/common/include/ani_error.h create mode 100644 frameworks/ets/ani/common/src/ani_error.cpp create mode 100644 frameworks/ets/ani/privacy/BUILD.gn create mode 100644 frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets create mode 100644 frameworks/ets/ani/privacy/src/privacy_manager.cpp diff --git a/access_token.gni b/access_token.gni index dee74ca93..3c8f3ea55 100644 --- a/access_token.gni +++ b/access_token.gni @@ -34,12 +34,6 @@ if (vendor_config_exist) { access_token_impl_include_dirs = [] } -if (product_name != "qemu-arm-linux-min") { - qemu_disable = true -} else { - qemu_disable = false -} - if (!defined(global_parts_info) || defined(global_parts_info.distributedhardware_device_manager)) { token_sync_enable = true diff --git a/bundle.json b/bundle.json index 49cabb8dc..3fd65d453 100644 --- a/bundle.json +++ b/bundle.json @@ -71,7 +71,7 @@ "//base/security/access_token/interfaces/kits/capi:capi_packages", "//base/security/access_token/interfaces/kits/cj:cj_packages", "//base/security/access_token/frameworks/js/napi:napi_packages", - "//base/security/access_token/frameworks/js/arkts:arkts_package" + "//base/security/access_token/frameworks/ets/ani:arkts_package" ], "service_group": [ "//base/security/access_token/interfaces/innerkits/tokensync:libtokensync_sdk", diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn new file mode 100644 index 000000000..fb76ab2d7 --- /dev/null +++ b/frameworks/ets/ani/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2025 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/access_token/access_token.gni") + +group("arkts_package") { + deps = [] + if (support_jsapi) { + deps += [ + "accesstoken:accesstoken_ets", + "common:libani_common", + "privacy:privacy_ets", + ] + } +} diff --git a/frameworks/ets/ani/accesstoken/BUILD.gn b/frameworks/ets/ani/accesstoken/BUILD.gn new file mode 100644 index 000000000..d407a574e --- /dev/null +++ b/frameworks/ets/ani/accesstoken/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2025 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/access_token/access_token.gni") +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") + +ohos_shared_library("accesstoken_ani") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + cflags_cc = [ "-DHILOG_ENABLE" ] + include_dirs = [ + "${access_token_path}/frameworks/common/include", + "${access_token_path}/interfaces/innerkits/accesstoken/include", + "${access_token_path}/interfaces/innerkits/privacy/include", + ] + sources = [ "src/ability_access_ctrl.cpp" ] + + deps = [ + "${access_token_path}/interfaces/innerkits/accesstoken:libaccesstoken_sdk", + "${access_token_path}/interfaces/innerkits/privacy:libprivacy_sdk", + ] + + external_deps = [ + "hilog:libhilog", + "runtime_core:ani", + "runtime_core:libarkruntime", + ] + + part_name = "access_token" + subsystem_name = "security" +} + +generate_static_abc("ability_access_ctrl") { + base_url = "./ets" + files = [ "./ets/@ohos.abilityAccessCtrl.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_access_ctrl.abc" +} + +ohos_prebuilt_etc("ability_access_ctrl_etc") { + source = "$target_out_dir/ability_access_ctrl.abc" + deps = [ ":ability_access_ctrl" ] + module_install_dir = "framework" + part_name = "access_token" + subsystem_name = "security" +} + +group("accesstoken_ets") { + deps = [ + ":ability_access_ctrl_etc", + ":accesstoken_ani", + ] +} diff --git a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets new file mode 100644 index 000000000..8892e950a --- /dev/null +++ b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2025 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncCallback, Callback } from '@ohos.base'; +import { Permissions } from 'permissions'; +import type _PermissionRequestResult from 'security.PermissionRequestResult'; + +export { Permissions }; + +export type PermissionRequestResult = _PermissionRequestResult; + +export default namespace abilityAccessCtrl { + + loadLibrary("accesstoken_ani.z"); + + export enum GrantStatus { + + PERMISSION_DENIED = -1, + + PERMISSION_GRANTED = 0 + } + + export enum PermissionRequestToggleStatus { + + CLOSED = 0, + + OPEN = 1, + } + + export enum PermissionStatus { + + DENIED = -1, + + GRANTED = 0, + + NOT_DETERMINED = 1, + + INVALID = 2, + + RESTRICTED = 3 + } + + interface PermissionStateChangeInfo { + + change: PermissionStateChangeType; + + tokenID: number; + + permissionName: Permissions; + } + + export enum PermissionStateChangeType { + + PERMISSION_REVOKED_OPER = 0, + + PERMISSION_GRANTED_OPER = 1 + } + + export enum SwitchType { + + CAMERA = 0, + + MICROPHONE = 1, + + LOCATION = 2, + } + + native function createAtManager(): AtManager; + + interface AtManager { + checkAccessTokenANI(tokenID: int, permissionName: Permissions): int; + checkAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus; + checkAccessToken(tokenID: int, permissionName: Permissions): Promise + } + + class AtManagerInner implements AtManager { + native checkAccessTokenANI(tokenID: int, permissionName: Permissions): int; + checkAccessTokenSync(tokenID: int, permissionName: Permissions): GrantStatus{ + let result = this.checkAccessTokenANI(tokenID, permissionName); + if (result == 0) { + return GrantStatus.PERMISSION_GRANTED + } + return GrantStatus.PERMISSION_DENIED + } + checkAccessToken(tokenID: int, permissionName: Permissions): Promise { + let p = new Promise((resolve: (v: GrantStatus) => void, reject: (error: Object) => void) => { + let p1 = taskpool.execute((): int => { return new AtManagerInner().checkAccessTokenANI(tokenID, + permissionName)}); + p1.then((e: NullishType) => { + if(e == 0){ + resolve(GrantStatus.PERMISSION_GRANTED); + }else{ + resolve(GrantStatus.PERMISSION_DENIED); + } + }, (err: Object): void => { + }); + } + ); + return p; + } + } +} \ No newline at end of file diff --git a/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp b/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp new file mode 100644 index 000000000..c3621be53 --- /dev/null +++ b/frameworks/ets/ani/accesstoken/src/ability_access_ctrl.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2025 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "accesstoken_log.h" +#include "ani.h" +#include "accesstoken_kit.h" + +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AniAbilityAccessCtrl" }; +constexpr int32_t MAX_LENGTH = 256; + +static ani_object CreateAtManager([[maybe_unused]] ani_env *env) +{ + ani_object atManagerObj = {}; + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); + return atManagerObj; + } + + static const char *className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", className); + return atManagerObj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "get ctor Failed %{public}s", className); + return atManagerObj; + } + + if (ANI_OK != env->Object_New(cls, ctor, &atManagerObj)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Create Object Failed %{public}s", className); + return atManagerObj; + } + + return atManagerObj; +} + +static ani_int CheckAccessTokenSync([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_int tokenID, + ani_string permissionName) +{ + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr vm"); + return OHOS::Security::AccessToken::PermissionState::PERMISSION_DENIED; + } + + ani_size strSize; + env->String_GetUTF8Size(permissionName, &strSize); + + if (strSize > MAX_LENGTH) { + ACCESSTOKEN_LOG_ERROR(LABEL, "the max lenth :%{public}d", MAX_LENGTH); + return OHOS::Security::AccessToken::PermissionState::PERMISSION_DENIED; + } + + std::vector buffer(strSize + 1); + char *utf8Buffer = buffer.data(); + + ani_size bytesWritten = 0; + env->String_GetUTF8(permissionName, utf8Buffer, strSize + 1, &bytesWritten); + + utf8Buffer[bytesWritten] = '\0'; + std::string outputPermissionName = std::string(utf8Buffer); + + int result = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, outputPermissionName); + ACCESSTOKEN_LOG_INFO(LABEL, "call CheckAccessTokenSync result : %{public}d", result); + return static_cast(result); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr vm"); + return ANI_INVALID_ARGS; + } + + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Unsupported ANI_VERSION_1"); + return ANI_OUT_OF_MEMORY; + } + + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); + return ANI_NOT_FOUND; + } + + const char *spaceName = "L@ohos/abilityAccessCtrl/abilityAccessCtrl;"; + ani_namespace spc; + if (ANI_OK != env->FindNamespace(spaceName, &spc)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", spaceName); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function{ "createAtManager", nullptr, reinterpret_cast(CreateAtManager) }, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(spc, methods.data(), methods.size())) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", spaceName); + return ANI_ERROR; + }; + + const char *className = "L@ohos/abilityAccessCtrl/abilityAccessCtrl/AtManagerInner;"; + + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + std::cerr << "Not found '" << className << "'" << std::endl; + return ANI_ERROR; + } + + std::array claMethods = { + ani_native_function{ + "checkAccessTokenANI", "ILstd/core/String;:I", reinterpret_cast(CheckAccessTokenSync) }, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, claMethods.data(), claMethods.size())) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", className); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/ani/common/BUILD.gn b/frameworks/ets/ani/common/BUILD.gn new file mode 100644 index 000000000..49877d006 --- /dev/null +++ b/frameworks/ets/ani/common/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2022-2023 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//base/security/access_token/access_token.gni") + +ohos_static_library("libani_common") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + include_dirs = [ + "./include", + ] + + sources = [ + "src/ani_error.cpp", + ] + + deps = ["${access_token_path}/frameworks/common:accesstoken_common_cxx",] + cflags_cc = [ "-DHILOG_ENABLE" ] + external_deps = [ + "hilog:libhilog", + "runtime_core:ani", + ] + + subsystem_name = "security" + part_name = "access_token" +} diff --git a/frameworks/ets/ani/common/include/ani_error.h b/frameworks/ets/ani/common/include/ani_error.h new file mode 100644 index 000000000..f681e8418 --- /dev/null +++ b/frameworks/ets/ani/common/include/ani_error.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_PRIVACY_KITS_ANI_ERROR_H +#define INTERFACES_PRIVACY_KITS_ANI_ERROR_H + +#include +#include + +namespace OHOS { +namespace Security { +namespace AccessToken { +typedef enum { + STS_OK = 0, + STS_ERROR_PERMISSION_DENIED = 201, + STS_ERROR_NOT_SYSTEM_APP = 202, + STS_ERROR_PARAM_ILLEGAL = 401, + STS_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT = 801, + STS_ERROR_START_ABILITY_FAIL = 1011, + STS_ERROR_BACKGROUND_FAIL = 1012, + STS_ERROR_TERMINATE_FAIL = 1013, + STS_ERROR_PARAM_INVALID = 12100001, + STS_ERROR_TOKENID_NOT_EXIST, + STS_ERROR_PERMISSION_NOT_EXIST, + STS_ERROR_NOT_USE_TOGETHER, + STS_ERROR_REGISTERS_EXCEED_LIMITATION, + STS_ERROR_PERMISSION_OPERATION_NOT_ALLOWED, + STS_ERROR_SERVICE_NOT_RUNNING, + STS_ERROR_OUT_OF_MEMORY, + STS_ERROR_INNER, + STS_ERROR_REQUEST_IS_ALREADY_EXIST = 12100010, + STS_ERROR_ALL_PERM_GRANTED = 12100011, + STS_ERROR_PERM_REVOKE_BY_USER = 12100012, + STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN = 12100013, +} STSErrorCode; + +class BusinessErrorAni { +public: + static ani_object CreateError(ani_env *env, ani_int code, const std::string &msg); + static ani_object CreateCommonError( + ani_env *env, int32_t err, const std::string &functionName = "", const std::string &permissionName = ""); + static ani_object CreateEnumError(ani_env *env, const std::string ¶meter, const std::string &enumClass); + static void ThrowTooFewParametersError(ani_env *env, int32_t err); + static void ThrowParameterTypeError(ani_env *env, int32_t err, + const std::string ¶meter, const std::string &type); + static void ThrowEnumError(ani_env *env, const std::string ¶meter, const std::string &type); + static void ThrowError(ani_env *env, int32_t err, const std::string &msg = ""); +private: + static void ThrowError(ani_env *env, ani_object err); +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif /* INTERFACES_PRIVACY_KITS_ANI_ERROR_H */ + diff --git a/frameworks/ets/ani/common/src/ani_error.cpp b/frameworks/ets/ani/common/src/ani_error.cpp new file mode 100644 index 000000000..a261bbfb7 --- /dev/null +++ b/frameworks/ets/ani/common/src/ani_error.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ani_error.h" +#include "accesstoken_log.h" +#include + +namespace OHOS { +namespace Security { +namespace AccessToken { +namespace { +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_PRIVACY, "CommonAni"}; +} // namespace +constexpr const char* BUSINESS_ERROR_CLASS = "L@ohos/base/BusinessError;"; +constexpr const char* ERR_MSG_PARAM_NUMBER_ERROR = + "BusinessError 401: Parameter error. The number of parameters is incorrect."; +constexpr const char* ERR_MSG_ENUM_EROOR = + "Parameter error. The value of $ is not a valid enum $."; +constexpr const char* ERR_MSG_BUSINESS_ERROR = "BusinessError $: "; +constexpr const char* ERR_MSG_PARAM_TYPE_ERROR = "Parameter error. The type of $ must be $."; +static const std::unordered_map g_errorStringMap = { + {STS_ERROR_PERMISSION_DENIED, "Permission denied."}, + {STS_ERROR_NOT_SYSTEM_APP, "Not system app."}, + {STS_ERROR_SYSTEM_CAPABILITY_NOT_SUPPORT, "Not support system capability."}, + {STS_ERROR_START_ABILITY_FAIL, "Start grant ability failed."}, + {STS_ERROR_BACKGROUND_FAIL, "Ui extension turn background failed."}, + {STS_ERROR_TERMINATE_FAIL, "Ui extension terminate failed."}, + {STS_ERROR_PARAM_INVALID, "Invalid parameter."}, + {STS_ERROR_TOKENID_NOT_EXIST, "The specified token id does not exist."}, + {STS_ERROR_PERMISSION_NOT_EXIST, "The specified permission does not exist."}, + {STS_ERROR_NOT_USE_TOGETHER, "The API is not used in pair with others."}, + {STS_ERROR_REGISTERS_EXCEED_LIMITATION, "The number of registered listeners exceeds limitation."}, + {STS_ERROR_PERMISSION_OPERATION_NOT_ALLOWED, "The operation of specified permission is not allowed."}, + {STS_ERROR_SERVICE_NOT_RUNNING, "The service is abnormal."}, + {STS_ERROR_OUT_OF_MEMORY, "Out of memory."}, + {STS_ERROR_INNER, "Common inner error."}, + {STS_ERROR_REQUEST_IS_ALREADY_EXIST, "The request already exists."}, + {STS_ERROR_ALL_PERM_GRANTED, "All permissions in the permission list have been granted."}, + {STS_ERROR_PERM_REVOKE_BY_USER, + "The permission list contains the permission that has not been revoked by the user."}, + {STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN, "The specific global switch is already open."}, + { STS_ERROR_PARAM_ILLEGAL, ERR_MSG_PARAM_TYPE_ERROR }, +}; + +void BusinessErrorAni::ThrowError(ani_env *env, int32_t err, const std::string &msg) +{ + if (env == nullptr) { + return; + } + ani_object error = CreateError(env, err, msg); + ThrowError(env, error); +} + +ani_object BusinessErrorAni::CreateError(ani_env *env, ani_int code, const std::string& msg) +{ + if (env == nullptr) { + return nullptr; + } + ani_class cls = nullptr; + ani_field field = nullptr; + ani_method method = nullptr; + ani_object obj = nullptr; + + env->ExistUnhandledError(&errorExists) + +/* 会报错误码6的那行代码 */ + + ani_status status = env->FindClass(BUSINESS_ERROR_CLASS, &cls); + + std::ostringstream buffer; + std::streambuf *oldStderr = std::cerr.rdbuf(buffer.rdbuf()); + ani_status status = env->DescribeError(); + std::cerr.rdbuf(oldStderr); + std::stirng output = buffer.str(); + env->ExistUnhandledError(&errorExists) + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass : %{public}s", output.c_str()); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "FindClass : %{public}d", status); + return nullptr; + } + status = env->Class_FindMethod(cls, "", ":V", &method); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindMethod : %{public}d", status); + return nullptr; + } + status = env->Object_New(cls, method, &obj); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_New : %{public}d", status); + return nullptr; + } + status = env->Class_FindField(cls, "code", &field); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindField : %{public}d", status); + return nullptr; + } + status = env->Object_SetField_Double(obj, field, code); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_SetField_Double : %{public}d", status); + return nullptr; + } + status = env->Class_FindField(cls, "message", &field); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Class_FindField : %{public}d", status); + return nullptr; + } + ani_string string = nullptr; + env->String_NewUTF8(msg.c_str(), msg.size(), &string); + status = env->Object_SetField_Ref(obj, field, string); + if (status != ANI_OK) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_SetField_Ref : %{public}d", status); + return nullptr; + } + return obj; +} + + +void BusinessErrorAni::ThrowParameterTypeError(ani_env *env, int32_t err, + const std::string ¶meter, const std::string &type) +{ + if (env == nullptr) { + return; + } + ani_object error = CreateCommonError(env, err, parameter, type); + ThrowError(env, error); +} + +void BusinessErrorAni::ThrowTooFewParametersError(ani_env *env, int32_t err) +{ + if (env == nullptr) { + return; + } + ThrowError(env, err, ERR_MSG_PARAM_NUMBER_ERROR); +} + +ani_object BusinessErrorAni::CreateCommonError( + ani_env *env, int32_t err, const std::string &functionName, const std::string &permissionName) +{ + if (env == nullptr) { + return nullptr; + } + std::string errMessage = ERR_MSG_BUSINESS_ERROR; + auto iter = errMessage.find("$"); + if (iter != std::string::npos) { + errMessage = errMessage.replace(iter, 1, std::to_string(err)); + } + if (g_errorStringMap.find(err) != g_errorStringMap.end()) { + errMessage += g_errorStringMap.at(err); + } + iter = errMessage.find("$"); + if (iter != std::string::npos) { + errMessage = errMessage.replace(iter, 1, functionName); + iter = errMessage.find("$"); + if (iter != std::string::npos) { + errMessage = errMessage.replace(iter, 1, permissionName); + } + } + return CreateError(env, err, errMessage); +} + +void BusinessErrorAni::ThrowEnumError(ani_env *env, + const std::string ¶meter, const std::string &type) +{ + if (env == nullptr) { + return; + } + ani_object error = CreateEnumError(env, parameter, type); + ThrowError(env, error); +} + +ani_object BusinessErrorAni::CreateEnumError(ani_env *env, + const std::string ¶meter, const std::string &enumClass) +{ + if (env == nullptr) { + return nullptr; + } + std::string errMessage = ERR_MSG_BUSINESS_ERROR; + auto iter = errMessage.find("$"); + if (iter != std::string::npos) { + errMessage = errMessage.replace(iter, 1, std::to_string(STS_ERROR_PARAM_ILLEGAL)); + } + errMessage += ERR_MSG_ENUM_EROOR; + iter = errMessage.find("$"); + if (iter != std::string::npos) { + errMessage = errMessage.replace(iter, 1, parameter); + iter = errMessage.find("$"); + if (iter != std::string::npos) { + errMessage = errMessage.replace(iter, 1, enumClass); + } + } + return CreateError(env, STS_ERROR_PARAM_ILLEGAL, errMessage); +} + +void BusinessErrorAni::ThrowError(ani_env *env, ani_object err) +{ + if (err == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "err is nullptr"); + return; + } + env->ThrowError(static_cast(err)); +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS diff --git a/frameworks/ets/ani/privacy/BUILD.gn b/frameworks/ets/ani/privacy/BUILD.gn new file mode 100644 index 000000000..52b0053e5 --- /dev/null +++ b/frameworks/ets/ani/privacy/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2025 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/access_token/access_token.gni") +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") + +ohos_shared_library("privacy_ani") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + cflags_cc = [ "-DHILOG_ENABLE" ] + include_dirs = [ + "${access_token_path}/frameworks/common/include", + "${access_token_path}/interfaces/innerkits/accesstoken/include", + "${access_token_path}/interfaces/innerkits/privacy/include", + "${access_token_path}/interfaces/kits/js/napi/common/include", + ] + sources = [ "src/privacy_manager.cpp" ] + + deps = [ "${access_token_path}/interfaces/innerkits/privacy:libprivacy_sdk" ] + + external_deps = [ + "hilog:libhilog", + "napi:ace_napi", + "runtime_core:ani", + "runtime_core:libarkruntime", + ] + + part_name = "access_token" + subsystem_name = "security" +} + +generate_static_abc("privacy_manager") { + base_url = "./ets" + files = [ "./ets/@ohos.privacyManager.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/privacy_manager.abc" +} + +ohos_prebuilt_etc("privacy_manager_etc") { + source = "$target_out_dir/privacy_manager.abc" + deps = [ ":privacy_manager" ] + module_install_dir = "framework" + + part_name = "access_token" + subsystem_name = "security" +} + +group("privacy_ets") { + deps = [ + ":privacy_ani", + ":privacy_manager_etc", + ] +} diff --git a/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets new file mode 100644 index 000000000..a0b790e00 --- /dev/null +++ b/frameworks/ets/ani/privacy/ets/@ohos.privacyManager.ets @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncCallback, Callback } from '@ohos.base'; +import { Permissions } from 'permissions'; + +export { Permissions } + +export default namespace privacyManager { + + loadLibrary("privacy_ani.z"); + + enum PermissionUsedType { + + NORMAL_TYPE = 0, + + PICKER_TYPE = 1, + + SECURITY_COMPONENT_TYPE = 2 + } + + interface AddPermissionUsedRecordOptions { + usedType?: PermissionUsedType; + } + + class AddPermissionUsedRecordOptionsInner implements AddPermissionUsedRecordOptions { + usedType: PermissionUsedType|undefined; + } + + class PrivacyManagerInner { + + native addPermissionUsedRecordSync(tokenID: int, permissionName: Permissions, successCount: int, failCount: int, + options: AddPermissionUsedRecordOptionsInner): int; + + } + + interface UsedRecordDetail { + + status: number; + + lockScreenStatus?: number; + + timestamp: number; + + count?: number; + + accessDuration: number; + + usedType?: PermissionUsedType; + } + + interface PermissionUsedTypeInfo { + + tokenId: number; + + permissionName: Permissions; + + usedType: PermissionUsedType; + } + + function addPermissionUsedRecord(tokenID: int, permissionName: Permissions, successCount: int, + failCount: int, options?: AddPermissionUsedRecordOptions): Promise { + + let usedTypeTemp : PermissionUsedType|undefined = options ? options.usedType : PermissionUsedType.NORMAL_TYPE + + let optionsLocal: AddPermissionUsedRecordOptionsInner = { + usedType: usedTypeTemp + }; + let p = new Promise((resolve: (v: int) => void, reject: (error: Object) => void) => { + let p1 = taskpool.execute((): int => { return new PrivacyManagerInner().addPermissionUsedRecordSync(tokenID, + permissionName, successCount, failCount, optionsLocal) }); + + p1.then((e: NullishType) => { + let r: Int = e as Int; + resolve(r.intValue()); + }, (err: Object): void => { + }); + } + ); + return p; + } +} \ No newline at end of file diff --git a/frameworks/ets/ani/privacy/src/privacy_manager.cpp b/frameworks/ets/ani/privacy/src/privacy_manager.cpp new file mode 100644 index 000000000..99e163755 --- /dev/null +++ b/frameworks/ets/ani/privacy/src/privacy_manager.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2025 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "accesstoken_log.h" +#include "ani.h" +#include "napi_error.h" +#include "privacy_error.h" +#include "privacy_kit.h" + +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_PRIVACY, "AniPrivacyManager" }; +constexpr int32_t MAX_LENGTH = 256; + +static int AddPermissionUsedRecordSync( + ani_int tokenID, const std::string &permissionName, ani_int successCount, ani_int failCount, ani_int ntype) +{ + OHOS::Security::AccessToken::AddPermParamInfo info; + info.tokenId = tokenID; + info.permissionName = permissionName; + info.successCount = successCount; + info.failCount = failCount; + info.type = static_cast(ntype); + auto retCode = OHOS::Security::AccessToken::PrivacyKit::AddPermissionUsedRecord(info); + ACCESSTOKEN_LOG_INFO(LABEL, "call addPermissionUsedRecord retCode : %{public}d", retCode); + return retCode; +} + +static ani_int AddPermissionUsedRecord([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_int tokenID, ani_string permissionName, ani_int successCount, ani_int failCount, ani_object options) +{ + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr vm"); + return OHOS::Security::AccessToken::PrivacyError::ERR_PARAM_INVALID; + } + + ani_size strSize; + ani_status status = ANI_ERROR; + if (ANI_OK != (status = env->String_GetUTF8Size(permissionName, &strSize))) { + ACCESSTOKEN_LOG_ERROR(LABEL, "get String_GetUTF8Size Faild status : %{public}d", status); + return OHOS::Security::AccessToken::JsErrorCode::JS_ERROR_PARAM_ILLEGAL; + } + + if (strSize > MAX_LENGTH) { + ACCESSTOKEN_LOG_ERROR(LABEL, "the max lenth : %{public}d", MAX_LENGTH); + return OHOS::Security::AccessToken::PrivacyError::ERR_PARAM_INVALID; + } + + std::vector buffer(strSize + 1); + char *utf8Buffer = buffer.data(); + + ani_size bytesWritten = 0; + if (ANI_OK != (status = env->String_GetUTF8(permissionName, utf8Buffer, strSize + 1, &bytesWritten))) { + ACCESSTOKEN_LOG_ERROR(LABEL, "get String_GetUTF8 Faild status : %{public}d", status); + return OHOS::Security::AccessToken::PrivacyError::ERR_PARAM_INVALID; + } + + utf8Buffer[bytesWritten] = '\0'; + std::string outputPermissionName = std::string(utf8Buffer); + + ani_ref usedTypeRef; + if (ANI_OK != (status = env->Object_GetPropertyByName_Ref(options, "usedType", &usedTypeRef))) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Object_GetFieldByName_Ref Faild status : %{public}d", status); + return OHOS::Security::AccessToken::PrivacyError::ERR_PARAM_INVALID; + } + + ani_int usedType = 0; + ani_boolean isUndefined = true; + if (ANI_OK != (status = env->Reference_IsUndefined(usedTypeRef, &isUndefined))) { + ACCESSTOKEN_LOG_ERROR(LABEL, "status : %{public}d", status); + return OHOS::Security::AccessToken::PrivacyError::ERR_PARAM_INVALID; + } + if (isUndefined) { + ACCESSTOKEN_LOG_INFO(LABEL, "usedType : undefined"); + } else { + ani_enum_item usedTypeEnum = static_cast(usedTypeRef); + + if (ANI_OK != env->EnumItem_GetValue_Int(usedTypeEnum, &usedType)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "EnumItem_GetValue_Int Faild"); + return OHOS::Security::AccessToken::PrivacyError::ERR_PARAM_INVALID; + } + } + + ACCESSTOKEN_LOG_INFO(LABEL,"Object_GetFieldByName_Ref tokenID:%{public}d PermissionName:%{public}s \ + successCount:%{public}d failCount:%{public}d usedType:%{public}d", + tokenID, outputPermissionName.c_str(), successCount, failCount, usedType); + + return AddPermissionUsedRecordSync(tokenID, outputPermissionName, successCount, failCount, usedType); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr || result == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr vm or result"); + return ANI_INVALID_ARGS; + } + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Unsupported ANI_VERSION_1"); + return ANI_OUT_OF_MEMORY; + } + + if (env == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "nullptr env"); + return ANI_NOT_FOUND; + } + + const char *className = "L@ohos/privacyManager/privacyManager/PrivacyManagerInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Not found %{public}s", className); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function{ "addPermissionUsedRecordSync", + "ILstd/core/String;IIL@ohos/privacyManager/privacyManager/AddPermissionUsedRecordOptionsInner;:I", + reinterpret_cast(AddPermissionUsedRecord) }, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Cannot bind native methods to %{public}s", className); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file -- Gitee