From 5775f2d768c9040f6375633a43086076b03947d5 Mon Sep 17 00:00:00 2001 From: lanhaoyu Date: Thu, 6 Mar 2025 19:44:08 +0800 Subject: [PATCH] add code Signed-off-by: lanhaoyu --- access_token.gni | 6 + bundle.json | 6 +- frameworks/js/arkts/BUILD.gn | 24 + .../accesstoken/aniabilityAccessCtrl/BUILD.gn | 86 ++ .../arkts/privacy/PermissionRequestResult.ets | 118 ++ .../arkts/privacy/abilityAccessCtrl_ani.ets | 176 +++ .../arkts/privacy/permissions.ets | 36 + .../arkts/privacy/test/main.ets | 71 + .../aniabilityAccessCtrl/arktsconfig.json | 33 + .../native/ani_abilityAccessCtrl.cpp | 1204 +++++++++++++++++ .../native/ani_abilityAccessCtrl.h | 147 ++ .../arkts/privacy/aniprivacyManager/BUILD.gn | 52 + .../arkts/privacy/permissions.ets | 36 + .../arkts/privacy/privacyManager_ani.ets | 97 ++ .../arkts/privacy/test/main.ets | 32 + .../aniprivacyManager/arktsconfig.json | 21 + .../native/ani_privacyManager.cpp | 103 ++ 17 files changed, 2246 insertions(+), 2 deletions(-) create mode 100644 frameworks/js/arkts/BUILD.gn create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/BUILD.gn create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/PermissionRequestResult.ets create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/abilityAccessCtrl_ani.ets create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/permissions.ets create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/test/main.ets create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arktsconfig.json create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.cpp create mode 100644 frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.h create mode 100644 frameworks/js/arkts/privacy/aniprivacyManager/BUILD.gn create mode 100644 frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/permissions.ets create mode 100644 frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/privacyManager_ani.ets create mode 100644 frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/test/main.ets create mode 100644 frameworks/js/arkts/privacy/aniprivacyManager/arktsconfig.json create mode 100644 frameworks/js/arkts/privacy/aniprivacyManager/native/ani_privacyManager.cpp diff --git a/access_token.gni b/access_token.gni index 3c8f3ea55..dee74ca93 100644 --- a/access_token.gni +++ b/access_token.gni @@ -34,6 +34,12 @@ 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 207d968ef..49cabb8dc 100644 --- a/bundle.json +++ b/bundle.json @@ -57,7 +57,8 @@ "selinux_adapter", "sqlite", "window_manager", - "zlib" + "zlib", + "runtime_core" ], "third_party": [] }, @@ -69,7 +70,8 @@ "fwk_group": [ "//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/napi:napi_packages", + "//base/security/access_token/frameworks/js/arkts:arkts_package" ], "service_group": [ "//base/security/access_token/interfaces/innerkits/tokensync:libtokensync_sdk", diff --git a/frameworks/js/arkts/BUILD.gn b/frameworks/js/arkts/BUILD.gn new file mode 100644 index 000000000..9279b3c30 --- /dev/null +++ b/frameworks/js/arkts/BUILD.gn @@ -0,0 +1,24 @@ +# 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 (qemu_disable) { + deps += [ + "accesstoken/aniabilityAccessCtrl:ani_abilityAccessCtrl", + "privacy/aniprivacyManager:ani_privacyManager", + ] + } +} diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/BUILD.gn b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/BUILD.gn new file mode 100644 index 000000000..006f78949 --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/BUILD.gn @@ -0,0 +1,86 @@ +# 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("aniabilityAccessCtrl") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "${access_token_path}/interfaces/innerkits/accesstoken/include", + "${access_token_path}/interfaces/innerkits/privacy/include", + "//base/security/access_token/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/", + + "${access_token_path}/frameworks/common/include", + "${access_token_path}/frameworks/privacy/include", + "${access_token_path}/interfaces/kits/js/napi/common/include", + "${access_token_path}/interfaces/kits/js/napi/privacy/include", + "${access_token_path}/interfaces/innerkits/token_setproc/include", + "${access_token_path}/interfaces/innerkits/token_callback/include", + ] + sources = [ "native/ani_abilityAccessCtrl.cpp" ] + + deps = [ + "${access_token_path}/interfaces/innerkits/accesstoken:libaccesstoken_sdk", + "${access_token_path}/interfaces/innerkits/privacy:libprivacy_sdk", + "${access_token_path}/interfaces/innerkits/token_callback:libtoken_callback_sdk", + "${access_token_path}/interfaces/innerkits/token_setproc:libtokensetproc_shared", + ] + + external_deps = [ + "runtime_core:ani", + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:napi_base_context", + "ability_runtime:ui_extension", + "ace_engine:ace_uicontent", + "c_utils:utils", + "hilog:libhilog", + "init:libbegetutil", + "ipc:ipc_single", + "napi:ace_napi", + ] + + part_name = "access_token" + subsystem_name = "security" +} + +generate_static_abc("abilityAccessCtrl_abc") { + arktsconfig = "arktsconfig.json" + dst_file = "$target_out_dir/abilityAccessCtrl_ani.abc" + out_puts = [ "$target_out_dir/abilityAccessCtrl_ani.abc" ] +} + +# ohos_prebuilt_etc("abilityAccessCtrl_abc_file") { +# source = "$target_out_dir/abilityAccessCtrl_ani.abc" +# deps = [ ":abilityAccessCtrl_abc" ] +# module_install_dir = "framework" +# part_name = "access_token" +# subsystem_name = "security" +# } + +group("ani_abilityAccessCtrl") { + deps = [ + ":abilityAccessCtrl_abc", + ":aniabilityAccessCtrl", + ] +} diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/PermissionRequestResult.ets b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/PermissionRequestResult.ets new file mode 100644 index 000000000..73f1987e4 --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/PermissionRequestResult.ets @@ -0,0 +1,118 @@ +/* + * 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. + */ + +/** + * @file + * @kit AbilityKit + */ + +/** + * The result of requestPermissionsFromUser with asynchronous callback. + * + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @since 9 + */ +/** + * The result of requestPermissionsFromUser with asynchronous callback. + * + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @crossplatform + * @since 10 + */ +/** + * The result of requestPermissionsFromUser with asynchronous callback. + * + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @crossplatform + * @atomicservice + * @since 11 + */ +export class PermissionRequestResult { + /** + * The permissions passed in by the user. + * + * @type { Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @since 9 + */ + /** + * The permissions passed in by the user. + * + * @type { Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @crossplatform + * @since 10 + */ + /** + * The permissions passed in by the user. + * + * @type { Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @crossplatform + * @atomicservice + * @since 11 + */ + permissions: Array = new Array(); + + /** + * The results for the corresponding request permissions. The value 0 indicates that a + * permission is granted, the value -1 indicates not, and the value 2 indicates the request is invalid. + * + * @type { Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @since 9 + */ + /** + * The results for the corresponding request permissions. The value 0 indicates that a + * permission is granted, the value -1 indicates not, and the value 2 indicates the request is invalid. + * + * @type { Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @crossplatform + * @since 10 + */ + /** + * The results for the corresponding request permissions. The value 0 indicates that a + * permission is granted, the value -1 indicates not, and the value 2 indicates the request is invalid. + * + * @type { Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @crossplatform + * @atomicservice + * @since 11 + */ + authResults: Array = new Array(); + + /** + * Specifies whether a dialog box is shown for each requested permission. + * The value true means that a dialog box is shown, and false means the opposite. + * + * @type { ?Array } + * @syscap SystemCapability.Security.AccessToken + * @stagemodelonly + * @atomicservice + * @since 12 + */ + dialogShownResults?: Array; +} \ No newline at end of file diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/abilityAccessCtrl_ani.ets b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/abilityAccessCtrl_ani.ets new file mode 100644 index 000000000..e066d61f0 --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/abilityAccessCtrl_ani.ets @@ -0,0 +1,176 @@ +/* + * 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 { Permissions } from './permissions'; +import { PermissionRequestResult } from './PermissionRequestResult'; +import { Context } from 'ContextSts'; +// import type _Context from 'ContextSts'; + +// export Context; +// export PermissionRequestResult; +export { Permissions ,PermissionRequestResult , Context }; + +export class BusinessError { + code: number; + data: T; + } + + type AsyncCallback = (err: BusinessError, data: T) => void; + + class Result{ + result:T; + error:E; + constructor(result: T , error: E) { + this.result = result; + this.error = error; + } + } + +export namespace abilityAccessCtrl { + + loadLibrary("aniabilityAccessCtrl.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, + } + + export native function createAtManager(): AtManager; + + interface AtManager { + checkAccessTokenANI(tokenID: int, permissionName: Permissions): int; + checkAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus; + checkAccessToken(tokenID: number, permissionName: Permissions): Promise + + requestPermissionsFromUserExecute(context: Context, permissionList: Array):PermissionRequestResult; + requestPermissionsFromUser( + context: Context, + permissionList: Array, + requestCallback: AsyncCallback + ): void; + + requestPermissionsFromUser( + context: Context, + permissionList: Array): Promise; + } + + class AtManagerInner implements AtManager { + native checkAccessTokenANI(tokenID: int, permissionName: Permissions): int; + checkAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus{ + let tmptokenID: int = tokenID as int; + let result = this.checkAccessTokenANI(tmptokenID, permissionName); + console.log("checkAccessTokenSync result = " + result + "."); + if (result == 0) { + return GrantStatus.PERMISSION_GRANTED + } + return GrantStatus.PERMISSION_DENIED + } + checkAccessToken(tokenID: number, permissionName: Permissions): Promise { + let tmptokenID: int = tokenID as int; + let p = new Promise((resolve: (v: GrantStatus) => void, reject: (error: Object) => void) => { + let p1 = taskpool.execute((): int => { return new AtManagerInner().checkAccessTokenANI(tmptokenID, permissionName)}); + p1.then((e: NullishType) => { + console.log("P1 then e = " + e + "."); + let r: GrantStatus = e as GrantStatus; + resolve(r); + }, (err: Object): void => { + console.log("Test Promise. The promise shouldn`t be rejected."); + }); + } + ); + return p; + } + + native requestPermissionsFromUserExecute(context: Context,permissionList: Array):PermissionRequestResult; + requestPermissionsFromUser( + context: Context, + permissionList: Array, + callback:AsyncCallback):void{ + let p2 = taskpool.execute((): PermissionRequestResult => { return new AtManagerInner().requestPermissionsFromUserExecute(context, permissionList) }); + p2.then((e: NullishType) => { + console.log("P2 then e = " + e + "."); + let err = new BusinessError() + err.code = 1//e as number + let r = new Result("code", err); + callback(r.error, e as PermissionRequestResult) + }, (err: Object): void => { + console.log("Test failed callback. The promise shouldn`t be rejected."); + }); + } + + requestPermissionsFromUser(context: Context, permissionList: Array): Promise{ + let p = new Promise((resolve: (v: PermissionRequestResult) => void, reject: (error: Object) => void) => { + let p1 = taskpool.execute((): PermissionRequestResult => { return new AtManagerInner().requestPermissionsFromUserExecute(context ,permissionList) }); + p1.then((e :NullishType)=>{ + console.log("P1 then e = " + e + "."); + let r : PermissionRequestResult = e as PermissionRequestResult; + resolve(r); + }, (err: Object): void => { + console.log("Test failed Promise. The promise shouldn`t be rejected."); + }); + + } + ); + return p; + } + } +} \ No newline at end of file diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/permissions.ets b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/permissions.ets new file mode 100644 index 000000000..c06103b96 --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/permissions.ets @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** + * @file Defines all permissions. + * @kit AbilityKit + */ + +/** + * Indicates permissions. + * + * @typedef { string } + * @syscap SystemCapability.Security.AccessToken + * @since 9 + */ + /** + * Indicates permissions. + * + * @typedef { string } + * @syscap SystemCapability.Security.AccessToken + * @atomicservice + * @since 11 + */ +export type Permissions = string; \ No newline at end of file diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/test/main.ets b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/test/main.ets new file mode 100644 index 000000000..7a9d8d933 --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arkts/privacy/test/main.ets @@ -0,0 +1,71 @@ +/* + * 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 { abilityAccessCtrl,BusinessError,Context,PermissionRequestResult,Permissions } from '@kit.abilityAccessCtrl_ani'; +// import { Permissions } from 'permissions'; +// import { PermissionRequestResult } from 'PermissionRequestResult'; +// import { Context } from 'ContextSts'; + +// import { common } from 'common'; + + +function main(){ + console.println("hello ani") + let atManager = abilityAccessCtrl.createAtManager() + + let permissionLists:Array = new Array("ohos.permission.APP_TRACKING_CONSENT") + + let permissionList: Array = permissionLists as Array + console.println("begin getContext") + // let context: Context = getContext(this) as common.UIAbilityContext; + let context: Context = {} + console.println("end getContext") + atManager.requestPermissionsFromUser(context, permissionList, (err: BusinessError, data: PermissionRequestResult) => { + if (err) { + console.error(`requestPermissionsFromUser fail, err->${JSON.stringify(err)}`); + } else { + console.info('data:' + JSON.stringify(data)); + console.info('data permissions:' + data.permissions); + console.info('data authResults:' + data.authResults); + console.info('data dialogShownResults:' + data.dialogShownResults); + } + }); + + atManager.requestPermissionsFromUser(context ,permissionList).then((result: PermissionRequestResult) => { + console.log(`get Permission success, result: ${JSON.stringify(result)}`); + }).catch((error: Object|null|undefined) => { + console.error(`get Permission error, error. Code: `); + }) + + let tokenID: number = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,三方应用可以通过bundleManager.getBundleInfoForSelf获取 + let permissionName: Permissions = 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS'; + let data: abilityAccessCtrl.GrantStatus = atManager.checkAccessTokenSync(tokenID, permissionName); + + // atManager.checkAccessToken(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS').then((data: abilityAccessCtrl.GrantStatus) => { + // console.log(`checkAccessToken success, data->${JSON.stringify(data)}`); + // }).catch((err: BusinessError) => { + // console.error(`checkAccessToken fail, err->${JSON.stringify(err)}`); + // }); + + let p = atManager.checkAccessToken(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS') + console.log("Start Invoked"); + p.then((value: abilityAccessCtrl.GrantStatus): void => { + console.log("Test passed."); + }, (err: Object): void => { + console.log("Test failed. The promise shouldn`t be rejected."); + }); + + console.println("hello ani end") +} \ No newline at end of file diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arktsconfig.json b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arktsconfig.json new file mode 100644 index 000000000..ffbe9f97c --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/arktsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "package": "", + "baseUrl": ".", + "outDir": "./out", + "paths": { + "std": [ + "../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/std" + ], + "escompat": [ + "../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/escompat" + ], + "@kit.abilityAccessCtrl_ani": [ + "./arkts/privacy/abilityAccessCtrl_ani.ets" + ], + "permissions": [ + "./arkts/privacy/permissions.ets" + ], + "PermissionRequestResult": [ + "./arkts/privacy/PermissionRequestResult.ets" + ], + "ContextSts": [ + "../../../../../../../../foundation/ability/ability_runtime/frameworks/ets/ani/app/application/Context.ets" + ], + "common": [ + "../../../../../../../../interface/sdk-js/api/@ohos.arkui.component.Common.d.ets" + ] + } + }, + "include": [ + "./arkts/privacy/*.ets","./arkts/privacy/test/*.ets" + ] +} \ No newline at end of file diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.cpp b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.cpp new file mode 100644 index 000000000..617433444 --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.cpp @@ -0,0 +1,1204 @@ +/* + * 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 "ani_abilityAccessCtrl.h" + +#include +#include + +#include "access_token.h" +#include "accesstoken_kit.h" +#include "ani_base_context.h" +#include "parameter.h" +#include "permission_list_state.h" +#include "privacy_kit.h" +#include "token_setproc.h" +#include "want.h" + +constexpr int64_t ERRCODE_2 = 2; +constexpr int64_t ERRCODE_3 = 3; +constexpr int64_t ERRCODE_9 = 9; + +const std::string PERMISSION_KEY = "ohos.user.grant.permission"; +const std::string STATE_KEY = "ohos.user.grant.permission.state"; +const std::string RESULT_KEY = "ohos.user.grant.permission.result"; +const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType"; +const std::string UI_EXTENSION_TYPE = "sys/commonUI"; +const std::string ORI_PERMISSION_MANAGER_BUNDLE_NAME = "com.ohos.permissionmanager"; +const std::string TOKEN_KEY = "ohos.ability.params.token"; +const std::string CALLBACK_KEY = "ohos.ability.params.callback"; + +const std::string WINDOW_RECTANGLE_LEFT_KEY = "ohos.ability.params.request.left"; +const std::string WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top"; +const std::string WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height"; +const std::string WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width"; +const std::string REQUEST_TOKEN_KEY = "ohos.ability.params.request.token"; + +#define SETTER_METHOD_NAME(property) "" #property + +static void UpdateGrantPermissionResultOnly(const std::vector &permissions, + const std::vector &grantResults, std::shared_ptr &data, + std::vector &newGrantResults) +{ + uint32_t size = permissions.size(); + + for (uint32_t i = 0; i < size; i++) { + int result = data->permissionsState[i]; + if (data->permissionsState[i] == OHOS::Security::AccessToken::DYNAMIC_OPER) { + result = data->result == OHOS::Security::AccessToken::RET_SUCCESS + ? grantResults[i] + : OHOS::Security::AccessToken::INVALID_OPER; + } + newGrantResults.emplace_back(result); + } +} +static bool IsDynamicRequest(std::shared_ptr &asyncContext) +{ + std::cout << "****************** lz 11" << std::endl; + std::vector permList; + if (asyncContext == nullptr) { + std::cout << "****************** lz asyncContext nullptr" << std::endl; + return false; + } + for (const auto &permission : asyncContext->permissionList) { + OHOS::Security::AccessToken::PermissionListState permState; + permState.permissionName = permission; + permState.state = OHOS::Security::AccessToken::INVALID_OPER; + permList.emplace_back(permState); + } + std::cout << "****************** lz 22" << std::endl; + auto ret = OHOS::Security::AccessToken::AccessTokenKit::GetSelfPermissionsState(permList, asyncContext->info); + if (ret == OHOS::Security::AccessToken::FORBIDDEN_OPER) { + for (auto &perm : permList) { + perm.state = OHOS::Security::AccessToken::INVALID_OPER; + } + } + std::cout << "****************** lz 33" << std::endl; + for (const auto &permState : permList) { + asyncContext->permissionsState.emplace_back(permState.state); + asyncContext->dialogShownResults.emplace_back( + permState.state == OHOS::Security::AccessToken::TypePermissionOper::DYNAMIC_OPER); + } + if (permList.size() != asyncContext->permissionList.size()) { + return false; + } + return ret == OHOS::Security::AccessToken::TypePermissionOper::DYNAMIC_OPER; +} + +static void RequestResultsHandler(const std::vector &permissionList, + const std::vector &permissionStates, + std::shared_ptr &data) +{ + auto *retCB = new (std::nothrow) OHOS::Security::AniSecurity::ResultCallback(); + if (retCB == nullptr) { + return; + } + + // only permissions which need to grant change the result, other keey as GetSelfPermissionsState result + std::vector newGrantResults; + UpdateGrantPermissionResultOnly(permissionList, permissionStates, data, newGrantResults); + + std::unique_ptr callbackPtr{ retCB }; + retCB->permissions = permissionList; + retCB->grantResults = newGrantResults; + retCB->dialogShownResults = data->dialogShownResults; + retCB->data = data; + + // uv_loop_s* loop = nullptr; + // NAPI_CALL_RETURN_VOID(data->env, napi_get_uv_event_loop(data->env, &loop)); + // if (loop == nullptr) { + // return; + // } + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + return; + } + std::unique_ptr uvWorkPtr{ work }; + // work->data = reinterpret_cast(retCB); + // NAPI_CALL_RETURN_VOID(data->env, uv_queue_work_with_qos( + // loop, work, [](uv_work_t* work) {}, ResultCallbackJSThreadWorker, uv_qos_user_initiated)); + + uvWorkPtr.release(); + callbackPtr.release(); +} + +static OHOS::Ace::UIContent *GetUIContent( + const std::shared_ptr &asyncContext) +{ + if (asyncContext == nullptr) { + return nullptr; + } + OHOS::Ace::UIContent *uiContent = nullptr; + if (asyncContext->uiAbilityFlag) { + uiContent = asyncContext->abilityContext->GetUIContent(); + } else { + uiContent = asyncContext->uiExtensionContext->GetUIContent(); + } + return uiContent; +} + +static void CreateUIExtensionMainThread(std::shared_ptr &asyncContext, + const OHOS::AAFwk::Want &want, const OHOS::Ace::ModalUIExtensionCallbacks &uiExtensionCallbacks, + const std::shared_ptr &uiExtCallback) +{ + auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() { + OHOS::Ace::UIContent *uiContent = GetUIContent(asyncContext); + if (uiContent == nullptr) { + std::cout << "Get ui content failed!" << std::endl; + asyncContext->result = OHOS::Security::AccessToken::RET_FAILED; + asyncContext->uiExtensionFlag = false; + return; + } + + OHOS::Ace::ModalUIExtensionConfig config; + config.isProhibitBack = true; + int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config); + if (sessionId == 0) { + std::cout << "Create component failed, sessionId is 0" << std::endl; + asyncContext->result = OHOS::Security::AccessToken::RET_FAILED; + asyncContext->uiExtensionFlag = false; + return; + } + uiExtCallback->SetSessionId(sessionId); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread"); + } else { + task(); + } +#else + task(); +#endif +} + +static void CreateServiceExtension(std::shared_ptr &asyncContext) +{ + if (!asyncContext->uiAbilityFlag) { + std::cout << "UIExtension ability can not pop service ablility window!" << std::endl; + asyncContext->needDynamicRequest = false; + asyncContext->result = OHOS::Security::AniSecurity::RET_FAILED; + return; + } + OHOS::sptr remoteObject = + new (std::nothrow) OHOS::Security::AniSecurity::AuthorizationResult(asyncContext); + if (remoteObject == nullptr) { + std::cout << "Create window failed!" << std::endl; + asyncContext->needDynamicRequest = false; + asyncContext->result = OHOS::Security::AniSecurity::RET_FAILED; + return; + } + OHOS::AAFwk::Want want; + want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantServiceAbilityName); + want.SetParam(PERMISSION_KEY, asyncContext->permissionList); + want.SetParam(STATE_KEY, asyncContext->permissionsState); + want.SetParam(TOKEN_KEY, asyncContext->abilityContext->GetToken()); + want.SetParam(CALLBACK_KEY, remoteObject); + + int32_t left; + int32_t top; + int32_t width; + int32_t height; + asyncContext->abilityContext->GetWindowRect(left, top, width, height); + want.SetParam(WINDOW_RECTANGLE_LEFT_KEY, left); + want.SetParam(WINDOW_RECTANGLE_TOP_KEY, top); + want.SetParam(WINDOW_RECTANGLE_WIDTH_KEY, width); + want.SetParam(WINDOW_RECTANGLE_HEIGHT_KEY, height); + want.SetParam(REQUEST_TOKEN_KEY, asyncContext->abilityContext->GetToken()); + int32_t ret = OHOS::AAFwk::AbilityManagerClient::GetInstance()->RequestDialogService( + want, asyncContext->abilityContext->GetToken()); + + std::cout << "ret " << ret << std::endl; +} + +static void CreateUIExtension(std::shared_ptr &asyncContext) +{ + OHOS::AAFwk::Want want; + want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantAbilityName); + want.SetParam(PERMISSION_KEY, asyncContext->permissionList); + want.SetParam(STATE_KEY, asyncContext->permissionsState); + want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE); + + auto uiExtCallback = std::make_shared(asyncContext); + OHOS::Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = { + [uiExtCallback](int32_t releaseCode) { uiExtCallback->OnRelease(releaseCode); }, + [uiExtCallback]( + int32_t resultCode, const OHOS::AAFwk::Want &result) { uiExtCallback->OnResult(resultCode, result); }, + [uiExtCallback](const OHOS::AAFwk::WantParams &receive) { uiExtCallback->OnReceive(receive); }, + [uiExtCallback](int32_t code, const std::string &name, [[maybe_unused]] const std::string &message) { + uiExtCallback->OnError(code, name, name); + }, + [uiExtCallback](const std::shared_ptr &uiProxy) { + uiExtCallback->OnRemoteReady(uiProxy); + }, + [uiExtCallback]() { uiExtCallback->OnDestroy(); }, + }; + CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback); +} + +// 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) +// { +// std::cout << "call addPermissionUsedRecord" <(FindParameter(OHOS::Security::AniSecurity::PERMISSION_STATUS_CHANGE_KEY)); if (handle == +// OHOS::Security::AniSecurity::PARAM_DEFAULT_VALUE) { +// std::cout << "FindParameter failed" <(GetParameterCommitId(OHOS::Security::AniSecurity::g_paramCache.handle)); if (currCommitId != +// OHOS::Security::AniSecurity::g_paramCache.commitIdCache) { +// char value[OHOS::Security::AniSecurity::AniContextCommon::VALUE_MAX_LEN] = {0}; +// auto ret = GetParameterValue(OHOS::Security::AniSecurity::g_paramCache.handle, value, +// OHOS::Security::AniSecurity::AniContextCommon::VALUE_MAX_LEN - 1); if (ret < 0) { +// std::cout << "call VerifyAccessTokenSync permissionName" << ret <empty()) || ((permissionName->length() > AniContextCommon::MAX_LENGTH))) { +// // std::cout << "call VerifyAccessTokenSync permissionName" <(tokenId) != selfTokenId) { +// int32_t cnt = OHOS::Security::AniSecurity::g_cnt.fetch_add(1); +// if (cnt % OHOS::Security::AniSecurity::REPORT_CNT == 0) { +// // TODO permissionName 类型ani_string转string +// result = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "permissionName"); +// return result; +// } +// } + +// std::lock_guard lock(g_lockCache); +// auto iter = OHOS::Security::AniSecurity::g_cache.find(permissionName); +// if (iter != OHOS::Security::AniSecurity::g_cache.end()) { +// std::string currPara = GetPermParamValue(); +// if (currPara != iter->second.paramValue) { +// result = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "permissionName"); +// iter->second.status = result; +// iter->second.paramValue = currPara; +// std::cout << "call VerifyAccessTokenSync permissionName" << currPara.c_str() <second.status; +// } +// } +// else +// { +// result = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "permissionName"); +// OHOS::Security::AniSecurity::g_cache[permissionName].status = result; +// OHOS::Security::AniSecurity::g_cache[permissionName].paramValue = GetPermParamValue(); +// std::cout << "call VerifyAccessTokenSync permissionName" << +// OHOS::Security::AniSecurity::g_cache[permissionName].paramValue.c_str() < &asyncContext) +{ + auto task = [asyncContext]() { + OHOS::Ace::UIContent *uiContent = GetUIContent(asyncContext); + if (uiContent == nullptr) { + std::cout << "Get ui content failed!" << std::endl; + return; + } + asyncContext->uiContentFlag = true; + asyncContext->instanceId = uiContent->GetInstanceId(); + }; +#ifdef EVENTHANDLER_ENABLE + if (asyncContext->handler_ != nullptr) { + asyncContext->handler_->PostSyncTask(task, "AT:GetInstanceId"); + } else { + task(); + } +#else + task(); +#endif +} + +static ani_ref ConvertAniArrayString(ani_env *env, const std::vector &cArray) +{ + ani_size length = cArray.size(); + ani_array_ref aArrayRef = nullptr; + ani_class aStringcls = nullptr; + if (env->FindClass("Lstd/core/String;", &aStringcls) != ANI_OK) { + std::cerr << "ConvertAniArrayString FindClass String failed " << std::endl; + return nullptr; + } + if (env->Array_New_Ref(aStringcls, length, nullptr, &aArrayRef) != ANI_OK) { + std::cerr << "ConvertAniArrayString Array_New_Ref failed " << std::endl; + return nullptr; + } + ani_string aString = nullptr; + for (ani_size i = 0; i < length; ++i) { + env->String_NewUTF8(cArray[i].c_str(), cArray[i].size(), &aString); + env->Array_Set_Ref(aArrayRef, i, aString); + } + ani_ref aRef = nullptr; + if (env->GlobalReference_Create(aArrayRef, &aRef) != ANI_OK) { + std::cerr << "ConvertAniArrayString GlobalReference_Create failed " << std::endl; + return nullptr; + } + return aRef; +} + +static ani_ref ConvertAniArrayInt(ani_env *env, const std::vector &cArray) +{ + ani_size length = cArray.size(); + ani_array_int aArrayInt = nullptr; + if (env->Array_New_Int(length, &aArrayInt) != ANI_OK) { + std::cerr << "ConvertAniArrayString Array_New_Ref failed " << std::endl; + return nullptr; + } + for (ani_size i = 0; i < length; ++i) { + env->Array_SetRegion_Int(aArrayInt, i, length, &cArray[i]); + } + ani_ref aRef = nullptr; + if (env->GlobalReference_Create(aArrayInt, &aRef) != ANI_OK) { + std::cerr << "ConvertAniArrayString GlobalReference_Create failed " << std::endl; + return nullptr; + } + return aRef; +} + +static ani_ref ConvertAniArrayBool(ani_env *env, const std::vector &cArray) +{ + ani_size length = cArray.size(); + ani_array_boolean aArrayBool = nullptr; + if (env->Array_New_Boolean(length, &aArrayBool) != ANI_OK) { + std::cerr << "ConvertAniArrayString Array_New_Boolean failed " << std::endl; + return nullptr; + } + std::vector boolArray(length); + for (ani_size i = 0; i < length; ++i) { + boolArray[i] = cArray[i]; + } + for (ani_size i = 0; i < length; ++i) { + env->Array_SetRegion_Boolean(aArrayBool, i, length, &boolArray[i]); + } + ani_ref aRef = nullptr; + if (env->GlobalReference_Create(aArrayBool, &aRef) != ANI_OK) { + std::cerr << "ConvertAniArrayString GlobalReference_Create failed " << std::endl; + return nullptr; + } + return aRef; +} + +template +static inline void CallSetter(ani_env *env, ani_class cls, ani_object object, const char *setterName, valueType value) +{ + ani_status status = ANI_ERROR; + ani_field fieldValue; + if (env->Class_FindField(cls, setterName, &fieldValue) != ANI_OK) { + std::cerr << setterName << " Class_FindField Fail " << status << std::endl; + } + + if ((status = env->Object_SetField_Ref(object, fieldValue, value)) != ANI_OK) { + std::cerr << setterName << " Class_FindMethod Fail " << status << std::endl; + } +} + +std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str) +{ + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector buffer(strSize + 1); + char *utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + +static void processArrayClass([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object arrayObj, + std::vector &permissionLists) +{ + ani_ref length; + if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "length", "I:Lstd/core/Object;", &length)) { + std::cerr << "Object_CallMethodByName_Ref length Failed" << std::endl; + return; + } + + for (int i = 0; i < int(length); i++) { + ani_ref stringEntryRef; + if (ANI_OK != + env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;", &stringEntryRef, (ani_int)i)) { + std::cerr << "Object_CallMethodByName_Ref _get Failed" << std::endl; + return; + } + permissionLists.emplace_back(ANIUtils_ANIStringToStdString(env, static_cast(stringEntryRef))); + } + for (const auto &s : permissionLists) { + std::cout << "Array String Content:" << s.c_str() << std::endl; + } +} + +static ani_object RequestPermissionsFromUserExecute( + [[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object permission) +{ + std::cout << "****************** lz start" << std::endl; + std::shared_ptr asyncContext = + std::make_shared(); + + ani_boolean stageMode = false; + ani_status status = IsStageContext(env, object, stageMode); + if (status != ANI_OK) { + std::cout << "call IsStageContext result stageMode :" << status << std::endl; + return nullptr; + } + if (stageMode) { + auto context = GetStageModeContext(env, object); + if (context == nullptr) { + std::cout << "Get context failed" << std::endl; + return nullptr; + } + asyncContext->abilityContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (asyncContext->abilityContext != nullptr) { + asyncContext->uiAbilityFlag = true; + asyncContext->tokenId = asyncContext->abilityContext->GetApplicationInfo()->accessTokenId; + asyncContext->bundleName = asyncContext->abilityContext->GetApplicationInfo()->bundleName; + } else { + std::cout << "Convert to ability context failed" << std::endl; + asyncContext->uiExtensionContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (asyncContext->uiExtensionContext == nullptr) { + std::cout << "Convert to ui extension context failed" << std::endl; + return nullptr; + } + asyncContext->tokenId = asyncContext->uiExtensionContext->GetApplicationInfo()->accessTokenId; + asyncContext->bundleName = asyncContext->uiExtensionContext->GetApplicationInfo()->bundleName; + } + } + + processArrayClass(env, object, permission, asyncContext->permissionList); + + asyncContext->tokenId = static_cast(GetSelfTokenID()); + + OHOS::Security::AniSecurity::AccessTokenID selfTokenID = + static_cast(GetSelfTokenID()); + if (asyncContext->tokenId != selfTokenID) { + std::cerr << "The context tokenID " << asyncContext->tokenId << " selfTokenID " << selfTokenID << std::endl; + asyncContext->result = OHOS::Security::AniSecurity::RET_FAILED; + return nullptr; + } + + std::cout << "****************** lz 1" << std::endl; + if (!IsDynamicRequest(asyncContext)) { + std::cout << "It does not need to request permission" << std::endl; + asyncContext->needDynamicRequest = false; + return nullptr; + } + std::cout << "****************** lz 2" << std::endl; + GetInstanceId(asyncContext); + std::cout << "****************** lz 3" << std::endl; + if (asyncContext->info.grantBundleName == ORI_PERMISSION_MANAGER_BUNDLE_NAME) { + std::cout << "Pop service extension dialog, uiContentFlag " << asyncContext->uiContentFlag << std::endl; + if (asyncContext->uiContentFlag) { + OHOS::Security::AniSecurity::RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + } else { + CreateServiceExtension(asyncContext); + } + } else if (asyncContext->instanceId == -1) { + std::cout << "Pop service extension dialog, instanceId is -1." << std::endl; + CreateServiceExtension(asyncContext); + // HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER", + // HiviewDFX::HiSysEvent::EventType::BEHAVIOR, + // "BUNDLENAME", asyncContext->bundleName, + // "UIEXTENSION_FLAG", false); + } else { + std::cout << "Pop ui extension dialog" << std::endl; + asyncContext->uiExtensionFlag = true; + OHOS::Security::AniSecurity::RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + // HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER", + // HiviewDFX::HiSysEvent::EventType::BEHAVIOR, + // "BUNDLENAME", asyncContext->bundleName, + // "UIEXTENSION_FLAG", asyncContext->uiExtensionFlag); + if (!asyncContext->uiExtensionFlag) { + std::cout << "Pop uiextension dialog fail, start to pop service extension dialog." << std::endl; + OHOS::Security::AniSecurity::RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext); + } + } + + status = ANI_ERROR; + ani_class cls = nullptr; + if ((status = env->FindClass("LPermissionRequestResult/PermissionRequestResult;", &cls)) != ANI_OK) { + std::cerr << "FindClass status: " << status << std::endl; + } + if (cls == nullptr) { + std::cerr << "null cls" << std::endl; + return nullptr; + } + + ani_method method = nullptr; + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + std::cerr << "Class_FindMethod status: " << status << std::endl; + } + + ani_object aObject = nullptr; + if ((status = env->Object_New(cls, method, &aObject)) != ANI_OK) { + std::cerr << "Object_New status: " << status << std::endl; + } + if (object == nullptr) { + std::cerr << "null object" << std::endl; + return nullptr; + } + + // asyncContext->permissionsState = {1, 2, 3}; + // asyncContext->dialogShownResults = {true, false, true}; + + std::cout << "****************** lz 3" << std::endl; + ani_ref a = ConvertAniArrayString(env, asyncContext->permissionList); + std::cout << "****************** lz 4" << std::endl; + ani_ref b = ConvertAniArrayInt(env, asyncContext->permissionsState); + std::cout << "****************** lz 5" << std::endl; + ani_ref c = ConvertAniArrayBool(env, asyncContext->dialogShownResults); + std::cout << "****************** lz 6" << std::endl; + CallSetter(env, cls, aObject, SETTER_METHOD_NAME(permissions), a); + CallSetter(env, cls, aObject, SETTER_METHOD_NAME(authResults), b); + CallSetter(env, cls, aObject, SETTER_METHOD_NAME(dialogShownResults), c); + + std::cout << "****************** lz end" << std::endl; + + return aObject; +} + +// ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +// { +// std::cout << "ANI_Constructor called" << std::endl; +// ani_env *env; +// if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { +// std::cerr << "Unsupported ANI_VERSION_1" << std::endl; +// return (ani_status)9; +// } + +// static const char *className = "Lhello_ani/Calc;"; +// ani_class cls; +// if (ANI_OK != env->FindClass(className, &cls)) { +// std::cerr << "Not found '" << className << "'" << std::endl; +// return (ani_status)2; +// } + +// std::cout << "array methods called" << std::endl; +// std::array methods = { +// // ani_native_function{"addPermissionUsedRecord", "ILstd/core/String;II:I", reinterpret_cast(AddPermissionUsedRecord)}, +// // ani_native_function{"verifyAccessTokenSync", "Lstd/core/String;II:I", reinterpret_cast(VerifyAccessTokenSync)}, ani_native_function{"requestPermissionsFromUserExecute", +// "nullptr:Lhello_ani/PermissionRequestResult;", reinterpret_cast(RequestPermissionsFromUserExecute)}, +// }; + +// if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { +// std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl; +// return (ani_status)3; +// }; + +// *result = ANI_VERSION_1; +// return ANI_OK; +// } + +void OHOS::Security::AniSecurity::RequestAsyncInstanceControl::ExecCallback(int32_t id) +{ + std::shared_ptr asyncContext = nullptr; + bool isDynamic = false; + { + std::lock_guard lock(instanceIdMutex_); + auto iter = OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_.find(id); + if (iter == OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_.end()) { + return; + } + while (!iter->second.empty()) { + asyncContext = iter->second[0]; + iter->second.erase(iter->second.begin()); + CheckDynamicRequest(asyncContext, isDynamic); + if (isDynamic) { + break; + } + } + if (iter->second.empty()) { + OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_.erase(id); + } + } + if (isDynamic) { + if (asyncContext->uiExtensionFlag) { + CreateUIExtension(asyncContext); + } else { + CreateServiceExtension(asyncContext); + } + } +} + +void OHOS::Security::AniSecurity::RequestAsyncInstanceControl::CheckDynamicRequest( + std::shared_ptr &asyncContext, bool &isDynamic) +{ + asyncContext->permissionsState.clear(); + asyncContext->dialogShownResults.clear(); + if (!IsDynamicRequest(asyncContext)) { + RequestResultsHandler(asyncContext->permissionList, asyncContext->permissionsState, asyncContext); + return; + } + isDynamic = true; +} + +void OHOS::Security::AniSecurity::RequestAsyncInstanceControl::AddCallbackByInstanceId( + std::shared_ptr &asyncContext) +{ + std::lock_guard lock(instanceIdMutex_); + auto iter = OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_.find(asyncContext->instanceId); + if (iter != OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_.end()) { + OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId].emplace_back( + asyncContext); + return; + } + OHOS::Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_[asyncContext->instanceId] = {}; + if (asyncContext->uiExtensionFlag) { + CreateUIExtension(asyncContext); + } else { + CreateServiceExtension(asyncContext); + } +} + +OHOS::Security::AniSecurity::UIExtensionCallback::UIExtensionCallback( + const std::shared_ptr &reqContext) +{ + this->reqContext_ = reqContext; +} + +OHOS::Security::AniSecurity::UIExtensionCallback::~UIExtensionCallback() {} + +void OHOS::Security::AniSecurity::UIExtensionCallback::SetSessionId(int32_t sessionId) +{ + this->sessionId_ = sessionId; +} + +void OHOS::Security::AniSecurity::UIExtensionCallback::OnResult(int32_t resultCode, const OHOS::AAFwk::Want &result) +{ + this->reqContext_->permissionList = result.GetStringArrayParam(PERMISSION_KEY); + this->reqContext_->permissionsState = result.GetIntArrayParam(RESULT_KEY); + // ReleaseHandler(0); +} + +void OHOS::Security::AniSecurity::UIExtensionCallback::OnReceive(const OHOS::AAFwk::WantParams &receive) {} + +void OHOS::Security::AniSecurity::UIExtensionCallback::OnRelease(int32_t releaseCode) +{ + // ReleaseHandler(-1); +} + +void OHOS::Security::AniSecurity::UIExtensionCallback::OnError( + int32_t code, const std::string &name, const std::string &message) +{ + // ReleaseHandler(-1); +} + +void OHOS::Security::AniSecurity::UIExtensionCallback::OnRemoteReady( + const std::shared_ptr &uiProxy) +{} + +void OHOS::Security::AniSecurity::UIExtensionCallback::OnDestroy() +{ + // ReleaseHandler(-1); +} + +void OHOS::Security::AniSecurity::AuthorizationResult::GrantResultsCallback( + const std::vector &permissionList, const std::vector &grantResults) +{ + std::shared_ptr asyncContext = data_; + if (asyncContext == nullptr) { + return; + } + RequestResultsHandler(permissionList, grantResults, asyncContext); +} + +void OHOS::Security::AniSecurity::AuthorizationResult::WindowShownCallback() +{ + std::shared_ptr asyncContext = data_; + if (asyncContext == nullptr) { + return; + } + OHOS::Ace::UIContent *uiContent = GetUIContent(asyncContext); + if ((uiContent == nullptr) || !(asyncContext->uiContentFlag)) { + return; + } + RequestAsyncInstanceControl::ExecCallback(asyncContext->instanceId); +} + +// static bool ParseAniRequestAsyncContext([[maybe_unused]] ani_env *env, ani_object aniContext, +// std::shared_ptr& asyncContext) +// { + +// } + +/* + // static bool ParseAniRequestAsyncContext([[maybe_unused]] ani_env *env, ani_object aniContext, + std::shared_ptr& asyncContext) + // { + // ani_class cls; + + // const char *className = "Lani_security/AniRequestAsyncContext;"; + // if (ANI_OK != env->FindClass(className, &cls)) { + // std::cerr << "Not found '" << className << "'" << std::endl; + // return false; + // } + + // ani_field valueField; + + // // 解析 tokenId + // if (ANI_OK != env->Class_GetField(cls, "tokenId", &valueField)) { + // std::cerr << "Get Field 'tokenId' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Int(aniContext, valueField, &asyncContext->tokenId)) { + // std::cerr << "Object_GetField_Int 'tokenId' Fail" << std::endl; + // return false; + // } + + // // 解析 bundleName + // if (ANI_OK != env->Class_GetField(cls, "bundleName", &valueField)) { + // std::cerr << "Get Field 'bundleName' Fail" << std::endl; + // return false; + // } + // ani_string aniBundleName; + // if (ANI_OK != env->Object_GetField_Char(aniContext, valueField, &aniBundleName)) { + // std::cerr << "Object_GetField_String 'bundleName' Fail" << std::endl; + // return false; + // } + // asyncContext->bundleName = aniBundleName; + + // // 解析 needDynamicRequest + // if (ANI_OK != env->Class_GetField(cls, "needDynamicRequest", &valueField)) { + // std::cerr << "Get Field 'needDynamicRequest' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Boolean(aniContext, valueField, &asyncContext->needDynamicRequest)) { + // std::cerr << "Object_GetField_Boolean 'needDynamicRequest' Fail" << std::endl; + // return false; + // } + + // // 解析 result + // if (ANI_OK != env->Class_GetField(cls, "result", &valueField)) { + // std::cerr << "Get Field 'result' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Int(aniContext, valueField, &asyncContext->result)) { + // std::cerr << "Object_GetField_Int 'result' Fail" << std::endl; + // return false; + // } + + // // 解析 instanceId + // if (ANI_OK != env->Class_GetField(cls, "instanceId", &valueField)) { + // std::cerr << "Get Field 'instanceId' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Int(aniContext, valueField, &asyncContext->instanceId)) { + // std::cerr << "Object_GetField_Int 'instanceId' Fail" << std::endl; + // return false; + // } + + // // 解析 permissionList + // + // if (ANI_OK != env->Class_GetField(cls, "permissionList", &valueField)) { + // std::cerr << "Get Field 'permissionList' Fail" << std::endl; + // return false; + // } + // ani_array aniPermissionList; + // if (ANI_OK != env->Object_GetField_Array(aniContext, valueField, &aniPermissionList)) { + // std::cerr << "Object_GetField_Array 'permissionList' Fail" << std::endl; + // return false; + // } + // for (size_t i = 0; i < aniPermissionList.size(); ++i) { + // ani_string aniPermission; + // if (ANI_OK != env->Array_Get_String(aniPermissionList, i, &aniPermission)) { + // std::cerr << "Array_Get_String 'permissionList' Fail" << std::endl; + // return false; + // } + // asyncContext->permissionList.push_back(aniPermission); + // } + // + + // // 解析 permissionsState + // + // if (ANI_OK != env->Class_GetField(cls, "permissionsState", &valueField)) { + // std::cerr << "Get Field 'permissionsState' Fail" << std::endl; + // return false; + // } + // ani_array aniPermissionsState; + // if (ANI_OK != env->Object_GetField_Array(aniContext, valueField, &aniPermissionsState)) { + // std::cerr << "Object_GetField_Array 'permissionsState' Fail" << std::endl; + // return false; + // } + // for (size_t i = 0; i < aniPermissionsState.size(); ++i) { + // ani_int aniPermissionState; + // if (ANI_OK != env->Array_Get_Int(aniPermissionsState, i, &aniPermissionState)) { + // std::cerr << "Array_Get_Int 'permissionsState' Fail" << std::endl; + // return false; + // } + // asyncContext->permissionsState.push_back(aniPermissionState); + // } + // + + // // 解析 requestResult + // if (ANI_OK != env->Class_GetField(cls, "uiAbilityFlag", &valueField)) { + // std::cerr << "Get Field 'uiAbilityFlag' Fail" << std::endl; + // return false; + // } + // ani_ref aniRequestResult; + // if (ANI_OK != env->Object_GetField_Ref(aniContext, valueField, &asyncContext->requestResult)) { + // std::cerr << "Object_GetField_Ref 'uiAbilityFlag' Fail" << std::endl; + // return false; + // } + + // // 解析 dialogShownResults + // + // if (ANI_OK != env->Class_GetField(cls, "dialogShownResults", &valueField)) { + // std::cerr << "Get Field 'dialogShownResults' Fail" << std::endl; + // return false; + // } + // ani_array aniDialogShownResults; + // if (ANI_OK != env->Object_GetField_Array(aniContext, valueField, &aniDialogShownResults)) { + // std::cerr << "Object_GetField_Array 'dialogShownResults' Fail" << std::endl; + // return false; + // } + // for (size_t i = 0; i < aniDialogShownResults.size(); ++i) { + // ani_bool aniDialogShownResult; + // if (ANI_OK != env->Array_Get_Bool(aniDialogShownResults, i, &aniDialogShownResult)) { + // std::cerr << "Array_Get_Bool 'dialogShownResults' Fail" << std::endl; + // return false; + // } + // asyncContext->dialogShownResults.push_back(aniDialogShownResult); + // } + // + + // // 解析 permissionQueryResults + // + // if (ANI_OK != env->Class_GetField(cls, "permissionQueryResults", &valueField)) { + // std::cerr << "Get Field 'permissionQueryResults' Fail" << std::endl; + // return false; + // } + // ani_array aniPermissionQueryResults; + // if (ANI_OK != env->Object_GetField_Array(aniContext, valueField, &aniPermissionQueryResults)) { + // std::cerr << "Object_GetField_Array 'permissionQueryResults' Fail" << std::endl; + // return false; + // } + // for (size_t i = 0; i < aniPermissionQueryResults.size(); ++i) { + // ani_int aniPermissionQueryResult; + // if (ANI_OK != env->Array_Get_Int(aniPermissionQueryResults, i, &aniPermissionQueryResult)) { + // std::cerr << "Array_Get_Int 'permissionQueryResults' Fail" << std::endl; + // return false; + // } + // asyncContext->permissionQueryResults.push_back(aniPermissionQueryResult); + // } + // + + // // 解析 info + // + // if (ANI_OK != env->Class_GetField(cls, "info", &valueField)) { + // std::cerr << "Get Field 'info' Fail" << std::endl; + // return false; + // } + // ani_object aniInfo; + // if (ANI_OK != env->Object_GetField_Object(aniContext, valueField, &aniInfo)) { + // std::cerr << "Object_GetField_Object 'info' Fail" << std::endl; + // return false; + // } + // // 假设 PermissionGrantInfo 有一个从 ani_object 解析的构造函数 + // asyncContext->info = PermissionGrantInfo(aniInfo); + // + + // // 解析 abilityContext + // + // if (ANI_OK != env->Class_GetField(cls, "abilityContext", &valueField)) { + // std::cerr << "Get Field 'abilityContext' Fail" << std::endl; + // return false; + // } + // ani_ref aniAbilityContext; + // if (ANI_OK != env->Object_GetField_Ref(aniContext, valueField, &aniAbilityContext)) { + // std::cerr << "Object_GetField_Ref 'abilityContext' Fail" << std::endl; + // return false; + // } + // asyncContext->abilityContext = std::make_shared(aniAbilityContext); + // + + // // 解析 uiExtensionContext + // + // if (ANI_OK != env->Class_GetField(cls, "uiExtensionContext", &valueField)) { + // std::cerr << "Get Field 'uiExtensionContext' Fail" << std::endl; + // return false; + // } + // ani_ref aniUIExtensionContext; + // if (ANI_OK != env->Object_GetField_Ref(aniContext, valueField, &aniUIExtensionContext)) { + // std::cerr << "Object_GetField_Ref 'uiExtensionContext' Fail" << std::endl; + // return false; + // } + // asyncContext->uiExtensionContext = + std::make_shared(aniUIExtensionContext); + // + + // // 解析 uiAbilityFlag + // if (ANI_OK != env->Class_GetField(cls, "uiAbilityFlag", &valueField)) { + // std::cerr << "Get Field 'uiAbilityFlag' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Boolean(aniContext, valueField, &asyncContext->uiAbilityFlag)) { + // std::cerr << "Object_GetField_Boolean 'uiAbilityFlag' Fail" << std::endl; + // return false; + // } + + // // 解析 uiExtensionFlag + // if (ANI_OK != env->Class_GetField(cls, "uiExtensionFlag", &valueField)) { + // std::cerr << "Get Field 'uiExtensionFlag' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Boolean(aniContext, valueField, &asyncContext->uiExtensionFlag)) { + // std::cerr << "Object_GetField_Boolean 'uiExtensionFlag' Fail" << std::endl; + // return false; + // } + + // // 解析 uiContentFlag + // if (ANI_OK != env->Class_GetField(cls, "uiContentFlag", &valueField)) { + // std::cerr << "Get Field 'uiContentFlag' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Boolean(aniContext, valueField, &asyncContext->uiContentFlag)) { + // std::cerr << "Object_GetField_Boolean 'uiContentFlag' Fail" << std::endl; + // return false; + // } + + // // 解析 releaseFlag + // if (ANI_OK != env->Class_GetField(cls, "releaseFlag", &valueField)) { + // std::cerr << "Get Field 'releaseFlag' Fail" << std::endl; + // return false; + // } + // if (ANI_OK != env->Object_GetField_Boolean(aniContext, valueField, &asyncContext->releaseFlag)) { + // std::cerr << "Object_GetField_Boolean 'releaseFlag' Fail" << std::endl; + // return false; + // } + + // return true; + // } +*/ + +static ani_object createAtManager([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + ani_object AtManager_obj = {}; + + // 这里只能创建一个 Class 的实例,可以尝试改为 ani_interface/Person 会无法创建Object + static const char *className = "LabilityAccessCtrl_ani/abilityAccessCtrl/AtManagerInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + std::cerr << "Not found '" << className << "'" << std::endl; + return AtManager_obj; + } + + // static const char *spaceName = "LabilityAccessCtrl_ani/abilityAccessCtrl;"; + // ani_namespace spc; + // if (ANI_OK != env->FindNamespace(spaceName, &spc)) { + // std::cerr << "Not found '" << spaceName << "'" << std::endl; + // return AtManager_obj; + // } + + // static const char *className = "LabilityAccessCtrl_ani/abilityAccessCtrl/AtManagerInner;"; + // ani_class cls; + // if (ANI_OK != env->Namespace_FindClass(spc, className, &cls)) { + // std::cerr << "Not found '" << className << "'" << std::endl; + // return AtManager_obj; + // } + + // 查找构造函数,如果没有重载,可以直接传递 nullptr + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + std::cerr << "get ctor Failed'" << className << "'" << std::endl; + return AtManager_obj; + } + + // 创建一个 PersonInner 的实例 + if (ANI_OK != env->Object_New(cls, ctor, &AtManager_obj)) { + std::cerr << "Create Object Failed'" << className << "'" << std::endl; + return AtManager_obj; + } + + // //Interface 及实现 Interface 中的成员都是 Property而不是 Field (参考spec, Interface Properties) + // //查找setter函数,当前FindSetter没实现,使用Class_FindMethod实现 + // ani_method ageSetter; + // if(ANI_OK != env->Class_FindMethod(cls, "age", nullptr, &ageSetter)){ + // std::cerr << "Class_FindMethod Fail'" << className << "'" << std::endl; + // } + + // if(ANI_OK != env->Object_CallMethod_Void(person_obj, ageSetter, ani_int(42))) + // { + // std::cerr << "Object_CallMethod_Void Fail'" << className << "'" << std::endl; + // return person_obj; + // } + + // ani_method nameSetter; + // if(ANI_OK != env->Class_FindMethod(cls, "name", nullptr, &nameSetter)){ + // std::cerr << "Class_FindMethod Fail'" << "name" << "'" << std::endl; + // } + + // //从C++的string (大多数情况是UTF8) 构造一个 ani_string + // std::string name = "Goose"; + // ani_string name_string{}; + + // env->String_NewUTF8(name.c_str(), name.size(), &name_string); + + // //调用 set name(n:string) + // if(ANI_OK != env->Object_CallMethod_Void(person_obj, nameSetter, name_string)) + // { + // std::cerr << "Object_CallMethod_Void Fail'" << className << "'" << std::endl; + // return person_obj; + // } + + return AtManager_obj; +} + +static ani_int CheckAccessTokenSync( + [[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_int tokenID, ani_string permissionName) +{ + ani_size strSize; + env->String_GetUTF8Size(permissionName, &strSize); + + std::vector buffer(strSize + 1); + char *utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env->String_GetUTF8(permissionName, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + std::cout << "CallMeWithOptionalString Get " << content << std::endl; + + int result = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, content); + std::cout << "call CheckAccessTokenSync result : " << result << std::endl; + return static_cast(result); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + std::cout << "ANI_Constructor called" << std::endl; + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + std::cerr << "Unsupported ANI_VERSION_1" << std::endl; + return (ani_status)ERRCODE_9; + } + + static const char *spaceName = "LabilityAccessCtrl_ani/abilityAccessCtrl;"; + ani_namespace spc; + if (ANI_OK != env->FindNamespace(spaceName, &spc)) { + std::cerr << "Not found '" << spaceName << "'" << std::endl; + return (ani_status)ERRCODE_2; + } + + // static const char *className = "LabilityAccessCtrl_ani/abilityAccessCtrl/AtManagerInner;"; + // ani_class cls; + // if (ANI_OK != env->Namespace_FindClass(spc, className, &cls)) { + // std::cerr << "Not found '" << className << "'" << std::endl; + // return (ani_status)2; + // } + + // 当前文件全局的 Function 实际时 ani_interface.ETSGLOBAL 这个class下的一个方法 + // static const char *className = "LabilityAccessCtrl_ani/ETSGLOBAL;"; + + // ani_class cls; + // if (ANI_OK != env->FindClass(className, &cls)) { + // std::cerr << "Not found '" << className << "'" << std::endl; + // return ANI_ERROR; + // } + + std::cout << "array methods called" << std::endl; + std::array methods = { + ani_native_function{ "createAtManager", nullptr, reinterpret_cast(createAtManager) }, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(spc, methods.data(), methods.size())) { + std::cerr << "Cannot bind native methods to '" << spaceName << "'" << std::endl; + return (ani_status)ERRCODE_3; + }; + + // if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + // std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl; + // return (ani_status)3; + // }; + + // 当前文件全局的 Function 实际时 ani_interface.ETSGLOBAL 这个class下的一个方法 + static const char *className1 = "LabilityAccessCtrl_ani/abilityAccessCtrl/AtManagerInner;"; + + ani_class cls1; + if (ANI_OK != env->FindClass(className1, &cls1)) { + std::cerr << "Not found '" << className1 << "'" << std::endl; + return ANI_ERROR; + } + + std::cout << "array methods called" << std::endl; + std::array methods1 = { + ani_native_function{ + "checkAccessTokenANI", "ILstd/core/String;:I", reinterpret_cast(CheckAccessTokenSync) }, + ani_native_function{ "requestPermissionsFromUserExecute", + "LContext/Context;Lescompat/Array;:LPermissionRequestResult/PermissionRequestResult;", + reinterpret_cast(RequestPermissionsFromUserExecute) }, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls1, methods1.data(), methods1.size())) { + std::cerr << "Cannot bind native methods to '" << className1 << "'" << std::endl; + return (ani_status)ERRCODE_3; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.h b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.h new file mode 100644 index 000000000..2d8abb70b --- /dev/null +++ b/frameworks/js/arkts/accesstoken/aniabilityAccessCtrl/native/ani_abilityAccessCtrl.h @@ -0,0 +1,147 @@ +/* + * 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 +#include + +#include "ability.h" +#include "ability_manager_client.h" +#include "access_token.h" +#include "ani.h" +#include "permission_grant_info.h" +#include "token_callback_stub.h" +#include "ui_content.h" +#include "ui_extension_context.h" + +std::mutex g_lockCache; + +namespace OHOS { +namespace Security { +namespace AniSecurity { +typedef unsigned int AccessTokenID; +static std::atomic g_cnt = 0; +constexpr uint32_t REPORT_CNT = 10; +constexpr uint32_t VERIFY_TOKENID_INCONSISTENCY = 0; +const int32_t PARAM_DEFAULT_VALUE = -1; +const int32_t RET_FAILED = -1; +const int32_t RET_SUCCESS = 0; + +static const char *PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change"; + +class AniContextCommon { +public: + static constexpr int32_t MAX_PARAMS_ONE = 1; + static constexpr int32_t MAX_PARAMS_TWO = 2; + static constexpr int32_t MAX_PARAMS_THREE = 3; + static constexpr int32_t MAX_PARAMS_FOUR = 4; + static constexpr int32_t MAX_LENGTH = 256; + static constexpr int32_t MAX_WAIT_TIME = 1000; + static constexpr int32_t VALUE_MAX_LEN = 32; +}; + +struct PermissionParamCache { + long long sysCommitIdCache = PARAM_DEFAULT_VALUE; + int32_t commitIdCache = PARAM_DEFAULT_VALUE; + int32_t handle = PARAM_DEFAULT_VALUE; + std::string sysParamCache; +}; + +struct PermissionStatusCache { + int32_t status; + std::string paramValue; +}; + +static PermissionParamCache g_paramCache; +std::map g_cache; + +struct RequestAsyncContext { + AccessTokenID tokenId = 0; + std::string bundleName; + bool needDynamicRequest = true; + int32_t result = RET_SUCCESS; + int32_t instanceId = -1; + std::vector permissionList; + std::vector permissionsState; + ani_object requestResult = nullptr; + std::vector dialogShownResults; + std::vector permissionQueryResults; + Security::AccessToken::PermissionGrantInfo info; + std::shared_ptr abilityContext; + std::shared_ptr uiExtensionContext; + bool uiAbilityFlag = false; + bool uiExtensionFlag = false; + bool uiContentFlag = false; + bool releaseFlag = false; +#ifdef EVENTHANDLER_ENABLE + std::shared_ptr handler_ = nullptr; +#endif +}; + +class UIExtensionCallback { +public: + explicit UIExtensionCallback(const std::shared_ptr &reqContext); + ~UIExtensionCallback(); + void SetSessionId(int32_t sessionId); + void OnRelease(int32_t releaseCode); + void OnResult(int32_t resultCode, const OHOS::AAFwk::Want &result); + void OnReceive(const OHOS::AAFwk::WantParams &request); + void OnError(int32_t code, const std::string &name, const std::string &message); + void OnRemoteReady(const std::shared_ptr &uiProxy); + void OnDestroy(); + void ReleaseHandler(int32_t code); + +private: + int32_t sessionId_ = 0; + std::shared_ptr reqContext_ = nullptr; +}; + +class AuthorizationResult : public Security::AccessToken::TokenCallbackStub { +public: + AuthorizationResult(std::shared_ptr &data) : data_(data) {} + virtual ~AuthorizationResult() override = default; + + virtual void GrantResultsCallback( + const std::vector &permissionList, const std::vector &grantResults) override; + virtual void WindowShownCallback() override; + +private: + std::shared_ptr data_ = nullptr; +}; + +class RequestAsyncInstanceControl { +public: + static void AddCallbackByInstanceId(std::shared_ptr &asyncContext); + static void ExecCallback(int32_t id); + static void CheckDynamicRequest(std::shared_ptr &asyncContext, bool &isDynamic); + +private: + static std::map>> instanceIdMap_; + static std::mutex instanceIdMutex_; +}; + +struct ResultCallback { + std::vector permissions; + std::vector grantResults; + std::vector dialogShownResults; + std::shared_ptr data = nullptr; +}; + +std::map>> + Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMap_; +std::mutex Security::AniSecurity::RequestAsyncInstanceControl::instanceIdMutex_; +} // namespace AniSecurity +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/arkts/privacy/aniprivacyManager/BUILD.gn b/frameworks/js/arkts/privacy/aniprivacyManager/BUILD.gn new file mode 100644 index 000000000..d2b3c5f40 --- /dev/null +++ b/frameworks/js/arkts/privacy/aniprivacyManager/BUILD.gn @@ -0,0 +1,52 @@ +# 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("aniprivacyManager") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "${access_token_path}/interfaces/innerkits/accesstoken/include", + "${access_token_path}/interfaces/innerkits/privacy/include", + "${access_token_path}/ani/include", + ] + sources = [ "native/ani_privacyManager.cpp" ] + + deps = [ "${access_token_path}/interfaces/innerkits/privacy:libprivacy_sdk" ] + + external_deps = [ "runtime_core:ani" ] + + part_name = "access_token" + subsystem_name = "security" +} + +generate_static_abc("privacyManager_abc") { + arktsconfig = "arktsconfig.json" + dst_file = "$target_out_dir/privacyManager_ani.abc" + out_puts = [ "$target_out_dir/privacyManager_ani.abc" ] +} + +group("ani_privacyManager") { + deps = [ + ":aniprivacyManager", + ":privacyManager_abc", + ] +} diff --git a/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/permissions.ets b/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/permissions.ets new file mode 100644 index 000000000..c06103b96 --- /dev/null +++ b/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/permissions.ets @@ -0,0 +1,36 @@ +/* + * 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. + */ + +/** + * @file Defines all permissions. + * @kit AbilityKit + */ + +/** + * Indicates permissions. + * + * @typedef { string } + * @syscap SystemCapability.Security.AccessToken + * @since 9 + */ + /** + * Indicates permissions. + * + * @typedef { string } + * @syscap SystemCapability.Security.AccessToken + * @atomicservice + * @since 11 + */ +export type Permissions = string; \ No newline at end of file diff --git a/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/privacyManager_ani.ets b/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/privacyManager_ani.ets new file mode 100644 index 000000000..4acb60d30 --- /dev/null +++ b/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/privacyManager_ani.ets @@ -0,0 +1,97 @@ +/* + * 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 { Permissions } from './permissions'; + +loadLibrary("aniprivacyManager.z"); + +export class BusinessError { + code: number; + data: T; + } + + export { Permissions } + + type AsyncCallback = (err: BusinessError, data: T) => void; + + class Result{ + result:T; + error:E; + constructor(result: T , error: E) { + this.result = result; + this.error = error; + } + } + export namespace privacyManager { + export enum PermissionUsedType { + + NORMAL_TYPE = 0, + + PICKER_TYPE = 1, + + SECURITY_COMPONENT_TYPE = 2 + } + + export class AddPermissionUsedRecordOptions { + usedType?: PermissionUsedType; + } + + export class PrivacyManagerInner { + + native addPermissionUsedRecordSync(tokenID: int, permissionName: Permissions, successCount: int, failCount: int, options: AddPermissionUsedRecordOptions): int; + + } + + interface UsedRecordDetail { + + status: number; + + lockScreenStatus?: number; + + timestamp: number; + + count?: number; + + accessDuration: number; + + usedType?: PermissionUsedType; + } + + interface PermissionUsedTypeInfo { + + tokenId: number; + + permissionName: Permissions; + + usedType: PermissionUsedType; + } + + + export function addPermissionUsedRecord(tokenID: int, permissionName: string, successCount: int, failCount: int, options: AddPermissionUsedRecordOptions): Promise { + 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, options) }); + p1.then((e: NullishType) => { + console.log("P1 then e = " + e + "."); + let r: Int = e as Int; + resolve(r.intValue()); + }, (err: Object): void => { + console.log("Test Promise. The promise shouldn`t be rejected."); + }); + } + ); + return p; + } +} + diff --git a/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/test/main.ets b/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/test/main.ets new file mode 100644 index 000000000..30b261d01 --- /dev/null +++ b/frameworks/js/arkts/privacy/aniprivacyManager/arkts/privacy/test/main.ets @@ -0,0 +1,32 @@ +/* + * 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 { privacyManager } from '../privacyManager_ani'; + +function main(){ + console.println("hello ani") + + let options: privacyManager.AddPermissionUsedRecordOptions = { + usedType: privacyManager.PermissionUsedType.PICKER_TYPE + }; + + let p = privacyManager.addPermissionUsedRecord(0, 'ohos.permission.READ_AUDIO', 1, 0,options) + console.log("Start Invoked"); + p.then((value: int): void => { + console.log("Test passed. value : " + value); + }, (err: Object): void => { + console.log("Test failed. The promise shouldn`t be rejected."); + }); +} \ No newline at end of file diff --git a/frameworks/js/arkts/privacy/aniprivacyManager/arktsconfig.json b/frameworks/js/arkts/privacy/aniprivacyManager/arktsconfig.json new file mode 100644 index 000000000..281a523d3 --- /dev/null +++ b/frameworks/js/arkts/privacy/aniprivacyManager/arktsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "package": "", + "baseUrl": ".", + "outDir": "./out", + "paths": { + "std": [ + "../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/std" + ], + "escompat": [ + "../../../../../../../../arkcompiler/runtime_core/static_core/plugins/ets/stdlib/escompat" + ], + "@kit.privacyManager_ani": [ + "./arkts/privacy/privacyManager_ani.ets" + ] + } + }, + "include": [ + "./arkts/privacy/*.ets","./arkts/privacy/test/*.ets" + ] +} \ No newline at end of file diff --git a/frameworks/js/arkts/privacy/aniprivacyManager/native/ani_privacyManager.cpp b/frameworks/js/arkts/privacy/aniprivacyManager/native/ani_privacyManager.cpp new file mode 100644 index 000000000..5da128c18 --- /dev/null +++ b/frameworks/js/arkts/privacy/aniprivacyManager/native/ani_privacyManager.cpp @@ -0,0 +1,103 @@ +/* + * 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 "ani.h" +#include "privacy_kit.h" + +constexpr int64_t ERRCODE_2 = 2; +constexpr int64_t ERRCODE_3 = 3; +constexpr int64_t ERRCODE_9 = 9; + +static int AddPermissionUsedRecordSync( + ani_int tokenID, 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 = (OHOS::Security::AccessToken::PermissionUsedType)ntype; + std::cout << "call addPermissionUsedRecord:" << info.type << std::endl; + auto retCode = OHOS::Security::AccessToken::PrivacyKit::AddPermissionUsedRecord(info); + std::cout << "call addPermissionUsedRecord " << retCode << std::endl; + 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) +{ + ani_size strSize; + env->String_GetUTF8Size(permissionName, &strSize); + + std::vector buffer(strSize + 1); + char *utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env->String_GetUTF8(permissionName, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + std::cout << "CallMeWithOptionalString Get " << content << std::endl; + + ani_boolean isUndefined; + env->Reference_IsUndefined(options, &isUndefined); + ani_int type = 0; + + ani_int usedTypeRef; + if (ANI_OK != env->Object_GetFieldByName_Int(options, "usedType", &usedTypeRef)) { + std::cerr << "Object_GetFieldByName_Ref Faild" << std::endl; + } + + std::cerr << "Object_GetFieldByName_Ref usedTypeRef:" << usedTypeRef << std::endl; + type = usedTypeRef; + + std::cout << "CallMeWithOptionalDouble get double " << type << std::endl; + + return AddPermissionUsedRecordSync(tokenID, content, successCount, failCount, type); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + std::cout << "ANI_Constructor called" << std::endl; + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + std::cerr << "Unsupported ANI_VERSION_1" << std::endl; + return (ani_status)ERRCODE_9; + } + + static const char *className = "LprivacyManager_ani/privacyManager/PrivacyManagerInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + std::cerr << "Not found '" << className << "'" << std::endl; + return (ani_status)ERRCODE_2; + } + + std::cout << "array methods called" << std::endl; + std::array methods = { + ani_native_function{ "addPermissionUsedRecordSync", + "ILstd/core/String;IILprivacyManager_ani/privacyManager/AddPermissionUsedRecordOptions;:I", + reinterpret_cast(AddPermissionUsedRecord) }, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + std::cerr << "Cannot bind native methods to '" << className << "'" << std::endl; + return (ani_status)ERRCODE_3; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file -- Gitee