• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "napi_remote_object_holder.h"
17 #include "napi_remote_object_internal.h"
18 
19 #include <hitrace_meter.h>
20 #include <string_ex.h>
21 #include <uv.h>
22 
23 #include "ipc_debug.h"
24 #include "iremote_invoker.h"
25 #include "log_tags.h"
26 #include "napi/native_api.h"
27 #include "napi/native_node_api.h"
28 #include "napi_message_parcel.h"
29 #include "napi_message_sequence.h"
30 #include "napi_remote_proxy_holder.h"
31 #include "napi_rpc_error.h"
32 #include "native_engine/native_value.h"
33 #include "napi_process_skeleton.h"
34 
35 namespace OHOS {
36 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_NAPI, "napi_remoteObject" };
37 
38 static const size_t ARGV_INDEX_0 = 0;
39 static const size_t ARGV_INDEX_1 = 1;
40 static const size_t ARGV_INDEX_2 = 2;
41 static const size_t ARGV_INDEX_3 = 3;
42 static const size_t ARGV_INDEX_4 = 4;
43 
44 static const size_t ARGV_LENGTH_1 = 1;
45 static const size_t ARGV_LENGTH_2 = 2;
46 static const size_t ARGV_LENGTH_5 = 5;
47 static const uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag.
48 
49 static std::atomic<int32_t> bytraceId = 1000;
50 static NapiError napiErr;
51 
RemoteObjectHolderFinalizeCb(napi_env env,void * data,void * hint)52 static void RemoteObjectHolderFinalizeCb(napi_env env, void *data, void *hint)
53 {
54     NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
55     if (holder == nullptr) {
56         ZLOGW(LOG_LABEL, "RemoteObjectHolderFinalizeCb null holder");
57         return;
58     }
59     holder->Lock();
60     int32_t curAttachCount = holder->DecAttachCount();
61     ZLOGD(LOG_LABEL, "NAPIRemoteObjectHolder destructed by js callback, curAttachCount:%{public}d", curAttachCount);
62     if (curAttachCount == 0) {
63         delete holder;
64     }
65 }
66 
DecreaseJsObjectRef(napi_env env,napi_ref ref)67 static void DecreaseJsObjectRef(napi_env env, napi_ref ref)
68 {
69     if (ref == nullptr) {
70         ZLOGI(LOG_LABEL, "ref is nullptr, do nothing");
71         return;
72     }
73 
74     uint32_t result;
75     napi_status napiStatus = napi_reference_unref(env, ref, &result);
76     NAPI_ASSERT_RETURN_VOID(env, napiStatus == napi_ok, "failed to decrease ref to js RemoteObject");
77 }
78 
IncreaseJsObjectRef(napi_env env,napi_ref ref)79 static void IncreaseJsObjectRef(napi_env env, napi_ref ref)
80 {
81     uint32_t result;
82     napi_status napiStatus = napi_reference_ref(env, ref, &result);
83     NAPI_ASSERT_RETURN_VOID(env, napiStatus == napi_ok, "failed to increase ref to js RemoteObject");
84 }
85 
RemoteObjectHolderRefCb(napi_env env,void * data,void * hint)86 static void RemoteObjectHolderRefCb(napi_env env, void *data, void *hint)
87 {
88     NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
89     if (holder == nullptr) {
90         ZLOGW(LOG_LABEL, "RemoteObjectHolderRefCb holder is nullptr");
91         return;
92     }
93     holder->Lock();
94     int32_t curAttachCount = holder->DecAttachCount();
95     holder->Unlock();
96     ZLOGD(LOG_LABEL, "RemoteObjectHolderRefCb, curAttachCount:%{public}d", curAttachCount);
97 
98     napi_ref ref = holder->GetJsObjectRef();
99     napi_env workerEnv = holder->GetJsObjectEnv();
100     if (ref == nullptr || workerEnv == nullptr) {
101         ZLOGE(LOG_LABEL, "ref or env is null");
102         return;
103     }
104     uv_loop_s *loop = nullptr;
105     napi_get_uv_event_loop(workerEnv, &loop);
106     uv_work_t *work = new(std::nothrow) uv_work_t;
107     NAPI_ASSERT_RETURN_VOID(workerEnv, work != nullptr, "cb failed to new work");
108     OperateJsRefParam *param = new OperateJsRefParam {
109         .env = workerEnv,
110         .thisVarRef = ref
111     };
112     work->data = reinterpret_cast<void *>(param);
113     uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
114         ZLOGI(LOG_LABEL, "decrease on uv work thread");
115         OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
116         napi_handle_scope scope = nullptr;
117         napi_open_handle_scope(param->env, &scope);
118         DecreaseJsObjectRef(param->env, param->thisVarRef);
119         napi_close_handle_scope(param->env, scope);
120         delete param;
121         delete work;
122     });
123 }
124 
RemoteObjectDetachCb(napi_env engine,void * value,void * hint)125 static void *RemoteObjectDetachCb(napi_env engine, void *value, void *hint)
126 {
127     (void)hint;
128     napi_env env = engine;
129     NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(value);
130     napi_ref ref = holder->GetJsObjectRef();
131 
132     uint32_t result;
133     napi_status napiStatus = napi_reference_ref(env, ref, &result);
134     if (napiStatus != napi_ok) {
135         ZLOGE(LOG_LABEL, "RemoteObjectDetachCb, failed to increase ref");
136     } else {
137         ZLOGI(LOG_LABEL, "RemoteObjectDetachCb, ref result:%{public}u", result);
138     }
139     return value;
140 }
141 
RemoteObjectAttachCb(napi_env engine,void * value,void * hint)142 static napi_value RemoteObjectAttachCb(napi_env engine, void *value, void *hint)
143 {
144     (void)hint;
145     NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(value);
146     if (holder == nullptr) {
147         ZLOGE(LOG_LABEL, "holder is nullptr when attach");
148         return nullptr;
149     }
150     holder->Lock();
151     ZLOGI(LOG_LABEL, "create js remote object when attach");
152     napi_env env = engine;
153     // retrieve js remote object constructor
154     napi_value global = nullptr;
155     napi_status status = napi_get_global(env, &global);
156     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
157     napi_value constructor = nullptr;
158     status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
159     NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
160     NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
161     // retrieve descriptor and it's length
162     std::u16string descriptor = holder->GetDescriptor();
163     std::string desc = Str16ToStr8(descriptor);
164     napi_value jsDesc = nullptr;
165     napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
166     // create a new js remote object
167     size_t argc = 1;
168     napi_value argv[ARGV_LENGTH_1] = { jsDesc };
169     napi_value jsRemoteObject = nullptr;
170     status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
171     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteObject when attach");
172     // retrieve and remove create holder
173     NAPIRemoteObjectHolder *createHolder = nullptr;
174     status = napi_remove_wrap(env, jsRemoteObject, (void **)&createHolder);
175     NAPI_ASSERT(env, status == napi_ok && createHolder != nullptr, "failed to remove create holder when attach");
176     status = napi_wrap(env, jsRemoteObject, holder, RemoteObjectHolderRefCb, nullptr, nullptr);
177     NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed when attach");
178     holder->IncAttachCount();
179     holder->Unlock();
180     return jsRemoteObject;
181 }
182 
RemoteObject_JS_Constructor(napi_env env,napi_callback_info info)183 napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
184 {
185     // new napi remote object
186     size_t argc = 2;
187     size_t expectedArgc = 1;
188     napi_value argv[ARGV_LENGTH_2] = { 0 };
189     napi_value thisVar = nullptr;
190     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
191     NAPI_ASSERT(env, argc >= expectedArgc, "requires at least 1 parameters");
192     napi_valuetype valueType = napi_null;
193     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
194     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
195     size_t bufferSize = 0;
196     size_t maxLen = 40960;
197     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
198     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
199     char stringValue[bufferSize + 1];
200     size_t jsStringLength = 0;
201     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
202     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
203     std::string descriptor = stringValue;
204     auto holder = new NAPIRemoteObjectHolder(env, Str8ToStr16(descriptor), thisVar);
205     napi_coerce_to_native_binding_object(env, thisVar, RemoteObjectDetachCb, RemoteObjectAttachCb, holder, nullptr);
206     // connect native object to js thisVar
207     napi_status status = napi_wrap(env, thisVar, holder, RemoteObjectHolderFinalizeCb, nullptr, nullptr);
208     NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed");
209     return thisVar;
210 }
211 
NAPIRemoteObject(std::thread::id jsThreadId,napi_env env,napi_ref jsObjectRef,const std::u16string & descriptor)212 NAPIRemoteObject::NAPIRemoteObject(std::thread::id jsThreadId, napi_env env, napi_ref jsObjectRef,
213     const std::u16string &descriptor)
214     : IPCObjectStub(descriptor)
215 {
216     ZLOGD(LOG_LABEL, "created, desc:%{public}s", Str16ToStr8(descriptor_).c_str());
217     env_ = env;
218     jsThreadId_ = jsThreadId;
219     thisVarRef_ = jsObjectRef;
220 
221     if (jsThreadId_ == std::this_thread::get_id()) {
222         IncreaseJsObjectRef(env, jsObjectRef);
223     } else {
224         uv_loop_s *loop = nullptr;
225         napi_get_uv_event_loop(env_, &loop);
226         uv_work_t *work = new(std::nothrow) uv_work_t;
227         NAPI_ASSERT_RETURN_VOID(env_, work != nullptr, "create NAPIRemoteObject, new work failed");
228         std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
229         OperateJsRefParam *param = new OperateJsRefParam {
230             .env = env_,
231             .thisVarRef = jsObjectRef,
232             .lockInfo = lockInfo.get()
233         };
234 
235         work->data = reinterpret_cast<void *>(param);
236         uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
237             OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
238             napi_handle_scope scope = nullptr;
239             napi_open_handle_scope(param->env, &scope);
240             IncreaseJsObjectRef(param->env, param->thisVarRef);
241             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
242             param->lockInfo->ready = true;
243             param->lockInfo->condition.notify_all();
244             napi_close_handle_scope(param->env, scope);
245         });
246         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
247         param->lockInfo->condition.wait(lock, [&param] { return param->lockInfo->ready; });
248         delete param;
249         delete work;
250     }
251 }
252 
~NAPIRemoteObject()253 NAPIRemoteObject::~NAPIRemoteObject()
254 {
255     ZLOGD(LOG_LABEL, "destoryed, desc:%{public}s", Str16ToStr8(descriptor_).c_str());
256     if (thisVarRef_ != nullptr && env_ != nullptr) {
257         if (jsThreadId_ == std::this_thread::get_id()) {
258             DecreaseJsObjectRef(env_, thisVarRef_);
259         } else {
260             uv_loop_s *loop = nullptr;
261             napi_get_uv_event_loop(env_, &loop);
262             uv_work_t *work = new(std::nothrow) uv_work_t;
263             NAPI_ASSERT_RETURN_VOID(env_, work != nullptr, "release NAPIRemoteObject, new work failed");
264             OperateJsRefParam *param = new OperateJsRefParam {
265                 .env = env_,
266                 .thisVarRef = thisVarRef_
267             };
268             work->data = reinterpret_cast<void *>(param);
269             uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
270                 OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
271                 napi_handle_scope scope = nullptr;
272                 napi_open_handle_scope(param->env, &scope);
273                 DecreaseJsObjectRef(param->env, param->thisVarRef);
274                 napi_close_handle_scope(param->env, scope);
275                 delete param;
276                 delete work;
277             });
278         }
279         thisVarRef_ = nullptr;
280     }
281 }
282 
CheckObjectLegality() const283 bool NAPIRemoteObject::CheckObjectLegality() const
284 {
285     return true;
286 }
287 
GetObjectType() const288 int NAPIRemoteObject::GetObjectType() const
289 {
290     return OBJECT_TYPE_JAVASCRIPT;
291 }
292 
GetJsObjectRef() const293 napi_ref NAPIRemoteObject::GetJsObjectRef() const
294 {
295     return thisVarRef_;
296 }
297 
ResetJsEnv()298 void NAPIRemoteObject::ResetJsEnv()
299 {
300     env_ = nullptr;
301     thisVarRef_ = nullptr;
302 }
303 
NAPI_RemoteObject_getCallingInfo(CallingInfo & newCallingInfoParam)304 void NAPI_RemoteObject_getCallingInfo(CallingInfo &newCallingInfoParam)
305 {
306     newCallingInfoParam.callingPid = IPCSkeleton::GetCallingPid();
307     newCallingInfoParam.callingUid = IPCSkeleton::GetCallingUid();
308     newCallingInfoParam.callingTokenId = IPCSkeleton::GetCallingTokenID();
309     newCallingInfoParam.callingDeviceID = IPCSkeleton::GetCallingDeviceID();
310     newCallingInfoParam.localDeviceID = IPCSkeleton::GetLocalDeviceID();
311     newCallingInfoParam.isLocalCalling = IPCSkeleton::IsLocalCalling();
312     newCallingInfoParam.activeStatus = IRemoteInvoker::ACTIVE_INVOKER;
313 };
314 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)315 int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
316 {
317     ZLOGD(LOG_LABEL, "enter OnRemoteRequest");
318     if (code == DUMP_TRANSACTION) {
319         ZLOGE(LOG_LABEL, "DUMP_TRANSACTION data size:%{public}zu", data.GetReadableBytes());
320     }
321     std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
322     CallbackParam *param = new CallbackParam {
323         .env = env_,
324         .thisVarRef = thisVarRef_,
325         .code = code,
326         .data = &data,
327         .reply = &reply,
328         .option = &option,
329         .lockInfo = lockInfo.get(),
330         .result = 0
331     };
332 
333     NAPI_RemoteObject_getCallingInfo(param->callingInfo);
334     ZLOGD(LOG_LABEL, "callingPid:%{public}u callingUid:%{public}u "
335         "callingDeviceID:%{public}s localDeviceId:%{public}s localCalling:%{public}d",
336         param->callingInfo.callingPid, param->callingInfo.callingUid,
337         param->callingInfo.callingDeviceID.c_str(), param->callingInfo.localDeviceID.c_str(),
338         param->callingInfo.isLocalCalling);
339     int ret = OnJsRemoteRequest(param);
340     ZLOGI(LOG_LABEL, "OnJsRemoteRequest done, ret:%{public}d", ret);
341     return ret;
342 }
343 
ThenCallback(napi_env env,napi_callback_info info)344 napi_value NAPIRemoteObject::ThenCallback(napi_env env, napi_callback_info info)
345 {
346     ZLOGD(LOG_LABEL, "call js onRemoteRequest done");
347     size_t argc = 1;
348     napi_value argv[ARGV_LENGTH_1] = {nullptr};
349     void* data = nullptr;
350     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
351     CallbackParam *param = static_cast<CallbackParam *>(data);
352     bool result = false;
353     napi_get_value_bool(param->env, argv[ARGV_INDEX_0], &result);
354     if (!result) {
355         ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s", result ? "true" : "false");
356         param->result = ERR_UNKNOWN_TRANSACTION;
357     } else {
358         param->result = ERR_NONE;
359     }
360     std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
361     param->lockInfo->ready = true;
362     param->lockInfo->condition.notify_all();
363     napi_value res;
364     napi_get_undefined(env, &res);
365     return res;
366 }
367 
CatchCallback(napi_env env,napi_callback_info info)368 napi_value NAPIRemoteObject::CatchCallback(napi_env env, napi_callback_info info)
369 {
370     ZLOGI(LOG_LABEL, "Async onReomteReuqest's returnVal is rejected");
371     size_t argc = 1;
372     napi_value argv[ARGV_LENGTH_1] = {nullptr};
373     void* data = nullptr;
374     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
375     CallbackParam *param = static_cast<CallbackParam *>(data);
376     param->result = ERR_UNKNOWN_TRANSACTION;
377     std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
378     param->lockInfo->ready = true;
379     param->lockInfo->condition.notify_all();
380     napi_value res;
381     napi_get_undefined(env, &res);
382     return res;
383 }
384 
NAPI_RemoteObject_saveOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)385 void NAPI_RemoteObject_saveOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
386 {
387     napi_value global = nullptr;
388     napi_get_global(env, &global);
389     napi_get_named_property(env, global, "callingPid_", &oldCallingInfo.callingPid);
390     napi_get_named_property(env, global, "callingUid_", &oldCallingInfo.callingUid);
391     napi_get_named_property(env, global, "callingTokenId_", &oldCallingInfo.callingTokenId);
392     napi_get_named_property(env, global, "callingDeviceID_", &oldCallingInfo.callingDeviceID);
393     napi_get_named_property(env, global, "localDeviceID_", &oldCallingInfo.localDeviceID);
394     napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
395     napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
396     napi_get_named_property(env, global, "activeStatus_", &oldCallingInfo.activeStatus);
397 }
398 
NAPI_RemoteObject_setNewCallingInfo(napi_env env,const CallingInfo & newCallingInfoParam)399 void NAPI_RemoteObject_setNewCallingInfo(napi_env env, const CallingInfo &newCallingInfoParam)
400 {
401     napi_value global = nullptr;
402     napi_get_global(env, &global);
403     napi_value newPid;
404     napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingPid), &newPid);
405     napi_set_named_property(env, global, "callingPid_", newPid);
406     napi_value newUid;
407     napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingUid), &newUid);
408     napi_set_named_property(env, global, "callingUid_", newUid);
409     napi_value newCallingTokenId;
410     napi_create_uint32(env, newCallingInfoParam.callingTokenId, &newCallingTokenId);
411     napi_set_named_property(env, global, "callingTokenId_", newCallingTokenId);
412     napi_value newDeviceID;
413     napi_create_string_utf8(env, newCallingInfoParam.callingDeviceID.c_str(), NAPI_AUTO_LENGTH, &newDeviceID);
414     napi_set_named_property(env, global, "callingDeviceID_", newDeviceID);
415     napi_value newLocalDeviceID;
416     napi_create_string_utf8(env, newCallingInfoParam.localDeviceID.c_str(), NAPI_AUTO_LENGTH, &newLocalDeviceID);
417     napi_set_named_property(env, global, "localDeviceID_", newLocalDeviceID);
418     napi_value newIsLocalCalling;
419     napi_get_boolean(env, newCallingInfoParam.isLocalCalling, &newIsLocalCalling);
420     napi_set_named_property(env, global, "isLocalCalling_", newIsLocalCalling);
421     napi_value newActiveStatus;
422     napi_create_int32(env, newCallingInfoParam.activeStatus, &newActiveStatus);
423     napi_set_named_property(env, global, "activeStatus_", newActiveStatus);
424 }
425 
NAPI_RemoteObject_resetOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)426 void NAPI_RemoteObject_resetOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
427 {
428     napi_value global = nullptr;
429     napi_get_global(env, &global);
430     napi_set_named_property(env, global, "callingPid_", oldCallingInfo.callingPid);
431     napi_set_named_property(env, global, "callingUid_", oldCallingInfo.callingUid);
432     napi_set_named_property(env, global, "callingTokenId_", oldCallingInfo.callingTokenId);
433     napi_set_named_property(env, global, "callingDeviceID_", oldCallingInfo.callingDeviceID);
434     napi_set_named_property(env, global, "localDeviceID_", oldCallingInfo.localDeviceID);
435     napi_set_named_property(env, global, "isLocalCalling_", oldCallingInfo.isLocalCalling);
436     napi_set_named_property(env, global, "activeStatus_", oldCallingInfo.activeStatus);
437 }
438 
OnJsRemoteRequest(CallbackParam * jsParam)439 int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
440 {
441     if (jsParam == nullptr) {
442         ZLOGE(LOG_LABEL, "Js Param is null");
443         return ERR_UNKNOWN_REASON;
444     }
445     if (thisVarRef_ == nullptr || env_ == nullptr) {
446         ZLOGE(LOG_LABEL, "Js env has been destructed");
447         return ERR_UNKNOWN_REASON;
448     }
449     uv_loop_s *loop = nullptr;
450     napi_get_uv_event_loop(env_, &loop);
451 
452     uv_work_t *work = new(std::nothrow) uv_work_t;
453     if (work == nullptr) {
454         ZLOGE(LOG_LABEL, "failed to new uv_work_t");
455         delete jsParam;
456         return -1;
457     }
458     work->data = reinterpret_cast<void *>(jsParam);
459     ZLOGI(LOG_LABEL, "start nv queue work loop. desc:%{public}s", Str16ToStr8(descriptor_).c_str());
460     uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {
461         ZLOGI(LOG_LABEL, "enter work pool. code:%{public}u", (reinterpret_cast<CallbackParam *>(work->data))->code);
462     }, [](uv_work_t *work, int status) {
463         ZLOGI(LOG_LABEL, "enter thread pool");
464         CallbackParam *param = reinterpret_cast<CallbackParam *>(work->data);
465         napi_handle_scope scope = nullptr;
466         napi_open_handle_scope(param->env, &scope);
467         napi_value onRemoteRequest = nullptr;
468         napi_value thisVar = nullptr;
469         napi_get_reference_value(param->env, param->thisVarRef, &thisVar);
470         if (thisVar == nullptr) {
471             ZLOGE(LOG_LABEL, "thisVar is null");
472             param->result = -1;
473             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
474             param->lockInfo->ready = true;
475             param->lockInfo->condition.notify_all();
476             napi_close_handle_scope(param->env, scope);
477             return;
478         }
479         napi_get_named_property(param->env, thisVar, "onRemoteMessageRequest", &onRemoteRequest);
480         if (onRemoteRequest == nullptr) {
481             ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
482             param->result = -1;
483             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
484             param->lockInfo->ready = true;
485             param->lockInfo->condition.notify_all();
486             napi_close_handle_scope(param->env, scope);
487             return;
488         }
489         napi_valuetype type = napi_undefined;
490         napi_typeof(param->env, onRemoteRequest, &type);
491         bool isOnRemoteMessageRequest = true;
492         if (type != napi_function) {
493             napi_get_named_property(param->env, thisVar, "onRemoteRequest", &onRemoteRequest);
494             if (onRemoteRequest == nullptr) {
495                 ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
496                 param->result = -1;
497                 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
498                 param->lockInfo->ready = true;
499                 param->lockInfo->condition.notify_all();
500                 napi_close_handle_scope(param->env, scope);
501                 return;
502             }
503             isOnRemoteMessageRequest = false;
504         }
505         napi_value jsCode;
506         napi_create_uint32(param->env, param->code, &jsCode);
507 
508         napi_value global = nullptr;
509         napi_get_global(param->env, &global);
510         if (global == nullptr) {
511             ZLOGE(LOG_LABEL, "get napi global failed");
512             param->result = -1;
513             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
514             param->lockInfo->ready = true;
515             param->lockInfo->condition.notify_all();
516             napi_close_handle_scope(param->env, scope);
517             return;
518         }
519         napi_value jsOptionConstructor = nullptr;
520         napi_get_named_property(param->env, global, "IPCOptionConstructor_", &jsOptionConstructor);
521         if (jsOptionConstructor == nullptr) {
522             ZLOGE(LOG_LABEL, "jsOption constructor is null");
523             param->result = -1;
524             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
525             param->lockInfo->ready = true;
526             param->lockInfo->condition.notify_all();
527             napi_close_handle_scope(param->env, scope);
528             return;
529         }
530         napi_value jsOption;
531         size_t argc = 2;
532         napi_value flags = nullptr;
533         napi_create_int32(param->env, param->option->GetFlags(), &flags);
534         napi_value waittime = nullptr;
535         napi_create_int32(param->env, param->option->GetWaitTime(), &waittime);
536         napi_value argv[ARGV_LENGTH_2] = { flags, waittime };
537         napi_new_instance(param->env, jsOptionConstructor, argc, argv, &jsOption);
538         if (jsOption == nullptr) {
539             ZLOGE(LOG_LABEL, "new jsOption failed");
540             param->result = -1;
541             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
542             param->lockInfo->ready = true;
543             param->lockInfo->condition.notify_all();
544             napi_close_handle_scope(param->env, scope);
545             return;
546         }
547         napi_value jsParcelConstructor = nullptr;
548         if (isOnRemoteMessageRequest) {
549             napi_get_named_property(param->env, global, "IPCSequenceConstructor_", &jsParcelConstructor);
550         } else {
551             napi_get_named_property(param->env, global, "IPCParcelConstructor_", &jsParcelConstructor);
552         }
553         if (jsParcelConstructor == nullptr) {
554             ZLOGE(LOG_LABEL, "jsParcel constructor is null");
555             param->result = -1;
556             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
557             param->lockInfo->ready = true;
558             param->lockInfo->condition.notify_all();
559             napi_close_handle_scope(param->env, scope);
560             return;
561         }
562         napi_value jsData;
563         napi_value dataParcel;
564         napi_create_object(param->env, &dataParcel);
565         napi_wrap(param->env, dataParcel, param->data,
566             [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
567         if (dataParcel == nullptr) {
568             ZLOGE(LOG_LABEL, "create js object for data parcel address failed");
569             param->result = -1;
570             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
571             param->lockInfo->ready = true;
572             param->lockInfo->condition.notify_all();
573             napi_close_handle_scope(param->env, scope);
574             return;
575         }
576         size_t argc3 = 1;
577         napi_value argv3[1] = { dataParcel };
578         napi_new_instance(param->env, jsParcelConstructor, argc3, argv3, &jsData);
579         if (jsData == nullptr) {
580             ZLOGE(LOG_LABEL, "create js data parcel failed");
581             param->result = -1;
582             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
583             param->lockInfo->ready = true;
584             param->lockInfo->condition.notify_all();
585             napi_close_handle_scope(param->env, scope);
586             return;
587         }
588         napi_value jsReply;
589         napi_value replyParcel;
590         napi_create_object(param->env, &replyParcel);
591         napi_wrap(param->env, replyParcel, param->reply,
592             [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
593         if (replyParcel == nullptr) {
594             ZLOGE(LOG_LABEL, "create js object for reply parcel address failed");
595             param->result = -1;
596             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
597             param->lockInfo->ready = true;
598             param->lockInfo->condition.notify_all();
599             napi_close_handle_scope(param->env, scope);
600             return;
601         }
602         size_t argc4 = 1;
603         napi_value argv4[1] = { replyParcel };
604         napi_new_instance(param->env, jsParcelConstructor, argc4, argv4, &jsReply);
605         if (jsReply == nullptr) {
606             ZLOGE(LOG_LABEL, "create js reply parcel failed");
607             param->result = -1;
608             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
609             param->lockInfo->ready = true;
610             param->lockInfo->condition.notify_all();
611             napi_close_handle_scope(param->env, scope);
612             return;
613         }
614         NAPI_CallingInfo oldCallingInfo;
615         NAPI_RemoteObject_saveOldCallingInfo(param->env, oldCallingInfo);
616         NAPI_RemoteObject_setNewCallingInfo(param->env, param->callingInfo);
617         // start to call onRemoteRequest
618         size_t argc2 = 4;
619         napi_value argv2[] = { jsCode, jsData, jsReply, jsOption };
620         napi_value returnVal;
621         napi_status ret = napi_call_function(param->env, thisVar, onRemoteRequest, argc2, argv2, &returnVal);
622         // Reset old calling pid, uid, device id
623         NAPI_RemoteObject_resetOldCallingInfo(param->env, oldCallingInfo);
624 
625         do {
626             if (ret != napi_ok) {
627                 ZLOGE(LOG_LABEL, "OnRemoteRequest got exception");
628                 param->result = ERR_UNKNOWN_TRANSACTION;
629                 break;
630             }
631 
632             ZLOGD(LOG_LABEL, "call js onRemoteRequest done");
633             // Check whether return_val is Promise
634             bool returnIsPromise = false;
635             napi_is_promise(param->env, returnVal, &returnIsPromise);
636             if (!returnIsPromise) {
637                 ZLOGD(LOG_LABEL, "onRemoteRequest is synchronous");
638                 bool result = false;
639                 napi_get_value_bool(param->env, returnVal, &result);
640                 if (!result) {
641                     ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s", result ? "true" : "false");
642                     param->result = ERR_UNKNOWN_TRANSACTION;
643                 } else {
644                     param->result = ERR_NONE;
645                 }
646                 break;
647             }
648 
649             ZLOGD(LOG_LABEL, "onRemoteRequest is asynchronous");
650             // Create promiseThen
651             napi_value promiseThen = nullptr;
652             napi_get_named_property(param->env, returnVal, "then", &promiseThen);
653             if (promiseThen == nullptr) {
654                 ZLOGE(LOG_LABEL, "get promiseThen failed");
655                 param->result = -1;
656                 break;
657             }
658             napi_value thenValue;
659             ret = napi_create_function(param->env, "thenCallback", NAPI_AUTO_LENGTH, ThenCallback, param, &thenValue);
660             if (ret != napi_ok) {
661                 ZLOGE(LOG_LABEL, "thenCallback got exception");
662                 param->result = ERR_UNKNOWN_TRANSACTION;
663                 break;
664             }
665             napi_value catchValue;
666             ret = napi_create_function(param->env, "catchCallback",
667                 NAPI_AUTO_LENGTH, CatchCallback, param, &catchValue);
668             if (ret != napi_ok) {
669                 ZLOGE(LOG_LABEL, "catchCallback got exception");
670                 param->result = ERR_UNKNOWN_TRANSACTION;
671                 break;
672             }
673             // Start to call promiseThen
674             napi_env env = param->env;
675             napi_value thenReturnValue;
676             constexpr uint32_t THEN_ARGC = 2;
677             napi_value thenArgv[THEN_ARGC] = {thenValue, catchValue};
678             ret = napi_call_function(env, returnVal, promiseThen, THEN_ARGC, thenArgv, &thenReturnValue);
679             if (ret != napi_ok) {
680                 ZLOGE(LOG_LABEL, "PromiseThen got exception");
681                 param->result = ERR_UNKNOWN_TRANSACTION;
682                 break;
683             }
684             napi_close_handle_scope(env, scope);
685             return;
686         } while (0);
687 
688         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
689         param->lockInfo->ready = true;
690         param->lockInfo->condition.notify_all();
691         napi_close_handle_scope(param->env, scope);
692     }, uv_qos_user_initiated);
693     std::unique_lock<std::mutex> lock(jsParam->lockInfo->mutex);
694     jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
695     int ret = jsParam->result;
696     delete jsParam;
697     delete work;
698     return ret;
699 }
700 
NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env,const sptr<IRemoteObject> target)701 napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteObject> target)
702 {
703     if (target == nullptr) {
704         ZLOGE(LOG_LABEL, "RemoteObject is null");
705         return nullptr;
706     }
707 
708     if (!target->IsProxyObject()) {
709         IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
710         uint32_t objectType = tmp->GetObjectType();
711         ZLOGI(LOG_LABEL, "create js object, type:%{public}d", objectType);
712         if (objectType == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT || objectType == IPCObjectStub::OBJECT_TYPE_NATIVE) {
713             // retrieve js remote object constructor
714             napi_value global = nullptr;
715             napi_status status = napi_get_global(env, &global);
716             NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
717             napi_value constructor = nullptr;
718             status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
719             NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
720             NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
721             // retrieve descriptor and it's length
722             std::u16string descriptor = target->GetObjectDescriptor();
723             std::string desc = Str16ToStr8(descriptor);
724             napi_value jsDesc = nullptr;
725             napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
726             // create a new js remote object
727             size_t argc = 1;
728             napi_value argv[ARGV_LENGTH_1] = { jsDesc };
729             napi_value jsRemoteObject = nullptr;
730             status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
731             NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteObject");
732             // retrieve holder and set object
733             NAPIRemoteObjectHolder *holder = nullptr;
734             napi_unwrap(env, jsRemoteObject, (void **)&holder);
735             NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
736             holder->Set(target);
737             return jsRemoteObject;
738         }
739     }
740 
741     napi_value global = nullptr;
742     napi_status status = napi_get_global(env, &global);
743     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
744     napi_value constructor = nullptr;
745     status = napi_get_named_property(env, global, "IPCProxyConstructor_", &constructor);
746     NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
747     napi_value jsRemoteProxy;
748     status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
749     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteProxy");
750     NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
751     proxyHolder->object_ = target;
752     proxyHolder->list_ = new NAPIDeathRecipientList();
753 
754     return jsRemoteProxy;
755 }
756 
NAPI_ohos_rpc_getNativeRemoteObject(napi_env env,napi_value object)757 sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
758 {
759     if (object != nullptr) {
760         napi_value global = nullptr;
761         napi_status status = napi_get_global(env, &global);
762         NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
763         napi_value stubConstructor = nullptr;
764         status = napi_get_named_property(env, global, "IPCStubConstructor_", &stubConstructor);
765         NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
766         bool instanceOfStub = false;
767         status = napi_instanceof(env, object, stubConstructor, &instanceOfStub);
768         NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
769         if (instanceOfStub) {
770             NAPIRemoteObjectHolder *holder = nullptr;
771             napi_unwrap(env, object, (void **)&holder);
772             NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
773             return holder != nullptr ? holder->Get() : nullptr;
774         }
775 
776         napi_value proxyConstructor = nullptr;
777         status = napi_get_named_property(env, global, "IPCProxyConstructor_", &proxyConstructor);
778         NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
779         bool instanceOfProxy = false;
780         status = napi_instanceof(env, object, proxyConstructor, &instanceOfProxy);
781         NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
782         if (instanceOfProxy) {
783             NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
784             return holder != nullptr ? holder->object_ : nullptr;
785         }
786     }
787     return nullptr;
788 }
789 
NAPI_RemoteObject_queryLocalInterface(napi_env env,napi_callback_info info)790 static napi_value NAPI_RemoteObject_queryLocalInterface(napi_env env, napi_callback_info info)
791 {
792     size_t argc = 1;
793     size_t expectedArgc = 1;
794     napi_value argv[ARGV_LENGTH_1] = {nullptr};
795     napi_value thisVar = nullptr;
796     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
797     NAPI_ASSERT(env, argc == expectedArgc, "requires 1 parameters");
798     napi_valuetype valueType = napi_null;
799     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
800     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
801     size_t bufferSize = 0;
802     size_t maxLen = 40960;
803     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
804     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
805     char stringValue[bufferSize + 1];
806     size_t jsStringLength = 0;
807     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
808     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
809     std::string descriptor = stringValue;
810     NAPIRemoteObjectHolder *holder = nullptr;
811     napi_unwrap(env, thisVar, (void **)&holder);
812     NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
813     napi_value ret = holder->queryLocalInterface(descriptor);
814     return ret;
815 }
816 
NAPI_RemoteObject_getLocalInterface(napi_env env,napi_callback_info info)817 static napi_value NAPI_RemoteObject_getLocalInterface(napi_env env, napi_callback_info info)
818 {
819     size_t argc = 1;
820     size_t expectedArgc = 1;
821     napi_value argv[ARGV_LENGTH_1] = {nullptr};
822     napi_value thisVar = nullptr;
823     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
824     if (argc != expectedArgc) {
825         ZLOGE(LOG_LABEL, "requires 1 parameters");
826         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
827     }
828     napi_valuetype valueType = napi_null;
829     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
830     if (valueType != napi_string) {
831         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
832         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
833     }
834     size_t bufferSize = 0;
835     size_t maxLen = 40960;
836     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
837     if (bufferSize >= maxLen) {
838         ZLOGE(LOG_LABEL, "string length too large");
839         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
840     }
841     char stringValue[bufferSize + 1];
842     size_t jsStringLength = 0;
843     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
844     if (jsStringLength != bufferSize) {
845         ZLOGE(LOG_LABEL, "string length wrong");
846         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
847     }
848     std::string descriptor = stringValue;
849     NAPIRemoteObjectHolder *holder = nullptr;
850     napi_unwrap(env, thisVar, (void **)&holder);
851     if (holder == nullptr) {
852         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
853         return nullptr;
854     }
855     napi_value ret = holder->queryLocalInterface(descriptor);
856     return ret;
857 }
858 
NAPI_RemoteObject_getInterfaceDescriptor(napi_env env,napi_callback_info info)859 static napi_value NAPI_RemoteObject_getInterfaceDescriptor(napi_env env, napi_callback_info info)
860 {
861     napi_value result = nullptr;
862     napi_value thisVar = nullptr;
863     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
864     sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
865     std::u16string descriptor = nativeObject->GetObjectDescriptor();
866     napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
867     return result;
868 }
869 
NAPI_RemoteObject_getDescriptor(napi_env env,napi_callback_info info)870 static napi_value NAPI_RemoteObject_getDescriptor(napi_env env, napi_callback_info info)
871 {
872     napi_value result = nullptr;
873     napi_value thisVar = nullptr;
874     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
875     sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
876     if (nativeObject == nullptr) {
877         ZLOGE(LOG_LABEL, "native stub object is nullptr");
878         return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
879     }
880     std::u16string descriptor = nativeObject->GetObjectDescriptor();
881     napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
882     return result;
883 }
884 
NAPI_RemoteObject_getCallingPid(napi_env env,napi_callback_info info)885 static napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
886 {
887     return NAPI_getCallingPid(env, info);
888 }
889 
NAPI_RemoteObject_getCallingUid(napi_env env,napi_callback_info info)890 static napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
891 {
892     return NAPI_getCallingUid(env, info);
893 }
894 
MakeSendRequestResult(SendRequestParam * param)895 napi_value MakeSendRequestResult(SendRequestParam *param)
896 {
897     if (param == nullptr) {
898         ZLOGE(LOG_LABEL, "send request param is null");
899         return nullptr;
900     }
901     napi_value errCode = nullptr;
902     napi_create_int32(param->env, param->errCode, &errCode);
903     napi_value code = nullptr;
904     napi_get_reference_value(param->env, param->jsCodeRef, &code);
905     napi_value data = nullptr;
906     napi_get_reference_value(param->env, param->jsDataRef, &data);
907     napi_value reply = nullptr;
908     napi_get_reference_value(param->env, param->jsReplyRef, &reply);
909     napi_value result = nullptr;
910     napi_create_object(param->env, &result);
911     napi_set_named_property(param->env, result, "errCode", errCode);
912     napi_set_named_property(param->env, result, "code", code);
913     napi_set_named_property(param->env, result, "data", data);
914     napi_set_named_property(param->env, result, "reply", reply);
915     return result;
916 }
917 
StubExecuteSendRequest(napi_env env,SendRequestParam * param)918 void StubExecuteSendRequest(napi_env env, SendRequestParam *param)
919 {
920     if (param == nullptr) {
921         ZLOGE(LOG_LABEL, "param is null");
922         return;
923     }
924     param->errCode = param->target->SendRequest(param->code,
925         *(param->data.get()), *(param->reply.get()), param->option);
926     ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d", param->errCode);
927     if (param->traceId != 0) {
928         FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
929     }
930     uv_loop_s *loop = nullptr;
931     napi_get_uv_event_loop(env, &loop);
932     uv_work_t *work = new uv_work_t;
933     work->data = reinterpret_cast<void *>(param);
934     uv_after_work_cb afterWorkCb = nullptr;
935     if (param->callback != nullptr) {
936         afterWorkCb = [](uv_work_t *work, int status) {
937             ZLOGI(LOG_LABEL, "callback started");
938             SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
939             napi_handle_scope scope = nullptr;
940             napi_open_handle_scope(param->env, &scope);
941             napi_value result = MakeSendRequestResult(param);
942             napi_value callback = nullptr;
943             napi_get_reference_value(param->env, param->callback, &callback);
944             napi_value cbResult = nullptr;
945             napi_call_function(param->env, nullptr, callback, 1, &result, &cbResult);
946             napi_delete_reference(param->env, param->jsCodeRef);
947             napi_delete_reference(param->env, param->jsDataRef);
948             napi_delete_reference(param->env, param->jsReplyRef);
949             napi_delete_reference(param->env, param->jsOptionRef);
950             napi_delete_reference(param->env, param->callback);
951             napi_close_handle_scope(param->env, scope);
952             delete param;
953             delete work;
954         };
955     } else {
956         afterWorkCb = [](uv_work_t *work, int status) {
957             ZLOGI(LOG_LABEL, "promise fullfilled");
958             SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
959             napi_handle_scope scope = nullptr;
960             napi_open_handle_scope(param->env, &scope);
961             napi_value result = MakeSendRequestResult(param);
962             if (param->errCode == 0) {
963                 napi_resolve_deferred(param->env, param->deferred, result);
964             } else {
965                 napi_reject_deferred(param->env, param->deferred, result);
966             }
967             napi_delete_reference(param->env, param->jsCodeRef);
968             napi_delete_reference(param->env, param->jsDataRef);
969             napi_delete_reference(param->env, param->jsReplyRef);
970             napi_delete_reference(param->env, param->jsOptionRef);
971             napi_close_handle_scope(param->env, scope);
972             delete param;
973             delete work;
974         };
975     }
976     uv_queue_work(loop, work, [](uv_work_t *work) {}, afterWorkCb);
977 }
978 
StubSendRequestAsync(napi_env env,sptr<IRemoteObject> target,uint32_t code,std::shared_ptr<MessageParcel> data,std::shared_ptr<MessageParcel> reply,MessageOption & option,napi_value * argv)979 napi_value StubSendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
980     std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
981     MessageOption &option, napi_value *argv)
982 {
983     SendRequestParam *sendRequestParam = new SendRequestParam {
984         .target = target,
985         .code = code,
986         .data = data,
987         .reply = reply,
988         .option = option,
989         .asyncWork = nullptr,
990         .deferred = nullptr,
991         .errCode = -1,
992         .jsCodeRef = nullptr,
993         .jsDataRef = nullptr,
994         .jsReplyRef = nullptr,
995         .jsOptionRef = nullptr,
996         .callback = nullptr,
997         .env = env,
998         .traceId = 0,
999     };
1000     if (target != nullptr) {
1001         std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1002         if (!remoteDescriptor.empty()) {
1003             sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1004             sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1005             StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1006         }
1007     }
1008     napi_create_reference(env, argv[ARGV_INDEX_0], 1, &sendRequestParam->jsCodeRef);
1009     napi_create_reference(env, argv[ARGV_INDEX_1], 1, &sendRequestParam->jsDataRef);
1010     napi_create_reference(env, argv[ARGV_INDEX_2], 1, &sendRequestParam->jsReplyRef);
1011     napi_create_reference(env, argv[ARGV_INDEX_3], 1, &sendRequestParam->jsOptionRef);
1012     napi_create_reference(env, argv[ARGV_INDEX_4], 1, &sendRequestParam->callback);
1013     std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1014     t.detach();
1015     napi_value result = nullptr;
1016     napi_get_undefined(env, &result);
1017     return result;
1018 }
1019 
StubSendRequestPromise(napi_env env,sptr<IRemoteObject> target,uint32_t code,std::shared_ptr<MessageParcel> data,std::shared_ptr<MessageParcel> reply,MessageOption & option,napi_value * argv)1020 napi_value StubSendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1021     std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1022     MessageOption &option, napi_value *argv)
1023 {
1024     napi_deferred deferred = nullptr;
1025     napi_value promise = nullptr;
1026     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1027     SendRequestParam *sendRequestParam = new SendRequestParam {
1028         .target = target,
1029         .code = code,
1030         .data = data,
1031         .reply = reply,
1032         .option = option,
1033         .asyncWork = nullptr,
1034         .deferred = deferred,
1035         .errCode = -1,
1036         .jsCodeRef = nullptr,
1037         .jsDataRef = nullptr,
1038         .jsReplyRef = nullptr,
1039         .jsOptionRef = nullptr,
1040         .callback = nullptr,
1041         .env = env,
1042         .traceId = 0,
1043     };
1044     if (target != nullptr) {
1045         std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1046         if (!remoteDescriptor.empty()) {
1047             sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1048             sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1049             StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1050         }
1051     }
1052     napi_create_reference(env, argv[ARGV_INDEX_0], 1, &sendRequestParam->jsCodeRef);
1053     napi_create_reference(env, argv[ARGV_INDEX_1], 1, &sendRequestParam->jsDataRef);
1054     napi_create_reference(env, argv[ARGV_INDEX_2], 1, &sendRequestParam->jsReplyRef);
1055     napi_create_reference(env, argv[ARGV_INDEX_3], 1, &sendRequestParam->jsOptionRef);
1056     std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1057     t.detach();
1058     return promise;
1059 }
1060 
NAPI_RemoteObject_sendRequest(napi_env env,napi_callback_info info)1061 static napi_value NAPI_RemoteObject_sendRequest(napi_env env, napi_callback_info info)
1062 {
1063     size_t argc = 4;
1064     size_t argcCallback = 5;
1065     size_t argcPromise = 4;
1066     napi_value argv[ARGV_LENGTH_5] = { 0 };
1067     napi_value thisVar = nullptr;
1068     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1069     NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1070     napi_valuetype valueType = napi_null;
1071     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1072     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1073     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1074     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1075     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1076     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1077     napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1078     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1079 
1080     NAPI_MessageParcel *data = nullptr;
1081     napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
1082     NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1083     NAPI_MessageParcel *reply = nullptr;
1084     status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
1085     NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1086     MessageOption *option = nullptr;
1087     status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
1088     NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1089     int32_t code = 0;
1090     napi_get_value_int32(env, argv[ARGV_INDEX_0], &code);
1091 
1092     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1093     if (argc == argcCallback) {
1094         napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1095         napi_valuetype valuetype = napi_undefined;
1096         napi_typeof(env, argv[argcPromise], &valuetype);
1097         if (valuetype == napi_function) {
1098             return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1099                 reply->GetMessageParcel(), *option, argv);
1100         }
1101     }
1102     return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1103         reply->GetMessageParcel(), *option, argv);
1104 }
1105 
NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,size_t argc,size_t argcCallback,size_t argcPromise,napi_value * argv)1106 napi_value NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,
1107                                                          size_t argc,
1108                                                          size_t argcCallback,
1109                                                          size_t argcPromise,
1110                                                          napi_value* argv)
1111 {
1112     if (argc != argcPromise && argc != argcCallback) {
1113         ZLOGE(LOG_LABEL, "requires 4 or 5 parameters");
1114         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1115     }
1116     napi_valuetype valueType = napi_null;
1117     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1118     if (valueType != napi_number) {
1119         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1120         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1121     }
1122     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1123     if (valueType != napi_object) {
1124         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1125         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1126     }
1127     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1128     if (valueType != napi_object) {
1129         ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
1130         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1131     }
1132     napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1133     if (valueType != napi_object) {
1134         ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
1135         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1136     }
1137     napi_value result = nullptr;
1138     napi_get_undefined(env, &result);
1139     return result;
1140 }
1141 
NAPI_RemoteObject_sendMessageRequest(napi_env env,napi_callback_info info)1142 static napi_value NAPI_RemoteObject_sendMessageRequest(napi_env env, napi_callback_info info)
1143 {
1144     size_t argc = 4;
1145     size_t argcCallback = 5;
1146     size_t argcPromise = 4;
1147     napi_value argv[ARGV_LENGTH_5] = { 0 };
1148     napi_value thisVar = nullptr;
1149     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1150     napi_value checkArgsResult = NAPI_RemoteObject_checkSendMessageRequestArgs(env, argc, argcCallback, argcPromise,
1151                                                                                argv);
1152     if (checkArgsResult == nullptr) {
1153         return checkArgsResult;
1154     }
1155     NAPI_MessageSequence *data = nullptr;
1156     napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
1157     if (status != napi_ok) {
1158         ZLOGE(LOG_LABEL, "failed to get data message sequence");
1159         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1160     }
1161     NAPI_MessageSequence *reply = nullptr;
1162     status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
1163     if (status != napi_ok) {
1164         ZLOGE(LOG_LABEL, "failed to get data message sequence");
1165         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1166     }
1167     MessageOption *option = nullptr;
1168     status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
1169     if (status != napi_ok) {
1170         ZLOGE(LOG_LABEL, "failed to get message option");
1171         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1172     }
1173     int32_t code = 0;
1174     napi_get_value_int32(env, argv[ARGV_INDEX_0], &code);
1175 
1176     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1177     if (argc == argcCallback) {
1178         napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1179         napi_valuetype valuetype = napi_undefined;
1180         napi_typeof(env, argv[argcPromise], &valuetype);
1181         if (valuetype == napi_function) {
1182             return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1183                 reply->GetMessageParcel(), *option, argv);
1184         }
1185     }
1186     return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1187         reply->GetMessageParcel(), *option, argv);
1188 }
1189 
NAPI_RemoteObject_attachLocalInterface(napi_env env,napi_callback_info info)1190 static napi_value NAPI_RemoteObject_attachLocalInterface(napi_env env, napi_callback_info info)
1191 {
1192     size_t argc = 2;
1193     size_t expectedArgc = 2;
1194     napi_value argv[ARGV_LENGTH_2] = { 0 };
1195     napi_value thisVar = nullptr;
1196     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1197     NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameters");
1198     napi_valuetype valueType = napi_null;
1199     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1200     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1201     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1202     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 2");
1203     size_t bufferSize = 0;
1204     size_t maxLen = 40960;
1205     napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], nullptr, 0, &bufferSize);
1206     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1207     char stringValue[bufferSize + 1];
1208     size_t jsStringLength = 0;
1209     napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], stringValue, bufferSize + 1, &jsStringLength);
1210     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1211     std::string descriptor = stringValue;
1212 
1213     NAPIRemoteObjectHolder *holder = nullptr;
1214     napi_unwrap(env, thisVar, (void* *)&holder);
1215     NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1216     holder->attachLocalInterface(argv[ARGV_INDEX_0], descriptor);
1217 
1218     napi_value result = nullptr;
1219     napi_get_undefined(env, &result);
1220     return result;
1221 }
1222 
NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env,size_t argc,napi_value * argv)1223 napi_value NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env, size_t argc, napi_value* argv)
1224 {
1225     size_t expectedArgc = 2;
1226 
1227     if (argc != expectedArgc) {
1228         ZLOGE(LOG_LABEL, "requires 2 parameters");
1229         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1230     }
1231     napi_valuetype valueType = napi_null;
1232     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1233     if (valueType != napi_object) {
1234         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1235         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1236     }
1237     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1238     if (valueType != napi_string) {
1239         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1240         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1241     }
1242     napi_value result = nullptr;
1243     napi_get_undefined(env, &result);
1244     return result;
1245 }
1246 
NAPI_RemoteObject_modifyLocalInterface(napi_env env,napi_callback_info info)1247 static napi_value NAPI_RemoteObject_modifyLocalInterface(napi_env env, napi_callback_info info)
1248 {
1249     size_t argc = 2;
1250     napi_value argv[ARGV_LENGTH_2] = { 0 };
1251     napi_value thisVar = nullptr;
1252     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1253     napi_value checkArgsResult = NAPI_RemoteObject_checkModifyLocalInterfaceArgs(env, argc, argv);
1254     if (checkArgsResult == nullptr) {
1255         return checkArgsResult;
1256     }
1257     size_t bufferSize = 0;
1258     size_t maxLen = 40960;
1259     napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], nullptr, 0, &bufferSize);
1260     if (bufferSize >= maxLen) {
1261         ZLOGE(LOG_LABEL, "string length too large");
1262         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1263     }
1264     char stringValue[bufferSize + 1];
1265     size_t jsStringLength = 0;
1266     napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], stringValue, bufferSize + 1, &jsStringLength);
1267     if (jsStringLength != bufferSize) {
1268         ZLOGE(LOG_LABEL, "string length wrong");
1269         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1270     }
1271     std::string descriptor = stringValue;
1272 
1273     NAPIRemoteObjectHolder *holder = nullptr;
1274     napi_unwrap(env, thisVar, (void* *)&holder);
1275     if (holder == nullptr) {
1276         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1277         return nullptr;
1278     }
1279     holder->attachLocalInterface(argv[ARGV_INDEX_0], descriptor);
1280 
1281     napi_value result = nullptr;
1282     napi_get_undefined(env, &result);
1283     return result;
1284 }
1285 
NAPI_RemoteObject_addDeathRecipient(napi_env env,napi_callback_info info)1286 static napi_value NAPI_RemoteObject_addDeathRecipient(napi_env env, napi_callback_info info)
1287 {
1288     napi_value result = nullptr;
1289     napi_get_boolean(env, false, &result);
1290     return result;
1291 }
1292 
NAPI_RemoteObject_registerDeathRecipient(napi_env env,napi_callback_info info)1293 static napi_value NAPI_RemoteObject_registerDeathRecipient(napi_env env, napi_callback_info info)
1294 {
1295     ZLOGE(LOG_LABEL, "only proxy object permitted");
1296     return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1297 }
1298 
NAPI_RemoteObject_removeDeathRecipient(napi_env env,napi_callback_info info)1299 static napi_value NAPI_RemoteObject_removeDeathRecipient(napi_env env, napi_callback_info info)
1300 {
1301     napi_value result = nullptr;
1302     napi_get_boolean(env, false, &result);
1303     return result;
1304 }
1305 
NAPI_RemoteObject_unregisterDeathRecipient(napi_env env,napi_callback_info info)1306 static napi_value NAPI_RemoteObject_unregisterDeathRecipient(napi_env env, napi_callback_info info)
1307 {
1308     ZLOGE(LOG_LABEL, "only proxy object permitted");
1309     return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1310 }
1311 
NAPI_RemoteObject_isObjectDead(napi_env env,napi_callback_info info)1312 static napi_value NAPI_RemoteObject_isObjectDead(napi_env env, napi_callback_info info)
1313 {
1314     napi_value result = nullptr;
1315     napi_get_boolean(env, false, &result);
1316     return result;
1317 }
1318 
1319 EXTERN_C_START
1320 /*
1321  * function for module exports
1322  */
NAPIRemoteObjectExport(napi_env env,napi_value exports)1323 napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports)
1324 {
1325     const std::string className = "RemoteObject";
1326     napi_property_descriptor properties[] = {
1327         DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteObject_sendRequest),
1328         DECLARE_NAPI_FUNCTION("sendMessageRequest", NAPI_RemoteObject_sendMessageRequest),
1329         DECLARE_NAPI_FUNCTION("getCallingPid", NAPI_RemoteObject_getCallingPid),
1330         DECLARE_NAPI_FUNCTION("getCallingUid", NAPI_RemoteObject_getCallingUid),
1331         DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteObject_getInterfaceDescriptor),
1332         DECLARE_NAPI_FUNCTION("getDescriptor", NAPI_RemoteObject_getDescriptor),
1333         DECLARE_NAPI_FUNCTION("attachLocalInterface", NAPI_RemoteObject_attachLocalInterface),
1334         DECLARE_NAPI_FUNCTION("modifyLocalInterface", NAPI_RemoteObject_modifyLocalInterface),
1335         DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteObject_queryLocalInterface),
1336         DECLARE_NAPI_FUNCTION("getLocalInterface", NAPI_RemoteObject_getLocalInterface),
1337         DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteObject_addDeathRecipient),
1338         DECLARE_NAPI_FUNCTION("registerDeathRecipient", NAPI_RemoteObject_registerDeathRecipient),
1339         DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteObject_removeDeathRecipient),
1340         DECLARE_NAPI_FUNCTION("unregisterDeathRecipient", NAPI_RemoteObject_unregisterDeathRecipient),
1341         DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteObject_isObjectDead),
1342     };
1343     napi_value constructor = nullptr;
1344     napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
1345         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
1346     NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteObject failed");
1347     napi_status status = napi_set_named_property(env, exports, "RemoteObject", constructor);
1348     NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
1349     napi_value global = nullptr;
1350     status = napi_get_global(env, &global);
1351     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
1352     status = napi_set_named_property(env, global, "IPCStubConstructor_", constructor);
1353     NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
1354     return exports;
1355 }
1356 EXTERN_C_END
1357 } // namespace OHOS
1358