From 69d325e89d8fd94f7d6860593492c669a042e9ae Mon Sep 17 00:00:00 2001 From: hhhhs9527 Date: Mon, 22 Aug 2022 10:02:47 +0800 Subject: [PATCH 1/4] =?UTF-8?q?2022/08/22=20=E6=9D=83=E9=99=90=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E7=9B=91=E5=90=ACnapi=20Signed-off-by:hanshu5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hhhhs9527 --- interfaces/kits/accesstoken/BUILD.gn | 2 + .../accesstoken/napi/include/napi_atmanager.h | 62 ++- .../accesstoken/napi/src/napi_atmanager.cpp | 474 +++++++++++++++++- interfaces/kits/common/BUILD.gn | 1 + interfaces/kits/common/include/napi_common.h | 6 + interfaces/kits/common/src/napi_common.cpp | 28 ++ 6 files changed, 570 insertions(+), 3 deletions(-) diff --git a/interfaces/kits/accesstoken/BUILD.gn b/interfaces/kits/accesstoken/BUILD.gn index 71bd9856d..c3781bc36 100644 --- a/interfaces/kits/accesstoken/BUILD.gn +++ b/interfaces/kits/accesstoken/BUILD.gn @@ -18,6 +18,7 @@ ohos_shared_library("libabilityaccessctrl") { "//base/security/access_token/frameworks/common/include", "//base/security/access_token/interfaces/innerkits/accesstoken/include", "//base/security/access_token/interfaces/kits/accesstoken/napi/include", + "//base/security/access_token/interfaces/kits/common/include", "//foundation/arkui/napi/interfaces/inner_api", "//foundation/arkui/napi/interfaces/kits", ] @@ -26,6 +27,7 @@ ohos_shared_library("libabilityaccessctrl") { deps = [ "//base/security/access_token/interfaces/innerkits/accesstoken:libaccesstoken_sdk", + "//base/security/access_token/interfaces/kits/common:libnapi_common", "//foundation/arkui/napi:ace_napi", ] cflags_cc = [ "-DHILOG_ENABLE" ] diff --git a/interfaces/kits/accesstoken/napi/include/napi_atmanager.h b/interfaces/kits/accesstoken/napi/include/napi_atmanager.h index 167e816c9..0be35fe4c 100644 --- a/interfaces/kits/accesstoken/napi/include/napi_atmanager.h +++ b/interfaces/kits/accesstoken/napi/include/napi_atmanager.h @@ -19,23 +19,68 @@ #include #include #include +#include +#include "access_token.h" +#include "accesstoken_kit.h" +#include "napi_common.h" #include "napi/native_api.h" #include "napi/native_node_api.h" +#include "perm_state_change_callback_customize.h" namespace OHOS { namespace Security { namespace AccessToken { const int AT_PERM_OPERA_FAIL = -1; const int AT_PERM_OPERA_SUCC = 0; -const int VALUE_BUFFER_SIZE = 256; -const int ASYNC_CALL_BACK_VALUES_NUM = 2; const int VERIFY_OR_FLAG_INPUT_MAX_VALUES = 2; const int GRANT_OR_REVOKE_INPUT_MAX_VALUES = 4; +enum PermissionStateChangeType { + PERMISSION_REVOKED_OPER = 0, + PERMISSION_GRANTED_OPER = 1, +}; + static thread_local napi_ref atManagerRef_; const std::string ATMANAGER_CLASS_NAME = "atManager"; +class RegisterPermStateChangeScopePtr : public PermStateChangeCallbackCustomize { +public: + explicit RegisterPermStateChangeScopePtr(const PermStateChangeScope& subscribeInfo); + ~RegisterPermStateChangeScopePtr(); + void PermStateChangeCallback(PermStateChangeInfo& result) override; + void SetEnv(const napi_env& env); + void SetCallbackRef(const napi_ref& ref); +private: + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; +}; + +struct RegisterPermStateChangeWorker { + napi_env env = nullptr; + napi_ref ref = nullptr; + PermStateChangeInfo result; + RegisterPermStateChangeScopePtr* subscriber = nullptr; +}; + +struct PermStateChangeContext { + virtual ~PermStateChangeContext(); + napi_env env = nullptr; + napi_async_work work = nullptr; + napi_ref callbackRef = nullptr; + int32_t errCode = RET_FAILED; + std::string permStateChangeType; + PermStateChangeScope scopeInfo; + AccessTokenKit* accessTokenKit = nullptr; + std::shared_ptr subscriber = nullptr; +}; + +struct RegisterPermStateChangeInfo : public PermStateChangeContext {}; + +struct UnregisterPermStateChangeInfo : public PermStateChangeContext { + ~UnregisterPermStateChangeInfo(); +}; + struct AtManagerAsyncContext { napi_env env = nullptr; uint32_t tokenId = 0; @@ -75,6 +120,19 @@ private: static void GetPermissionFlagsExcute(napi_env env, void *data); static void GetPermissionFlagsComplete(napi_env env, napi_status status, void *data); static void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName); + static bool ParseInputToRegister(const napi_env env, napi_callback_info cbInfo, + RegisterPermStateChangeInfo& registerPermStateChangeInfo); + static napi_value RegisterPermStateChangeCallback(napi_env env, napi_callback_info cbinfo); + static void RegisterPermStateChangeExecute(napi_env env, void* data); + static void RegisterPermStateChangeComplete(napi_env env, napi_status status, void* data); + static bool IsExistRegister(const RegisterPermStateChangeInfo* registerPermStateChangeInfo); + static bool ParseInputToUnregister(const napi_env env, napi_callback_info cbInfo, + UnregisterPermStateChangeInfo& unregisterPermStateChangeInfo); + static napi_value UnregisterPermStateChangeCallback(napi_env env, napi_callback_info cbinfo); + static void UnregisterPermStateChangeExecute(napi_env env, void* data); + static void UnregisterPermStateChangeCompleted(napi_env env, napi_status status, void* data); + static bool FindAndGetSubscriberInMap(UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo); + static void DeleteRegisterInMap(AccessTokenKit* accessTokenKit, const PermStateChangeScope& scopeInfo); }; } // namespace AccessToken } // namespace Security diff --git a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp index a74f44ccc..db450074e 100644 --- a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp +++ b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -27,12 +28,145 @@ namespace OHOS { namespace Security { namespace AccessToken { +std::mutex g_lockForPermStateChangeRegisters; +std::map> g_permStateChangeRegisters; namespace { static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AccessTokenAbilityAccessCtrl" }; + +static bool ConvertPermStateChangeInfo(napi_env env, napi_value value, const PermStateChangeInfo& result) +{ + napi_value element; + NAPI_CALL_BASE(env, napi_create_int32(env, result.PermStateChangeType, &element), false); + NAPI_CALL_BASE(env, napi_set_named_property(env, value, "change", element), false); + element = nullptr; + NAPI_CALL_BASE(env, napi_create_int32(env, result.tokenID, &element), false); + NAPI_CALL_BASE(env, napi_set_named_property(env, value, "tokenID", element), false); + element = nullptr; + NAPI_CALL_BASE(env, napi_create_string_utf8(env, result.permissionName.c_str(), + NAPI_AUTO_LENGTH, &element), false); + NAPI_CALL_BASE(env, napi_set_named_property(env, value, "permissionName", element), false); + return true; +}; + +static bool CompareScopeInfo(const PermStateChangeScope& scopeInfo, + const std::vector& tokenIDs, const std::vector& permList) +{ + std::vector targetTokenIDs = scopeInfo.tokenIDs; + std::vector targetPermList = scopeInfo.permList; + if (targetTokenIDs.size() != tokenIDs.size() || targetPermList.size() != permList.size()) { + return false; + } + std::sort(targetTokenIDs.begin(), targetTokenIDs.end()); + std::sort(targetPermList.begin(), targetPermList.end()); + if (std::equal(targetTokenIDs.begin(), targetTokenIDs.end(), tokenIDs.begin()) && + std::equal(targetPermList.begin(), targetPermList.end(), permList.begin())) { + return true; + } + return false; +}; + +static void UvQueueWorkPermStateChanged(uv_work_t* work, int status) +{ + if (work == nullptr || work->data == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "work == nullptr || work->data == nullptr"); + return; + } + std::unique_ptr uvWorkPtr {work}; + RegisterPermStateChangeWorker* registerPermStateChangeData = + reinterpret_cast(work->data); + std::unique_ptr workPtr {registerPermStateChangeData}; + napi_value result[ARGS_ONE] = {nullptr}; + NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env, + napi_create_array(registerPermStateChangeData->env, &result[PARAM0])); + if (!ConvertPermStateChangeInfo(registerPermStateChangeData->env, + result[PARAM0], registerPermStateChangeData->result)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertPermStateChangeInfo failed"); + return; + } + napi_value undefined = nullptr; + napi_value callback = nullptr; + napi_value resultout = nullptr; + NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env, + napi_get_undefined(registerPermStateChangeData->env, &undefined)); + NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env, + napi_get_reference_value(registerPermStateChangeData->env, registerPermStateChangeData->ref, &callback)); + NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env, + napi_call_function(registerPermStateChangeData->env, + undefined, callback, ARGS_ONE, &result[PARAM0], &resultout)); + ACCESSTOKEN_LOG_DEBUG(LABEL, "UvQueueWorkPermStateChanged end"); +}; } // namespace +RegisterPermStateChangeScopePtr::RegisterPermStateChangeScopePtr(const PermStateChangeScope& subscribeInfo) + : PermStateChangeCallbackCustomize(subscribeInfo) +{} + +RegisterPermStateChangeScopePtr::~RegisterPermStateChangeScopePtr() +{} + +void RegisterPermStateChangeScopePtr::PermStateChangeCallback(PermStateChangeInfo& result) +{ + uv_loop_s* loop = nullptr; + NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop)); + if (loop == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "loop instance is nullptr"); + return; + } + uv_work_t* work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "insufficient memory for work!"); + return; + } + std::unique_ptr uvWorkPtr {work}; + RegisterPermStateChangeWorker* registerPermStateChangeWorker = + new (std::nothrow) RegisterPermStateChangeWorker(); + if (registerPermStateChangeWorker == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "insufficient memory for RegisterPermStateChangeWorker!"); + return; + } + std::unique_ptr workPtr {registerPermStateChangeWorker}; + registerPermStateChangeWorker->env = env_; + registerPermStateChangeWorker->ref = ref_; + registerPermStateChangeWorker->result = result; + ACCESSTOKEN_LOG_DEBUG(LABEL, + "result PermStateChangeType = %{public}d, tokenID = %{public}d, permissionName = %{public}s", + result.PermStateChangeType, result.tokenID, result.permissionName.c_str()); + registerPermStateChangeWorker->subscriber = this; + work->data = reinterpret_cast(registerPermStateChangeWorker); + NAPI_CALL_RETURN_VOID(env_, + uv_queue_work(loop, work, [](uv_work_t* work) {}, UvQueueWorkPermStateChanged)); + uvWorkPtr.release(); + workPtr.release(); +} + +void RegisterPermStateChangeScopePtr::SetEnv(const napi_env& env) +{ + env_ = env; +} + +void RegisterPermStateChangeScopePtr::SetCallbackRef(const napi_ref& ref) +{ + ref_ = ref; +} + +PermStateChangeContext::~PermStateChangeContext() +{ + if (callbackRef != nullptr) { + napi_delete_reference(env, callbackRef); + callbackRef = nullptr; + } +} + +UnregisterPermStateChangeInfo::~UnregisterPermStateChangeInfo() +{ + if (work != nullptr) { + napi_delete_async_work(env, work); + work = nullptr; + } +} + void NapiAtManager::SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName) { napi_value prop = nullptr; @@ -54,7 +188,9 @@ napi_value NapiAtManager::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("verifyAccessTokenSync", VerifyAccessTokenSync), DECLARE_NAPI_FUNCTION("grantUserGrantedPermission", GrantUserGrantedPermission), DECLARE_NAPI_FUNCTION("revokeUserGrantedPermission", RevokeUserGrantedPermission), - DECLARE_NAPI_FUNCTION("getPermissionFlags", GetPermissionFlags) + DECLARE_NAPI_FUNCTION("getPermissionFlags", GetPermissionFlags), + DECLARE_NAPI_FUNCTION("on", RegisterPermStateChangeCallback), + DECLARE_NAPI_FUNCTION("off", UnregisterPermStateChangeCallback), }; napi_value cons = nullptr; @@ -70,8 +206,15 @@ napi_value NapiAtManager::Init(napi_env env, napi_value exports) SetNamedProperty(env, GrantStatus, PERMISSION_DENIED, "PERMISSION_DENIED"); SetNamedProperty(env, GrantStatus, PERMISSION_GRANTED, "PERMISSION_GRANTED"); + napi_value permStateChangeType = nullptr; + napi_create_object(env, &permStateChangeType); + + SetNamedProperty(env, permStateChangeType, PERMISSION_REVOKED_OPER, "PERMISSION_REVOKED_OPER"); + SetNamedProperty(env, permStateChangeType, PERMISSION_GRANTED_OPER, "PERMISSION_GRANTED_OPER"); + napi_property_descriptor exportFuncs[] = { DECLARE_NAPI_PROPERTY("GrantStatus", GrantStatus), + DECLARE_NAPI_PROPERTY("PermissionStateChangeType", permStateChangeType), }; napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs); @@ -85,6 +228,21 @@ napi_value NapiAtManager::JsConstructor(napi_env env, napi_callback_info cbinfo) napi_value thisVar = nullptr; NAPI_CALL(env, napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr)); + AccessTokenKit* objectInfo = new (std::nothrow) AccessTokenKit(); + if (objectInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "objectInfo == nullptr"); + return nullptr; + } + if (napi_wrap(env, thisVar, objectInfo, [](napi_env env, void* data, void* hint) { + ACCESSTOKEN_LOG_DEBUG(LABEL, "delete accesstoken kit"); + if (data != nullptr) { + AccessTokenKit* objectInfo = (AccessTokenKit*) data; + delete objectInfo; + } + }, nullptr, nullptr) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_wrap failed"); + return nullptr; + } return thisVar; } @@ -550,6 +708,320 @@ napi_value NapiAtManager::GetPermissionFlags(napi_env env, napi_callback_info in return result; } + +bool NapiAtManager::ParseInputToRegister(const napi_env env, const napi_callback_info cbInfo, + RegisterPermStateChangeInfo& registerPermStateChangeInfo) +{ + size_t argc = ARGS_FOUR; + napi_value argv[ARGS_FOUR] = {nullptr}; + napi_value thisVar = nullptr; + napi_ref callback = nullptr; + if (napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, NULL) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_get_cb_info failed"); + return false; + } + std::string type = ParseString(env, argv[PARAM0]); + PermStateChangeScope scopeInfo; + if (!ParseAccessTokenIDArray(env, argv[PARAM1], scopeInfo.tokenIDs)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ParseAccessTokenIDArray failed"); + return false; + } + scopeInfo.permList = ParseStringArray(env, argv[PARAM2]); + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[PARAM3], &valueType); // get PRARM[3] type + if (valueType == napi_function) { + if (napi_create_reference(env, argv[PARAM3], 1, &callback) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_create_reference failed"); + return false; + } + } else { + ACCESSTOKEN_LOG_ERROR(LABEL, "argv[PARAM3] type matching failed"); + return false; + } + registerPermStateChangeInfo.env = env; + registerPermStateChangeInfo.work = nullptr; + registerPermStateChangeInfo.callbackRef = callback; + registerPermStateChangeInfo.permStateChangeType = type; + registerPermStateChangeInfo.scopeInfo = scopeInfo; + registerPermStateChangeInfo.subscriber = std::make_shared(scopeInfo); + AccessTokenKit* accessTokenKitInfo = nullptr; + if (napi_unwrap(env, thisVar, reinterpret_cast(&accessTokenKitInfo)) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_unwrap failed"); + return false; + } + registerPermStateChangeInfo.accessTokenKit = accessTokenKitInfo; + return true; +} + +void NapiAtManager::RegisterPermStateChangeExecute(napi_env env, void* data) +{ + if (data == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "data is null"); + return; + } + RegisterPermStateChangeInfo* registerPermStateChangeInfo = + reinterpret_cast(data); + (*registerPermStateChangeInfo->subscriber).SetEnv(env); + (*registerPermStateChangeInfo->subscriber).SetCallbackRef(registerPermStateChangeInfo->callbackRef); + registerPermStateChangeInfo->errCode = + AccessTokenKit::RegisterPermStateChangeCallback(registerPermStateChangeInfo->subscriber); + ACCESSTOKEN_LOG_DEBUG(LABEL, "RegisterPermStateChangeCallback ret = %{public}d", + registerPermStateChangeInfo->errCode); +} + +void NapiAtManager::RegisterPermStateChangeComplete(napi_env env, napi_status status, void *data) +{ + if (data == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "data is null"); + return; + } + RegisterPermStateChangeInfo* registerPermStateChangeInfo = + reinterpret_cast(data); + std::unique_ptr callbackPtr {registerPermStateChangeInfo}; + if (registerPermStateChangeInfo->errCode != RET_SUCCESS) { + ACCESSTOKEN_LOG_ERROR(LABEL, "errCode = %{public}d, delete register in map", + registerPermStateChangeInfo->errCode); + DeleteRegisterInMap(registerPermStateChangeInfo->accessTokenKit, registerPermStateChangeInfo->scopeInfo); + return; + } + NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, registerPermStateChangeInfo->work)); + registerPermStateChangeInfo->work = nullptr; + callbackPtr.release(); +} + +napi_value NapiAtManager::RegisterPermStateChangeCallback(napi_env env, napi_callback_info cbInfo) +{ + RegisterPermStateChangeInfo* registerPermStateChangeInfo = + new (std::nothrow) RegisterPermStateChangeInfo(); + if (registerPermStateChangeInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "insufficient memory for subscribeCBInfo!"); + return nullptr; + } + std::unique_ptr callbackPtr {registerPermStateChangeInfo}; + if (!ParseInputToRegister(env, cbInfo, *registerPermStateChangeInfo)) { + return nullptr; + } + if (IsExistRegister(registerPermStateChangeInfo)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Subscribe failed. The current subscriber has been existed"); + return nullptr; + } + { // add to map + std::lock_guard lock(g_lockForPermStateChangeRegisters); + g_permStateChangeRegisters[registerPermStateChangeInfo->accessTokenKit].emplace_back( + registerPermStateChangeInfo); + ACCESSTOKEN_LOG_DEBUG(LABEL, "add g_PermStateChangeRegisters->second.size = %{public}zu", + g_permStateChangeRegisters[registerPermStateChangeInfo->accessTokenKit].size()); + } + napi_value resource = nullptr; + if (napi_create_string_utf8(env, "RegisterPermStateChangeCallback", NAPI_AUTO_LENGTH, &resource) != napi_ok) { + DeleteRegisterInMap(registerPermStateChangeInfo->accessTokenKit, registerPermStateChangeInfo->scopeInfo); + return nullptr; + } + if (napi_create_async_work(env, + nullptr, + resource, + RegisterPermStateChangeExecute, + RegisterPermStateChangeComplete, + reinterpret_cast(registerPermStateChangeInfo), + ®isterPermStateChangeInfo->work) != napi_ok) { + DeleteRegisterInMap(registerPermStateChangeInfo->accessTokenKit, registerPermStateChangeInfo->scopeInfo); + return nullptr; + } + if (napi_queue_async_work(env, registerPermStateChangeInfo->work) != napi_ok) { + DeleteRegisterInMap(registerPermStateChangeInfo->accessTokenKit, registerPermStateChangeInfo->scopeInfo); + return nullptr; + } + callbackPtr.release(); + return nullptr; +} + +bool NapiAtManager::ParseInputToUnregister(const napi_env env, napi_callback_info cbInfo, + UnregisterPermStateChangeInfo& unregisterPermStateChangeInfo) +{ + size_t argc = ARGS_FOUR; + napi_value argv[ARGS_FOUR] = {nullptr}; + napi_value thisVar = nullptr; + napi_ref callback = nullptr; + if (napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, NULL) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_get_cb_info failed"); + return false; + } + std::string type = ParseString(env, argv[PARAM0]); + PermStateChangeScope scopeInfo; + if (!ParseAccessTokenIDArray(env, argv[PARAM1], scopeInfo.tokenIDs)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "ParseAccessTokenIDArray failed"); + return false; + } + scopeInfo.permList = ParseStringArray(env, argv[PARAM2]); + if (argc >= ARGS_FOUR) { + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[PARAM3], &valueType); // get PRARM[3] type + if (valueType == napi_function) { + if (napi_create_reference(env, argv[PARAM3], 1, &callback) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_create_reference failed"); + return false; + } + } else { + ACCESSTOKEN_LOG_ERROR(LABEL, "argv[PARAM3] type matching failed"); + return false; + } + } + unregisterPermStateChangeInfo.env = env; + unregisterPermStateChangeInfo.callbackRef = callback; + unregisterPermStateChangeInfo.permStateChangeType = type; + unregisterPermStateChangeInfo.scopeInfo = scopeInfo; + AccessTokenKit* accessTokenKitInfo = nullptr; + if (napi_unwrap(env, thisVar, reinterpret_cast(&accessTokenKitInfo)) != napi_ok) { + ACCESSTOKEN_LOG_ERROR(LABEL, "napi_unwrap failed"); + return false; + } + unregisterPermStateChangeInfo.accessTokenKit = accessTokenKitInfo; + return true; +} + +void NapiAtManager::UnregisterPermStateChangeExecute(napi_env env, void* data) +{ + ACCESSTOKEN_LOG_DEBUG(LABEL, "UnregisterPermStateChangeExecute begin"); + if (data == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "data is null"); + return; + } + UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo = + reinterpret_cast(data); + auto subscriber = unregisterPermStateChangeInfo->subscriber; + unregisterPermStateChangeInfo->errCode = AccessTokenKit::UnRegisterPermStateChangeCallback(subscriber); +} + +void NapiAtManager::UnregisterPermStateChangeCompleted(napi_env env, napi_status status, void* data) +{ + if (data == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "data is null"); + return; + } + UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo = + reinterpret_cast(data); + std::unique_ptr callbackPtr {unregisterPermStateChangeInfo}; + if (unregisterPermStateChangeInfo->callbackRef != nullptr) { + napi_value results[ARGS_ONE] = {nullptr}; + NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &results[PARAM0])); + napi_value undefined; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + napi_value resultout = nullptr; + napi_value callback = nullptr; + NAPI_CALL_RETURN_VOID(env, + napi_get_reference_value(env, unregisterPermStateChangeInfo->callbackRef, &callback)); + NAPI_CALL_RETURN_VOID(env, + napi_call_function(env, undefined, callback, ARGS_ONE, &results[PARAM0], &resultout)); + } + if (unregisterPermStateChangeInfo->errCode == RET_SUCCESS) { + DeleteRegisterInMap(unregisterPermStateChangeInfo->accessTokenKit, unregisterPermStateChangeInfo->scopeInfo); + } else { + ACCESSTOKEN_LOG_ERROR(LABEL, "errCode = %{public}d", unregisterPermStateChangeInfo->errCode); + } +} + +napi_value NapiAtManager::UnregisterPermStateChangeCallback(napi_env env, napi_callback_info cbInfo) +{ + UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo = + new (std::nothrow) UnregisterPermStateChangeInfo(); + if (unregisterPermStateChangeInfo == nullptr) { + ACCESSTOKEN_LOG_ERROR(LABEL, "insufficient memory for subscribeCBInfo!"); + return nullptr; + } + std::unique_ptr callbackPtr {unregisterPermStateChangeInfo}; + if (!ParseInputToUnregister(env, cbInfo, *unregisterPermStateChangeInfo)) { + return nullptr; + } + if (!FindAndGetSubscriberInMap(unregisterPermStateChangeInfo)) { + ACCESSTOKEN_LOG_ERROR(LABEL, "Unsubscribe failed. The current subscriber does not exist"); + return nullptr; + } + ACCESSTOKEN_LOG_DEBUG(LABEL, "The current subscriber exist"); + napi_value resource = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, "RegisterPermStateChangeCallback", NAPI_AUTO_LENGTH, &resource)); + NAPI_CALL(env, napi_create_async_work(env, + nullptr, + resource, + UnregisterPermStateChangeExecute, + UnregisterPermStateChangeCompleted, + reinterpret_cast(unregisterPermStateChangeInfo), + &(unregisterPermStateChangeInfo->work))); + NAPI_CALL(env, napi_queue_async_work(env, unregisterPermStateChangeInfo->work)); + callbackPtr.release(); + return nullptr; +} + +bool NapiAtManager::FindAndGetSubscriberInMap(UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo) +{ + std::lock_guard lock(g_lockForPermStateChangeRegisters); + std::vector tokenIDs = unregisterPermStateChangeInfo->scopeInfo.tokenIDs; + std::vector permList = unregisterPermStateChangeInfo->scopeInfo.permList; + std::sort(tokenIDs.begin(), tokenIDs.end()); + std::sort(permList.begin(), permList.end()); + auto registerInstance = g_permStateChangeRegisters.find(unregisterPermStateChangeInfo->accessTokenKit); + if (registerInstance != g_permStateChangeRegisters.end()) { + for (const auto& item : registerInstance->second) { + PermStateChangeScope scopeInfo; + item->subscriber->GetScope(scopeInfo); + if (CompareScopeInfo(scopeInfo, tokenIDs, permList)) { + ACCESSTOKEN_LOG_DEBUG(LABEL, "find subscriber in map"); + unregisterPermStateChangeInfo->subscriber = item->subscriber; + return true; + } + } + } + return false; +} + +bool NapiAtManager::IsExistRegister(const RegisterPermStateChangeInfo* registerPermStateChangeInfo) +{ + std::lock_guard lock(g_lockForPermStateChangeRegisters); + std::vector tokenIDs = registerPermStateChangeInfo->scopeInfo.tokenIDs; + std::vector permList = registerPermStateChangeInfo->scopeInfo.permList; + std::sort(tokenIDs.begin(), tokenIDs.end()); + std::sort(permList.begin(), permList.end()); + auto registerInstance = g_permStateChangeRegisters.find(registerPermStateChangeInfo->accessTokenKit); + if (registerInstance != g_permStateChangeRegisters.end()) { + for (const auto& item : registerInstance->second) { + PermStateChangeScope scopeInfo; + item->subscriber->GetScope(scopeInfo); + if (CompareScopeInfo(scopeInfo, tokenIDs, permList)) { + ACCESSTOKEN_LOG_DEBUG(LABEL, "find subscriber in map"); + return true; + } + } + } + ACCESSTOKEN_LOG_DEBUG(LABEL, "cannot find subscriber in map"); + return false; +} + +void NapiAtManager::DeleteRegisterInMap(AccessTokenKit* accessTokenKit, const PermStateChangeScope& scopeInfo) +{ + std::vector tokenIDs = scopeInfo.tokenIDs; + std::vector permList = scopeInfo.permList; + std::sort(tokenIDs.begin(), tokenIDs.end()); + std::sort(permList.begin(), permList.end()); + std::lock_guard lock(g_lockForPermStateChangeRegisters); + auto subscribers = g_permStateChangeRegisters.find(accessTokenKit); + if (subscribers != g_permStateChangeRegisters.end()) { + auto it = subscribers->second.begin(); + while (it != subscribers->second.end()) { + if (CompareScopeInfo((*it)->scopeInfo, tokenIDs, permList)) { + ACCESSTOKEN_LOG_DEBUG(LABEL, "Find subscribers in map, delete"); + subscribers->second.erase(it); + delete *it; + *it =nullptr; + break; + } else { + ++it; + } + } + if (subscribers->second.empty()) { + ACCESSTOKEN_LOG_DEBUG(LABEL, "No subscriberInfo in the vector, erase the map."); + g_permStateChangeRegisters.erase(subscribers); + } + } +} } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/interfaces/kits/common/BUILD.gn b/interfaces/kits/common/BUILD.gn index 7e98c3eea..53d90c905 100644 --- a/interfaces/kits/common/BUILD.gn +++ b/interfaces/kits/common/BUILD.gn @@ -17,6 +17,7 @@ ohos_static_library("libnapi_common") { include_dirs = [ "include", "//base/security/access_token/frameworks/common/include", + "//base/security/access_token/interfaces/innerkits/accesstoken/include", "//foundation/arkui/napi/interfaces/inner_api", "//foundation/arkui/napi/interfaces/kits", ] diff --git a/interfaces/kits/common/include/napi_common.h b/interfaces/kits/common/include/napi_common.h index 22c776293..4dda17ac7 100644 --- a/interfaces/kits/common/include/napi_common.h +++ b/interfaces/kits/common/include/napi_common.h @@ -16,20 +16,24 @@ #ifndef INTERFACES_PRIVACY_KITS_NAPI_COMMON_H #define INTERFACES_PRIVACY_KITS_NAPI_COMMON_H +#include "access_token.h" #include "napi/native_api.h" #include "napi/native_node_api.h" namespace OHOS { namespace Security { namespace AccessToken { +const int ARGS_ONE = 1; const int ARGS_TWO = 2; const int ARGS_THREE = 3; +const int ARGS_FOUR = 4; const int ARGS_FIVE = 5; const int ASYNC_CALL_BACK_VALUES_NUM = 2; const int PARAM0 = 0; const int PARAM1 = 1; const int PARAM2 = 2; const int PARAM3 = 3; +const int VALUE_BUFFER_SIZE = 256; bool ParseBool(const napi_env env, const napi_value value); int32_t ParseInt32(const napi_env env, const napi_value value); @@ -37,6 +41,8 @@ int64_t ParseInt64(const napi_env env, const napi_value value); uint32_t ParseUint32(const napi_env env, const napi_value value); std::string ParseString(const napi_env env, const napi_value value); std::vector ParseStringArray(const napi_env env, const napi_value value); +bool ParseAccessTokenIDArray(const napi_env& env, const napi_value& value, std::vector& res); +bool IsArray(const napi_env& env, const napi_value& value); } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/interfaces/kits/common/src/napi_common.cpp b/interfaces/kits/common/src/napi_common.cpp index 28c487953..000d7a8a1 100644 --- a/interfaces/kits/common/src/napi_common.cpp +++ b/interfaces/kits/common/src/napi_common.cpp @@ -109,6 +109,9 @@ std::string ParseString(const napi_env env, const napi_value value) std::vector ParseStringArray(const napi_env env, const napi_value value) { std::vector res; + if (!IsArray(env, value)) { + return res; + } uint32_t length = 0; napi_valuetype valuetype = napi_undefined; @@ -124,6 +127,31 @@ std::vector ParseStringArray(const napi_env env, const napi_value v } return res; } + +bool ParseAccessTokenIDArray(const napi_env& env, const napi_value& value, std::vector& res) +{ + uint32_t length = 0; + if (!IsArray(env, value)) { + return false; + } + napi_get_array_length(env, value, &length); + napi_value valueArray; + for (uint32_t i = 0; i < length; i++) { + napi_get_element(env, value, i, &valueArray); + res.emplace_back(ParseUint32(env, valueArray)); + } + return true; +}; + +bool IsArray(const napi_env& env, const napi_value& value) +{ + bool isArray = false; + napi_status ret = napi_is_array(env, value, &isArray); + if (ret != napi_ok) { + return false; + } + return isArray; +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file -- Gitee From 74bd631ad338f230495bde41eea5baf4883dda31 Mon Sep 17 00:00:00 2001 From: hhhhs9527 Date: Mon, 22 Aug 2022 10:36:12 +0800 Subject: [PATCH 2/4] =?UTF-8?q?2022/08/22=20=E6=9D=83=E9=99=90=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E7=9B=91=E5=90=ACnapi=20Signed-off-by:hanshu5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hhhhs9527 --- interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp index db450074e..ba1583c03 100644 --- a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp +++ b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp @@ -781,6 +781,9 @@ void NapiAtManager::RegisterPermStateChangeComplete(napi_env env, napi_status st if (registerPermStateChangeInfo->errCode != RET_SUCCESS) { ACCESSTOKEN_LOG_ERROR(LABEL, "errCode = %{public}d, delete register in map", registerPermStateChangeInfo->errCode); + // Even if napi_delete_async_work failed, invalid registerPermStateChangeInfo needs to be deleted + napi_delete_async_work(env, registerPermStateChangeInfo->work); + registerPermStateChangeInfo->work = nullptr; DeleteRegisterInMap(registerPermStateChangeInfo->accessTokenKit, registerPermStateChangeInfo->scopeInfo); return; } -- Gitee From 4775bfedfbd03c77477b7f788299f9dc43bb44a1 Mon Sep 17 00:00:00 2001 From: hhhhs9527 Date: Mon, 22 Aug 2022 21:00:47 +0800 Subject: [PATCH 3/4] =?UTF-8?q?2022/08/22=20=E6=9D=83=E9=99=90=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E7=8A=B6=E6=80=81=E7=9B=91=E5=90=ACnapi=20Signed-off-?= =?UTF-8?q?by:hanshu5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hhhhs9527 --- interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp | 2 -- services/privacymanager/BUILD.gn | 1 - 2 files changed, 3 deletions(-) diff --git a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp index ba1583c03..7a79a3689 100644 --- a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp +++ b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp @@ -777,7 +777,6 @@ void NapiAtManager::RegisterPermStateChangeComplete(napi_env env, napi_status st } RegisterPermStateChangeInfo* registerPermStateChangeInfo = reinterpret_cast(data); - std::unique_ptr callbackPtr {registerPermStateChangeInfo}; if (registerPermStateChangeInfo->errCode != RET_SUCCESS) { ACCESSTOKEN_LOG_ERROR(LABEL, "errCode = %{public}d, delete register in map", registerPermStateChangeInfo->errCode); @@ -789,7 +788,6 @@ void NapiAtManager::RegisterPermStateChangeComplete(napi_env env, napi_status st } NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, registerPermStateChangeInfo->work)); registerPermStateChangeInfo->work = nullptr; - callbackPtr.release(); } napi_value NapiAtManager::RegisterPermStateChangeCallback(napi_env env, napi_callback_info cbInfo) diff --git a/services/privacymanager/BUILD.gn b/services/privacymanager/BUILD.gn index a6db98aa7..06af0b7f8 100644 --- a/services/privacymanager/BUILD.gn +++ b/services/privacymanager/BUILD.gn @@ -67,7 +67,6 @@ if (is_standard_system) { "//base/security/access_token/services/common/database:accesstoken_database_cxx", "//base/security/access_token/services/privacymanager:privacy.rc", "//third_party/sqlite:sqlite", - "//utils/native/base:utils", ] external_deps = [ -- Gitee From 59a3b7282bacf2e699e0986e7e71e152e9a13a6b Mon Sep 17 00:00:00 2001 From: hhhhs9527 Date: Tue, 23 Aug 2022 07:57:38 +0800 Subject: [PATCH 4/4] =?UTF-8?q?2022/08/23=20=E6=9D=83=E9=99=90=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9B=91=E5=90=ACnapi=20Signed-off-by:hanshu5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp index 7a79a3689..b24861695 100644 --- a/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp +++ b/interfaces/kits/accesstoken/napi/src/napi_atmanager.cpp @@ -85,6 +85,7 @@ static void UvQueueWorkPermStateChanged(uv_work_t* work, int status) ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertPermStateChangeInfo failed"); return; } + napi_value undefined = nullptr; napi_value callback = nullptr; napi_value resultout = nullptr; @@ -230,7 +231,7 @@ napi_value NapiAtManager::JsConstructor(napi_env env, napi_callback_info cbinfo) NAPI_CALL(env, napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr)); AccessTokenKit* objectInfo = new (std::nothrow) AccessTokenKit(); if (objectInfo == nullptr) { - ACCESSTOKEN_LOG_ERROR(LABEL, "objectInfo == nullptr"); + ACCESSTOKEN_LOG_ERROR(LABEL, "objectInfo is nullptr"); return nullptr; } if (napi_wrap(env, thisVar, objectInfo, [](napi_env env, void* data, void* hint) { @@ -1009,9 +1010,9 @@ void NapiAtManager::DeleteRegisterInMap(AccessTokenKit* accessTokenKit, const Pe while (it != subscribers->second.end()) { if (CompareScopeInfo((*it)->scopeInfo, tokenIDs, permList)) { ACCESSTOKEN_LOG_DEBUG(LABEL, "Find subscribers in map, delete"); - subscribers->second.erase(it); delete *it; - *it =nullptr; + *it = nullptr; + subscribers->second.erase(it); break; } else { ++it; -- Gitee