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 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_group_js_bridge.h"
17
18 #include "base/json/json_util.h"
19 #include "base/log/event_report.h"
20 #include "base/log/log.h"
21 #include "base/memory/ace_type.h"
22 #include "frameworks/bridge/codec/function_call.h"
23 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
24 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
25
26 namespace OHOS::Ace::Framework {
27 namespace {
28
29 const int32_t PLUGIN_REQUEST_MIN_ARGC_NUM = 4;
30 const int32_t PLUGIN_REQUEST_ARG_RESOLVE_INDEX = 0;
31 const int32_t PLUGIN_REQUEST_ARG_REJECT_INDEX = 1;
32 const int32_t PLUGIN_REQUEST_ARG_GROUP_NAME_INDEX = 2;
33 const int32_t PLUGIN_REQUEST_ARG_FUNCTION_NAME_INDEX = 3;
34 const int32_t PLUGIN_REQUEST_ARG_APP_PARAMS_INDEX = 4;
35
36 const int32_t PLUGIN_REQUEST_MIN_ARGC_NUM_SYNC = 2;
37 const int32_t PLUGIN_REQUEST_ARG_GROUP_NAME_INDEX_SYNC = 0;
38 const int32_t PLUGIN_REQUEST_ARG_FUNCTION_NAME_INDEX_SYNC = 1;
39 const int32_t PLUGIN_REQUEST_ARG_APP_PARAMS_INDEX_SYNC = 2;
40
41 } // namespace
42
InitializeGroupJsBridge(const shared_ptr<JsRuntime> & runtime)43 int32_t JsiDeclarativeGroupJsBridge::InitializeGroupJsBridge(const shared_ptr<JsRuntime>& runtime)
44 {
45 LOGD("Enter InitializeGroupJsBridge");
46 if (!runtime) {
47 LOGE("group module init, context is null");
48 EventReport::SendAPIChannelException(APIChannelExcepType::JS_BRIDGE_INIT_ERR);
49 return JS_CALL_FAIL;
50 }
51 runtime_ = runtime;
52
53 if (LoadJsBridgeFunction() != JS_CALL_SUCCESS) {
54 LOGE("group module init, load bridge function failed!");
55 EventReport::SendAPIChannelException(APIChannelExcepType::JS_BRIDGE_INIT_ERR);
56 return JS_CALL_FAIL;
57 }
58
59 eventCallBackFuncs_.clear();
60 moduleCallBackFuncs_.clear();
61 pendingCallbackId_ = 1;
62
63 return JS_CALL_SUCCESS;
64 }
65
LoadJsBridgeFunction()66 int32_t JsiDeclarativeGroupJsBridge::LoadJsBridgeFunction()
67 {
68 shared_ptr<JsValue> group = runtime_->NewObject();
69 bool succ = group->SetProperty(runtime_, "sendGroupMessage", runtime_->NewFunction(ProcessJsRequest));
70 if (!succ) {
71 LOGE("bridge function, set sendGroupMessage sending function mapping failed!");
72 EventReport::SendAPIChannelException(APIChannelExcepType::SET_FUNCTION_ERR);
73 return JS_CALL_FAIL;
74 }
75 succ = group->SetProperty(runtime_, "sendGroupMessageSync", runtime_->NewFunction(ProcessJsRequestSync));
76 if (!succ) {
77 LOGE("bridge function, set sendGroupMessageSync sending function mapping failed!");
78 EventReport::SendAPIChannelException(APIChannelExcepType::SET_FUNCTION_ERR);
79 return JS_CALL_FAIL;
80 }
81 succ = runtime_->GetGlobal()->SetProperty(runtime_, "group", group);
82 if (!succ) {
83 LOGE("bridge function, set root node failed!");
84 EventReport::SendAPIChannelException(APIChannelExcepType::SET_FUNCTION_ERR);
85 return JS_CALL_FAIL;
86 }
87 return JS_CALL_SUCCESS;
88 }
89
90 // function callback for groupObj's function: sendGroupMessage
ProcessJsRequest(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)91 shared_ptr<JsValue> JsiDeclarativeGroupJsBridge::ProcessJsRequest(const shared_ptr<JsRuntime>& runtime,
92 const shared_ptr<JsValue>& thisObj, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
93 {
94 shared_ptr<JsValue> res = runtime->NewUndefined();
95 auto engine = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
96 if (engine == nullptr) {
97 LOGE("send message para check, fail to get engine");
98 return res;
99 }
100 auto delegate = engine->GetDelegate();
101 if (!delegate) {
102 LOGE("send message para check, fail to get front-end delegate");
103 return res;
104 }
105
106 auto groupJsBridge = AceType::DynamicCast<JsiDeclarativeGroupJsBridge>(delegate->GetGroupJsBridge());
107 if (!groupJsBridge) {
108 LOGE("send message para check, fail to get group-js-bridge");
109 return res;
110 }
111
112 // Should have at least 4 parameters
113 if (argv.size() < PLUGIN_REQUEST_MIN_ARGC_NUM) {
114 LOGE("send message para check, invalid args number:%{public}u", (uint32_t)argv.size());
115 return res;
116 }
117
118 std::string strGroupName(argv[PLUGIN_REQUEST_ARG_GROUP_NAME_INDEX]->ToString(runtime));
119 std::string strFunctionName(argv[PLUGIN_REQUEST_ARG_FUNCTION_NAME_INDEX]->ToString(runtime));
120 if (strGroupName.empty()) {
121 LOGE("send message para check, group or function name is null");
122 return res;
123 }
124 int32_t callbackId = groupJsBridge->GetPendingCallbackIdAndIncrement();
125 // the third and fourth parameters are resolve and reject callback function
126 if (!groupJsBridge->SetModuleGroupCallbackFuncs(argv,
127 PLUGIN_REQUEST_ARG_RESOLVE_INDEX, PLUGIN_REQUEST_ARG_REJECT_INDEX, callbackId)) {
128 LOGE("send message, set module callback function failed!");
129 return res;
130 }
131
132 if (strGroupName.empty()) {
133 groupJsBridge->TriggerModulePluginGetErrorCallback(
134 callbackId, PLUGIN_REQUEST_FAIL, "plugin name can't be null");
135 LOGE("plugin name is null");
136 return res;
137 }
138
139 LOGI("send message, groupName:%{private}s functionName:%{private}s callbackId:%{private}d", strGroupName.c_str(),
140 strFunctionName.c_str(), callbackId);
141
142 std::vector<CodecData> arguments;
143 ParseJsDataResult parseJsResult =
144 groupJsBridge->ParseJsPara(runtime, argv, PLUGIN_REQUEST_ARG_APP_PARAMS_INDEX, callbackId, arguments);
145 if (parseJsResult != ParseJsDataResult::PARSE_JS_SUCCESS) {
146 ProcessParseJsError(parseJsResult, runtime, callbackId);
147 return res;
148 }
149
150 FunctionCall functionCall(strFunctionName, arguments);
151 StandardFunctionCodec codec;
152 std::vector<uint8_t> encodeBuf;
153 if (!codec.EncodeFunctionCall(functionCall, encodeBuf)) {
154 groupJsBridge->TriggerModulePluginGetErrorCallback(
155 callbackId, PLUGIN_REQUEST_FAIL, "encode request message failed");
156 return res;
157 }
158
159 // CallPlatformFunction
160 auto dispatcher = engine->GetJsMessageDispatcher().Upgrade();
161 if (dispatcher) {
162 dispatcher->Dispatch(strGroupName, std::move(encodeBuf), callbackId);
163 } else {
164 LOGW("Dispatcher Upgrade fail when dispatch request message to platform");
165 groupJsBridge->TriggerModulePluginGetErrorCallback(callbackId, PLUGIN_REQUEST_FAIL, "send message failed");
166 }
167 return res;
168 }
169
170 // function callback for groupObj's function: sendGroupMessageSync
ProcessJsRequestSync(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)171 shared_ptr<JsValue> JsiDeclarativeGroupJsBridge::ProcessJsRequestSync(const shared_ptr<JsRuntime>& runtime,
172 const shared_ptr<JsValue>& thisObj, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
173 {
174 shared_ptr<JsValue> res = runtime->NewUndefined();
175 auto engine = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
176 if (engine == nullptr) {
177 LOGE("send message para check, fail to get engine");
178 return res;
179 }
180 auto delegate = engine->GetDelegate();
181 if (!delegate) {
182 LOGE("send message para check, fail to get front-end delegate");
183 return res;
184 }
185
186 auto groupJsBridge = AceType::DynamicCast<JsiDeclarativeGroupJsBridge>(delegate->GetGroupJsBridge());
187 if (!groupJsBridge) {
188 LOGE("send message para check, fail to get group-js-bridge");
189 return res;
190 }
191
192 // Should have at least 2 parameters
193 if (argv.size() < PLUGIN_REQUEST_MIN_ARGC_NUM_SYNC) {
194 LOGE("send message para check, invalid args number:%{public}u", (uint32_t)argv.size());
195 return res;
196 }
197
198 std::string strGroupName(argv[PLUGIN_REQUEST_ARG_GROUP_NAME_INDEX_SYNC]->ToString(runtime));
199 std::string strFunctionName(argv[PLUGIN_REQUEST_ARG_FUNCTION_NAME_INDEX_SYNC]->ToString(runtime));
200 if (strGroupName.empty()) {
201 LOGE("send message para check, group or function name is null");
202 return res;
203 }
204
205 if (strGroupName.empty()) {
206 LOGE("plugin name is null");
207 return res;
208 }
209
210 LOGI("send message, groupName:%{private}s functionName:%{private}s", strGroupName.c_str(), strFunctionName.c_str());
211
212 std::vector<CodecData> arguments;
213 ParseJsDataResult parseJsResult =
214 groupJsBridge->ParseJsPara(runtime, argv, PLUGIN_REQUEST_ARG_APP_PARAMS_INDEX_SYNC, 0, arguments);
215 if (parseJsResult != ParseJsDataResult::PARSE_JS_SUCCESS) {
216 LOGE("encode arguments fail");
217 return res;
218 }
219
220 FunctionCall functionCall(strFunctionName, arguments);
221 StandardFunctionCodec codec;
222 std::vector<uint8_t> encodeBuf;
223 if (!codec.EncodeFunctionCall(functionCall, encodeBuf)) {
224 LOGE("encode request message failed");
225 return res;
226 }
227
228 // CallPlatformFunction
229 auto dispatcher = engine->GetJsMessageDispatcher().Upgrade();
230
231 uint8_t* resData = nullptr;
232 int64_t position = 0;
233 if (dispatcher) {
234 dispatcher->DispatchSync(strGroupName, std::move(encodeBuf), &resData, position);
235 } else {
236 LOGW("Dispatcher Upgrade fail when dispatch request message to platform");
237 return res;
238 }
239 std::vector<uint8_t> messageData = std::vector<uint8_t>(resData, resData + position);
240
241 shared_ptr<JsValue> callBackResult;
242 CodecData codecResult;
243 if (codec.DecodePlatformMessage(messageData, codecResult)) {
244 std::string resultString = codecResult.GetStringValue();
245 LOGI("sync resultString = %{private}s", resultString.c_str());
246 if (resultString.empty()) {
247 callBackResult = runtime->NewNull();
248 } else {
249 callBackResult = runtime->NewString(resultString);
250 }
251 }
252 return callBackResult;
253 }
254
SetEventGroupCallBackFuncs(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & localEventCallbackFunc,int32_t callbackId,int32_t requestId)255 bool JsiDeclarativeGroupJsBridge::SetEventGroupCallBackFuncs(const shared_ptr<JsRuntime>& runtime,
256 const shared_ptr<JsValue>& localEventCallbackFunc, int32_t callbackId, int32_t requestId)
257 {
258 if (localEventCallbackFunc->IsNull(runtime) || !localEventCallbackFunc->IsFunction(runtime)) {
259 LOGE("callback function is invalid!");
260 return false;
261 }
262
263 LOGI("record event callback, requestId:%{private}d, callbackId:%{private}d", requestId, callbackId);
264 auto result = eventCallBackFuncs_.try_emplace(callbackId, localEventCallbackFunc);
265 if (!result.second) {
266 result.first->second = localEventCallbackFunc;
267 }
268 AddRequestIdCallbackIdRelation(callbackId, requestId);
269 return true;
270 }
271
RemoveEventGroupCallBackFuncs(int32_t callbackId)272 void JsiDeclarativeGroupJsBridge::RemoveEventGroupCallBackFuncs(int32_t callbackId)
273 {
274 LOGI("remove event callback, callbackId:%{private}d", callbackId);
275 auto itFunc = eventCallBackFuncs_.find(callbackId);
276 if (itFunc != eventCallBackFuncs_.end()) {
277 eventCallBackFuncs_.erase(callbackId);
278 }
279 }
280
AddRequestIdCallbackIdRelation(int32_t eventId,int32_t requestId)281 void JsiDeclarativeGroupJsBridge::AddRequestIdCallbackIdRelation(int32_t eventId, int32_t requestId)
282 {
283 auto result = requestIdCallbackIdMap_.try_emplace(requestId, eventId);
284 if (!result.second) {
285 result.first->second = eventId;
286 }
287 }
288
RemoveRequestIdCallbackIdRelation(int32_t requestId,bool removeEventCallback)289 void JsiDeclarativeGroupJsBridge::RemoveRequestIdCallbackIdRelation(int32_t requestId, bool removeEventCallback)
290 {
291 auto eventId = requestIdCallbackIdMap_.find(requestId);
292 if (eventId != requestIdCallbackIdMap_.end()) {
293 if (removeEventCallback) {
294 RemoveEventGroupCallBackFuncs(eventId->second);
295 }
296 requestIdCallbackIdMap_.erase(requestId);
297 }
298 }
299
ProcessParseJsError(ParseJsDataResult errorType,const shared_ptr<JsRuntime> & runtime,int32_t callbackId)300 void JsiDeclarativeGroupJsBridge::ProcessParseJsError(
301 ParseJsDataResult errorType, const shared_ptr<JsRuntime>& runtime, int32_t callbackId)
302 {
303 auto engine = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
304 if (engine == nullptr) {
305 LOGE("Process parse js error check, fail to get engine");
306 return;
307 }
308 // PluginErrorCallback
309 auto dispatcher = engine->GetJsMessageDispatcher().Upgrade();
310 if (!dispatcher) {
311 LOGW("Dispatcher Upgrade fail at ProcessParseJsError");
312 return;
313 }
314 std::string errMessage;
315 switch (errorType) {
316 case ParseJsDataResult::PARSE_JS_ERR_UNSUPPORTED_TYPE:
317 errMessage = "unsupported js parameter types";
318 dispatcher->DispatchPluginError(callbackId,
319 static_cast<int32_t>(ParseJsDataResult::PARSE_JS_ERR_UNSUPPORTED_TYPE), std::move(errMessage));
320 break;
321 case ParseJsDataResult::PARSE_JS_ERR_TOO_MANY_PARAM:
322 errMessage = "the number of parameters exceeds 255";
323 dispatcher->DispatchPluginError(callbackId,
324 static_cast<int32_t>(ParseJsDataResult::PARSE_JS_ERR_TOO_MANY_PARAM), std::move(errMessage));
325 break;
326 default:
327 break;
328 }
329 }
330
SetModuleGroupCallbackFuncs(const std::vector<shared_ptr<JsValue>> & argv,int32_t resolveCallbackIndex,int32_t rejectCallbackIndex,int32_t callbackId)331 bool JsiDeclarativeGroupJsBridge::SetModuleGroupCallbackFuncs(const std::vector<shared_ptr<JsValue>>& argv,
332 int32_t resolveCallbackIndex, int32_t rejectCallbackIndex, int32_t callbackId)
333 {
334 LOGD("Enter SetModuleGroupCallbackFuncs");
335 if (argv[resolveCallbackIndex]->IsNull(runtime_) || !argv[resolveCallbackIndex]->IsFunction(runtime_) ||
336 argv[rejectCallbackIndex]->IsNull(runtime_) || !argv[rejectCallbackIndex]->IsFunction(runtime_)) {
337 LOGE("resolve or reject callback function is invalid");
338 return false;
339 }
340
341 PromiseCallback promiseCallJsFunc;
342
343 promiseCallJsFunc.resolveCallback = argv[resolveCallbackIndex];
344 promiseCallJsFunc.rejectCallback = argv[rejectCallbackIndex];
345
346 auto result = moduleCallBackFuncs_.try_emplace(callbackId, promiseCallJsFunc);
347 if (!result.second) {
348 LOGE("module callback function has been existed!");
349 return false;
350 }
351 return true;
352 }
353
SerializationObjectToString(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & val)354 std::string JsiDeclarativeGroupJsBridge::SerializationObjectToString(
355 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& val)
356 {
357 shared_ptr<JsValue> global = runtime->GetGlobal();
358 if (!global->IsObject(runtime)) {
359 LOGE("SerializationObjectToString error: fail to get Global Object");
360 return "";
361 }
362 shared_ptr<JsValue> json = global->GetProperty(runtime, "JSON");
363 if (!json->IsObject(runtime)) {
364 LOGE("SerializationObjectToString error: global has no attribute JsON");
365 return "";
366 }
367 shared_ptr<JsValue> jsFunc = json->GetProperty(runtime, "stringify");
368 if (!jsFunc->IsFunction(runtime)) {
369 LOGE("SerializationObjectToString error: JSON has no attribute stringify");
370 return "";
371 }
372 shared_ptr<JsValue> strValue = jsFunc->Call(runtime, runtime->NewUndefined(), { val }, 1);
373 if (strValue->IsUndefined(runtime)) {
374 LOGE("SerializationObjectToString error: js call error.");
375 return "";
376 }
377 return strValue->ToString(runtime);
378 }
379
ParseJsPara(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv,int32_t beginIndex,int32_t requestId,std::vector<CodecData> & arguments)380 ParseJsDataResult JsiDeclarativeGroupJsBridge::ParseJsPara(const shared_ptr<JsRuntime>& runtime,
381 const std::vector<shared_ptr<JsValue>>& argv, int32_t beginIndex, int32_t requestId,
382 std::vector<CodecData>& arguments)
383 {
384 int32_t argc = (int32_t)argv.size();
385 if (argc < beginIndex) { // no others params
386 return ParseJsDataResult::PARSE_JS_SUCCESS;
387 }
388 for (int32_t i = beginIndex; i < argc; i++) {
389 shared_ptr<JsValue> val = argv[i];
390 if (val->IsString(runtime)) {
391 CodecData arg(val->ToString(runtime));
392 arguments.push_back(arg);
393 } else if (val->IsNumber(runtime)) {
394 if (val->WithinInt32(runtime)) {
395 int32_t valInt = val->ToInt32(runtime);
396 CodecData arg(valInt);
397 arguments.push_back(arg);
398 } else {
399 double valDouble = val->ToDouble(runtime);
400 CodecData arg(valDouble);
401 arguments.push_back(arg);
402 }
403 } else if (val->IsBoolean(runtime)) {
404 bool valBool = val->ToBoolean(runtime);
405 CodecData arg(valBool);
406 arguments.push_back(arg);
407 } else if (val->IsNull(runtime)) {
408 CodecData argNull;
409 arguments.push_back(argNull);
410 } else if (val->IsFunction(runtime)) {
411 int32_t functionId = GetPendingCallbackIdAndIncrement();
412 CodecData arg(functionId, BufferDataType::TYPE_FUNCTION);
413 arguments.push_back(arg);
414 SetEventGroupCallBackFuncs(runtime, val, functionId, requestId);
415 } else if (val->IsArray(runtime) || val->IsObject(runtime)) {
416 std::string objStr = SerializationObjectToString(runtime, val);
417 CodecData arg(objStr);
418 arguments.push_back(arg);
419 } else if (val->IsUndefined(runtime)) {
420 LOGD("Process callNative para type:undefined");
421 } else {
422 LOGE("Process callNative para type: unsupported type");
423 return ParseJsDataResult::PARSE_JS_ERR_UNSUPPORTED_TYPE;
424 }
425 }
426 return ParseJsDataResult::PARSE_JS_SUCCESS;
427 }
428
TriggerModuleJsCallback(int32_t callbackId,int32_t code,std::vector<uint8_t> && messageData)429 void JsiDeclarativeGroupJsBridge::TriggerModuleJsCallback(
430 int32_t callbackId, int32_t code, std::vector<uint8_t>&& messageData)
431 {
432 shared_ptr<JsValue> callBackResult;
433 CodecData codecResult;
434 StandardFunctionCodec codec;
435 if (codec.DecodePlatformMessage(messageData, codecResult)) {
436 std::string resultString = codecResult.GetStringValue();
437 if (resultString.empty()) {
438 callBackResult = runtime_->NewNull();
439 } else {
440 callBackResult = runtime_->NewString(resultString);
441 }
442 } else {
443 LOGE("trigger JS resolve callback function error, decode message fail, callbackId:%{private}d", callbackId);
444 callBackResult = runtime_->NewString("invalid response data");
445 }
446 CallModuleJsCallback(callbackId, code, callBackResult);
447
448 messageData.clear();
449 }
450
CallModuleJsCallback(int32_t callbackId,int32_t code,const shared_ptr<JsValue> & callBackResult)451 void JsiDeclarativeGroupJsBridge::CallModuleJsCallback(
452 int32_t callbackId, int32_t code, const shared_ptr<JsValue>& callBackResult)
453 {
454 RemoveRequestIdCallbackIdRelation(callbackId, code != PLUGIN_REQUEST_SUCCESS);
455
456 shared_ptr<JsValue> global = runtime_->GetGlobal();
457
458 auto itFunc = moduleCallBackFuncs_.find(callbackId);
459 if (itFunc != moduleCallBackFuncs_.end()) {
460 shared_ptr<JsValue> jsFunc =
461 (code == PLUGIN_REQUEST_SUCCESS ? itFunc->second.resolveCallback : itFunc->second.rejectCallback);
462 if (jsFunc->IsNull(runtime_) || !jsFunc->IsFunction(runtime_)) {
463 LOGE("trigger JS result function error, it is not a function, callbackId:%{private}d", callbackId);
464 return;
465 }
466 std::vector<shared_ptr<JsValue>> argv = { callBackResult };
467
468 // Pass only 1 parameter, call promise resolve call back.
469 jsFunc->Call(runtime_, global, argv, 1);
470 itFunc->second.rejectCallback = runtime_->NewUndefined();
471 itFunc->second.resolveCallback = runtime_->NewUndefined();
472 moduleCallBackFuncs_.erase(itFunc);
473 } else {
474 LOGE("trigger JS result function is not exists, callbackId:%{private}d, code:%{private}d", callbackId, code);
475 }
476 }
477
TriggerModulePluginGetErrorCallback(int32_t callbackId,int32_t errorCode,std::string && errorMessage)478 void JsiDeclarativeGroupJsBridge::TriggerModulePluginGetErrorCallback(
479 int32_t callbackId, int32_t errorCode, std::string&& errorMessage)
480 {
481 RemoveRequestIdCallbackIdRelation(callbackId, true);
482 shared_ptr<JsValue> global = runtime_->GetGlobal();
483
484 CodecData codecResult;
485 auto itFunc = moduleCallBackFuncs_.find(callbackId);
486 if (itFunc != moduleCallBackFuncs_.end()) {
487 shared_ptr<JsValue> jsFunc = itFunc->second.rejectCallback;
488 if (jsFunc->IsNull(runtime_) || !jsFunc->IsFunction(runtime_)) {
489 LOGE("trigger Js reject callback function error, reject is not a function, callbackId:%{private}d",
490 callbackId);
491 return;
492 }
493 auto resultJson = JsonUtil::Create(true);
494 resultJson->Put(std::string("code").c_str(), errorCode);
495 resultJson->Put(std::string("data").c_str(), errorMessage.c_str());
496 shared_ptr<JsValue> emptyReplyCallback = runtime_-> NewString(resultJson->ToString().c_str());
497 std::vector<shared_ptr<JsValue>> argv;
498 argv.push_back(emptyReplyCallback);
499 int32_t len = 1;
500 // Pass only 1 parameter, call promise reject call back for error get in plugin.
501 shared_ptr<JsValue> res = jsFunc->Call(runtime_, global, argv, len);
502 if (!res || res->IsUndefined(runtime_)) {
503 LOGW("trigger Js reject callback function fail, callbackId:%{private}d", callbackId);
504 } else {
505 LOGI("trigger Js reject callback function success, callbackId:%{private}d", callbackId);
506 }
507 moduleCallBackFuncs_.erase(itFunc);
508 } else {
509 LOGE("trigger Js reject callback function is not exists, callbackId:%{private}d", callbackId);
510 }
511 }
512
CallEventJsCallback(int32_t callbackId,std::vector<uint8_t> && eventData)513 void JsiDeclarativeGroupJsBridge::CallEventJsCallback(int32_t callbackId, std::vector<uint8_t>&& eventData)
514 {
515 shared_ptr<JsValue> global = runtime_->GetGlobal();
516
517 shared_ptr<JsValue> callBackEvent;
518 CodecData codecEvent;
519 StandardFunctionCodec codec;
520 if (codec.DecodePlatformMessage(eventData, codecEvent)) {
521 std::string eventString = codecEvent.GetStringValue();
522 if (eventString.empty()) {
523 callBackEvent = runtime_->NewNull();
524 } else {
525 callBackEvent = runtime_->NewString(eventString);
526 }
527 } else {
528 LOGE("trigger Js callback function error, decode message fail, callbackId:%{private}d", callbackId);
529 return;
530 }
531
532 auto itFunc = eventCallBackFuncs_.find(callbackId);
533 if (itFunc != eventCallBackFuncs_.end()) {
534 shared_ptr<JsValue> jsFunc = itFunc->second;
535 if (!jsFunc->IsFunction(runtime_) || jsFunc->IsNull(runtime_)) {
536 LOGE("trigger Js callback function error, callback is not a function, callbackId:%{private}d", callbackId);
537 return;
538 }
539
540 // Pass only 1 parameter
541 int32_t len = 1;
542 std::vector<shared_ptr<JsValue>> argv = { callBackEvent };
543 jsFunc->Call(runtime_, global, argv, len);
544 } else {
545 LOGE("trigger Js callback function error, it is not exists, callbackId:%{private}d", callbackId);
546 }
547 eventData.clear();
548 }
549
TriggerEventJsCallback(int32_t callbackId,int32_t code,std::vector<uint8_t> && eventData)550 void JsiDeclarativeGroupJsBridge::TriggerEventJsCallback(
551 int32_t callbackId, int32_t code, std::vector<uint8_t>&& eventData)
552 {
553 if (code == PLUGIN_CALLBACK_DESTROY) {
554 RemoveEventGroupCallBackFuncs(callbackId);
555 } else {
556 CallEventJsCallback(callbackId, std::move(eventData));
557 }
558 }
559
LoadPluginJsCode(std::string && jsCode)560 void JsiDeclarativeGroupJsBridge::LoadPluginJsCode(std::string&& jsCode)
561 {
562 LOGE("Do not support load JsCode in ark vm.");
563 }
564
LoadPluginJsByteCode(std::vector<uint8_t> && jsCode,std::vector<int32_t> && jsCodeLen)565 void JsiDeclarativeGroupJsBridge::LoadPluginJsByteCode(std::vector<uint8_t>&& jsCode, std::vector<int32_t>&& jsCodeLen)
566 {
567 if (!runtime_) {
568 return;
569 }
570 int32_t countLen = 0;
571 for (auto len : jsCodeLen) {
572 runtime_->EvaluateJsCode(jsCode.data() + countLen, len);
573 countLen += len;
574 }
575 }
576
Destroy()577 void JsiDeclarativeGroupJsBridge::Destroy()
578 {
579 eventCallBackFuncs_.clear();
580 moduleCallBackFuncs_.clear();
581 runtime_.reset();
582 }
583 #if defined(PREVIEW)
TriggerModuleJsCallbackPreview(int32_t callbackId,int32_t code,ResponseData responseData)584 void JsiDeclarativeGroupJsBridge::TriggerModuleJsCallbackPreview(
585 int32_t callbackId, int32_t code, ResponseData responseData)
586 {
587 shared_ptr<JsValue> callBackResult = runtime_->NewNull();
588 std::string resultString = responseData.GetResultString()->ToString();
589 code = responseData.GetActionCode();
590 if (!resultString.empty()) {
591 callBackResult = runtime_->NewString(resultString);
592 } else {
593 code = PLUGIN_REQUEST_FAIL;
594 callBackResult = runtime_->NewString(std::string("{\"code\":").append(std::to_string(code)).append(",")
595 .append("\"data\":\"invalid response data\"}"));
596 }
597
598 CallModuleJsCallback(callbackId, code, callBackResult);
599 }
600
601 const LinearMapNode<void (*)(const char*, RequestData&)> JsiDeclarativeGroupJsBridge::fetchRequestDataMap1[] = {
602 { "data",
__anon21ef328e0202() 603 [](const char* valStr, OHOS::Ace::RequestData& requestData) { requestData.SetData(valStr); } },
604 { "method",
__anon21ef328e0302() 605 [](const char* valStr, OHOS::Ace::RequestData& requestData) {
606 requestData.SetMethod(valStr);
607 } },
608 { "responseType", [](const char* valStr,
__anon21ef328e0402() 609 OHOS::Ace::RequestData& requestData) { requestData.SetResponseType(valStr); } },
__anon21ef328e0502() 610 { "url", [](const char* valStr, RequestData& requestData) { requestData.SetUrl(valStr); } },
611 };
612
613 const LinearMapNode<void (*)(shared_ptr<JsRuntime>, const shared_ptr<JsValue>&, RequestData&)>
614 JsiDeclarativeGroupJsBridge::fetchRequestDataMap2[] = {
615 { "data",
616 [](shared_ptr<JsRuntime> runtime,
__anon21ef328e0602() 617 const shared_ptr<JsValue>& val, OHOS::Ace::RequestData& requestData) {
618 std::string objStr = SerializationObjectToString(runtime, val);
619 if (objStr.empty()) {
620 return;
621 }
622 requestData.SetData(objStr.c_str());
623 } },
624 { "header",
625 [](shared_ptr<JsRuntime> runtime,
__anon21ef328e0702() 626 const shared_ptr<JsValue>& val, OHOS::Ace::RequestData& requestData) {
627 if (!val->IsObject(runtime)) {
628 return;
629 }
630 int32_t length = 0;
631 shared_ptr<JsValue> propertyNames;
632 if (val->GetEnumerablePropertyNames(runtime, propertyNames, length)) {
633 std::map<std::string, std::string> header;
634 for (int32_t i = 0; i < length; ++i) {
635 shared_ptr<JsValue> key = propertyNames->GetElement(runtime, i);
636 if (key->IsString(runtime)) {
637 shared_ptr<JsValue> item = val->GetProperty(runtime, key);
638 if (item->IsString(runtime)) {
639 header[key->ToString(runtime)] = item->ToString(runtime);
640 }
641 } else {
642 LOGW("key is null. Ignoring!");
643 }
644 }
645 requestData.SetHeader(header);
646 }
647 } },
648 };
649
GetRequestData(const shared_ptr<JsValue> & valObject,RequestData & requestData)650 void JsiDeclarativeGroupJsBridge::GetRequestData(const shared_ptr<JsValue>& valObject, RequestData& requestData)
651 {
652 if (!valObject->IsObject(runtime_)) {
653 return;
654 }
655 int32_t len = 0;
656 shared_ptr<JsValue> propertyNames;
657 valObject->GetEnumerablePropertyNames(runtime_, propertyNames, len);
658 for (int32_t i = 0; i < len; ++i) {
659 shared_ptr<JsValue> key = propertyNames->GetElement(runtime_, i);
660 if (key->IsUndefined(runtime_)) {
661 continue;
662 }
663 shared_ptr<JsValue> item = valObject->GetProperty(runtime_, key);
664 if (item->IsString(runtime_)) {
665 auto iter = BinarySearchFindIndex(
666 fetchRequestDataMap1, ArraySize(fetchRequestDataMap1), key->ToString(runtime_).c_str());
667 if (iter != -1) {
668 fetchRequestDataMap1[iter].value(item->ToString(runtime_).c_str(), requestData);
669 } else {
670 LOGD("key : %{public}s unsupported. Ignoring!", key->ToString(runtime_).c_str());
671 }
672 } else if (item->IsObject(runtime_)) {
673 auto iter = BinarySearchFindIndex(
674 fetchRequestDataMap2, ArraySize(fetchRequestDataMap2), key->ToString(runtime_).c_str());
675 if (iter != -1) {
676 fetchRequestDataMap2[iter].value(runtime_, item, requestData);
677 } else {
678 LOGD("key : %{public}s unsupported. Ignoring!", key->ToString(runtime_).c_str());
679 }
680 } else {
681 LOGD("key : %{public}s, value of unsupported type. Ignoring!", key->ToString(runtime_).c_str());
682 }
683 }
684 }
685
ParseRequestData(int32_t argc,const std::vector<shared_ptr<JsValue>> & argv,RequestData & requestData,int32_t requestId)686 ParseJsDataResult JsiDeclarativeGroupJsBridge::ParseRequestData(
687 int32_t argc, const std::vector<shared_ptr<JsValue>>& argv, RequestData& requestData, int32_t requestId)
688 {
689
690 if (argc < PLUGIN_REQUEST_ARG_APP_PARAMS_INDEX) {
691 return ParseJsDataResult::PARSE_JS_SUCCESS;
692 }
693 for (int32_t i = PLUGIN_REQUEST_ARG_APP_PARAMS_INDEX; i < argc; i++) {
694 const shared_ptr<JsValue> val = argv[i];
695 if (val->IsObject(runtime_)) {
696 std::string objStr = SerializationObjectToString(runtime_, val);
697 if (objStr.empty()) {
698 LOGW("Process callNative para is null");
699 return ParseJsDataResult::PARSE_JS_ERR_UNSUPPORTED_TYPE;
700 }
701 GetRequestData(val, requestData);
702 } else if (val->IsUndefined(runtime_)) {
703 LOGD("Process callNative para type:undefined");
704 } else {
705 LOGE("Process callNative para type: unsupported type");
706 return ParseJsDataResult::PARSE_JS_ERR_UNSUPPORTED_TYPE;
707 }
708 }
709 return ParseJsDataResult::PARSE_JS_SUCCESS;
710 }
711 #endif
712 } // namespace OHOS::Ace::Framework
713