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 ZLOGI(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 ZLOGI(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 ZLOGE(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 ZLOGI(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 newCallingInfoParam.callingPid = IPCSkeleton::GetCallingPid();
702 newCallingInfoParam.callingUid = IPCSkeleton::GetCallingUid();
703 newCallingInfoParam.callingTokenId = IPCSkeleton::GetCallingTokenID();
704 newCallingInfoParam.callingDeviceID = IPCSkeleton::GetCallingDeviceID();
705 newCallingInfoParam.localDeviceID = IPCSkeleton::GetLocalDeviceID();
706 newCallingInfoParam.isLocalCalling = IPCSkeleton::IsLocalCalling();
707 newCallingInfoParam.activeStatus = IRemoteInvoker::ACTIVE_INVOKER;
708 };
709
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)710 int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
711 {
712 ZLOGD(LOG_LABEL, "enter OnRemoteRequest");
713 if (code == DUMP_TRANSACTION) {
714 ZLOGE(LOG_LABEL, "DUMP_TRANSACTION data size:%{public}zu", data.GetReadableBytes());
715 }
716 std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
717 CallbackParam *param = new (std::nothrow) CallbackParam {
718 .env = env_,
719 .thisVarRef = thisVarRef_,
720 .code = code,
721 .data = &data,
722 .reply = &reply,
723 .option = &option,
724 .lockInfo = lockInfo.get(),
725 .result = 0
726 };
727 if (param == nullptr) {
728 ZLOGE(LOG_LABEL, "new CallbackParam failed");
729 return ERR_ALLOC_MEMORY;
730 }
731
732 NAPI_RemoteObject_getCallingInfo(param->callingInfo);
733 ZLOGD(LOG_LABEL, "callingPid:%{public}u callingUid:%{public}u "
734 "callingDeviceID:%{public}s localDeviceId:%{public}s localCalling:%{public}d",
735 param->callingInfo.callingPid, param->callingInfo.callingUid,
736 IPCProcessSkeleton::ConvertToSecureString(param->callingInfo.callingDeviceID).c_str(),
737 IPCProcessSkeleton::ConvertToSecureString(param->callingInfo.localDeviceID).c_str(),
738 param->callingInfo.isLocalCalling);
739 int ret = OnJsRemoteRequest(param);
740 if (ret != 0) {
741 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
742 std::chrono::steady_clock::now().time_since_epoch()).count());
743 ZLOGE(LOG_LABEL, "OnJsRemoteRequest failed, ret:%{public}d time:%{public}" PRIu64, ret, curTime);
744 }
745 delete param;
746 return ret;
747 }
748
NAPI_RemoteObject_saveOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)749 void NAPI_RemoteObject_saveOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
750 {
751 napi_value global = nullptr;
752 napi_get_global(env, &global);
753 napi_get_named_property(env, global, "callingPid_", &oldCallingInfo.callingPid);
754 napi_get_named_property(env, global, "callingUid_", &oldCallingInfo.callingUid);
755 napi_get_named_property(env, global, "callingTokenId_", &oldCallingInfo.callingTokenId);
756 napi_get_named_property(env, global, "callingDeviceID_", &oldCallingInfo.callingDeviceID);
757 napi_get_named_property(env, global, "localDeviceID_", &oldCallingInfo.localDeviceID);
758 napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
759 napi_get_named_property(env, global, "isLocalCalling_", &oldCallingInfo.isLocalCalling);
760 napi_get_named_property(env, global, "activeStatus_", &oldCallingInfo.activeStatus);
761 }
762
NAPI_RemoteObject_setNewCallingInfo(napi_env env,const CallingInfo & newCallingInfoParam)763 void NAPI_RemoteObject_setNewCallingInfo(napi_env env, const CallingInfo &newCallingInfoParam)
764 {
765 napi_value global = nullptr;
766 napi_get_global(env, &global);
767 napi_value newPid = nullptr;
768 napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingPid), &newPid);
769 napi_set_named_property(env, global, "callingPid_", newPid);
770 napi_value newUid = nullptr;
771 napi_create_int32(env, static_cast<int32_t>(newCallingInfoParam.callingUid), &newUid);
772 napi_set_named_property(env, global, "callingUid_", newUid);
773 napi_value newCallingTokenId = nullptr;
774 napi_create_uint32(env, newCallingInfoParam.callingTokenId, &newCallingTokenId);
775 napi_set_named_property(env, global, "callingTokenId_", newCallingTokenId);
776 napi_value newDeviceID = nullptr;
777 napi_create_string_utf8(env, newCallingInfoParam.callingDeviceID.c_str(), NAPI_AUTO_LENGTH, &newDeviceID);
778 napi_set_named_property(env, global, "callingDeviceID_", newDeviceID);
779 napi_value newLocalDeviceID = nullptr;
780 napi_create_string_utf8(env, newCallingInfoParam.localDeviceID.c_str(), NAPI_AUTO_LENGTH, &newLocalDeviceID);
781 napi_set_named_property(env, global, "localDeviceID_", newLocalDeviceID);
782 napi_value newIsLocalCalling = nullptr;
783 napi_get_boolean(env, newCallingInfoParam.isLocalCalling, &newIsLocalCalling);
784 napi_set_named_property(env, global, "isLocalCalling_", newIsLocalCalling);
785 napi_value newActiveStatus = nullptr;
786 napi_create_int32(env, newCallingInfoParam.activeStatus, &newActiveStatus);
787 napi_set_named_property(env, global, "activeStatus_", newActiveStatus);
788 }
789
NAPI_RemoteObject_resetOldCallingInfo(napi_env env,NAPI_CallingInfo & oldCallingInfo)790 void NAPI_RemoteObject_resetOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCallingInfo)
791 {
792 napi_value global = nullptr;
793 napi_get_global(env, &global);
794 napi_set_named_property(env, global, "callingPid_", oldCallingInfo.callingPid);
795 napi_set_named_property(env, global, "callingUid_", oldCallingInfo.callingUid);
796 napi_set_named_property(env, global, "callingTokenId_", oldCallingInfo.callingTokenId);
797 napi_set_named_property(env, global, "callingDeviceID_", oldCallingInfo.callingDeviceID);
798 napi_set_named_property(env, global, "localDeviceID_", oldCallingInfo.localDeviceID);
799 napi_set_named_property(env, global, "isLocalCalling_", oldCallingInfo.isLocalCalling);
800 napi_set_named_property(env, global, "activeStatus_", oldCallingInfo.activeStatus);
801 }
802
OnJsRemoteRequest(CallbackParam * jsParam)803 int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
804 {
805 if (jsParam == nullptr) {
806 ZLOGE(LOG_LABEL, "Js Param is null");
807 return ERR_UNKNOWN_REASON;
808 }
809 if (thisVarRef_ == nullptr || env_ == nullptr) {
810 ZLOGE(LOG_LABEL, "Js env has been destructed");
811 return ERR_UNKNOWN_REASON;
812 }
813
814 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
815 std::chrono::steady_clock::now().time_since_epoch()).count());
816 ZLOGD(LOG_LABEL, "start nv queue work loop. desc:%{public}s time:%{public}" PRIu64,
817 desc_.c_str(), curTime);
818
819 std::string descriptor = desc_;
820 auto task = [jsParam, &descriptor]() {
821 OnJsRemoteRequestCallBack(jsParam, descriptor);
822 };
823 napi_status sendRet = napi_send_event(env_, task, napi_eprio_immediate);
824 if (sendRet != napi_ok) {
825 ZLOGE(LOG_LABEL, "napi_send_event failed, ret:%{public}d", sendRet);
826 return ERR_SEND_EVENT;
827 }
828
829 std::unique_lock<std::mutex> lock(jsParam->lockInfo->mutex);
830 jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
831 return jsParam->result;
832 }
833
CreateJsProxyRemoteObject(napi_env env,const sptr<IRemoteObject> target)834 napi_value CreateJsProxyRemoteObject(napi_env env, const sptr<IRemoteObject> target)
835 {
836 napi_value global = nullptr;
837 napi_status status = napi_get_global(env, &global);
838 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
839 napi_value constructor = nullptr;
840 status = napi_get_named_property(env, global, "IPCProxyConstructor_", &constructor);
841 NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
842 napi_value jsRemoteProxy;
843 status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
844 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteProxy");
845 NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
846 if (proxyHolder == nullptr) {
847 ZLOGE(LOG_LABEL, "proxyHolder null");
848 return nullptr;
849 }
850 proxyHolder->object_ = target;
851 proxyHolder->list_ = new (std::nothrow) NAPIDeathRecipientList();
852 NAPI_ASSERT(env, proxyHolder->list_ != nullptr, "new NAPIDeathRecipientList failed");
853
854 return jsRemoteProxy;
855 }
856
CreateJsStubRemoteObject(napi_env env,const sptr<IRemoteObject> target)857 napi_value CreateJsStubRemoteObject(napi_env env, const sptr<IRemoteObject> target)
858 {
859 // retrieve js remote object constructor
860 napi_value global = nullptr;
861 napi_status status = napi_get_global(env, &global);
862 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
863 napi_value constructor = nullptr;
864 status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
865 NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
866 NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
867 // retrieve descriptor and it's length
868 std::u16string descriptor = target->GetObjectDescriptor();
869 std::string desc = Str16ToStr8(descriptor);
870 napi_value jsDesc = nullptr;
871 napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
872 // create a new js remote object
873 size_t argc = 1;
874 napi_value argv[ARGV_LENGTH_1] = { jsDesc };
875 napi_value jsRemoteObject = nullptr;
876 status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
877 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteObject");
878 // retrieve holder and set object
879 NAPIRemoteObjectHolder *holder = nullptr;
880 napi_unwrap(env, jsRemoteObject, (void **)&holder);
881 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
882 holder->Set(target);
883 return jsRemoteObject;
884 }
885
GetJsStubRemoteObjectByRef(napi_env env,const sptr<IRemoteObject> target)886 napi_value GetJsStubRemoteObjectByRef(napi_env env, const sptr<IRemoteObject> target)
887 {
888 NAPIRemoteObject *object = static_cast<NAPIRemoteObject *>(target.GetRefPtr());
889 NAPI_ASSERT(env, object != nullptr, "get NAPIRemoteObject failed");
890 if (std::this_thread::get_id() != object->GetJSThreadId()) {
891 return CreateJsStubRemoteObject(env, target);
892 }
893 napi_value jsRemoteObject = nullptr;
894 napi_get_reference_value(env, object->GetJsObjectRef(), &jsRemoteObject);
895 return jsRemoteObject;
896 }
897
NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env,const sptr<IRemoteObject> target)898 napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteObject> target)
899 {
900 if (target == nullptr) {
901 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
902 std::chrono::steady_clock::now().time_since_epoch()).count());
903 ZLOGE(LOG_LABEL, "RemoteObject is null time:%{public}" PRIu64, curTime);
904 return nullptr;
905 }
906
907 if (!target->IsProxyObject()) {
908 IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
909 uint32_t objectType = static_cast<uint32_t>(tmp->GetObjectType());
910 ZLOGD(LOG_LABEL, "create js object, type:%{public}d", objectType);
911 if (objectType == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT) {
912 return GetJsStubRemoteObjectByRef(env, target);
913 } else if (objectType == IPCObjectStub::OBJECT_TYPE_NATIVE) {
914 return CreateJsStubRemoteObject(env, target);
915 } else {
916 ZLOGE(LOG_LABEL, "invalid type:%{public}d", objectType);
917 return nullptr;
918 }
919 }
920
921 return CreateJsProxyRemoteObject(env, target);
922 }
923
NAPI_ohos_rpc_ClearNativeRemoteProxy(napi_env env,napi_value jsRemoteProxy)924 bool NAPI_ohos_rpc_ClearNativeRemoteProxy(napi_env env, napi_value jsRemoteProxy)
925 {
926 NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
927 if (holder == nullptr) {
928 ZLOGE(LOG_LABEL, "holder null");
929 return false;
930 }
931 ZLOGI(LOG_LABEL, "clear native remote proxy");
932 holder->object_ = nullptr;
933 return true;
934 }
935
NAPI_ohos_rpc_getNativeRemoteObject(napi_env env,napi_value object)936 sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
937 {
938 if (object != nullptr) {
939 napi_value global = nullptr;
940 napi_status status = napi_get_global(env, &global);
941 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
942 napi_value stubConstructor = nullptr;
943 status = napi_get_named_property(env, global, "IPCStubConstructor_", &stubConstructor);
944 NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
945 bool instanceOfStub = false;
946 status = napi_instanceof(env, object, stubConstructor, &instanceOfStub);
947 NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
948 if (instanceOfStub) {
949 NAPIRemoteObjectHolder *holder = nullptr;
950 napi_unwrap(env, object, (void **)&holder);
951 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
952 return holder != nullptr ? holder->Get() : nullptr;
953 }
954
955 napi_value proxyConstructor = nullptr;
956 status = napi_get_named_property(env, global, "IPCProxyConstructor_", &proxyConstructor);
957 NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
958 bool instanceOfProxy = false;
959 status = napi_instanceof(env, object, proxyConstructor, &instanceOfProxy);
960 NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
961 if (instanceOfProxy) {
962 NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
963 return holder != nullptr ? holder->object_ : nullptr;
964 }
965 }
966 return nullptr;
967 }
968
NAPI_RemoteObject_queryLocalInterface(napi_env env,napi_callback_info info)969 static napi_value NAPI_RemoteObject_queryLocalInterface(napi_env env, napi_callback_info info)
970 {
971 size_t argc = 1;
972 size_t expectedArgc = 1;
973 napi_value argv[ARGV_LENGTH_1] = {nullptr};
974 napi_value thisVar = nullptr;
975 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
976 NAPI_ASSERT(env, argc == expectedArgc, "requires 1 parameters");
977 napi_valuetype valueType = napi_null;
978 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
979 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
980 size_t bufferSize = 0;
981 size_t maxLen = 40960;
982 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
983 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
984 char stringValue[bufferSize + 1];
985 size_t jsStringLength = 0;
986 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
987 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
988 std::string descriptor = stringValue;
989 NAPIRemoteObjectHolder *holder = nullptr;
990 napi_unwrap(env, thisVar, (void **)&holder);
991 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
992 napi_value ret = holder->queryLocalInterface(descriptor);
993 return ret;
994 }
995
NAPI_RemoteObject_getLocalInterface(napi_env env,napi_callback_info info)996 static napi_value NAPI_RemoteObject_getLocalInterface(napi_env env, napi_callback_info info)
997 {
998 size_t argc = 1;
999 size_t expectedArgc = 1;
1000 napi_value argv[ARGV_LENGTH_1] = {nullptr};
1001 napi_value thisVar = nullptr;
1002 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1003 if (argc != expectedArgc) {
1004 ZLOGE(LOG_LABEL, "requires 1 parameters");
1005 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1006 }
1007 napi_valuetype valueType = napi_null;
1008 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1009 if (valueType != napi_string) {
1010 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1011 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1012 }
1013 size_t bufferSize = 0;
1014 size_t maxLen = 40960;
1015 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], nullptr, 0, &bufferSize);
1016 if (bufferSize >= maxLen) {
1017 ZLOGE(LOG_LABEL, "string length too large");
1018 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1019 }
1020 char stringValue[bufferSize + 1];
1021 size_t jsStringLength = 0;
1022 napi_get_value_string_utf8(env, argv[ARGV_INDEX_0], stringValue, bufferSize + 1, &jsStringLength);
1023 if (jsStringLength != bufferSize) {
1024 ZLOGE(LOG_LABEL, "string length wrong");
1025 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1026 }
1027 std::string descriptor = stringValue;
1028 NAPIRemoteObjectHolder *holder = nullptr;
1029 napi_unwrap(env, thisVar, (void **)&holder);
1030 if (holder == nullptr) {
1031 ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1032 return nullptr;
1033 }
1034 napi_value ret = holder->queryLocalInterface(descriptor);
1035 return ret;
1036 }
1037
NAPI_RemoteObject_getInterfaceDescriptor(napi_env env,napi_callback_info info)1038 static napi_value NAPI_RemoteObject_getInterfaceDescriptor(napi_env env, napi_callback_info info)
1039 {
1040 napi_value result = nullptr;
1041 napi_value thisVar = nullptr;
1042 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1043 sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1044 NAPI_ASSERT(env, nativeObject != nullptr, "nativeObject is NULL.");
1045 std::u16string descriptor = nativeObject->GetObjectDescriptor();
1046 napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1047 return result;
1048 }
1049
NAPI_RemoteObject_getDescriptor(napi_env env,napi_callback_info info)1050 static napi_value NAPI_RemoteObject_getDescriptor(napi_env env, napi_callback_info info)
1051 {
1052 napi_value result = nullptr;
1053 napi_value thisVar = nullptr;
1054 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
1055 sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1056 if (nativeObject == nullptr) {
1057 ZLOGE(LOG_LABEL, "native stub object is nullptr");
1058 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
1059 }
1060 std::u16string descriptor = nativeObject->GetObjectDescriptor();
1061 napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1062 return result;
1063 }
1064
NAPI_RemoteObject_getCallingPid(napi_env env,napi_callback_info info)1065 static napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
1066 {
1067 return NAPI_getCallingPid(env, info);
1068 }
1069
NAPI_RemoteObject_getCallingUid(napi_env env,napi_callback_info info)1070 static napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
1071 {
1072 return NAPI_getCallingUid(env, info);
1073 }
1074
MakeSendRequestResult(SendRequestParam * param)1075 napi_value MakeSendRequestResult(SendRequestParam *param)
1076 {
1077 if (param == nullptr) {
1078 ZLOGE(LOG_LABEL, "send request param is null");
1079 return nullptr;
1080 }
1081 napi_value errCode = nullptr;
1082 napi_create_int32(param->env, param->errCode, &errCode);
1083 napi_value code = nullptr;
1084 napi_get_reference_value(param->env, param->jsCodeRef, &code);
1085 napi_value data = nullptr;
1086 napi_get_reference_value(param->env, param->jsDataRef, &data);
1087 napi_value reply = nullptr;
1088 napi_get_reference_value(param->env, param->jsReplyRef, &reply);
1089 napi_value result = nullptr;
1090 napi_create_object(param->env, &result);
1091 napi_set_named_property(param->env, result, "errCode", errCode);
1092 napi_set_named_property(param->env, result, "code", code);
1093 napi_set_named_property(param->env, result, "data", data);
1094 napi_set_named_property(param->env, result, "reply", reply);
1095 return result;
1096 }
1097
AfterWorkCallback(SendRequestParam * param)1098 static void AfterWorkCallback(SendRequestParam *param)
1099 {
1100 if (param->callback != nullptr) {
1101 ZLOGI(LOG_LABEL, "callback started");
1102 napi_handle_scope scope = nullptr;
1103 napi_open_handle_scope(param->env, &scope);
1104 napi_value result = MakeSendRequestResult(param);
1105 napi_value callbackValue = nullptr;
1106 napi_get_reference_value(param->env, param->callback, &callbackValue);
1107 napi_value cbResult = nullptr;
1108 napi_call_function(param->env, nullptr, callbackValue, 1, &result, &cbResult);
1109 napi_delete_reference(param->env, param->jsCodeRef);
1110 napi_delete_reference(param->env, param->jsDataRef);
1111 napi_delete_reference(param->env, param->jsReplyRef);
1112 napi_delete_reference(param->env, param->jsOptionRef);
1113 napi_delete_reference(param->env, param->callback);
1114 napi_close_handle_scope(param->env, scope);
1115 } else {
1116 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
1117 std::chrono::steady_clock::now().time_since_epoch()).count());
1118 ZLOGI(LOG_LABEL, "promise fulfilled time:%{public}" PRIu64, curTime);
1119 napi_handle_scope scope = nullptr;
1120 napi_open_handle_scope(param->env, &scope);
1121 napi_value result = MakeSendRequestResult(param);
1122 if (param->errCode == 0) {
1123 napi_resolve_deferred(param->env, param->deferred, result);
1124 } else {
1125 napi_reject_deferred(param->env, param->deferred, result);
1126 }
1127 napi_delete_reference(param->env, param->jsCodeRef);
1128 napi_delete_reference(param->env, param->jsDataRef);
1129 napi_delete_reference(param->env, param->jsReplyRef);
1130 napi_delete_reference(param->env, param->jsOptionRef);
1131 napi_close_handle_scope(param->env, scope);
1132 }
1133 delete param;
1134 }
1135
StubExecuteSendRequest(napi_env env,SendRequestParam * param)1136 void StubExecuteSendRequest(napi_env env, SendRequestParam *param)
1137 {
1138 if (param == nullptr) {
1139 ZLOGE(LOG_LABEL, "param is null");
1140 return;
1141 }
1142 param->errCode = param->target->SendRequest(param->code,
1143 *(param->data.get()), *(param->reply.get()), param->option);
1144 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
1145 std::chrono::steady_clock::now().time_since_epoch()).count());
1146 ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d time:%{public}" PRIu64, param->errCode, curTime);
1147 if (param->traceId != 0) {
1148 FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
1149 }
1150
1151 auto task = [param]() {
1152 AfterWorkCallback(param);
1153 };
1154 napi_status sendRet = napi_send_event(env, task, napi_eprio_high);
1155 if (sendRet != napi_ok) {
1156 ZLOGE(LOG_LABEL, "napi_send_event failed, ret:%{public}d", sendRet);
1157 delete param;
1158 }
1159 }
1160
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)1161 napi_value StubSendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1162 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1163 MessageOption &option, napi_value *argv)
1164 {
1165 napi_value result = nullptr;
1166 SendRequestParam *sendRequestParam = new (std::nothrow) SendRequestParam {
1167 .target = target,
1168 .code = code,
1169 .data = data,
1170 .reply = reply,
1171 .option = option,
1172 .asyncWork = nullptr,
1173 .deferred = nullptr,
1174 .errCode = -1,
1175 .jsCodeRef = nullptr,
1176 .jsDataRef = nullptr,
1177 .jsReplyRef = nullptr,
1178 .jsOptionRef = nullptr,
1179 .callback = nullptr,
1180 .env = env,
1181 .traceId = 0,
1182 };
1183 NAPI_ASSERT(env, sendRequestParam != nullptr, "new SendRequestParam failed");
1184 if (target != nullptr) {
1185 std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1186 if (!remoteDescriptor.empty()) {
1187 sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1188 sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1189 StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1190 }
1191 }
1192 napi_create_reference(env, argv[ARGV_INDEX_0], 1, &sendRequestParam->jsCodeRef);
1193 napi_create_reference(env, argv[ARGV_INDEX_1], 1, &sendRequestParam->jsDataRef);
1194 napi_create_reference(env, argv[ARGV_INDEX_2], 1, &sendRequestParam->jsReplyRef);
1195 napi_create_reference(env, argv[ARGV_INDEX_3], 1, &sendRequestParam->jsOptionRef);
1196 napi_create_reference(env, argv[ARGV_INDEX_4], 1, &sendRequestParam->callback);
1197 std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1198 t.detach();
1199 napi_get_undefined(env, &result);
1200 return result;
1201 }
1202
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)1203 napi_value StubSendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1204 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1205 MessageOption &option, napi_value *argv)
1206 {
1207 napi_deferred deferred = nullptr;
1208 napi_value promise = nullptr;
1209 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1210 SendRequestParam *sendRequestParam = new (std::nothrow) SendRequestParam {
1211 .target = target,
1212 .code = code,
1213 .data = data,
1214 .reply = reply,
1215 .option = option,
1216 .asyncWork = nullptr,
1217 .deferred = deferred,
1218 .errCode = -1,
1219 .jsCodeRef = nullptr,
1220 .jsDataRef = nullptr,
1221 .jsReplyRef = nullptr,
1222 .jsOptionRef = nullptr,
1223 .callback = nullptr,
1224 .env = env,
1225 .traceId = 0,
1226 };
1227 NAPI_ASSERT(env, sendRequestParam != nullptr, "new SendRequestParam failed");
1228 if (target != nullptr) {
1229 std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
1230 if (!remoteDescriptor.empty()) {
1231 sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
1232 sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
1233 StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
1234 }
1235 }
1236 napi_create_reference(env, argv[ARGV_INDEX_0], 1, &sendRequestParam->jsCodeRef);
1237 napi_create_reference(env, argv[ARGV_INDEX_1], 1, &sendRequestParam->jsDataRef);
1238 napi_create_reference(env, argv[ARGV_INDEX_2], 1, &sendRequestParam->jsReplyRef);
1239 napi_create_reference(env, argv[ARGV_INDEX_3], 1, &sendRequestParam->jsOptionRef);
1240 std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1241 t.detach();
1242 return promise;
1243 }
1244
NAPI_RemoteObject_sendRequest(napi_env env,napi_callback_info info)1245 static napi_value NAPI_RemoteObject_sendRequest(napi_env env, napi_callback_info info)
1246 {
1247 size_t argc = 4;
1248 size_t argcCallback = 5;
1249 size_t argcPromise = 4;
1250 napi_value argv[ARGV_LENGTH_5] = { 0 };
1251 napi_value thisVar = nullptr;
1252 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1253 NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1254 napi_valuetype valueType = napi_null;
1255 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1256 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1257 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1258 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1259 napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1260 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1261 napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1262 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1263
1264 NAPI_MessageParcel *data = nullptr;
1265 napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
1266 NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1267 NAPI_MessageParcel *reply = nullptr;
1268 status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
1269 NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1270 MessageOption *option = nullptr;
1271 status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
1272 NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1273 int32_t code = 0;
1274 napi_get_value_int32(env, argv[ARGV_INDEX_0], &code);
1275
1276 sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1277 if (argc == argcCallback) {
1278 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1279 napi_valuetype valuetype = napi_undefined;
1280 napi_typeof(env, argv[argcPromise], &valuetype);
1281 if (valuetype == napi_function) {
1282 return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1283 reply->GetMessageParcel(), *option, argv);
1284 }
1285 }
1286 return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1287 reply->GetMessageParcel(), *option, argv);
1288 }
1289
NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,size_t argc,size_t argcCallback,size_t argcPromise,napi_value * argv)1290 napi_value NAPI_RemoteObject_checkSendMessageRequestArgs(napi_env env,
1291 size_t argc,
1292 size_t argcCallback,
1293 size_t argcPromise,
1294 napi_value* argv)
1295 {
1296 if (argc != argcPromise && argc != argcCallback) {
1297 ZLOGE(LOG_LABEL, "requires 4 or 5 parameters");
1298 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1299 }
1300 napi_valuetype valueType = napi_null;
1301 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1302 if (valueType != napi_number) {
1303 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1304 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1305 }
1306 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1307 if (valueType != napi_object) {
1308 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1309 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1310 }
1311 napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
1312 if (valueType != napi_object) {
1313 ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
1314 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1315 }
1316 napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
1317 if (valueType != napi_object) {
1318 ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
1319 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1320 }
1321 napi_value result = nullptr;
1322 napi_get_undefined(env, &result);
1323 return result;
1324 }
1325
NAPI_RemoteObject_sendMessageRequest(napi_env env,napi_callback_info info)1326 static napi_value NAPI_RemoteObject_sendMessageRequest(napi_env env, napi_callback_info info)
1327 {
1328 size_t argc = 4;
1329 size_t argcCallback = 5;
1330 size_t argcPromise = 4;
1331 napi_value argv[ARGV_LENGTH_5] = { 0 };
1332 napi_value thisVar = nullptr;
1333 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1334 napi_value checkArgsResult = NAPI_RemoteObject_checkSendMessageRequestArgs(env, argc, argcCallback, argcPromise,
1335 argv);
1336 if (checkArgsResult == nullptr) {
1337 return checkArgsResult;
1338 }
1339 NAPI_MessageSequence *data = nullptr;
1340 napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
1341 if (status != napi_ok) {
1342 ZLOGE(LOG_LABEL, "failed to get data message sequence");
1343 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1344 }
1345 NAPI_MessageSequence *reply = nullptr;
1346 status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
1347 if (status != napi_ok) {
1348 ZLOGE(LOG_LABEL, "failed to get data message sequence");
1349 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1350 }
1351 MessageOption *option = nullptr;
1352 status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
1353 if (status != napi_ok) {
1354 ZLOGE(LOG_LABEL, "failed to get message option");
1355 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1356 }
1357 int32_t code = 0;
1358 napi_get_value_int32(env, argv[ARGV_INDEX_0], &code);
1359
1360 sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1361 if (argc == argcCallback) {
1362 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1363 napi_valuetype valuetype = napi_undefined;
1364 napi_typeof(env, argv[argcPromise], &valuetype);
1365 if (valuetype == napi_function) {
1366 return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1367 reply->GetMessageParcel(), *option, argv);
1368 }
1369 }
1370 return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1371 reply->GetMessageParcel(), *option, argv);
1372 }
1373
NAPI_RemoteObject_attachLocalInterface(napi_env env,napi_callback_info info)1374 static napi_value NAPI_RemoteObject_attachLocalInterface(napi_env env, napi_callback_info info)
1375 {
1376 size_t argc = 2;
1377 size_t expectedArgc = 2;
1378 napi_value argv[ARGV_LENGTH_2] = { 0 };
1379 napi_value thisVar = nullptr;
1380 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1381 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameters");
1382 napi_valuetype valueType = napi_null;
1383 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1384 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1385 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1386 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 2");
1387 size_t bufferSize = 0;
1388 size_t maxLen = 40960;
1389 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], nullptr, 0, &bufferSize);
1390 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1391 char stringValue[bufferSize + 1];
1392 size_t jsStringLength = 0;
1393 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], stringValue, bufferSize + 1, &jsStringLength);
1394 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1395 std::string descriptor = stringValue;
1396
1397 NAPIRemoteObjectHolder *holder = nullptr;
1398 napi_unwrap(env, thisVar, (void* *)&holder);
1399 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1400 holder->attachLocalInterface(argv[ARGV_INDEX_0], descriptor);
1401
1402 napi_value result = nullptr;
1403 napi_get_undefined(env, &result);
1404 return result;
1405 }
1406
NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env,size_t argc,napi_value * argv)1407 napi_value NAPI_RemoteObject_checkModifyLocalInterfaceArgs(napi_env env, size_t argc, napi_value* argv)
1408 {
1409 size_t expectedArgc = 2;
1410
1411 if (argc != expectedArgc) {
1412 ZLOGE(LOG_LABEL, "requires 2 parameters");
1413 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1414 }
1415 napi_valuetype valueType = napi_null;
1416 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
1417 if (valueType != napi_object) {
1418 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
1419 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1420 }
1421 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
1422 if (valueType != napi_string) {
1423 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
1424 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1425 }
1426 napi_value result = nullptr;
1427 napi_get_undefined(env, &result);
1428 return result;
1429 }
1430
NAPI_RemoteObject_modifyLocalInterface(napi_env env,napi_callback_info info)1431 static napi_value NAPI_RemoteObject_modifyLocalInterface(napi_env env, napi_callback_info info)
1432 {
1433 size_t argc = 2;
1434 napi_value argv[ARGV_LENGTH_2] = { 0 };
1435 napi_value thisVar = nullptr;
1436 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1437 napi_value checkArgsResult = NAPI_RemoteObject_checkModifyLocalInterfaceArgs(env, argc, argv);
1438 if (checkArgsResult == nullptr) {
1439 return checkArgsResult;
1440 }
1441 size_t bufferSize = 0;
1442 size_t maxLen = 40960;
1443 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], nullptr, 0, &bufferSize);
1444 if (bufferSize >= maxLen) {
1445 ZLOGE(LOG_LABEL, "string length too large");
1446 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1447 }
1448 char stringValue[bufferSize + 1];
1449 size_t jsStringLength = 0;
1450 napi_get_value_string_utf8(env, argv[ARGV_INDEX_1], stringValue, bufferSize + 1, &jsStringLength);
1451 if (jsStringLength != bufferSize) {
1452 ZLOGE(LOG_LABEL, "string length wrong");
1453 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
1454 }
1455 std::string descriptor = stringValue;
1456
1457 NAPIRemoteObjectHolder *holder = nullptr;
1458 napi_unwrap(env, thisVar, (void* *)&holder);
1459 if (holder == nullptr) {
1460 ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
1461 return nullptr;
1462 }
1463 holder->attachLocalInterface(argv[ARGV_INDEX_0], descriptor);
1464
1465 napi_value result = nullptr;
1466 napi_get_undefined(env, &result);
1467 return result;
1468 }
1469
NAPI_RemoteObject_addDeathRecipient(napi_env env,napi_callback_info info)1470 static napi_value NAPI_RemoteObject_addDeathRecipient(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
NAPI_RemoteObject_registerDeathRecipient(napi_env env,napi_callback_info info)1477 static napi_value NAPI_RemoteObject_registerDeathRecipient(napi_env env, napi_callback_info info)
1478 {
1479 ZLOGE(LOG_LABEL, "only proxy object permitted");
1480 return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1481 }
1482
NAPI_RemoteObject_removeDeathRecipient(napi_env env,napi_callback_info info)1483 static napi_value NAPI_RemoteObject_removeDeathRecipient(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_unregisterDeathRecipient(napi_env env,napi_callback_info info)1490 static napi_value NAPI_RemoteObject_unregisterDeathRecipient(napi_env env, napi_callback_info info)
1491 {
1492 ZLOGE(LOG_LABEL, "only proxy object permitted");
1493 return napiErr.ThrowError(env, errorDesc::ONLY_PROXY_OBJECT_PERMITTED_ERROR);
1494 }
1495
NAPI_RemoteObject_isObjectDead(napi_env env,napi_callback_info info)1496 static napi_value NAPI_RemoteObject_isObjectDead(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_Reclaim(napi_env env,napi_callback_info info)1503 static napi_value NAPI_RemoteObject_Reclaim(napi_env env, napi_callback_info info)
1504 {
1505 napi_value result = nullptr;
1506 napi_get_undefined(env, &result);
1507 return result;
1508 }
1509
1510 EXTERN_C_START
1511 /*
1512 * function for module exports
1513 */
NAPIRemoteObjectExport(napi_env env,napi_value exports)1514 napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports)
1515 {
1516 const std::string className = "RemoteObject";
1517 napi_property_descriptor properties[] = {
1518 DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteObject_sendRequest),
1519 DECLARE_NAPI_FUNCTION("sendMessageRequest", NAPI_RemoteObject_sendMessageRequest),
1520 DECLARE_NAPI_FUNCTION("getCallingPid", NAPI_RemoteObject_getCallingPid),
1521 DECLARE_NAPI_FUNCTION("getCallingUid", NAPI_RemoteObject_getCallingUid),
1522 DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteObject_getInterfaceDescriptor),
1523 DECLARE_NAPI_FUNCTION("getDescriptor", NAPI_RemoteObject_getDescriptor),
1524 DECLARE_NAPI_FUNCTION("attachLocalInterface", NAPI_RemoteObject_attachLocalInterface),
1525 DECLARE_NAPI_FUNCTION("modifyLocalInterface", NAPI_RemoteObject_modifyLocalInterface),
1526 DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteObject_queryLocalInterface),
1527 DECLARE_NAPI_FUNCTION("getLocalInterface", NAPI_RemoteObject_getLocalInterface),
1528 DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteObject_addDeathRecipient),
1529 DECLARE_NAPI_FUNCTION("registerDeathRecipient", NAPI_RemoteObject_registerDeathRecipient),
1530 DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteObject_removeDeathRecipient),
1531 DECLARE_NAPI_FUNCTION("unregisterDeathRecipient", NAPI_RemoteObject_unregisterDeathRecipient),
1532 DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteObject_isObjectDead),
1533 DECLARE_NAPI_FUNCTION("reclaim", NAPI_RemoteObject_Reclaim),
1534 };
1535 napi_value constructor = nullptr;
1536 napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
1537 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
1538 NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteObject failed");
1539 napi_status status = napi_set_named_property(env, exports, "RemoteObject", constructor);
1540 NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
1541 napi_value global = nullptr;
1542 status = napi_get_global(env, &global);
1543 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
1544 status = napi_set_named_property(env, global, "IPCStubConstructor_", constructor);
1545 NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
1546 return exports;
1547 }
1548 EXTERN_C_END
1549 } // namespace OHOS
1550