• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_async_callback_manager.h"
17 #include <uv.h>
18 #include "event_logger.h"
19 #include "serialize.h"
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 DEFINE_EH_HILOG_LABEL("EventsEmitter");
24 }
25 
NapiDeleteCallbackInfoByEventId(const InnerEvent::EventId & eventIdValue)26 void NapiAsyncCallbackManager::NapiDeleteCallbackInfoByEventId(const InnerEvent::EventId &eventIdValue)
27 {
28     std::lock_guard<std::mutex> lock(napiAsyncCallbackContainerMutex_);
29     auto iter = napiAsyncCallbackContainer_.find(eventIdValue);
30     if (iter != napiAsyncCallbackContainer_.end()) {
31         for (auto callbackInfo : iter->second) {
32             callbackInfo->isDeleted = true;
33         }
34     }
35     napiAsyncCallbackContainer_.erase(eventIdValue);
36 }
37 
NapiGetListenerCountByEventId(const InnerEvent::EventId & eventId)38 uint32_t NapiAsyncCallbackManager::NapiGetListenerCountByEventId(const InnerEvent::EventId &eventId)
39 {
40     uint32_t cnt = 0u;
41     std::lock_guard<std::mutex> lock(napiAsyncCallbackContainerMutex_);
42     auto subscribe = napiAsyncCallbackContainer_.find(eventId);
43     if (subscribe != napiAsyncCallbackContainer_.end()) {
44         for (auto it = subscribe->second.begin(); it != subscribe->second.end();) {
45             if ((*it)->isDeleted == true || (*it)->env == nullptr) {
46                 it = subscribe->second.erase(it);
47                 continue;
48             }
49             ++it;
50             ++cnt;
51         }
52     }
53     return cnt;
54 }
55 
NapiIsExistValidCallback(const InnerEvent::EventId & eventId)56 bool NapiAsyncCallbackManager::NapiIsExistValidCallback(const InnerEvent::EventId &eventId)
57 {
58     std::lock_guard<std::mutex> lock(napiAsyncCallbackContainerMutex_);
59     auto subscribe = napiAsyncCallbackContainer_.find(eventId);
60     if (subscribe == napiAsyncCallbackContainer_.end()) {
61         return false;
62     }
63     if (subscribe->second.size() != 0) {
64         return true;
65     }
66     return false;
67 }
68 
NapiDeleteCallbackInfo(napi_env env,const InnerEvent::EventId & eventIdValue,napi_value argv)69 void NapiAsyncCallbackManager::NapiDeleteCallbackInfo(
70     napi_env env, const InnerEvent::EventId &eventIdValue, napi_value argv)
71 {
72     std::lock_guard<std::mutex> lock(napiAsyncCallbackContainerMutex_);
73     auto iter = napiAsyncCallbackContainer_.find(eventIdValue);
74     if (iter == napiAsyncCallbackContainer_.end()) {
75         return;
76     }
77     for (auto callbackInfo = iter->second.begin(); callbackInfo != iter->second.end();) {
78         napi_value callback = nullptr;
79         if ((*callbackInfo)->env != env) {
80             ++callbackInfo;
81             continue;
82         }
83         napi_get_reference_value((*callbackInfo)->env, (*callbackInfo)->callback, &callback);
84         bool isEq = false;
85         napi_strict_equals(env, argv, callback, &isEq);
86         if (!isEq) {
87             ++callbackInfo;
88             continue;
89         }
90         (*callbackInfo)->isDeleted = true;
91         callbackInfo = iter->second.erase(callbackInfo);
92         return;
93     }
94     return;
95 }
96 
NapiGetAsyncCallbackInfo(const InnerEvent::EventId & eventId)97 std::unordered_set<std::shared_ptr<AsyncCallbackInfo>> NapiAsyncCallbackManager::NapiGetAsyncCallbackInfo(
98     const InnerEvent::EventId &eventId)
99 {
100     std::lock_guard<std::mutex> lock(napiAsyncCallbackContainerMutex_);
101     auto iter = napiAsyncCallbackContainer_.find(eventId);
102     if (iter == napiAsyncCallbackContainer_.end()) {
103         std::unordered_set<std::shared_ptr<AsyncCallbackInfo>> result;
104         return result;
105     }
106     for (auto it = iter->second.begin(); it != iter->second.end();) {
107         if ((*it)->isDeleted == true || (*it)->env == nullptr) {
108             it = iter->second.erase(it);
109             continue;
110         }
111         ++it;
112     }
113     return iter->second;
114 }
115 
NapiDoCallback(const InnerEvent::Pointer & event)116 void NapiAsyncCallbackManager::NapiDoCallback(const InnerEvent::Pointer& event)
117 {
118     auto napiCallbackInfos = NapiGetAsyncCallbackInfo(event->GetInnerEventIdEx());
119     auto serializeData = event->GetSharedObject<SerializeData>();
120     auto deleter = [](napi_value* data) {
121         if (data != nullptr) {
122             delete data;
123         }
124     };
125     for (auto it = napiCallbackInfos.begin(); it != napiCallbackInfos.end(); ++it) {
126         if (*it == nullptr || (*it)->env == nullptr || (*it)->isDeleted) {
127             HILOGE("napiCallbackInfo is unavailable");
128             continue;
129         }
130         EventDataWorker* eventDataWorker = new (std::nothrow) EventDataWorker();
131         if (!eventDataWorker) {
132             HILOGE("new object failed");
133             return;
134         }
135         eventDataWorker->IsEnhanced = true;
136         eventDataWorker->serializePtr = serializeData;
137         eventDataWorker->callbackInfo = *it;
138         if (serializeData->envType == EnvType::NAPI) {
139             auto napiValue = std::get<napi_value>(serializeData->peerData);
140             auto* heapValue = new napi_value(napiValue);
141             eventDataWorker->data = std::shared_ptr<napi_value>(heapValue, deleter);
142             eventDataWorker->isCrossRuntime = false;
143         } else {
144             eventDataWorker->enhancedData =
145                 reinterpret_cast<void*>(const_cast<char*>(serializeData->crossData.c_str()));
146             eventDataWorker->isCrossRuntime = true;
147         }
148         napi_acquire_threadsafe_function((*it)->tsfn);
149         napi_call_threadsafe_function((*it)->tsfn, eventDataWorker, napi_tsfn_nonblocking);
150         napi_release_threadsafe_function((*it)->tsfn, napi_tsfn_release);
151     }
152 }
153 } // namespace AppExecFwk
154 } // namespace OHOS