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 "node_api.h"
17 #include "ark_native_engine.h"
18 #include "ark_interop_log.h"
19 #include "cj_envsetup.h"
20 
ParseLoadParams(napi_env env,napi_callback_info info,char * nameBuf,size_t & size)21 static bool ParseLoadParams(napi_env env, napi_callback_info info, char* nameBuf, size_t& size)
22 {
23     napi_value libNameValue;
24     size_t argCount = 1;
25     auto status = napi_get_cb_info(env, info, &argCount, &libNameValue, nullptr, nullptr);
26     if (status != napi_ok) {
27         napi_throw_error(env, "napi call fail", "napi_get_cb_info failed");
28         return false;
29     }
30 
31     if (argCount != 1) {
32         napi_throw_error(env, "argument invalid", "need one argument");
33         return false;
34     }
35 
36     napi_valuetype valuetype;
37     status = napi_typeof(env, libNameValue, &valuetype);
38     if (status != napi_ok) {
39         napi_throw_error(env, "napi call fail", "napi_typeof failed");
40         return false;
41     }
42     if (valuetype != napi_string) {
43         napi_throw_error(env, "argument invalid", "need a string");
44         return false;
45     }
46 
47     status = napi_get_value_string_utf8(env, libNameValue, nameBuf, size, &size);
48     if (status != napi_ok) {
49         napi_throw_error(env, "argument invalid", "napi_get_value_string_utf8 not ok");
50         return false;
51     }
52     return true;
53 }
54 
LoadArkCJModule(napi_env env,const char * libName,napi_value * result)55 static bool LoadArkCJModule(napi_env env, const char* libName, napi_value* result)
56 {
57     auto engine = reinterpret_cast<ArkNativeEngine*>(env);
58     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
59     do {
60         const char* targetName;
61         const char* loaderName = "ARKTS_LoadModule";
62 #ifdef __OHOS__
63         targetName = "libark_interop.z.so";
64 #elif defined(__WINDOWS__)
65         targetName = "libark_interop.dll";
66 #elif defined(__LINUX__)
67         targetName = "libark_interop.so";
68 #endif
69         auto runtime = OHOS::CJEnv::LoadInstance();
70         auto handle = runtime->loadLibrary(0, targetName);
71         if (!handle) {
72             LOGE("open '%{public}s' failed", targetName);
73             return false;
74         }
75         auto symbol = runtime->getSymbol(handle, loaderName);
76         if (!symbol) {
77             LOGE("no symbol of '%{public}s'", loaderName);
78             return false;
79         }
80         auto loader = reinterpret_cast<napi_value(*)(EcmaVM*, const char*)>(symbol);
81         *result = loader(vm, libName);
82     } while (false);
83     return true;
84 }
85 
LoadCJModule(napi_env env,napi_callback_info info)86 static napi_value LoadCJModule(napi_env env, napi_callback_info info)
87 {
88     napi_value result;
89     if (napi_get_undefined(env, &result) != napi_ok) {
90         return result;
91     }
92     constexpr size_t BUF_SIZE = 256;
93     char nameBuf[BUF_SIZE];
94     size_t realSize = BUF_SIZE;
95     if (!ParseLoadParams(env, info, nameBuf, realSize)) {
96         return result;
97     }
98     auto runtime = OHOS::CJEnv::LoadInstance();
99     runtime->initCJChipSDKNS("/system/lib64/chipset-pub-sdk");
100     runtime->initCJAppNS("/data/storage/el1/bundle/libs/arm64");
101     runtime->initCJSDKNS("/data/storage/el1/bundle/libs/arm64/ohos:"
102                                  "/data/storage/el1/bundle/libs/arm64/runtime");
103     runtime->initCJSysNS("/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk");
104     if (!runtime->startRuntime()) {
105         LOGE("start cjruntime failed");
106         return result;
107     }
108     if (!runtime->startUIScheduler()) {
109         LOGE("start cj ui context failed");
110         return result;
111     }
112 
113     LoadArkCJModule(env, nameBuf, &result);
114     return result;
115 }
116 
ExportLoadCJModule(napi_env env,napi_value exports)117 static napi_value ExportLoadCJModule(napi_env env, napi_value exports)
118 {
119     static napi_property_descriptor desc[] = {
120         {"requireCJLib", nullptr, LoadCJModule, nullptr, nullptr, nullptr, napi_default, nullptr}
121     };
122     napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc);
123     return exports;
124 }
125 
LoadCJModuleRegister()126 extern "C" __attribute__((constructor)) void LoadCJModuleRegister()
127 {
128     static napi_module callbackModule = {
129         .nm_version = 1,
130         .nm_flags = 0,
131         .nm_filename = nullptr,
132         .nm_register_func = ExportLoadCJModule,
133         .nm_modname = "ark_interop_loader",
134         .nm_priv = nullptr,
135         .reserved = { 0 },
136     };
137     napi_module_register(&callbackModule);
138 }
139