1 /*
2 * Copyright (c) 2021 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 <set>
19 #include <cstring>
20 #include <thread>
21 #include <unistd.h>
22 #include <uv.h>
23 #include "access_token_adapter.h"
24 #include "hilog/log.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_types.h"
30 #include "log_tags.h"
31 #include "napi_message_option.h"
32 #include "napi_message_parcel.h"
33 #include "rpc_bytrace.h"
34 #include "string_ex.h"
35
36
37 namespace OHOS {
38 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "napi_remoteObject" };
39 #ifndef TITLE
40 #define TITLE __PRETTY_FUNCTION__
41 #endif
42 #define DBINDER_LOGE(fmt, args...) \
43 (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
44 #define DBINDER_LOGI(fmt, args...) \
45 (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
46
47 /*
48 * The native DeathRecipient container.
49 * As an recipient of obituary of service death,
50 * and pass the message to js Layer.
51 */
52 class NAPIDeathRecipient : public IRemoteObject::DeathRecipient {
53 public:
54 explicit NAPIDeathRecipient(napi_env env, napi_value jsRecipient);
55
56 void OnRemoteDied(const wptr<IRemoteObject> &object) override;
57
58 bool Matches(napi_value jsRecipient);
59
60 protected:
61 virtual ~NAPIDeathRecipient();
62
63 private:
64 struct OnRemoteDiedParam {
65 napi_env env;
66 napi_ref deathRecipientRef;
67 };
68 napi_env env_ = nullptr;
69 napi_ref deathRecipientRef_ = nullptr;
70 };
71
NAPIDeathRecipient(napi_env env,napi_value jsDeathRecipient)72 NAPIDeathRecipient::NAPIDeathRecipient(napi_env env, napi_value jsDeathRecipient)
73 {
74 env_ = env;
75 napi_status status = napi_create_reference(env_, jsDeathRecipient, 1, &deathRecipientRef_);
76 NAPI_ASSERT_RETURN_VOID(env, status == napi_ok, "failed to create ref to js death recipient");
77 }
78
~NAPIDeathRecipient()79 NAPIDeathRecipient::~NAPIDeathRecipient()
80 {
81 if (env_ != nullptr) {
82 if (deathRecipientRef_ != nullptr) {
83 napi_status status = napi_delete_reference(env_, deathRecipientRef_);
84 NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js death recipient");
85 deathRecipientRef_ = nullptr;
86 }
87 }
88 }
89
OnRemoteDied(const wptr<IRemoteObject> & object)90 void NAPIDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
91 {
92 if (deathRecipientRef_ == nullptr) {
93 DBINDER_LOGE("js death recipient has already removed");
94 return;
95 }
96
97 uv_loop_s *loop = nullptr;
98 napi_get_uv_event_loop(env_, &loop);
99 uv_work_t *work = new(std::nothrow) uv_work_t;
100 if (work == nullptr) {
101 DBINDER_LOGE("failed to new uv_work_t");
102 return;
103 };
104 OnRemoteDiedParam *param = new OnRemoteDiedParam {
105 .env = env_,
106 .deathRecipientRef = deathRecipientRef_
107 };
108 work->data = reinterpret_cast<void *>(param);
109 DBINDER_LOGI("start to queue");
110 uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
111 DBINDER_LOGI("start to call onRmeoteDied");
112 OnRemoteDiedParam *param = reinterpret_cast<OnRemoteDiedParam *>(work->data);
113 napi_value jsDeathRecipient = nullptr;
114 napi_get_reference_value(param->env, param->deathRecipientRef, &jsDeathRecipient);
115 NAPI_ASSERT_RETURN_VOID(param->env, jsDeathRecipient != nullptr, "failed to get js death recipient");
116 napi_value onRemoteDied = nullptr;
117 napi_get_named_property(param->env, jsDeathRecipient, "onRemoteDied", &onRemoteDied);
118 NAPI_ASSERT_RETURN_VOID(param->env, onRemoteDied != nullptr, "failed to get property onRemoteDied");
119 napi_value return_val = nullptr;
120 napi_call_function(param->env, jsDeathRecipient, onRemoteDied, 0, nullptr, &return_val);
121 if (return_val == nullptr) {
122 DBINDER_LOGE("failed to call function onRemoteDied");
123 }
124 delete param;
125 delete work;
126 });
127 }
128
Matches(napi_value object)129 bool NAPIDeathRecipient::Matches(napi_value object)
130 {
131 bool result = false;
132 if (object != nullptr) {
133 if (deathRecipientRef_ != nullptr) {
134 napi_value jsDeathRecipient = nullptr;
135 napi_get_reference_value(env_, deathRecipientRef_, &jsDeathRecipient);
136 napi_status status = napi_strict_equals(env_, object, jsDeathRecipient, &result);
137 if (status != napi_ok) {
138 DBINDER_LOGI("compares death recipients failed");
139 }
140 }
141 }
142 return result;
143 }
144
145 /*
146 * List of native NAPIDeathRecipient
147 */
148 class NAPIDeathRecipientList : public RefBase {
149 public:
150 NAPIDeathRecipientList();
151
152 ~NAPIDeathRecipientList();
153
154 bool Add(const sptr<NAPIDeathRecipient> &recipient);
155
156 bool Remove(const sptr<NAPIDeathRecipient> &recipient);
157
158 sptr<NAPIDeathRecipient> Find(napi_value jsRecipient);
159 private:
160 std::mutex mutex_;
161 std::set<sptr<NAPIDeathRecipient>> set_;
162 };
163
NAPIDeathRecipientList()164 NAPIDeathRecipientList::NAPIDeathRecipientList() {}
165
~NAPIDeathRecipientList()166 NAPIDeathRecipientList::~NAPIDeathRecipientList()
167 {
168 std::lock_guard<std::mutex> lockGuard(mutex_);
169 set_.clear();
170 }
171
Add(const sptr<NAPIDeathRecipient> & recipient)172 bool NAPIDeathRecipientList::Add(const sptr<NAPIDeathRecipient> &recipient)
173 {
174 std::lock_guard<std::mutex> lockGuard(mutex_);
175 auto ret = set_.insert(recipient);
176 return ret.second;
177 }
178
Remove(const sptr<NAPIDeathRecipient> & recipient)179 bool NAPIDeathRecipientList::Remove(const sptr<NAPIDeathRecipient> &recipient)
180 {
181 std::lock_guard<std::mutex> lockGuard(mutex_);
182 return (set_.erase(recipient) > 0);
183 }
184
Find(napi_value jsRecipient)185 sptr<NAPIDeathRecipient> NAPIDeathRecipientList::Find(napi_value jsRecipient)
186 {
187 std::lock_guard<std::mutex> lockGuard(mutex_);
188 for (auto it = set_.begin(); it != set_.end(); it++) {
189 if ((*it)->Matches(jsRecipient)) {
190 return *it;
191 }
192 }
193 return nullptr;
194 }
195
196 class NAPIRemoteProxyHolder {
197 public:
198 NAPIRemoteProxyHolder();
199 ~NAPIRemoteProxyHolder();
200 sptr<NAPIDeathRecipientList> list_;
201 sptr<IRemoteObject> object_;
202 };
203
NAPIRemoteProxyHolder()204 NAPIRemoteProxyHolder::NAPIRemoteProxyHolder() : list_(nullptr), object_(nullptr) {}
205
~NAPIRemoteProxyHolder()206 NAPIRemoteProxyHolder::~NAPIRemoteProxyHolder()
207 {
208 list_ = nullptr;
209 object_ = nullptr;
210 }
211
RemoteProxy_JS_Constructor(napi_env env,napi_callback_info info)212 napi_value RemoteProxy_JS_Constructor(napi_env env, napi_callback_info info)
213 {
214 napi_value thisVar = nullptr;
215 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
216 // new napi proxy holder instance
217 auto proxyHolder = new NAPIRemoteProxyHolder();
218 // connect native object to js thisVar
219 napi_status status = napi_wrap(
220 env, thisVar, proxyHolder,
221 [](napi_env env, void *data, void *hint) {
222 DBINDER_LOGI("proxy holder destructed by js callback");
223 delete (reinterpret_cast<NAPIRemoteProxyHolder *>(data));
224 },
225 nullptr, nullptr);
226 NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteProxy and native holder failed");
227 return thisVar;
228 }
229
230 EXTERN_C_START
231 /*
232 * function for module exports
233 */
NAPIRemoteProxyExport(napi_env env,napi_value exports)234 napi_value NAPIRemoteProxyExport(napi_env env, napi_value exports)
235 {
236 const std::string className = "RemoteProxy";
237 napi_value pingTransaction = nullptr;
238 napi_create_int32(env, PING_TRANSACTION, &pingTransaction);
239 napi_value dumpTransaction = nullptr;
240 napi_create_int32(env, DUMP_TRANSACTION, &dumpTransaction);
241 napi_value interfaceTransaction = nullptr;
242 napi_create_int32(env, INTERFACE_TRANSACTION, &interfaceTransaction);
243 napi_value minTransactionId = nullptr;
244 napi_create_int32(env, MIN_TRANSACTION_ID, &minTransactionId);
245 napi_value maxTransactionId = nullptr;
246 napi_create_int32(env, MAX_TRANSACTION_ID, &maxTransactionId);
247 napi_property_descriptor properties[] = {
248 DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteProxy_queryLocalInterface),
249 DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteProxy_addDeathRecipient),
250 DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteProxy_removeDeathRecipient),
251 DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteProxy_getInterfaceDescriptor),
252 DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteProxy_sendRequest),
253 DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteProxy_isObjectDead),
254 DECLARE_NAPI_STATIC_PROPERTY("PING_TRANSACTION", pingTransaction),
255 DECLARE_NAPI_STATIC_PROPERTY("DUMP_TRANSACTION", dumpTransaction),
256 DECLARE_NAPI_STATIC_PROPERTY("INTERFACE_TRANSACTION", interfaceTransaction),
257 DECLARE_NAPI_STATIC_PROPERTY("MIN_TRANSACTION_ID", minTransactionId),
258 DECLARE_NAPI_STATIC_PROPERTY("MAX_TRANSACTION_ID", maxTransactionId),
259 };
260 napi_value constructor = nullptr;
261 napi_define_class(env, className.c_str(), className.length(), RemoteProxy_JS_Constructor, nullptr,
262 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
263 NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteProxy failed");
264 napi_status status = napi_set_named_property(env, exports, "RemoteProxy", constructor);
265 NAPI_ASSERT(env, status == napi_ok, "set property RemoteProxy to exports failed");
266 napi_value global = nullptr;
267 status = napi_get_global(env, &global);
268 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
269 status = napi_set_named_property(env, global, "IPCProxyConstructor_", constructor);
270 NAPI_ASSERT(env, status == napi_ok, "set proxy constructor failed");
271 return exports;
272 }
273 EXTERN_C_END
274
275 /*
276 * The native NAPIRemoteObject act as bridger between js and native.
277 * It received the request from client and pass it js Layer.
278 */
279 class NAPIRemoteObject : public IPCObjectStub {
280 public:
281 NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor);
282
283 ~NAPIRemoteObject() override;
284
285 bool CheckObjectLegality() const override;
286
287 int GetObjectType() const override;
288
289 int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
290
291 napi_ref GetJsObjectRef() const;
292 private:
293 napi_env env_ = nullptr;
294 napi_value thisVar_ = nullptr;
295 napi_ref thisVarRef_ = nullptr;
296 struct ThreadLockInfo {
297 std::mutex mutex;
298 std::condition_variable condition;
299 bool ready = false;
300 };
301 struct CallbackParam {
302 napi_env env;
303 napi_ref thisVarRef;
304 uint32_t code;
305 MessageParcel *data;
306 MessageParcel *reply;
307 MessageOption *option;
308 pid_t callingPid;
309 pid_t callingUid;
310 uint32_t callingTokenId;
311 std::string callingDeviceID;
312 std::string localDeviceID;
313 bool isLocalCalling;
314 int activeStatus;
315 ThreadLockInfo *lockInfo;
316 int result;
317 };
318 int OnJsRemoteRequest(CallbackParam *param);
319 };
320
321 /*
322 * To ensure a better consistency of the life time of
323 * js RemoteObject and native object, we designed
324 * a container to save the native object.
325 */
326 class NAPIRemoteObjectHolder : public RefBase {
327 public:
328 explicit NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor);
329 ~NAPIRemoteObjectHolder();
330 sptr<NAPIRemoteObject> Get(napi_value object);
331 void Set(sptr<NAPIRemoteObject> object);
332 void attachLocalInterface(napi_value localInterface, std::string &descriptor);
333 napi_value queryLocalInterface(std::string &descriptor);
334 private:
335 std::mutex mutex_;
336 napi_env env_ = nullptr;
337 std::u16string descriptor_;
338 sptr<NAPIRemoteObject> cachedObject_;
339 napi_ref localInterfaceRef_;
340 };
341
NAPIRemoteObjectHolder(napi_env env,const std::u16string & descriptor)342 NAPIRemoteObjectHolder::NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor)
343 : env_(env), descriptor_(descriptor), cachedObject_(nullptr), localInterfaceRef_(nullptr)
344 {}
345
~NAPIRemoteObjectHolder()346 NAPIRemoteObjectHolder::~NAPIRemoteObjectHolder()
347 {
348 // free the reference of object.
349 cachedObject_ = nullptr;
350 if (localInterfaceRef_ != nullptr) {
351 napi_delete_reference(env_, localInterfaceRef_);
352 }
353 }
354
Get(napi_value jsRemoteObject)355 sptr<NAPIRemoteObject> NAPIRemoteObjectHolder::Get(napi_value jsRemoteObject)
356 {
357 std::lock_guard<std::mutex> lockGuard(mutex_);
358 // grab an strong reference to the object,
359 // so it will not be freed util this reference released.
360 sptr<NAPIRemoteObject> remoteObject = nullptr;
361 if (cachedObject_ != nullptr) {
362 remoteObject = cachedObject_;
363 }
364
365 if (remoteObject == nullptr) {
366 remoteObject = new NAPIRemoteObject(env_, jsRemoteObject, descriptor_);
367 cachedObject_ = remoteObject;
368 }
369 return remoteObject;
370 }
371
Set(sptr<NAPIRemoteObject> object)372 void NAPIRemoteObjectHolder::Set(sptr<NAPIRemoteObject> object)
373 {
374 std::lock_guard<std::mutex> lockGuard(mutex_);
375 cachedObject_ = object;
376 }
377
attachLocalInterface(napi_value localInterface,std::string & descriptor)378 void NAPIRemoteObjectHolder::attachLocalInterface(napi_value localInterface, std::string &descriptor)
379 {
380 if (localInterfaceRef_ != nullptr) {
381 napi_delete_reference(env_, localInterfaceRef_);
382 }
383 napi_create_reference(env_, localInterface, 1, &localInterfaceRef_);
384 descriptor_ = Str8ToStr16(descriptor);
385 }
386
queryLocalInterface(std::string & descriptor)387 napi_value NAPIRemoteObjectHolder::queryLocalInterface(std::string &descriptor)
388 {
389 if (!descriptor_.empty() && strcmp(Str16ToStr8(descriptor_).c_str(), descriptor.c_str()) == 0) {
390 napi_value ret = nullptr;
391 napi_get_reference_value(env_, localInterfaceRef_, &ret);
392 return ret;
393 }
394 napi_value result = nullptr;
395 napi_get_null(env_, &result);
396 return result;
397 }
398
RemoteObject_JS_Constructor(napi_env env,napi_callback_info info)399 napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
400 {
401 // new napi remote object
402 size_t argc = 2;
403 size_t expectedArgc = 1;
404 napi_value argv[2] = { 0 };
405 napi_value thisVar = nullptr;
406 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
407 NAPI_ASSERT(env, argc >= expectedArgc, "requires at least 1 parameters");
408 napi_valuetype valueType = napi_null;
409 napi_typeof(env, argv[0], &valueType);
410 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
411 size_t bufferSize = 0;
412 size_t maxLen = 40960;
413 napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
414 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
415 char stringValue[bufferSize + 1];
416 size_t jsStringLength = 0;
417 napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
418 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
419 std::string descriptor = stringValue;
420 auto holder = new NAPIRemoteObjectHolder(env, Str8ToStr16(descriptor));
421 // connect native object to js thisVar
422 napi_status status = napi_wrap(
423 env, thisVar, holder,
424 [](napi_env env, void *data, void *hint) {
425 DBINDER_LOGI("NAPIRemoteObjectHolder destructed by js callback");
426 delete (reinterpret_cast<NAPIRemoteObjectHolder *>(data));
427 },
428 nullptr, nullptr);
429 NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed");
430 return thisVar;
431 }
432
433 EXTERN_C_START
434 /*
435 * function for module exports
436 */
NAPIRemoteObjectExport(napi_env env,napi_value exports)437 napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports)
438 {
439 const std::string className = "RemoteObject";
440 napi_property_descriptor properties[] = {
441 DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteObject_sendRequest),
442 DECLARE_NAPI_FUNCTION("getCallingPid", NAPI_RemoteObject_getCallingPid),
443 DECLARE_NAPI_FUNCTION("getCallingUid", NAPI_RemoteObject_getCallingUid),
444 DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteObject_getInterfaceDescriptor),
445 DECLARE_NAPI_FUNCTION("attachLocalInterface", NAPI_RemoteObject_attachLocalInterface),
446 DECLARE_NAPI_FUNCTION("queryLocalInterface", NAPI_RemoteObject_queryLocalInterface),
447 DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteObject_addDeathRecipient),
448 DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteObject_removeDeathRecipient),
449 DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteObject_isObjectDead),
450 };
451 napi_value constructor = nullptr;
452 napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
453 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
454 NAPI_ASSERT(env, constructor != nullptr, "define js class RemoteObject failed");
455 napi_status status = napi_set_named_property(env, exports, "RemoteObject", constructor);
456 NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
457 napi_value global = nullptr;
458 status = napi_get_global(env, &global);
459 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
460 status = napi_set_named_property(env, global, "IPCStubConstructor_", constructor);
461 NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
462 return exports;
463 }
464 EXTERN_C_END
465
NAPIRemoteObject(napi_env env,napi_value thisVar,const std::u16string & descriptor)466 NAPIRemoteObject::NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor)
467 : IPCObjectStub(descriptor)
468 {
469 env_ = env;
470 thisVar_ = thisVar;
471 napi_create_reference(env, thisVar_, 1, &thisVarRef_);
472 NAPI_ASSERT_RETURN_VOID(env, thisVarRef_ != nullptr, "failed to create ref to js RemoteObject");
473 }
474
~NAPIRemoteObject()475 NAPIRemoteObject::~NAPIRemoteObject()
476 {
477 DBINDER_LOGI("NAPIRemoteObject Destructor");
478 if (thisVarRef_ != nullptr) {
479 napi_status status = napi_delete_reference(env_, thisVarRef_);
480 NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js RemoteObject");
481 thisVarRef_ = nullptr;
482 }
483 }
484
CheckObjectLegality() const485 bool NAPIRemoteObject::CheckObjectLegality() const
486 {
487 return true;
488 }
489
GetObjectType() const490 int NAPIRemoteObject::GetObjectType() const
491 {
492 return OBJECT_TYPE_JAVASCRIPT;
493 }
494
GetJsObjectRef() const495 napi_ref NAPIRemoteObject::GetJsObjectRef() const
496 {
497 return thisVarRef_;
498 }
499
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)500 int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
501 {
502 DBINDER_LOGI("enter OnRemoteRequest");
503 if (code == DUMP_TRANSACTION) {
504 DBINDER_LOGE("DUMP_TRANSACTION data size:%zu", data.GetReadableBytes());
505 }
506 pid_t callingPid = IPCSkeleton::GetCallingPid();
507 pid_t callingUid = IPCSkeleton::GetCallingUid();
508 uint32_t callingTokenId = IPCSkeleton::GetCallingTokenID();
509 std::string callingDeviceID = IPCSkeleton::GetCallingDeviceID();
510 std::string localDeviceID = IPCSkeleton::GetLocalDeviceID();
511 bool isLocalCalling = IPCSkeleton::IsLocalCalling();
512 DBINDER_LOGI("callingPid:%{public}u, callingUid:%{public}u, callingDeviceID:%{public}s,\
513 localDeviceId:%{public}s, localCalling:%{public}d",
514 callingPid, callingUid, callingDeviceID.c_str(), localDeviceID.c_str(), isLocalCalling);
515 std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
516 CallbackParam *param = new CallbackParam {
517 .env = env_,
518 .thisVarRef = thisVarRef_,
519 .code = code,
520 .data = &data,
521 .reply = &reply,
522 .option = &option,
523 .callingPid = callingPid,
524 .callingUid = callingUid,
525 .callingTokenId = callingTokenId,
526 .callingDeviceID = callingDeviceID,
527 .localDeviceID = localDeviceID,
528 .isLocalCalling = isLocalCalling,
529 .activeStatus = IRemoteInvoker::ACTIVE_INVOKER,
530 .lockInfo = lockInfo.get(),
531 .result = 0
532 };
533 int ret = OnJsRemoteRequest(param);
534 DBINDER_LOGI("OnJsRemoteRequest done, ret:%{public}d", ret);
535 return ret;
536 }
537
OnJsRemoteRequest(CallbackParam * jsParam)538 int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
539 {
540 uv_loop_s *loop = nullptr;
541 napi_get_uv_event_loop(env_, &loop);
542
543 uv_work_t *work = new(std::nothrow) uv_work_t;
544 if (work == nullptr) {
545 DBINDER_LOGE("failed to new uv_work_t");
546 delete jsParam;
547 return -1;
548 }
549 work->data = reinterpret_cast<void *>(jsParam);
550 DBINDER_LOGI("start nv queue work loop");
551 uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
552 DBINDER_LOGI("enter thread pool");
553 CallbackParam *param = reinterpret_cast<CallbackParam *>(work->data);
554 napi_value onRemoteRequest = nullptr;
555 napi_value thisVar = nullptr;
556 napi_get_reference_value(param->env, param->thisVarRef, &thisVar);
557 if (thisVar == nullptr) {
558 DBINDER_LOGE("thisVar is null");
559 param->result = -1;
560 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
561 param->lockInfo->ready = true;
562 param->lockInfo->condition.notify_all();
563 return;
564 }
565 napi_get_named_property(param->env, thisVar, "onRemoteRequest", &onRemoteRequest);
566 if (onRemoteRequest == nullptr) {
567 DBINDER_LOGE("get founction onRemoteRequest failed");
568 param->result = -1;
569 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
570 param->lockInfo->ready = true;
571 param->lockInfo->condition.notify_all();
572 return;
573 }
574 napi_value jsCode;
575 napi_create_uint32(param->env, param->code, &jsCode);
576
577 napi_value global = nullptr;
578 napi_get_global(param->env, &global);
579 if (global == nullptr) {
580 DBINDER_LOGE("get napi global failed");
581 param->result = -1;
582 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
583 param->lockInfo->ready = true;
584 param->lockInfo->condition.notify_all();
585 return;
586 }
587 napi_value jsOptionConstructor = nullptr;
588 napi_get_named_property(param->env, global, "IPCOptionConstructor_", &jsOptionConstructor);
589 if (jsOptionConstructor == nullptr) {
590 DBINDER_LOGE("jsOption constructor is null");
591 param->result = -1;
592 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
593 param->lockInfo->ready = true;
594 param->lockInfo->condition.notify_all();
595 return;
596 }
597 napi_value jsOption;
598 size_t argc = 2;
599 napi_value flags = nullptr;
600 napi_create_int32(param->env, param->option->GetFlags(), &flags);
601 napi_value waittime = nullptr;
602 napi_create_int32(param->env, param->option->GetWaitTime(), &waittime);
603 napi_value argv[2] = { flags, waittime };
604 napi_new_instance(param->env, jsOptionConstructor, argc, argv, &jsOption);
605 if (jsOption == nullptr) {
606 DBINDER_LOGE("new jsOption failed");
607 param->result = -1;
608 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
609 param->lockInfo->ready = true;
610 param->lockInfo->condition.notify_all();
611 return;
612 }
613 napi_value jsParcelConstructor = nullptr;
614 napi_get_named_property(param->env, global, "IPCParcelConstructor_", &jsParcelConstructor);
615 if (jsParcelConstructor == nullptr) {
616 DBINDER_LOGE("jsParcel constructor is null");
617 param->result = -1;
618 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
619 param->lockInfo->ready = true;
620 param->lockInfo->condition.notify_all();
621 return;
622 }
623 napi_value jsData;
624 napi_value dataParcel;
625 napi_create_int64(param->env, reinterpret_cast<int64_t>(param->data), &dataParcel);
626 if (dataParcel == nullptr) {
627 DBINDER_LOGE("create js object for data parcel address failed");
628 param->result = -1;
629 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
630 param->lockInfo->ready = true;
631 param->lockInfo->condition.notify_all();
632 return;
633 }
634 size_t argc3 = 1;
635 napi_value argv3[1] = { dataParcel };
636 napi_new_instance(param->env, jsParcelConstructor, argc3, argv3, &jsData);
637 if (jsData == nullptr) {
638 DBINDER_LOGE("create js data parcel failed");
639 param->result = -1;
640 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
641 param->lockInfo->ready = true;
642 param->lockInfo->condition.notify_all();
643 return;
644 }
645 napi_value jsReply;
646 napi_value replyParcel;
647 napi_create_int64(param->env, reinterpret_cast<int64_t>(param->reply), &replyParcel);
648 if (replyParcel == nullptr) {
649 DBINDER_LOGE("create js object for reply parcel address failed");
650 param->result = -1;
651 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
652 param->lockInfo->ready = true;
653 param->lockInfo->condition.notify_all();
654 return;
655 }
656 size_t argc4 = 1;
657 napi_value argv4[1] = { replyParcel };
658 napi_new_instance(param->env, jsParcelConstructor, argc4, argv4, &jsReply);
659 if (jsReply == nullptr) {
660 DBINDER_LOGE("create js reply parcel failed");
661 param->result = -1;
662 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
663 param->lockInfo->ready = true;
664 param->lockInfo->condition.notify_all();
665 return;
666 }
667 // save old calling pid, uid, device id
668 napi_get_global(param->env, &global);
669 napi_value oldPid;
670 napi_get_named_property(param->env, global, "callingPid_", &oldPid);
671 napi_value oldUid;
672 napi_get_named_property(param->env, global, "callingUid_", &oldUid);
673 napi_value oldCallingTokenId;
674 napi_get_named_property(param->env, global, "callingTokenId_", &oldCallingTokenId);
675 napi_value oldCallingDeviceID;
676 napi_get_named_property(param->env, global, "callingDeviceID_", &oldCallingDeviceID);
677 napi_value oldLocalDeviceID;
678 napi_get_named_property(param->env, global, "localDeviceID_", &oldLocalDeviceID);
679 napi_value oldIsLocalCalling;
680 napi_get_named_property(param->env, global, "isLocalCalling_", &oldIsLocalCalling);
681 napi_value oldActiveStatus;
682 napi_get_named_property(param->env, global, "activeStatus_", &oldActiveStatus);
683
684 // set new calling pid, uid, device id
685 napi_value newPid;
686 napi_create_int32(param->env, static_cast<int32_t>(param->callingPid), &newPid);
687 napi_set_named_property(param->env, global, "callingPid_", newPid);
688 napi_value newUid;
689 napi_create_int32(param->env, static_cast<int32_t>(param->callingUid), &newUid);
690 napi_set_named_property(param->env, global, "callingUid_", newUid);
691 napi_value newCallingTokenId;
692 napi_create_uint32(param->env, param->callingTokenId, &newCallingTokenId);
693 napi_set_named_property(param->env, global, "callingTokenId_", newCallingTokenId);
694 napi_value newDeviceID;
695 napi_create_string_utf8(param->env, param->callingDeviceID.c_str(), NAPI_AUTO_LENGTH, &newDeviceID);
696 napi_set_named_property(param->env, global, "callingDeviceID_", newDeviceID);
697 napi_value newLocalDeviceID;
698 napi_create_string_utf8(param->env, param->localDeviceID.c_str(), NAPI_AUTO_LENGTH, &newLocalDeviceID);
699 napi_set_named_property(param->env, global, "localDeviceID_", newLocalDeviceID);
700 napi_value newIsLocalCalling;
701 napi_get_boolean(param->env, param->isLocalCalling, &newIsLocalCalling);
702 napi_set_named_property(param->env, global, "isLocalCalling_", newIsLocalCalling);
703 napi_value newActiveStatus;
704 napi_create_int32(param->env, param->activeStatus, &newActiveStatus);
705 napi_set_named_property(param->env, global, "activeStatus_", newActiveStatus);
706
707 // start to call onRemoteRequest
708 size_t argc2 = 4;
709 napi_value argv2[] = { jsCode, jsData, jsReply, jsOption };
710 napi_value return_val;
711 napi_status ret = napi_call_function(param->env, thisVar, onRemoteRequest, argc2, argv2, &return_val);
712 DBINDER_LOGI("call js onRemoteRequest done");
713 if (ret != napi_ok) {
714 DBINDER_LOGE("OnRemoteRequest got exception");
715 param->result = ERR_UNKNOWN_TRANSACTION;
716 } else {
717 bool result = false;
718 napi_get_value_bool(param->env, return_val, &result);
719 if (!result) {
720 DBINDER_LOGE("OnRemoteRequest res:%{public}s", result ? "true" : "false");
721 param->result = ERR_UNKNOWN_TRANSACTION;
722 } else {
723 param->result = ERR_NONE;
724 }
725 }
726
727 napi_set_named_property(param->env, global, "callingPid_", oldPid);
728 napi_set_named_property(param->env, global, "callingUid_", oldUid);
729 napi_set_named_property(param->env, global, "callingTokenId_", oldCallingTokenId);
730 napi_set_named_property(param->env, global, "callingDeviceID_", oldCallingDeviceID);
731 napi_set_named_property(param->env, global, "localDeviceID_", oldLocalDeviceID);
732 napi_set_named_property(param->env, global, "isLocalCalling_", oldIsLocalCalling);
733 napi_set_named_property(param->env, global, "activeStatus_", oldActiveStatus);
734 std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
735 param->lockInfo->ready = true;
736 param->lockInfo->condition.notify_all();
737 });
738 std::unique_lock<std::mutex> lock(jsParam->lockInfo->mutex);
739 jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
740 int ret = jsParam->result;
741 delete jsParam;
742 delete work;
743 return ret;
744 }
745
NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env,napi_value jsRemoteProxy)746 NAPIRemoteProxyHolder *NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env, napi_value jsRemoteProxy)
747 {
748 NAPIRemoteProxyHolder *proxyHolder = nullptr;
749 napi_unwrap(env, jsRemoteProxy, (void **)&proxyHolder);
750 NAPI_ASSERT(env, proxyHolder != nullptr, "failed to get napi remote proxy holder");
751 return proxyHolder;
752 }
753
NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env,const sptr<IRemoteObject> target)754 napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteObject> target)
755 {
756 if (target == nullptr) {
757 DBINDER_LOGE("RemoteObject is null");
758 return nullptr;
759 }
760
761 if (target->CheckObjectLegality()) {
762 IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
763 DBINDER_LOGI("object type:%{public}d", tmp->GetObjectType());
764 if (tmp->GetObjectType() == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT) {
765 DBINDER_LOGI("napi create js remote object");
766 sptr<NAPIRemoteObject> object = static_cast<NAPIRemoteObject *>(target.GetRefPtr());
767 // retrieve js remote object constructor
768 napi_value global = nullptr;
769 napi_status status = napi_get_global(env, &global);
770 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
771 napi_value constructor = nullptr;
772 status = napi_get_named_property(env, global, "IPCStubConstructor_", &constructor);
773 NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
774 NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
775 // retrieve descriptor and it's length
776 std::u16string descriptor = object->GetObjectDescriptor();
777 std::string desc = Str16ToStr8(descriptor);
778 napi_value jsDesc = nullptr;
779 napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
780 // create a new js remote object
781 size_t argc = 1;
782 napi_value argv[1] = { jsDesc };
783 napi_value jsRemoteObject = nullptr;
784 status = napi_new_instance(env, constructor, argc, argv, &jsRemoteObject);
785 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteObject");
786 // retrieve holder and set object
787 NAPIRemoteObjectHolder *holder = nullptr;
788 napi_unwrap(env, jsRemoteObject, (void **)&holder);
789 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
790 holder->Set(object);
791 return jsRemoteObject;
792 }
793 }
794
795 napi_value global = nullptr;
796 napi_status status = napi_get_global(env, &global);
797 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
798 napi_value constructor = nullptr;
799 status = napi_get_named_property(env, global, "IPCProxyConstructor_", &constructor);
800 NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
801 napi_value jsRemoteProxy;
802 status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
803 NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteProxy");
804 NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
805 proxyHolder->object_ = target;
806 proxyHolder->list_ = new NAPIDeathRecipientList();
807
808 return jsRemoteProxy;
809 }
810
NAPI_ohos_rpc_getNativeRemoteObject(napi_env env,napi_value object)811 sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
812 {
813 if (object != nullptr) {
814 napi_value global = nullptr;
815 napi_status status = napi_get_global(env, &global);
816 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
817 napi_value stubConstructor = nullptr;
818 status = napi_get_named_property(env, global, "IPCStubConstructor_", &stubConstructor);
819 NAPI_ASSERT(env, status == napi_ok, "get stub constructor failed");
820 bool instanceOfStub = false;
821 status = napi_instanceof(env, object, stubConstructor, &instanceOfStub);
822 NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
823 if (instanceOfStub) {
824 NAPIRemoteObjectHolder *holder = nullptr;
825 napi_unwrap(env, object, (void **)&holder);
826 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
827 return holder != nullptr ? holder->Get(object) : nullptr;
828 }
829
830 napi_value proxyConstructor = nullptr;
831 status = napi_get_named_property(env, global, "IPCProxyConstructor_", &proxyConstructor);
832 NAPI_ASSERT(env, status == napi_ok, "get proxy constructor failed");
833 bool instanceOfProxy = false;
834 status = napi_instanceof(env, object, proxyConstructor, &instanceOfProxy);
835 NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
836 if (instanceOfProxy) {
837 NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
838 return holder != nullptr ? holder->object_ : nullptr;
839 }
840 }
841 return nullptr;
842 }
843
NAPI_IPCSkeleton_getContextObject(napi_env env,napi_callback_info info)844 napi_value NAPI_IPCSkeleton_getContextObject(napi_env env, napi_callback_info info)
845 {
846 sptr<IRemoteObject> object = IPCSkeleton::GetContextObject();
847 if (object == nullptr) {
848 DBINDER_LOGE("fatal error, could not get registry object");
849 return nullptr;
850 }
851 return NAPI_ohos_rpc_CreateJsRemoteObject(env, object);
852 }
853
NAPI_IPCSkeleton_getCallingPid(napi_env env,napi_callback_info info)854 napi_value NAPI_IPCSkeleton_getCallingPid(napi_env env, napi_callback_info info)
855 {
856 napi_value global = nullptr;
857 napi_get_global(env, &global);
858 napi_value napiActiveStatus = nullptr;
859 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
860 if (napiActiveStatus != nullptr) {
861 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
862 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
863 if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
864 napi_value callingPid = nullptr;
865 napi_get_named_property(env, global, "callingPid_", &callingPid);
866 return callingPid;
867 }
868 }
869 pid_t pid = getpid();
870 napi_value result = nullptr;
871 napi_create_int32(env, static_cast<int32_t>(pid), &result);
872 return result;
873 }
874
NAPI_IPCSkeleton_getCallingUid(napi_env env,napi_callback_info info)875 napi_value NAPI_IPCSkeleton_getCallingUid(napi_env env, napi_callback_info info)
876 {
877 napi_value global = nullptr;
878 napi_get_global(env, &global);
879 napi_value napiActiveStatus = nullptr;
880 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
881 if (napiActiveStatus != nullptr) {
882 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
883 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
884 if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
885 napi_value callingUid = nullptr;
886 napi_get_named_property(env, global, "callingUid_", &callingUid);
887 return callingUid;
888 }
889 }
890 uint32_t uid = getuid();
891 napi_value result = nullptr;
892 napi_create_int32(env, static_cast<int32_t>(uid), &result);
893 return result;
894 }
895
NAPI_IPCSkeleton_getCallingTokenId(napi_env env,napi_callback_info info)896 napi_value NAPI_IPCSkeleton_getCallingTokenId(napi_env env, napi_callback_info info)
897 {
898 napi_value global = nullptr;
899 napi_get_global(env, &global);
900 napi_value napiActiveStatus = nullptr;
901 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
902 if (napiActiveStatus != nullptr) {
903 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
904 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
905 if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
906 napi_value callingTokenId = nullptr;
907 napi_get_named_property(env, global, "callingTokenId_", &callingTokenId);
908 return callingTokenId;
909 }
910 }
911 uint64_t TokenId = RpcGetSelfTokenID();
912 napi_value result = nullptr;
913 napi_create_uint32(env, static_cast<uint32_t>(TokenId), &result);
914 return result;
915 }
916
NAPI_IPCSkeleton_getCallingDeviceID(napi_env env,napi_callback_info info)917 napi_value NAPI_IPCSkeleton_getCallingDeviceID(napi_env env, napi_callback_info info)
918 {
919 napi_value global = nullptr;
920 napi_get_global(env, &global);
921 napi_value napiActiveStatus = nullptr;
922 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
923 if (napiActiveStatus != nullptr) {
924 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
925 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
926 if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
927 napi_value callingDeviceID = nullptr;
928 napi_get_named_property(env, global, "callingDeviceID_", &callingDeviceID);
929 return callingDeviceID;
930 }
931 }
932 napi_value result = nullptr;
933 napi_create_string_utf8(env, "", 0, &result);
934 return result;
935 }
936
NAPI_IPCSkeleton_getLocalDeviceID(napi_env env,napi_callback_info info)937 napi_value NAPI_IPCSkeleton_getLocalDeviceID(napi_env env, napi_callback_info info)
938 {
939 napi_value global = nullptr;
940 napi_get_global(env, &global);
941 napi_value napiActiveStatus = nullptr;
942 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
943 if (napiActiveStatus != nullptr) {
944 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
945 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
946 if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
947 napi_value localDeviceID = nullptr;
948 napi_get_named_property(env, global, "localDeviceID_", &localDeviceID);
949 return localDeviceID;
950 }
951 }
952 napi_value result = nullptr;
953 napi_create_string_utf8(env, "", 0, &result);
954 return result;
955 }
956
NAPI_IPCSkeleton_isLocalCalling(napi_env env,napi_callback_info info)957 napi_value NAPI_IPCSkeleton_isLocalCalling(napi_env env, napi_callback_info info)
958 {
959 napi_value global = nullptr;
960 napi_get_global(env, &global);
961 napi_value napiActiveStatus = nullptr;
962 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
963 if (napiActiveStatus != nullptr) {
964 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
965 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
966 if (activeStatus == IRemoteInvoker::ACTIVE_INVOKER) {
967 napi_value isLocalCalling = nullptr;
968 napi_get_named_property(env, global, "isLocalCalling_", &isLocalCalling);
969 return isLocalCalling;
970 }
971 }
972 napi_value result = nullptr;
973 napi_get_boolean(env, true, &result);
974 return result;
975 }
976
NAPI_IPCSkeleton_flushCommands(napi_env env,napi_callback_info info)977 napi_value NAPI_IPCSkeleton_flushCommands(napi_env env, napi_callback_info info)
978 {
979 size_t argc = 1;
980 napi_value argv[1] = {0};
981 napi_value thisVar = nullptr;
982 void *data = nullptr;
983 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
984 NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
985
986 napi_valuetype valueType = napi_null;
987 napi_typeof(env, argv[0], &valueType);
988 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
989
990 sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
991 int32_t result = IPCSkeleton::FlushCommands(target);
992 napi_value napiValue = nullptr;
993 NAPI_CALL(env, napi_create_int32(env, result, &napiValue));
994 return napiValue;
995 }
996
NAPI_IPCSkeleton_resetCallingIdentity(napi_env env,napi_callback_info info)997 napi_value NAPI_IPCSkeleton_resetCallingIdentity(napi_env env, napi_callback_info info)
998 {
999 napi_value global = nullptr;
1000 napi_get_global(env, &global);
1001 napi_value napiActiveStatus = nullptr;
1002 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1003 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1004 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1005 if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1006 napi_value result = nullptr;
1007 napi_create_string_utf8(env, "", 0, &result);
1008 return result;
1009 }
1010 napi_value napiCallingPid = nullptr;
1011 napi_get_named_property(env, global, "callingPid_", &napiCallingPid);
1012 int32_t callerPid;
1013 napi_get_value_int32(env, napiCallingPid, &callerPid);
1014 napi_value napiCallingUid = nullptr;
1015 napi_get_named_property(env, global, "callingUid_", &napiCallingUid);
1016 uint32_t callerUid;
1017 napi_get_value_uint32(env, napiCallingUid, &callerUid);
1018 napi_value napiIsLocalCalling = nullptr;
1019 napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1020 bool isLocalCalling = true;
1021 napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1022 if (isLocalCalling) {
1023 int64_t identity = (static_cast<uint64_t>(callerUid) << PID_LEN) | static_cast<uint64_t>(callerPid);
1024 callerPid = getpid();
1025 callerUid = getuid();
1026 napi_value newCallingPid;
1027 napi_create_int32(env, callerPid, &newCallingPid);
1028 napi_set_named_property(env, global, "callingPid_", newCallingPid);
1029 napi_value newCallingUid;
1030 napi_create_uint32(env, callerUid, &newCallingUid);
1031 napi_set_named_property(env, global, "callingUid_", newCallingUid);
1032 napi_value result = nullptr;
1033 napi_create_string_utf8(env, std::to_string(identity).c_str(), NAPI_AUTO_LENGTH, &result);
1034 return result;
1035 } else {
1036 napi_value napiCallingDeviceID = nullptr;
1037 napi_get_named_property(env, global, "callingDeviceID_", &napiCallingDeviceID);
1038 size_t bufferSize = 0;
1039 size_t maxLen = 4096;
1040 napi_get_value_string_utf8(env, napiCallingDeviceID, nullptr, 0, &bufferSize);
1041 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1042 char stringValue[bufferSize + 1];
1043 size_t jsStringLength = 0;
1044 napi_get_value_string_utf8(env, napiCallingDeviceID, stringValue, bufferSize + 1, &jsStringLength);
1045 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1046 std::string callerDeviceID = stringValue;
1047 std::string token = std::to_string(((static_cast<uint64_t>(callerUid) << PID_LEN)
1048 | static_cast<uint64_t>(callerPid)));
1049 std::string identity = callerDeviceID + token;
1050 callerUid = getuid();
1051 napi_value newCallingUid;
1052 napi_create_uint32(env, callerUid, &newCallingUid);
1053 napi_set_named_property(env, global, "callingUid_", newCallingUid);
1054 callerPid = getpid();
1055 napi_value newCallingPid;
1056 napi_create_int32(env, callerPid, &newCallingPid);
1057 napi_set_named_property(env, global, "callingPid_", newCallingPid);
1058 napi_value newCallingDeviceID = nullptr;
1059 napi_get_named_property(env, global, "localDeviceID_", &newCallingDeviceID);
1060 napi_set_named_property(env, global, "callingDeviceID_", newCallingDeviceID);
1061
1062 napi_value result = nullptr;
1063 napi_create_string_utf8(env, identity.c_str(), NAPI_AUTO_LENGTH, &result);
1064 return result;
1065 }
1066 }
1067
NAPI_IPCSkeleton_setCallingIdentity(napi_env env,napi_callback_info info)1068 napi_value NAPI_IPCSkeleton_setCallingIdentity(napi_env env, napi_callback_info info)
1069 {
1070 napi_value global = nullptr;
1071 napi_get_global(env, &global);
1072 napi_value napiActiveStatus = nullptr;
1073 napi_get_named_property(env, global, "activeStatus_", &napiActiveStatus);
1074 int32_t activeStatus = IRemoteInvoker::IDLE_INVOKER;
1075 napi_get_value_int32(env, napiActiveStatus, &activeStatus);
1076 if (activeStatus != IRemoteInvoker::ACTIVE_INVOKER) {
1077 napi_value result = nullptr;
1078 napi_get_boolean(env, true, &result);
1079 return result;
1080 }
1081
1082 napi_value retValue = nullptr;
1083 napi_get_boolean(env, false, &retValue);
1084
1085 size_t argc = 1;
1086 size_t expectedArgc = 1;
1087 napi_value argv[1] = { 0 };
1088 napi_value thisVar = nullptr;
1089 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1090 NAPI_ASSERT_BASE(env, argc == expectedArgc, "requires 1 parameters", retValue);
1091 napi_valuetype valueType = napi_null;
1092 napi_typeof(env, argv[0], &valueType);
1093 NAPI_ASSERT_BASE(env, valueType == napi_string, "type mismatch for parameter 1", retValue);
1094 size_t bufferSize = 0;
1095 size_t maxLen = 40960;
1096 napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1097 NAPI_ASSERT_BASE(env, bufferSize < maxLen, "string length too large", retValue);
1098 char stringValue[bufferSize + 1];
1099 size_t jsStringLength = 0;
1100 napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1101 NAPI_ASSERT_BASE(env, jsStringLength == bufferSize, "string length wrong", retValue);
1102
1103 std::string identity = stringValue;
1104 napi_value napiIsLocalCalling = nullptr;
1105 napi_get_named_property(env, global, "isLocalCalling_", &napiIsLocalCalling);
1106 bool isLocalCalling = true;
1107 napi_get_value_bool(env, napiIsLocalCalling, &isLocalCalling);
1108 napi_value result;
1109 if (isLocalCalling) {
1110 if (identity.empty()) {
1111 napi_get_boolean(env, false, &result);
1112 return result;
1113 }
1114
1115 int64_t token = std::atoll(identity.c_str());
1116 int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1117 int callerPid = static_cast<int>(token);
1118 napi_value napiCallingPid;
1119 napi_create_int32(env, callerPid, &napiCallingPid);
1120 napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1121 napi_value napiCallingUid;
1122 napi_create_int32(env, callerUid, &napiCallingUid);
1123 napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1124 napi_get_boolean(env, true, &result);
1125 return result;
1126 } else {
1127 if (identity.empty() || identity.length() <= DEVICEID_LENGTH) {
1128 napi_get_boolean(env, false, &result);
1129 return result;
1130 }
1131
1132 std::string deviceId = identity.substr(0, DEVICEID_LENGTH);
1133 int64_t token = std::atoll(identity.substr(DEVICEID_LENGTH, identity.length() - DEVICEID_LENGTH).c_str());
1134 int callerUid = static_cast<int>((static_cast<uint64_t>(token)) >> PID_LEN);
1135 int callerPid = static_cast<int>(token);
1136 napi_value napiCallingPid;
1137 napi_create_int32(env, callerPid, &napiCallingPid);
1138 napi_set_named_property(env, global, "callingPid_", napiCallingPid);
1139 napi_value napiCallingUid;
1140 napi_create_int32(env, callerUid, &napiCallingUid);
1141 napi_set_named_property(env, global, "callingUid_", napiCallingUid);
1142 napi_value napiCallingDeviceID = nullptr;
1143 napi_create_string_utf8(env, deviceId.c_str(), NAPI_AUTO_LENGTH, &napiCallingDeviceID);
1144 napi_set_named_property(env, global, "callingDeviceID_", napiCallingDeviceID);
1145 napi_get_boolean(env, true, &result);
1146 return result;
1147 }
1148 }
1149
NAPI_RemoteObject_queryLocalInterface(napi_env env,napi_callback_info info)1150 napi_value NAPI_RemoteObject_queryLocalInterface(napi_env env, napi_callback_info info)
1151 {
1152 size_t argc = 1;
1153 size_t expectedArgc = 1;
1154 napi_value argv[1] = { 0 };
1155 napi_value thisVar = nullptr;
1156 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1157 NAPI_ASSERT(env, argc == expectedArgc, "requires 1 parameters");
1158 napi_valuetype valueType = napi_null;
1159 napi_typeof(env, argv[0], &valueType);
1160 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
1161 size_t bufferSize = 0;
1162 size_t maxLen = 40960;
1163 napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
1164 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1165 char stringValue[bufferSize + 1];
1166 size_t jsStringLength = 0;
1167 napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
1168 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1169 std::string descriptor = stringValue;
1170 NAPIRemoteObjectHolder *holder = nullptr;
1171 napi_unwrap(env, thisVar, (void **)&holder);
1172 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1173 napi_value ret = holder->queryLocalInterface(descriptor);
1174 return ret;
1175 }
1176
NAPI_RemoteObject_getInterfaceDescriptor(napi_env env,napi_callback_info info)1177 napi_value NAPI_RemoteObject_getInterfaceDescriptor(napi_env env, napi_callback_info info)
1178 {
1179 napi_value result = nullptr;
1180 napi_value thisVar = nullptr;
1181 napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
1182 sptr<IRemoteObject> nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1183 std::u16string descriptor = nativeObject->GetObjectDescriptor();
1184 napi_create_string_utf8(env, Str16ToStr8(descriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1185 return result;
1186 }
1187
NAPI_RemoteObject_getCallingPid(napi_env env,napi_callback_info info)1188 napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
1189 {
1190 return NAPI_IPCSkeleton_getCallingPid(env, info);
1191 }
1192
NAPI_RemoteObject_getCallingUid(napi_env env,napi_callback_info info)1193 napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
1194 {
1195 return NAPI_IPCSkeleton_getCallingUid(env, info);
1196 }
1197
MakeSendRequestResult(SendRequestParam * param)1198 napi_value MakeSendRequestResult(SendRequestParam *param)
1199 {
1200 napi_value errCode = nullptr;
1201 napi_create_int32(param->env, param->errCode, &errCode);
1202 napi_value code = nullptr;
1203 napi_get_reference_value(param->env, param->jsCodeRef, &code);
1204 napi_value data = nullptr;
1205 napi_get_reference_value(param->env, param->jsDataRef, &data);
1206 napi_value reply = nullptr;
1207 napi_get_reference_value(param->env, param->jsReplyRef, &reply);
1208 napi_value result = nullptr;
1209 napi_create_object(param->env, &result);
1210 napi_set_named_property(param->env, result, "errCode", errCode);
1211 napi_set_named_property(param->env, result, "code", code);
1212 napi_set_named_property(param->env, result, "data", data);
1213 napi_set_named_property(param->env, result, "reply", reply);
1214 return result;
1215 }
1216
StubExecuteSendRequest(napi_env env,SendRequestParam * param)1217 void StubExecuteSendRequest(napi_env env, SendRequestParam *param)
1218 {
1219 param->errCode = param->target->SendRequest(param->code,
1220 *(param->data.get()), *(param->reply.get()), param->option);
1221 DBINDER_LOGI("sendRequest done, errCode:%{public}d", param->errCode);
1222 uv_loop_s *loop = nullptr;
1223 napi_get_uv_event_loop(env, &loop);
1224 uv_work_t *work = new uv_work_t;
1225 work->data = reinterpret_cast<void *>(param);
1226 uv_after_work_cb afterWorkCb = nullptr;
1227 if (param->callback != nullptr) {
1228 afterWorkCb = [](uv_work_t *work, int status) {
1229 DBINDER_LOGI("callback started");
1230 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1231 napi_value result = MakeSendRequestResult(param);
1232 napi_value callback = nullptr;
1233 napi_get_reference_value(param->env, param->callback, &callback);
1234 napi_value cbResult = nullptr;
1235 napi_call_function(param->env, nullptr, callback, 1, &result, &cbResult);
1236 napi_delete_reference(param->env, param->jsCodeRef);
1237 napi_delete_reference(param->env, param->jsDataRef);
1238 napi_delete_reference(param->env, param->jsReplyRef);
1239 napi_delete_reference(param->env, param->callback);
1240 delete param;
1241 delete work;
1242 };
1243 } else {
1244 afterWorkCb = [](uv_work_t *work, int status) {
1245 DBINDER_LOGI("promise fullfilled");
1246 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(work->data);
1247 napi_value result = MakeSendRequestResult(param);
1248 if (param->errCode == 0) {
1249 napi_resolve_deferred(param->env, param->deferred, result);
1250 } else {
1251 napi_reject_deferred(param->env, param->deferred, result);
1252 }
1253 napi_delete_reference(param->env, param->jsCodeRef);
1254 napi_delete_reference(param->env, param->jsDataRef);
1255 napi_delete_reference(param->env, param->jsReplyRef);
1256 delete param;
1257 delete work;
1258 };
1259 }
1260 uv_queue_work(loop, work, [](uv_work_t *work) {}, afterWorkCb);
1261 }
1262
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)1263 napi_value StubSendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1264 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1265 MessageOption &option, napi_value *argv)
1266 {
1267 SendRequestParam *sendRequestParam = new SendRequestParam {
1268 .target = target,
1269 .code = code,
1270 .data = data,
1271 .reply = reply,
1272 .option = option,
1273 .asyncWork = nullptr,
1274 .deferred = nullptr,
1275 .errCode = -1,
1276 .jsCodeRef = nullptr,
1277 .jsDataRef = nullptr,
1278 .jsReplyRef = nullptr,
1279 .callback = nullptr,
1280 .env = env,
1281 };
1282 napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1283 napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1284 napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1285 napi_create_reference(env, argv[4], 1, &sendRequestParam->callback);
1286 std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1287 t.detach();
1288 napi_value result = nullptr;
1289 napi_get_undefined(env, &result);
1290 return result;
1291 }
1292
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)1293 napi_value StubSendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1294 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1295 MessageOption &option, napi_value *argv)
1296 {
1297 napi_deferred deferred = nullptr;
1298 napi_value promise = nullptr;
1299 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1300 SendRequestParam *sendRequestParam = new SendRequestParam {
1301 .target = target,
1302 .code = code,
1303 .data = data,
1304 .reply = reply,
1305 .option = option,
1306 .asyncWork = nullptr,
1307 .deferred = deferred,
1308 .errCode = -1,
1309 .jsCodeRef = nullptr,
1310 .jsDataRef = nullptr,
1311 .jsReplyRef = nullptr,
1312 .callback = nullptr,
1313 .env = env,
1314 };
1315 napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1316 napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1317 napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1318 std::thread t(StubExecuteSendRequest, env, sendRequestParam);
1319 t.detach();
1320 return promise;
1321 }
1322
NAPI_RemoteObject_sendRequest(napi_env env,napi_callback_info info)1323 napi_value NAPI_RemoteObject_sendRequest(napi_env env, napi_callback_info info)
1324 {
1325 size_t argc = 4;
1326 size_t argcCallback = 5;
1327 size_t argcPromise = 4;
1328 napi_value argv[5] = { 0 };
1329 napi_value thisVar = nullptr;
1330 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1331 NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1332 napi_valuetype valueType = napi_null;
1333 napi_typeof(env, argv[0], &valueType);
1334 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1335 napi_typeof(env, argv[1], &valueType);
1336 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1337 napi_typeof(env, argv[2], &valueType);
1338 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1339 napi_typeof(env, argv[3], &valueType);
1340 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1341
1342 NAPI_MessageParcel *data = nullptr;
1343 napi_status status = napi_unwrap(env, argv[1], (void **)&data);
1344 NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1345 NAPI_MessageParcel *reply = nullptr;
1346 status = napi_unwrap(env, argv[2], (void **)&reply);
1347 NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1348 MessageOption *option = nullptr;
1349 status = napi_unwrap(env, argv[3], (void **)&option);
1350 NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1351 int32_t code = 0;
1352 napi_get_value_int32(env, argv[0], &code);
1353
1354 sptr<IRemoteObject> target = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
1355 if (argc == argcCallback) {
1356 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1357 napi_valuetype valuetype = napi_undefined;
1358 napi_typeof(env, argv[argcPromise], &valuetype);
1359 if (valuetype == napi_function) {
1360 return StubSendRequestAsync(env, target, code, data->GetMessageParcel(),
1361 reply->GetMessageParcel(), *option, argv);
1362 }
1363 }
1364 return StubSendRequestPromise(env, target, code, data->GetMessageParcel(),
1365 reply->GetMessageParcel(), *option, argv);
1366 }
1367
NAPI_RemoteObject_attachLocalInterface(napi_env env,napi_callback_info info)1368 napi_value NAPI_RemoteObject_attachLocalInterface(napi_env env, napi_callback_info info)
1369 {
1370 size_t argc = 2;
1371 size_t expectedArgc = 2;
1372 napi_value argv[2] = { 0 };
1373 napi_value thisVar = nullptr;
1374 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1375 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameters");
1376 napi_valuetype valueType = napi_null;
1377 napi_typeof(env, argv[0], &valueType);
1378 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1379 napi_typeof(env, argv[1], &valueType);
1380 NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 2");
1381 size_t bufferSize = 0;
1382 size_t maxLen = 40960;
1383 napi_get_value_string_utf8(env, argv[1], nullptr, 0, &bufferSize);
1384 NAPI_ASSERT(env, bufferSize < maxLen, "string length too large");
1385 char stringValue[bufferSize + 1];
1386 size_t jsStringLength = 0;
1387 napi_get_value_string_utf8(env, argv[1], stringValue, bufferSize + 1, &jsStringLength);
1388 NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
1389 std::string descriptor = stringValue;
1390
1391 NAPIRemoteObjectHolder *holder = nullptr;
1392 napi_unwrap(env, thisVar, (void* *)&holder);
1393 NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
1394 holder->attachLocalInterface(argv[0], descriptor);
1395
1396 napi_value result = nullptr;
1397 napi_get_undefined(env, &result);
1398 return result;
1399 }
1400
NAPI_RemoteObject_addDeathRecipient(napi_env env,napi_callback_info info)1401 napi_value NAPI_RemoteObject_addDeathRecipient(napi_env env, napi_callback_info info)
1402 {
1403 napi_value result = nullptr;
1404 napi_get_boolean(env, false, &result);
1405 return result;
1406 }
1407
NAPI_RemoteObject_removeDeathRecipient(napi_env env,napi_callback_info info)1408 napi_value NAPI_RemoteObject_removeDeathRecipient(napi_env env, napi_callback_info info)
1409 {
1410 napi_value result = nullptr;
1411 napi_get_boolean(env, false, &result);
1412 return result;
1413 }
1414
NAPI_RemoteObject_isObjectDead(napi_env env,napi_callback_info info)1415 napi_value NAPI_RemoteObject_isObjectDead(napi_env env, napi_callback_info info)
1416 {
1417 napi_value result = nullptr;
1418 napi_get_boolean(env, false, &result);
1419 return result;
1420 }
1421
1422 // This method runs on a worker thread, no access to the JavaScript
ExecuteSendRequest(napi_env env,void * data)1423 void ExecuteSendRequest(napi_env env, void *data)
1424 {
1425 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(data);
1426 param->errCode = param->target->SendRequest(param->code,
1427 *(param->data.get()), *(param->reply.get()), param->option);
1428 DBINDER_LOGI("sendRequest done, errCode:%{public}d", param->errCode);
1429 }
1430
1431 // This method runs on the main thread after 'ExecuteSendRequest' exits
SendRequestCbComplete(napi_env env,napi_status status,void * data)1432 void SendRequestCbComplete(napi_env env, napi_status status, void *data)
1433 {
1434 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(data);
1435 DBINDER_LOGI("sendRequestCallback completed, errCode:%{public}d", param->errCode);
1436 napi_value result = MakeSendRequestResult(param);
1437 napi_value callback = nullptr;
1438 napi_get_reference_value(env, param->callback, &callback);
1439 napi_value cbResult = nullptr;
1440 napi_call_function(env, nullptr, callback, 1, &result, &cbResult);
1441 napi_delete_reference(env, param->jsCodeRef);
1442 napi_delete_reference(env, param->jsDataRef);
1443 napi_delete_reference(env, param->jsReplyRef);
1444 napi_delete_reference(env, param->callback);
1445 napi_delete_async_work(env, param->asyncWork);
1446 delete param;
1447 }
1448
1449 // This method runs on the main thread after 'ExecuteSendRequest' exits
SendRequestPromiseComplete(napi_env env,napi_status status,void * data)1450 void SendRequestPromiseComplete(napi_env env, napi_status status, void *data)
1451 {
1452 SendRequestParam *param = reinterpret_cast<SendRequestParam *>(data);
1453 DBINDER_LOGI("sendRequestPromise completed, errCode:%{public}d", param->errCode);
1454 napi_value result = MakeSendRequestResult(param);
1455 if (param->errCode == 0) {
1456 napi_resolve_deferred(env, param->deferred, result);
1457 } else {
1458 napi_reject_deferred(env, param->deferred, result);
1459 }
1460 napi_delete_reference(env, param->jsCodeRef);
1461 napi_delete_reference(env, param->jsDataRef);
1462 napi_delete_reference(env, param->jsReplyRef);
1463 napi_delete_async_work(env, param->asyncWork);
1464 delete param;
1465 }
1466
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)1467 napi_value SendRequestAsync(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1468 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1469 MessageOption &option, napi_value *argv)
1470 {
1471 napi_value result = nullptr;
1472 SendRequestParam *sendRequestParam = new SendRequestParam {
1473 .target = target,
1474 .code = code,
1475 .data = data,
1476 .reply = reply,
1477 .option = option,
1478 .asyncWork = nullptr,
1479 .deferred = nullptr,
1480 .errCode = -1,
1481 .jsCodeRef = nullptr,
1482 .jsDataRef = nullptr,
1483 .jsReplyRef = nullptr,
1484 .callback = nullptr,
1485 .env = env,
1486 };
1487 napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1488 napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1489 napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1490 napi_create_reference(env, argv[4], 1, &sendRequestParam->callback);
1491 napi_value resourceName = nullptr;
1492 NAPI_CALL(env, napi_create_string_utf8(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
1493 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, ExecuteSendRequest,
1494 SendRequestCbComplete, (void *)sendRequestParam, &sendRequestParam->asyncWork));
1495 NAPI_CALL(env, napi_queue_async_work(env, sendRequestParam->asyncWork));
1496 napi_get_undefined(env, &result);
1497 return result;
1498 }
1499
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)1500 napi_value SendRequestPromise(napi_env env, sptr<IRemoteObject> target, uint32_t code,
1501 std::shared_ptr<MessageParcel> data, std::shared_ptr<MessageParcel> reply,
1502 MessageOption &option, napi_value *argv)
1503 {
1504 napi_deferred deferred = nullptr;
1505 napi_value promise = nullptr;
1506 napi_create_promise(env, &deferred, &promise);
1507 SendRequestParam *sendRequestParam = new SendRequestParam {
1508 .target = target,
1509 .code = code,
1510 .data = data,
1511 .reply = reply,
1512 .option = option,
1513 .asyncWork = nullptr,
1514 .deferred = deferred,
1515 .errCode = -1,
1516 .jsCodeRef = nullptr,
1517 .jsDataRef = nullptr,
1518 .jsReplyRef = nullptr,
1519 .callback = nullptr,
1520 .env = env,
1521 };
1522 napi_create_reference(env, argv[0], 1, &sendRequestParam->jsCodeRef);
1523 napi_create_reference(env, argv[1], 1, &sendRequestParam->jsDataRef);
1524 napi_create_reference(env, argv[2], 1, &sendRequestParam->jsReplyRef);
1525 napi_value resourceName = nullptr;
1526 NAPI_CALL(env, napi_create_string_utf8(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
1527 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, ExecuteSendRequest,
1528 SendRequestPromiseComplete, (void *)sendRequestParam, &sendRequestParam->asyncWork));
1529 NAPI_CALL(env, napi_queue_async_work(env, sendRequestParam->asyncWork));
1530 return promise;
1531 }
1532
NAPI_RemoteProxy_sendRequest(napi_env env,napi_callback_info info)1533 napi_value NAPI_RemoteProxy_sendRequest(napi_env env, napi_callback_info info)
1534 {
1535 size_t argc = 4;
1536 size_t argcCallback = 5;
1537 size_t argcPromise = 4;
1538 napi_value argv[5] = { 0 };
1539 napi_value thisVar = nullptr;
1540 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1541 NAPI_ASSERT(env, argc == argcPromise || argc == argcCallback, "requires 4 or 5 parameters");
1542 napi_valuetype valueType = napi_null;
1543 napi_typeof(env, argv[0], &valueType);
1544 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1545 napi_typeof(env, argv[1], &valueType);
1546 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
1547 napi_typeof(env, argv[2], &valueType);
1548 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
1549 napi_typeof(env, argv[3], &valueType);
1550 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
1551
1552 NAPI_MessageParcel *data = nullptr;
1553 napi_status status = napi_unwrap(env, argv[1], (void **)&data);
1554 NAPI_ASSERT(env, status == napi_ok, "failed to get data message parcel");
1555 NAPI_MessageParcel *reply = nullptr;
1556 status = napi_unwrap(env, argv[2], (void **)&reply);
1557 NAPI_ASSERT(env, status == napi_ok, "failed to get reply message parcel");
1558 MessageOption *option = nullptr;
1559 status = napi_unwrap(env, argv[3], (void **)&option);
1560 NAPI_ASSERT(env, status == napi_ok, "failed to get message option");
1561 int32_t code = 0;
1562 napi_get_value_int32(env, argv[0], &code);
1563
1564 NAPIRemoteProxyHolder *proxyHolder = nullptr;
1565 status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
1566 NAPI_ASSERT(env, proxyHolder != nullptr, "failed to get proxy holder");
1567 sptr<IRemoteObject> target = proxyHolder->object_;
1568 NAPI_ASSERT(env, target != nullptr, "invalid proxy object");
1569 if (argc == argcCallback) {
1570 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1571 napi_valuetype valuetype = napi_undefined;
1572 napi_typeof(env, argv[argcPromise], &valuetype);
1573 if (valuetype == napi_function) {
1574 return SendRequestAsync(env, target, code, data->GetMessageParcel(),
1575 reply->GetMessageParcel(), *option, argv);
1576 }
1577 }
1578 return SendRequestPromise(env, target, code, data->GetMessageParcel(),
1579 reply->GetMessageParcel(), *option, argv);
1580 }
1581
NAPI_RemoteProxy_queryLocalInterface(napi_env env,napi_callback_info info)1582 napi_value NAPI_RemoteProxy_queryLocalInterface(napi_env env, napi_callback_info info)
1583 {
1584 napi_value result = nullptr;
1585 napi_get_null(env, &result);
1586 return result;
1587 }
1588
NAPI_RemoteProxy_addDeathRecipient(napi_env env,napi_callback_info info)1589 napi_value NAPI_RemoteProxy_addDeathRecipient(napi_env env, napi_callback_info info)
1590 {
1591 DBINDER_LOGI("add death recipient");
1592 size_t argc = 2;
1593 size_t expectedArgc = 2;
1594 napi_value argv[2] = { 0 };
1595 napi_value thisVar = nullptr;
1596 void *data = nullptr;
1597 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1598 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameter");
1599 napi_valuetype valueType = napi_null;
1600 napi_typeof(env, argv[0], &valueType);
1601 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1602 napi_typeof(env, argv[1], &valueType);
1603 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
1604 int32_t flag = 0;
1605 napi_get_value_int32(env, argv[1], &flag);
1606
1607 napi_value result;
1608 if (argv[0] == nullptr) {
1609 napi_get_boolean(env, false, &result);
1610 return result;
1611 }
1612
1613 NAPIRemoteProxyHolder *proxyHolder = nullptr;
1614 napi_status status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
1615 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
1616 if (proxyHolder == nullptr) {
1617 napi_get_boolean(env, false, &result);
1618 return result;
1619 }
1620 sptr<IRemoteObject> target = proxyHolder->object_;
1621 if ((target == nullptr) || !target->IsProxyObject()) {
1622 DBINDER_LOGE("could not add recipient from invalid target");
1623 napi_get_boolean(env, false, &result);
1624 return result;
1625 }
1626
1627 sptr<NAPIDeathRecipient> nativeRecipient = new NAPIDeathRecipient(env, argv[0]);
1628 if (target->AddDeathRecipient(nativeRecipient)) {
1629 NAPIDeathRecipientList *list = proxyHolder->list_;
1630 if (list->Add(nativeRecipient)) {
1631 napi_get_boolean(env, true, &result);
1632 return result;
1633 }
1634 }
1635 napi_get_boolean(env, false, &result);
1636 return result;
1637 }
1638
NAPI_RemoteProxy_removeDeathRecipient(napi_env env,napi_callback_info info)1639 napi_value NAPI_RemoteProxy_removeDeathRecipient(napi_env env, napi_callback_info info)
1640 {
1641 DBINDER_LOGI("remove death recipient");
1642 size_t argc = 2;
1643 napi_value argv[2] = { 0 };
1644 napi_value thisVar = nullptr;
1645 void *data = nullptr;
1646 size_t expectedArgc = 2;
1647 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1648 NAPI_ASSERT(env, argc == expectedArgc, "requires 2 parameter");
1649 napi_valuetype valueType = napi_null;
1650 napi_typeof(env, argv[0], &valueType);
1651 NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
1652 napi_typeof(env, argv[1], &valueType);
1653 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
1654 napi_value result;
1655 if (argv[0] == nullptr) {
1656 napi_get_boolean(env, false, &result);
1657 return result;
1658 }
1659 int32_t flag = 0;
1660 napi_get_value_int32(env, argv[1], &flag);
1661
1662 NAPIRemoteProxyHolder *proxyHolder = nullptr;
1663 napi_status status = napi_unwrap(env, thisVar, (void **)&proxyHolder);
1664 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
1665 if (proxyHolder == nullptr) {
1666 napi_get_boolean(env, false, &result);
1667 return result;
1668 }
1669 sptr<IRemoteObject> target = proxyHolder->object_;
1670 if ((target == nullptr) || !target->IsProxyObject()) {
1671 DBINDER_LOGE("could not remove recipient from invalid target");
1672 napi_get_boolean(env, false, &result);
1673 return result;
1674 }
1675 sptr<NAPIDeathRecipientList> list = proxyHolder->list_;
1676 sptr<NAPIDeathRecipient> nativeRecipient = list->Find(argv[0]);
1677 if (nativeRecipient == nullptr) {
1678 DBINDER_LOGE("recipient not found");
1679 napi_get_boolean(env, false, &result);
1680 return result;
1681 }
1682 target->RemoveDeathRecipient(nativeRecipient);
1683 if (list->Remove(nativeRecipient)) {
1684 napi_get_boolean(env, true, &result);
1685 return result;
1686 } else {
1687 napi_get_boolean(env, false, &result);
1688 return result;
1689 }
1690 }
1691
NAPI_RemoteProxy_getInterfaceDescriptor(napi_env env,napi_callback_info info)1692 napi_value NAPI_RemoteProxy_getInterfaceDescriptor(napi_env env, napi_callback_info info)
1693 {
1694 napi_value thisVar = nullptr;
1695 napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
1696 NAPIRemoteProxyHolder *holder = nullptr;
1697 napi_status status = napi_unwrap(env, thisVar, (void **)&holder);
1698 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
1699 napi_value result;
1700 if (holder == nullptr) {
1701 napi_create_string_utf8(env, "", 0, &result);
1702 return result;
1703 }
1704 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
1705 if (target == nullptr) {
1706 DBINDER_LOGE("Invalid proxy object");
1707 napi_create_string_utf8(env, "", 0, &result);
1708 return result;
1709 }
1710 std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
1711 napi_create_string_utf8(env, Str16ToStr8(remoteDescriptor).c_str(), NAPI_AUTO_LENGTH, &result);
1712 return result;
1713 }
1714
NAPI_RemoteProxy_isObjectDead(napi_env env,napi_callback_info info)1715 napi_value NAPI_RemoteProxy_isObjectDead(napi_env env, napi_callback_info info)
1716 {
1717 DBINDER_LOGI("call isObjectDead");
1718 napi_value thisVar = nullptr;
1719 napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
1720 NAPIRemoteProxyHolder *holder = nullptr;
1721 napi_status status = napi_unwrap(env, thisVar, (void **)&holder);
1722 NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
1723 napi_value result;
1724 if (holder == nullptr) {
1725 napi_get_boolean(env, false, &result);
1726 return result;
1727 }
1728 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
1729 if (target == nullptr) {
1730 DBINDER_LOGE("Invalid proxy object");
1731 napi_get_boolean(env, false, &result);
1732 return result;
1733 }
1734
1735 if (target->IsObjectDead()) {
1736 napi_get_boolean(env, true, &result);
1737 return result;
1738 } else {
1739 napi_get_boolean(env, false, &result);
1740 return result;
1741 }
1742 }
1743
NAPIIPCSkeleton_JS_Constructor(napi_env env,napi_callback_info info)1744 napi_value NAPIIPCSkeleton_JS_Constructor(napi_env env, napi_callback_info info)
1745 {
1746 napi_value thisArg = nullptr;
1747 void *data = nullptr;
1748 napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
1749 napi_value global = nullptr;
1750 napi_get_global(env, &global);
1751 return thisArg;
1752 }
1753
1754 EXTERN_C_START
1755 /*
1756 * function for module exports
1757 */
NAPIIPCSkeletonExport(napi_env env,napi_value exports)1758 napi_value NAPIIPCSkeletonExport(napi_env env, napi_value exports)
1759 {
1760 DBINDER_LOGI("napi_moudule IPCSkeleton Init start...");
1761 napi_property_descriptor desc[] = {
1762 DECLARE_NAPI_STATIC_FUNCTION("getContextObject", NAPI_IPCSkeleton_getContextObject),
1763 DECLARE_NAPI_STATIC_FUNCTION("getCallingPid", NAPI_IPCSkeleton_getCallingPid),
1764 DECLARE_NAPI_STATIC_FUNCTION("getCallingUid", NAPI_IPCSkeleton_getCallingUid),
1765 DECLARE_NAPI_STATIC_FUNCTION("getCallingDeviceID", NAPI_IPCSkeleton_getCallingDeviceID),
1766 DECLARE_NAPI_STATIC_FUNCTION("getLocalDeviceID", NAPI_IPCSkeleton_getLocalDeviceID),
1767 DECLARE_NAPI_STATIC_FUNCTION("isLocalCalling", NAPI_IPCSkeleton_isLocalCalling),
1768 DECLARE_NAPI_STATIC_FUNCTION("flushCommands", NAPI_IPCSkeleton_flushCommands),
1769 DECLARE_NAPI_STATIC_FUNCTION("resetCallingIdentity", NAPI_IPCSkeleton_resetCallingIdentity),
1770 DECLARE_NAPI_STATIC_FUNCTION("setCallingIdentity", NAPI_IPCSkeleton_setCallingIdentity),
1771 DECLARE_NAPI_STATIC_FUNCTION("getCallingTokenId", NAPI_IPCSkeleton_getCallingTokenId),
1772 };
1773 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1774 napi_value result = nullptr;
1775 napi_define_class(env, "IPCSkeleton", NAPI_AUTO_LENGTH, NAPIIPCSkeleton_JS_Constructor, nullptr,
1776 sizeof(desc) / sizeof(desc[0]), desc, &result);
1777 napi_status status = napi_set_named_property(env, exports, "IPCSkeleton", result);
1778 NAPI_ASSERT(env, status == napi_ok, "create ref to js RemoteObject constructor failed");
1779 DBINDER_LOGI("napi_moudule IPCSkeleton Init end...");
1780 return exports;
1781 }
1782 EXTERN_C_END
1783
1784
NAPIMessageOption_JS_Constructor(napi_env env,napi_callback_info info)1785 napi_value NAPIMessageOption_JS_Constructor(napi_env env, napi_callback_info info)
1786 {
1787 size_t argc = 2;
1788 napi_value argv[2] = { 0 };
1789 napi_value thisVar = nullptr;
1790 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
1791 NAPI_ASSERT(env, argc >= 0, "invalid parameter number");
1792 int flags = 0;
1793 int waittime = 0;
1794 if (argc == 0) {
1795 flags = MessageOption::TF_SYNC;
1796 waittime = MessageOption::TF_WAIT_TIME;
1797 } else if (argc == 1) {
1798 napi_valuetype valueType;
1799 napi_typeof(env, argv[0], &valueType);
1800 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1801 int32_t jsFlags = 0;
1802 napi_get_value_int32(env, argv[1], &jsFlags);
1803 flags = jsFlags;
1804 waittime = MessageOption::TF_WAIT_TIME;
1805 } else {
1806 napi_valuetype valueType = napi_null;
1807 napi_typeof(env, argv[0], &valueType);
1808 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
1809 napi_typeof(env, argv[1], &valueType);
1810 NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
1811 int32_t jsFlags = 0;
1812 napi_get_value_int32(env, argv[0], &jsFlags);
1813 int32_t jsWaittime = 0;
1814 napi_get_value_int32(env, argv[1], &jsWaittime);
1815 flags = jsFlags;
1816 waittime = jsWaittime;
1817 }
1818
1819 auto messageOption = new MessageOption(flags, waittime);
1820 // connect native message option to js thisVar
1821 napi_status status = napi_wrap(
1822 env, thisVar, messageOption,
1823 [](napi_env env, void *data, void *hint) {
1824 DBINDER_LOGI("NAPIMessageOption destructed by js callback");
1825 delete (reinterpret_cast<MessageOption *>(data));
1826 },
1827 nullptr, nullptr);
1828 NAPI_ASSERT(env, status == napi_ok, "wrap js MessageOption and native option failed");
1829 return thisVar;
1830 }
1831
1832 EXTERN_C_START
1833 /*
1834 * function for module exports
1835 */
NAPIMessageOptionExport(napi_env env,napi_value exports)1836 napi_value NAPIMessageOptionExport(napi_env env, napi_value exports)
1837 {
1838 const std::string className = "MessageOption";
1839 napi_value tfSync = nullptr;
1840 napi_create_int32(env, MessageOption::TF_SYNC, &tfSync);
1841 napi_value tfAsync = nullptr;
1842 napi_create_int32(env, MessageOption::TF_ASYNC, &tfAsync);
1843 napi_value tfFds = nullptr;
1844 napi_create_int32(env, MessageOption::TF_ACCEPT_FDS, &tfFds);
1845 napi_value tfWaitTime = nullptr;
1846 napi_create_int32(env, MessageOption::TF_WAIT_TIME, &tfWaitTime);
1847 napi_property_descriptor properties[] = {
1848 DECLARE_NAPI_FUNCTION("getFlags", NapiOhosRpcMessageOptionGetFlags),
1849 DECLARE_NAPI_FUNCTION("setFlags", NapiOhosRpcMessageOptionSetFlags),
1850 DECLARE_NAPI_FUNCTION("getWaitTime", NapiOhosRpcMessageOptionGetWaittime),
1851 DECLARE_NAPI_FUNCTION("setWaitTime", NapiOhosRpcMessageOptionSetWaittime),
1852 DECLARE_NAPI_STATIC_PROPERTY("TF_SYNC", tfSync),
1853 DECLARE_NAPI_STATIC_PROPERTY("TF_ASYNC", tfAsync),
1854 DECLARE_NAPI_STATIC_PROPERTY("TF_ACCEPT_FDS", tfFds),
1855 DECLARE_NAPI_STATIC_PROPERTY("TF_WAIT_TIME", tfWaitTime),
1856 };
1857 napi_value constructor = nullptr;
1858 napi_define_class(env, className.c_str(), className.length(), NAPIMessageOption_JS_Constructor, nullptr,
1859 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
1860 NAPI_ASSERT(env, constructor != nullptr, "define js class MessageOption failed");
1861 napi_status status = napi_set_named_property(env, exports, "MessageOption", constructor);
1862 NAPI_ASSERT(env, status == napi_ok, "set property MessageOption to exports failed");
1863 napi_value global = nullptr;
1864 status = napi_get_global(env, &global);
1865 NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
1866 status = napi_set_named_property(env, global, "IPCOptionConstructor_", constructor);
1867 NAPI_ASSERT(env, status == napi_ok, "set message option constructor failed");
1868 return exports;
1869 }
1870 EXTERN_C_END
1871 } // namespace OHOS