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