1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "napi_remote_object.h"
17 #include <mutex>
18 #include <cstring>
19 #include <thread>
20 #include <unistd.h>
21 #include <uv.h>
22 #include "access_token_adapter.h"
23 #include "hilog/log.h"
24 #include "hitrace_meter.h"
25 #include "ipc_object_proxy.h"
26 #include "ipc_object_stub.h"
27 #include "ipc_skeleton.h"
28 #include "ipc_thread_skeleton.h"
29 #include "ipc_debug.h"
30 #include "ipc_types.h"
31 #include "log_tags.h"
32 #include "napi_message_option.h"
33 #include "napi_message_parcel.h"
34 #include "napi_message_sequence.h"
35 #include "napi_rpc_error.h"
36 #include "rpc_bytrace.h"
37 #include "string_ex.h"
38
39 static std::atomic<int32_t> bytraceId = 1000;
40 namespace OHOS {
41 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "napi_remoteObject" };
42
43 static const uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag.
44
45 static NapiError napiErr;
46
47 static const size_t ARGV_INDEX_0 = 0;
48 static const size_t ARGV_INDEX_1 = 1;
49 static const size_t ARGV_INDEX_2 = 2;
50 static const size_t ARGV_INDEX_3 = 3;
51
NAPIDeathRecipient(napi_env env,napi_value jsDeathRecipient)52 NAPIDeathRecipient::NAPIDeathRecipient(napi_env env, napi_value jsDeathRecipient)
53 {
54 env_ = env;
55 napi_status status = napi_create_reference(env_, jsDeathRecipient, 1, &deathRecipientRef_);
56 NAPI_ASSERT_RETURN_VOID(env, status == napi_ok, "failed to create ref to js death recipient");
57 }
58
~NAPIDeathRecipient()59 NAPIDeathRecipient::~NAPIDeathRecipient()
60 {
61 if (env_ != nullptr) {
62 if (deathRecipientRef_ != nullptr) {
63 napi_status status = napi_delete_reference(env_, deathRecipientRef_);
64 NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js death recipient");
65 deathRecipientRef_ = nullptr;
66 }
67 }
68 }
69
OnRemoteDied(const wptr<IRemoteObject> & object)70 void NAPIDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
71 {
72 if (deathRecipientRef_ == nullptr) {
73 ZLOGE(LOG_LABEL, "js death recipient has already removed");
74 return;
75 }
76
77 uv_loop_s *loop = nullptr;
78 napi_get_uv_event_loop(env_, &loop);
79 uv_work_t *work = new(std::nothrow) uv_work_t;
80 if (work == nullptr) {
81 ZLOGE(LOG_LABEL, "failed to new uv_work_t");
82 return;
83 }
84 OnRemoteDiedParam *param = new OnRemoteDiedParam {
85 .env = env_,
86 .deathRecipientRef = deathRecipientRef_
87 };
88 work->data = reinterpret_cast<void *>(param);
89 ZLOGI(LOG_LABEL, "start to queue");
90 uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
91 ZLOGI(LOG_LABEL, "start to call onRmeoteDied");
92 OnRemoteDiedParam *param = reinterpret_cast<OnRemoteDiedParam *>(work->data);
93 napi_value jsDeathRecipient = nullptr;
94 napi_get_reference_value(param->env, param->deathRecipientRef, &jsDeathRecipient);
95 NAPI_ASSERT_RETURN_VOID(param->env, jsDeathRecipient != nullptr, "failed to get js death recipient");
96 napi_value onRemoteDied = nullptr;
97 napi_get_named_property(param->env, jsDeathRecipient, "onRemoteDied", &onRemoteDied);
98 NAPI_ASSERT_RETURN_VOID(param->env, onRemoteDied != nullptr, "failed to get property onRemoteDied");
99 napi_value return_val = nullptr;
100 napi_call_function(param->env, jsDeathRecipient, onRemoteDied, 0, nullptr, &return_val);
101 if (return_val == nullptr) {
102 ZLOGE(LOG_LABEL, "failed to call function onRemoteDied");
103 }
104 delete param;
105 delete work;
106 });
107 }
108
Matches(napi_value object)109 bool NAPIDeathRecipient::Matches(napi_value object)
110 {
111 bool result = false;
112 if (object != nullptr) {
113 if (deathRecipientRef_ != nullptr) {
114 napi_value jsDeathRecipient = nullptr;
115 napi_get_reference_value(env_, deathRecipientRef_, &jsDeathRecipient);
116 napi_status status = napi_strict_equals(env_, object, jsDeathRecipient, &result);
117 if (status != napi_ok) {
118 ZLOGI(LOG_LABEL, "compares death recipients failed");
119 }
120 }
121 }
122 return result;
123 }
124
NAPIDeathRecipientList()125 NAPIDeathRecipientList::NAPIDeathRecipientList() {}
126
~NAPIDeathRecipientList()127 NAPIDeathRecipientList::~NAPIDeathRecipientList()
128 {
129 std::lock_guard<std::mutex> lockGuard(mutex_);
130 set_.clear();
131 }
132
Add(const sptr<NAPIDeathRecipient> & recipient)133 bool NAPIDeathRecipientList::Add(const sptr<NAPIDeathRecipient> &recipient)
134 {
135 std::lock_guard<std::mutex> lockGuard(mutex_);
136 auto ret = set_.insert(recipient);
137 return ret.second;
138 }
139
Remove(const sptr<NAPIDeathRecipient> & recipient)140 bool NAPIDeathRecipientList::Remove(const sptr<NAPIDeathRecipient> &recipient)
141 {
142 std::lock_guard<std::mutex> lockGuard(mutex_);
143 return (set_.erase(recipient) > 0);
144 }
145
Find(napi_value jsRecipient)146 sptr<NAPIDeathRecipient> NAPIDeathRecipientList::Find(napi_value jsRecipient)
147 {
148 std::lock_guard<std::mutex> lockGuard(mutex_);
149 for (auto it = set_.begin(); it != set_.end(); it++) {
150 if ((*it)->Matches(jsRecipient)) {
151 return *it;
152 }
153 }
154 return nullptr;
155 }
156
NAPIRemoteProxyHolder()157 NAPIRemoteProxyHolder::NAPIRemoteProxyHolder() : list_(nullptr), object_(nullptr) {}
158
~NAPIRemoteProxyHolder()159 NAPIRemoteProxyHolder::~NAPIRemoteProxyHolder()
160 {
161 list_ = nullptr;
162 object_ = nullptr;
163 }
164
RemoteProxy_JS_Constructor(napi_env env,napi_callback_info info)165 napi_value RemoteProxy_JS_Constructor(napi_env env, napi_callback_info info)
166 {
167 napi_value thisVar = nullptr;
168 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
169 // new napi proxy holder instance
170 auto proxyHolder = new NAPIRemoteProxyHolder();
171 // connect native object to js thisVar
172 napi_status status = napi_wrap(
173 env, thisVar, proxyHolder,
174 [](napi_env env, void *data, void *hint) {
175 ZLOGI(LOG_LABEL, "proxy holder destructed by js callback");
176 delete (reinterpret_cast<NAPIRemoteProxyHolder *>(data));
177 },
178 nullptr, nullptr);
179 NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteProxy and native holder failed");
180 return thisVar;
181 }
182
183 EXTERN_C_START
184 /*
185 * function for module exports
186 */
NAPIRemoteProxyExport(napi_env env,napi_value exports)187 napi_value NAPIRemoteProxyExport(napi_env env, napi_value exports)
188 {
189 const std::string className = "RemoteProxy";
190 napi_value pingTransaction = nullptr;
191 napi_create_int32(env, PING_TRANSACTION, &pingTransaction);
192 napi_value dumpTransaction = nullptr;
193 napi_create_int32(env, DUMP_TRANSACTION, &dumpTransaction);
194 napi_value interfaceTransaction = nullptr;
195 napi_create_int32(env, INTERFACE_TRANSACTION, &interfaceTransaction);
196 napi_value minTransactionId = nullptr;
197 napi_create_int32(env, MIN_TRANSACTION_ID, &minTransactionId);
198 napi_value maxTransactionId = nullptr;
199 napi_create_int32(env, MAX_TRANSACTION_ID, &maxTransactionId);
200 napi_property_descriptor properties[] = {
201 DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteProxy_queryLocalInterface),
202 DECLARE_NAPI_FUNCTION("getLocalInterface", NAPI_RemoteProxy_getLocalInterface),
203 DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteProxy_addDeathRecipient),
204 DECLARE_NAPI_FUNCTION("registerDeathRecipient", NAPI_RemoteProxy_registerDeathRecipient),
205 DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteProxy_removeDeathRecipient),
206 DECLARE_NAPI_FUNCTION("unregisterDeathRecipient", NAPI_RemoteProxy_unregisterDeathRecipient),
207 DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteProxy_getInterfaceDescriptor),
208 DECLARE_NAPI_FUNCTION("getDescriptor", NAPI_RemoteProxy_getDescriptor),
209 DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteProxy_sendRequest),
210 DECLARE_NAPI_FUNCTION("sendMessageRequest", NAPI_RemoteProxy_sendMessageRequest),
211 DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteProxy_isObjectDead),
212 DECLARE_NAPI_STATIC_PROPERTY("PING_TRANSACTION", pingTransaction),
213 DECLARE_NAPI_STATIC_PROPERTY("DUMP_TRANSACTION", dumpTransaction),
214 DECLARE_NAPI_STATIC_PROPERTY("INTERFACE_TRANSACTION", interfaceTransaction),
215 DECLARE_NAPI_STATIC_PROPERTY("MIN_TRANSACTION_ID", minTransactionId),
216 DECLARE_NAPI_STATIC_PROPERTY("MAX_TRANSACTION_ID", maxTransactionId),
217 };
218 napi_value constructor = nullptr;
219 napi_define_class(env, className.c_str(), className.length(), RemoteProxy_JS_Constructor, nullptr,
220 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
221 NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteProxy failed");
222 napi_status status = napi_set_named_property(env, exports, "RemoteProxy", constructor);
223 NAPI_ASSERT(env, status == napi_ok, "set property RemoteProxy to exports failed");
224 napi_value global = nullptr;
225 status = napi_get_global(env, &global);
226 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
227 status = napi_set_named_property(env, global, "IPCProxyConstructor_", constructor);
228 NAPI_ASSERT(env, status == napi_ok, "set proxy constructor failed");
229 return exports;
230 }
231 EXTERN_C_END
232
233 // This method runs on a worker thread, no access to the JavaScript
ExecuteSendRequest(napi_env env,void * data)234 void ExecuteSendRequest(napi_env env, void *data)
235 {
236 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(data);
237 param->errCode = param->target->SendRequest(param->code,
238 *(param->data.get()), *(param->reply.get()), param->option);
239 ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d", param->errCode);
240 if (param->traceId != 0) {
241 FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
242 }
243 }
244
245 // This method runs on the main thread after 'ExecuteSendRequest' exits
SendRequestCbComplete(napi_env env,napi_status status,void * data)246 void SendRequestCbComplete(napi_env env, napi_status status, void *data)
247 {
248 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(data);
249 ZLOGI(LOG_LABEL, "sendRequestCallback completed, errCode:%{public}d", param->errCode);
250 napi_value result = MakeSendRequestResult(param);
251 napi_value callback = nullptr;
252 napi_get_reference_value(env, param->callback, &callback);
253 napi_value cbResult = nullptr;
254 napi_call_function(env, nullptr, callback, 1, &result, &cbResult);
255 napi_delete_reference(env, param->jsCodeRef);
256 napi_delete_reference(env, param->jsDataRef);
257 napi_delete_reference(env, param->jsReplyRef);
258 napi_delete_reference(env, param->callback);
259 napi_delete_async_work(env, param->asyncWork);
260 delete param;
261 }
262
263 // This method runs on the main thread after 'ExecuteSendRequest' exits
SendRequestPromiseComplete(napi_env env,napi_status status,void * data)264 void SendRequestPromiseComplete(napi_env env, napi_status status, void *data)
265 {
266 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(data);
267 ZLOGI(LOG_LABEL, "sendRequestPromise completed, errCode:%{public}d", param->errCode);
268 napi_value result = MakeSendRequestResult(param);
269 if (param->errCode == 0) {
270 napi_resolve_deferred(env, param->deferred, result);
271 } else {
272 napi_reject_deferred(env, param->deferred, result);
273 }
274 napi_delete_reference(env, param->jsCodeRef);
275 napi_delete_reference(env, param->jsDataRef);
276 napi_delete_reference(env, param->jsReplyRef);
277 napi_delete_async_work(env, param->asyncWork);
278 delete param;
279 }
280
SendRequestAsync(napi_env env,sptr<IRemoteObject> target,uint32_t code,std::shared_ptr<MessageParcel> data,std::shared_ptr<MessageParcel> reply,MessageOption & option,napi_value * argv)281 napi_value SendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
282 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
283 MessageOption &option, napi_value *argv)
284 {
285 napi_value result = nullptr;
286 SendRequestParam *sendRequestParam = new SendRequestParam {
287 .target = target,
288 .code = code,
289 .data = data,
290 .reply = reply,
291 .option = option,
292 .asyncWork = nullptr,
293 .deferred = nullptr,
294 .errCode = -1,
295 .jsCodeRef = nullptr,
296 .jsDataRef = nullptr,
297 .jsReplyRef = nullptr,
298 .callback = nullptr,
299 .env = env,
300 .traceId = 0,
301 };
302 IPCObjectProxy *targetProxy = reinterpret_cast<IPCObjectProxy *>(target.GetRefPtr());
303 if (targetProxy != nullptr) {
304 std::string remoteDescriptor = Str16ToStr8(targetProxy->GetInterfaceDescriptor());
305 if (!remoteDescriptor.empty()) {
306 sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
307 sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
308 StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
309 }
310 }
311 napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
312 napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
313 napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
314 napi_create_reference(env, argv[4], 1, &sendRequestParam->callback);
315 napi_value resourceName = nullptr;
316 NAPI_CALL(env, napi_create_string_utf8(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
317 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, ExecuteSendRequest,
318 SendRequestCbComplete, (void *)sendRequestParam, &sendRequestParam->asyncWork));
319 NAPI_CALL(env, napi_queue_async_work(env, sendRequestParam->asyncWork));
320 napi_get_undefined(env, &result);
321 return result;
322 }
323
SendRequestPromise(napi_env env,sptr<IRemoteObject> target,uint32_t code,std::shared_ptr<MessageParcel> data,std::shared_ptr<MessageParcel> reply,MessageOption & option,napi_value * argv)324 napi_value SendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
325 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
326 MessageOption &option, napi_value *argv)
327 {
328 napi_deferred deferred = nullptr;
329 napi_value promise = nullptr;
330 napi_create_promise(env, &deferred, &promise);
331 SendRequestParam *sendRequestParam = new SendRequestParam {
332 .target = target,
333 .code = code,
334 .data = data,
335 .reply = reply,
336 .option = option,
337 .asyncWork = nullptr,
338 .deferred = deferred,
339 .errCode = -1,
340 .jsCodeRef = nullptr,
341 .jsDataRef = nullptr,
342 .jsReplyRef = nullptr,
343 .callback = nullptr,
344 .env = env,
345 .traceId = 0,
346 };
347 IPCObjectProxy *targetProxy = reinterpret_cast<IPCObjectProxy *>(target.GetRefPtr());
348 if (targetProxy != nullptr) {
349 std::string remoteDescriptor = Str16ToStr8(targetProxy->GetInterfaceDescriptor());
350 if (!remoteDescriptor.empty()) {
351 sendRequestParam->traceValue = remoteDescriptor + std::to_string(code);
352 sendRequestParam->traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
353 StartAsyncTrace(HITRACE_TAG_RPC, (sendRequestParam->traceValue).c_str(), sendRequestParam->traceId);
354 }
355 }
356 napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
357 napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
358 napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
359 napi_value resourceName = nullptr;
360 NAPI_CALL(env, napi_create_string_utf8(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
361 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, ExecuteSendRequest,
362 SendRequestPromiseComplete, (void *)sendRequestParam, &sendRequestParam->asyncWork));
363 NAPI_CALL(env, napi_queue_async_work(env, sendRequestParam->asyncWork));
364 return promise;
365 }
366
NAPI_RemoteProxy_sendRequest(napi_env env,napi_callback_info info)367 napi_value NAPI_RemoteProxy_sendRequest(napi_env env, napi_callback_info info)
368 {
369 size_t argc = 4;
370 size_t argcCallback = 5;
371 size_t argcPromise = 4;
372 napi_value argv[5] = { 0 };
373 napi_value thisVar = nullptr;
374 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
375 NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
376 napi_valuetype valueType = napi_null;
377 napi_typeof(env, argv[0], &valueType);
378 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
379 napi_typeof(env, argv[1], &valueType);
380 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
381 napi_typeof(env, argv[2], &valueType);
382 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
383 napi_typeof(env, argv[3], &valueType);
384 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
385
386 NAPI_MessageParcel *data = nullptr;
387 napi_status status = napi_unwrap(env, argv[1], (void **)&data);
388 NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
389 NAPI_MessageParcel *reply = nullptr;
390 status = napi_unwrap(env, argv[2], (void **)&reply);
391 NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
392 MessageOption *option = nullptr;
393 status = napi_unwrap(env, argv[3], (void **)&option);
394 NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
395 int32_t code = 0;
396 napi_get_value_int32(env, argv[0], &code);
397
398 NAPIRemoteProxyHolder *proxyHolder = nullptr;
399 napi_unwrap(env, thisVar, (void **)&proxyHolder);
400 NAPI_ASSERT(env, proxyHolder != nullptr, "failed to get proxy holder");
401 sptr<IRemoteObject> target = proxyHolder->object_;
402 NAPI_ASSERT(env, target != nullptr, "invalid proxy object");
403 if (argc == argcCallback) {
404 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
405 napi_valuetype valuetype = napi_undefined;
406 napi_typeof(env, argv[argcPromise], &valuetype);
407 if (valuetype == napi_function) {
408 return SendRequestAsync(env, target, code, data->GetMessageParcel(),
409 reply->GetMessageParcel(), *option, argv);
410 }
411 }
412 return SendRequestPromise(env, target, code, data->GetMessageParcel(),
413 reply->GetMessageParcel(), *option, argv);
414 }
415
NAPI_RemoteProxy_checkSendMessageRequestArgs(napi_env env,napi_value * argv,NAPI_MessageSequence * & data,NAPI_MessageSequence * & reply,MessageOption * & option)416 napi_value NAPI_RemoteProxy_checkSendMessageRequestArgs(napi_env env,
417 napi_value* argv,
418 NAPI_MessageSequence* &data,
419 NAPI_MessageSequence* &reply,
420 MessageOption* &option)
421 {
422 napi_valuetype valueType = napi_null;
423 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
424 if (valueType != napi_number) {
425 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
426 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
427 }
428 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
429 if (valueType != napi_object) {
430 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
431 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
432 }
433 napi_typeof(env, argv[ARGV_INDEX_2], &valueType);
434 if (valueType != napi_object) {
435 ZLOGE(LOG_LABEL, "type mismatch for parameter 3");
436 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
437 }
438 napi_typeof(env, argv[ARGV_INDEX_3], &valueType);
439 if (valueType != napi_object) {
440 ZLOGE(LOG_LABEL, "type mismatch for parameter 4");
441 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
442 }
443
444 napi_status status = napi_unwrap(env, argv[ARGV_INDEX_1], (void **)&data);
445 if (status != napi_ok) {
446 ZLOGE(LOG_LABEL, "failed to get data message parcel");
447 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
448 }
449 status = napi_unwrap(env, argv[ARGV_INDEX_2], (void **)&reply);
450 if (status != napi_ok) {
451 ZLOGE(LOG_LABEL, "failed to get reply message parcel");
452 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
453 }
454 status = napi_unwrap(env, argv[ARGV_INDEX_3], (void **)&option);
455 if (status != napi_ok) {
456 ZLOGE(LOG_LABEL, "failed to get message option");
457 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
458 }
459 napi_value result = nullptr;
460 napi_get_undefined(env, &result);
461 return result;
462 }
463
NAPI_RemoteProxy_sendMessageRequest(napi_env env,napi_callback_info info)464 napi_value NAPI_RemoteProxy_sendMessageRequest(napi_env env, napi_callback_info info)
465 {
466 size_t argc = 4;
467 size_t argcCallback = 5;
468 size_t argcPromise = 4;
469 napi_value argv[5] = { 0 };
470 napi_value thisVar = nullptr;
471 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
472 if (argc != argcPromise && argc != argcCallback) {
473 ZLOGE(LOG_LABEL, "requires 4 or 5 parameters");
474 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
475 }
476 NAPI_MessageSequence *data = nullptr;
477 NAPI_MessageSequence *reply = nullptr;
478 MessageOption *option = nullptr;
479 napi_value checkArgsResult = NAPI_RemoteProxy_checkSendMessageRequestArgs(env, argv, data, reply, option);
480 if (checkArgsResult == nullptr) {
481 return checkArgsResult;
482 }
483 int32_t code = 0;
484 napi_get_value_int32(env, argv[0], &code);
485
486 napi_value result = nullptr;
487 napi_get_undefined(env, &result);
488 NAPIRemoteProxyHolder *proxyHolder = nullptr;
489 napi_unwrap(env, thisVar, (void **)&proxyHolder);
490 if (proxyHolder == nullptr) {
491 ZLOGE(LOG_LABEL, "failed to get proxy holder");
492 return result;
493 }
494 sptr<IRemoteObject> target = proxyHolder->object_;
495 if (target == nullptr) {
496 ZLOGE(LOG_LABEL, "invalid proxy object");
497 return result;
498 }
499 if (argc == argcCallback) {
500 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
501 napi_valuetype valuetype = napi_undefined;
502 napi_typeof(env, argv[argcPromise], &valuetype);
503 if (valuetype == napi_function) {
504 return SendRequestAsync(env, target, code, data->GetMessageParcel(),
505 reply->GetMessageParcel(), *option, argv);
506 }
507 }
508 return SendRequestPromise(env, target, code, data->GetMessageParcel(),
509 reply->GetMessageParcel(), *option, argv);
510 }
511
NAPI_RemoteProxy_queryLocalInterface(napi_env env,napi_callback_info info)512 napi_value NAPI_RemoteProxy_queryLocalInterface(napi_env env, napi_callback_info info)
513 {
514 napi_value result = nullptr;
515 napi_get_null(env, &result);
516 return result;
517 }
518
NAPI_RemoteProxy_getLocalInterface(napi_env env,napi_callback_info info)519 napi_value NAPI_RemoteProxy_getLocalInterface(napi_env env, napi_callback_info info)
520 {
521 ZLOGE(LOG_LABEL, "only remote object permitted");
522 return napiErr.ThrowError(env, errorDesc::ONLY_REMOTE_OBJECT_PERMITTED_ERROR);
523 }
524
NAPI_RemoteProxy_addDeathRecipient(napi_env env,napi_callback_info info)525 napi_value NAPI_RemoteProxy_addDeathRecipient(napi_env env, napi_callback_info info)
526 {
527 ZLOGI(LOG_LABEL, "add death recipient");
528 size_t argc = 2;
529 size_t expectedArgc = 2;
530 napi_value argv[2] = { 0 };
531 napi_value thisVar = nullptr;
532 void *data = nullptr;
533 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
534 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameter");
535 napi_valuetype valueType = napi_null;
536 napi_typeof(env, argv[0], &valueType);
537 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
538 napi_typeof(env, argv[1], &valueType);
539 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
540 int32_t flag = 0;
541 napi_get_value_int32(env, argv[1], &flag);
542
543 napi_value result;
544 if (argv[0] == nullptr) {
545 napi_get_boolean(env, false, &result);
546 return result;
547 }
548
549 NAPIRemoteProxyHolder *proxyHolder = nullptr;
550 napi_status status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
551 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
552 if (proxyHolder == nullptr) {
553 napi_get_boolean(env, false, &result);
554 return result;
555 }
556 sptr<IRemoteObject> target = proxyHolder->object_;
557 if ((target == nullptr) || !target->IsProxyObject()) {
558 ZLOGE(LOG_LABEL, "could not add recipient from invalid target");
559 napi_get_boolean(env, false, &result);
560 return result;
561 }
562
563 sptr<NAPIDeathRecipient> nativeRecipient = new NAPIDeathRecipient(env, argv[0]);
564 if (target->AddDeathRecipient(nativeRecipient)) {
565 NAPIDeathRecipientList *list = proxyHolder->list_;
566 if (list->Add(nativeRecipient)) {
567 napi_get_boolean(env, true, &result);
568 return result;
569 }
570 }
571 napi_get_boolean(env, false, &result);
572 return result;
573 }
574
NAPI_RemoteProxy_checkRegisterDeathRecipientArgs(napi_env env,size_t argc,napi_value * argv)575 napi_value NAPI_RemoteProxy_checkRegisterDeathRecipientArgs(napi_env env, size_t argc, napi_value* argv)
576 {
577 size_t expectedArgc = 2;
578
579 if (argc != expectedArgc) {
580 ZLOGE(LOG_LABEL, "requires 2 parameter");
581 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
582 }
583 napi_valuetype valueType = napi_null;
584 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
585 if (valueType != napi_object) {
586 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
587 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
588 }
589 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
590 if (valueType != napi_number) {
591 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
592 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
593 }
594 napi_value result = nullptr;
595 napi_get_undefined(env, &result);
596 return result;
597 }
598
NAPI_RemoteProxy_registerDeathRecipient(napi_env env,napi_callback_info info)599 napi_value NAPI_RemoteProxy_registerDeathRecipient(napi_env env, napi_callback_info info)
600 {
601 ZLOGI(LOG_LABEL, "register death recipient");
602 size_t argc = 2;
603 napi_value argv[2] = { 0 };
604 napi_value thisVar = nullptr;
605 void *data = nullptr;
606 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
607 napi_value checkArgsResult = NAPI_RemoteProxy_checkRegisterDeathRecipientArgs(env, argc, argv);
608 if (checkArgsResult == nullptr) {
609 return checkArgsResult;
610 }
611 int32_t flag = 0;
612 napi_get_value_int32(env, argv[1], &flag);
613
614 if (argv[0] == nullptr) {
615 ZLOGE(LOG_LABEL, "invalid parameter 1");
616 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
617 }
618
619 NAPIRemoteProxyHolder *proxyHolder = nullptr;
620 napi_status status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
621 if (status != napi_ok) {
622 ZLOGE(LOG_LABEL, "failed to get proxy holder");
623 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
624 }
625 if (proxyHolder == nullptr) {
626 ZLOGE(LOG_LABEL, "proxy holder is nullptr");
627 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
628 }
629 sptr<IRemoteObject> target = proxyHolder->object_;
630 if ((target == nullptr) || !target->IsProxyObject()) {
631 ZLOGE(LOG_LABEL, "could not add recipient from invalid target");
632 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
633 }
634
635 sptr<NAPIDeathRecipient> nativeRecipient = new NAPIDeathRecipient(env, argv[0]);
636 if (target->AddDeathRecipient(nativeRecipient)) {
637 NAPIDeathRecipientList *list = proxyHolder->list_;
638 if (list->Add(nativeRecipient)) {
639 ZLOGD(LOG_LABEL, "register recipient success");
640 }
641 }
642 napi_value result = nullptr;
643 napi_get_undefined(env, &result);
644 return result;
645 }
646
NAPI_RemoteProxy_removeDeathRecipient(napi_env env,napi_callback_info info)647 napi_value NAPI_RemoteProxy_removeDeathRecipient(napi_env env, napi_callback_info info)
648 {
649 ZLOGI(LOG_LABEL, "remove death recipient");
650 size_t argc = 2;
651 napi_value argv[2] = { 0 };
652 napi_value thisVar = nullptr;
653 void *data = nullptr;
654 size_t expectedArgc = 2;
655 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
656 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameter");
657 napi_valuetype valueType = napi_null;
658 napi_typeof(env, argv[0], &valueType);
659 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
660 napi_typeof(env, argv[1], &valueType);
661 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
662 napi_value result;
663 if (argv[0] == nullptr) {
664 napi_get_boolean(env, false, &result);
665 return result;
666 }
667 int32_t flag = 0;
668 napi_get_value_int32(env, argv[1], &flag);
669
670 NAPIRemoteProxyHolder *proxyHolder = nullptr;
671 napi_status status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
672 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
673 if (proxyHolder == nullptr) {
674 napi_get_boolean(env, false, &result);
675 return result;
676 }
677 sptr<IRemoteObject> target = proxyHolder->object_;
678 if ((target == nullptr) || !target->IsProxyObject()) {
679 ZLOGE(LOG_LABEL, "could not remove recipient from invalid target");
680 napi_get_boolean(env, false, &result);
681 return result;
682 }
683 sptr<NAPIDeathRecipientList> list = proxyHolder->list_;
684 sptr<NAPIDeathRecipient> nativeRecipient = list->Find(argv[0]);
685 if (nativeRecipient == nullptr) {
686 ZLOGE(LOG_LABEL, "recipient not found");
687 napi_get_boolean(env, false, &result);
688 return result;
689 }
690 target->RemoveDeathRecipient(nativeRecipient);
691 if (list->Remove(nativeRecipient)) {
692 napi_get_boolean(env, true, &result);
693 return result;
694 } else {
695 napi_get_boolean(env, false, &result);
696 return result;
697 }
698 }
699
NAPI_RemoteProxy_checkUnregisterDeathRecipientArgs(napi_env env,size_t argc,napi_value * argv)700 napi_value NAPI_RemoteProxy_checkUnregisterDeathRecipientArgs(napi_env env, size_t argc, napi_value* argv)
701 {
702 size_t expectedArgc = 2;
703 if (argc != expectedArgc) {
704 ZLOGE(LOG_LABEL, "requires 2 parameter");
705 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
706 }
707 napi_valuetype valueType = napi_null;
708 napi_typeof(env, argv[ARGV_INDEX_0], &valueType);
709 if (valueType != napi_object) {
710 ZLOGE(LOG_LABEL, "type mismatch for parameter 1");
711 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
712 }
713 napi_typeof(env, argv[ARGV_INDEX_1], &valueType);
714 if (valueType != napi_number) {
715 ZLOGE(LOG_LABEL, "type mismatch for parameter 2");
716 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
717 }
718 if (argv[ARGV_INDEX_0] == nullptr) {
719 ZLOGE(LOG_LABEL, "invalid parameter 1");
720 return napiErr.ThrowError(env, errorDesc::CHECK_PARAM_ERROR);
721 }
722 napi_value result = nullptr;
723 napi_get_undefined(env, &result);
724 return result;
725 }
726
NAPI_RemoteProxy_unregisterDeathRecipient(napi_env env,napi_callback_info info)727 napi_value NAPI_RemoteProxy_unregisterDeathRecipient(napi_env env, napi_callback_info info)
728 {
729 ZLOGI(LOG_LABEL, "unregister death recipient");
730 size_t argc = 2;
731 napi_value argv[2] = { 0 };
732 napi_value thisVar = nullptr;
733 void *data = nullptr;
734 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
735 napi_value checkArgsResult = NAPI_RemoteProxy_checkUnregisterDeathRecipientArgs(env, argc, argv);
736 if (checkArgsResult == nullptr) {
737 return checkArgsResult;
738 }
739 int32_t flag = 0;
740 napi_get_value_int32(env, argv[1], &flag);
741
742 NAPIRemoteProxyHolder *proxyHolder = nullptr;
743 napi_status status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
744 if (status != napi_ok) {
745 ZLOGE(LOG_LABEL, "failed to get proxy holder");
746 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
747 }
748 if (proxyHolder == nullptr) {
749 ZLOGE(LOG_LABEL, "proxy holder is nullptr");
750 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
751 }
752 sptr<IRemoteObject> target = proxyHolder->object_;
753 if ((target == nullptr) || !target->IsProxyObject()) {
754 ZLOGE(LOG_LABEL, "could not remove recipient from invalid target");
755 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
756 }
757 napi_value result = nullptr;
758 napi_get_undefined(env, &result);
759 sptr<NAPIDeathRecipientList> list = proxyHolder->list_;
760 sptr<NAPIDeathRecipient> nativeRecipient = list->Find(argv[0]);
761 if (nativeRecipient == nullptr) {
762 ZLOGE(LOG_LABEL, "recipient not found");
763 return result;
764 }
765 target->RemoveDeathRecipient(nativeRecipient);
766 if (list->Remove(nativeRecipient)) {
767 ZLOGD(LOG_LABEL, "remove recipient from list success");
768 return result;
769 } else {
770 ZLOGE(LOG_LABEL, "remove recipient from list failed");
771 return result;
772 }
773 }
774
NAPI_RemoteProxy_getInterfaceDescriptor(napi_env env,napi_callback_info info)775 napi_value NAPI_RemoteProxy_getInterfaceDescriptor(napi_env env, napi_callback_info info)
776 {
777 napi_value thisVar = nullptr;
778 napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
779 NAPIRemoteProxyHolder *holder = nullptr;
780 napi_status status = napi_unwrap(env, thisVar, (void **)&holder);
781 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
782 napi_value result;
783 if (holder == nullptr) {
784 napi_create_string_utf8(env, "", 0, &result);
785 return result;
786 }
787 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
788 if (target == nullptr) {
789 ZLOGE(LOG_LABEL, "Invalid proxy object");
790 napi_create_string_utf8(env, "", 0, &result);
791 return result;
792 }
793 std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
794 napi_create_string_utf8(env, Str16ToStr8(remoteDescriptor).c_str(), NAPI_AUTO_LENGTH, &result);
795 return result;
796 }
797
NAPI_RemoteProxy_getDescriptor(napi_env env,napi_callback_info info)798 napi_value NAPI_RemoteProxy_getDescriptor(napi_env env, napi_callback_info info)
799 {
800 napi_value thisVar = nullptr;
801 napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
802 NAPIRemoteProxyHolder *holder = nullptr;
803 napi_status status = napi_unwrap(env, thisVar, (void **)&holder);
804 if (status != napi_ok) {
805 ZLOGE(LOG_LABEL, "failed to get proxy holder");
806 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
807 }
808 napi_value result;
809 if (holder == nullptr) {
810 ZLOGE(LOG_LABEL, "proxy holder is nullptr");
811 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
812 }
813 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
814 if (target == nullptr) {
815 ZLOGE(LOG_LABEL, "proxy object is nullptr");
816 return napiErr.ThrowError(env, errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR);
817 }
818 std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
819 if (remoteDescriptor == std::u16string()) {
820 ZLOGE(LOG_LABEL, "failed to get interface descriptor");
821 return napiErr.ThrowError(env, errorDesc::COMMUNICATION_ERROR);
822 }
823 napi_create_string_utf8(env, Str16ToStr8(remoteDescriptor).c_str(), NAPI_AUTO_LENGTH, &result);
824 return result;
825 }
826
NAPI_RemoteProxy_isObjectDead(napi_env env,napi_callback_info info)827 napi_value NAPI_RemoteProxy_isObjectDead(napi_env env, napi_callback_info info)
828 {
829 ZLOGI(LOG_LABEL, "call isObjectDead");
830 napi_value thisVar = nullptr;
831 napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
832 NAPIRemoteProxyHolder *holder = nullptr;
833 napi_status status = napi_unwrap(env, thisVar, (void **)&holder);
834 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
835 napi_value result;
836 if (holder == nullptr) {
837 napi_get_boolean(env, false, &result);
838 return result;
839 }
840 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
841 if (target == nullptr) {
842 ZLOGE(LOG_LABEL, "Invalid proxy object");
843 napi_get_boolean(env, false, &result);
844 return result;
845 }
846
847 if (target->IsObjectDead()) {
848 napi_get_boolean(env, true, &result);
849 return result;
850 } else {
851 napi_get_boolean(env, false, &result);
852 return result;
853 }
854 }
855
856 } // namespace OHOS