• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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