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