1 /*
2  * Copyright (c) 2021-2022 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 #ifndef INTERFACES_KITS_NAPI_GRAPHIC_COMMON_COMMON_H
17 #define INTERFACES_KITS_NAPI_GRAPHIC_COMMON_COMMON_H
18 
19 #include <cstdint>
20 #include <node_api.h>
21 #include <node_api_types.h>
22 #include <memory>
23 #include <string>
24 
25 #include "js_native_api.h"
26 #include "js_native_api_types.h"
27 #include "window_manager_hilog.h"
28 #include "dm_common.h"
29 
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, OHOS::Rosen::HILOG_DOMAIN_WINDOW,
31                                                 "NapiWindowManagerCommonLayer" };
32 
33 const int PARAM_NUMBER = 2; // 2: callback func input number, also reused by Promise
34 
35 #define GNAPI_LOG(fmt, ...) OHOS::HiviewDFX::HiLog::Info(LABEL, \
36     "%{public}s:%{public}d " fmt, __func__, __LINE__, ##__VA_ARGS__)
37 
38 #define GNAPI_ASSERT(env, assertion, fmt, ...)  \
39     do {                                        \
40         if (assertion) {                        \
41             GNAPI_LOG(fmt, ##__VA_ARGS__);      \
42             return nullptr;                     \
43         }                                       \
44     } while (0)
45 
46 namespace OHOS {
47 napi_status SetMemberInt32(napi_env env, napi_value result, const char *key, int32_t value);
48 napi_status SetMemberUint32(napi_env env, napi_value result, const char *key, uint32_t value);
49 napi_status SetMemberUndefined(napi_env env, napi_value result, const char *key);
50 
51 bool CheckCallingPermission(const std::string& permission);
52 void SetErrorInfo(napi_env env, Rosen::DmErrorCode wret, const std::string& errMessage,
53     napi_value result[], int count);
54 void ProcessPromise(napi_env env, Rosen::DmErrorCode wret, napi_deferred deferred,
55     napi_value result[], int count);
56 void ProcessCallback(napi_env env, napi_ref ref, napi_value result[], int count);
57 bool NAPICall(napi_env env, napi_status status);
58 
59 template<typename ParamT>
60 struct AsyncCallbackInfo {
61     napi_async_work asyncWork;
62     napi_deferred deferred;
63     void (*async)(napi_env env, std::unique_ptr<ParamT>& param);
64     napi_value (*resolve)(napi_env env, std::unique_ptr<ParamT>& param);
65     std::unique_ptr<ParamT> param;
66     napi_ref ref;
67 };
68 
69 template<typename ParamT>
AsyncFunc(napi_env env,void * data)70 void AsyncFunc(napi_env env, void *data)
71 {
72     AsyncCallbackInfo<ParamT> *info = reinterpret_cast<AsyncCallbackInfo<ParamT> *>(data);
73     if (info->async) {
74         info->async(env, info->param);
75     }
76 }
77 
78 template<typename ParamT>
CompleteFunc(napi_env env,napi_status status,void * data)79 void CompleteFunc(napi_env env, napi_status status, void *data)
80 {
81     AsyncCallbackInfo<ParamT> *info = reinterpret_cast<AsyncCallbackInfo<ParamT> *>(data);
82     napi_value result[PARAM_NUMBER] = {nullptr};
83     if (info->param->wret == Rosen::DmErrorCode::DM_OK) {
84         napi_get_undefined(env, &result[0]);
85         result[1] = info->resolve(env, info->param);
86     } else {
87         SetErrorInfo(env, info->param->wret, info->param->errMessage, result, PARAM_NUMBER);
88     }
89     if (info->deferred) {
90         ProcessPromise(env, info->param->wret, info->deferred, result, PARAM_NUMBER);
91     } else {
92         ProcessCallback(env, info->ref, result, PARAM_NUMBER);
93     }
94     napi_delete_async_work(env, info->asyncWork);
95     delete info;
96 }
97 
98 template<typename ParamT>
CreatePromise(napi_env env,napi_value resourceName,const std::string & funcname,AsyncCallbackInfo<ParamT> * info)99 napi_value CreatePromise(napi_env env, napi_value resourceName,
100     const std::string& funcname, AsyncCallbackInfo<ParamT>* info)
101 {
102     napi_value result = nullptr;
103     if (!NAPICall(env, napi_create_promise(env, &info->deferred, &result))) {
104         return nullptr;
105     }
106     return result;
107 }
108 
109 template<typename ParamT>
CreateUndefined(napi_env env,napi_value resourceName,const std::string & funcname,AsyncCallbackInfo<ParamT> * info)110 napi_value CreateUndefined(napi_env env, napi_value resourceName,
111     const std::string& funcname, AsyncCallbackInfo<ParamT>* info)
112 {
113     napi_value result = nullptr;
114     if (!NAPICall(env, napi_get_undefined(env, &result))) {
115         return nullptr;
116     }
117     return result;
118 }
119 
120 template<typename ParamT>
AsyncProcess(napi_env env,const std::string & funcname,void (* async)(napi_env env,std::unique_ptr<ParamT> & param),napi_value (* resolve)(napi_env env,std::unique_ptr<ParamT> & param),napi_ref & callbackRef,std::unique_ptr<ParamT> & param)121 napi_value AsyncProcess(napi_env env,
122                         const std::string& funcname,
123                         void(*async)(napi_env env, std::unique_ptr<ParamT>& param),
124                         napi_value(*resolve)(napi_env env, std::unique_ptr<ParamT>& param),
125                         napi_ref& callbackRef,
126                         std::unique_ptr<ParamT>& param)
127 {
128     AsyncCallbackInfo<ParamT> *info = new AsyncCallbackInfo<ParamT> {
129         .async = async,
130         .resolve = resolve,
131         .param = std::move(param),
132         .ref = callbackRef,
133     };
134 
135     napi_value resourceName = nullptr;
136     if (!NAPICall(env, napi_create_string_latin1(env, funcname.c_str(), NAPI_AUTO_LENGTH, &resourceName))) {
137         delete info;
138         return nullptr;
139     }
140 
141     napi_value result = nullptr;
142     if (callbackRef == nullptr) {
143         result = CreatePromise(env, resourceName, funcname, info);
144     } else {
145         result = CreateUndefined(env, resourceName, funcname, info);
146     }
147 
148     if (result == nullptr) {
149         delete info;
150         return nullptr;
151     }
152 
153     if (!NAPICall(env, napi_create_async_work(env, nullptr, resourceName, AsyncFunc<ParamT>,
154         CompleteFunc<ParamT>, reinterpret_cast<void *>(info), &info->asyncWork))) {
155         delete info;
156         return nullptr;
157     }
158     if (!NAPICall(env, napi_queue_async_work(env, info->asyncWork))) {
159         delete info;
160         return nullptr;
161     }
162 
163     return result;
164 };
165 } // namespace OHOS
166 
167 #endif // INTERFACES_KITS_NAPI_GRAPHIC_COMMON_COMMON_H
168