diff --git a/interfaces/innerkits/cert_manager_standard/main/include/cm_type.h b/interfaces/innerkits/cert_manager_standard/main/include/cm_type.h index a8cd415f6d4d7de80475883544cd6239e0fdfe9d..caeee2dc8d5122a4bc5aa3b9b269dc147493ec63 100644 --- a/interfaces/innerkits/cert_manager_standard/main/include/cm_type.h +++ b/interfaces/innerkits/cert_manager_standard/main/include/cm_type.h @@ -159,6 +159,9 @@ enum CMDialogErrorCode { CMR_DIALOG_ERROR = -1, CMR_DIALOG_ERROR_INVALID_ARGUMENT = -2, CMR_DIALOG_ERROR_INTERNAL = -3, + CMR_DIALOG_ERROR_OPERATION_CANCELS = -4, + CMR_DIALOG_ERROR_INSTALL_FAILED = -5, + CMR_DIALOG_ERROR_NOT_SUPPORTED = -6, CMR_DIALOG_ERROR_PERMISSION_DENIED = 1011, }; @@ -380,11 +383,6 @@ static inline bool CmIsAdditionOverflow(uint32_t a, uint32_t b) return (UINT32_MAX - a) < b; } -static inline bool CmIsInvalidLength(uint32_t length) -{ - return (length == 0) || (length > MAX_OUT_BLOB_SIZE); -} - static inline int32_t CmCheckBlob(const struct CmBlob *blob) { if ((blob == NULL) || (blob->data == NULL) || (blob->size == 0)) { diff --git a/interfaces/kits/napi/BUILD.gn b/interfaces/kits/napi/BUILD.gn index e493638aa9a945802ab74e8fdb21396cf3f86bc7..f13feb524c3af0a77f4ac27041a27c6bb382e2b9 100644 --- a/interfaces/kits/napi/BUILD.gn +++ b/interfaces/kits/napi/BUILD.gn @@ -56,7 +56,9 @@ ohos_shared_library("certmanager") { external_deps = [ "c_utils:utils", + "ipc:ipc_core", "napi:ace_napi", + "samgr:samgr_proxy", ] cflags_cc = [ "-Wall", @@ -94,6 +96,7 @@ ohos_shared_library("certmanagerdialog") { "src/dialog/cm_napi_dialog.cpp", "src/dialog/cm_napi_dialog_common.cpp", "src/dialog/cm_napi_open_dialog.cpp", + "src/dialog/cm_napi_open_install_dialog.cpp", ] external_deps = [ @@ -107,7 +110,9 @@ ohos_shared_library("certmanagerdialog") { "ability_runtime:napi_common", "ace_engine:ace_uicontent", "c_utils:utils", + "ipc:ipc_core", "napi:ace_napi", + "samgr:samgr_proxy", ] cflags_cc = [ "-Wall", diff --git a/interfaces/kits/napi/include/dialog/cm_napi_dialog_common.h b/interfaces/kits/napi/include/dialog/cm_napi_dialog_common.h index 84cb3c4029febe7e9f3f84f29f932d98232a7352..47e51f0477e2906d71103a338bf1af96dee574f3 100644 --- a/interfaces/kits/napi/include/dialog/cm_napi_dialog_common.h +++ b/interfaces/kits/napi/include/dialog/cm_napi_dialog_common.h @@ -21,6 +21,7 @@ #include "napi/native_api.h" #include "napi/native_node_api.h" +#include "cm_napi_open_dialog.h" #include "cm_mem.h" #include "cm_type.h" @@ -30,9 +31,14 @@ static const std::string BUSINESS_ERROR_PROPERTY_CODE = "code"; static const std::string BUSINESS_ERROR_PROPERTY_MESSAGE = "message"; static const int32_t RESULT_NUMBER = 2; +void StartUIExtensionAbility(std::shared_ptr asyncContext, + OHOS::AAFwk::Want want, std::shared_ptr uiExtCallback); +bool ParseCmUIAbilityContextReq( + napi_env env, const napi_value& obj, std::shared_ptr& abilityContext); napi_value ParseUint32(napi_env env, napi_value object, uint32_t &store); napi_value ParseBoolean(napi_env env, napi_value object, bool &status); napi_value ParseString(napi_env env, napi_value object, CmBlob *&blob); +napi_value GetUint8ArrayToBase64Str(napi_env env, napi_value object, std::string &certArray); void ThrowError(napi_env env, int32_t errorCode, const std::string errMsg); napi_value GenerateBusinessError(napi_env env, int32_t errorCode); @@ -40,13 +46,6 @@ napi_value GenerateBusinessError(napi_env env, int32_t errorCode); void GeneratePromise(napi_env env, napi_deferred deferred, int32_t resultCode, napi_value *result, int32_t length); -inline napi_value GetNull(napi_env env) -{ - napi_value result = nullptr; - NAPI_CALL(env, napi_get_null(env, &result)); - return result; -} - inline napi_value GetInt32(napi_env env, int32_t value) { napi_value result = nullptr; @@ -58,7 +57,16 @@ enum CmDialogPageType { PAGE_MAIN = 1, PAGE_CA_CERTIFICATE = 2, PAGE_CREDENTIAL = 3, - PAGE_INSTALL_CERTIFICATE = 4 + PAGE_INSTALL_CERTIFICATE = 4, + PAGE_INSTALL_CA_GUIDE = 5 +}; + +enum CmCertificateType { + CA_CERT = 1 +}; + +enum CertificateScope { + CURRENT_USER = 1 }; enum ErrorCode { @@ -68,6 +76,8 @@ enum ErrorCode { PARAM_ERROR = 401, DIALOG_ERROR_GENERIC = 29700001, DIALOG_ERROR_OPERATION_CANCELED = 29700002, + DIALOG_ERROR_INSTALL_FAILED = 29700003, + DIALOG_ERROR_NOT_SUPPORTED = 29700004, }; } // namespace CertManagerNapi diff --git a/interfaces/kits/napi/include/dialog/cm_napi_open_dialog.h b/interfaces/kits/napi/include/dialog/cm_napi_open_dialog.h index f78e582fc61a2336beee3ceae488059f94b43f44..d9a0ba405f956abdbdd0e5651c548cad465eb7c7 100644 --- a/interfaces/kits/napi/include/dialog/cm_napi_open_dialog.h +++ b/interfaces/kits/napi/include/dialog/cm_napi_open_dialog.h @@ -24,7 +24,23 @@ #include "ui_content.h" namespace CMNapi { +const std::string PARAM_UI_EXTENSION_TYPE = "ability.want.params.uiExtensionType"; +const std::string SYS_COMMON_UI = "sys/commonUI"; +const std::string CERT_MANAGER_BUNDLENAME = "com.ohos.certmanager"; +const std::string CERT_MANAGER_ABILITYNAME = "CertPickerUIExtAbility"; +const std::string CERT_MANAGER_PAGE_TYPE = "pageType"; +const std::string CERT_MANAGER_CERTSCOPE_TYPE = "certScope"; +const std::string CERT_MANAGER_CERTIFICATE_DATA = "cert"; +const std::string CERT_MANAGER_CALLER_BUNDLENAME = "bundleName"; +constexpr int32_t PARAM0 = 0; +constexpr int32_t PARAM1 = 1; +constexpr int32_t PARAM2 = 2; +constexpr int32_t PARAM3 = 3; +constexpr int32_t PARAM_SIZE_TWO = 2; +constexpr int32_t PARAM_SIZE_FOUR = 4; + napi_value CMNapiOpenCertManagerDialog(napi_env env, napi_callback_info info); +napi_value CMNapiOpenInstallCertDialog(napi_env env, napi_callback_info info); struct CommonAsyncContext { explicit CommonAsyncContext(napi_env env); @@ -33,25 +49,32 @@ struct CommonAsyncContext { napi_status status = napi_invalid_arg; int32_t errCode = 0; napi_deferred deferred = nullptr; // promise handle + std::string uri = ""; }; struct CmUIExtensionRequestContext : public CommonAsyncContext { explicit CmUIExtensionRequestContext(napi_env env) : CommonAsyncContext(env) {}; std::shared_ptr context = nullptr; uint32_t pageType = 0; + uint32_t certificateType = 0; + uint32_t certificateScope = 0; + std::string certStr = ""; + std::string labelName = ""; }; class CmUIExtensionCallback { public: explicit CmUIExtensionCallback(std::shared_ptr& reqContext); - void SetSessionId(const int32_t sessionId); - void OnRelease(const int32_t releaseCode); - void OnResult(const int32_t resultCode, const OHOS::AAFwk::Want& result); - void OnReceive(const OHOS::AAFwk::WantParams& request); - void OnError(const int32_t code, const std::string& name, const std::string& message); - void OnRemoteReady(const std::shared_ptr& uiProxy); - void OnDestroy(); - void SendMessageBack(); + virtual ~CmUIExtensionCallback(); + virtual void SetSessionId(const int32_t sessionId); + virtual void OnRelease(const int32_t releaseCode); + virtual void OnResult(const int32_t resultCode, const OHOS::AAFwk::Want& result); + virtual void OnReceive(const OHOS::AAFwk::WantParams& request); + virtual void OnError(const int32_t code, const std::string& name, const std::string& message); + virtual void OnRemoteReady(const std::shared_ptr& uiProxy); + virtual void OnDestroy(); + virtual void SendMessageBack(); + virtual void ProcessCallback(napi_env env, const CommonAsyncContext* asyncContext); private: bool SetErrorCode(int32_t errCode); diff --git a/interfaces/kits/napi/src/dialog/cm_napi_dialog.cpp b/interfaces/kits/napi/src/dialog/cm_napi_dialog.cpp index 175bb45152279adf1fe7a67640c6c5f49bcdf456..6b2948f0f3d8ff18d6e9168078503848375e7202 100644 --- a/interfaces/kits/napi/src/dialog/cm_napi_dialog.cpp +++ b/interfaces/kits/napi/src/dialog/cm_napi_dialog.cpp @@ -35,6 +35,8 @@ static napi_value CreateCmErrorCode(napi_env env) AddInt32Property(env, dialogErrorCode, "ERROR_GENERIC", DIALOG_ERROR_GENERIC); AddInt32Property(env, dialogErrorCode, "ERROR_OPERATION_CANCELED", DIALOG_ERROR_OPERATION_CANCELED); + AddInt32Property(env, dialogErrorCode, "ERROR_OPERATION_FAILED", DIALOG_ERROR_INSTALL_FAILED); + AddInt32Property(env, dialogErrorCode, "ERROR_DEVICE_NOT_SUPPORTED", DIALOG_ERROR_NOT_SUPPORTED); return dialogErrorCode; } @@ -51,6 +53,26 @@ static napi_value CreateCmDialogPageType(napi_env env) return dialogPageType; } + +static napi_value CreateCmCertificateType(napi_env env) +{ + napi_value certificateType = nullptr; + NAPI_CALL(env, napi_create_object(env, &certificateType)); + + AddInt32Property(env, certificateType, "CA_CERT", CA_CERT); + + return certificateType; +} + +static napi_value CreateCmCertificateScope(napi_env env) +{ + napi_value certificateScope = nullptr; + NAPI_CALL(env, napi_create_object(env, &certificateScope)); + + AddInt32Property(env, certificateScope, "CURRENT_USER", CURRENT_USER); + + return certificateScope; +} } // namespace CertManagerNapi using namespace CMNapi; @@ -61,9 +83,12 @@ static napi_value CMDialogNapiRegister(napi_env env, napi_value exports) napi_property_descriptor desc[] = { DECLARE_NAPI_PROPERTY("CertificateDialogErrorCode", CreateCmErrorCode(env)), DECLARE_NAPI_PROPERTY("CertificateDialogPageType", CreateCmDialogPageType(env)), + DECLARE_NAPI_PROPERTY("CertificateType", CreateCmCertificateType(env)), + DECLARE_NAPI_PROPERTY("CertificateScope", CreateCmCertificateScope(env)), /* dialog */ DECLARE_NAPI_FUNCTION("openCertificateManagerDialog", CMNapiOpenCertManagerDialog), + DECLARE_NAPI_FUNCTION("openInstallCertificateDialog", CMNapiOpenInstallCertDialog), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); return exports; diff --git a/interfaces/kits/napi/src/dialog/cm_napi_dialog_common.cpp b/interfaces/kits/napi/src/dialog/cm_napi_dialog_common.cpp index 511bc30d883ed23811e4a1b155c2cf407f725144..149fa7eb55e8579ec3de3ebdc5166fa99df13e68 100644 --- a/interfaces/kits/napi/src/dialog/cm_napi_dialog_common.cpp +++ b/interfaces/kits/napi/src/dialog/cm_napi_dialog_common.cpp @@ -21,6 +21,20 @@ #include "cm_log.h" #include "cm_type.h" +#define BYTE_SHIFT_16 0x10 +#define BYTE_SHIFT_8 0x08 +#define BYTE_SHIFT_6 6 +#define BASE64_URL_TABLE_SIZE 0x3F +#define BASE64_GROUP_NUM 3 +#define BYTE_INDEX_ZONE 0 +#define BYTE_INDEX_ONE 1 +#define BYTE_INDEX_TWO 2 +#define BYTE_INDEX_THREE 3 +#define BASE64_PADDING "=" +#define BYTE_END_ONE 1 +#define BYTE_END_TWO 2 + +static const char g_base64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; namespace CMNapi { namespace { constexpr int CM_MAX_DATA_LEN = 0x6400000; // The maximum length is 100M @@ -28,6 +42,10 @@ constexpr int CM_MAX_DATA_LEN = 0x6400000; // The maximum length is 100M static const std::string DIALOG_NO_PERMISSION_MSG = "the caller has no permission"; static const std::string DIALOG_INVALID_PARAMS_MSG = "the input parameters is invalid"; static const std::string DIALOG_GENERIC_MSG = "there is an internal error"; +static const std::string DIALOG_OPERATION_CANCELS_MSG = "the user cancels the installation operation"; +static const std::string DIALOG_INSTALL_FAILED_MSG = "the user install certificate failed" + " in the certificate manager dialog"; +static const std::string DIALOG_NOT_SUPPORTED_MSG = "the API is not supported on this device"; static const std::unordered_map DIALOG_CODE_TO_JS_CODE_MAP = { // invalid params @@ -36,15 +54,125 @@ static const std::unordered_map DIALOG_CODE_TO_JS_CODE_MAP = { { CMR_DIALOG_ERROR_PERMISSION_DENIED, HAS_NO_PERMISSION }, // internal error { CMR_DIALOG_ERROR_INTERNAL, DIALOG_ERROR_GENERIC }, + // the user cancels the installation operation + { CMR_DIALOG_ERROR_OPERATION_CANCELS, DIALOG_ERROR_OPERATION_CANCELED }, + // the user install certificate failed in the certificate manager dialog + { CMR_DIALOG_ERROR_INSTALL_FAILED, DIALOG_ERROR_INSTALL_FAILED }, + // the API is not supported on this device + { CMR_DIALOG_ERROR_NOT_SUPPORTED, DIALOG_ERROR_NOT_SUPPORTED }, }; static const std::unordered_map DIALOG_CODE_TO_MSG_MAP = { { CMR_DIALOG_ERROR_INVALID_ARGUMENT, DIALOG_INVALID_PARAMS_MSG }, { CMR_DIALOG_ERROR_PERMISSION_DENIED, DIALOG_NO_PERMISSION_MSG }, { CMR_DIALOG_ERROR_INTERNAL, DIALOG_GENERIC_MSG }, + { CMR_DIALOG_ERROR_OPERATION_CANCELS, DIALOG_OPERATION_CANCELS_MSG }, + { CMR_DIALOG_ERROR_INSTALL_FAILED, DIALOG_INSTALL_FAILED_MSG }, + { CMR_DIALOG_ERROR_NOT_SUPPORTED, DIALOG_NOT_SUPPORTED_MSG }, }; } // namespace +void StartUIExtensionAbility(std::shared_ptr asyncContext, + OHOS::AAFwk::Want want, std::shared_ptr uiExtCallback) +{ + CM_LOG_D("begin StartUIExtensionAbility"); + auto abilityContext = asyncContext->context; + if (abilityContext == nullptr) { + CM_LOG_E("abilityContext is null"); + ThrowError(asyncContext->env, PARAM_ERROR, "abilityContext is null"); + return; + } + auto uiContent = abilityContext->GetUIContent(); + if (uiContent == nullptr) { + CM_LOG_E("uiContent is null"); + ThrowError(asyncContext->env, PARAM_ERROR, "uiContent is null"); + return; + } + + OHOS::Ace::ModalUIExtensionCallbacks extensionCallbacks = { + [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& request) { uiExtCallback->OnReceive(request); }, + [uiExtCallback](int32_t errorCode, const std::string& name, const std::string& message) { + uiExtCallback->OnError(errorCode, name, message); }, + [uiExtCallback](const std::shared_ptr& uiProxy) { + uiExtCallback->OnRemoteReady(uiProxy); }, + [uiExtCallback]() { uiExtCallback->OnDestroy(); } + }; + + OHOS::Ace::ModalUIExtensionConfig uiExtConfig; + uiExtConfig.isProhibitBack = false; + int32_t sessionId = uiContent->CreateModalUIExtension(want, extensionCallbacks, uiExtConfig); + CM_LOG_I("end CreateModalUIExtension"); + if (sessionId == 0) { + CM_LOG_E("CreateModalUIExtension failed"); + ThrowError(asyncContext->env, PARAM_ERROR, "CreateModalUIExtension failed"); + } + uiExtCallback->SetSessionId(sessionId); + return; +} + +static std::string EncodeBase64(const uint8_t *indata, const uint32_t length) +{ + std::string encodeStr(""); + if (indata == nullptr) { + CM_LOG_E("input param is invalid"); + return encodeStr; + } + int i = 0; + while (i < (int)length) { + unsigned int octeta = i < (int)length ? *(indata + (i++)) : 0; + unsigned int octetb = i < (int)length ? *(indata + (i++)) : 0; + unsigned int octetc = i < (int)length ? *(indata + (i++)) : 0; + + unsigned int triple = (octeta << BYTE_SHIFT_16) + (octetb << BYTE_SHIFT_8) + octetc; + + encodeStr += g_base64Table[(triple >> BYTE_INDEX_THREE * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE]; + encodeStr += g_base64Table[(triple >> BYTE_INDEX_TWO * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE]; + encodeStr += g_base64Table[(triple >> BYTE_INDEX_ONE * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE]; + encodeStr += g_base64Table[(triple >> BYTE_INDEX_ZONE * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE]; + } + + switch (BASE64_GROUP_NUM - (i % BASE64_GROUP_NUM)) { + case BYTE_END_TWO: + encodeStr.replace(encodeStr.length() - BYTE_END_TWO, 1, BASE64_PADDING); + encodeStr.replace(encodeStr.length() - BYTE_END_ONE, 1, BASE64_PADDING); + break; + case BYTE_END_ONE: + encodeStr.replace(encodeStr.length() - BYTE_END_ONE, 1, BASE64_PADDING); + break; + default: + break; + } + return encodeStr; +} + +bool ParseCmUIAbilityContextReq( + napi_env env, const napi_value& obj, std::shared_ptr& abilityContext) +{ + bool stageMode = false; + napi_status status = OHOS::AbilityRuntime::IsStageContext(env, obj, stageMode); + if (status != napi_ok || !stageMode) { + CM_LOG_E("not stage mode"); + return false; + } + + auto context = OHOS::AbilityRuntime::GetStageModeContext(env, obj); + if (context == nullptr) { + CM_LOG_E("get context failed"); + return false; + } + + abilityContext = OHOS::AbilityRuntime::Context::ConvertTo(context); + if (abilityContext == nullptr) { + CM_LOG_E("get abilityContext failed"); + return false; + } + CM_LOG_I("end ParseUIAbilityContextReq"); + return true; +} + napi_value ParseUint32(napi_env env, napi_value object, uint32_t &store) { napi_valuetype type; @@ -89,7 +217,6 @@ napi_value ParseString(napi_env env, napi_value obj, CmBlob *&blob) return nullptr; } - // add 0 length check if ((length == 0) || (length > CM_MAX_DATA_LEN)) { CM_LOG_E("input string length is 0 or too large, length: %d", length); return nullptr; @@ -125,6 +252,51 @@ napi_value ParseString(napi_env env, napi_value obj, CmBlob *&blob) return GetInt32(env, 0); } +napi_value GetUint8ArrayToBase64Str(napi_env env, napi_value object, std::string &certArray) +{ + napi_typedarray_type arrayType; + napi_value arrayBuffer = nullptr; + size_t length = 0; + size_t offset = 0; + void *certData = nullptr; + + napi_status status = napi_get_typedarray_info( + env, object, &arrayType, &length, static_cast(&certData), &arrayBuffer, &offset); + if (arrayType != napi_uint8_array) { + return nullptr; + } + if (status != napi_ok) { + CM_LOG_E("the type of param is not uint8_array"); + return nullptr; + } + if (length > CM_MAX_DATA_LEN) { + CM_LOG_E("certData is too large, length = %x", length); + return nullptr; + } + uint8_t *data = nullptr; + if (length == 0) { + CM_LOG_D("The memory length created is only 1 Byte"); + // The memory length created is only 1 Byte + data = static_cast(CmMalloc(1)); + } else { + data = static_cast(CmMalloc(length)); + } + if (data == nullptr) { + CM_LOG_E("Malloc failed"); + return nullptr; + } + (void)memset_s(data, length, 0, length); + if (memcpy_s(data, length, certData, length) != EOK) { + CmFree(data); + CM_LOG_E("memcpy_s fail, length = %x", length); + return nullptr; + } + std::string encode = EncodeBase64(data, length); + certArray = encode; + CmFree(data); + return GetInt32(env, 0); +} + static const char *GetJsErrorMsg(int32_t errCode) { auto iter = DIALOG_CODE_TO_MSG_MAP.find(errCode); diff --git a/interfaces/kits/napi/src/dialog/cm_napi_open_dialog.cpp b/interfaces/kits/napi/src/dialog/cm_napi_open_dialog.cpp index 44d837cd761ae0af61124316d4debe63214554ba..7f70837b40eeaf486847c49a6252d7f420529824 100644 --- a/interfaces/kits/napi/src/dialog/cm_napi_open_dialog.cpp +++ b/interfaces/kits/napi/src/dialog/cm_napi_open_dialog.cpp @@ -25,16 +25,6 @@ #include "want_params_wrapper.h" namespace CMNapi { -namespace { -const std::string PARAM_UI_EXTENSION_TYPE = "ability.want.params.uiExtensionType"; -const std::string SYS_COMMON_UI = "sys/commonUI"; -const std::string CERT_MANAGER_BUNDLENAME = "com.ohos.certmanager"; -const std::string CERT_MANAGER_ABILITYNAME = "CertPickerUIExtAbility"; -const std::string CERT_MANAGER_PAGE_TYPE = "pageType"; -constexpr int32_t PARAM0 = 0; -constexpr int32_t PARAM1 = 1; -constexpr int32_t PARAM_SIZE_TWO = 2; -} // namespace CommonAsyncContext::CommonAsyncContext(napi_env env) { @@ -52,6 +42,11 @@ CmUIExtensionCallback::CmUIExtensionCallback(std::shared_ptrreqContext_ = reqContext; } +CmUIExtensionCallback::~CmUIExtensionCallback() +{ + CM_LOG_D("~CmUIExtensionCallback"); +} + void CmUIExtensionCallback::SetSessionId(const int32_t sessionId) { this->sessionId_ = sessionId; @@ -120,7 +115,7 @@ void CmUIExtensionCallback::OnDestroy() } } -void ProcessCallback(napi_env env, const CommonAsyncContext* asyncContext) +void CmUIExtensionCallback::ProcessCallback(napi_env env, const CommonAsyncContext* asyncContext) { napi_value args[PARAM_SIZE_TWO] = {nullptr}; @@ -158,73 +153,6 @@ void CmUIExtensionCallback::SendMessageBack() ProcessCallback(this->reqContext_->env, this->reqContext_.get()); } -bool ParseCmUIAbilityContextReq( - napi_env env, const napi_value& obj, std::shared_ptr& abilityContext) -{ - bool stageMode = false; - napi_status status = OHOS::AbilityRuntime::IsStageContext(env, obj, stageMode); - if (status != napi_ok || !stageMode) { - CM_LOG_E("not stage mode"); - return false; - } - - auto context = OHOS::AbilityRuntime::GetStageModeContext(env, obj); - if (context == nullptr) { - CM_LOG_E("get context failed"); - return false; - } - - abilityContext = OHOS::AbilityRuntime::Context::ConvertTo(context); - if (abilityContext == nullptr) { - CM_LOG_E("get abilityContext failed"); - return false; - } - CM_LOG_I("end ParseUIAbilityContextReq"); - return true; -} - -static void StartUIExtensionAbility(std::shared_ptr asyncContext, - OHOS::AAFwk::Want want) -{ - CM_LOG_D("begin StartUIExtensionAbility"); - auto abilityContext = asyncContext->context; - if (abilityContext == nullptr) { - CM_LOG_E("abilityContext is null"); - ThrowError(asyncContext->env, PARAM_ERROR, "abilityContext is null"); - return; - } - auto uiContent = abilityContext->GetUIContent(); - if (uiContent == nullptr) { - CM_LOG_E("uiContent is null"); - ThrowError(asyncContext->env, PARAM_ERROR, "uiContent is null"); - return; - } - - auto uiExtCallback = std::make_shared(asyncContext); - OHOS::Ace::ModalUIExtensionCallbacks extensionCallbacks = { - [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& request) { uiExtCallback->OnReceive(request); }, - [uiExtCallback](int32_t errorCode, const std::string& name, const std::string& message) { - uiExtCallback->OnError(errorCode, name, message); }, - [uiExtCallback](const std::shared_ptr& uiProxy) { - uiExtCallback->OnRemoteReady(uiProxy); }, - [uiExtCallback]() { uiExtCallback->OnDestroy(); } - }; - - OHOS::Ace::ModalUIExtensionConfig uiExtConfig; - uiExtConfig.isProhibitBack = false; - int32_t sessionId = uiContent->CreateModalUIExtension(want, extensionCallbacks, uiExtConfig); - CM_LOG_I("end CreateModalUIExtension"); - if (sessionId == 0) { - CM_LOG_E("CreateModalUIExtension failed"); - ThrowError(asyncContext->env, PARAM_ERROR, "CreateModalUIExtension failed"); - } - uiExtCallback->SetSessionId(sessionId); - return; -} - static bool IsCmDialogPageTypeEnum(const uint32_t value) { switch (static_cast(value)) { @@ -283,8 +211,9 @@ napi_value CMNapiOpenCertManagerDialog(napi_env env, napi_callback_info info) want.SetParam(PARAM_UI_EXTENSION_TYPE, SYS_COMMON_UI); NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result)); + auto uiExtCallback = std::make_shared(asyncContext); // Start ui extension by context. - StartUIExtensionAbility(asyncContext, want); + StartUIExtensionAbility(asyncContext, want, uiExtCallback); CM_LOG_D("cert manager dialog end"); return result; } diff --git a/interfaces/kits/napi/src/dialog/cm_napi_open_install_dialog.cpp b/interfaces/kits/napi/src/dialog/cm_napi_open_install_dialog.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5f842ca2d5e687fba70365c77ed109da18ef6209 --- /dev/null +++ b/interfaces/kits/napi/src/dialog/cm_napi_open_install_dialog.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2024 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 "cm_napi_open_dialog.h" + +#include "syspara/parameters.h" +#include "securec.h" + +#include "cert_manager_api.h" +#include "cm_log.h" +#include "iservice_registry.h" +#include "bundle_mgr_proxy.h" +#include "system_ability_definition.h" + +#include "cm_napi_dialog_common.h" +#include "want.h" +#include "want_params_wrapper.h" + +namespace CMNapi { + +class CmInstallUIExtensionCallback : public CmUIExtensionCallback { +public: + explicit CmInstallUIExtensionCallback( + std::shared_ptr& reqContext) : CmUIExtensionCallback(reqContext) + { + this->reqContext_ = reqContext; + } + + ~CmInstallUIExtensionCallback() override + { + CM_LOG_D("~CmInstallUIExtensionCallback"); + } + + void OnRelease(const int32_t releaseCode) override + { + CM_LOG_D("InstallUIExtensionComponent OnRelease(), releaseCode = %d", releaseCode); + if (SetErrorCode(CMR_DIALOG_ERROR_OPERATION_CANCELS)) { + SendMessageBack(); + } + } + + void OnResult(const int32_t resultCode, const OHOS::AAFwk::Want& result) override + { + CM_LOG_D("InstallUIExtensionComponent OnResult(), resultCode = %d", resultCode); + this->resultCode_ = resultCode; + this->resultWant_ = result; + if (SetErrorCode(CMR_DIALOG_ERROR_INSTALL_FAILED)) { + SendMessageBack(); + } + } + + void OnReceive(const OHOS::AAFwk::WantParams& request) override + { + CM_LOG_D("InstallUIExtensionComponent OnReceive()"); + this->reqContext_->uri = request.GetStringParam("uri"); + if (SetErrorCode(0)) { + SendMessageBack(); + } + } + + void ProcessCallback(napi_env env, const CommonAsyncContext* asyncContext) override + { + napi_value args = nullptr; + if (asyncContext->errCode == CM_SUCCESS) { + NAPI_CALL_RETURN_VOID(env, + napi_create_string_utf8(env, asyncContext->uri.c_str(), NAPI_AUTO_LENGTH, &args)); + } else { + args = GenerateBusinessError(env, asyncContext->errCode); + } + + if (asyncContext->deferred != nullptr) { + if (asyncContext->errCode == CM_SUCCESS) { + NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncContext->deferred, args)); + } else { + NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncContext->deferred, args)); + } + } + } + + void OnDestroy() override + { + CM_LOG_D("InstallUIExtensionComponent OnDestroy()"); + } + +private: + bool SetErrorCode(int32_t errCode) + { + if (this->reqContext_ == nullptr) { + CM_LOG_E("OnError reqContext is nullptr"); + return false; + } + if (this->alreadyCallback_) { + CM_LOG_D("alreadyCallback"); + return false; + } + this->alreadyCallback_ = true; + this->reqContext_->errCode = errCode; + return true; + }; + int32_t resultCode_ = 0; + OHOS::AAFwk::Want resultWant_; + std::shared_ptr reqContext_ = nullptr; + bool alreadyCallback_ = false; +}; + +static bool IsCmCertificateScopeEnum(const uint32_t value) +{ + switch (static_cast(value)) { + case CertificateScope::CURRENT_USER: + return true; + default: + return false; + } +} + +static bool IsCmCertificateTypeAndConvert(const uint32_t value, uint32_t &pageType) +{ + switch (static_cast(value)) { + case CmCertificateType::CA_CERT: + pageType = CmDialogPageType::PAGE_INSTALL_CA_GUIDE; + return true; + default: + return false; + } +} + +static napi_value CMCheckArgvAndInitContext(std::shared_ptr asyncContext, + napi_value argv[], size_t length) +{ + if (length != PARAM_SIZE_FOUR) { + CM_LOG_E("params number vaild failed"); + return nullptr; + } + // Parse first argument for context. + if (!ParseCmUIAbilityContextReq(asyncContext->env, argv[PARAM0], asyncContext->context)) { + CM_LOG_E("ParseUIAbilityContextReq failed"); + return nullptr; + } + + // Parse second argument for certificate type. + uint32_t certificateType = 0; + if (ParseUint32(asyncContext->env, argv[PARAM1], certificateType) == nullptr) { + CM_LOG_E("parse type failed"); + return nullptr; + } + if (!IsCmCertificateTypeAndConvert(certificateType, asyncContext->certificateType)) { + CM_LOG_E("certificateType invalid"); + return nullptr; + } + + // Parse third argument for certificateScope. + if (ParseUint32(asyncContext->env, argv[PARAM2], asyncContext->certificateScope) == nullptr) { + CM_LOG_E("parse type failed"); + return nullptr; + } + if (!IsCmCertificateScopeEnum(asyncContext->certificateScope)) { + CM_LOG_E("certificateScope invalid"); + return nullptr; + } + + // Parse fourth argument for cert. + if (GetUint8ArrayToBase64Str(asyncContext->env, argv[PARAM3], asyncContext->certStr) == nullptr) { + CM_LOG_E("cert is not a uint8Array or the length is 0 or too long."); + return nullptr; + } + return GetInt32(asyncContext->env, 0); +} + +static OHOS::AAFwk::Want CMGetInstallCertWant(std::shared_ptr asyncContext) +{ + OHOS::AAFwk::Want want; + want.SetElementName(CERT_MANAGER_BUNDLENAME, CERT_MANAGER_ABILITYNAME); + want.SetParam(CERT_MANAGER_PAGE_TYPE, static_cast(asyncContext->certificateType)); + want.SetParam(CERT_MANAGER_CERTIFICATE_DATA, asyncContext->certStr); + want.SetParam(CERT_MANAGER_CERTSCOPE_TYPE, static_cast(asyncContext->certificateScope)); + want.SetParam(CERT_MANAGER_CALLER_BUNDLENAME, asyncContext->labelName); + want.SetParam(PARAM_UI_EXTENSION_TYPE, SYS_COMMON_UI); + return want; +} + +static OHOS::sptr GetBundleMgrProxy() +{ + auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + CM_LOG_E("fail to get system ability mgr."); + return nullptr; + } + + auto remoteObject = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (!remoteObject) { + CM_LOG_E("fail to get bundle manager proxy."); + return nullptr; + } + return OHOS::iface_cast(remoteObject); +} + +static int32_t GetCallerLabelName(std::shared_ptr asyncContext) +{ + OHOS::sptr bundleMgrProxy = GetBundleMgrProxy(); + if (bundleMgrProxy == nullptr) { + CM_LOG_E("Failed to get bundle manager proxy."); + return CM_FAILURE; + } + + OHOS::AppExecFwk::BundleInfo bundleInfo; + int32_t flags = static_cast(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_DEFAULT) | + static_cast(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) | + static_cast(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) | + static_cast(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_ABILITY); + int32_t resCode = bundleMgrProxy->GetBundleInfoForSelf(flags, bundleInfo); + if (resCode != CM_SUCCESS) { + CM_LOG_E("Failed to get bundleInfo, resCode is %d", resCode); + return CM_FAILURE; + } + + if (asyncContext->context->GetResourceManager() == nullptr) { + CM_LOG_E("context get resourcemanager faild"); + return CMR_ERROR_NULL_POINTER; + } + + resCode = asyncContext->context->GetResourceManager()->GetStringById(bundleInfo.applicationInfo.labelId, + asyncContext->labelName); + if (resCode != CM_SUCCESS) { + CM_LOG_E("getStringById is faild, resCode is %d", resCode); + return CM_FAILURE; + } + return CM_SUCCESS; +} + +napi_value CMNapiOpenInstallCertDialog(napi_env env, napi_callback_info info) +{ + CM_LOG_D("cert install dialog enter"); + napi_value result = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &result)); + if (OHOS::system::GetParameter("const.product.devicetype", "") != "2in1") { + CM_LOG_E("deviceType is not 2in1"); + std::string errMsg = "DeviceType Error. deviceType is not 2in1"; + ThrowError(env, DIALOG_ERROR_NOT_SUPPORTED, errMsg); + return result; + } + + size_t argc = PARAM_SIZE_FOUR; + napi_value argv[PARAM_SIZE_FOUR] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + if (argc != PARAM_SIZE_FOUR) { + CM_LOG_E("params number mismatch"); + std::string errMsg = "Parameter Error. Params number mismatch, need " + std::to_string(PARAM_SIZE_FOUR) + + ", given " + std::to_string(argc); + ThrowError(env, PARAM_ERROR, errMsg); + return result; + } + + auto asyncContext = std::make_shared(env); + asyncContext->env = env; + if (CMCheckArgvAndInitContext(asyncContext, argv, sizeof(argv) / sizeof(argv[0])) == nullptr) { + CM_LOG_E("check argv vaild and init faild"); + ThrowError(env, PARAM_ERROR, "check argv vaild and init faild"); + return nullptr; + } + + if (GetCallerLabelName(asyncContext) != CM_SUCCESS) { + CM_LOG_E("get caller labelName faild"); + ThrowError(env, DIALOG_ERROR_GENERIC, "get caller labelName faild"); + return nullptr; + } + NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result)); + + auto uiExtCallback = std::make_shared(asyncContext); + StartUIExtensionAbility(asyncContext, CMGetInstallCertWant(asyncContext), uiExtCallback); + CM_LOG_D("cert install dialog end"); + return result; +} +} // namespace CMNapi +