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 "hilog/log.h"
17 #include "napi/native_api.h"
18 #include <chrono>
19 #include <string>
20 #include "common/native_common.h"
21 #include "web/native_interface_arkweb.h"
22 #include "web/arkweb_interface.h"
23 #include "jsbridgeObject.h"
24 #include <thread>
25
26
27 constexpr unsigned int LOG_PRINT_DOMAIN = 0xFF00;
28 ArkWeb_ControllerAPI *controller = nullptr;
29 ArkWeb_JavaScriptValueAPI *javaScriptValueApi = nullptr;
30 std::shared_ptr<JSBridgeObject> jsbridge_object_ptr = nullptr;
31
32 std::chrono::time_point<std::chrono::high_resolution_clock> start;
33
34 int g_funcOnePid = -1;
35 int g_funcTwoPid = -1;
36
37 std::thread::id g_thisId = std::this_thread::get_id();
38 std::size_t g_hashValueCur = std::hash<std::thread::id>()(g_thisId);
39 int g_mPid = static_cast<int>(g_hashValueCur);
40
GetStringValue(napi_env env,napi_value value)41 char *GetStringValue(napi_env env, napi_value value)
42 {
43 size_t size = 0;
44 napi_get_value_string_utf8(env, value, nullptr, 0, &size);
45 char *paramValue = new (std::nothrow) char[size + 1];
46 size_t paramLength = 0;
47 napi_get_value_string_utf8(env, value, paramValue, size + 1, ¶mLength);
48 return paramValue;
49 }
50
51 // 发送JS脚本到H5侧执行,执行结果的回调
RunJavaScriptCallback(const char * result)52 static void RunJavaScriptCallback(const char *result)
53 {
54 std::chrono::duration<double, std::milli> elapsed_ms = std::chrono::high_resolution_clock::now() - start;
55 }
56
57 // 示例代码 ,注册了1个对象,2个方法
ProxyMethod1(const char ** argv,int argc)58 static char *ProxyMethod1(const char **argv, int argc)
59 {
60 return nullptr;
61 }
62
ProxyMethod2(const char ** argv,int argc)63 static char *ProxyMethod2(const char **argv, int argc)
64 {
65 char *ret = "ygz hello from native ProxyMethod2";
66 return ret;
67 }
68
ProxyMethod3(const char ** argv,int argc)69 static char *ProxyMethod3(const char **argv, int argc)
70 {
71 char *ret = "ygz hello from native ProxyMethod3";
72 return ret;
73 }
74
ValidCallback(const char * webName)75 void ValidCallback(const char *webName)
76 {
77 const char *methodName[2] = {"method1", "method2"};
78 NativeArkWeb_OnJavaScriptProxyCallback callback[2] = {ProxyMethod1, ProxyMethod2};
79 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method1调用此文件下的ProxyMethod1和ProxyMethod2方法了
80 int32_t size = 2;
81 OH_NativeArkWeb_RegisterJavaScriptProxy(webName, "ndkProxy", methodName, callback, size, false);
82 }
83
DestroyCallback(const char * webName)84 void DestroyCallback(const char *webName)
85 {
86 }
87
NativeWebInit(napi_env env,napi_callback_info info)88 static napi_value NativeWebInit(napi_env env, napi_callback_info info)
89 {
90 size_t argc = 1;
91 napi_value args[1] = {nullptr};
92 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
93 // 获取第一个参数 webName
94 size_t webNameSize = 0;
95 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webNameSize);
96 char *webNameValue = new (std::nothrow) char[webNameSize + 1];
97 size_t webNameLength = 0;
98 napi_get_value_string_utf8(env, args[0], webNameValue, webNameSize + 1, &webNameLength);
99
100 // 注js proxy册回调函数
101 NativeArkWeb_OnValidCallback ptr = ValidCallback;
102 OH_NativeArkWeb_SetJavaScriptProxyValidCallback(webNameValue, ptr);
103 OH_NativeArkWeb_GetJavaScriptProxyValidCallback(webNameValue);
104 // 注册destroy回调函数
105 OH_NativeArkWeb_SetDestroyCallback(webNameValue, DestroyCallback);
106 OH_NativeArkWeb_GetDestroyCallback(webNameValue);
107 napi_value output;
108 NAPI_CALL(env, napi_create_string_utf8(env, "RunSuccess", NAPI_AUTO_LENGTH, &output));
109 return output;
110 }
111
112 // 发送JS脚本到H5侧执行
RunJavaScript(napi_env env,napi_callback_info info)113 static napi_value RunJavaScript(napi_env env, napi_callback_info info)
114 {
115 size_t argc = 2;
116 napi_value args[2] = {nullptr};
117 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
118
119 // 获取第一个参数 webName
120 size_t webNameSize = 0;
121 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webNameSize);
122 char *webNameValue = new (std::nothrow) char[webNameSize + 1];
123 size_t webNameLength = 0;
124 napi_get_value_string_utf8(env, args[0], webNameValue, webNameSize + 1, &webNameLength);
125
126 // 获取第二个参数 jsCode
127 size_t bufferSize = 0;
128 napi_get_value_string_utf8(env, args[1], nullptr, 0, &bufferSize);
129 char *jsCode = new (std::nothrow) char[bufferSize + 1];
130 size_t byteLength = 0;
131 napi_get_value_string_utf8(env, args[1], jsCode, bufferSize + 1, &byteLength);
132 start = std::chrono::high_resolution_clock::now();
133
134 // 调用ndk接口
135 OH_NativeArkWeb_RunJavaScript(webNameValue, jsCode, RunJavaScriptCallback);
136 napi_value output;
137 NAPI_CALL(env, napi_create_string_utf8(env, "RunSuccess", NAPI_AUTO_LENGTH, &output));
138 return output;
139 }
140
RegisterJavaScriptProxy(napi_env env,napi_callback_info info)141 static napi_value RegisterJavaScriptProxy(napi_env env, napi_callback_info info)
142 {
143 size_t argc = 1;
144 napi_value args[1] = {nullptr};
145 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
146 // 获取第一个参数 webName
147 size_t webNameSize = 0;
148 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webNameSize);
149 char *webNameValue = new (std::nothrow) char[webNameSize + 1];
150 size_t webNameLength = 0;
151 napi_get_value_string_utf8(env, args[0], webNameValue, webNameSize + 1, &webNameLength);
152 const char *methodName[3] = {"method1", "method2", "method3"};
153 NativeArkWeb_OnJavaScriptProxyCallback callback[3] = {ProxyMethod1, ProxyMethod2, ProxyMethod3};
154 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method1调用此文件下的ProxyMethod1和ProxyMethod2方法了
155 int32_t size = 3;
156 OH_NativeArkWeb_RegisterJavaScriptProxy(webNameValue, "ndkProxy", methodName, callback, size, false);
157 napi_value output;
158 NAPI_CALL(env, napi_create_string_utf8(env, "RunSuccess", NAPI_AUTO_LENGTH, &output));
159 return output;
160 }
161
UnregisterJavaScriptProxy(napi_env env,napi_callback_info info)162 static napi_value UnregisterJavaScriptProxy(napi_env env, napi_callback_info info)
163 {
164 size_t argc = 1;
165 napi_value args[1] = {nullptr};
166 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
167 // 获取第一个参数 webName
168 size_t webNameSize = 0;
169 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webNameSize);
170 char *webNameValue = new (std::nothrow) char[webNameSize + 1];
171 size_t webNameLength = 0;
172 napi_get_value_string_utf8(env, args[0], webNameValue, webNameSize + 1, &webNameLength);
173 NativeArkWeb_OnJavaScriptProxyCallback callback[3] = {ProxyMethod1, ProxyMethod2, ProxyMethod3};
174 // 如此注册的情况下,在H5页面就可以使用proxy.method1、proxy.method1调用此文件下的ProxyMethod1和ProxyMethod2方法了
175 OH_NativeArkWeb_UnregisterJavaScriptProxy(webNameValue, "ndkProxy");
176 napi_value output;
177 NAPI_CALL(env, napi_create_string_utf8(env, "RunSuccess", NAPI_AUTO_LENGTH, &output));
178 return output;
179 }
180
ArkWebProxyMethodOne(const char * webTag,const ArkWeb_JavaScriptBridgeData * dataArray,size_t arraySize,void * userData)181 ArkWeb_JavaScriptValuePtr ArkWebProxyMethodOne(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray,
182 size_t arraySize, void *userData)
183 {
184 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb",
185 "ArkWebProxyMethodOne webTag:%{public}s userData:%{public}s",
186 webTag,
187 (char *)userData);
188 std::size_t hashValue = std::hash<std::thread::id>()(std::this_thread::get_id());
189 g_funcOnePid = static_cast<int>(hashValue);
190 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb",
191 "ArkWebProxyMethodOne PID:%{public}d, Fid:%{public}d",
192 g_mPid,
193 g_funcOnePid);
194 jsbridge_object_ptr->ProxyMethod(dataArray, arraySize);
195 std::string str = std::string((char *)userData);
196 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_STRING,
197 (void *)str.c_str(),
198 str.length() + 1);
199 }
200
ArkWebProxyMethodTwo(const char * webTag,const ArkWeb_JavaScriptBridgeData * dataArray,size_t arraySize,void * userData)201 ArkWeb_JavaScriptValuePtr ArkWebProxyMethodTwo(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray,
202 size_t arraySize, void *userData)
203 {
204 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb",
205 "ArkWebProxyMethodTwo webTag:%{public}s userData:%{public}s",
206 webTag,
207 (char *)userData);
208 std::size_t hashValue = std::hash<std::thread::id>()(std::this_thread::get_id());
209 g_funcTwoPid = static_cast<int>(hashValue);
210 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb",
211 "ArkWebProxyMethodTwo PID:%{public}d, Fid:%{public}d",
212 g_mPid,
213 g_funcTwoPid);
214 jsbridge_object_ptr->ProxyMethod(dataArray, arraySize);
215 bool boolValue = true;
216 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_BOOL,
217 (void *)(&boolValue),
218 1);
219 }
220
ArkWebProxyMethodThree(const char * webTag,const ArkWeb_JavaScriptBridgeData * dataArray,size_t arraySize,void * userData)221 ArkWeb_JavaScriptValuePtr ArkWebProxyMethodThree(const char *webTag, const ArkWeb_JavaScriptBridgeData *dataArray,
222 size_t arraySize, void *userData)
223 {
224 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb",
225 "ArkWebProxyMethodThree webTag:%{public}s userData:%{public}s",
226 webTag,
227 (char *)userData);
228 jsbridge_object_ptr->ProxyMethod(dataArray, arraySize);
229 return javaScriptValueApi->createJavaScriptValue(ArkWeb_JavaScriptValueType::ARKWEB_JAVASCRIPT_NONE,
230 (void *)nullptr,
231 1);
232 }
233
GetProxyObjectWithResult(napi_env env,napi_value args[])234 ArkWeb_ProxyObjectWithResult GetProxyObjectWithResult(napi_env env, napi_value args[])
235 {
236 ArkWeb_ProxyMethodWithResult *methodList = new ArkWeb_ProxyMethodWithResult[3];
237 const char *userDataOne = "method1";
238 const char *userDataTwo = "method2";
239 const char *userDataThree = "method3";
240 const int indexOne = 0;
241 const int indexTwo = 1;
242 const int indexThree = 2;
243 methodList[indexOne] = {"method1", ArkWebProxyMethodOne, (void *)userDataOne};
244 methodList[indexTwo] = {"method2", ArkWebProxyMethodTwo, (void *)userDataTwo};
245 methodList[indexThree] = {"method3", ArkWebProxyMethodThree, (void *)userDataThree};
246
247 int32_t size = 3;
248 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "AsyncRegister", "methodSize:%{public}d", size);
249 ArkWeb_ProxyObjectWithResult proxyObject = {"ndkProxy", methodList, (size_t)size};
250 return proxyObject;
251 }
252
253
254
NativeWebInitTwo(napi_env env,napi_callback_info info)255 static napi_value NativeWebInitTwo(napi_env env, napi_callback_info info)
256 {
257 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "NativeWebInitTwo start");
258 size_t argc = 1;
259 napi_value args[1] = {nullptr};
260 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
261 // 获取第一个参数 webName
262 size_t webTagSize = 0;
263 napi_get_value_string_utf8(env, args[0], nullptr, 0, &webTagSize);
264 char *webTagValue = new (std::nothrow) char[webTagSize + 1];
265 size_t webTagLength = 0;
266 napi_get_value_string_utf8(env, args[0], webTagValue, webTagSize + 1, &webTagLength);
267 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb",
268 "NativeWebInitTwo webTag:%{public}s",
269 webTagValue);
270
271 jsbridge_object_ptr = std::make_shared<JSBridgeObject>(webTagValue);
272 if (jsbridge_object_ptr) {
273 jsbridge_object_ptr->Init();
274 }
275
276 controller = reinterpret_cast<ArkWeb_ControllerAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_CONTROLLER));
277 javaScriptValueApi =
278 reinterpret_cast<ArkWeb_JavaScriptValueAPI *>(OH_ArkWeb_GetNativeAPI(ARKWEB_NATIVE_JAVASCRIPT_VALUE));
279 if (javaScriptValueApi) {
280 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "ArkWeb_JavaScriptValueAPI success");
281 }
282
283 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "NativeWebInitTwo end");
284
285 napi_value output;
286 NAPI_CALL(env, napi_create_string_utf8(env, "RunSuccess", NAPI_AUTO_LENGTH, &output));
287 return output;
288 }
289
RegisterAsyncThreadJavaScriptProxy(napi_env env,napi_callback_info info)290 static napi_value RegisterAsyncThreadJavaScriptProxy(napi_env env, napi_callback_info info)
291 {
292 size_t argc = 2;
293 napi_value args[2] = {nullptr};
294 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
295
296 char *webTagValue = GetStringValue(env, args[0]);
297 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "AsyncRegister",
298 "RegisterAsyncThreadJavaScriptProxy webTag:%{public}s",
299 webTagValue);
300
301 char *permission = GetStringValue(env, args[1]);
302 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "AsyncRegister",
303 "RegisterAsyncThreadJavaScriptProxy permissionStr:%{public}s",
304 permission);
305
306 if (strcmp(permission, "null") == 0) {
307 permission = nullptr;
308 }
309 if (strcmp(webTagValue, "null") == 0) {
310 webTagValue = nullptr;
311 }
312
313 ArkWeb_ProxyObjectWithResult proxyObjectWithResult = GetProxyObjectWithResult(env, args);
314 OH_NativeArkWeb_RegisterAsyncThreadJavaScriptProxy(webTagValue, &proxyObjectWithResult, permission);
315 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "AsyncRegister",
316 "RegisterAsyncThreadJavaScriptProxy success");
317
318 napi_value output;
319 NAPI_CALL(env, napi_create_string_utf8(env, "RunSuccess", NAPI_AUTO_LENGTH, &output));
320 return output;
321 }
322
GetPidResult(napi_env env,napi_callback_info info)323 static napi_value GetPidResult(napi_env env, napi_callback_info info)
324 {
325 napi_value result;
326 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "GetPidResult g_mPid:%{public}d", g_mPid);
327 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "GetPidResult funcOnePid:%{public}d", g_funcOnePid);
328 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "ArkWeb", "GetPidResult funcTwoPid:%{public}d", g_funcTwoPid);
329 int32_t testResult = 0;
330 if (g_mPid != g_funcOnePid && g_mPid != g_funcTwoPid && g_funcOnePid == g_funcTwoPid) {
331 testResult = 1;
332 }
333 napi_create_int32(env, testResult, &result);
334 return result;
335 }
336
337
338
339 EXTERN_C_START
Init(napi_env env,napi_value exports)340 static napi_value Init(napi_env env, napi_value exports)
341 {
342 napi_property_descriptor desc[] = {
343 {"nativeWebInit", nullptr, NativeWebInit, nullptr, nullptr, nullptr, napi_default, nullptr},
344 {"runJavaScript", nullptr, RunJavaScript, nullptr, nullptr, nullptr, napi_default, nullptr},
345 {"registerJavaScriptProxy", nullptr, RegisterJavaScriptProxy, nullptr, nullptr, nullptr, napi_default, nullptr},
346 {"unregisterJavaScriptProxy", nullptr, UnregisterJavaScriptProxy, nullptr, nullptr, nullptr, napi_default, nullptr},
347 {"nativeWebInitTwo", nullptr, NativeWebInitTwo, nullptr, nullptr, nullptr, napi_default, nullptr},
348 {"registerAsyncThreadJavaScriptProxy", nullptr, RegisterAsyncThreadJavaScriptProxy, nullptr, nullptr, nullptr,
349 napi_default,
350 nullptr},
351 {"getPidResult", nullptr, GetPidResult, nullptr, nullptr, nullptr, napi_default, nullptr},
352 };
353 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
354 return exports;
355 }
356 EXTERN_C_END
357
358 static napi_module demoModule = {
359 .nm_version = 1,
360 .nm_flags = 0,
361 .nm_filename = nullptr,
362 .nm_register_func = Init,
363 .nm_modname = "entry",
364 .nm_priv = ((void *)0),
365 .reserved = {0},
366 };
367
RegisterEntryModule(void)368 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
369 {
370 napi_module_register(&demoModule);
371 }