1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "native_node_napi.h"
17
18
19#include "node/node_extened.h"
20#include "node/node_model.h"
21
22#include "base/error/error_code.h"
23#include "core/components_ng/base/frame_node.h"
24
25extern "C" {
26
27int32_t OH_ArkUI_GetNodeHandleFromNapiValue(napi_env env, napi_value value, ArkUI_NodeHandle* handle)
28{
29    bool hasProperty = false;
30    auto result = napi_has_named_property(env, value, "nodePtr_", &hasProperty);
31    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
32    if (result == napi_ok && hasProperty) {
33        napi_value frameNodePtr = nullptr;
34        auto result = napi_get_named_property(env, value, "nodePtr_", &frameNodePtr);
35        if (result != napi_ok) {
36            LOGE("fail to get nodePtr");
37            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
38        }
39        // BuilderNode case.
40        void* nativePtr = nullptr;
41        result = napi_get_value_external(env, frameNodePtr, &nativePtr);
42        if (result != napi_ok || nativePtr == nullptr) {
43            LOGE("fail to get nodePtr external value");
44            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
45        }
46        auto* uiNodePtr = reinterpret_cast<OHOS::Ace::NG::UINode*>(nativePtr);
47        uiNodePtr->IncRefCount();
48        *handle = new ArkUI_Node({ .type = -1, .uiNodeHandle = reinterpret_cast<ArkUINodeHandle>(nativePtr) });
49        if (impl) {
50            impl->getExtendedAPI()->setAttachNodePtr((*handle)->uiNodeHandle, reinterpret_cast<void*>(*handle));
51        }
52        return OHOS::Ace::ERROR_CODE_NO_ERROR;
53    }
54    result = napi_has_named_property(env, value, "builderNode_", &hasProperty);
55    if (result == napi_ok && hasProperty) {
56        // Component Content case.
57        napi_value builderNode = nullptr;
58        auto result = napi_get_named_property(env, value, "builderNode_", &builderNode);
59        if (result != napi_ok) {
60            LOGE("fail to get builderNode");
61            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
62        }
63        napi_value nodePtr = nullptr;
64        result = napi_get_named_property(env, builderNode, "nodePtr_", &nodePtr);
65        if (result != napi_ok) {
66            LOGE("fail to get nodePtr in builderNode");
67            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
68        }
69        void* nativePtr = nullptr;
70        result = napi_get_value_external(env, nodePtr, &nativePtr);
71        if (result != napi_ok) {
72            LOGE("fail to get nodePtr external value in builderNode");
73            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
74        }
75        auto* uiNode = reinterpret_cast<OHOS::Ace::NG::UINode*>(nativePtr);
76        OHOS::Ace::NG::FrameNode* frameNode = OHOS::Ace::AceType::DynamicCast<OHOS::Ace::NG::FrameNode>(uiNode);
77        if (frameNode == nullptr) {
78            LOGE("fail to get frameNode value in builderNode");
79            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
80        }
81        if (frameNode->GetTag() == "BuilderProxyNode") {
82            // need to get the really frameNode.
83            if (!impl) {
84                return OHOS::Ace::ERROR_CODE_NATIVE_IMPL_LIBRARY_NOT_FOUND;
85            }
86            auto* child = impl->getNodeModifiers()->getFrameNodeModifier()->getChild(
87                reinterpret_cast<ArkUINodeHandle>(frameNode), 0, true);
88            if (!child) {
89                LOGE("fail to get child in BuilderProxyNode");
90                return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
91            }
92            frameNode = reinterpret_cast<OHOS::Ace::NG::FrameNode*>(child);
93        }
94        frameNode->IncRefCount();
95        *handle = new ArkUI_Node({ .type = -1, .uiNodeHandle = reinterpret_cast<ArkUINodeHandle>(frameNode) });
96        if (impl) {
97            impl->getExtendedAPI()->setAttachNodePtr((*handle)->uiNodeHandle, reinterpret_cast<void*>(*handle));
98        }
99        return OHOS::Ace::ERROR_CODE_NO_ERROR;
100    }
101    return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
102}
103
104int32_t OH_ArkUI_GetContextFromNapiValue(napi_env env, napi_value value, ArkUI_ContextHandle* context)
105{
106    bool hasProperty = false;
107    auto result = napi_has_named_property(env, value, "instanceId_", &hasProperty);
108    if (result != napi_ok || !hasProperty) {
109        LOGE("fail to get Context value");
110        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
111    }
112
113    napi_value contextPtr = nullptr;
114    result = napi_get_named_property(env, value, "instanceId_", &contextPtr);
115    if (result != napi_ok) {
116        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
117    }
118
119    napi_valuetype valuetype;
120    if (napi_typeof(env, contextPtr, &valuetype) != napi_ok) {
121        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
122    }
123    if (valuetype != napi_number) {
124        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
125    }
126    int32_t instanceId = -1;
127    result = napi_get_value_int32(env, contextPtr, &instanceId);
128    if (result != napi_ok) {
129        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
130    }
131    *context = new ArkUI_Context({ .id = instanceId });
132    return OHOS::Ace::ERROR_CODE_NO_ERROR;
133}
134
135int32_t OH_ArkUI_GetNodeContentFromNapiValue(napi_env env, napi_value value, ArkUI_NodeContentHandle* content)
136{
137    bool hasProperty = false;
138    auto result = napi_has_named_property(env, value, "nativePtr_", &hasProperty);
139    if (result != napi_ok || !hasProperty) {
140        LOGE("fail to get native content value");
141        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
142    }
143    napi_value nativeContent = nullptr;
144    result = napi_get_named_property(env, value, "nativePtr_", &nativeContent);
145    if (result != napi_ok) {
146        LOGE("fail to get native content");
147        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
148    }
149    void* nativePtr = nullptr;
150    result = napi_get_value_external(env, nativeContent, &nativePtr);
151    if (result != napi_ok) {
152        LOGE("fail to get native content ptr");
153        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
154    }
155    *content = reinterpret_cast<ArkUI_NodeContentHandle>(nativePtr);
156    return OHOS::Ace::ERROR_CODE_NO_ERROR;
157}
158
159int32_t OH_ArkUI_GetDrawableDescriptorFromNapiValue(
160    napi_env env, napi_value value, ArkUI_DrawableDescriptor** drawableDescriptor)
161{
162    void* objectNapi = nullptr;
163    napi_unwrap(env, value, &objectNapi);
164    if (!objectNapi) {
165        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
166    }
167    ArkUI_DrawableDescriptor* drawable =
168        new ArkUI_DrawableDescriptor { nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr };
169    auto* descriptor = reinterpret_cast<OHOS::Ace::Napi::DrawableDescriptor*>(objectNapi);
170    if (!descriptor) {
171        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
172    }
173    auto drawableType = descriptor->GetDrawableType();
174    if (drawableType == OHOS::Ace::Napi::DrawableDescriptor::DrawableType::ANIMATED) {
175        auto* animatedDrawable = static_cast<OHOS::Ace::Napi::AnimatedDrawableDescriptor*>(descriptor);
176        if (!animatedDrawable) {
177            return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
178        }
179        int32_t duration = animatedDrawable->GetDuration();
180        int32_t iteration = animatedDrawable->GetIterations();
181        drawable->animatedDrawableDescriptor = std::make_shared<OHOS::Ace::Napi::AnimatedDrawableDescriptor>(
182            animatedDrawable->GetPixelMapList(), duration, iteration);
183        *drawableDescriptor = drawable;
184        return OHOS::Ace::ERROR_CODE_NO_ERROR;
185    }
186    drawable->drawableDescriptor = std::make_shared<OHOS::Ace::Napi::DrawableDescriptor>(descriptor->GetPixelMap());
187    *drawableDescriptor = drawable;
188    return OHOS::Ace::ERROR_CODE_NO_ERROR;
189}
190
191int32_t OH_ArkUI_GetDrawableDescriptorFromResourceNapiValue(
192    napi_env env, napi_value value, ArkUI_DrawableDescriptor** drawableDescriptor)
193{
194    auto parseApi = reinterpret_cast<void (*)(void*, void*)>(OHOS::Ace::NodeModel::GetParseJsMedia());
195    if (!parseApi) {
196        return OHOS::Ace::ERROR_CODE_PARAM_INVALID;
197    }
198
199    ArkUI_DrawableDescriptor* drawable =
200        new ArkUI_DrawableDescriptor { nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr };
201    drawable->resource = std::make_shared<ArkUI_Resource>();
202    parseApi(value, drawable->resource.get());
203    *drawableDescriptor = drawable;
204    return OHOS::Ace::ERROR_CODE_NO_ERROR;
205}
206
207ArkUI_ErrorCode  OH_ArkUI_GetNavigationId(
208    ArkUI_NodeHandle node, char* buffer, int32_t bufferSize, int32_t* writeLength)
209{
210    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
211    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
212    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
213    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
214    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
215    auto navigationAPI = fullImpl->getNavigation();
216    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
217    auto ret =
218        navigationAPI->getNavigationId(node->uiNodeHandle, buffer, bufferSize, writeLength);
219    return static_cast<ArkUI_ErrorCode>(ret);
220}
221
222ArkUI_ErrorCode OH_ArkUI_GetNavDestinationName(
223    ArkUI_NodeHandle node, char* buffer, int32_t bufferSize, int32_t* writeLength)
224{
225    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
226    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
227    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
228    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
229    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
230    auto navigationAPI = fullImpl->getNavigation();
231    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
232    auto ret =
233        navigationAPI->getNavDestinationName(node->uiNodeHandle, buffer, bufferSize, writeLength);
234    return static_cast<ArkUI_ErrorCode>(ret);
235}
236
237ArkUI_ErrorCode OH_ArkUI_GetNavStackLength(ArkUI_NodeHandle node, int32_t* length)
238{
239    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
240    CHECK_NULL_RETURN(length, ARKUI_ERROR_CODE_PARAM_INVALID);
241    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
242    auto stacklength = fullImpl->getNavigation()->getStackLength(node->uiNodeHandle);
243    if (stacklength < 0) {
244        return ARKUI_ERROR_CODE_GET_INFO_FAILED;
245    }
246    *length = stacklength;
247    return ARKUI_ERROR_CODE_NO_ERROR;
248}
249
250ArkUI_ErrorCode OH_ArkUI_GetNavDestinationNameByIndex(
251    ArkUI_NodeHandle node, int32_t index, char* buffer, int32_t bufferSize, int32_t* writeLength)
252{
253    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
254    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
255    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
256    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
257    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
258    auto navigationAPI = fullImpl->getNavigation();
259    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
260    auto ret =
261        navigationAPI->getNavDesNameByIndex(node->uiNodeHandle, index, buffer, bufferSize, writeLength);
262    return static_cast<ArkUI_ErrorCode>(ret);
263}
264
265ArkUI_ErrorCode OH_ArkUI_GetNavDestinationId(
266    ArkUI_NodeHandle node, char* buffer, int32_t bufferSize, int32_t* writeLength)
267{
268    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
269    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
270    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
271    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
272    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
273    auto navigationAPI = fullImpl->getNavigation();
274    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
275    auto ret =
276        navigationAPI->getNavDestinationId(node->uiNodeHandle, buffer, bufferSize, writeLength);
277    return static_cast<ArkUI_ErrorCode>(ret);
278}
279
280ArkUI_ErrorCode OH_ArkUI_GetNavDestinationState(ArkUI_NodeHandle node, ArkUI_NavDestinationState* state)
281{
282    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
283    CHECK_NULL_RETURN(state, ARKUI_ERROR_CODE_PARAM_INVALID);
284    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
285    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
286    auto navigationAPI = fullImpl->getNavigation();
287    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
288
289    auto navDestinationState = navigationAPI->getNavDestinationState(node->uiNodeHandle);
290    if (navDestinationState < 0) {
291        return ARKUI_ERROR_CODE_GET_INFO_FAILED;
292    }
293    *state = static_cast<ArkUI_NavDestinationState>(navDestinationState);
294    return ARKUI_ERROR_CODE_NO_ERROR;
295}
296
297ArkUI_ErrorCode OH_ArkUI_GetNavDestinationIndex(ArkUI_NodeHandle node, int32_t* index)
298{
299    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
300    CHECK_NULL_RETURN(index, ARKUI_ERROR_CODE_PARAM_INVALID);
301    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
302    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
303    auto navigationAPI = fullImpl->getNavigation();
304    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
305
306    auto retIndex = navigationAPI->getNavDestinationIndex(node->uiNodeHandle);
307    if (retIndex < 0) {
308        return ARKUI_ERROR_CODE_GET_INFO_FAILED;
309    }
310    *index = retIndex;
311    return ARKUI_ERROR_CODE_NO_ERROR;
312}
313
314napi_value OH_ArkUI_GetNavDestinationParam(ArkUI_NodeHandle node)
315{
316    CHECK_NULL_RETURN(node, nullptr);
317    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
318    CHECK_NULL_RETURN(fullImpl, nullptr);
319    auto navigationAPI = fullImpl->getNavigation();
320    CHECK_NULL_RETURN(navigationAPI, nullptr);
321    return reinterpret_cast<napi_value>(navigationAPI->getNavDestinationParam(node->uiNodeHandle));
322}
323
324ArkUI_ErrorCode OH_ArkUI_GetRouterPageIndex(ArkUI_NodeHandle node, int32_t* index)
325{
326    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
327    CHECK_NULL_RETURN(index, ARKUI_ERROR_CODE_PARAM_INVALID);
328    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
329    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
330    auto navigationAPI = fullImpl->getNavigation();
331    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
332
333    auto retIndex = navigationAPI->getRouterPageIndex(node->uiNodeHandle);
334    if (retIndex < 0) {
335        return ARKUI_ERROR_CODE_GET_INFO_FAILED;
336    }
337    *index = retIndex;
338    return ARKUI_ERROR_CODE_NO_ERROR;
339}
340
341ArkUI_ErrorCode OH_ArkUI_GetRouterPageName(
342    ArkUI_NodeHandle node, char* buffer, int32_t bufferSize, int32_t* writeLength)
343{
344    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
345    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
346    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
347    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
348    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
349    auto navigationAPI = fullImpl->getNavigation();
350    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
351    auto ret =
352        navigationAPI->getRouterPageName(node->uiNodeHandle, buffer, bufferSize, writeLength);
353    return static_cast<ArkUI_ErrorCode>(ret);
354}
355
356ArkUI_ErrorCode OH_ArkUI_GetRouterPagePath(
357    ArkUI_NodeHandle node, char* buffer, int32_t bufferSize, int32_t* writeLength)
358{
359    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
360    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
361    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
362    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
363    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
364    auto navigationAPI = fullImpl->getNavigation();
365    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
366    auto ret =
367        navigationAPI->getRouterPagePath(node->uiNodeHandle, buffer, bufferSize, writeLength);
368    return static_cast<ArkUI_ErrorCode>(ret);
369}
370
371ArkUI_ErrorCode OH_ArkUI_GetRouterPageState(ArkUI_NodeHandle node, ArkUI_RouterPageState* state)
372{
373    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
374    CHECK_NULL_RETURN(state, ARKUI_ERROR_CODE_PARAM_INVALID);
375    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
376    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
377    auto navigationAPI = fullImpl->getNavigation();
378    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
379
380    auto routerPageState = navigationAPI->getRouterPageState(node->uiNodeHandle);
381    if (routerPageState < 0) {
382        return ARKUI_ERROR_CODE_GET_INFO_FAILED;
383    }
384    *state = static_cast<ArkUI_RouterPageState>(routerPageState);
385    return ARKUI_ERROR_CODE_NO_ERROR;
386}
387
388ArkUI_ErrorCode OH_ArkUI_GetRouterPageId(
389    ArkUI_NodeHandle node, char* buffer, int32_t bufferSize, int32_t* writeLength)
390{
391    CHECK_NULL_RETURN(node, ARKUI_ERROR_CODE_PARAM_INVALID);
392    CHECK_NULL_RETURN(buffer, ARKUI_ERROR_CODE_PARAM_INVALID);
393    CHECK_NULL_RETURN(writeLength, ARKUI_ERROR_CODE_PARAM_INVALID);
394    auto* fullImpl = OHOS::Ace::NodeModel::GetFullImpl();
395    CHECK_NULL_RETURN(fullImpl, ARKUI_ERROR_CODE_GET_INFO_FAILED);
396    auto navigationAPI = fullImpl->getNavigation();
397    CHECK_NULL_RETURN(navigationAPI, ARKUI_ERROR_CODE_GET_INFO_FAILED);
398    auto ret =
399        navigationAPI->getRouterPageId(node->uiNodeHandle, buffer, bufferSize, writeLength);
400    return static_cast<ArkUI_ErrorCode>(ret);
401}
402}
403