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