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