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