1 /* 2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "events_emitter.h" 17 18 #include <iterator> 19 #include <memory> 20 #include <mutex> 21 #include <new> 22 #include <uv.h> 23 #include <unordered_set> 24 #include "event_logger.h" 25 #include "js_native_api_types.h" 26 #include "napi/native_node_api.h" 27 28 using namespace std; 29 namespace OHOS { 30 namespace AppExecFwk { 31 namespace { 32 DEFINE_EH_HILOG_LABEL("EventsEmitter"); 33 constexpr static uint32_t ARGC_ONE = 1u; 34 } 35 static std::mutex g_emitterInsMutex; 36 static map<InnerEvent::EventId, std::unordered_set<std::shared_ptr<AsyncCallbackInfo>>> emitterInstances; 37 std::shared_ptr<EventHandlerInstance> eventHandler; ~AsyncCallbackInfo()38 AsyncCallbackInfo::~AsyncCallbackInfo() 39 { 40 env = nullptr; 41 } EventHandlerInstance(const std::shared_ptr<EventRunner> & runner)42 EventHandlerInstance::EventHandlerInstance(const std::shared_ptr<EventRunner>& runner): EventHandler(runner) 43 { 44 HILOGI("EventHandlerInstance constructed"); 45 } ~EventHandlerInstance()46 EventHandlerInstance::~EventHandlerInstance() 47 { 48 HILOGI("EventHandlerInstance de-constructed"); 49 } GetInstance()50 std::shared_ptr<EventHandlerInstance> EventHandlerInstance::GetInstance() 51 { 52 static auto runner = EventRunner::Create("OS_eventsEmtr"); 53 if (runner.get() == nullptr) { 54 HILOGE("failed to create EventRunner events_emitter"); 55 return nullptr; 56 } 57 static auto instance = std::make_shared<EventHandlerInstance>(runner); 58 return instance; 59 } 60 ProcessCallback(const EventDataWorker * eventDataInner)61 void ProcessCallback(const EventDataWorker* eventDataInner) 62 { 63 HILOGD("enter"); 64 65 std::shared_ptr<AsyncCallbackInfo> callbackInner = eventDataInner->callbackInfo; 66 napi_value resultData = nullptr; 67 if (eventDataInner->data != nullptr && *(eventDataInner->data) != nullptr) { 68 if (napi_deserialize(callbackInner->env, *(eventDataInner->data), &resultData) != napi_ok || 69 resultData == nullptr) { 70 HILOGE("Deserialize fail."); 71 return; 72 } 73 } 74 napi_value event = nullptr; 75 napi_create_object(callbackInner->env, &event); 76 napi_set_named_property(callbackInner->env, event, "data", resultData); 77 napi_value callback = nullptr; 78 napi_value returnVal = nullptr; 79 napi_get_reference_value(callbackInner->env, callbackInner->callback, &callback); 80 napi_call_function(callbackInner->env, nullptr, callback, 1, &event, &returnVal); 81 if (callbackInner->once) { 82 HILOGD("ProcessEvent delete once"); 83 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 84 auto iter = emitterInstances.find(callbackInner->eventId); 85 if (iter != emitterInstances.end()) { 86 auto callback = iter->second.find(callbackInner); 87 if (callback != iter->second.end()) { 88 iter->second.erase(callback); 89 } 90 } 91 } 92 } 93 OutPutEventIdLog(const InnerEvent::EventId & eventId)94 void OutPutEventIdLog(const InnerEvent::EventId &eventId) 95 { 96 if (eventId.index() == TYPE_U32_INDEX) { 97 HILOGD("Event id value:%{public}u", std::get<uint32_t>(eventId)); 98 } else { 99 HILOGD("Event id value:%{public}s", std::get<std::string>(eventId).c_str()); 100 } 101 } 102 ThreadSafeCallback(napi_env env,napi_value jsCallback,void * context,void * data)103 void ThreadSafeCallback(napi_env env, napi_value jsCallback, void* context, void* data) 104 { 105 napi_handle_scope scope; 106 EventDataWorker* eventDataInner = static_cast<EventDataWorker*>(data); 107 if (eventDataInner != nullptr) { 108 auto callbackInfoInner = eventDataInner->callbackInfo; 109 if (callbackInfoInner && !(callbackInfoInner->isDeleted)) { 110 HILOGD("eventDataInner address: %{public}p", &eventDataInner); 111 napi_open_handle_scope(callbackInfoInner->env, &scope); 112 ProcessCallback(eventDataInner); 113 napi_close_handle_scope(callbackInfoInner->env, scope); 114 } 115 } 116 delete eventDataInner; 117 eventDataInner = nullptr; 118 data = nullptr; 119 } 120 ProcessEvent(const InnerEvent::Pointer & event)121 void EventHandlerInstance::ProcessEvent([[maybe_unused]] const InnerEvent::Pointer& event) 122 { 123 InnerEvent::EventId eventId = event->GetInnerEventIdEx(); 124 OutPutEventIdLog(eventId); 125 std::unordered_set<std::shared_ptr<AsyncCallbackInfo>> callbackInfos; 126 { 127 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 128 auto iter = emitterInstances.find(eventId); 129 if (iter == emitterInstances.end()) { 130 HILOGW("ProcessEvent has no callback"); 131 return; 132 } 133 134 callbackInfos = iter->second; 135 } 136 137 HILOGD("size = %{public}zu", callbackInfos.size()); 138 auto value = event->GetUniqueObject<napi_value>(); 139 std::shared_ptr<napi_value> eventData(value.release(), [this](napi_value* pData) { 140 if (pData != nullptr && (*pData) != nullptr && deleteEnv != nullptr) { 141 napi_delete_serialization_data(deleteEnv, *pData); 142 } 143 }); 144 for (auto it = callbackInfos.begin(); it != callbackInfos.end(); ++it) { 145 EventDataWorker* eventDataWorker = new (std::nothrow) EventDataWorker(); 146 if (!eventDataWorker) { 147 HILOGE("new object failed"); 148 continue; 149 } 150 deleteEnv = (*it)->env; 151 eventDataWorker->data = eventData; 152 eventDataWorker->callbackInfo = (*it); 153 napi_acquire_threadsafe_function((*it)->tsfn); 154 napi_call_threadsafe_function((*it)->tsfn, eventDataWorker, napi_tsfn_nonblocking); 155 napi_release_threadsafe_function((*it)->tsfn, napi_tsfn_release); 156 } 157 } 158 UpdateOnceFlag(std::shared_ptr<AsyncCallbackInfo> callbackInfo,bool once)159 static void UpdateOnceFlag(std::shared_ptr<AsyncCallbackInfo>callbackInfo, bool once) 160 { 161 if (!once) { 162 if (callbackInfo->once) { 163 HILOGD("JS_On change once to on"); 164 callbackInfo->once = false; 165 } else { 166 HILOGD("JS_On already on"); 167 } 168 } else { 169 if (callbackInfo->once) { 170 HILOGD("JS_Once already once"); 171 } else { 172 HILOGD("JS_Once change on to once"); 173 callbackInfo->once = true; 174 } 175 } 176 } 177 DeleteCallbackInfo(napi_env env,const InnerEvent::EventId & eventIdValue,napi_value argv)178 void DeleteCallbackInfo(napi_env env, const InnerEvent::EventId &eventIdValue, napi_value argv) 179 { 180 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 181 auto iter = emitterInstances.find(eventIdValue); 182 if (iter == emitterInstances.end()) { 183 return; 184 } 185 for (auto callbackInfo = iter->second.begin(); callbackInfo != iter->second.end();) { 186 napi_value callback = nullptr; 187 if ((*callbackInfo)->env != env) { 188 ++callbackInfo; 189 continue; 190 } 191 napi_get_reference_value((*callbackInfo)->env, (*callbackInfo)->callback, &callback); 192 bool isEq = false; 193 napi_strict_equals(env, argv, callback, &isEq); 194 if (!isEq) { 195 ++callbackInfo; 196 continue; 197 } 198 (*callbackInfo)->isDeleted = true; 199 callbackInfo = iter->second.erase(callbackInfo); 200 return; 201 } 202 return; 203 } 204 SearchCallbackInfo(napi_env env,const InnerEvent::EventId & eventIdValue,napi_value argv)205 std::shared_ptr<AsyncCallbackInfo> SearchCallbackInfo(napi_env env, const InnerEvent::EventId &eventIdValue, 206 napi_value argv) 207 { 208 auto subscribe = emitterInstances.find(eventIdValue); 209 if (subscribe == emitterInstances.end()) { 210 return nullptr; 211 } 212 for (auto callbackInfo : subscribe->second) { 213 napi_value callback = nullptr; 214 if (callbackInfo->isDeleted) { 215 continue; 216 } 217 if (callbackInfo->env != env) { 218 continue; 219 } 220 napi_get_reference_value(callbackInfo->env, callbackInfo->callback, &callback); 221 bool isEq = false; 222 napi_strict_equals(env, argv, callback, &isEq); 223 if (!isEq) { 224 continue; 225 } 226 return callbackInfo; 227 } 228 return nullptr; 229 } 230 GetEventIdWithObjectOrString(napi_env env,napi_value argv,napi_valuetype eventValueType,InnerEvent::EventId & eventId)231 bool GetEventIdWithObjectOrString( 232 napi_env env, napi_value argv, napi_valuetype eventValueType, InnerEvent::EventId &eventId) 233 { 234 if (eventValueType == napi_string) { 235 size_t valueStrBufLength = 0; 236 napi_get_value_string_utf8(env, argv, nullptr, NAPI_VALUE_STRING_LEN, &valueStrBufLength); 237 auto valueCStr = std::make_unique<char[]>(NAPI_VALUE_STRING_LEN + 1); 238 size_t valueStrLength = 0; 239 napi_get_value_string_utf8(env, argv, valueCStr.get(), NAPI_VALUE_STRING_LEN, &valueStrLength); 240 std::string id(valueCStr.get(), valueStrLength); 241 if (id.empty()) { 242 HILOGE("Event id is empty for argument 1."); 243 return false; 244 } 245 eventId = id; 246 HILOGD("Event id value:%{public}s", id.c_str()); 247 } else { 248 bool hasEventId = false; 249 napi_has_named_property(env, argv, "eventId", &hasEventId); 250 if (!hasEventId) { 251 HILOGE("Argument 1 does not have event id."); 252 return false; 253 } 254 255 napi_value eventIdValue = nullptr; 256 napi_get_named_property(env, argv, "eventId", &eventIdValue); 257 uint32_t id = 0u; 258 napi_get_value_uint32(env, eventIdValue, &id); 259 eventId = id; 260 HILOGD("Event id value:%{public}u", id); 261 } 262 return true; 263 } 264 ThreadFinished(napi_env env,void * data,void * context)265 void ThreadFinished(napi_env env, void* data, [[maybe_unused]] void* context) 266 { 267 HILOGD("ThreadFinished"); 268 } 269 ReleaseCallbackInfo(AsyncCallbackInfo * callbackInfo)270 void ReleaseCallbackInfo(AsyncCallbackInfo* callbackInfo) 271 { 272 if (callbackInfo != nullptr) { 273 uv_loop_s *loop = nullptr; 274 if (napi_get_uv_event_loop(callbackInfo->env, &loop) != napi_ok) { 275 return; 276 } 277 uv_work_t *work = new (std::nothrow) uv_work_t; 278 if (work == nullptr) { 279 return; 280 } 281 work->data = reinterpret_cast<void*>(callbackInfo); 282 uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {}, [](uv_work_t *work, int status) { 283 AsyncCallbackInfo* callbackInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data); 284 if (napi_delete_reference(callbackInfo->env, callbackInfo->callback) != napi_ok) { 285 HILOGE("napi_delete_reference fail."); 286 } 287 napi_release_threadsafe_function(callbackInfo->tsfn, napi_tsfn_release); 288 delete callbackInfo; 289 callbackInfo = nullptr; 290 delete work; 291 work = nullptr; 292 }, uv_qos_user_initiated); 293 } 294 } 295 OnOrOnce(napi_env env,napi_callback_info cbinfo,bool once)296 napi_value OnOrOnce(napi_env env, napi_callback_info cbinfo, bool once) 297 { 298 size_t argc = ARGC_NUM; 299 napi_value argv[ARGC_NUM] = {0}; 300 NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL)); 301 if (argc < ARGC_NUM) { 302 HILOGE("requires 2 parameter"); 303 return nullptr; 304 } 305 306 napi_valuetype eventValueType = GetNapiType(env, argv[0]); 307 if (eventValueType != napi_object && eventValueType != napi_string) { 308 HILOGE("type mismatch for parameter 1"); 309 return nullptr; 310 } 311 312 if (GetNapiType(env, argv[1]) != napi_function) { 313 HILOGE("type mismatch for parameter 2"); 314 return nullptr; 315 } 316 317 InnerEvent::EventId eventIdValue = 0u; 318 bool ret = GetEventIdWithObjectOrString(env, argv[0], eventValueType, eventIdValue); 319 if (!ret) { 320 return nullptr; 321 } 322 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 323 auto callbackInfo = SearchCallbackInfo(env, eventIdValue, argv[1]); 324 if (callbackInfo != nullptr) { 325 UpdateOnceFlag(callbackInfo, once); 326 } else { 327 callbackInfo = std::shared_ptr<AsyncCallbackInfo>(new (std::nothrow) AsyncCallbackInfo(), 328 [](AsyncCallbackInfo* callbackInfo) { 329 ReleaseCallbackInfo(callbackInfo); 330 }); 331 if (!callbackInfo) { 332 HILOGE("new object failed"); 333 return nullptr; 334 } 335 callbackInfo->env = env; 336 callbackInfo->once = once; 337 callbackInfo->eventId = eventIdValue; 338 napi_create_reference(env, argv[1], 1, &callbackInfo->callback); 339 napi_wrap(env, argv[1], new (std::nothrow) std::weak_ptr<AsyncCallbackInfo>(callbackInfo), 340 [](napi_env env, void* data, void* hint) { 341 auto callbackInfoPtr = static_cast<std::weak_ptr<AsyncCallbackInfo>*>(data); 342 if (callbackInfoPtr != nullptr && (*callbackInfoPtr).lock() != nullptr) { 343 (*callbackInfoPtr).lock()->isDeleted = true; 344 (*callbackInfoPtr).lock()->env = nullptr; 345 } 346 }, nullptr, nullptr); 347 napi_value resourceName = nullptr; 348 napi_create_string_utf8(env, "Call thread-safe function", NAPI_AUTO_LENGTH, &resourceName); 349 napi_create_threadsafe_function(env, argv[1], nullptr, resourceName, 0, 1, nullptr, ThreadFinished, 350 nullptr, ThreadSafeCallback, &(callbackInfo->tsfn)); 351 emitterInstances[eventIdValue].insert(callbackInfo); 352 } 353 return nullptr; 354 } 355 GetEventIdWithNumberOrString(napi_env env,napi_value argv,napi_valuetype eventValueType,InnerEvent::EventId & eventId)356 bool GetEventIdWithNumberOrString( 357 napi_env env, napi_value argv, napi_valuetype eventValueType, InnerEvent::EventId &eventId) 358 { 359 if (eventValueType == napi_string) { 360 size_t valueStrBufLength = 0; 361 napi_get_value_string_utf8(env, argv, nullptr, NAPI_VALUE_STRING_LEN, &valueStrBufLength); 362 auto valueCStr = std::make_unique<char[]>(NAPI_VALUE_STRING_LEN + 1); 363 size_t valueStrLength = 0; 364 napi_get_value_string_utf8(env, argv, valueCStr.get(), NAPI_VALUE_STRING_LEN, &valueStrLength); 365 std::string id(valueCStr.get(), valueStrLength); 366 if (id.empty()) { 367 return false; 368 } 369 eventId = id; 370 HILOGD("Event id value:%{public}s", id.c_str()); 371 } else { 372 uint32_t id = 0u; 373 napi_get_value_uint32(env, argv, &id); 374 eventId = id; 375 HILOGD("Event id value:%{public}u", id); 376 } 377 return true; 378 } 379 JS_On(napi_env env,napi_callback_info cbinfo)380 napi_value JS_On(napi_env env, napi_callback_info cbinfo) 381 { 382 HILOGD("enter"); 383 return OnOrOnce(env, cbinfo, false); 384 } 385 JS_Once(napi_env env,napi_callback_info cbinfo)386 napi_value JS_Once(napi_env env, napi_callback_info cbinfo) 387 { 388 HILOGD("enter"); 389 return OnOrOnce(env, cbinfo, true); 390 } 391 JS_Off(napi_env env,napi_callback_info cbinfo)392 napi_value JS_Off(napi_env env, napi_callback_info cbinfo) 393 { 394 HILOGD("enter"); 395 size_t argc = ARGC_NUM; 396 napi_value argv[ARGC_NUM] = {0}; 397 NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL)); 398 if (argc < 1) { 399 HILOGE("requires at least 1 parameter"); 400 return nullptr; 401 } 402 403 napi_valuetype eventValueType; 404 napi_typeof(env, argv[0], &eventValueType); 405 if (eventValueType != napi_number && eventValueType != napi_string) { 406 HILOGE("type mismatch for parameter 1"); 407 return nullptr; 408 } 409 410 InnerEvent::EventId eventId = 0u; 411 bool ret = GetEventIdWithNumberOrString(env, argv[0], eventValueType, eventId); 412 if (!ret) { 413 HILOGE("Event id is empty for parameter 1."); 414 return nullptr; 415 } 416 417 if (argc == ARGC_NUM) { 418 napi_valuetype eventHandleType; 419 napi_typeof(env, argv[1], &eventHandleType); 420 if (eventHandleType != napi_function) { 421 HILOGE("type mismatch for parameter 2"); 422 return nullptr; 423 } 424 DeleteCallbackInfo(env, eventId, argv[1]); 425 return nullptr; 426 } 427 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 428 auto iter = emitterInstances.find(eventId); 429 if (iter != emitterInstances.end()) { 430 for (auto callbackInfo : iter->second) { 431 callbackInfo->isDeleted = true; 432 } 433 } 434 emitterInstances.erase(eventId); 435 return nullptr; 436 } 437 EmitWithEventData(napi_env env,napi_value argv,const InnerEvent::EventId & eventId,Priority priority)438 bool EmitWithEventData(napi_env env, napi_value argv, const InnerEvent::EventId &eventId, Priority priority) 439 { 440 HILOGD("enter"); 441 napi_valuetype dataType; 442 napi_typeof(env, argv, &dataType); 443 if (dataType != napi_object) { 444 HILOGE("type mismatch for parameter 2"); 445 return false; 446 } 447 bool hasData = false; 448 napi_value serializeData = nullptr; 449 napi_has_named_property(env, argv, "data", &hasData); 450 if (hasData) { 451 napi_value data = nullptr; 452 napi_get_named_property(env, argv, "data", &data); 453 napi_status serializeResult = napi_ok; 454 napi_value undefined = nullptr; 455 napi_get_undefined(env, &undefined); 456 bool defaultTransfer = false; 457 bool defaultCloneSendable = true; 458 serializeResult = napi_serialize(env, data, undefined, undefined, 459 defaultTransfer, defaultCloneSendable, &serializeData); 460 if (serializeResult != napi_ok || serializeData == nullptr) { 461 HILOGE("Serialize fail."); 462 return false; 463 } 464 } 465 OutPutEventIdLog(eventId); 466 auto event = InnerEvent::Get(eventId, make_unique<napi_value>(serializeData)); 467 eventHandler->SendEvent(event, 0, priority); 468 return true; 469 } 470 IsExistValidCallback(napi_env env,const InnerEvent::EventId & eventId)471 bool IsExistValidCallback(napi_env env, const InnerEvent::EventId &eventId) 472 { 473 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 474 auto subscribe = emitterInstances.find(eventId); 475 if (subscribe == emitterInstances.end()) { 476 HILOGW("JS_Emit has no callback"); 477 return false; 478 } 479 if (subscribe->second.size() != 0) { 480 return true; 481 } 482 return false; 483 } 484 EmitWithEventIdUint32(napi_env env,size_t argc,napi_value argv[])485 napi_value EmitWithEventIdUint32(napi_env env, size_t argc, napi_value argv[]) 486 { 487 InnerEvent::EventId eventId = 0u; 488 bool hasEventId = false; 489 napi_value value = nullptr; 490 napi_has_named_property(env, argv[0], "eventId", &hasEventId); 491 if (hasEventId == false) { 492 HILOGE("Wrong argument 1 does not have event id."); 493 return nullptr; 494 } 495 496 napi_get_named_property(env, argv[0], "eventId", &value); 497 uint32_t id = 0u; 498 napi_get_value_uint32(env, value, &id); 499 eventId = id; 500 HILOGD("Event id value:%{public}u", id); 501 502 if (!IsExistValidCallback(env, eventId)) { 503 HILOGE("Invalid callback"); 504 return nullptr; 505 } 506 507 bool hasPriority = false; 508 napi_has_named_property(env, argv[0], "priority", &hasPriority); 509 Priority priority = Priority::LOW; 510 if (hasPriority) { 511 napi_get_named_property(env, argv[0], "priority", &value); 512 uint32_t priorityValue = 0u; 513 napi_get_value_uint32(env, value, &priorityValue); 514 HILOGD("Event priority:%{public}d", priorityValue); 515 priority = static_cast<Priority>(priorityValue); 516 } 517 518 if (argc == ARGC_NUM && EmitWithEventData(env, argv[1], eventId, priority)) { 519 return nullptr; 520 } else { 521 auto event = InnerEvent::Get(eventId, make_unique<EventData>()); 522 eventHandler->SendEvent(event, 0, priority); 523 } 524 return nullptr; 525 } 526 EmitWithEventIdString(napi_env env,size_t argc,napi_value argv[])527 napi_value EmitWithEventIdString(napi_env env, size_t argc, napi_value argv[]) 528 { 529 InnerEvent::EventId eventId = 0u; 530 size_t valueStrBufLength = 0; 531 napi_get_value_string_utf8(env, argv[0], nullptr, NAPI_VALUE_STRING_LEN, &valueStrBufLength); 532 auto valueCStr = std::make_unique<char[]>(NAPI_VALUE_STRING_LEN + 1); 533 size_t valueStrLength = 0; 534 napi_get_value_string_utf8(env, argv[0], valueCStr.get(), NAPI_VALUE_STRING_LEN, &valueStrLength); 535 std::string id(valueCStr.get(), valueStrLength); 536 if (id.empty()) { 537 HILOGE("Invalid event id:%{public}s", id.c_str()); 538 return nullptr; 539 } 540 eventId = id; 541 HILOGD("Event id value:%{public}s", id.c_str()); 542 543 if (!IsExistValidCallback(env, eventId)) { 544 HILOGE("Invalid callback"); 545 return nullptr; 546 } 547 548 Priority priority = Priority::LOW; 549 if (argc < ARGC_NUM) { 550 auto event = InnerEvent::Get(eventId, make_unique<EventData>()); 551 eventHandler->SendEvent(event, 0, priority); 552 return nullptr; 553 } 554 555 bool hasPriority = false; 556 napi_value value = nullptr; 557 napi_has_named_property(env, argv[1], "priority", &hasPriority); 558 if (!hasPriority) { 559 if (!EmitWithEventData(env, argv[1], eventId, priority)) { 560 auto event = InnerEvent::Get(eventId, make_unique<EventData>()); 561 eventHandler->SendEvent(event, 0, priority); 562 } 563 return nullptr; 564 } 565 566 napi_get_named_property(env, argv[1], "priority", &value); 567 uint32_t priorityValue = 0u; 568 napi_get_value_uint32(env, value, &priorityValue); 569 HILOGD("Event priority:%{public}d", priorityValue); 570 priority = static_cast<Priority>(priorityValue); 571 572 if (argc > ARGC_NUM && EmitWithEventData(env, argv[ARGC_NUM], eventId, priority)) { 573 return nullptr; 574 } else { 575 auto event = InnerEvent::Get(eventId, make_unique<EventData>()); 576 eventHandler->SendEvent(event, 0, priority); 577 } 578 return nullptr; 579 } 580 JS_Emit(napi_env env,napi_callback_info cbinfo)581 napi_value JS_Emit(napi_env env, napi_callback_info cbinfo) 582 { 583 HILOGD("enter"); 584 size_t argc = ARGC_NUM + ARGC_ONE; 585 napi_value argv[ARGC_NUM + ARGC_ONE] = {0}; 586 NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL)); 587 if (argc < ARGC_ONE) { 588 HILOGE("Requires more than 1 parameter"); 589 return nullptr; 590 } 591 592 napi_valuetype eventValueType; 593 napi_typeof(env, argv[0], &eventValueType); 594 if (eventValueType != napi_object && eventValueType != napi_string) { 595 HILOGE("Type mismatch for parameter 1"); 596 return nullptr; 597 } 598 599 if (eventValueType == napi_string) { 600 return EmitWithEventIdString(env, argc, argv); 601 } 602 return EmitWithEventIdUint32(env, argc, argv); 603 } 604 EnumEventClassConstructor(napi_env env,napi_callback_info info)605 napi_value EnumEventClassConstructor(napi_env env, napi_callback_info info) 606 { 607 napi_value thisArg = nullptr; 608 void *data = nullptr; 609 610 napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data); 611 612 napi_value global = nullptr; 613 napi_get_global(env, &global); 614 615 return thisArg; 616 } 617 CreateEnumEventPriority(napi_env env,napi_value exports)618 napi_value CreateEnumEventPriority(napi_env env, napi_value exports) 619 { 620 napi_value immediate = nullptr; 621 napi_value high = nullptr; 622 napi_value low = nullptr; 623 napi_value idle = nullptr; 624 625 napi_create_uint32(env, (uint32_t)Priority::IMMEDIATE, &immediate); 626 napi_create_uint32(env, (uint32_t)Priority::HIGH, &high); 627 napi_create_uint32(env, (uint32_t)Priority::LOW, &low); 628 napi_create_uint32(env, (uint32_t)Priority::IDLE, &idle); 629 630 napi_property_descriptor desc[] = { 631 DECLARE_NAPI_STATIC_PROPERTY("IMMEDIATE", immediate), 632 DECLARE_NAPI_STATIC_PROPERTY("HIGH", high), 633 DECLARE_NAPI_STATIC_PROPERTY("LOW", low), 634 DECLARE_NAPI_STATIC_PROPERTY("IDLE", idle), 635 }; 636 napi_value result = nullptr; 637 napi_define_class(env, "EventPriority", NAPI_AUTO_LENGTH, EnumEventClassConstructor, nullptr, 638 sizeof(desc) / sizeof(*desc), desc, &result); 639 640 napi_set_named_property(env, exports, "EventPriority", result); 641 642 return exports; 643 } 644 CreateJsUndefined(napi_env env)645 napi_value CreateJsUndefined(napi_env env) 646 { 647 napi_value result = nullptr; 648 napi_get_undefined(env, &result); 649 return result; 650 } 651 CreateJsNumber(napi_env env,uint32_t value)652 napi_value CreateJsNumber(napi_env env, uint32_t value) 653 { 654 napi_value result = nullptr; 655 napi_create_uint32(env, value, &result); 656 return result; 657 } 658 JS_GetListenerCount(napi_env env,napi_callback_info cbinfo)659 napi_value JS_GetListenerCount(napi_env env, napi_callback_info cbinfo) 660 { 661 HILOGD("enter"); 662 size_t argc = ARGC_NUM; 663 napi_value argv[ARGC_NUM] = {0}; 664 NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, NULL, NULL)); 665 if (argc < ARGC_ONE) { 666 HILOGE("Requires more than 1 parameter"); 667 return CreateJsUndefined(env); 668 } 669 670 napi_valuetype eventValueType; 671 napi_typeof(env, argv[0], &eventValueType); 672 if (eventValueType != napi_number && eventValueType != napi_string) { 673 HILOGE("Type mismatch for parameter 1"); 674 return CreateJsUndefined(env); 675 } 676 677 uint32_t cnt = 0u; 678 InnerEvent::EventId eventId = 0u; 679 bool ret = GetEventIdWithNumberOrString(env, argv[0], eventValueType, eventId); 680 if (!ret) { 681 HILOGE("Event id is empty for parameter 1."); 682 return CreateJsUndefined(env); 683 } 684 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 685 auto subscribe = emitterInstances.find(eventId); 686 if (subscribe != emitterInstances.end()) { 687 for (auto callbackInfo : subscribe->second) { 688 ++cnt; 689 } 690 } 691 return CreateJsNumber(env, cnt); 692 } 693 EmitterInit(napi_env env,napi_value exports)694 napi_value EmitterInit(napi_env env, napi_value exports) 695 { 696 HILOGD("enter"); 697 napi_property_descriptor desc[] = { 698 DECLARE_NAPI_FUNCTION("on", JS_On), 699 DECLARE_NAPI_FUNCTION("once", JS_Once), 700 DECLARE_NAPI_FUNCTION("off", JS_Off), 701 DECLARE_NAPI_FUNCTION("emit", JS_Emit), 702 DECLARE_NAPI_FUNCTION("getListenerCount", JS_GetListenerCount), 703 }; 704 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); 705 706 CreateEnumEventPriority(env, exports); 707 708 eventHandler = EventHandlerInstance::GetInstance(); 709 return exports; 710 } 711 } // namespace AppExecFwk 712 } // namespace OHOS 713