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