• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_remote_object.h"
17 #include <mutex>
18 #include <native_value.h>
19 #include <cstring>
20 #include <thread>
21 #include <unistd.h>
22 #include <uv.h>
23 #include "access_token_adapter.h"
24 #include "hilog/log.h"
25 #include "hitrace_meter.h"
26 #include "ipc_object_proxy.h"
27 #include "ipc_object_stub.h"
28 #include "ipc_skeleton.h"
29 #include "ipc_thread_skeleton.h"
30 #include "ipc_debug.h"
31 #include "ipc_types.h"
32 #include "log_tags.h"
33 #include "napi_message_option.h"
34 #include "napi_message_parcel.h"
35 #include "napi_message_sequence.h"
36 #include "napi_rpc_error.h"
37 #include "rpc_bytrace.h"
38 #include "string_ex.h"
39 
40 static std::atomic<int32_t> bytraceId = 1000;
41 namespace OHOS {
42 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "napi_remoteObject" };
43 
44 static const uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag.
45 
46 template<class T>
ConvertNativeValueTo(NativeValue * value)47 inline T *ConvertNativeValueTo(NativeValue *value)
48 {
49     return (value != nullptr) ? static_cast<T *>(value->GetInterface(T::INTERFACE_ID)) : nullptr;
50 }
51 
52 static NapiError napiErr;
53 
54 static const size_t ARGV_INDEX_0 = 0;
55 static const size_t ARGV_INDEX_1 = 1;
56 static const size_t ARGV_INDEX_2 = 2;
57 static const size_t ARGV_INDEX_3 = 3;
58 
59 /*
60  * The native NAPIRemoteObject act as bridger between js and native.
61  * It received the request from client and pass it js Layer.
62  */
63 class NAPIRemoteObject : public IPCObjectStub {
64 public:
65     NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor);
66 
67     ~NAPIRemoteObject() override;
68 
69     bool CheckObjectLegality() const override;
70 
71     int GetObjectType() const override;
72 
73     int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
74 
75     napi_ref GetJsObjectRef() const;
76 private:
77     napi_env env_ = nullptr;
78     napi_value thisVar_ = nullptr;
79     static napi_value ThenCallback(napi_env env, napi_callback_info info);
80     static napi_value CatchCallback(napi_env env, napi_callback_info info);
81     napi_ref thisVarRef_ = nullptr;
82     struct ThreadLockInfo {
83         std::mutex mutex;
84         std::condition_variable condition;
85         bool ready = false;
86     };
87     struct CallbackParam {
88         napi_env env;
89         napi_ref thisVarRef;
90         uint32_t code;
91         MessageParcel *data;
92         MessageParcel *reply;
93         MessageOption *option;
94         CallingInfo callingInfo;
95         ThreadLockInfo *lockInfo;
96         int result;
97     };
98     int OnJsRemoteRequest(CallbackParam *jsParam);
99 };
100 
101 /*
102  * To ensure a better consistency of the life time of
103  * js RemoteObject and native object, we designed
104  * a container to save the native object.
105  */
106 class NAPIRemoteObjectHolder : public RefBase {
107 public:
108     explicit NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor);
109     ~NAPIRemoteObjectHolder();
110     sptr<NAPIRemoteObject> Get(napi_value object);
111     void Set(sptr<NAPIRemoteObject> object);
112     void attachLocalInterface(napi_value localInterface, std::string &descriptor);
113     napi_value queryLocalInterface(std::string &descriptor);
Lock()114     void Lock()
115     {
116         mutex_.lock();
117     };
118 
Unlock()119     void Unlock()
120     {
121         mutex_.unlock();
122     };
123 
IncAttachCount()124     void IncAttachCount()
125     {
126         ++attachCount_;
127     };
128 
DecAttachCount()129     int32_t DecAttachCount()
130     {
131         if (attachCount_ > 0) {
132             --attachCount_;
133         }
134         return attachCount_;
135     };
136 
GetDescriptor()137     std::u16string GetDescriptor()
138     {
139         return descriptor_;
140     };
141 
142 private:
143     std::mutex mutex_;
144     napi_env env_ = nullptr;
145     std::u16string descriptor_;
146     sptr<NAPIRemoteObject> cachedObject_;
147     napi_ref localInterfaceRef_;
148     int32_t attachCount_;
149 };
150 
NAPIRemoteObjectHolder(napi_env env,const std::u16string & descriptor)151 NAPIRemoteObjectHolder::NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor)
152     : env_(env), descriptor_(descriptor), cachedObject_(nullptr), localInterfaceRef_(nullptr), attachCount_(1)
153 {}
154 
~NAPIRemoteObjectHolder()155 NAPIRemoteObjectHolder::~NAPIRemoteObjectHolder()
156 {
157     // free the reference of object.
158     cachedObject_ = nullptr;
159     if (localInterfaceRef_ != nullptr) {
160         napi_delete_reference(env_, localInterfaceRef_);
161     }
162 }
163 
Get(napi_value jsRemoteObject)164 sptr<NAPIRemoteObject> NAPIRemoteObjectHolder::Get(napi_value jsRemoteObject)
165 {
166     std::lock_guard<std::mutex> lockGuard(mutex_);
167     // grab an strong reference to the object,
168     // so it will not be freed util this reference released.
169     sptr<NAPIRemoteObject> remoteObject = nullptr;
170     if (cachedObject_ != nullptr) {
171         remoteObject = cachedObject_;
172     }
173 
174     if (remoteObject == nullptr) {
175         remoteObject = new NAPIRemoteObject(env_, jsRemoteObject, descriptor_);
176         cachedObject_ = remoteObject;
177     }
178     return remoteObject;
179 }
180 
Set(sptr<NAPIRemoteObject> object)181 void NAPIRemoteObjectHolder::Set(sptr<NAPIRemoteObject> object)
182 {
183     std::lock_guard<std::mutex> lockGuard(mutex_);
184     cachedObject_ = object;
185 }
186 
attachLocalInterface(napi_value localInterface,std::string & descriptor)187 void NAPIRemoteObjectHolder::attachLocalInterface(napi_value localInterface, std::string &descriptor)
188 {
189     if (localInterfaceRef_ != nullptr) {
190         napi_delete_reference(env_, localInterfaceRef_);
191     }
192     napi_create_reference(env_, localInterface, 1, &localInterfaceRef_);
193     descriptor_ = Str8ToStr16(descriptor);
194 }
195 
queryLocalInterface(std::string & descriptor)196 napi_value NAPIRemoteObjectHolder::queryLocalInterface(std::string &descriptor)
197 {
198     if (!descriptor_.empty() && strcmp(Str16ToStr8(descriptor_).c_str(), descriptor.c_str()) == 0) {
199         napi_value ret = nullptr;
200         napi_get_reference_value(env_, localInterfaceRef_, &ret);
201         return ret;
202     }
203     napi_value result = nullptr;
204     napi_get_null(env_, &result);
205     return result;
206 }
207 
RemoteObjectHolderFinalizeCb(napi_env env,void * data,void * hint)208 static void RemoteObjectHolderFinalizeCb(napi_env env, void *data, void *hint)
209 {
210     NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
211     if (holder == nullptr) {
212         ZLOGW(LOG_LABEL, "RemoteObjectHolderFinalizeCb null holder");
213         return;
214     }
215     holder->Lock();
216     int32_t curAttachCount = holder->DecAttachCount();
217     if (curAttachCount == 0) {
218         delete holder;
219     }
220 }
221 
RemoteObjectDetachCb(NativeEngine * engine,void * value,void * hint)222 static void *RemoteObjectDetachCb(NativeEngine *engine, void *value, void *hint)
223 {
224     (void)engine;
225     (void)hint;
226     return value;
227 }
228 
RemoteObjectAttachCb(NativeEngine * engine,void * value,void * hint)229 static NativeValue *RemoteObjectAttachCb(NativeEngine *engine, void *value, void *hint)
230 {
231     (void)hint;
232     NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(value);
233     if (holder == nullptr) {
234         ZLOGE(LOG_LABEL, "holder is nullptr when attach");
235         return nullptr;
236     }
237     holder->Lock();
238     ZLOGI(LOG_LABEL, "create js remote object when attach");
239     napi_env env = reinterpret_cast<napi_env>(engine);
240     // retrieve js remote object constructor
241     napi_value global = nullptr;
242     napi_status status = napi_get_global(env, &global);
243     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
244     napi_value constructor = nullptr;
245     status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
246     NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
247     NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
248     // retrieve descriptor and it's length
249     std::u16string descriptor = holder->GetDescriptor();
250     std::string desc = Str16ToStr8(descriptor);
251     napi_value jsDesc = nullptr;
252     napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
253     // create a new js remote object
254     size_t argc = 1;
255     napi_value argv[1] = { jsDesc };
256     napi_value jsRemoteObject = nullptr;
257     status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
258     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteObject when attach");
259     // retrieve and remove create holder
260     NAPIRemoteObjectHolder *createHolder = nullptr;
261     status = napi_remove_wrap(env, jsRemoteObject, (void **)&createHolder);
262     NAPI_ASSERT(env, status == napi_ok && createHolder != nullptr, "failed to remove create holder when attach");
263     status = napi_wrap(env, jsRemoteObject, holder, RemoteObjectHolderFinalizeCb, nullptr, nullptr);
264     NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed when attach");
265     holder->IncAttachCount();
266     holder->Unlock();
267     return reinterpret_cast<NativeValue *>(jsRemoteObject);
268 }
269 
RemoteObject_JS_Constructor(napi_env env,napi_callback_info info)270 napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
271 {
272     // new napi remote object
273     size_t argc = 2;
274     size_t expectedArgc = 1;
275     napi_value argv[2] = { 0 };
276     napi_value thisVar = nullptr;
277     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
278     NAPI_ASSERT(env, argc >= expectedArgc, "requires at least 1 parameters");
279     napi_valuetype valueType = napi_null;
280     napi_typeof(env, argv[0], &valueType);
281     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
282     size_t bufferSize = 0;
283     size_t maxLen = 40960;
284     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
285     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
286     char stringValue[bufferSize + 1];
287     size_t jsStringLength = 0;
288     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
289     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
290     std::string descriptor = stringValue;
291     auto holder = new NAPIRemoteObjectHolder(env, Str8ToStr16(descriptor));
292     auto nativeObj = ConvertNativeValueTo<NativeObject>(reinterpret_cast<NativeValue *>(thisVar));
293     if (nativeObj == nullptr) {
294         ZLOGE(LOG_LABEL, "Failed to get RemoteObject native object");
295         delete holder;
296         return nullptr;
297     }
298     nativeObj->ConvertToNativeBindingObject(env, RemoteObjectDetachCb, RemoteObjectAttachCb, holder, nullptr);
299     // connect native object to js thisVar
300     napi_status status = napi_wrap(env, thisVar, holder, RemoteObjectHolderFinalizeCb, nullptr, nullptr);
301     NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed");
302     if (NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar) == nullptr) {
303         ZLOGE(LOG_LABEL, "RemoteObject_JS_Constructor create native object failed");
304         return nullptr;
305     }
306     return thisVar;
307 }
308 
309 EXTERN_C_START
310 /*
311  * function for module exports
312  */
NAPIRemoteObjectExport(napi_env env,napi_value exports)313 napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports)
314 {
315     const std::string className = "RemoteObject";
316     napi_property_descriptor properties[] = {
317         DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteObject_sendRequest),
318         DECLARE_NAPI_FUNCTION("sendMessageRequest", NAPI_RemoteObject_sendMessageRequest),
319         DECLARE_NAPI_FUNCTION("getCallingPid", NAPI_RemoteObject_getCallingPid),
320         DECLARE_NAPI_FUNCTION("getCallingUid", NAPI_RemoteObject_getCallingUid),
321         DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteObject_getInterfaceDescriptor),
322         DECLARE_NAPI_FUNCTION("getDescriptor", NAPI_RemoteObject_getDescriptor),
323         DECLARE_NAPI_FUNCTION("attachLocalInterface", NAPI_RemoteObject_attachLocalInterface),
324         DECLARE_NAPI_FUNCTION("modifyLocalInterface", NAPI_RemoteObject_modifyLocalInterface),
325         DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteObject_queryLocalInterface),
326         DECLARE_NAPI_FUNCTION("getLocalInterface", NAPI_RemoteObject_getLocalInterface),
327         DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteObject_addDeathRecipient),
328         DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteObject_removeDeathRecipient),
329         DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteObject_isObjectDead),
330     };
331     napi_value constructor = nullptr;
332     napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
333         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
334     NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteObject failed");
335     napi_status status = napi_set_named_property(env, exports, "RemoteObject", constructor);
336     NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
337     napi_value global = nullptr;
338     status = napi_get_global(env, &global);
339     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
340     status = napi_set_named_property(env, global, "IPCStubConstructor_", constructor);
341     NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
342     return exports;
343 }
344 EXTERN_C_END
345 
NAPIRemoteObject(napi_env env,napi_value thisVar,const std::u16string & descriptor)346 NAPIRemoteObject::NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor)
347     : IPCObjectStub(descriptor)
348 {
349     env_ = env;
350     thisVar_ = thisVar;
351     napi_create_reference(env, thisVar_, 1, &thisVarRef_);
352     NAPI_ASSERT_RETURN_VOID(env, thisVarRef_ != nullptr, "failed to create ref to js RemoteObject");
353 }
354 
~NAPIRemoteObject()355 NAPIRemoteObject::~NAPIRemoteObject()
356 {
357     ZLOGI(LOG_LABEL, "NAPIRemoteObject Destructor");
358     if (thisVarRef_ != nullptr) {
359         napi_status status = napi_delete_reference(env_, thisVarRef_);
360         NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js RemoteObject");
361         thisVarRef_ = nullptr;
362     }
363 }
364 
CheckObjectLegality() const365 bool NAPIRemoteObject::CheckObjectLegality() const
366 {
367     return true;
368 }
369 
GetObjectType() const370 int NAPIRemoteObject::GetObjectType() const
371 {
372     return OBJECT_TYPE_JAVASCRIPT;
373 }
374 
GetJsObjectRef() const375 napi_ref NAPIRemoteObject::GetJsObjectRef() const
376 {
377     return thisVarRef_;
378 }
379 
NAPI_RemoteObject_getCallingInfo(CallingInfo & newCallingInfoParam)380 void NAPI_RemoteObject_getCallingInfo(CallingInfo &newCallingInfoParam)
381 {
382     newCallingInfoParam.callingPid = IPCSkeleton::GetCallingPid();
383     newCallingInfoParam.callingUid = IPCSkeleton::GetCallingUid();
384     newCallingInfoParam.callingTokenId = IPCSkeleton::GetCallingTokenID();
385     newCallingInfoParam.callingDeviceID = IPCSkeleton::GetCallingDeviceID();
386     newCallingInfoParam.localDeviceID = IPCSkeleton::GetLocalDeviceID();
387     newCallingInfoParam.isLocalCalling = IPCSkeleton::IsLocalCalling();
388     newCallingInfoParam.activeStatus = IRemoteInvoker::ACTIVE_INVOKER;
389 };
390 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)391 int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
392 {
393     ZLOGI(LOG_LABEL, "enter OnRemoteRequest");
394     if (code == DUMP_TRANSACTION) {
395         ZLOGE(LOG_LABEL, "DUMP_TRANSACTION data size:%zu", data.GetReadableBytes());
396     }
397     std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
398     CallbackParam *param = new CallbackParam {
399         .env = env_,
400         .thisVarRef = thisVarRef_,
401         .code = code,
402         .data = &data,
403         .reply = &reply,
404         .option = &option,
405         .lockInfo = lockInfo.get(),
406         .result = 0
407     };
408 
409     NAPI_RemoteObject_getCallingInfo(param->callingInfo);
410     ZLOGI(LOG_LABEL, "callingPid:%{public}u, callingUid:%{public}u,"
411         "callingDeviceID:%{public}s, localDeviceId:%{public}s, localCalling:%{public}d",
412         param->callingInfo.callingPid, param->callingInfo.callingUid,
413         param->callingInfo.callingDeviceID.c_str(), param->callingInfo.localDeviceID.c_str(),
414         param->callingInfo.isLocalCalling);
415     int ret = OnJsRemoteRequest(param);
416     ZLOGI(LOG_LABEL, "OnJsRemoteRequest done, ret:%{public}d", ret);
417     return ret;
418 }
419 
ThenCallback(napi_env env,napi_callback_info info)420 napi_value NAPIRemoteObject::ThenCallback(napi_env env, napi_callback_info info)
421 {
422     ZLOGI(LOG_LABEL, "call js onRemoteRequest done");
423     size_t argc = 1;
424     napi_value argv[1] = {nullptr};
425     void* data = nullptr;
426     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
427     CallbackParam *param = static_cast<CallbackParam *>(data);
428     bool result = false;
429     napi_get_value_bool(param->env, argv[0], &result);
430     if (!result) {
431         ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s", result ? "true" : "false");
432         param->result = ERR_UNKNOWN_TRANSACTION;
433     } else {
434         param->result = ERR_NONE;
435     }
436     std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
437     param->lockInfo->ready = true;
438     param->lockInfo->condition.notify_all();
439     napi_value res;
440     napi_get_undefined(env, &res);
441     return res;
442 }
443 
CatchCallback(napi_env env,napi_callback_info info)444 napi_value NAPIRemoteObject::CatchCallback(napi_env env, napi_callback_info info)
445 {
446     ZLOGI(LOG_LABEL, "Async onReomteReuqest's return_val is rejected");
447     size_t argc = 1;
448     napi_value argv[1] = {nullptr};
449     void* data = nullptr;
450     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
451     CallbackParam *param = static_cast<CallbackParam *>(data);
452     param->result = ERR_UNKNOWN_TRANSACTION;
453     std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
454     param->lockInfo->ready = true;
455     param->lockInfo->condition.notify_all();
456     napi_value res;
457     napi_get_undefined(env, &res);
458     return res;
459 }
460 
NAPI_RemoteObject_saveOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)461 void NAPI_RemoteObject_saveOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
462 {
463     napi_value global = nullptr;
464     napi_get_global(env, &global);
465     napi_get_named_property(env, global, "callingPid_", &oldCallingInfo.callingPid);
466     napi_get_named_property(env, global, "callingUid_", &oldCallingInfo.callingUid);
467     napi_get_named_property(env, global, "callingTokenId_", &oldCallingInfo.callingTokenId);
468     napi_get_named_property(env, global, "callingDeviceID_", &oldCallingInfo.callingDeviceID);
469     napi_get_named_property(env, global, "localDeviceID_", &oldCallingInfo.localDeviceID);
470     napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
471     napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
472     napi_get_named_property(env, global, "activeStatus_", &oldCallingInfo.activeStatus);
473 }
474 
NAPI_RemoteObject_setNewCallingInfo(napi_env env,const CallingInfo & newCallingInfoParam)475 void NAPI_RemoteObject_setNewCallingInfo(napi_env env, const CallingInfo &newCallingInfoParam)
476 {
477     napi_value global = nullptr;
478     napi_get_global(env, &global);
479     napi_value newPid;
480     napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingPid), &newPid);
481     napi_set_named_property(env, global, "callingPid_", newPid);
482     napi_value newUid;
483     napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingUid), &newUid);
484     napi_set_named_property(env, global, "callingUid_", newUid);
485     napi_value newCallingTokenId;
486     napi_create_uint32(env, newCallingInfoParam.callingTokenId, &newCallingTokenId);
487     napi_set_named_property(env, global, "callingTokenId_", newCallingTokenId);
488     napi_value newDeviceID;
489     napi_create_string_utf8(env, newCallingInfoParam.callingDeviceID.c_str(), NAPI_AUTO_LENGTH, &newDeviceID);
490     napi_set_named_property(env, global, "callingDeviceID_", newDeviceID);
491     napi_value newLocalDeviceID;
492     napi_create_string_utf8(env, newCallingInfoParam.localDeviceID.c_str(), NAPI_AUTO_LENGTH, &newLocalDeviceID);
493     napi_set_named_property(env, global, "localDeviceID_", newLocalDeviceID);
494     napi_value newIsLocalCalling;
495     napi_get_boolean(env, newCallingInfoParam.isLocalCalling, &newIsLocalCalling);
496     napi_set_named_property(env, global, "isLocalCalling_", newIsLocalCalling);
497     napi_value newActiveStatus;
498     napi_create_int32(env, newCallingInfoParam.activeStatus, &newActiveStatus);
499     napi_set_named_property(env, global, "activeStatus_", newActiveStatus);
500 }
501 
NAPI_RemoteObject_resetOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)502 void NAPI_RemoteObject_resetOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
503 {
504     napi_value global = nullptr;
505     napi_get_global(env, &global);
506     napi_set_named_property(env, global, "callingPid_", oldCallingInfo.callingPid);
507     napi_set_named_property(env, global, "callingUid_", oldCallingInfo.callingUid);
508     napi_set_named_property(env, global, "callingTokenId_", oldCallingInfo.callingTokenId);
509     napi_set_named_property(env, global, "callingDeviceID_", oldCallingInfo.callingDeviceID);
510     napi_set_named_property(env, global, "localDeviceID_", oldCallingInfo.localDeviceID);
511     napi_set_named_property(env, global, "isLocalCalling_", oldCallingInfo.isLocalCalling);
512     napi_set_named_property(env, global, "activeStatus_", oldCallingInfo.activeStatus);
513 }
514 
OnJsRemoteRequest(CallbackParam * jsParam)515 int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
516 {
517     uv_loop_s *loop = nullptr;
518     napi_get_uv_event_loop(env_, &loop);
519 
520     uv_work_t *work = new(std::nothrow) uv_work_t;
521     if (work == nullptr) {
522         ZLOGE(LOG_LABEL, "failed to new uv_work_t");
523         delete jsParam;
524         return -1;
525     }
526     work->data = reinterpret_cast<void *>(jsParam);
527     ZLOGI(LOG_LABEL, "start nv queue work loop");
528     uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
529         ZLOGI(LOG_LABEL, "enter thread pool");
530         CallbackParam *param = reinterpret_cast<CallbackParam *>(work->data);
531         napi_value onRemoteRequest = nullptr;
532         napi_value thisVar = nullptr;
533         napi_get_reference_value(param->env, param->thisVarRef, &thisVar);
534         if (thisVar == nullptr) {
535             ZLOGE(LOG_LABEL, "thisVar is null");
536             param->result = -1;
537             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
538             param->lockInfo->ready = true;
539             param->lockInfo->condition.notify_all();
540             return;
541         }
542         napi_get_named_property(param->env, thisVar, "onRemoteMessageRequest", &onRemoteRequest);
543         if (onRemoteRequest == nullptr) {
544             ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
545             param->result = -1;
546             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
547             param->lockInfo->ready = true;
548             param->lockInfo->condition.notify_all();
549             return;
550         }
551         napi_valuetype type = napi_undefined;
552         napi_typeof(param->env, onRemoteRequest, &type);
553         bool isOnRemoteMessageRequest = true;
554         if (type != napi_function) {
555             napi_get_named_property(param->env, thisVar, "onRemoteRequest", &onRemoteRequest);
556             if (onRemoteRequest == nullptr) {
557                 ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
558                 param->result = -1;
559                 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
560                 param->lockInfo->ready = true;
561                 param->lockInfo->condition.notify_all();
562                 return;
563             }
564             isOnRemoteMessageRequest = false;
565         }
566         napi_value jsCode;
567         napi_create_uint32(param->env, param->code, &jsCode);
568 
569         napi_value global = nullptr;
570         napi_get_global(param->env, &global);
571         if (global == nullptr) {
572             ZLOGE(LOG_LABEL, "get napi global failed");
573             param->result = -1;
574             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
575             param->lockInfo->ready = true;
576             param->lockInfo->condition.notify_all();
577             return;
578         }
579         napi_value jsOptionConstructor = nullptr;
580         napi_get_named_property(param->env, global, "IPCOptionConstructor_", &jsOptionConstructor);
581         if (jsOptionConstructor == nullptr) {
582             ZLOGE(LOG_LABEL, "jsOption constructor is null");
583             param->result = -1;
584             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
585             param->lockInfo->ready = true;
586             param->lockInfo->condition.notify_all();
587             return;
588         }
589         napi_value jsOption;
590         size_t argc = 2;
591         napi_value flags = nullptr;
592         napi_create_int32(param->env, param->option->GetFlags(), &flags);
593         napi_value waittime = nullptr;
594         napi_create_int32(param->env, param->option->GetWaitTime(), &waittime);
595         napi_value argv[2] = { flags, waittime };
596         napi_new_instance(param->env, jsOptionConstructor, argc, argv, &jsOption);
597         if (jsOption == nullptr) {
598             ZLOGE(LOG_LABEL, "new jsOption failed");
599             param->result = -1;
600             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
601             param->lockInfo->ready = true;
602             param->lockInfo->condition.notify_all();
603             return;
604         }
605         napi_value jsParcelConstructor = nullptr;
606         if (isOnRemoteMessageRequest) {
607             napi_get_named_property(param->env, global, "IPCSequenceConstructor_", &jsParcelConstructor);
608         } else {
609             napi_get_named_property(param->env, global, "IPCParcelConstructor_", &jsParcelConstructor);
610         }
611         if (jsParcelConstructor == nullptr) {
612             ZLOGE(LOG_LABEL, "jsParcel constructor is null");
613             param->result = -1;
614             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
615             param->lockInfo->ready = true;
616             param->lockInfo->condition.notify_all();
617             return;
618         }
619         napi_value jsData;
620         napi_value dataParcel;
621         napi_create_object(param->env, &dataParcel);
622         napi_wrap(param->env, dataParcel, param->data,
623             [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
624         if (dataParcel == nullptr) {
625             ZLOGE(LOG_LABEL, "create js object for data parcel address failed");
626             param->result = -1;
627             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
628             param->lockInfo->ready = true;
629             param->lockInfo->condition.notify_all();
630             return;
631         }
632         size_t argc3 = 1;
633         napi_value argv3[1] = { dataParcel };
634         napi_new_instance(param->env, jsParcelConstructor, argc3, argv3, &jsData);
635         if (jsData == nullptr) {
636             ZLOGE(LOG_LABEL, "create js data parcel failed");
637             param->result = -1;
638             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
639             param->lockInfo->ready = true;
640             param->lockInfo->condition.notify_all();
641             return;
642         }
643         napi_value jsReply;
644         napi_value replyParcel;
645         napi_create_object(param->env, &replyParcel);
646         napi_wrap(param->env, replyParcel, param->reply,
647             [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
648         if (replyParcel == nullptr) {
649             ZLOGE(LOG_LABEL, "create js object for reply parcel address failed");
650             param->result = -1;
651             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
652             param->lockInfo->ready = true;
653             param->lockInfo->condition.notify_all();
654             return;
655         }
656         size_t argc4 = 1;
657         napi_value argv4[1] = { replyParcel };
658         napi_new_instance(param->env, jsParcelConstructor, argc4, argv4, &jsReply);
659         if (jsReply == nullptr) {
660             ZLOGE(LOG_LABEL, "create js reply parcel failed");
661             param->result = -1;
662             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
663             param->lockInfo->ready = true;
664             param->lockInfo->condition.notify_all();
665             return;
666         }
667         NAPI_CallingInfo oldCallingInfo;
668         NAPI_RemoteObject_saveOldCallingInfo(param->env, oldCallingInfo);
669         NAPI_RemoteObject_setNewCallingInfo(param->env, param->callingInfo);
670         // start to call onRemoteRequest
671         size_t argc2 = 4;
672         napi_value argv2[] = { jsCode, jsData, jsReply, jsOption };
673         napi_value return_val;
674         napi_status ret = napi_call_function(param->env, thisVar, onRemoteRequest, argc2, argv2, &return_val);
675         // Reset old calling pid, uid, device id
676         NAPI_RemoteObject_resetOldCallingInfo(param->env, oldCallingInfo);
677 
678         do {
679             if (ret != napi_ok) {
680                 ZLOGE(LOG_LABEL, "OnRemoteRequest got exception");
681                 param->result = ERR_UNKNOWN_TRANSACTION;
682                 break;
683             }
684 
685             ZLOGD(LOG_LABEL, "call js onRemoteRequest done");
686             // Check whether return_val is Promise
687             bool returnIsPromise = false;//
688             napi_is_promise(param->env, return_val, &returnIsPromise);
689             if (!returnIsPromise) {
690                 ZLOGD(LOG_LABEL, "onRemoteRequest is synchronous");
691                 bool result = false;
692                 napi_get_value_bool(param->env, return_val, &result);
693                 if (!result) {
694                     ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s", result ? "true" : "false");
695                     param->result = ERR_UNKNOWN_TRANSACTION;
696                 } else {
697                     param->result = ERR_NONE;
698                 }
699                 break;
700             }
701 
702             ZLOGD(LOG_LABEL, "onRemoteRequest is asynchronous");
703             // Create promiseThen
704             napi_value promiseThen = nullptr;
705             napi_get_named_property(param->env, return_val, "then", &promiseThen);
706             if (promiseThen == nullptr) {
707                 ZLOGE(LOG_LABEL, "get promiseThen failed");
708                 param->result = -1;
709                 break;
710             }
711             napi_value then_value;
712             ret = napi_create_function(param->env, "thenCallback", NAPI_AUTO_LENGTH, ThenCallback, param, &then_value);
713             if (ret != napi_ok) {
714                 ZLOGE(LOG_LABEL, "thenCallback got exception");
715                 param->result = ERR_UNKNOWN_TRANSACTION;
716                 break;
717             }
718             // Start to call promiseThen
719             napi_value then_return_value;
720             ret = napi_call_function(param->env, return_val, promiseThen, 1, &then_value, &then_return_value);
721             if (ret != napi_ok) {
722                 ZLOGE(LOG_LABEL, "PromiseThen got exception");
723                 param->result = ERR_UNKNOWN_TRANSACTION;
724                 break;
725             }
726             // Create promiseCatch
727             napi_value promiseCatch = nullptr;
728             napi_get_named_property(param->env, return_val, "catch", &promiseCatch);
729             if (promiseCatch == nullptr) {
730                 ZLOGE(LOG_LABEL, "get promiseCatch failed");
731                 param->result = -1;
732                 break;
733             }
734             napi_value catch_value;
735             ret = napi_create_function(param->env, "catchCallback",
736                 NAPI_AUTO_LENGTH, CatchCallback, param, &catch_value);
737             if (ret != napi_ok) {
738                 ZLOGE(LOG_LABEL, "catchCallback got exception");
739                 param->result = ERR_UNKNOWN_TRANSACTION;
740                 break;
741             }
742             // Start to call promiseCatch
743             napi_value catch_return_value;
744             ret = napi_call_function(param->env, return_val, promiseCatch, 1, &catch_value, &catch_return_value);
745             if (ret != napi_ok) {
746                 ZLOGE(LOG_LABEL, "PromiseCatch got exception");
747                 param->result = ERR_UNKNOWN_TRANSACTION;
748                 break;
749             }
750             return;
751         } while (0);
752 
753         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
754         param->lockInfo->ready = true;
755         param->lockInfo->condition.notify_all();
756     });
757     std::unique_lock<std::mutex> lock(jsParam->lockInfo->mutex);
758     jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
759     int ret = jsParam->result;
760     delete jsParam;
761     delete work;
762     return ret;
763 }
764 
NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env,napi_value jsRemoteProxy)765 NAPIRemoteProxyHolder *NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env, napi_value jsRemoteProxy)
766 {
767     NAPIRemoteProxyHolder *proxyHolder = nullptr;
768     napi_unwrap(env, jsRemoteProxy, (void **)&proxyHolder);
769     NAPI_ASSERT(env, proxyHolder != nullptr, "failed to get napi remote proxy holder");
770     return proxyHolder;
771 }
772 
NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env,const sptr<IRemoteObject> target)773 napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteObject> target)
774 {
775     if (target == nullptr) {
776         ZLOGE(LOG_LABEL, "RemoteObject is null");
777         return nullptr;
778     }
779 
780     if (target->CheckObjectLegality()) {
781         IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
782         ZLOGI(LOG_LABEL, "object type:%{public}d", tmp->GetObjectType());
783         if (tmp->GetObjectType() == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT) {
784             ZLOGI(LOG_LABEL, "napi create js remote object");
785             sptr<NAPIRemoteObject> object = static_cast<NAPIRemoteObject *>(target.GetRefPtr());
786             // retrieve js remote object constructor
787             napi_value global = nullptr;
788             napi_status status = napi_get_global(env, &global);
789             NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
790             napi_value constructor = nullptr;
791             status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
792             NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
793             NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
794             // retrieve descriptor and it's length
795             std::u16string descriptor = object->GetObjectDescriptor();
796             std::string desc = Str16ToStr8(descriptor);
797             napi_value jsDesc = nullptr;
798             napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
799             // create a new js remote object
800             size_t argc = 1;
801             napi_value argv[1] = { jsDesc };
802             napi_value jsRemoteObject = nullptr;
803             status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
804             NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteObject");
805             // retrieve holder and set object
806             NAPIRemoteObjectHolder *holder = nullptr;
807             napi_unwrap(env, jsRemoteObject, (void **)&holder);
808             NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
809             holder->Set(object);
810             return jsRemoteObject;
811         }
812     }
813 
814     napi_value global = nullptr;
815     napi_status status = napi_get_global(env, &global);
816     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
817     napi_value constructor = nullptr;
818     status = napi_get_named_property(env, global, "IPCProxyConstructor_", &constructor);
819     NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
820     napi_value jsRemoteProxy;
821     status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
822     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteProxy");
823     NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
824     proxyHolder->object_ = target;
825     proxyHolder->list_ = new NAPIDeathRecipientList();
826 
827     return jsRemoteProxy;
828 }
829 
NAPI_ohos_rpc_getNativeRemoteObject(napi_env env,napi_value object)830 sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
831 {
832     if (object != nullptr) {
833         napi_value global = nullptr;
834         napi_status status = napi_get_global(env, &global);
835         NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
836         napi_value stubConstructor = nullptr;
837         status = napi_get_named_property(env, global, "IPCStubConstructor_", &stubConstructor);
838         NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
839         bool instanceOfStub = false;
840         status = napi_instanceof(env, object, stubConstructor, &instanceOfStub);
841         NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
842         if (instanceOfStub) {
843             NAPIRemoteObjectHolder *holder = nullptr;
844             napi_unwrap(env, object, (void **)&holder);
845             NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
846             return holder != nullptr ? holder->Get(object) : nullptr;
847         }
848 
849         napi_value proxyConstructor = nullptr;
850         status = napi_get_named_property(env, global, "IPCProxyConstructor_", &proxyConstructor);
851         NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
852         bool instanceOfProxy = false;
853         status = napi_instanceof(env, object, proxyConstructor, &instanceOfProxy);
854         NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
855         if (instanceOfProxy) {
856             NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
857             return holder != nullptr ? holder->object_ : nullptr;
858         }
859     }
860     return nullptr;
861 }
862 
NAPI_IPCSkeleton_getContextObject(napi_env env,napi_callback_info info)863 napi_value NAPI_IPCSkeleton_getContextObject(napi_env env, napi_callback_info info)
864 {
865     sptr<IRemoteObject> object = IPCSkeleton::GetContextObject();
866     if (object == nullptr) {
867         ZLOGE(LOG_LABEL, "fatal error, could not get registry object");
868         return nullptr;
869     }
870     return NAPI_ohos_rpc_CreateJsRemoteObject(env, object);
871 }
872 
NAPI_IPCSkeleton_getCallingPid(napi_env env,napi_callback_info info)873 napi_value NAPI_IPCSkeleton_getCallingPid(napi_env env, napi_callback_info info)
874 {
875     napi_value global = nullptr;
876     napi_get_global(env, &global);
877     napi_value napiActiveStatus = nullptr;
878     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
879     if (napiActiveStatus != nullptr) {
880         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
881         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
882         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
883             napi_value callingPid = nullptr;
884             napi_get_named_property(env, global, "callingPid_", &callingPid);
885             return callingPid;
886         }
887     }
888     pid_t pid = getpid();
889     napi_value result = nullptr;
890     napi_create_int32(env, static_cast<int32_t>(pid), &result);
891     return result;
892 }
893 
NAPI_IPCSkeleton_getCallingUid(napi_env env,napi_callback_info info)894 napi_value NAPI_IPCSkeleton_getCallingUid(napi_env env, napi_callback_info info)
895 {
896     napi_value global = nullptr;
897     napi_get_global(env, &global);
898     napi_value napiActiveStatus = nullptr;
899     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
900     if (napiActiveStatus != nullptr) {
901         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
902         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
903         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
904             napi_value callingUid = nullptr;
905             napi_get_named_property(env, global, "callingUid_", &callingUid);
906             return callingUid;
907         }
908     }
909     uint32_t uid = getuid();
910     napi_value result = nullptr;
911     napi_create_int32(env, static_cast<int32_t>(uid), &result);
912     return result;
913 }
914 
NAPI_IPCSkeleton_getCallingTokenId(napi_env env,napi_callback_info info)915 napi_value NAPI_IPCSkeleton_getCallingTokenId(napi_env env, napi_callback_info info)
916 {
917     napi_value global = nullptr;
918     napi_get_global(env, &global);
919     napi_value napiActiveStatus = nullptr;
920     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
921     if (napiActiveStatus != nullptr) {
922         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
923         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
924         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
925             napi_value callingTokenId = nullptr;
926             napi_get_named_property(env, global, "callingTokenId_", &callingTokenId);
927             return callingTokenId;
928         }
929     }
930     uint64_t TokenId = RpcGetSelfTokenID();
931     napi_value result = nullptr;
932     napi_create_uint32(env, static_cast<uint32_t>(TokenId), &result);
933     return result;
934 }
935 
NAPI_IPCSkeleton_getCallingDeviceID(napi_env env,napi_callback_info info)936 napi_value NAPI_IPCSkeleton_getCallingDeviceID(napi_env env, napi_callback_info info)
937 {
938     napi_value global = nullptr;
939     napi_get_global(env, &global);
940     napi_value napiActiveStatus = nullptr;
941     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
942     if (napiActiveStatus != nullptr) {
943         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
944         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
945         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
946             napi_value callingDeviceID = nullptr;
947             napi_get_named_property(env, global, "callingDeviceID_", &callingDeviceID);
948             return callingDeviceID;
949         }
950     }
951     napi_value result = nullptr;
952     napi_create_string_utf8(env, "", 0, &result);
953     return result;
954 }
955 
NAPI_IPCSkeleton_getLocalDeviceID(napi_env env,napi_callback_info info)956 napi_value NAPI_IPCSkeleton_getLocalDeviceID(napi_env env, napi_callback_info info)
957 {
958     napi_value global = nullptr;
959     napi_get_global(env, &global);
960     napi_value napiActiveStatus = nullptr;
961     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
962     if (napiActiveStatus != nullptr) {
963         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
964         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
965         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
966             napi_value localDeviceID = nullptr;
967             napi_get_named_property(env, global, "localDeviceID_", &localDeviceID);
968             return localDeviceID;
969         }
970     }
971     napi_value result = nullptr;
972     napi_create_string_utf8(env, "", 0, &result);
973     return result;
974 }
975 
NAPI_IPCSkeleton_isLocalCalling(napi_env env,napi_callback_info info)976 napi_value NAPI_IPCSkeleton_isLocalCalling(napi_env env, napi_callback_info info)
977 {
978     napi_value global = nullptr;
979     napi_get_global(env, &global);
980     napi_value napiActiveStatus = nullptr;
981     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
982     if (napiActiveStatus != nullptr) {
983         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
984         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
985         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
986             napi_value isLocalCalling = nullptr;
987             napi_get_named_property(env, global, "isLocalCalling_", &isLocalCalling);
988             return isLocalCalling;
989         }
990     }
991     napi_value result = nullptr;
992     napi_get_boolean(env, true, &result);
993     return result;
994 }
995 
NAPI_IPCSkeleton_flushCommands(napi_env env,napi_callback_info info)996 napi_value NAPI_IPCSkeleton_flushCommands(napi_env env, napi_callback_info info)
997 {
998     size_t argc = 1;
999     napi_value argv[1] = {0};
1000     napi_value thisVar = nullptr;
1001     void *data = nullptr;
1002     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1003     NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
1004 
1005     napi_valuetype valueType = napi_null;
1006     napi_typeof(env, argv[0], &valueType);
1007     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1008 
1009     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
1010     int32_t result = IPCSkeleton::FlushCommands(target);
1011     napi_value napiValue = nullptr;
1012     NAPI_CALL(env, napi_create_int32(env, result, &napiValue));
1013     return napiValue;
1014 }
1015 
NAPI_IPCSkeleton_flushCmdBuffer(napi_env env,napi_callback_info info)1016 napi_value NAPI_IPCSkeleton_flushCmdBuffer(napi_env env, napi_callback_info info)
1017 {
1018     size_t argc = 1;
1019     napi_value argv[1] = {0};
1020     napi_value thisVar = nullptr;
1021     void *data = nullptr;
1022     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1023     if (argc != 1) {
1024         ZLOGE(LOG_LABEL, "requires 1 parameter");
1025         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1026     }
1027 
1028     napi_valuetype valueType = napi_null;
1029     napi_typeof(env, argv[0], &valueType);
1030     if (valueType != napi_object) {
1031         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1032         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1033     }
1034 
1035     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
1036     IPCSkeleton::FlushCommands(target);
1037     napi_value napiValue = nullptr;
1038     napi_get_undefined(env, &napiValue);
1039     return napiValue;
1040 }
1041 
NAPI_IPCSkeleton_resetCallingIdentity(napi_env env,napi_callback_info info)1042 napi_value NAPI_IPCSkeleton_resetCallingIdentity(napi_env env, napi_callback_info info)
1043 {
1044     napi_value global = nullptr;
1045     napi_get_global(env, &global);
1046     napi_value napiActiveStatus = nullptr;
1047     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1048     int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1049     napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1050     if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1051         napi_value result = nullptr;
1052         napi_create_string_utf8(env, "", 0, &result);
1053         return result;
1054     }
1055     napi_value napiCallingPid = nullptr;
1056     napi_get_named_property(env, global, "callingPid_", &napiCallingPid);
1057     int32_t callerPid;
1058     napi_get_value_int32(env, napiCallingPid, &callerPid);
1059     napi_value napiCallingUid = nullptr;
1060     napi_get_named_property(env, global, "callingUid_", &napiCallingUid);
1061     uint32_t callerUid;
1062     napi_get_value_uint32(env, napiCallingUid, &callerUid);
1063     napi_value napiIsLocalCalling = nullptr;
1064     napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1065     bool isLocalCalling = true;
1066     napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1067     if (isLocalCalling) {
1068         int64_t identity = (static_cast<uint64_t>(callerUid) << PID_LEN) | static_cast<uint64_t>(callerPid);
1069         callerPid = getpid();
1070         callerUid = getuid();
1071         napi_value newCallingPid;
1072         napi_create_int32(env, callerPid, &newCallingPid);
1073         napi_set_named_property(env, global, "callingPid_", newCallingPid);
1074         napi_value newCallingUid;
1075         napi_create_uint32(env, callerUid, &newCallingUid);
1076         napi_set_named_property(env, global, "callingUid_", newCallingUid);
1077         napi_value result = nullptr;
1078         napi_create_string_utf8(env, std::to_string(identity).c_str(), NAPI_AUTO_LENGTH, &result);
1079         return result;
1080     } else {
1081         napi_value napiCallingDeviceID = nullptr;
1082         napi_get_named_property(env, global, "callingDeviceID_", &napiCallingDeviceID);
1083         size_t bufferSize = 0;
1084         size_t maxLen = 4096;
1085         napi_get_value_string_utf8(env, napiCallingDeviceID, nullptr, 0, &bufferSize);
1086         NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1087         char stringValue[bufferSize + 1];
1088         size_t jsStringLength = 0;
1089         napi_get_value_string_utf8(env, napiCallingDeviceID, stringValue, bufferSize + 1, &jsStringLength);
1090         NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1091         std::string callerDeviceID = stringValue;
1092         std::string token = std::to_string(((static_cast<uint64_t>(callerUid) << PID_LEN)
1093             | static_cast<uint64_t>(callerPid)));
1094         std::string identity = callerDeviceID + token;
1095         callerUid = getuid();
1096         napi_value newCallingUid;
1097         napi_create_uint32(env, callerUid, &newCallingUid);
1098         napi_set_named_property(env, global, "callingUid_", newCallingUid);
1099         callerPid = getpid();
1100         napi_value newCallingPid;
1101         napi_create_int32(env, callerPid, &newCallingPid);
1102         napi_set_named_property(env, global, "callingPid_", newCallingPid);
1103         napi_value newCallingDeviceID = nullptr;
1104         napi_get_named_property(env, global, "localDeviceID_", &newCallingDeviceID);
1105         napi_set_named_property(env, global, "callingDeviceID_", newCallingDeviceID);
1106 
1107         napi_value result = nullptr;
1108         napi_create_string_utf8(env, identity.c_str(), NAPI_AUTO_LENGTH, &result);
1109         return result;
1110     }
1111 }
1112 
NAPI_IPCSkeleton_setCallingIdentity(napi_env env,napi_callback_info info)1113 napi_value NAPI_IPCSkeleton_setCallingIdentity(napi_env env, napi_callback_info info)
1114 {
1115     napi_value global = nullptr;
1116     napi_get_global(env, &global);
1117     napi_value napiActiveStatus = nullptr;
1118     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1119     int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1120     napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1121     if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1122         napi_value result = nullptr;
1123         napi_get_boolean(env, true, &result);
1124         return result;
1125     }
1126 
1127     napi_value retValue = nullptr;
1128     napi_get_boolean(env, false, &retValue);
1129 
1130     size_t argc = 1;
1131     size_t expectedArgc = 1;
1132     napi_value argv[1] = { 0 };
1133     napi_value thisVar = nullptr;
1134     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1135     NAPI_ASSERT_BASE(env, argc == expectedArgc, "requires 1 parameters", retValue);
1136     napi_valuetype valueType = napi_null;
1137     napi_typeof(env, argv[0], &valueType);
1138     NAPI_ASSERT_BASE(env, valueType == napi_string, "type mismatch for parameter 1", retValue);
1139     size_t bufferSize = 0;
1140     size_t maxLen = 40960;
1141     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1142     NAPI_ASSERT_BASE(env, bufferSize < maxLen, "string length too large", retValue);
1143     char stringValue[bufferSize + 1];
1144     size_t jsStringLength = 0;
1145     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1146     NAPI_ASSERT_BASE(env, jsStringLength == bufferSize, "string length wrong", retValue);
1147 
1148     std::string identity = stringValue;
1149     napi_value napiIsLocalCalling = nullptr;
1150     napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1151     bool isLocalCalling = true;
1152     napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1153     napi_value result;
1154     if (isLocalCalling) {
1155         if (identity.empty()) {
1156             napi_get_boolean(env, false, &result);
1157             return result;
1158         }
1159 
1160         int64_t token = std::stoll(identity);
1161         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1162         int callerPid = static_cast<int>(token);
1163         napi_value napiCallingPid;
1164         napi_create_int32(env, callerPid, &napiCallingPid);
1165         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1166         napi_value napiCallingUid;
1167         napi_create_int32(env, callerUid, &napiCallingUid);
1168         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1169         napi_get_boolean(env, true, &result);
1170         return result;
1171     } else {
1172         if (identity.empty() || identity.length() <= DEVICEID_LENGTH) {
1173             napi_get_boolean(env, false, &result);
1174             return result;
1175         }
1176 
1177         std::string deviceId = identity.substr(0, DEVICEID_LENGTH);
1178         int64_t token = std::stoll(identity.substr(DEVICEID_LENGTH, identity.length() - DEVICEID_LENGTH));
1179         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1180         int callerPid = static_cast<int>(token);
1181         napi_value napiCallingPid;
1182         napi_create_int32(env, callerPid, &napiCallingPid);
1183         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1184         napi_value napiCallingUid;
1185         napi_create_int32(env, callerUid, &napiCallingUid);
1186         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1187         napi_value napiCallingDeviceID = nullptr;
1188         napi_create_string_utf8(env, deviceId.c_str(), NAPI_AUTO_LENGTH, &napiCallingDeviceID);
1189         napi_set_named_property(env, global, "callingDeviceID_", napiCallingDeviceID);
1190         napi_get_boolean(env, true, &result);
1191         return result;
1192     }
1193 }
1194 
NAPI_IPCSkeleton_restoreCallingIdentitySetProperty(napi_env env,napi_value & global,char * stringValue)1195 static napi_value NAPI_IPCSkeleton_restoreCallingIdentitySetProperty(napi_env env,
1196                                                                      napi_value &global,
1197                                                                      char* stringValue)
1198 {
1199     std::string identity = stringValue;
1200     napi_value napiIsLocalCalling = nullptr;
1201     napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1202     bool isLocalCalling = true;
1203     napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1204     napi_value result;
1205     napi_get_undefined(env, &result);
1206     if (isLocalCalling) {
1207         if (identity.empty()) {
1208             ZLOGE(LOG_LABEL, "identity is empty");
1209             return result;
1210         }
1211 
1212         int64_t token = std::stoll(identity);
1213         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1214         int callerPid = static_cast<int>(token);
1215         napi_value napiCallingPid;
1216         napi_create_int32(env, callerPid, &napiCallingPid);
1217         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1218         napi_value napiCallingUid;
1219         napi_create_int32(env, callerUid, &napiCallingUid);
1220         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1221         return result;
1222     } else {
1223         if (identity.empty() || identity.length() <= DEVICEID_LENGTH) {
1224             ZLOGE(LOG_LABEL, "identity is empty or length is too short");
1225             return result;
1226         }
1227 
1228         std::string deviceId = identity.substr(0, DEVICEID_LENGTH);
1229         int64_t token = std::stoll(identity.substr(DEVICEID_LENGTH, identity.length() - DEVICEID_LENGTH));
1230         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1231         int callerPid = static_cast<int>(token);
1232         napi_value napiCallingPid;
1233         napi_create_int32(env, callerPid, &napiCallingPid);
1234         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1235         napi_value napiCallingUid;
1236         napi_create_int32(env, callerUid, &napiCallingUid);
1237         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1238         napi_value napiCallingDeviceID = nullptr;
1239         napi_create_string_utf8(env, deviceId.c_str(), NAPI_AUTO_LENGTH, &napiCallingDeviceID);
1240         napi_set_named_property(env, global, "callingDeviceID_", napiCallingDeviceID);
1241         return result;
1242     }
1243 }
1244 
NAPI_IPCSkeleton_restoreCallingIdentity(napi_env env,napi_callback_info info)1245 napi_value NAPI_IPCSkeleton_restoreCallingIdentity(napi_env env, napi_callback_info info)
1246 {
1247     napi_value global = nullptr;
1248     napi_get_global(env, &global);
1249     napi_value napiActiveStatus = nullptr;
1250     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1251     int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1252     napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1253     if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1254         ZLOGD(LOG_LABEL, "status is not active");
1255         napi_value result = nullptr;
1256         napi_get_undefined(env, &result);
1257         return result;
1258     }
1259 
1260     size_t argc = 1;
1261     size_t expectedArgc = 1;
1262     napi_value argv[ARGV_INDEX_1] = { 0 };
1263     napi_value thisVar = nullptr;
1264     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1265     if (argc != expectedArgc) {
1266         ZLOGE(LOG_LABEL, "requires 1 parameter");
1267         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1268     }
1269     napi_valuetype valueType = napi_null;
1270     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1271     if (valueType != napi_string) {
1272         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1273         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1274     }
1275     size_t bufferSize = 0;
1276     size_t maxLen = 40960;
1277     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
1278     if (bufferSize >= maxLen) {
1279         ZLOGE(LOG_LABEL, "string length too large");
1280         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1281     }
1282     char stringValue[bufferSize + 1];
1283     size_t jsStringLength = 0;
1284     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
1285     if (jsStringLength != bufferSize) {
1286         ZLOGE(LOG_LABEL, "string length wrong");
1287         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1288     }
1289 
1290     return NAPI_IPCSkeleton_restoreCallingIdentitySetProperty(env, global, stringValue);
1291 }
1292 
NAPI_RemoteObject_queryLocalInterface(napi_env env,napi_callback_info info)1293 napi_value NAPI_RemoteObject_queryLocalInterface(napi_env env, napi_callback_info info)
1294 {
1295     size_t argc = 1;
1296     size_t expectedArgc = 1;
1297     napi_value argv[1] = { 0 };
1298     napi_value thisVar = nullptr;
1299     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1300     NAPI_ASSERT(env, argc == expectedArgc, "requires 1 parameters");
1301     napi_valuetype valueType = napi_null;
1302     napi_typeof(env, argv[0], &valueType);
1303     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
1304     size_t bufferSize = 0;
1305     size_t maxLen = 40960;
1306     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1307     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1308     char stringValue[bufferSize + 1];
1309     size_t jsStringLength = 0;
1310     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1311     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1312     std::string descriptor = stringValue;
1313     NAPIRemoteObjectHolder *holder = nullptr;
1314     napi_unwrap(env, thisVar, (void **)&holder);
1315     NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1316     napi_value ret = holder->queryLocalInterface(descriptor);
1317     return ret;
1318 }
1319 
NAPI_RemoteObject_getLocalInterface(napi_env env,napi_callback_info info)1320 napi_value NAPI_RemoteObject_getLocalInterface(napi_env env, napi_callback_info info)
1321 {
1322     size_t argc = 1;
1323     size_t expectedArgc = 1;
1324     napi_value argv[1] = { 0 };
1325     napi_value thisVar = nullptr;
1326     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1327     if (argc != expectedArgc) {
1328         ZLOGE(LOG_LABEL, "requires 1 parameters");
1329         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1330     }
1331     napi_valuetype valueType = napi_null;
1332     napi_typeof(env, argv[0], &valueType);
1333     if (valueType != napi_string) {
1334         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1335         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1336     }
1337     size_t bufferSize = 0;
1338     size_t maxLen = 40960;
1339     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1340     if (bufferSize >= maxLen) {
1341         ZLOGE(LOG_LABEL, "string length too large");
1342         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1343     }
1344     char stringValue[bufferSize + 1];
1345     size_t jsStringLength = 0;
1346     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1347     if (jsStringLength != bufferSize) {
1348         ZLOGE(LOG_LABEL, "string length wrong");
1349         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1350     }
1351     std::string descriptor = stringValue;
1352     NAPIRemoteObjectHolder *holder = nullptr;
1353     napi_unwrap(env, thisVar, (void **)&holder);
1354     if (holder == nullptr) {
1355         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1356         return nullptr;
1357     }
1358     napi_value ret = holder->queryLocalInterface(descriptor);
1359     return ret;
1360 }
1361 
NAPI_RemoteObject_getInterfaceDescriptor(napi_env env,napi_callback_info info)1362 napi_value NAPI_RemoteObject_getInterfaceDescriptor(napi_env env, napi_callback_info info)
1363 {
1364     napi_value result = nullptr;
1365     napi_value thisVar = nullptr;
1366     napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
1367     sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1368     std::u16string descriptor = nativeObject->GetObjectDescriptor();
1369     napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1370     return result;
1371 }
1372 
NAPI_RemoteObject_getDescriptor(napi_env env,napi_callback_info info)1373 napi_value NAPI_RemoteObject_getDescriptor(napi_env env, napi_callback_info info)
1374 {
1375     napi_value result = nullptr;
1376     napi_value thisVar = nullptr;
1377     napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
1378     sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1379     if (nativeObject == nullptr) {
1380         ZLOGE(LOG_LABEL, "native stub object is nullptr");
1381         return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
1382     }
1383     std::u16string descriptor = nativeObject->GetObjectDescriptor();
1384     napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1385     return result;
1386 }
1387 
NAPI_RemoteObject_getCallingPid(napi_env env,napi_callback_info info)1388 napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
1389 {
1390     return NAPI_IPCSkeleton_getCallingPid(env, info);
1391 }
1392 
NAPI_RemoteObject_getCallingUid(napi_env env,napi_callback_info info)1393 napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
1394 {
1395     return NAPI_IPCSkeleton_getCallingUid(env, info);
1396 }
1397 
MakeSendRequestResult(SendRequestParam * param)1398 napi_value MakeSendRequestResult(SendRequestParam *param)
1399 {
1400     napi_value errCode = nullptr;
1401     napi_create_int32(param->env, param->errCode, &errCode);
1402     napi_value code = nullptr;
1403     napi_get_reference_value(param->env, param->jsCodeRef, &code);
1404     napi_value data = nullptr;
1405     napi_get_reference_value(param->env, param->jsDataRef, &data);
1406     napi_value reply = nullptr;
1407     napi_get_reference_value(param->env, param->jsReplyRef, &reply);
1408     napi_value result = nullptr;
1409     napi_create_object(param->env, &result);
1410     napi_set_named_property(param->env, result, "errCode", errCode);
1411     napi_set_named_property(param->env, result, "code", code);
1412     napi_set_named_property(param->env, result, "data", data);
1413     napi_set_named_property(param->env, result, "reply", reply);
1414     return result;
1415 }
1416 
StubExecuteSendRequest(napi_env env,SendRequestParam * param)1417 void StubExecuteSendRequest(napi_env env, SendRequestParam *param)
1418 {
1419     param->errCode = param->target->SendRequest(param->code,
1420         *(param->data.get()), *(param->reply.get()), param->option);
1421     ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d", param->errCode);
1422     if (param->traceId != 0) {
1423         FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
1424     }
1425     uv_loop_s *loop = nullptr;
1426     napi_get_uv_event_loop(env, &loop);
1427     uv_work_t *work = new uv_work_t;
1428     work->data = reinterpret_cast<void *>(param);
1429     uv_after_work_cb afterWorkCb = nullptr;
1430     if (param->callback != nullptr) {
1431         afterWorkCb = [](uv_work_t *work, int status) {
1432             ZLOGI(LOG_LABEL, "callback started");
1433             SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1434             napi_value result = MakeSendRequestResult(param);
1435             napi_value callback = nullptr;
1436             napi_get_reference_value(param->env, param->callback, &callback);
1437             napi_value cbResult = nullptr;
1438             napi_call_function(param->env, nullptr, callback, 1, &result, &cbResult);
1439             napi_delete_reference(param->env, param->jsCodeRef);
1440             napi_delete_reference(param->env, param->jsDataRef);
1441             napi_delete_reference(param->env, param->jsReplyRef);
1442             napi_delete_reference(param->env, param->callback);
1443             delete param;
1444             delete work;
1445         };
1446     } else {
1447         afterWorkCb = [](uv_work_t *work, int status) {
1448             ZLOGI(LOG_LABEL, "promise fullfilled");
1449             SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1450             napi_value result = MakeSendRequestResult(param);
1451             if (param->errCode == 0) {
1452                 napi_resolve_deferred(param->env, param->deferred, result);
1453             } else {
1454                 napi_reject_deferred(param->env, param->deferred, result);
1455             }
1456             napi_delete_reference(param->env, param->jsCodeRef);
1457             napi_delete_reference(param->env, param->jsDataRef);
1458             napi_delete_reference(param->env, param->jsReplyRef);
1459             delete param;
1460             delete work;
1461         };
1462     }
1463     uv_queue_work(loop, work, [](uv_work_t *work) {}, afterWorkCb);
1464 }
1465 
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)1466 napi_value StubSendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1467     std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1468     MessageOption &option, napi_value *argv)
1469 {
1470     SendRequestParam *sendRequestParam = new SendRequestParam {
1471         .target = target,
1472         .code = code,
1473         .data = data,
1474         .reply = reply,
1475         .option = option,
1476         .asyncWork = nullptr,
1477         .deferred = nullptr,
1478         .errCode = -1,
1479         .jsCodeRef = nullptr,
1480         .jsDataRef = nullptr,
1481         .jsReplyRef = nullptr,
1482         .callback = nullptr,
1483         .env = env,
1484         .traceId = 0,
1485     };
1486     if (target != nullptr) {
1487         std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1488         if (!remoteDescriptor.empty()) {
1489             sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1490             sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1491             StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1492         }
1493     }
1494     napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1495     napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1496     napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1497     napi_create_reference(env, argv[4], 1, &sendRequestParam->callback);
1498     std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1499     t.detach();
1500     napi_value result = nullptr;
1501     napi_get_undefined(env, &result);
1502     return result;
1503 }
1504 
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)1505 napi_value StubSendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1506     std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1507     MessageOption &option, napi_value *argv)
1508 {
1509     napi_deferred deferred = nullptr;
1510     napi_value promise = nullptr;
1511     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1512     SendRequestParam *sendRequestParam = new SendRequestParam {
1513         .target = target,
1514         .code = code,
1515         .data = data,
1516         .reply = reply,
1517         .option = option,
1518         .asyncWork = nullptr,
1519         .deferred = deferred,
1520         .errCode = -1,
1521         .jsCodeRef = nullptr,
1522         .jsDataRef = nullptr,
1523         .jsReplyRef = nullptr,
1524         .callback = nullptr,
1525         .env = env,
1526         .traceId = 0,
1527     };
1528     if (target != nullptr) {
1529         std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1530         if (!remoteDescriptor.empty()) {
1531             sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1532             sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1533             StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1534         }
1535     }
1536     napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1537     napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1538     napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1539     std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1540     t.detach();
1541     return promise;
1542 }
1543 
NAPI_RemoteObject_sendRequest(napi_env env,napi_callback_info info)1544 napi_value NAPI_RemoteObject_sendRequest(napi_env env, napi_callback_info info)
1545 {
1546     size_t argc = 4;
1547     size_t argcCallback = 5;
1548     size_t argcPromise = 4;
1549     napi_value argv[5] = { 0 };
1550     napi_value thisVar = nullptr;
1551     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1552     NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1553     napi_valuetype valueType = napi_null;
1554     napi_typeof(env, argv[0], &valueType);
1555     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1556     napi_typeof(env, argv[1], &valueType);
1557     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1558     napi_typeof(env, argv[2], &valueType);
1559     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1560     napi_typeof(env, argv[3], &valueType);
1561     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1562 
1563     NAPI_MessageParcel *data = nullptr;
1564     napi_status status = napi_unwrap(env, argv[1], (void **)&data);
1565     NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1566     NAPI_MessageParcel *reply = nullptr;
1567     status = napi_unwrap(env, argv[2], (void **)&reply);
1568     NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1569     MessageOption *option = nullptr;
1570     status = napi_unwrap(env, argv[3], (void **)&option);
1571     NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1572     int32_t code = 0;
1573     napi_get_value_int32(env, argv[0], &code);
1574 
1575     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1576     if (argc == argcCallback) {
1577         napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1578         napi_valuetype valuetype = napi_undefined;
1579         napi_typeof(env, argv[argcPromise], &valuetype);
1580         if (valuetype == napi_function) {
1581             return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1582                 reply->GetMessageParcel(), *option, argv);
1583         }
1584     }
1585     return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1586         reply->GetMessageParcel(), *option, argv);
1587 }
1588 
NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,size_t argc,size_t argcCallback,size_t argcPromise,napi_value * argv)1589 napi_value NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,
1590                                                          size_t argc,
1591                                                          size_t argcCallback,
1592                                                          size_t argcPromise,
1593                                                          napi_value* argv)
1594 {
1595     if (argc != argcPromise && argc != argcCallback) {
1596         ZLOGE(LOG_LABEL, "requires 4 or 5 parameters");
1597         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1598     }
1599     napi_valuetype valueType = napi_null;
1600     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1601     if (valueType != napi_number) {
1602         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1603         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1604     }
1605     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1606     if (valueType != napi_object) {
1607         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1608         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1609     }
1610     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1611     if (valueType != napi_object) {
1612         ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
1613         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1614     }
1615     napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1616     if (valueType != napi_object) {
1617         ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
1618         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1619     }
1620     napi_value result = nullptr;
1621     napi_get_undefined(env, &result);
1622     return result;
1623 }
1624 
NAPI_RemoteObject_sendMessageRequest(napi_env env,napi_callback_info info)1625 napi_value NAPI_RemoteObject_sendMessageRequest(napi_env env, napi_callback_info info)
1626 {
1627     size_t argc = 4;
1628     size_t argcCallback = 5;
1629     size_t argcPromise = 4;
1630     napi_value argv[5] = { 0 };
1631     napi_value thisVar = nullptr;
1632     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1633     napi_value checkArgsResult = NAPI_RemoteObject_checkSendMessageRequestArgs(env, argc, argcCallback, argcPromise,
1634                                                                                argv);
1635     if (checkArgsResult == nullptr) {
1636         return checkArgsResult;
1637     }
1638     NAPI_MessageSequence *data = nullptr;
1639     napi_status status = napi_unwrap(env, argv[1], (void **)&data);
1640     if (status != napi_ok) {
1641         ZLOGE(LOG_LABEL, "failed to get data message sequence");
1642         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1643     }
1644     NAPI_MessageSequence *reply = nullptr;
1645     status = napi_unwrap(env, argv[2], (void **)&reply);
1646     if (status != napi_ok) {
1647         ZLOGE(LOG_LABEL, "failed to get data message sequence");
1648         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1649     }
1650     MessageOption *option = nullptr;
1651     status = napi_unwrap(env, argv[3], (void **)&option);
1652     if (status != napi_ok) {
1653         ZLOGE(LOG_LABEL, "failed to get message option");
1654         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1655     }
1656     int32_t code = 0;
1657     napi_get_value_int32(env, argv[0], &code);
1658 
1659     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1660     if (argc == argcCallback) {
1661         napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1662         napi_valuetype valuetype = napi_undefined;
1663         napi_typeof(env, argv[argcPromise], &valuetype);
1664         if (valuetype == napi_function) {
1665             return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1666                 reply->GetMessageParcel(), *option, argv);
1667         }
1668     }
1669     return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1670         reply->GetMessageParcel(), *option, argv);
1671 }
1672 
NAPI_RemoteObject_attachLocalInterface(napi_env env,napi_callback_info info)1673 napi_value NAPI_RemoteObject_attachLocalInterface(napi_env env, napi_callback_info info)
1674 {
1675     size_t argc = 2;
1676     size_t expectedArgc = 2;
1677     napi_value argv[2] = { 0 };
1678     napi_value thisVar = nullptr;
1679     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1680     NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameters");
1681     napi_valuetype valueType = napi_null;
1682     napi_typeof(env, argv[0], &valueType);
1683     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1684     napi_typeof(env, argv[1], &valueType);
1685     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 2");
1686     size_t bufferSize = 0;
1687     size_t maxLen = 40960;
1688     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &bufferSize);
1689     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1690     char stringValue[bufferSize + 1];
1691     size_t jsStringLength = 0;
1692     napi_get_value_string_utf8(env, argv[1], stringValue, bufferSize + 1, &jsStringLength);
1693     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1694     std::string descriptor = stringValue;
1695 
1696     NAPIRemoteObjectHolder *holder = nullptr;
1697     napi_unwrap(env, thisVar, (void* *)&holder);
1698     NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1699     holder->attachLocalInterface(argv[0], descriptor);
1700 
1701     napi_value result = nullptr;
1702     napi_get_undefined(env, &result);
1703     return result;
1704 }
1705 
NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env,size_t argc,napi_value * argv)1706 napi_value NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env, size_t argc, napi_value* argv)
1707 {
1708     size_t expectedArgc = 2;
1709 
1710     if (argc != expectedArgc) {
1711         ZLOGE(LOG_LABEL, "requires 2 parameters");
1712         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1713     }
1714     napi_valuetype valueType = napi_null;
1715     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1716     if (valueType != napi_object) {
1717         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1718         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1719     }
1720     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1721     if (valueType != napi_string) {
1722         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1723         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1724     }
1725     napi_value result = nullptr;
1726     napi_get_undefined(env, &result);
1727     return result;
1728 }
1729 
NAPI_RemoteObject_modifyLocalInterface(napi_env env,napi_callback_info info)1730 napi_value NAPI_RemoteObject_modifyLocalInterface(napi_env env, napi_callback_info info)
1731 {
1732     size_t argc = 2;
1733     napi_value argv[2] = { 0 };
1734     napi_value thisVar = nullptr;
1735     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1736     napi_value checkArgsResult = NAPI_RemoteObject_checkModifyLocalInterfaceArgs(env, argc, argv);
1737     if (checkArgsResult == nullptr) {
1738         return checkArgsResult;
1739     }
1740     size_t bufferSize = 0;
1741     size_t maxLen = 40960;
1742     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &bufferSize);
1743     if (bufferSize >= maxLen) {
1744         ZLOGE(LOG_LABEL, "string length too large");
1745         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1746     }
1747     char stringValue[bufferSize + 1];
1748     size_t jsStringLength = 0;
1749     napi_get_value_string_utf8(env, argv[1], stringValue, bufferSize + 1, &jsStringLength);
1750     if (jsStringLength != bufferSize) {
1751         ZLOGE(LOG_LABEL, "string length wrong");
1752         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1753     }
1754     std::string descriptor = stringValue;
1755 
1756     NAPIRemoteObjectHolder *holder = nullptr;
1757     napi_unwrap(env, thisVar, (void* *)&holder);
1758     if (holder == nullptr) {
1759         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1760         return nullptr;
1761     }
1762     holder->attachLocalInterface(argv[0], descriptor);
1763 
1764     napi_value result = nullptr;
1765     napi_get_undefined(env, &result);
1766     return result;
1767 }
1768 
NAPI_RemoteObject_addDeathRecipient(napi_env env,napi_callback_info info)1769 napi_value NAPI_RemoteObject_addDeathRecipient(napi_env env, napi_callback_info info)
1770 {
1771     napi_value result = nullptr;
1772     napi_get_boolean(env, false, &result);
1773     return result;
1774 }
1775 
NAPI_RemoteObject_removeDeathRecipient(napi_env env,napi_callback_info info)1776 napi_value NAPI_RemoteObject_removeDeathRecipient(napi_env env, napi_callback_info info)
1777 {
1778     napi_value result = nullptr;
1779     napi_get_boolean(env, false, &result);
1780     return result;
1781 }
1782 
NAPI_RemoteObject_isObjectDead(napi_env env,napi_callback_info info)1783 napi_value NAPI_RemoteObject_isObjectDead(napi_env env, napi_callback_info info)
1784 {
1785     napi_value result = nullptr;
1786     napi_get_boolean(env, false, &result);
1787     return result;
1788 }
1789 
NAPIIPCSkeleton_JS_Constructor(napi_env env,napi_callback_info info)1790 napi_value NAPIIPCSkeleton_JS_Constructor(napi_env env, napi_callback_info info)
1791 {
1792     napi_value thisArg = nullptr;
1793     void *data = nullptr;
1794     napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
1795     napi_value global = nullptr;
1796     napi_get_global(env, &global);
1797     return thisArg;
1798 }
1799 
1800 EXTERN_C_START
1801 /*
1802  * function for module exports
1803  */
NAPIIPCSkeletonExport(napi_env env,napi_value exports)1804 napi_value NAPIIPCSkeletonExport(napi_env env, napi_value exports)
1805 {
1806     ZLOGI(LOG_LABEL, "napi_moudule IPCSkeleton Init start...");
1807     napi_property_descriptor desc[] = {
1808         DECLARE_NAPI_STATIC_FUNCTION("getContextObject", NAPI_IPCSkeleton_getContextObject),
1809         DECLARE_NAPI_STATIC_FUNCTION("getCallingPid", NAPI_IPCSkeleton_getCallingPid),
1810         DECLARE_NAPI_STATIC_FUNCTION("getCallingUid", NAPI_IPCSkeleton_getCallingUid),
1811         DECLARE_NAPI_STATIC_FUNCTION("getCallingDeviceID", NAPI_IPCSkeleton_getCallingDeviceID),
1812         DECLARE_NAPI_STATIC_FUNCTION("getLocalDeviceID", NAPI_IPCSkeleton_getLocalDeviceID),
1813         DECLARE_NAPI_STATIC_FUNCTION("isLocalCalling", NAPI_IPCSkeleton_isLocalCalling),
1814         DECLARE_NAPI_STATIC_FUNCTION("flushCmdBuffer", NAPI_IPCSkeleton_flushCmdBuffer),
1815         DECLARE_NAPI_STATIC_FUNCTION("flushCommands", NAPI_IPCSkeleton_flushCommands),
1816         DECLARE_NAPI_STATIC_FUNCTION("resetCallingIdentity", NAPI_IPCSkeleton_resetCallingIdentity),
1817         DECLARE_NAPI_STATIC_FUNCTION("restoreCallingIdentity", NAPI_IPCSkeleton_restoreCallingIdentity),
1818         DECLARE_NAPI_STATIC_FUNCTION("setCallingIdentity", NAPI_IPCSkeleton_setCallingIdentity),
1819         DECLARE_NAPI_STATIC_FUNCTION("getCallingTokenId", NAPI_IPCSkeleton_getCallingTokenId),
1820     };
1821     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1822     napi_value result = nullptr;
1823     napi_define_class(env, "IPCSkeleton", NAPI_AUTO_LENGTH, NAPIIPCSkeleton_JS_Constructor, nullptr,
1824         sizeof(desc) / sizeof(desc[0]), desc, &result);
1825     napi_status status = napi_set_named_property(env, exports, "IPCSkeleton", result);
1826     NAPI_ASSERT(env, status == napi_ok, "create ref to js RemoteObject constructor failed");
1827     ZLOGI(LOG_LABEL, "napi_moudule IPCSkeleton Init end...");
1828     return exports;
1829 }
1830 EXTERN_C_END
1831 
NAPIMessageOption_JS_Constructor(napi_env env,napi_callback_info info)1832 napi_value NAPIMessageOption_JS_Constructor(napi_env env, napi_callback_info info)
1833 {
1834     size_t argc = 2;
1835     napi_value argv[2] = { 0 };
1836     napi_value thisVar = nullptr;
1837     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1838     NAPI_ASSERT(env, argc >= 0, "invalid parameter number");
1839     int flags = 0;
1840     int waittime = 0;
1841     if (argc == 0) {
1842         flags = MessageOption::TF_SYNC;
1843         waittime = MessageOption::TF_WAIT_TIME;
1844     } else if (argc == 1) {
1845         napi_valuetype valueType;
1846         napi_typeof(env, argv[0], &valueType);
1847         NAPI_ASSERT(env, valueType == napi_number || valueType == napi_boolean, "type mismatch for parameter 1");
1848         if (valueType == napi_boolean) {
1849             bool jsBoolFlags = false;
1850             napi_get_value_bool(env, argv[0], &jsBoolFlags);
1851             flags = jsBoolFlags ? MessageOption::TF_ASYNC : MessageOption::TF_SYNC;
1852         } else {
1853             int32_t jsFlags = 0;
1854             napi_get_value_int32(env, argv[0], &jsFlags);
1855             flags = jsFlags == 0 ? MessageOption::TF_SYNC : MessageOption::TF_ASYNC;
1856         }
1857         waittime = MessageOption::TF_WAIT_TIME;
1858     } else {
1859         napi_valuetype valueType = napi_null;
1860         napi_typeof(env, argv[0], &valueType);
1861         NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1862         napi_typeof(env, argv[1], &valueType);
1863         NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
1864         int32_t jsFlags = 0;
1865         napi_get_value_int32(env, argv[0], &jsFlags);
1866         int32_t jsWaittime = 0;
1867         napi_get_value_int32(env, argv[1], &jsWaittime);
1868         flags = jsFlags == 0 ? MessageOption::TF_SYNC : MessageOption::TF_ASYNC;
1869         waittime = jsWaittime;
1870     }
1871 
1872     auto messageOption = new MessageOption(flags, waittime);
1873     // connect native message option to js thisVar
1874     napi_status status = napi_wrap(
1875         env, thisVar, messageOption,
1876         [](napi_env env, void *data, void *hint) {
1877             ZLOGI(LOG_LABEL, "NAPIMessageOption destructed by js callback");
1878             delete (reinterpret_cast<MessageOption *>(data));
1879         },
1880         nullptr, nullptr);
1881     NAPI_ASSERT(env, status == napi_ok, "wrap js MessageOption and native option failed");
1882     return thisVar;
1883 }
1884 
1885 EXTERN_C_START
1886 /*
1887  * function for module exports
1888  */
NAPIMessageOptionExport(napi_env env,napi_value exports)1889 napi_value NAPIMessageOptionExport(napi_env env, napi_value exports)
1890 {
1891     const std::string className = "MessageOption";
1892     napi_value tfSync = nullptr;
1893     napi_create_int32(env, MessageOption::TF_SYNC, &tfSync);
1894     napi_value tfAsync = nullptr;
1895     napi_create_int32(env, MessageOption::TF_ASYNC, &tfAsync);
1896     napi_value tfFds = nullptr;
1897     napi_create_int32(env, MessageOption::TF_ACCEPT_FDS, &tfFds);
1898     napi_value tfWaitTime = nullptr;
1899     napi_create_int32(env, MessageOption::TF_WAIT_TIME, &tfWaitTime);
1900     napi_property_descriptor properties[] = {
1901         DECLARE_NAPI_FUNCTION("getFlags", NapiOhosRpcMessageOptionGetFlags),
1902         DECLARE_NAPI_FUNCTION("setFlags", NapiOhosRpcMessageOptionSetFlags),
1903         DECLARE_NAPI_FUNCTION("isAsync", NapiOhosRpcMessageOptionIsAsync),
1904         DECLARE_NAPI_FUNCTION("setAsync", NapiOhosRpcMessageOptionSetAsync),
1905         DECLARE_NAPI_FUNCTION("getWaitTime", NapiOhosRpcMessageOptionGetWaittime),
1906         DECLARE_NAPI_FUNCTION("setWaitTime", NapiOhosRpcMessageOptionSetWaittime),
1907         DECLARE_NAPI_STATIC_PROPERTY("TF_SYNC", tfSync),
1908         DECLARE_NAPI_STATIC_PROPERTY("TF_ASYNC", tfAsync),
1909         DECLARE_NAPI_STATIC_PROPERTY("TF_ACCEPT_FDS", tfFds),
1910         DECLARE_NAPI_STATIC_PROPERTY("TF_WAIT_TIME", tfWaitTime),
1911     };
1912     napi_value constructor = nullptr;
1913     napi_define_class(env, className.c_str(), className.length(), NAPIMessageOption_JS_Constructor, nullptr,
1914         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
1915     NAPI_ASSERT(env, constructor != nullptr, "define js class MessageOption failed");
1916     napi_status status = napi_set_named_property(env, exports, "MessageOption", constructor);
1917     NAPI_ASSERT(env, status == napi_ok, "set property MessageOption to exports failed");
1918     napi_value global = nullptr;
1919     status = napi_get_global(env, &global);
1920     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
1921     status = napi_set_named_property(env, global, "IPCOptionConstructor_", constructor);
1922     NAPI_ASSERT(env, status == napi_ok, "set message option constructor failed");
1923     return exports;
1924 }
1925 EXTERN_C_END
1926 } // namespace OHOS
1927