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