• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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