1 /*
2 * Copyright (c) 2023 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_holder.h"
17 #include "napi_remote_object_internal.h"
18
19 #include <hitrace_meter.h>
20 #include <string_ex.h>
21 #include <uv.h>
22
23 #include "ipc_debug.h"
24 #include "ipc_process_skeleton.h"
25 #include "iremote_invoker.h"
26 #include "log_tags.h"
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "napi_message_parcel.h"
30 #include "napi_message_sequence.h"
31 #include "napi_remote_proxy_holder.h"
32 #include "napi_rpc_error.h"
33 #include "native_engine/native_value.h"
34 #include "napi_process_skeleton.h"
35
36 namespace OHOS {
37 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_NAPI, "napi_remoteObject" };
38
39 static const size_t ARGV_INDEX_0 = 0;
40 static const size_t ARGV_INDEX_1 = 1;
41 static const size_t ARGV_INDEX_2 = 2;
42 static const size_t ARGV_INDEX_3 = 3;
43 static const size_t ARGV_INDEX_4 = 4;
44
45 static const size_t ARGV_LENGTH_1 = 1;
46 static const size_t ARGV_LENGTH_2 = 2;
47 static const size_t ARGV_LENGTH_5 = 5;
48
49 static const size_t DEVICE_ID_LENGTH = 64;
50
51 static const uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag.
52
53 static std::atomic<int32_t> bytraceId = 1000;
54 static NapiError napiErr;
55
RemoteObjectHolderFinalizeCb(napi_env env,void * data,void * hint)56 static void RemoteObjectHolderFinalizeCb(napi_env env, void *data, void *hint)
57 {
58 NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
59 if (holder == nullptr) {
60 ZLOGW(LOG_LABEL, "RemoteObjectHolderFinalizeCb null holder");
61 return;
62 }
63 holder->Lock();
64 int32_t curAttachCount = holder->DecAttachCount();
65 ZLOGD(LOG_LABEL, "NAPIRemoteObjectHolder destructed by js callback, curAttachCount:%{public}d", curAttachCount);
66 if (curAttachCount == 0) {
67 delete holder;
68 }
69 }
70
DecreaseJsObjectRef(napi_env env,napi_ref ref)71 static void DecreaseJsObjectRef(napi_env env, napi_ref ref)
72 {
73 if (ref == nullptr) {
74 ZLOGI(LOG_LABEL, "ref is nullptr, do nothing");
75 return;
76 }
77
78 uint32_t result;
79 napi_status napiStatus = napi_reference_unref(env, ref, &result);
80 NAPI_ASSERT_RETURN_VOID(env, napiStatus == napi_ok, "failed to decrease ref to js RemoteObject");
81 }
82
IncreaseJsObjectRef(napi_env env,napi_ref ref)83 static void IncreaseJsObjectRef(napi_env env, napi_ref ref)
84 {
85 uint32_t result;
86 napi_status napiStatus = napi_reference_ref(env, ref, &result);
87 NAPI_ASSERT_RETURN_VOID(env, napiStatus == napi_ok, "failed to increase ref to js RemoteObject");
88 }
89
RemoteObjectHolderRefCb(napi_env env,void * data,void * hint)90 static void RemoteObjectHolderRefCb(napi_env env, void *data, void *hint)
91 {
92 NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
93 NAPI_ASSERT_RETURN_VOID(env, holder != nullptr, "holder is nullptr");
94 holder->Lock();
95 int32_t curAttachCount = holder->DecAttachCount();
96 holder->Unlock();
97 ZLOGD(LOG_LABEL, "RemoteObjectHolderRefCb, curAttachCount:%{public}d", curAttachCount);
98
99 napi_ref ref = holder->GetJsObjectRef();
100 NAPI_ASSERT_RETURN_VOID(env, ref != nullptr, "ref is nullptr");
101 napi_env workerEnv = holder->GetJsObjectEnv();
102 NAPI_ASSERT_RETURN_VOID(env, workerEnv != nullptr, "workerEnv is nullptr");
103 uv_loop_s *loop = nullptr;
104 napi_get_uv_event_loop(workerEnv, &loop);
105 uv_work_t *work = new (std::nothrow) uv_work_t;
106 NAPI_ASSERT_RETURN_VOID(workerEnv, loop != nullptr, "loop is nullptr");
107
108 NAPI_ASSERT_RETURN_VOID(workerEnv, work != nullptr, "cb failed to new work");
109 OperateJsRefParam *param = new (std::nothrow) OperateJsRefParam {
110 .env = workerEnv,
111 .thisVarRef = ref
112 };
113 if (param == nullptr) {
114 delete work;
115 NAPI_ASSERT_RETURN_VOID(workerEnv, false, "new OperateJsRefParam failed");
116 }
117 work->data = reinterpret_cast<void *>(param);
118 int uvRet = uv_queue_work(loop, work, [](uv_work_t *work) {
119 ZLOGD(LOG_LABEL, "enter work pool.");
120 }, [](uv_work_t *work, int status) {
121 ZLOGI(LOG_LABEL, "decrease on uv work thread");
122 OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
123 napi_handle_scope scope = nullptr;
124 napi_open_handle_scope(param->env, &scope);
125 DecreaseJsObjectRef(param->env, param->thisVarRef);
126 napi_close_handle_scope(param->env, scope);
127 delete param;
128 delete work;
129 });
130 if (uvRet != 0) {
131 delete param;
132 delete work;
133 ZLOGE(LOG_LABEL, "uv_queue_work failed, ret %{public}d", uvRet);
134 }
135 }
136
RemoteObjectDetachCb(napi_env engine,void * value,void * hint)137 static void *RemoteObjectDetachCb(napi_env engine, void *value, void *hint)
138 {
139 (void)hint;
140 napi_env env = engine;
141 NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(value);
142 napi_ref ref = holder->GetJsObjectRef();
143
144 uint32_t result;
145 napi_status napiStatus = napi_reference_ref(env, ref, &result);
146 if (napiStatus != napi_ok) {
147 ZLOGE(LOG_LABEL, "RemoteObjectDetachCb, failed to increase ref");
148 } else {
149 ZLOGI(LOG_LABEL, "RemoteObjectDetachCb, ref result:%{public}u", result);
150 }
151 return value;
152 }
153
RemoteObjectAttachCb(napi_env engine,void * value,void * hint)154 static napi_value RemoteObjectAttachCb(napi_env engine, void *value, void *hint)
155 {
156 (void)hint;
157 NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(value);
158 if (holder == nullptr) {
159 ZLOGE(LOG_LABEL, "holder is nullptr when attach");
160 return nullptr;
161 }
162 holder->Lock();
163 ZLOGI(LOG_LABEL, "create js remote object when attach");
164 napi_env env = engine;
165 // retrieve js remote object constructor
166 napi_value global = nullptr;
167 napi_status status = napi_get_global(env, &global);
168 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
169 napi_value constructor = nullptr;
170 status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
171 NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
172 NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
173 // retrieve descriptor and it's length
174 std::u16string descriptor = holder->GetDescriptor();
175 std::string desc = Str16ToStr8(descriptor);
176 napi_value jsDesc = nullptr;
177 napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
178 // create a new js remote object
179 size_t argc = 1;
180 napi_value argv[ARGV_LENGTH_1] = { jsDesc };
181 napi_value jsRemoteObject = nullptr;
182 status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
183 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteObject when attach");
184 // retrieve and remove create holder
185 NAPIRemoteObjectHolder *createHolder = nullptr;
186 status = napi_remove_wrap(env, jsRemoteObject, (void **)&createHolder);
187 NAPI_ASSERT(env, status == napi_ok && createHolder != nullptr, "failed to remove create holder when attach");
188 status = napi_wrap(env, jsRemoteObject, holder, RemoteObjectHolderRefCb, nullptr, nullptr);
189 NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed when attach");
190 holder->IncAttachCount();
191 holder->Unlock();
192 return jsRemoteObject;
193 }
194
RemoteObject_JS_Constructor(napi_env env,napi_callback_info info)195 napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
196 {
197 // new napi remote object
198 size_t argc = 2;
199 size_t expectedArgc = 1;
200 napi_value argv[ARGV_LENGTH_2] = { 0 };
201 napi_value thisVar = nullptr;
202 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
203 NAPI_ASSERT(env, argc >= expectedArgc, "requires at least 1 parameters");
204 napi_valuetype valueType = napi_null;
205 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
206 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
207 size_t bufferSize = 0;
208 size_t maxLen = 40960;
209 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
210 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
211 char stringValue[bufferSize + 1];
212 size_t jsStringLength = 0;
213 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
214 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
215 std::string descriptor = stringValue;
216 auto holder = new (std::nothrow) NAPIRemoteObjectHolder(env, Str8ToStr16(descriptor), thisVar);
217 NAPI_ASSERT(env, holder != nullptr, "new NAPIRemoteObjectHolder failed");
218 napi_status status = napi_coerce_to_native_binding_object(env, thisVar, RemoteObjectDetachCb, RemoteObjectAttachCb,
219 holder, nullptr);
220 if (status != napi_ok) {
221 delete holder;
222 NAPI_ASSERT(env, false, "bind native RemoteObject failed");
223 }
224 // connect native object to js thisVar
225 status = napi_wrap(env, thisVar, holder, RemoteObjectHolderFinalizeCb, nullptr, nullptr);
226 if (status != napi_ok) {
227 delete holder;
228 NAPI_ASSERT(env, false, "wrap js RemoteObject and native holder failed");
229 }
230 return thisVar;
231 }
232
NAPIRemoteObject(std::thread::id jsThreadId,napi_env env,napi_ref jsObjectRef,const std::u16string & descriptor)233 NAPIRemoteObject::NAPIRemoteObject(std::thread::id jsThreadId, napi_env env, napi_ref jsObjectRef,
234 const std::u16string &descriptor)
235 : IPCObjectStub(descriptor)
236 {
237 ZLOGD(LOG_LABEL, "created, desc:%{public}s", Str16ToStr8(descriptor_).c_str());
238 env_ = env;
239 jsThreadId_ = jsThreadId;
240 thisVarRef_ = jsObjectRef;
241
242 if (jsThreadId_ == std::this_thread::get_id()) {
243 IncreaseJsObjectRef(env_, jsObjectRef);
244 } else {
245 uv_loop_s *loop = nullptr;
246 napi_get_uv_event_loop(env_, &loop);
247 NAPI_ASSERT_RETURN_VOID(env_, loop != nullptr, "loop is nullptr");
248 uv_work_t *work = new (std::nothrow) uv_work_t;
249 NAPI_ASSERT_RETURN_VOID(env_, work != nullptr, "create NAPIRemoteObject, new work failed");
250 std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
251 OperateJsRefParam *param = new (std::nothrow) OperateJsRefParam {
252 .env = env_,
253 .thisVarRef = jsObjectRef,
254 .lockInfo = lockInfo.get()
255 };
256 if (param == nullptr) {
257 delete work;
258 NAPI_ASSERT_RETURN_VOID(env_, false, "new OperateJsRefParam failed");
259 }
260
261 work->data = reinterpret_cast<void *>(param);
262 int uvRet = uv_queue_work(loop, work, [](uv_work_t *work) {
263 ZLOGD(LOG_LABEL, "enter work pool.");
264 }, [](uv_work_t *work, int status) {
265 OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
266 napi_handle_scope scope = nullptr;
267 napi_open_handle_scope(param->env, &scope);
268 IncreaseJsObjectRef(param->env, param->thisVarRef);
269 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
270 param->lockInfo->ready = true;
271 param->lockInfo->condition.notify_all();
272 napi_close_handle_scope(param->env, scope);
273 });
274 if (uvRet != 0) {
275 ZLOGE(LOG_LABEL, "uv_queue_work failed, ret %{public}d", uvRet);
276 } else {
277 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
278 param->lockInfo->condition.wait(lock, [¶m] { return param->lockInfo->ready; });
279 }
280 delete param;
281 delete work;
282 }
283 }
284
~NAPIRemoteObject()285 NAPIRemoteObject::~NAPIRemoteObject()
286 {
287 ZLOGD(LOG_LABEL, "destoryed, desc:%{public}s", Str16ToStr8(descriptor_).c_str());
288 if (thisVarRef_ != nullptr && env_ != nullptr) {
289 if (jsThreadId_ == std::this_thread::get_id()) {
290 DecreaseJsObjectRef(env_, thisVarRef_);
291 } else {
292 uv_loop_s *loop = nullptr;
293 napi_get_uv_event_loop(env_, &loop);
294 NAPI_ASSERT_RETURN_VOID(env_, loop != nullptr, "loop is nullptr");
295 uv_work_t *work = new (std::nothrow) uv_work_t;
296 NAPI_ASSERT_RETURN_VOID(env_, work != nullptr, "release NAPIRemoteObject, new work failed");
297 OperateJsRefParam *param = new (std::nothrow) OperateJsRefParam {
298 .env = env_,
299 .thisVarRef = thisVarRef_
300 };
301 if (param == nullptr) {
302 thisVarRef_ = nullptr;
303 delete work;
304 NAPI_ASSERT_RETURN_VOID(env_, false, "new OperateJsRefParam failed");
305 }
306 work->data = reinterpret_cast<void *>(param);
307 int uvRet = uv_queue_work(loop, work, [](uv_work_t *work) {
308 ZLOGD(LOG_LABEL, "enter work pool.");
309 }, [](uv_work_t *work, int status) {
310 OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
311 napi_handle_scope scope = nullptr;
312 napi_open_handle_scope(param->env, &scope);
313 DecreaseJsObjectRef(param->env, param->thisVarRef);
314 napi_close_handle_scope(param->env, scope);
315 delete param;
316 delete work;
317 });
318 if (uvRet != 0) {
319 ZLOGE(LOG_LABEL, "uv_queue_work failed, ret %{public}d", uvRet);
320 delete param;
321 delete work;
322 }
323 }
324 thisVarRef_ = nullptr;
325 }
326 }
327
CheckObjectLegality() const328 bool NAPIRemoteObject::CheckObjectLegality() const
329 {
330 return true;
331 }
332
GetObjectType() const333 int NAPIRemoteObject::GetObjectType() const
334 {
335 return OBJECT_TYPE_JAVASCRIPT;
336 }
337
GetJsObjectRef() const338 napi_ref NAPIRemoteObject::GetJsObjectRef() const
339 {
340 return thisVarRef_;
341 }
342
ResetJsEnv()343 void NAPIRemoteObject::ResetJsEnv()
344 {
345 env_ = nullptr;
346 thisVarRef_ = nullptr;
347 }
348
NAPI_RemoteObject_getCallingInfo(CallingInfo & newCallingInfoParam)349 void NAPI_RemoteObject_getCallingInfo(CallingInfo &newCallingInfoParam)
350 {
351 newCallingInfoParam.callingPid = IPCSkeleton::GetCallingPid();
352 newCallingInfoParam.callingUid = IPCSkeleton::GetCallingUid();
353 newCallingInfoParam.callingTokenId = IPCSkeleton::GetCallingTokenID();
354 newCallingInfoParam.callingDeviceID = IPCSkeleton::GetCallingDeviceID();
355 newCallingInfoParam.localDeviceID = IPCSkeleton::GetLocalDeviceID();
356 newCallingInfoParam.isLocalCalling = IPCSkeleton::IsLocalCalling();
357 newCallingInfoParam.activeStatus = IRemoteInvoker::ACTIVE_INVOKER;
358 };
359
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)360 int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
361 {
362 ZLOGD(LOG_LABEL, "enter OnRemoteRequest");
363 if (code == DUMP_TRANSACTION) {
364 ZLOGE(LOG_LABEL, "DUMP_TRANSACTION data size:%{public}zu", data.GetReadableBytes());
365 }
366 std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
367 CallbackParam *param = new (std::nothrow) CallbackParam {
368 .env = env_,
369 .thisVarRef = thisVarRef_,
370 .code = code,
371 .data = &data,
372 .reply = &reply,
373 .option = &option,
374 .lockInfo = lockInfo.get(),
375 .result = 0
376 };
377 if (param == nullptr) {
378 ZLOGE(LOG_LABEL, "new CallbackParam failed");
379 return ERR_ALLOC_MEMORY;
380 }
381
382 NAPI_RemoteObject_getCallingInfo(param->callingInfo);
383 ZLOGD(LOG_LABEL, "callingPid:%{public}u callingUid:%{public}u "
384 "callingDeviceID:%{public}s localDeviceId:%{public}s localCalling:%{public}d",
385 param->callingInfo.callingPid, param->callingInfo.callingUid,
386 IPCProcessSkeleton::ConvertToSecureString(param->callingInfo.callingDeviceID).c_str(),
387 IPCProcessSkeleton::ConvertToSecureString(param->callingInfo.localDeviceID).c_str(),
388 param->callingInfo.isLocalCalling);
389 int ret = OnJsRemoteRequest(param);
390 if (ret != 0) {
391 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
392 std::chrono::steady_clock::now().time_since_epoch()).count());
393 ZLOGE(LOG_LABEL, "OnJsRemoteRequest failed, ret:%{public}d time:%{public}" PRIu64, ret, curTime);
394 }
395 delete param;
396 return ret;
397 }
398
NAPI_RemoteObject_saveOldCallingInfoInner(napi_env env,CallingInfo & oldCallingInfo)399 static void NAPI_RemoteObject_saveOldCallingInfoInner(napi_env env, CallingInfo &oldCallingInfo)
400 {
401 napi_value global = nullptr;
402 napi_get_global(env, &global);
403 napi_value value = nullptr;
404 napi_get_named_property(env, global, "callingPid_", &value);
405 napi_get_value_int32(env, value, &oldCallingInfo.callingPid);
406 napi_get_named_property(env, global, "callingUid_", &value);
407 napi_get_value_int32(env, value, &oldCallingInfo.callingUid);
408 napi_get_named_property(env, global, "callingTokenId_", &value);
409 napi_get_value_uint32(env, value, &oldCallingInfo.callingTokenId);
410 napi_get_named_property(env, global, "callingDeviceID_", &value);
411 char deviceID[DEVICE_ID_LENGTH + 1] = { 0 };
412 size_t deviceLength = 0;
413 napi_get_value_string_utf8(env, global, deviceID, DEVICE_ID_LENGTH + 1, &deviceLength);
414 oldCallingInfo.callingDeviceID = deviceID;
415 char localDeviceID[DEVICE_ID_LENGTH + 1] = { 0 };
416 napi_get_named_property(env, global, "localDeviceID_", &value);
417 napi_get_value_string_utf8(env, global, localDeviceID, DEVICE_ID_LENGTH + 1, &deviceLength);
418 oldCallingInfo.localDeviceID = localDeviceID;
419 napi_get_named_property(env, global, "isLocalCalling_", &value);
420 napi_get_value_bool(env, value, &oldCallingInfo.isLocalCalling);
421 napi_get_named_property(env, global, "activeStatus_", &value);
422 napi_get_value_int32(env, value, &oldCallingInfo.activeStatus);
423 }
424
NAPI_RemoteObject_resetOldCallingInfoInner(napi_env env,CallingInfo & oldCallingInfo)425 static void NAPI_RemoteObject_resetOldCallingInfoInner(napi_env env, CallingInfo &oldCallingInfo)
426 {
427 NAPI_RemoteObject_setNewCallingInfo(env, oldCallingInfo);
428 }
429
ThenCallback(napi_env env,napi_callback_info info)430 napi_value NAPIRemoteObject::ThenCallback(napi_env env, napi_callback_info info)
431 {
432 ZLOGD(LOG_LABEL, "call js onRemoteRequest done");
433 size_t argc = 1;
434 napi_value argv[ARGV_LENGTH_1] = {nullptr};
435 void* data = nullptr;
436 napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
437 CallbackParam *param = static_cast<CallbackParam *>(data);
438 bool result = false;
439 napi_get_value_bool(param->env, argv[ARGV_INDEX_0], &result);
440 if (!result) {
441 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
442 std::chrono::steady_clock::now().time_since_epoch()).count());
443 ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s time:%{public}" PRIu64, result ? "true" : "false", curTime);
444 param->result = ERR_UNKNOWN_TRANSACTION;
445 } else {
446 param->result = ERR_NONE;
447 }
448
449 // Reset old calling pid, uid, device id
450 NAPI_RemoteObject_resetOldCallingInfoInner(param->env, param->oldCallingInfo);
451 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
452 param->lockInfo->ready = true;
453 param->lockInfo->condition.notify_all();
454 napi_value res;
455 napi_get_undefined(env, &res);
456 return res;
457 }
458
CatchCallback(napi_env env,napi_callback_info info)459 napi_value NAPIRemoteObject::CatchCallback(napi_env env, napi_callback_info info)
460 {
461 ZLOGI(LOG_LABEL, "Async onReomteReuqest's returnVal is rejected");
462 size_t argc = 1;
463 napi_value argv[ARGV_LENGTH_1] = {nullptr};
464 void* data = nullptr;
465 napi_get_cb_info(env, info, &argc, argv, nullptr, &data);
466 napi_value res;
467 CallbackParam *param = static_cast<CallbackParam *>(data);
468 if (param == nullptr) {
469 ZLOGE(LOG_LABEL, "param is null");
470 napi_get_undefined(env, &res);
471 return res;
472 }
473
474 // Reset old calling pid, uid, device id
475 NAPI_RemoteObject_resetOldCallingInfoInner(param->env, param->oldCallingInfo);
476 param->result = ERR_UNKNOWN_TRANSACTION;
477 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
478 param->lockInfo->ready = true;
479 param->lockInfo->condition.notify_all();
480 napi_get_undefined(env, &res);
481 return res;
482 }
483
NAPI_RemoteObject_saveOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)484 void NAPI_RemoteObject_saveOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
485 {
486 napi_value global = nullptr;
487 napi_get_global(env, &global);
488 napi_get_named_property(env, global, "callingPid_", &oldCallingInfo.callingPid);
489 napi_get_named_property(env, global, "callingUid_", &oldCallingInfo.callingUid);
490 napi_get_named_property(env, global, "callingTokenId_", &oldCallingInfo.callingTokenId);
491 napi_get_named_property(env, global, "callingDeviceID_", &oldCallingInfo.callingDeviceID);
492 napi_get_named_property(env, global, "localDeviceID_", &oldCallingInfo.localDeviceID);
493 napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
494 napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
495 napi_get_named_property(env, global, "activeStatus_", &oldCallingInfo.activeStatus);
496 }
497
NAPI_RemoteObject_setNewCallingInfo(napi_env env,const CallingInfo & newCallingInfoParam)498 void NAPI_RemoteObject_setNewCallingInfo(napi_env env, const CallingInfo &newCallingInfoParam)
499 {
500 napi_value global = nullptr;
501 napi_get_global(env, &global);
502 napi_value newPid = nullptr;
503 napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingPid), &newPid);
504 napi_set_named_property(env, global, "callingPid_", newPid);
505 napi_value newUid = nullptr;
506 napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingUid), &newUid);
507 napi_set_named_property(env, global, "callingUid_", newUid);
508 napi_value newCallingTokenId = nullptr;
509 napi_create_uint32(env, newCallingInfoParam.callingTokenId, &newCallingTokenId);
510 napi_set_named_property(env, global, "callingTokenId_", newCallingTokenId);
511 napi_value newDeviceID = nullptr;
512 napi_create_string_utf8(env, newCallingInfoParam.callingDeviceID.c_str(), NAPI_AUTO_LENGTH, &newDeviceID);
513 napi_set_named_property(env, global, "callingDeviceID_", newDeviceID);
514 napi_value newLocalDeviceID = nullptr;
515 napi_create_string_utf8(env, newCallingInfoParam.localDeviceID.c_str(), NAPI_AUTO_LENGTH, &newLocalDeviceID);
516 napi_set_named_property(env, global, "localDeviceID_", newLocalDeviceID);
517 napi_value newIsLocalCalling = nullptr;
518 napi_get_boolean(env, newCallingInfoParam.isLocalCalling, &newIsLocalCalling);
519 napi_set_named_property(env, global, "isLocalCalling_", newIsLocalCalling);
520 napi_value newActiveStatus = nullptr;
521 napi_create_int32(env, newCallingInfoParam.activeStatus, &newActiveStatus);
522 napi_set_named_property(env, global, "activeStatus_", newActiveStatus);
523 }
524
NAPI_RemoteObject_resetOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)525 void NAPI_RemoteObject_resetOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
526 {
527 napi_value global = nullptr;
528 napi_get_global(env, &global);
529 napi_set_named_property(env, global, "callingPid_", oldCallingInfo.callingPid);
530 napi_set_named_property(env, global, "callingUid_", oldCallingInfo.callingUid);
531 napi_set_named_property(env, global, "callingTokenId_", oldCallingInfo.callingTokenId);
532 napi_set_named_property(env, global, "callingDeviceID_", oldCallingInfo.callingDeviceID);
533 napi_set_named_property(env, global, "localDeviceID_", oldCallingInfo.localDeviceID);
534 napi_set_named_property(env, global, "isLocalCalling_", oldCallingInfo.isLocalCalling);
535 napi_set_named_property(env, global, "activeStatus_", oldCallingInfo.activeStatus);
536 }
537
OnJsRemoteRequest(CallbackParam * jsParam)538 int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
539 {
540 if (jsParam == nullptr) {
541 ZLOGE(LOG_LABEL, "Js Param is null");
542 return ERR_UNKNOWN_REASON;
543 }
544 if (thisVarRef_ == nullptr || env_ == nullptr) {
545 ZLOGE(LOG_LABEL, "Js env has been destructed");
546 return ERR_UNKNOWN_REASON;
547 }
548 uv_loop_s *loop = nullptr;
549 napi_get_uv_event_loop(env_, &loop);
550 if (loop == nullptr) {
551 ZLOGE(LOG_LABEL, "loop is nullptr");
552 return ERR_UNKNOWN_REASON;
553 }
554
555 uv_work_t *work = new (std::nothrow) uv_work_t;
556 if (work == nullptr) {
557 ZLOGE(LOG_LABEL, "failed to new uv_work_t");
558 return ERR_ALLOC_MEMORY;
559 }
560 work->data = reinterpret_cast<void *>(jsParam);
561
562 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
563 std::chrono::steady_clock::now().time_since_epoch()).count());
564 ZLOGD(LOG_LABEL, "start nv queue work loop. desc:%{public}s time:%{public}" PRIu64,
565 Str16ToStr8(descriptor_).c_str(), curTime);
566 int uvRet = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {
567 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
568 std::chrono::steady_clock::now().time_since_epoch()).count());
569 ZLOGI(LOG_LABEL, "enter work pool. code:%{public}u time:%{public}" PRIu64,
570 (reinterpret_cast<CallbackParam *>(work->data))->code, curTime);
571 }, [](uv_work_t *work, int status) {
572 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
573 std::chrono::steady_clock::now().time_since_epoch()).count());
574 ZLOGI(LOG_LABEL, "enter thread pool time:%{public}" PRIu64, curTime);
575 CallbackParam *param = reinterpret_cast<CallbackParam *>(work->data);
576 napi_handle_scope scope = nullptr;
577 napi_open_handle_scope(param->env, &scope);
578 napi_value onRemoteRequest = nullptr;
579 napi_value thisVar = nullptr;
580 napi_get_reference_value(param->env, param->thisVarRef, &thisVar);
581 if (thisVar == nullptr) {
582 ZLOGE(LOG_LABEL, "thisVar is null");
583 param->result = IPC_INVALID_PARAM_ERR;
584 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
585 param->lockInfo->ready = true;
586 param->lockInfo->condition.notify_all();
587 napi_close_handle_scope(param->env, scope);
588 return;
589 }
590 napi_get_named_property(param->env, thisVar, "onRemoteMessageRequest", &onRemoteRequest);
591 if (onRemoteRequest == nullptr) {
592 ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
593 param->result = IPC_INVALID_PARAM_ERR;
594 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
595 param->lockInfo->ready = true;
596 param->lockInfo->condition.notify_all();
597 napi_close_handle_scope(param->env, scope);
598 return;
599 }
600 napi_valuetype type = napi_undefined;
601 napi_typeof(param->env, onRemoteRequest, &type);
602 bool isOnRemoteMessageRequest = true;
603 if (type != napi_function) {
604 napi_get_named_property(param->env, thisVar, "onRemoteRequest", &onRemoteRequest);
605 if (onRemoteRequest == nullptr) {
606 ZLOGE(LOG_LABEL, "get founction onRemoteRequest failed");
607 param->result = IPC_INVALID_PARAM_ERR;
608 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
609 param->lockInfo->ready = true;
610 param->lockInfo->condition.notify_all();
611 napi_close_handle_scope(param->env, scope);
612 return;
613 }
614 isOnRemoteMessageRequest = false;
615 }
616 napi_value jsCode;
617 napi_create_uint32(param->env, param->code, &jsCode);
618
619 napi_value global = nullptr;
620 napi_get_global(param->env, &global);
621 if (global == nullptr) {
622 ZLOGE(LOG_LABEL, "get napi global failed");
623 param->result = IPC_INVALID_PARAM_ERR;
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 jsOptionConstructor = nullptr;
631 napi_get_named_property(param->env, global, "IPCOptionConstructor_", &jsOptionConstructor);
632 if (jsOptionConstructor == nullptr) {
633 ZLOGE(LOG_LABEL, "jsOption constructor is null");
634 param->result = IPC_INVALID_PARAM_ERR;
635 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
636 param->lockInfo->ready = true;
637 param->lockInfo->condition.notify_all();
638 napi_close_handle_scope(param->env, scope);
639 return;
640 }
641 napi_value jsOption;
642 size_t argc = 2;
643 napi_value flags = nullptr;
644 napi_create_int32(param->env, param->option->GetFlags(), &flags);
645 napi_value waittime = nullptr;
646 napi_create_int32(param->env, param->option->GetWaitTime(), &waittime);
647 napi_value argv[ARGV_LENGTH_2] = { flags, waittime };
648 napi_new_instance(param->env, jsOptionConstructor, argc, argv, &jsOption);
649 if (jsOption == nullptr) {
650 ZLOGE(LOG_LABEL, "new jsOption failed");
651 param->result = IPC_INVALID_PARAM_ERR;
652 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
653 param->lockInfo->ready = true;
654 param->lockInfo->condition.notify_all();
655 napi_close_handle_scope(param->env, scope);
656 return;
657 }
658 napi_value jsParcelConstructor = nullptr;
659 if (isOnRemoteMessageRequest) {
660 napi_get_named_property(param->env, global, "IPCSequenceConstructor_", &jsParcelConstructor);
661 } else {
662 napi_get_named_property(param->env, global, "IPCParcelConstructor_", &jsParcelConstructor);
663 }
664 if (jsParcelConstructor == nullptr) {
665 ZLOGE(LOG_LABEL, "jsParcel constructor is null");
666 param->result = IPC_INVALID_PARAM_ERR;
667 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
668 param->lockInfo->ready = true;
669 param->lockInfo->condition.notify_all();
670 napi_close_handle_scope(param->env, scope);
671 return;
672 }
673 napi_value jsData;
674 napi_value dataParcel;
675 napi_create_object(param->env, &dataParcel);
676 napi_wrap(param->env, dataParcel, param->data,
677 [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
678 if (dataParcel == nullptr) {
679 ZLOGE(LOG_LABEL, "create js object for data parcel address failed");
680 param->result = IPC_INVALID_PARAM_ERR;
681 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
682 param->lockInfo->ready = true;
683 param->lockInfo->condition.notify_all();
684 napi_close_handle_scope(param->env, scope);
685 return;
686 }
687 size_t argc3 = 1;
688 napi_value argv3[1] = { dataParcel };
689 napi_new_instance(param->env, jsParcelConstructor, argc3, argv3, &jsData);
690 if (jsData == nullptr) {
691 ZLOGE(LOG_LABEL, "create js data parcel failed");
692 param->result = IPC_INVALID_PARAM_ERR;
693 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
694 param->lockInfo->ready = true;
695 param->lockInfo->condition.notify_all();
696 napi_close_handle_scope(param->env, scope);
697 return;
698 }
699 napi_value jsReply;
700 napi_value replyParcel;
701 napi_create_object(param->env, &replyParcel);
702 napi_wrap(param->env, replyParcel, param->reply,
703 [](napi_env env, void *data, void *hint) {}, nullptr, nullptr);
704 if (replyParcel == nullptr) {
705 ZLOGE(LOG_LABEL, "create js object for reply parcel address failed");
706 param->result = IPC_INVALID_PARAM_ERR;
707 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
708 param->lockInfo->ready = true;
709 param->lockInfo->condition.notify_all();
710 napi_close_handle_scope(param->env, scope);
711 return;
712 }
713 size_t argc4 = 1;
714 napi_value argv4[1] = { replyParcel };
715 napi_new_instance(param->env, jsParcelConstructor, argc4, argv4, &jsReply);
716 if (jsReply == nullptr) {
717 ZLOGE(LOG_LABEL, "create js reply parcel failed");
718 param->result = IPC_INVALID_PARAM_ERR;
719 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
720 param->lockInfo->ready = true;
721 param->lockInfo->condition.notify_all();
722 napi_close_handle_scope(param->env, scope);
723 return;
724 }
725 NAPI_RemoteObject_saveOldCallingInfoInner(param->env, param->oldCallingInfo);
726 NAPI_RemoteObject_setNewCallingInfo(param->env, param->callingInfo);
727 // start to call onRemoteRequest
728 size_t argc2 = 4;
729 napi_value argv2[] = { jsCode, jsData, jsReply, jsOption };
730 napi_value returnVal;
731 napi_status ret = napi_call_function(param->env, thisVar, onRemoteRequest, argc2, argv2, &returnVal);
732
733 do {
734 if (ret != napi_ok) {
735 ZLOGE(LOG_LABEL, "OnRemoteRequest got exception");
736 param->result = ERR_UNKNOWN_TRANSACTION;
737 break;
738 }
739
740 ZLOGD(LOG_LABEL, "call js onRemoteRequest done");
741 // Check whether return_val is Promise
742 bool returnIsPromise = false;
743 napi_is_promise(param->env, returnVal, &returnIsPromise);
744 if (!returnIsPromise) {
745 ZLOGD(LOG_LABEL, "onRemoteRequest is synchronous");
746 bool result = false;
747 napi_get_value_bool(param->env, returnVal, &result);
748 if (!result) {
749 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
750 std::chrono::steady_clock::now().time_since_epoch()).count());
751 ZLOGE(LOG_LABEL, "OnRemoteRequest res:%{public}s time:%{public}" PRIu64,
752 result ? "true" : "false", curTime);
753 param->result = ERR_UNKNOWN_TRANSACTION;
754 } else {
755 param->result = ERR_NONE;
756 }
757 break;
758 }
759
760 ZLOGD(LOG_LABEL, "onRemoteRequest is asynchronous");
761 // Create promiseThen
762 napi_value promiseThen = nullptr;
763 napi_get_named_property(param->env, returnVal, "then", &promiseThen);
764 if (promiseThen == nullptr) {
765 ZLOGE(LOG_LABEL, "get promiseThen failed");
766 param->result = IPC_INVALID_PARAM_ERR;
767 break;
768 }
769 napi_value thenValue;
770 ret = napi_create_function(param->env, "thenCallback", NAPI_AUTO_LENGTH, ThenCallback, param, &thenValue);
771 if (ret != napi_ok) {
772 ZLOGE(LOG_LABEL, "thenCallback got exception");
773 param->result = ERR_UNKNOWN_TRANSACTION;
774 break;
775 }
776 napi_value catchValue;
777 ret = napi_create_function(param->env, "catchCallback",
778 NAPI_AUTO_LENGTH, CatchCallback, param, &catchValue);
779 if (ret != napi_ok) {
780 ZLOGE(LOG_LABEL, "catchCallback got exception");
781 param->result = ERR_UNKNOWN_TRANSACTION;
782 break;
783 }
784 // Start to call promiseThen
785 napi_env env = param->env;
786 napi_value thenReturnValue;
787 constexpr uint32_t THEN_ARGC = 2;
788 napi_value thenArgv[THEN_ARGC] = {thenValue, catchValue};
789 ret = napi_call_function(env, returnVal, promiseThen, THEN_ARGC, thenArgv, &thenReturnValue);
790 if (ret != napi_ok) {
791 ZLOGE(LOG_LABEL, "PromiseThen got exception");
792 param->result = ERR_UNKNOWN_TRANSACTION;
793 break;
794 }
795 napi_close_handle_scope(env, scope);
796 return;
797 } while (0);
798
799 // Reset old calling pid, uid, device id
800 NAPI_RemoteObject_resetOldCallingInfoInner(param->env, param->oldCallingInfo);
801 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
802 param->lockInfo->ready = true;
803 param->lockInfo->condition.notify_all();
804 napi_close_handle_scope(param->env, scope);
805 }, uv_qos_user_initiated);
806 int ret = 0;
807 if (uvRet != 0) {
808 ZLOGE(LOG_LABEL, "uv_queue_work_with_qos failed, ret:%{public}d", uvRet);
809 ret = ERR_START_UV_WORK;
810 } else {
811 std::unique_lock<std::mutex> lock(jsParam->lockInfo->mutex);
812 jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
813 ret = jsParam->result;
814 }
815 delete work;
816 return ret;
817 }
818
NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env,const sptr<IRemoteObject> target)819 napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteObject> target)
820 {
821 if (target == nullptr) {
822 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
823 std::chrono::steady_clock::now().time_since_epoch()).count());
824 ZLOGE(LOG_LABEL, "RemoteObject is null time:%{public}" PRIu64, curTime);
825 return nullptr;
826 }
827
828 if (!target->IsProxyObject()) {
829 IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
830 uint32_t objectType = static_cast<uint32_t>(tmp->GetObjectType());
831 ZLOGD(LOG_LABEL, "create js object, type:%{public}d", objectType);
832 if (objectType == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT || objectType == IPCObjectStub::OBJECT_TYPE_NATIVE) {
833 // retrieve js remote object constructor
834 napi_value global = nullptr;
835 napi_status status = napi_get_global(env, &global);
836 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
837 napi_value constructor = nullptr;
838 status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
839 NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
840 NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
841 // retrieve descriptor and it's length
842 std::u16string descriptor = target->GetObjectDescriptor();
843 std::string desc = Str16ToStr8(descriptor);
844 napi_value jsDesc = nullptr;
845 napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
846 // create a new js remote object
847 size_t argc = 1;
848 napi_value argv[ARGV_LENGTH_1] = { jsDesc };
849 napi_value jsRemoteObject = nullptr;
850 status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
851 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteObject");
852 // retrieve holder and set object
853 NAPIRemoteObjectHolder *holder = nullptr;
854 napi_unwrap(env, jsRemoteObject, (void **)&holder);
855 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
856 holder->Set(target);
857 return jsRemoteObject;
858 }
859 }
860
861 napi_value global = nullptr;
862 napi_status status = napi_get_global(env, &global);
863 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
864 napi_value constructor = nullptr;
865 status = napi_get_named_property(env, global, "IPCProxyConstructor_", &constructor);
866 NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
867 napi_value jsRemoteProxy;
868 status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
869 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteProxy");
870 NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
871 if (proxyHolder == nullptr) {
872 ZLOGE(LOG_LABEL, "proxyHolder null");
873 return nullptr;
874 }
875 proxyHolder->object_ = target;
876 proxyHolder->list_ = new (std::nothrow) NAPIDeathRecipientList();
877 NAPI_ASSERT(env, proxyHolder->list_ != nullptr, "new NAPIDeathRecipientList failed");
878
879 return jsRemoteProxy;
880 }
881
NAPI_ohos_rpc_ClearNativeRemoteProxy(napi_env env,napi_value jsRemoteProxy)882 bool NAPI_ohos_rpc_ClearNativeRemoteProxy(napi_env env, napi_value jsRemoteProxy)
883 {
884 NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
885 if (holder == nullptr) {
886 ZLOGE(LOG_LABEL, "holder null");
887 return false;
888 }
889 ZLOGI(LOG_LABEL, "clear native remote proxy");
890 holder->object_ = nullptr;
891 return true;
892 }
893
NAPI_ohos_rpc_getNativeRemoteObject(napi_env env,napi_value object)894 sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
895 {
896 if (object != nullptr) {
897 napi_value global = nullptr;
898 napi_status status = napi_get_global(env, &global);
899 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
900 napi_value stubConstructor = nullptr;
901 status = napi_get_named_property(env, global, "IPCStubConstructor_", &stubConstructor);
902 NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
903 bool instanceOfStub = false;
904 status = napi_instanceof(env, object, stubConstructor, &instanceOfStub);
905 NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
906 if (instanceOfStub) {
907 NAPIRemoteObjectHolder *holder = nullptr;
908 napi_unwrap(env, object, (void **)&holder);
909 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
910 return holder != nullptr ? holder->Get() : nullptr;
911 }
912
913 napi_value proxyConstructor = nullptr;
914 status = napi_get_named_property(env, global, "IPCProxyConstructor_", &proxyConstructor);
915 NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
916 bool instanceOfProxy = false;
917 status = napi_instanceof(env, object, proxyConstructor, &instanceOfProxy);
918 NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
919 if (instanceOfProxy) {
920 NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
921 return holder != nullptr ? holder->object_ : nullptr;
922 }
923 }
924 return nullptr;
925 }
926
NAPI_RemoteObject_queryLocalInterface(napi_env env,napi_callback_info info)927 static napi_value NAPI_RemoteObject_queryLocalInterface(napi_env env, napi_callback_info info)
928 {
929 size_t argc = 1;
930 size_t expectedArgc = 1;
931 napi_value argv[ARGV_LENGTH_1] = {nullptr};
932 napi_value thisVar = nullptr;
933 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
934 NAPI_ASSERT(env, argc == expectedArgc, "requires 1 parameters");
935 napi_valuetype valueType = napi_null;
936 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
937 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
938 size_t bufferSize = 0;
939 size_t maxLen = 40960;
940 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
941 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
942 char stringValue[bufferSize + 1];
943 size_t jsStringLength = 0;
944 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
945 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
946 std::string descriptor = stringValue;
947 NAPIRemoteObjectHolder *holder = nullptr;
948 napi_unwrap(env, thisVar, (void **)&holder);
949 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
950 napi_value ret = holder->queryLocalInterface(descriptor);
951 return ret;
952 }
953
NAPI_RemoteObject_getLocalInterface(napi_env env,napi_callback_info info)954 static napi_value NAPI_RemoteObject_getLocalInterface(napi_env env, napi_callback_info info)
955 {
956 size_t argc = 1;
957 size_t expectedArgc = 1;
958 napi_value argv[ARGV_LENGTH_1] = {nullptr};
959 napi_value thisVar = nullptr;
960 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
961 if (argc != expectedArgc) {
962 ZLOGE(LOG_LABEL, "requires 1 parameters");
963 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
964 }
965 napi_valuetype valueType = napi_null;
966 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
967 if (valueType != napi_string) {
968 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
969 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
970 }
971 size_t bufferSize = 0;
972 size_t maxLen = 40960;
973 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
974 if (bufferSize >= maxLen) {
975 ZLOGE(LOG_LABEL, "string length too large");
976 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
977 }
978 char stringValue[bufferSize + 1];
979 size_t jsStringLength = 0;
980 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
981 if (jsStringLength != bufferSize) {
982 ZLOGE(LOG_LABEL, "string length wrong");
983 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
984 }
985 std::string descriptor = stringValue;
986 NAPIRemoteObjectHolder *holder = nullptr;
987 napi_unwrap(env, thisVar, (void **)&holder);
988 if (holder == nullptr) {
989 ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
990 return nullptr;
991 }
992 napi_value ret = holder->queryLocalInterface(descriptor);
993 return ret;
994 }
995
NAPI_RemoteObject_getInterfaceDescriptor(napi_env env,napi_callback_info info)996 static napi_value NAPI_RemoteObject_getInterfaceDescriptor(napi_env env, napi_callback_info info)
997 {
998 napi_value result = nullptr;
999 napi_value thisVar = nullptr;
1000 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1001 sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1002 std::u16string descriptor = nativeObject->GetObjectDescriptor();
1003 napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1004 return result;
1005 }
1006
NAPI_RemoteObject_getDescriptor(napi_env env,napi_callback_info info)1007 static napi_value NAPI_RemoteObject_getDescriptor(napi_env env, napi_callback_info info)
1008 {
1009 napi_value result = nullptr;
1010 napi_value thisVar = nullptr;
1011 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1012 sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1013 if (nativeObject == nullptr) {
1014 ZLOGE(LOG_LABEL, "native stub object is nullptr");
1015 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
1016 }
1017 std::u16string descriptor = nativeObject->GetObjectDescriptor();
1018 napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1019 return result;
1020 }
1021
NAPI_RemoteObject_getCallingPid(napi_env env,napi_callback_info info)1022 static napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
1023 {
1024 return NAPI_getCallingPid(env, info);
1025 }
1026
NAPI_RemoteObject_getCallingUid(napi_env env,napi_callback_info info)1027 static napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
1028 {
1029 return NAPI_getCallingUid(env, info);
1030 }
1031
MakeSendRequestResult(SendRequestParam * param)1032 napi_value MakeSendRequestResult(SendRequestParam *param)
1033 {
1034 if (param == nullptr) {
1035 ZLOGE(LOG_LABEL, "send request param is null");
1036 return nullptr;
1037 }
1038 napi_value errCode = nullptr;
1039 napi_create_int32(param->env, param->errCode, &errCode);
1040 napi_value code = nullptr;
1041 napi_get_reference_value(param->env, param->jsCodeRef, &code);
1042 napi_value data = nullptr;
1043 napi_get_reference_value(param->env, param->jsDataRef, &data);
1044 napi_value reply = nullptr;
1045 napi_get_reference_value(param->env, param->jsReplyRef, &reply);
1046 napi_value result = nullptr;
1047 napi_create_object(param->env, &result);
1048 napi_set_named_property(param->env, result, "errCode", errCode);
1049 napi_set_named_property(param->env, result, "code", code);
1050 napi_set_named_property(param->env, result, "data", data);
1051 napi_set_named_property(param->env, result, "reply", reply);
1052 return result;
1053 }
1054
StubExecuteSendRequest(napi_env env,SendRequestParam * param)1055 void StubExecuteSendRequest(napi_env env, SendRequestParam *param)
1056 {
1057 if (param == nullptr) {
1058 ZLOGE(LOG_LABEL, "param is null");
1059 return;
1060 }
1061 param->errCode = param->target->SendRequest(param->code,
1062 *(param->data.get()), *(param->reply.get()), param->option);
1063 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
1064 std::chrono::steady_clock::now().time_since_epoch()).count());
1065 ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d time:%{public}" PRIu64, param->errCode, curTime);
1066 if (param->traceId != 0) {
1067 FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
1068 }
1069 uv_loop_s *loop = nullptr;
1070 napi_get_uv_event_loop(env, &loop);
1071 if (loop == nullptr) {
1072 ZLOGE(LOG_LABEL, "loop is nullptr");
1073 return;
1074 }
1075 uv_work_t *work = new (std::nothrow) uv_work_t;
1076 if (work == nullptr) {
1077 ZLOGE(LOG_LABEL, "new uv_work_t failed");
1078 return;
1079 }
1080 work->data = reinterpret_cast<void *>(param);
1081 uv_after_work_cb afterWorkCb = nullptr;
1082 if (param->callback != nullptr) {
1083 afterWorkCb = [](uv_work_t *work, int status) {
1084 ZLOGI(LOG_LABEL, "callback started");
1085 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1086 napi_handle_scope scope = nullptr;
1087 napi_open_handle_scope(param->env, &scope);
1088 napi_value result = MakeSendRequestResult(param);
1089 napi_value callback = nullptr;
1090 napi_get_reference_value(param->env, param->callback, &callback);
1091 napi_value cbResult = nullptr;
1092 napi_call_function(param->env, nullptr, callback, 1, &result, &cbResult);
1093 napi_delete_reference(param->env, param->jsCodeRef);
1094 napi_delete_reference(param->env, param->jsDataRef);
1095 napi_delete_reference(param->env, param->jsReplyRef);
1096 napi_delete_reference(param->env, param->jsOptionRef);
1097 napi_delete_reference(param->env, param->callback);
1098 napi_close_handle_scope(param->env, scope);
1099 delete param;
1100 delete work;
1101 };
1102 } else {
1103 afterWorkCb = [](uv_work_t *work, int status) {
1104 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
1105 std::chrono::steady_clock::now().time_since_epoch()).count());
1106 ZLOGI(LOG_LABEL, "promise fullfilled time:%{public}" PRIu64, curTime);
1107 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1108 napi_handle_scope scope = nullptr;
1109 napi_open_handle_scope(param->env, &scope);
1110 napi_value result = MakeSendRequestResult(param);
1111 if (param->errCode == 0) {
1112 napi_resolve_deferred(param->env, param->deferred, result);
1113 } else {
1114 napi_reject_deferred(param->env, param->deferred, result);
1115 }
1116 napi_delete_reference(param->env, param->jsCodeRef);
1117 napi_delete_reference(param->env, param->jsDataRef);
1118 napi_delete_reference(param->env, param->jsReplyRef);
1119 napi_delete_reference(param->env, param->jsOptionRef);
1120 napi_close_handle_scope(param->env, scope);
1121 delete param;
1122 delete work;
1123 };
1124 }
1125 int uvRet = uv_queue_work(loop, work, [](uv_work_t *work) {
1126 ZLOGD(LOG_LABEL, "enter work pool.");
1127 }, afterWorkCb);
1128 if (uvRet != 0) {
1129 ZLOGE(LOG_LABEL, "uv_queue_work failed, ret %{public}d", uvRet);
1130 delete param;
1131 delete work;
1132 }
1133 }
1134
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)1135 napi_value StubSendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1136 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1137 MessageOption &option, napi_value *argv)
1138 {
1139 SendRequestParam *sendRequestParam = new (std::nothrow) SendRequestParam {
1140 .target = target,
1141 .code = code,
1142 .data = data,
1143 .reply = reply,
1144 .option = option,
1145 .asyncWork = nullptr,
1146 .deferred = nullptr,
1147 .errCode = -1,
1148 .jsCodeRef = nullptr,
1149 .jsDataRef = nullptr,
1150 .jsReplyRef = nullptr,
1151 .jsOptionRef = nullptr,
1152 .callback = nullptr,
1153 .env = env,
1154 .traceId = 0,
1155 };
1156 NAPI_ASSERT(env, sendRequestParam != nullptr, "new SendRequestParam failed");
1157 if (target != nullptr) {
1158 std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1159 if (!remoteDescriptor.empty()) {
1160 sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1161 sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1162 StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1163 }
1164 }
1165 napi_create_reference(env, argv[ARGV_INDEX_0], 1, &sendRequestParam->jsCodeRef);
1166 napi_create_reference(env, argv[ARGV_INDEX_1], 1, &sendRequestParam->jsDataRef);
1167 napi_create_reference(env, argv[ARGV_INDEX_2], 1, &sendRequestParam->jsReplyRef);
1168 napi_create_reference(env, argv[ARGV_INDEX_3], 1, &sendRequestParam->jsOptionRef);
1169 napi_create_reference(env, argv[ARGV_INDEX_4], 1, &sendRequestParam->callback);
1170 std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1171 t.detach();
1172 napi_value result = nullptr;
1173 napi_get_undefined(env, &result);
1174 return result;
1175 }
1176
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)1177 napi_value StubSendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1178 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1179 MessageOption &option, napi_value *argv)
1180 {
1181 napi_deferred deferred = nullptr;
1182 napi_value promise = nullptr;
1183 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1184 SendRequestParam *sendRequestParam = new (std::nothrow) SendRequestParam {
1185 .target = target,
1186 .code = code,
1187 .data = data,
1188 .reply = reply,
1189 .option = option,
1190 .asyncWork = nullptr,
1191 .deferred = deferred,
1192 .errCode = -1,
1193 .jsCodeRef = nullptr,
1194 .jsDataRef = nullptr,
1195 .jsReplyRef = nullptr,
1196 .jsOptionRef = nullptr,
1197 .callback = nullptr,
1198 .env = env,
1199 .traceId = 0,
1200 };
1201 NAPI_ASSERT(env, sendRequestParam != nullptr, "new SendRequestParam failed");
1202 if (target != nullptr) {
1203 std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1204 if (!remoteDescriptor.empty()) {
1205 sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1206 sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1207 StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1208 }
1209 }
1210 napi_create_reference(env, argv[ARGV_INDEX_0], 1, &sendRequestParam->jsCodeRef);
1211 napi_create_reference(env, argv[ARGV_INDEX_1], 1, &sendRequestParam->jsDataRef);
1212 napi_create_reference(env, argv[ARGV_INDEX_2], 1, &sendRequestParam->jsReplyRef);
1213 napi_create_reference(env, argv[ARGV_INDEX_3], 1, &sendRequestParam->jsOptionRef);
1214 std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1215 t.detach();
1216 return promise;
1217 }
1218
NAPI_RemoteObject_sendRequest(napi_env env,napi_callback_info info)1219 static napi_value NAPI_RemoteObject_sendRequest(napi_env env, napi_callback_info info)
1220 {
1221 size_t argc = 4;
1222 size_t argcCallback = 5;
1223 size_t argcPromise = 4;
1224 napi_value argv[ARGV_LENGTH_5] = { 0 };
1225 napi_value thisVar = nullptr;
1226 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1227 NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1228 napi_valuetype valueType = napi_null;
1229 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1230 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1231 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1232 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1233 napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1234 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1235 napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1236 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1237
1238 NAPI_MessageParcel *data = nullptr;
1239 napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
1240 NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1241 NAPI_MessageParcel *reply = nullptr;
1242 status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
1243 NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1244 MessageOption *option = nullptr;
1245 status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
1246 NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1247 int32_t code = 0;
1248 napi_get_value_int32(env, argv[ARGV_INDEX_0], &code);
1249
1250 sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1251 if (argc == argcCallback) {
1252 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1253 napi_valuetype valuetype = napi_undefined;
1254 napi_typeof(env, argv[argcPromise], &valuetype);
1255 if (valuetype == napi_function) {
1256 return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1257 reply->GetMessageParcel(), *option, argv);
1258 }
1259 }
1260 return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1261 reply->GetMessageParcel(), *option, argv);
1262 }
1263
NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,size_t argc,size_t argcCallback,size_t argcPromise,napi_value * argv)1264 napi_value NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,
1265 size_t argc,
1266 size_t argcCallback,
1267 size_t argcPromise,
1268 napi_value* argv)
1269 {
1270 if (argc != argcPromise && argc != argcCallback) {
1271 ZLOGE(LOG_LABEL, "requires 4 or 5 parameters");
1272 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1273 }
1274 napi_valuetype valueType = napi_null;
1275 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1276 if (valueType != napi_number) {
1277 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1278 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1279 }
1280 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1281 if (valueType != napi_object) {
1282 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1283 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1284 }
1285 napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1286 if (valueType != napi_object) {
1287 ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
1288 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1289 }
1290 napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1291 if (valueType != napi_object) {
1292 ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
1293 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1294 }
1295 napi_value result = nullptr;
1296 napi_get_undefined(env, &result);
1297 return result;
1298 }
1299
NAPI_RemoteObject_sendMessageRequest(napi_env env,napi_callback_info info)1300 static napi_value NAPI_RemoteObject_sendMessageRequest(napi_env env, napi_callback_info info)
1301 {
1302 size_t argc = 4;
1303 size_t argcCallback = 5;
1304 size_t argcPromise = 4;
1305 napi_value argv[ARGV_LENGTH_5] = { 0 };
1306 napi_value thisVar = nullptr;
1307 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1308 napi_value checkArgsResult = NAPI_RemoteObject_checkSendMessageRequestArgs(env, argc, argcCallback, argcPromise,
1309 argv);
1310 if (checkArgsResult == nullptr) {
1311 return checkArgsResult;
1312 }
1313 NAPI_MessageSequence *data = nullptr;
1314 napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
1315 if (status != napi_ok) {
1316 ZLOGE(LOG_LABEL, "failed to get data message sequence");
1317 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1318 }
1319 NAPI_MessageSequence *reply = nullptr;
1320 status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
1321 if (status != napi_ok) {
1322 ZLOGE(LOG_LABEL, "failed to get data message sequence");
1323 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1324 }
1325 MessageOption *option = nullptr;
1326 status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
1327 if (status != napi_ok) {
1328 ZLOGE(LOG_LABEL, "failed to get message option");
1329 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1330 }
1331 int32_t code = 0;
1332 napi_get_value_int32(env, argv[ARGV_INDEX_0], &code);
1333
1334 sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1335 if (argc == argcCallback) {
1336 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1337 napi_valuetype valuetype = napi_undefined;
1338 napi_typeof(env, argv[argcPromise], &valuetype);
1339 if (valuetype == napi_function) {
1340 return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1341 reply->GetMessageParcel(), *option, argv);
1342 }
1343 }
1344 return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1345 reply->GetMessageParcel(), *option, argv);
1346 }
1347
NAPI_RemoteObject_attachLocalInterface(napi_env env,napi_callback_info info)1348 static napi_value NAPI_RemoteObject_attachLocalInterface(napi_env env, napi_callback_info info)
1349 {
1350 size_t argc = 2;
1351 size_t expectedArgc = 2;
1352 napi_value argv[ARGV_LENGTH_2] = { 0 };
1353 napi_value thisVar = nullptr;
1354 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1355 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameters");
1356 napi_valuetype valueType = napi_null;
1357 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1358 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1359 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1360 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 2");
1361 size_t bufferSize = 0;
1362 size_t maxLen = 40960;
1363 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], nullptr, 0, &bufferSize);
1364 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1365 char stringValue[bufferSize + 1];
1366 size_t jsStringLength = 0;
1367 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], stringValue, bufferSize + 1, &jsStringLength);
1368 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1369 std::string descriptor = stringValue;
1370
1371 NAPIRemoteObjectHolder *holder = nullptr;
1372 napi_unwrap(env, thisVar, (void* *)&holder);
1373 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1374 holder->attachLocalInterface(argv[ARGV_INDEX_0], descriptor);
1375
1376 napi_value result = nullptr;
1377 napi_get_undefined(env, &result);
1378 return result;
1379 }
1380
NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env,size_t argc,napi_value * argv)1381 napi_value NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env, size_t argc, napi_value* argv)
1382 {
1383 size_t expectedArgc = 2;
1384
1385 if (argc != expectedArgc) {
1386 ZLOGE(LOG_LABEL, "requires 2 parameters");
1387 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1388 }
1389 napi_valuetype valueType = napi_null;
1390 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1391 if (valueType != napi_object) {
1392 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1393 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1394 }
1395 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1396 if (valueType != napi_string) {
1397 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1398 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1399 }
1400 napi_value result = nullptr;
1401 napi_get_undefined(env, &result);
1402 return result;
1403 }
1404
NAPI_RemoteObject_modifyLocalInterface(napi_env env,napi_callback_info info)1405 static napi_value NAPI_RemoteObject_modifyLocalInterface(napi_env env, napi_callback_info info)
1406 {
1407 size_t argc = 2;
1408 napi_value argv[ARGV_LENGTH_2] = { 0 };
1409 napi_value thisVar = nullptr;
1410 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1411 napi_value checkArgsResult = NAPI_RemoteObject_checkModifyLocalInterfaceArgs(env, argc, argv);
1412 if (checkArgsResult == nullptr) {
1413 return checkArgsResult;
1414 }
1415 size_t bufferSize = 0;
1416 size_t maxLen = 40960;
1417 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], nullptr, 0, &bufferSize);
1418 if (bufferSize >= maxLen) {
1419 ZLOGE(LOG_LABEL, "string length too large");
1420 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1421 }
1422 char stringValue[bufferSize + 1];
1423 size_t jsStringLength = 0;
1424 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], stringValue, bufferSize + 1, &jsStringLength);
1425 if (jsStringLength != bufferSize) {
1426 ZLOGE(LOG_LABEL, "string length wrong");
1427 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1428 }
1429 std::string descriptor = stringValue;
1430
1431 NAPIRemoteObjectHolder *holder = nullptr;
1432 napi_unwrap(env, thisVar, (void* *)&holder);
1433 if (holder == nullptr) {
1434 ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1435 return nullptr;
1436 }
1437 holder->attachLocalInterface(argv[ARGV_INDEX_0], descriptor);
1438
1439 napi_value result = nullptr;
1440 napi_get_undefined(env, &result);
1441 return result;
1442 }
1443
NAPI_RemoteObject_addDeathRecipient(napi_env env,napi_callback_info info)1444 static napi_value NAPI_RemoteObject_addDeathRecipient(napi_env env, napi_callback_info info)
1445 {
1446 napi_value result = nullptr;
1447 napi_get_boolean(env, false, &result);
1448 return result;
1449 }
1450
NAPI_RemoteObject_registerDeathRecipient(napi_env env,napi_callback_info info)1451 static napi_value NAPI_RemoteObject_registerDeathRecipient(napi_env env, napi_callback_info info)
1452 {
1453 ZLOGE(LOG_LABEL, "only proxy object permitted");
1454 return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1455 }
1456
NAPI_RemoteObject_removeDeathRecipient(napi_env env,napi_callback_info info)1457 static napi_value NAPI_RemoteObject_removeDeathRecipient(napi_env env, napi_callback_info info)
1458 {
1459 napi_value result = nullptr;
1460 napi_get_boolean(env, false, &result);
1461 return result;
1462 }
1463
NAPI_RemoteObject_unregisterDeathRecipient(napi_env env,napi_callback_info info)1464 static napi_value NAPI_RemoteObject_unregisterDeathRecipient(napi_env env, napi_callback_info info)
1465 {
1466 ZLOGE(LOG_LABEL, "only proxy object permitted");
1467 return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1468 }
1469
NAPI_RemoteObject_isObjectDead(napi_env env,napi_callback_info info)1470 static napi_value NAPI_RemoteObject_isObjectDead(napi_env env, napi_callback_info info)
1471 {
1472 napi_value result = nullptr;
1473 napi_get_boolean(env, false, &result);
1474 return result;
1475 }
1476
1477 EXTERN_C_START
1478 /*
1479 * function for module exports
1480 */
NAPIRemoteObjectExport(napi_env env,napi_value exports)1481 napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports)
1482 {
1483 const std::string className = "RemoteObject";
1484 napi_property_descriptor properties[] = {
1485 DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteObject_sendRequest),
1486 DECLARE_NAPI_FUNCTION("sendMessageRequest", NAPI_RemoteObject_sendMessageRequest),
1487 DECLARE_NAPI_FUNCTION("getCallingPid", NAPI_RemoteObject_getCallingPid),
1488 DECLARE_NAPI_FUNCTION("getCallingUid", NAPI_RemoteObject_getCallingUid),
1489 DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteObject_getInterfaceDescriptor),
1490 DECLARE_NAPI_FUNCTION("getDescriptor", NAPI_RemoteObject_getDescriptor),
1491 DECLARE_NAPI_FUNCTION("attachLocalInterface", NAPI_RemoteObject_attachLocalInterface),
1492 DECLARE_NAPI_FUNCTION("modifyLocalInterface", NAPI_RemoteObject_modifyLocalInterface),
1493 DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteObject_queryLocalInterface),
1494 DECLARE_NAPI_FUNCTION("getLocalInterface", NAPI_RemoteObject_getLocalInterface),
1495 DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteObject_addDeathRecipient),
1496 DECLARE_NAPI_FUNCTION("registerDeathRecipient", NAPI_RemoteObject_registerDeathRecipient),
1497 DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteObject_removeDeathRecipient),
1498 DECLARE_NAPI_FUNCTION("unregisterDeathRecipient", NAPI_RemoteObject_unregisterDeathRecipient),
1499 DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteObject_isObjectDead),
1500 };
1501 napi_value constructor = nullptr;
1502 napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
1503 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
1504 NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteObject failed");
1505 napi_status status = napi_set_named_property(env, exports, "RemoteObject", constructor);
1506 NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
1507 napi_value global = nullptr;
1508 status = napi_get_global(env, &global);
1509 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
1510 status = napi_set_named_property(env, global, "IPCStubConstructor_", constructor);
1511 NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
1512 return exports;
1513 }
1514 EXTERN_C_END
1515 } // namespace OHOS
1516