• 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("registerDeathRecipient", NAPI_RemoteObject_registerDeathRecipient),
329         DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteObject_removeDeathRecipient),
330         DECLARE_NAPI_FUNCTION("unregisterDeathRecipient", NAPI_RemoteObject_unregisterDeathRecipient),
331         DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteObject_isObjectDead),
332     };
333     napi_value constructor = nullptr;
334     napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
335         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
336     NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteObject failed");
337     napi_status status = napi_set_named_property(env, exports, "RemoteObject", constructor);
338     NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
339     napi_value global = nullptr;
340     status = napi_get_global(env, &global);
341     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
342     status = napi_set_named_property(env, global, "IPCStubConstructor_", constructor);
343     NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
344     return exports;
345 }
346 EXTERN_C_END
347 
NAPIRemoteObject(napi_env env,napi_value thisVar,const std::u16string & descriptor)348 NAPIRemoteObject::NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor)
349     : IPCObjectStub(descriptor)
350 {
351     env_ = env;
352     thisVar_ = thisVar;
353     napi_create_reference(env, thisVar_, 1, &thisVarRef_);
354     NAPI_ASSERT_RETURN_VOID(env, thisVarRef_ != nullptr, "failed to create ref to js RemoteObject");
355 }
356 
~NAPIRemoteObject()357 NAPIRemoteObject::~NAPIRemoteObject()
358 {
359     ZLOGI(LOG_LABEL, "NAPIRemoteObject Destructor");
360     if (thisVarRef_ != nullptr) {
361         napi_status status = napi_delete_reference(env_, thisVarRef_);
362         NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js RemoteObject");
363         thisVarRef_ = nullptr;
364     }
365 }
366 
CheckObjectLegality() const367 bool NAPIRemoteObject::CheckObjectLegality() const
368 {
369     return true;
370 }
371 
GetObjectType() const372 int NAPIRemoteObject::GetObjectType() const
373 {
374     return OBJECT_TYPE_JAVASCRIPT;
375 }
376 
GetJsObjectRef() const377 napi_ref NAPIRemoteObject::GetJsObjectRef() const
378 {
379     return thisVarRef_;
380 }
381 
NAPI_RemoteObject_getCallingInfo(CallingInfo & newCallingInfoParam)382 void NAPI_RemoteObject_getCallingInfo(CallingInfo &newCallingInfoParam)
383 {
384     newCallingInfoParam.callingPid = IPCSkeleton::GetCallingPid();
385     newCallingInfoParam.callingUid = IPCSkeleton::GetCallingUid();
386     newCallingInfoParam.callingTokenId = IPCSkeleton::GetCallingTokenID();
387     newCallingInfoParam.callingDeviceID = IPCSkeleton::GetCallingDeviceID();
388     newCallingInfoParam.localDeviceID = IPCSkeleton::GetLocalDeviceID();
389     newCallingInfoParam.isLocalCalling = IPCSkeleton::IsLocalCalling();
390     newCallingInfoParam.activeStatus = IRemoteInvoker::ACTIVE_INVOKER;
391 };
392 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)393 int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
394 {
395     ZLOGI(LOG_LABEL, "enter OnRemoteRequest");
396     if (code == DUMP_TRANSACTION) {
397         ZLOGE(LOG_LABEL, "DUMP_TRANSACTION data size:%zu", data.GetReadableBytes());
398     }
399     std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
400     CallbackParam *param = new CallbackParam {
401         .env = env_,
402         .thisVarRef = thisVarRef_,
403         .code = code,
404         .data = &data,
405         .reply = &reply,
406         .option = &option,
407         .lockInfo = lockInfo.get(),
408         .result = 0
409     };
410 
411     NAPI_RemoteObject_getCallingInfo(param->callingInfo);
412     ZLOGI(LOG_LABEL, "callingPid:%{public}u, callingUid:%{public}u,"
413         "callingDeviceID:%{public}s, localDeviceId:%{public}s, localCalling:%{public}d",
414         param->callingInfo.callingPid, param->callingInfo.callingUid,
415         param->callingInfo.callingDeviceID.c_str(), param->callingInfo.localDeviceID.c_str(),
416         param->callingInfo.isLocalCalling);
417     int ret = OnJsRemoteRequest(param);
418     ZLOGI(LOG_LABEL, "OnJsRemoteRequest done, ret:%{public}d", ret);
419     return ret;
420 }
421 
ThenCallback(napi_env env,napi_callback_info info)422 napi_value NAPIRemoteObject::ThenCallback(napi_env env, napi_callback_info info)
423 {
424     ZLOGI(LOG_LABEL, "call js onRemoteRequest done");
425     size_t argc = 1;
426     napi_value argv[1] = {nullptr};
427     void* data = nullptr;
428     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
429     CallbackParam *param = static_cast<CallbackParam *>(data);
430     bool result = false;
431     napi_get_value_bool(param->env, argv[0], &result);
432     if (!result) {
433         ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s", result ? "true" : "false");
434         param->result = ERR_UNKNOWN_TRANSACTION;
435     } else {
436         param->result = ERR_NONE;
437     }
438     std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
439     param->lockInfo->ready = true;
440     param->lockInfo->condition.notify_all();
441     napi_value res;
442     napi_get_undefined(env, &res);
443     return res;
444 }
445 
CatchCallback(napi_env env,napi_callback_info info)446 napi_value NAPIRemoteObject::CatchCallback(napi_env env, napi_callback_info info)
447 {
448     ZLOGI(LOG_LABEL, "Async onReomteReuqest's return_val is rejected");
449     size_t argc = 1;
450     napi_value argv[1] = {nullptr};
451     void* data = nullptr;
452     napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
453     CallbackParam *param = static_cast<CallbackParam *>(data);
454     param->result = ERR_UNKNOWN_TRANSACTION;
455     std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
456     param->lockInfo->ready = true;
457     param->lockInfo->condition.notify_all();
458     napi_value res;
459     napi_get_undefined(env, &res);
460     return res;
461 }
462 
NAPI_RemoteObject_saveOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)463 void NAPI_RemoteObject_saveOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
464 {
465     napi_value global = nullptr;
466     napi_get_global(env, &global);
467     napi_get_named_property(env, global, "callingPid_", &oldCallingInfo.callingPid);
468     napi_get_named_property(env, global, "callingUid_", &oldCallingInfo.callingUid);
469     napi_get_named_property(env, global, "callingTokenId_", &oldCallingInfo.callingTokenId);
470     napi_get_named_property(env, global, "callingDeviceID_", &oldCallingInfo.callingDeviceID);
471     napi_get_named_property(env, global, "localDeviceID_", &oldCallingInfo.localDeviceID);
472     napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
473     napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
474     napi_get_named_property(env, global, "activeStatus_", &oldCallingInfo.activeStatus);
475 }
476 
NAPI_RemoteObject_setNewCallingInfo(napi_env env,const CallingInfo & newCallingInfoParam)477 void NAPI_RemoteObject_setNewCallingInfo(napi_env env, const CallingInfo &newCallingInfoParam)
478 {
479     napi_value global = nullptr;
480     napi_get_global(env, &global);
481     napi_value newPid;
482     napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingPid), &newPid);
483     napi_set_named_property(env, global, "callingPid_", newPid);
484     napi_value newUid;
485     napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingUid), &newUid);
486     napi_set_named_property(env, global, "callingUid_", newUid);
487     napi_value newCallingTokenId;
488     napi_create_uint32(env, newCallingInfoParam.callingTokenId, &newCallingTokenId);
489     napi_set_named_property(env, global, "callingTokenId_", newCallingTokenId);
490     napi_value newDeviceID;
491     napi_create_string_utf8(env, newCallingInfoParam.callingDeviceID.c_str(), NAPI_AUTO_LENGTH, &newDeviceID);
492     napi_set_named_property(env, global, "callingDeviceID_", newDeviceID);
493     napi_value newLocalDeviceID;
494     napi_create_string_utf8(env, newCallingInfoParam.localDeviceID.c_str(), NAPI_AUTO_LENGTH, &newLocalDeviceID);
495     napi_set_named_property(env, global, "localDeviceID_", newLocalDeviceID);
496     napi_value newIsLocalCalling;
497     napi_get_boolean(env, newCallingInfoParam.isLocalCalling, &newIsLocalCalling);
498     napi_set_named_property(env, global, "isLocalCalling_", newIsLocalCalling);
499     napi_value newActiveStatus;
500     napi_create_int32(env, newCallingInfoParam.activeStatus, &newActiveStatus);
501     napi_set_named_property(env, global, "activeStatus_", newActiveStatus);
502 }
503 
NAPI_RemoteObject_resetOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)504 void NAPI_RemoteObject_resetOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
505 {
506     napi_value global = nullptr;
507     napi_get_global(env, &global);
508     napi_set_named_property(env, global, "callingPid_", oldCallingInfo.callingPid);
509     napi_set_named_property(env, global, "callingUid_", oldCallingInfo.callingUid);
510     napi_set_named_property(env, global, "callingTokenId_", oldCallingInfo.callingTokenId);
511     napi_set_named_property(env, global, "callingDeviceID_", oldCallingInfo.callingDeviceID);
512     napi_set_named_property(env, global, "localDeviceID_", oldCallingInfo.localDeviceID);
513     napi_set_named_property(env, global, "isLocalCalling_", oldCallingInfo.isLocalCalling);
514     napi_set_named_property(env, global, "activeStatus_", oldCallingInfo.activeStatus);
515 }
516 
OnJsRemoteRequest(CallbackParam * jsParam)517 int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
518 {
519     uv_loop_s *loop = nullptr;
520     napi_get_uv_event_loop(env_, &loop);
521 
522     uv_work_t *work = new(std::nothrow) uv_work_t;
523     if (work == nullptr) {
524         ZLOGE(LOG_LABEL, "failed to new uv_work_t");
525         delete jsParam;
526         return -1;
527     }
528     work->data = reinterpret_cast<void *>(jsParam);
529     ZLOGI(LOG_LABEL, "start nv queue work loop");
530     uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
531         ZLOGI(LOG_LABEL, "enter thread pool");
532         CallbackParam *param = reinterpret_cast<CallbackParam *>(work->data);
533         napi_value onRemoteRequest = nullptr;
534         napi_value thisVar = nullptr;
535         napi_get_reference_value(param->env, param->thisVarRef, &thisVar);
536         if (thisVar == nullptr) {
537             ZLOGE(LOG_LABEL, "thisVar is null");
538             param->result = -1;
539             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
540             param->lockInfo->ready = true;
541             param->lockInfo->condition.notify_all();
542             return;
543         }
544         napi_get_named_property(param->env, thisVar, "onRemoteMessageRequest", &onRemoteRequest);
545         if (onRemoteRequest == nullptr) {
546             ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
547             param->result = -1;
548             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
549             param->lockInfo->ready = true;
550             param->lockInfo->condition.notify_all();
551             return;
552         }
553         napi_valuetype type = napi_undefined;
554         napi_typeof(param->env, onRemoteRequest, &type);
555         bool isOnRemoteMessageRequest = true;
556         if (type != napi_function) {
557             napi_get_named_property(param->env, thisVar, "onRemoteRequest", &onRemoteRequest);
558             if (onRemoteRequest == nullptr) {
559                 ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
560                 param->result = -1;
561                 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
562                 param->lockInfo->ready = true;
563                 param->lockInfo->condition.notify_all();
564                 return;
565             }
566             isOnRemoteMessageRequest = false;
567         }
568         napi_value jsCode;
569         napi_create_uint32(param->env, param->code, &jsCode);
570 
571         napi_value global = nullptr;
572         napi_get_global(param->env, &global);
573         if (global == nullptr) {
574             ZLOGE(LOG_LABEL, "get napi global failed");
575             param->result = -1;
576             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
577             param->lockInfo->ready = true;
578             param->lockInfo->condition.notify_all();
579             return;
580         }
581         napi_value jsOptionConstructor = nullptr;
582         napi_get_named_property(param->env, global, "IPCOptionConstructor_", &jsOptionConstructor);
583         if (jsOptionConstructor == nullptr) {
584             ZLOGE(LOG_LABEL, "jsOption constructor is null");
585             param->result = -1;
586             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
587             param->lockInfo->ready = true;
588             param->lockInfo->condition.notify_all();
589             return;
590         }
591         napi_value jsOption;
592         size_t argc = 2;
593         napi_value flags = nullptr;
594         napi_create_int32(param->env, param->option->GetFlags(), &flags);
595         napi_value waittime = nullptr;
596         napi_create_int32(param->env, param->option->GetWaitTime(), &waittime);
597         napi_value argv[2] = { flags, waittime };
598         napi_new_instance(param->env, jsOptionConstructor, argc, argv, &jsOption);
599         if (jsOption == nullptr) {
600             ZLOGE(LOG_LABEL, "new jsOption failed");
601             param->result = -1;
602             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
603             param->lockInfo->ready = true;
604             param->lockInfo->condition.notify_all();
605             return;
606         }
607         napi_value jsParcelConstructor = nullptr;
608         if (isOnRemoteMessageRequest) {
609             napi_get_named_property(param->env, global, "IPCSequenceConstructor_", &jsParcelConstructor);
610         } else {
611             napi_get_named_property(param->env, global, "IPCParcelConstructor_", &jsParcelConstructor);
612         }
613         if (jsParcelConstructor == nullptr) {
614             ZLOGE(LOG_LABEL, "jsParcel constructor is null");
615             param->result = -1;
616             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
617             param->lockInfo->ready = true;
618             param->lockInfo->condition.notify_all();
619             return;
620         }
621         napi_value jsData;
622         napi_value dataParcel;
623         napi_create_object(param->env, &dataParcel);
624         napi_wrap(param->env, dataParcel, param->data,
625             [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
626         if (dataParcel == nullptr) {
627             ZLOGE(LOG_LABEL, "create js object for data parcel address failed");
628             param->result = -1;
629             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
630             param->lockInfo->ready = true;
631             param->lockInfo->condition.notify_all();
632             return;
633         }
634         size_t argc3 = 1;
635         napi_value argv3[1] = { dataParcel };
636         napi_new_instance(param->env, jsParcelConstructor, argc3, argv3, &jsData);
637         if (jsData == nullptr) {
638             ZLOGE(LOG_LABEL, "create js data parcel failed");
639             param->result = -1;
640             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
641             param->lockInfo->ready = true;
642             param->lockInfo->condition.notify_all();
643             return;
644         }
645         napi_value jsReply;
646         napi_value replyParcel;
647         napi_create_object(param->env, &replyParcel);
648         napi_wrap(param->env, replyParcel, param->reply,
649             [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
650         if (replyParcel == nullptr) {
651             ZLOGE(LOG_LABEL, "create js object for reply parcel address failed");
652             param->result = -1;
653             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
654             param->lockInfo->ready = true;
655             param->lockInfo->condition.notify_all();
656             return;
657         }
658         size_t argc4 = 1;
659         napi_value argv4[1] = { replyParcel };
660         napi_new_instance(param->env, jsParcelConstructor, argc4, argv4, &jsReply);
661         if (jsReply == nullptr) {
662             ZLOGE(LOG_LABEL, "create js reply parcel failed");
663             param->result = -1;
664             std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
665             param->lockInfo->ready = true;
666             param->lockInfo->condition.notify_all();
667             return;
668         }
669         NAPI_CallingInfo oldCallingInfo;
670         NAPI_RemoteObject_saveOldCallingInfo(param->env, oldCallingInfo);
671         NAPI_RemoteObject_setNewCallingInfo(param->env, param->callingInfo);
672         // start to call onRemoteRequest
673         size_t argc2 = 4;
674         napi_value argv2[] = { jsCode, jsData, jsReply, jsOption };
675         napi_value return_val;
676         napi_status ret = napi_call_function(param->env, thisVar, onRemoteRequest, argc2, argv2, &return_val);
677         // Reset old calling pid, uid, device id
678         NAPI_RemoteObject_resetOldCallingInfo(param->env, oldCallingInfo);
679 
680         do {
681             if (ret != napi_ok) {
682                 ZLOGE(LOG_LABEL, "OnRemoteRequest got exception");
683                 param->result = ERR_UNKNOWN_TRANSACTION;
684                 break;
685             }
686 
687             ZLOGD(LOG_LABEL, "call js onRemoteRequest done");
688             // Check whether return_val is Promise
689             bool returnIsPromise = false;//
690             napi_is_promise(param->env, return_val, &returnIsPromise);
691             if (!returnIsPromise) {
692                 ZLOGD(LOG_LABEL, "onRemoteRequest is synchronous");
693                 bool result = false;
694                 napi_get_value_bool(param->env, return_val, &result);
695                 if (!result) {
696                     ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s", result ? "true" : "false");
697                     param->result = ERR_UNKNOWN_TRANSACTION;
698                 } else {
699                     param->result = ERR_NONE;
700                 }
701                 break;
702             }
703 
704             ZLOGD(LOG_LABEL, "onRemoteRequest is asynchronous");
705             // Create promiseThen
706             napi_value promiseThen = nullptr;
707             napi_get_named_property(param->env, return_val, "then", &promiseThen);
708             if (promiseThen == nullptr) {
709                 ZLOGE(LOG_LABEL, "get promiseThen failed");
710                 param->result = -1;
711                 break;
712             }
713             napi_value then_value;
714             ret = napi_create_function(param->env, "thenCallback", NAPI_AUTO_LENGTH, ThenCallback, param, &then_value);
715             if (ret != napi_ok) {
716                 ZLOGE(LOG_LABEL, "thenCallback got exception");
717                 param->result = ERR_UNKNOWN_TRANSACTION;
718                 break;
719             }
720             // Start to call promiseThen
721             napi_value then_return_value;
722             ret = napi_call_function(param->env, return_val, promiseThen, 1, &then_value, &then_return_value);
723             if (ret != napi_ok) {
724                 ZLOGE(LOG_LABEL, "PromiseThen got exception");
725                 param->result = ERR_UNKNOWN_TRANSACTION;
726                 break;
727             }
728             // Create promiseCatch
729             napi_value promiseCatch = nullptr;
730             napi_get_named_property(param->env, return_val, "catch", &promiseCatch);
731             if (promiseCatch == nullptr) {
732                 ZLOGE(LOG_LABEL, "get promiseCatch failed");
733                 param->result = -1;
734                 break;
735             }
736             napi_value catch_value;
737             ret = napi_create_function(param->env, "catchCallback",
738                 NAPI_AUTO_LENGTH, CatchCallback, param, &catch_value);
739             if (ret != napi_ok) {
740                 ZLOGE(LOG_LABEL, "catchCallback got exception");
741                 param->result = ERR_UNKNOWN_TRANSACTION;
742                 break;
743             }
744             // Start to call promiseCatch
745             napi_value catch_return_value;
746             ret = napi_call_function(param->env, return_val, promiseCatch, 1, &catch_value, &catch_return_value);
747             if (ret != napi_ok) {
748                 ZLOGE(LOG_LABEL, "PromiseCatch got exception");
749                 param->result = ERR_UNKNOWN_TRANSACTION;
750                 break;
751             }
752             return;
753         } while (0);
754 
755         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
756         param->lockInfo->ready = true;
757         param->lockInfo->condition.notify_all();
758     });
759     std::unique_lock<std::mutex> lock(jsParam->lockInfo->mutex);
760     jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
761     int ret = jsParam->result;
762     delete jsParam;
763     delete work;
764     return ret;
765 }
766 
NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env,napi_value jsRemoteProxy)767 NAPIRemoteProxyHolder *NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env, napi_value jsRemoteProxy)
768 {
769     NAPIRemoteProxyHolder *proxyHolder = nullptr;
770     napi_unwrap(env, jsRemoteProxy, (void **)&proxyHolder);
771     NAPI_ASSERT(env, proxyHolder != nullptr, "failed to get napi remote proxy holder");
772     return proxyHolder;
773 }
774 
NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env,const sptr<IRemoteObject> target)775 napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteObject> target)
776 {
777     if (target == nullptr) {
778         ZLOGE(LOG_LABEL, "RemoteObject is null");
779         return nullptr;
780     }
781 
782     if (target->CheckObjectLegality()) {
783         IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
784         ZLOGI(LOG_LABEL, "object type:%{public}d", tmp->GetObjectType());
785         if (tmp->GetObjectType() == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT) {
786             ZLOGI(LOG_LABEL, "napi create js remote object");
787             sptr<NAPIRemoteObject> object = static_cast<NAPIRemoteObject *>(target.GetRefPtr());
788             // retrieve js remote object constructor
789             napi_value global = nullptr;
790             napi_status status = napi_get_global(env, &global);
791             NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
792             napi_value constructor = nullptr;
793             status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
794             NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
795             NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
796             // retrieve descriptor and it's length
797             std::u16string descriptor = object->GetObjectDescriptor();
798             std::string desc = Str16ToStr8(descriptor);
799             napi_value jsDesc = nullptr;
800             napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
801             // create a new js remote object
802             size_t argc = 1;
803             napi_value argv[1] = { jsDesc };
804             napi_value jsRemoteObject = nullptr;
805             status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
806             NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteObject");
807             // retrieve holder and set object
808             NAPIRemoteObjectHolder *holder = nullptr;
809             napi_unwrap(env, jsRemoteObject, (void **)&holder);
810             NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
811             holder->Set(object);
812             return jsRemoteObject;
813         }
814     }
815 
816     napi_value global = nullptr;
817     napi_status status = napi_get_global(env, &global);
818     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
819     napi_value constructor = nullptr;
820     status = napi_get_named_property(env, global, "IPCProxyConstructor_", &constructor);
821     NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
822     napi_value jsRemoteProxy;
823     status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
824     NAPI_ASSERT(env, status == napi_ok, "failed to  construct js RemoteProxy");
825     NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
826     proxyHolder->object_ = target;
827     proxyHolder->list_ = new NAPIDeathRecipientList();
828 
829     return jsRemoteProxy;
830 }
831 
NAPI_ohos_rpc_getNativeRemoteObject(napi_env env,napi_value object)832 sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
833 {
834     if (object != nullptr) {
835         napi_value global = nullptr;
836         napi_status status = napi_get_global(env, &global);
837         NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
838         napi_value stubConstructor = nullptr;
839         status = napi_get_named_property(env, global, "IPCStubConstructor_", &stubConstructor);
840         NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
841         bool instanceOfStub = false;
842         status = napi_instanceof(env, object, stubConstructor, &instanceOfStub);
843         NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
844         if (instanceOfStub) {
845             NAPIRemoteObjectHolder *holder = nullptr;
846             napi_unwrap(env, object, (void **)&holder);
847             NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
848             return holder != nullptr ? holder->Get(object) : nullptr;
849         }
850 
851         napi_value proxyConstructor = nullptr;
852         status = napi_get_named_property(env, global, "IPCProxyConstructor_", &proxyConstructor);
853         NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
854         bool instanceOfProxy = false;
855         status = napi_instanceof(env, object, proxyConstructor, &instanceOfProxy);
856         NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
857         if (instanceOfProxy) {
858             NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
859             return holder != nullptr ? holder->object_ : nullptr;
860         }
861     }
862     return nullptr;
863 }
864 
NAPI_IPCSkeleton_getContextObject(napi_env env,napi_callback_info info)865 napi_value NAPI_IPCSkeleton_getContextObject(napi_env env, napi_callback_info info)
866 {
867     sptr<IRemoteObject> object = IPCSkeleton::GetContextObject();
868     if (object == nullptr) {
869         ZLOGE(LOG_LABEL, "fatal error, could not get registry object");
870         return nullptr;
871     }
872     return NAPI_ohos_rpc_CreateJsRemoteObject(env, object);
873 }
874 
NAPI_IPCSkeleton_getCallingPid(napi_env env,napi_callback_info info)875 napi_value NAPI_IPCSkeleton_getCallingPid(napi_env env, napi_callback_info info)
876 {
877     napi_value global = nullptr;
878     napi_get_global(env, &global);
879     napi_value napiActiveStatus = nullptr;
880     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
881     if (napiActiveStatus != nullptr) {
882         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
883         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
884         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
885             napi_value callingPid = nullptr;
886             napi_get_named_property(env, global, "callingPid_", &callingPid);
887             return callingPid;
888         }
889     }
890     pid_t pid = getpid();
891     napi_value result = nullptr;
892     napi_create_int32(env, static_cast<int32_t>(pid), &result);
893     return result;
894 }
895 
NAPI_IPCSkeleton_getCallingUid(napi_env env,napi_callback_info info)896 napi_value NAPI_IPCSkeleton_getCallingUid(napi_env env, napi_callback_info info)
897 {
898     napi_value global = nullptr;
899     napi_get_global(env, &global);
900     napi_value napiActiveStatus = nullptr;
901     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
902     if (napiActiveStatus != nullptr) {
903         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
904         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
905         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
906             napi_value callingUid = nullptr;
907             napi_get_named_property(env, global, "callingUid_", &callingUid);
908             return callingUid;
909         }
910     }
911     uint32_t uid = getuid();
912     napi_value result = nullptr;
913     napi_create_int32(env, static_cast<int32_t>(uid), &result);
914     return result;
915 }
916 
NAPI_IPCSkeleton_getCallingTokenId(napi_env env,napi_callback_info info)917 napi_value NAPI_IPCSkeleton_getCallingTokenId(napi_env env, napi_callback_info info)
918 {
919     napi_value global = nullptr;
920     napi_get_global(env, &global);
921     napi_value napiActiveStatus = nullptr;
922     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
923     if (napiActiveStatus != nullptr) {
924         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
925         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
926         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
927             napi_value callingTokenId = nullptr;
928             napi_get_named_property(env, global, "callingTokenId_", &callingTokenId);
929             return callingTokenId;
930         }
931     }
932     uint64_t TokenId = RpcGetSelfTokenID();
933     napi_value result = nullptr;
934     napi_create_uint32(env, static_cast<uint32_t>(TokenId), &result);
935     return result;
936 }
937 
NAPI_IPCSkeleton_getCallingDeviceID(napi_env env,napi_callback_info info)938 napi_value NAPI_IPCSkeleton_getCallingDeviceID(napi_env env, napi_callback_info info)
939 {
940     napi_value global = nullptr;
941     napi_get_global(env, &global);
942     napi_value napiActiveStatus = nullptr;
943     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
944     if (napiActiveStatus != nullptr) {
945         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
946         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
947         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
948             napi_value callingDeviceID = nullptr;
949             napi_get_named_property(env, global, "callingDeviceID_", &callingDeviceID);
950             return callingDeviceID;
951         }
952     }
953     napi_value result = nullptr;
954     napi_create_string_utf8(env, "", 0, &result);
955     return result;
956 }
957 
NAPI_IPCSkeleton_getLocalDeviceID(napi_env env,napi_callback_info info)958 napi_value NAPI_IPCSkeleton_getLocalDeviceID(napi_env env, napi_callback_info info)
959 {
960     napi_value global = nullptr;
961     napi_get_global(env, &global);
962     napi_value napiActiveStatus = nullptr;
963     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
964     if (napiActiveStatus != nullptr) {
965         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
966         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
967         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
968             napi_value localDeviceID = nullptr;
969             napi_get_named_property(env, global, "localDeviceID_", &localDeviceID);
970             return localDeviceID;
971         }
972     }
973     napi_value result = nullptr;
974     napi_create_string_utf8(env, "", 0, &result);
975     return result;
976 }
977 
NAPI_IPCSkeleton_isLocalCalling(napi_env env,napi_callback_info info)978 napi_value NAPI_IPCSkeleton_isLocalCalling(napi_env env, napi_callback_info info)
979 {
980     napi_value global = nullptr;
981     napi_get_global(env, &global);
982     napi_value napiActiveStatus = nullptr;
983     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
984     if (napiActiveStatus != nullptr) {
985         int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
986         napi_get_value_int32(env, napiActiveStatus, &activeStatus);
987         if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
988             napi_value isLocalCalling = nullptr;
989             napi_get_named_property(env, global, "isLocalCalling_", &isLocalCalling);
990             return isLocalCalling;
991         }
992     }
993     napi_value result = nullptr;
994     napi_get_boolean(env, true, &result);
995     return result;
996 }
997 
NAPI_IPCSkeleton_flushCommands(napi_env env,napi_callback_info info)998 napi_value NAPI_IPCSkeleton_flushCommands(napi_env env, napi_callback_info info)
999 {
1000     size_t argc = 1;
1001     napi_value argv[1] = {0};
1002     napi_value thisVar = nullptr;
1003     void *data = nullptr;
1004     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1005     NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
1006 
1007     napi_valuetype valueType = napi_null;
1008     napi_typeof(env, argv[0], &valueType);
1009     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1010 
1011     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
1012     int32_t result = IPCSkeleton::FlushCommands(target);
1013     napi_value napiValue = nullptr;
1014     NAPI_CALL(env, napi_create_int32(env, result, &napiValue));
1015     return napiValue;
1016 }
1017 
NAPI_IPCSkeleton_flushCmdBuffer(napi_env env,napi_callback_info info)1018 napi_value NAPI_IPCSkeleton_flushCmdBuffer(napi_env env, napi_callback_info info)
1019 {
1020     size_t argc = 1;
1021     napi_value argv[1] = {0};
1022     napi_value thisVar = nullptr;
1023     void *data = nullptr;
1024     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1025     if (argc != 1) {
1026         ZLOGE(LOG_LABEL, "requires 1 parameter");
1027         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1028     }
1029 
1030     napi_valuetype valueType = napi_null;
1031     napi_typeof(env, argv[0], &valueType);
1032     if (valueType != napi_object) {
1033         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1034         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1035     }
1036 
1037     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
1038     IPCSkeleton::FlushCommands(target);
1039     napi_value napiValue = nullptr;
1040     napi_get_undefined(env, &napiValue);
1041     return napiValue;
1042 }
1043 
NAPI_IPCSkeleton_resetCallingIdentity(napi_env env,napi_callback_info info)1044 napi_value NAPI_IPCSkeleton_resetCallingIdentity(napi_env env, napi_callback_info info)
1045 {
1046     napi_value global = nullptr;
1047     napi_get_global(env, &global);
1048     napi_value napiActiveStatus = nullptr;
1049     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1050     int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1051     napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1052     if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1053         napi_value result = nullptr;
1054         napi_create_string_utf8(env, "", 0, &result);
1055         return result;
1056     }
1057     napi_value napiCallingPid = nullptr;
1058     napi_get_named_property(env, global, "callingPid_", &napiCallingPid);
1059     int32_t callerPid;
1060     napi_get_value_int32(env, napiCallingPid, &callerPid);
1061     napi_value napiCallingUid = nullptr;
1062     napi_get_named_property(env, global, "callingUid_", &napiCallingUid);
1063     uint32_t callerUid;
1064     napi_get_value_uint32(env, napiCallingUid, &callerUid);
1065     napi_value napiIsLocalCalling = nullptr;
1066     napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1067     bool isLocalCalling = true;
1068     napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1069     if (isLocalCalling) {
1070         int64_t identity = (static_cast<uint64_t>(callerUid) << PID_LEN) | static_cast<uint64_t>(callerPid);
1071         callerPid = getpid();
1072         callerUid = getuid();
1073         napi_value newCallingPid;
1074         napi_create_int32(env, callerPid, &newCallingPid);
1075         napi_set_named_property(env, global, "callingPid_", newCallingPid);
1076         napi_value newCallingUid;
1077         napi_create_uint32(env, callerUid, &newCallingUid);
1078         napi_set_named_property(env, global, "callingUid_", newCallingUid);
1079         napi_value result = nullptr;
1080         napi_create_string_utf8(env, std::to_string(identity).c_str(), NAPI_AUTO_LENGTH, &result);
1081         return result;
1082     } else {
1083         napi_value napiCallingDeviceID = nullptr;
1084         napi_get_named_property(env, global, "callingDeviceID_", &napiCallingDeviceID);
1085         size_t bufferSize = 0;
1086         size_t maxLen = 4096;
1087         napi_get_value_string_utf8(env, napiCallingDeviceID, nullptr, 0, &bufferSize);
1088         NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1089         char stringValue[bufferSize + 1];
1090         size_t jsStringLength = 0;
1091         napi_get_value_string_utf8(env, napiCallingDeviceID, stringValue, bufferSize + 1, &jsStringLength);
1092         NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1093         std::string callerDeviceID = stringValue;
1094         std::string token = std::to_string(((static_cast<uint64_t>(callerUid) << PID_LEN)
1095             | static_cast<uint64_t>(callerPid)));
1096         std::string identity = callerDeviceID + token;
1097         callerUid = getuid();
1098         napi_value newCallingUid;
1099         napi_create_uint32(env, callerUid, &newCallingUid);
1100         napi_set_named_property(env, global, "callingUid_", newCallingUid);
1101         callerPid = getpid();
1102         napi_value newCallingPid;
1103         napi_create_int32(env, callerPid, &newCallingPid);
1104         napi_set_named_property(env, global, "callingPid_", newCallingPid);
1105         napi_value newCallingDeviceID = nullptr;
1106         napi_get_named_property(env, global, "localDeviceID_", &newCallingDeviceID);
1107         napi_set_named_property(env, global, "callingDeviceID_", newCallingDeviceID);
1108 
1109         napi_value result = nullptr;
1110         napi_create_string_utf8(env, identity.c_str(), NAPI_AUTO_LENGTH, &result);
1111         return result;
1112     }
1113 }
1114 
NAPI_IPCSkeleton_setCallingIdentity(napi_env env,napi_callback_info info)1115 napi_value NAPI_IPCSkeleton_setCallingIdentity(napi_env env, napi_callback_info info)
1116 {
1117     napi_value global = nullptr;
1118     napi_get_global(env, &global);
1119     napi_value napiActiveStatus = nullptr;
1120     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1121     int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1122     napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1123     if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1124         napi_value result = nullptr;
1125         napi_get_boolean(env, true, &result);
1126         return result;
1127     }
1128 
1129     napi_value retValue = nullptr;
1130     napi_get_boolean(env, false, &retValue);
1131 
1132     size_t argc = 1;
1133     size_t expectedArgc = 1;
1134     napi_value argv[1] = { 0 };
1135     napi_value thisVar = nullptr;
1136     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1137     NAPI_ASSERT_BASE(env, argc == expectedArgc, "requires 1 parameters", retValue);
1138     napi_valuetype valueType = napi_null;
1139     napi_typeof(env, argv[0], &valueType);
1140     NAPI_ASSERT_BASE(env, valueType == napi_string, "type mismatch for parameter 1", retValue);
1141     size_t bufferSize = 0;
1142     size_t maxLen = 40960;
1143     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1144     NAPI_ASSERT_BASE(env, bufferSize < maxLen, "string length too large", retValue);
1145     char stringValue[bufferSize + 1];
1146     size_t jsStringLength = 0;
1147     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1148     NAPI_ASSERT_BASE(env, jsStringLength == bufferSize, "string length wrong", retValue);
1149 
1150     std::string identity = stringValue;
1151     napi_value napiIsLocalCalling = nullptr;
1152     napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1153     bool isLocalCalling = true;
1154     napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1155     napi_value result;
1156     if (isLocalCalling) {
1157         if (identity.empty()) {
1158             napi_get_boolean(env, false, &result);
1159             return result;
1160         }
1161 
1162         int64_t token = std::stoll(identity);
1163         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1164         int callerPid = static_cast<int>(token);
1165         napi_value napiCallingPid;
1166         napi_create_int32(env, callerPid, &napiCallingPid);
1167         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1168         napi_value napiCallingUid;
1169         napi_create_int32(env, callerUid, &napiCallingUid);
1170         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1171         napi_get_boolean(env, true, &result);
1172         return result;
1173     } else {
1174         if (identity.empty() || identity.length() <= DEVICEID_LENGTH) {
1175             napi_get_boolean(env, false, &result);
1176             return result;
1177         }
1178 
1179         std::string deviceId = identity.substr(0, DEVICEID_LENGTH);
1180         int64_t token = std::stoll(identity.substr(DEVICEID_LENGTH, identity.length() - DEVICEID_LENGTH));
1181         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1182         int callerPid = static_cast<int>(token);
1183         napi_value napiCallingPid;
1184         napi_create_int32(env, callerPid, &napiCallingPid);
1185         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1186         napi_value napiCallingUid;
1187         napi_create_int32(env, callerUid, &napiCallingUid);
1188         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1189         napi_value napiCallingDeviceID = nullptr;
1190         napi_create_string_utf8(env, deviceId.c_str(), NAPI_AUTO_LENGTH, &napiCallingDeviceID);
1191         napi_set_named_property(env, global, "callingDeviceID_", napiCallingDeviceID);
1192         napi_get_boolean(env, true, &result);
1193         return result;
1194     }
1195 }
1196 
NAPI_IPCSkeleton_restoreCallingIdentitySetProperty(napi_env env,napi_value & global,char * stringValue)1197 static napi_value NAPI_IPCSkeleton_restoreCallingIdentitySetProperty(napi_env env,
1198                                                                      napi_value &global,
1199                                                                      char* stringValue)
1200 {
1201     std::string identity = stringValue;
1202     napi_value napiIsLocalCalling = nullptr;
1203     napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1204     bool isLocalCalling = true;
1205     napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1206     napi_value result;
1207     napi_get_undefined(env, &result);
1208     if (isLocalCalling) {
1209         if (identity.empty()) {
1210             ZLOGE(LOG_LABEL, "identity is empty");
1211             return result;
1212         }
1213 
1214         int64_t token = std::stoll(identity);
1215         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1216         int callerPid = static_cast<int>(token);
1217         napi_value napiCallingPid;
1218         napi_create_int32(env, callerPid, &napiCallingPid);
1219         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1220         napi_value napiCallingUid;
1221         napi_create_int32(env, callerUid, &napiCallingUid);
1222         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1223         return result;
1224     } else {
1225         if (identity.empty() || identity.length() <= DEVICEID_LENGTH) {
1226             ZLOGE(LOG_LABEL, "identity is empty or length is too short");
1227             return result;
1228         }
1229 
1230         std::string deviceId = identity.substr(0, DEVICEID_LENGTH);
1231         int64_t token = std::stoll(identity.substr(DEVICEID_LENGTH, identity.length() - DEVICEID_LENGTH));
1232         int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1233         int callerPid = static_cast<int>(token);
1234         napi_value napiCallingPid;
1235         napi_create_int32(env, callerPid, &napiCallingPid);
1236         napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1237         napi_value napiCallingUid;
1238         napi_create_int32(env, callerUid, &napiCallingUid);
1239         napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1240         napi_value napiCallingDeviceID = nullptr;
1241         napi_create_string_utf8(env, deviceId.c_str(), NAPI_AUTO_LENGTH, &napiCallingDeviceID);
1242         napi_set_named_property(env, global, "callingDeviceID_", napiCallingDeviceID);
1243         return result;
1244     }
1245 }
1246 
NAPI_IPCSkeleton_restoreCallingIdentity(napi_env env,napi_callback_info info)1247 napi_value NAPI_IPCSkeleton_restoreCallingIdentity(napi_env env, napi_callback_info info)
1248 {
1249     napi_value global = nullptr;
1250     napi_get_global(env, &global);
1251     napi_value napiActiveStatus = nullptr;
1252     napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1253     int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1254     napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1255     if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1256         ZLOGD(LOG_LABEL, "status is not active");
1257         napi_value result = nullptr;
1258         napi_get_undefined(env, &result);
1259         return result;
1260     }
1261 
1262     size_t argc = 1;
1263     size_t expectedArgc = 1;
1264     napi_value argv[ARGV_INDEX_1] = { 0 };
1265     napi_value thisVar = nullptr;
1266     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1267     if (argc != expectedArgc) {
1268         ZLOGE(LOG_LABEL, "requires 1 parameter");
1269         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1270     }
1271     napi_valuetype valueType = napi_null;
1272     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1273     if (valueType != napi_string) {
1274         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1275         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1276     }
1277     size_t bufferSize = 0;
1278     size_t maxLen = 40960;
1279     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
1280     if (bufferSize >= maxLen) {
1281         ZLOGE(LOG_LABEL, "string length too large");
1282         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1283     }
1284     char stringValue[bufferSize + 1];
1285     size_t jsStringLength = 0;
1286     napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
1287     if (jsStringLength != bufferSize) {
1288         ZLOGE(LOG_LABEL, "string length wrong");
1289         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1290     }
1291 
1292     return NAPI_IPCSkeleton_restoreCallingIdentitySetProperty(env, global, stringValue);
1293 }
1294 
NAPI_RemoteObject_queryLocalInterface(napi_env env,napi_callback_info info)1295 napi_value NAPI_RemoteObject_queryLocalInterface(napi_env env, napi_callback_info info)
1296 {
1297     size_t argc = 1;
1298     size_t expectedArgc = 1;
1299     napi_value argv[1] = { 0 };
1300     napi_value thisVar = nullptr;
1301     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1302     NAPI_ASSERT(env, argc == expectedArgc, "requires 1 parameters");
1303     napi_valuetype valueType = napi_null;
1304     napi_typeof(env, argv[0], &valueType);
1305     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
1306     size_t bufferSize = 0;
1307     size_t maxLen = 40960;
1308     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1309     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1310     char stringValue[bufferSize + 1];
1311     size_t jsStringLength = 0;
1312     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1313     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1314     std::string descriptor = stringValue;
1315     NAPIRemoteObjectHolder *holder = nullptr;
1316     napi_unwrap(env, thisVar, (void **)&holder);
1317     NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1318     napi_value ret = holder->queryLocalInterface(descriptor);
1319     return ret;
1320 }
1321 
NAPI_RemoteObject_getLocalInterface(napi_env env,napi_callback_info info)1322 napi_value NAPI_RemoteObject_getLocalInterface(napi_env env, napi_callback_info info)
1323 {
1324     size_t argc = 1;
1325     size_t expectedArgc = 1;
1326     napi_value argv[1] = { 0 };
1327     napi_value thisVar = nullptr;
1328     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1329     if (argc != expectedArgc) {
1330         ZLOGE(LOG_LABEL, "requires 1 parameters");
1331         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1332     }
1333     napi_valuetype valueType = napi_null;
1334     napi_typeof(env, argv[0], &valueType);
1335     if (valueType != napi_string) {
1336         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1337         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1338     }
1339     size_t bufferSize = 0;
1340     size_t maxLen = 40960;
1341     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1342     if (bufferSize >= maxLen) {
1343         ZLOGE(LOG_LABEL, "string length too large");
1344         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1345     }
1346     char stringValue[bufferSize + 1];
1347     size_t jsStringLength = 0;
1348     napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1349     if (jsStringLength != bufferSize) {
1350         ZLOGE(LOG_LABEL, "string length wrong");
1351         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1352     }
1353     std::string descriptor = stringValue;
1354     NAPIRemoteObjectHolder *holder = nullptr;
1355     napi_unwrap(env, thisVar, (void **)&holder);
1356     if (holder == nullptr) {
1357         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1358         return nullptr;
1359     }
1360     napi_value ret = holder->queryLocalInterface(descriptor);
1361     return ret;
1362 }
1363 
NAPI_RemoteObject_getInterfaceDescriptor(napi_env env,napi_callback_info info)1364 napi_value NAPI_RemoteObject_getInterfaceDescriptor(napi_env env, napi_callback_info info)
1365 {
1366     napi_value result = nullptr;
1367     napi_value thisVar = nullptr;
1368     napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
1369     sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1370     std::u16string descriptor = nativeObject->GetObjectDescriptor();
1371     napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1372     return result;
1373 }
1374 
NAPI_RemoteObject_getDescriptor(napi_env env,napi_callback_info info)1375 napi_value NAPI_RemoteObject_getDescriptor(napi_env env, napi_callback_info info)
1376 {
1377     napi_value result = nullptr;
1378     napi_value thisVar = nullptr;
1379     napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
1380     sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1381     if (nativeObject == nullptr) {
1382         ZLOGE(LOG_LABEL, "native stub object is nullptr");
1383         return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
1384     }
1385     std::u16string descriptor = nativeObject->GetObjectDescriptor();
1386     napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1387     return result;
1388 }
1389 
NAPI_RemoteObject_getCallingPid(napi_env env,napi_callback_info info)1390 napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
1391 {
1392     return NAPI_IPCSkeleton_getCallingPid(env, info);
1393 }
1394 
NAPI_RemoteObject_getCallingUid(napi_env env,napi_callback_info info)1395 napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
1396 {
1397     return NAPI_IPCSkeleton_getCallingUid(env, info);
1398 }
1399 
MakeSendRequestResult(SendRequestParam * param)1400 napi_value MakeSendRequestResult(SendRequestParam *param)
1401 {
1402     napi_value errCode = nullptr;
1403     napi_create_int32(param->env, param->errCode, &errCode);
1404     napi_value code = nullptr;
1405     napi_get_reference_value(param->env, param->jsCodeRef, &code);
1406     napi_value data = nullptr;
1407     napi_get_reference_value(param->env, param->jsDataRef, &data);
1408     napi_value reply = nullptr;
1409     napi_get_reference_value(param->env, param->jsReplyRef, &reply);
1410     napi_value result = nullptr;
1411     napi_create_object(param->env, &result);
1412     napi_set_named_property(param->env, result, "errCode", errCode);
1413     napi_set_named_property(param->env, result, "code", code);
1414     napi_set_named_property(param->env, result, "data", data);
1415     napi_set_named_property(param->env, result, "reply", reply);
1416     return result;
1417 }
1418 
StubExecuteSendRequest(napi_env env,SendRequestParam * param)1419 void StubExecuteSendRequest(napi_env env, SendRequestParam *param)
1420 {
1421     param->errCode = param->target->SendRequest(param->code,
1422         *(param->data.get()), *(param->reply.get()), param->option);
1423     ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d", param->errCode);
1424     if (param->traceId != 0) {
1425         FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
1426     }
1427     uv_loop_s *loop = nullptr;
1428     napi_get_uv_event_loop(env, &loop);
1429     uv_work_t *work = new uv_work_t;
1430     work->data = reinterpret_cast<void *>(param);
1431     uv_after_work_cb afterWorkCb = nullptr;
1432     if (param->callback != nullptr) {
1433         afterWorkCb = [](uv_work_t *work, int status) {
1434             ZLOGI(LOG_LABEL, "callback started");
1435             SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1436             napi_value result = MakeSendRequestResult(param);
1437             napi_value callback = nullptr;
1438             napi_get_reference_value(param->env, param->callback, &callback);
1439             napi_value cbResult = nullptr;
1440             napi_call_function(param->env, nullptr, callback, 1, &result, &cbResult);
1441             napi_delete_reference(param->env, param->jsCodeRef);
1442             napi_delete_reference(param->env, param->jsDataRef);
1443             napi_delete_reference(param->env, param->jsReplyRef);
1444             napi_delete_reference(param->env, param->callback);
1445             delete param;
1446             delete work;
1447         };
1448     } else {
1449         afterWorkCb = [](uv_work_t *work, int status) {
1450             ZLOGI(LOG_LABEL, "promise fullfilled");
1451             SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1452             napi_value result = MakeSendRequestResult(param);
1453             if (param->errCode == 0) {
1454                 napi_resolve_deferred(param->env, param->deferred, result);
1455             } else {
1456                 napi_reject_deferred(param->env, param->deferred, result);
1457             }
1458             napi_delete_reference(param->env, param->jsCodeRef);
1459             napi_delete_reference(param->env, param->jsDataRef);
1460             napi_delete_reference(param->env, param->jsReplyRef);
1461             delete param;
1462             delete work;
1463         };
1464     }
1465     uv_queue_work(loop, work, [](uv_work_t *work) {}, afterWorkCb);
1466 }
1467 
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)1468 napi_value StubSendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1469     std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1470     MessageOption &option, napi_value *argv)
1471 {
1472     SendRequestParam *sendRequestParam = new SendRequestParam {
1473         .target = target,
1474         .code = code,
1475         .data = data,
1476         .reply = reply,
1477         .option = option,
1478         .asyncWork = nullptr,
1479         .deferred = nullptr,
1480         .errCode = -1,
1481         .jsCodeRef = nullptr,
1482         .jsDataRef = nullptr,
1483         .jsReplyRef = nullptr,
1484         .callback = nullptr,
1485         .env = env,
1486         .traceId = 0,
1487     };
1488     if (target != nullptr) {
1489         std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1490         if (!remoteDescriptor.empty()) {
1491             sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1492             sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1493             StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1494         }
1495     }
1496     napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1497     napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1498     napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1499     napi_create_reference(env, argv[4], 1, &sendRequestParam->callback);
1500     std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1501     t.detach();
1502     napi_value result = nullptr;
1503     napi_get_undefined(env, &result);
1504     return result;
1505 }
1506 
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)1507 napi_value StubSendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1508     std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1509     MessageOption &option, napi_value *argv)
1510 {
1511     napi_deferred deferred = nullptr;
1512     napi_value promise = nullptr;
1513     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1514     SendRequestParam *sendRequestParam = new SendRequestParam {
1515         .target = target,
1516         .code = code,
1517         .data = data,
1518         .reply = reply,
1519         .option = option,
1520         .asyncWork = nullptr,
1521         .deferred = deferred,
1522         .errCode = -1,
1523         .jsCodeRef = nullptr,
1524         .jsDataRef = nullptr,
1525         .jsReplyRef = nullptr,
1526         .callback = nullptr,
1527         .env = env,
1528         .traceId = 0,
1529     };
1530     if (target != nullptr) {
1531         std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1532         if (!remoteDescriptor.empty()) {
1533             sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1534             sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1535             StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1536         }
1537     }
1538     napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1539     napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1540     napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1541     std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1542     t.detach();
1543     return promise;
1544 }
1545 
NAPI_RemoteObject_sendRequest(napi_env env,napi_callback_info info)1546 napi_value NAPI_RemoteObject_sendRequest(napi_env env, napi_callback_info info)
1547 {
1548     size_t argc = 4;
1549     size_t argcCallback = 5;
1550     size_t argcPromise = 4;
1551     napi_value argv[5] = { 0 };
1552     napi_value thisVar = nullptr;
1553     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1554     NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1555     napi_valuetype valueType = napi_null;
1556     napi_typeof(env, argv[0], &valueType);
1557     NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1558     napi_typeof(env, argv[1], &valueType);
1559     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1560     napi_typeof(env, argv[2], &valueType);
1561     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1562     napi_typeof(env, argv[3], &valueType);
1563     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1564 
1565     NAPI_MessageParcel *data = nullptr;
1566     napi_status status = napi_unwrap(env, argv[1], (void **)&data);
1567     NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1568     NAPI_MessageParcel *reply = nullptr;
1569     status = napi_unwrap(env, argv[2], (void **)&reply);
1570     NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1571     MessageOption *option = nullptr;
1572     status = napi_unwrap(env, argv[3], (void **)&option);
1573     NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1574     int32_t code = 0;
1575     napi_get_value_int32(env, argv[0], &code);
1576 
1577     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1578     if (argc == argcCallback) {
1579         napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1580         napi_valuetype valuetype = napi_undefined;
1581         napi_typeof(env, argv[argcPromise], &valuetype);
1582         if (valuetype == napi_function) {
1583             return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1584                 reply->GetMessageParcel(), *option, argv);
1585         }
1586     }
1587     return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1588         reply->GetMessageParcel(), *option, argv);
1589 }
1590 
NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,size_t argc,size_t argcCallback,size_t argcPromise,napi_value * argv)1591 napi_value NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,
1592                                                          size_t argc,
1593                                                          size_t argcCallback,
1594                                                          size_t argcPromise,
1595                                                          napi_value* argv)
1596 {
1597     if (argc != argcPromise && argc != argcCallback) {
1598         ZLOGE(LOG_LABEL, "requires 4 or 5 parameters");
1599         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1600     }
1601     napi_valuetype valueType = napi_null;
1602     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1603     if (valueType != napi_number) {
1604         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1605         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1606     }
1607     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1608     if (valueType != napi_object) {
1609         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1610         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1611     }
1612     napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1613     if (valueType != napi_object) {
1614         ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
1615         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1616     }
1617     napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1618     if (valueType != napi_object) {
1619         ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
1620         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1621     }
1622     napi_value result = nullptr;
1623     napi_get_undefined(env, &result);
1624     return result;
1625 }
1626 
NAPI_RemoteObject_sendMessageRequest(napi_env env,napi_callback_info info)1627 napi_value NAPI_RemoteObject_sendMessageRequest(napi_env env, napi_callback_info info)
1628 {
1629     size_t argc = 4;
1630     size_t argcCallback = 5;
1631     size_t argcPromise = 4;
1632     napi_value argv[5] = { 0 };
1633     napi_value thisVar = nullptr;
1634     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1635     napi_value checkArgsResult = NAPI_RemoteObject_checkSendMessageRequestArgs(env, argc, argcCallback, argcPromise,
1636                                                                                argv);
1637     if (checkArgsResult == nullptr) {
1638         return checkArgsResult;
1639     }
1640     NAPI_MessageSequence *data = nullptr;
1641     napi_status status = napi_unwrap(env, argv[1], (void **)&data);
1642     if (status != napi_ok) {
1643         ZLOGE(LOG_LABEL, "failed to get data message sequence");
1644         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1645     }
1646     NAPI_MessageSequence *reply = nullptr;
1647     status = napi_unwrap(env, argv[2], (void **)&reply);
1648     if (status != napi_ok) {
1649         ZLOGE(LOG_LABEL, "failed to get data message sequence");
1650         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1651     }
1652     MessageOption *option = nullptr;
1653     status = napi_unwrap(env, argv[3], (void **)&option);
1654     if (status != napi_ok) {
1655         ZLOGE(LOG_LABEL, "failed to get message option");
1656         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1657     }
1658     int32_t code = 0;
1659     napi_get_value_int32(env, argv[0], &code);
1660 
1661     sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1662     if (argc == argcCallback) {
1663         napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1664         napi_valuetype valuetype = napi_undefined;
1665         napi_typeof(env, argv[argcPromise], &valuetype);
1666         if (valuetype == napi_function) {
1667             return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1668                 reply->GetMessageParcel(), *option, argv);
1669         }
1670     }
1671     return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1672         reply->GetMessageParcel(), *option, argv);
1673 }
1674 
NAPI_RemoteObject_attachLocalInterface(napi_env env,napi_callback_info info)1675 napi_value NAPI_RemoteObject_attachLocalInterface(napi_env env, napi_callback_info info)
1676 {
1677     size_t argc = 2;
1678     size_t expectedArgc = 2;
1679     napi_value argv[2] = { 0 };
1680     napi_value thisVar = nullptr;
1681     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1682     NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameters");
1683     napi_valuetype valueType = napi_null;
1684     napi_typeof(env, argv[0], &valueType);
1685     NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1686     napi_typeof(env, argv[1], &valueType);
1687     NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 2");
1688     size_t bufferSize = 0;
1689     size_t maxLen = 40960;
1690     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &bufferSize);
1691     NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1692     char stringValue[bufferSize + 1];
1693     size_t jsStringLength = 0;
1694     napi_get_value_string_utf8(env, argv[1], stringValue, bufferSize + 1, &jsStringLength);
1695     NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1696     std::string descriptor = stringValue;
1697 
1698     NAPIRemoteObjectHolder *holder = nullptr;
1699     napi_unwrap(env, thisVar, (void* *)&holder);
1700     NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1701     holder->attachLocalInterface(argv[0], descriptor);
1702 
1703     napi_value result = nullptr;
1704     napi_get_undefined(env, &result);
1705     return result;
1706 }
1707 
NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env,size_t argc,napi_value * argv)1708 napi_value NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env, size_t argc, napi_value* argv)
1709 {
1710     size_t expectedArgc = 2;
1711 
1712     if (argc != expectedArgc) {
1713         ZLOGE(LOG_LABEL, "requires 2 parameters");
1714         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1715     }
1716     napi_valuetype valueType = napi_null;
1717     napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1718     if (valueType != napi_object) {
1719         ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1720         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1721     }
1722     napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1723     if (valueType != napi_string) {
1724         ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1725         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1726     }
1727     napi_value result = nullptr;
1728     napi_get_undefined(env, &result);
1729     return result;
1730 }
1731 
NAPI_RemoteObject_modifyLocalInterface(napi_env env,napi_callback_info info)1732 napi_value NAPI_RemoteObject_modifyLocalInterface(napi_env env, napi_callback_info info)
1733 {
1734     size_t argc = 2;
1735     napi_value argv[2] = { 0 };
1736     napi_value thisVar = nullptr;
1737     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1738     napi_value checkArgsResult = NAPI_RemoteObject_checkModifyLocalInterfaceArgs(env, argc, argv);
1739     if (checkArgsResult == nullptr) {
1740         return checkArgsResult;
1741     }
1742     size_t bufferSize = 0;
1743     size_t maxLen = 40960;
1744     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &bufferSize);
1745     if (bufferSize >= maxLen) {
1746         ZLOGE(LOG_LABEL, "string length too large");
1747         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1748     }
1749     char stringValue[bufferSize + 1];
1750     size_t jsStringLength = 0;
1751     napi_get_value_string_utf8(env, argv[1], stringValue, bufferSize + 1, &jsStringLength);
1752     if (jsStringLength != bufferSize) {
1753         ZLOGE(LOG_LABEL, "string length wrong");
1754         return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1755     }
1756     std::string descriptor = stringValue;
1757 
1758     NAPIRemoteObjectHolder *holder = nullptr;
1759     napi_unwrap(env, thisVar, (void* *)&holder);
1760     if (holder == nullptr) {
1761         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1762         return nullptr;
1763     }
1764     holder->attachLocalInterface(argv[0], descriptor);
1765 
1766     napi_value result = nullptr;
1767     napi_get_undefined(env, &result);
1768     return result;
1769 }
1770 
NAPI_RemoteObject_addDeathRecipient(napi_env env,napi_callback_info info)1771 napi_value NAPI_RemoteObject_addDeathRecipient(napi_env env, napi_callback_info info)
1772 {
1773     napi_value result = nullptr;
1774     napi_get_boolean(env, false, &result);
1775     return result;
1776 }
1777 
NAPI_RemoteObject_registerDeathRecipient(napi_env env,napi_callback_info info)1778 napi_value NAPI_RemoteObject_registerDeathRecipient(napi_env env, napi_callback_info info)
1779 {
1780     ZLOGE(LOG_LABEL, "only proxy object permitted");
1781     return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1782 }
1783 
NAPI_RemoteObject_removeDeathRecipient(napi_env env,napi_callback_info info)1784 napi_value NAPI_RemoteObject_removeDeathRecipient(napi_env env, napi_callback_info info)
1785 {
1786     napi_value result = nullptr;
1787     napi_get_boolean(env, false, &result);
1788     return result;
1789 }
1790 
NAPI_RemoteObject_unregisterDeathRecipient(napi_env env,napi_callback_info info)1791 napi_value NAPI_RemoteObject_unregisterDeathRecipient(napi_env env, napi_callback_info info)
1792 {
1793     ZLOGE(LOG_LABEL, "only proxy object permitted");
1794     return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1795 }
1796 
NAPI_RemoteObject_isObjectDead(napi_env env,napi_callback_info info)1797 napi_value NAPI_RemoteObject_isObjectDead(napi_env env, napi_callback_info info)
1798 {
1799     napi_value result = nullptr;
1800     napi_get_boolean(env, false, &result);
1801     return result;
1802 }
1803 
NAPIIPCSkeleton_JS_Constructor(napi_env env,napi_callback_info info)1804 napi_value NAPIIPCSkeleton_JS_Constructor(napi_env env, napi_callback_info info)
1805 {
1806     napi_value thisArg = nullptr;
1807     void *data = nullptr;
1808     napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
1809     napi_value global = nullptr;
1810     napi_get_global(env, &global);
1811     return thisArg;
1812 }
1813 
1814 EXTERN_C_START
1815 /*
1816  * function for module exports
1817  */
NAPIIPCSkeletonExport(napi_env env,napi_value exports)1818 napi_value NAPIIPCSkeletonExport(napi_env env, napi_value exports)
1819 {
1820     ZLOGI(LOG_LABEL, "napi_moudule IPCSkeleton Init start...");
1821     napi_property_descriptor desc[] = {
1822         DECLARE_NAPI_STATIC_FUNCTION("getContextObject", NAPI_IPCSkeleton_getContextObject),
1823         DECLARE_NAPI_STATIC_FUNCTION("getCallingPid", NAPI_IPCSkeleton_getCallingPid),
1824         DECLARE_NAPI_STATIC_FUNCTION("getCallingUid", NAPI_IPCSkeleton_getCallingUid),
1825         DECLARE_NAPI_STATIC_FUNCTION("getCallingDeviceID", NAPI_IPCSkeleton_getCallingDeviceID),
1826         DECLARE_NAPI_STATIC_FUNCTION("getLocalDeviceID", NAPI_IPCSkeleton_getLocalDeviceID),
1827         DECLARE_NAPI_STATIC_FUNCTION("isLocalCalling", NAPI_IPCSkeleton_isLocalCalling),
1828         DECLARE_NAPI_STATIC_FUNCTION("flushCmdBuffer", NAPI_IPCSkeleton_flushCmdBuffer),
1829         DECLARE_NAPI_STATIC_FUNCTION("flushCommands", NAPI_IPCSkeleton_flushCommands),
1830         DECLARE_NAPI_STATIC_FUNCTION("resetCallingIdentity", NAPI_IPCSkeleton_resetCallingIdentity),
1831         DECLARE_NAPI_STATIC_FUNCTION("restoreCallingIdentity", NAPI_IPCSkeleton_restoreCallingIdentity),
1832         DECLARE_NAPI_STATIC_FUNCTION("setCallingIdentity", NAPI_IPCSkeleton_setCallingIdentity),
1833         DECLARE_NAPI_STATIC_FUNCTION("getCallingTokenId", NAPI_IPCSkeleton_getCallingTokenId),
1834     };
1835     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1836     napi_value result = nullptr;
1837     napi_define_class(env, "IPCSkeleton", NAPI_AUTO_LENGTH, NAPIIPCSkeleton_JS_Constructor, nullptr,
1838         sizeof(desc) / sizeof(desc[0]), desc, &result);
1839     napi_status status = napi_set_named_property(env, exports, "IPCSkeleton", result);
1840     NAPI_ASSERT(env, status == napi_ok, "create ref to js RemoteObject constructor failed");
1841     ZLOGI(LOG_LABEL, "napi_moudule IPCSkeleton Init end...");
1842     return exports;
1843 }
1844 EXTERN_C_END
1845 
NAPIMessageOption_JS_Constructor(napi_env env,napi_callback_info info)1846 napi_value NAPIMessageOption_JS_Constructor(napi_env env, napi_callback_info info)
1847 {
1848     size_t argc = 2;
1849     napi_value argv[2] = { 0 };
1850     napi_value thisVar = nullptr;
1851     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1852     NAPI_ASSERT(env, argc >= 0, "invalid parameter number");
1853     int flags = 0;
1854     int waittime = 0;
1855     if (argc == 0) {
1856         flags = MessageOption::TF_SYNC;
1857         waittime = MessageOption::TF_WAIT_TIME;
1858     } else if (argc == 1) {
1859         napi_valuetype valueType;
1860         napi_typeof(env, argv[0], &valueType);
1861         NAPI_ASSERT(env, valueType == napi_number || valueType == napi_boolean, "type mismatch for parameter 1");
1862         if (valueType == napi_boolean) {
1863             bool jsBoolFlags = false;
1864             napi_get_value_bool(env, argv[0], &jsBoolFlags);
1865             flags = jsBoolFlags ? MessageOption::TF_ASYNC : MessageOption::TF_SYNC;
1866         } else {
1867             int32_t jsFlags = 0;
1868             napi_get_value_int32(env, argv[0], &jsFlags);
1869             flags = jsFlags == 0 ? MessageOption::TF_SYNC : MessageOption::TF_ASYNC;
1870         }
1871         waittime = MessageOption::TF_WAIT_TIME;
1872     } else {
1873         napi_valuetype valueType = napi_null;
1874         napi_typeof(env, argv[0], &valueType);
1875         NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1876         napi_typeof(env, argv[1], &valueType);
1877         NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
1878         int32_t jsFlags = 0;
1879         napi_get_value_int32(env, argv[0], &jsFlags);
1880         int32_t jsWaittime = 0;
1881         napi_get_value_int32(env, argv[1], &jsWaittime);
1882         flags = jsFlags == 0 ? MessageOption::TF_SYNC : MessageOption::TF_ASYNC;
1883         waittime = jsWaittime;
1884     }
1885 
1886     auto messageOption = new MessageOption(flags, waittime);
1887     // connect native message option to js thisVar
1888     napi_status status = napi_wrap(
1889         env, thisVar, messageOption,
1890         [](napi_env env, void *data, void *hint) {
1891             ZLOGI(LOG_LABEL, "NAPIMessageOption destructed by js callback");
1892             delete (reinterpret_cast<MessageOption *>(data));
1893         },
1894         nullptr, nullptr);
1895     NAPI_ASSERT(env, status == napi_ok, "wrap js MessageOption and native option failed");
1896     return thisVar;
1897 }
1898 
1899 EXTERN_C_START
1900 /*
1901  * function for module exports
1902  */
NAPIMessageOptionExport(napi_env env,napi_value exports)1903 napi_value NAPIMessageOptionExport(napi_env env, napi_value exports)
1904 {
1905     const std::string className = "MessageOption";
1906     napi_value tfSync = nullptr;
1907     napi_create_int32(env, MessageOption::TF_SYNC, &tfSync);
1908     napi_value tfAsync = nullptr;
1909     napi_create_int32(env, MessageOption::TF_ASYNC, &tfAsync);
1910     napi_value tfFds = nullptr;
1911     napi_create_int32(env, MessageOption::TF_ACCEPT_FDS, &tfFds);
1912     napi_value tfWaitTime = nullptr;
1913     napi_create_int32(env, MessageOption::TF_WAIT_TIME, &tfWaitTime);
1914     napi_property_descriptor properties[] = {
1915         DECLARE_NAPI_FUNCTION("getFlags", NapiOhosRpcMessageOptionGetFlags),
1916         DECLARE_NAPI_FUNCTION("setFlags", NapiOhosRpcMessageOptionSetFlags),
1917         DECLARE_NAPI_FUNCTION("isAsync", NapiOhosRpcMessageOptionIsAsync),
1918         DECLARE_NAPI_FUNCTION("setAsync", NapiOhosRpcMessageOptionSetAsync),
1919         DECLARE_NAPI_FUNCTION("getWaitTime", NapiOhosRpcMessageOptionGetWaittime),
1920         DECLARE_NAPI_FUNCTION("setWaitTime", NapiOhosRpcMessageOptionSetWaittime),
1921         DECLARE_NAPI_STATIC_PROPERTY("TF_SYNC", tfSync),
1922         DECLARE_NAPI_STATIC_PROPERTY("TF_ASYNC", tfAsync),
1923         DECLARE_NAPI_STATIC_PROPERTY("TF_ACCEPT_FDS", tfFds),
1924         DECLARE_NAPI_STATIC_PROPERTY("TF_WAIT_TIME", tfWaitTime),
1925     };
1926     napi_value constructor = nullptr;
1927     napi_define_class(env, className.c_str(), className.length(), NAPIMessageOption_JS_Constructor, nullptr,
1928         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
1929     NAPI_ASSERT(env, constructor != nullptr, "define js class MessageOption failed");
1930     napi_status status = napi_set_named_property(env, exports, "MessageOption", constructor);
1931     NAPI_ASSERT(env, status == napi_ok, "set property MessageOption to exports failed");
1932     napi_value global = nullptr;
1933     status = napi_get_global(env, &global);
1934     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
1935     status = napi_set_named_property(env, global, "IPCOptionConstructor_", constructor);
1936     NAPI_ASSERT(env, status == napi_ok, "set message option constructor failed");
1937     return exports;
1938 }
1939 EXTERN_C_END
1940 } // namespace OHOS
1941