* 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 "manager.h"
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <arkui/native_interface.h>
#include <arkui/native_node.h>
#include <arkui/native_node_napi.h>
#include <arkui/native_type.h>
#include <hilog/log.h>
#include <string>
#include "napi/native_api.h"
namespace NativeXComponentSample {
Manager Manager::manager_;
Manager::~Manager()
{
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "~Manager");
for (auto iter = nativeXComponentMap_.begin(); iter != nativeXComponentMap_.end(); ++iter) {
if (iter->second != nullptr) {
iter->second = nullptr;
}
}
nativeXComponentMap_.clear();
for (auto iter = containerMap_.begin(); iter != containerMap_.end(); ++iter) {
if (iter->second != nullptr) {
delete iter->second;
iter->second = nullptr;
}
}
containerMap_.clear();
}
static ArkUI_NativeNodeAPI_1* nodeAPI = nullptr;
void CreateKeyEventSample(napi_env env, napi_value arg, OH_NativeXComponent* component)
{
KeyEventSample::KeyEventHandler* keyHandler = KeyEventSample::KeyEventHandler::GetInstance();
keyHandler->Initialize();
ArkUI_NodeHandle keyEventNode = keyHandler->CreateKeyEventNode();
if (keyEventNode) {
OH_NativeXComponent_AttachNativeRootNode(component, keyEventNode);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "Key event sample UI created successfully");
} else {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Failed to create key event sample UI");
}
}
napi_value Manager::CreateNativeNode(napi_env env, napi_callback_info info)
{
if ((env == nullptr) || (info == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null");
return nullptr;
}
size_t argCnt = 2;
napi_value args[2] = { nullptr };
if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed");
}
if (argCnt < 1) {
napi_throw_type_error(env, NULL, "Wrong number of arguments");
return nullptr;
}
napi_valuetype valuetype;
if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_typeof failed");
return nullptr;
}
if (valuetype != napi_string) {
napi_throw_type_error(env, NULL, "Wrong type of arguments");
return nullptr;
}
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
size_t length;
if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
return nullptr;
}
auto manager = Manager::GetInstance();
if (manager == nullptr) {
return nullptr;
}
OH_NativeXComponent* component = manager->GetNativeXComponent(idStr);
if (component == nullptr) {
return nullptr;
}
OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
if (nodeAPI != nullptr) {
if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
CreateKeyEventSample(env, args[1], component);
}
}
return nullptr;
}
napi_value Manager::UpdateNativeNode(napi_env env, napi_callback_info info)
{
if ((env == nullptr) || (info == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode env or info is null");
return nullptr;
}
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "UpdateNativeNode");
size_t argCnt = 1;
napi_value args[1] = { nullptr };
if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode napi_get_cb_info failed");
}
if (argCnt != 1) {
napi_throw_type_error(env, NULL, "Wrong number of arguments");
return nullptr;
}
napi_valuetype valuetype;
if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_typeof failed");
return nullptr;
}
if (valuetype != napi_string) {
napi_throw_type_error(env, NULL, "Wrong type of arguments");
return nullptr;
}
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
size_t length;
if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
return nullptr;
}
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "UpdateNativeNode %{public}s", idStr);
auto manager = Manager::GetInstance();
if (manager == nullptr) {
return nullptr;
}
OH_NativeXComponent* component = manager->GetNativeXComponent(idStr);
if (component == nullptr) {
return nullptr;
}
return nullptr;
}
napi_value Manager::GetContext(napi_env env, napi_callback_info info)
{
if ((env == nullptr) || (info == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
return nullptr;
}
size_t argCnt = 1;
napi_value args[1] = { nullptr };
if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext napi_get_cb_info failed");
}
if (argCnt != 1) {
napi_throw_type_error(env, NULL, "Wrong number of arguments");
return nullptr;
}
napi_valuetype valuetype;
if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_typeof failed");
return nullptr;
}
if (valuetype != napi_number) {
napi_throw_type_error(env, NULL, "Wrong type of arguments");
return nullptr;
}
int64_t value;
if (napi_get_value_int64(env, args[0], &value) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
return nullptr;
}
napi_value exports;
if (napi_create_object(env, &exports) != napi_ok) {
napi_throw_type_error(env, NULL, "napi_create_object failed");
return nullptr;
}
return exports;
}
void Manager::Export(napi_env env, napi_value exports)
{
if ((env == nullptr) || (exports == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: env or exports is null");
return;
}
napi_value exportInstance = nullptr;
if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_get_named_property fail");
return;
}
OH_NativeXComponent* nativeXComponent = nullptr;
if (napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent)) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_unwrap fail");
return;
}
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
OH_LOG_Print(
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: OH_NativeXComponent_GetXComponentId fail");
return;
}
std::string id(idStr);
auto manager = Manager::GetInstance();
if ((manager != nullptr) && (nativeXComponent != nullptr)) {
manager->SetNativeXComponent(id, nativeXComponent);
}
}
void Manager::SetNativeXComponent(std::string& id, OH_NativeXComponent* nativeXComponent)
{
if (nativeXComponent == nullptr) {
return;
}
if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {
nativeXComponentMap_[id] = nativeXComponent;
return;
}
if (nativeXComponentMap_[id] != nativeXComponent) {
OH_NativeXComponent* tmp = nativeXComponentMap_[id];
tmp = nullptr;
nativeXComponentMap_[id] = nativeXComponent;
}
}
OH_NativeXComponent* Manager::GetNativeXComponent(const std::string& id)
{
return nativeXComponentMap_[id];
}
}