• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_hisysevent_init.h"
17 
18 #include <memory>
19 #include <unordered_map>
20 
21 #include "def.h"
22 #include "hilog/log.h"
23 #include "hisysevent_base_manager.h"
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "napi_callback_context.h"
27 #include "napi_hisysevent_init.h"
28 #include "napi_hisysevent_listener.h"
29 #include "napi_hisysevent_querier.h"
30 #include "napi_hisysevent_util.h"
31 #include "ret_def.h"
32 
33 using namespace OHOS::HiviewDFX;
34 
35 namespace {
36 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD002D08, "NAPI_HISYSEVENT_JS" };
37 constexpr char RULES_ATTR[] = "rules";
38 constexpr size_t WRITE_FUNC_MAX_PARAM_NUM = 2;
39 constexpr size_t ADD_LISTENER_FUNC_MAX_PARAM_NUM = 1;
40 constexpr size_t REMOVE_LISTENER_FUNC_MAX_PARAM_NUM = 1;
41 constexpr size_t QUERY_FUNC_MAX_PARAM_NUM = 3;
42 constexpr size_t ADD_LISTENER_LISTENER_PARAM_INDEX = 0;
43 constexpr size_t REMOVE_LISTENER_LISTENER_PARAM_INDEX = 0;
44 constexpr size_t QUERY_QUERY_ARG_PARAM_INDEX = 0;
45 constexpr size_t QUERY_RULE_ARRAY_PARAM_INDEX = 1;
46 constexpr size_t QUERY_QUERIER_PARAM_INDEX = 2;
47 constexpr long long DEFAULT_TIME_STAMP = -1;
48 constexpr int DEFAULT_EVENT_COUNT = 1000;
49 using NAPI_LISTENER_PAIR = std::pair<pid_t, std::shared_ptr<NapiHiSysEventListener>>;
50 using NAPI_QUERIER_PAIR = std::pair<pid_t, std::shared_ptr<NapiHiSysEventQuerier>>;
51 std::unordered_map<napi_ref, NAPI_LISTENER_PAIR> listeners;
52 std::unordered_map<napi_ref, NAPI_QUERIER_PAIR> queriers;
53 }
54 
Write(napi_env env,napi_callback_info info)55 static napi_value Write(napi_env env, napi_callback_info info)
56 {
57     size_t paramNum = WRITE_FUNC_MAX_PARAM_NUM;
58     napi_value params[WRITE_FUNC_MAX_PARAM_NUM] = {0};
59     napi_value thisArg = nullptr;
60     void *data = nullptr;
61     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisArg, &data));
62     napi_value val = nullptr;
63     napi_get_undefined(env, &val);
64     if (paramNum < WRITE_FUNC_MAX_PARAM_NUM - 1) {
65         HiLog::Error(LABEL,
66             "count of parameters is not equal to %{public}zu or %{public}zu.",
67             WRITE_FUNC_MAX_PARAM_NUM - 1, WRITE_FUNC_MAX_PARAM_NUM);
68         NapiHiSysEventUtil::ThrowParamMandatoryError(env, "info");
69         return val;
70     }
71     HiSysEventAsyncContext* asyncContext = new(std::nothrow) HiSysEventAsyncContext {
72         .env = env,
73         .asyncWork = nullptr,
74         .deferred = nullptr,
75     };
76     if (asyncContext == nullptr) {
77         HiLog::Error(LABEL, "failed to new HiSysEventAsyncContext.");
78         return val;
79     }
80     NapiHiSysEventUtil::ParseHiSysEventInfo(env, params, paramNum, asyncContext->eventInfo);
81     asyncContext->eventWroteResult = SUCCESS;
82     // set callback function if it exists
83     if (paramNum == WRITE_FUNC_MAX_PARAM_NUM) {
84         napi_valuetype lastParamType;
85         napi_typeof(env, params[paramNum - 1], &lastParamType);
86         if (lastParamType == napi_valuetype::napi_function) {
87             napi_create_reference(env, params[paramNum - 1], 1, &asyncContext->callback);
88         }
89     } else if (paramNum > WRITE_FUNC_MAX_PARAM_NUM) {
90         HiLog::Warn(LABEL, "count of params is invalid =%{public}d.", static_cast<int>(paramNum));
91     }
92     // set promise object if callback function is null
93     napi_value promise = nullptr;
94     napi_get_undefined(env, &promise);
95     if (asyncContext->callback == nullptr) {
96         napi_create_promise(env, &asyncContext->deferred, &promise);
97     }
98     NapiHiSysEventAdapter::Write(env, asyncContext);
99     return promise;
100 }
101 
AddWatcher(napi_env env,napi_callback_info info)102 static napi_value AddWatcher(napi_env env, napi_callback_info info)
103 {
104     size_t paramNum = ADD_LISTENER_FUNC_MAX_PARAM_NUM;
105     napi_value params[ADD_LISTENER_FUNC_MAX_PARAM_NUM] = {0};
106     napi_value thisArg = nullptr;
107     void* data = nullptr;
108     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisArg, &data));
109     if (paramNum < ADD_LISTENER_FUNC_MAX_PARAM_NUM) {
110         HiLog::Error(LABEL, "count of parameters is less than %{public}zu.", ADD_LISTENER_FUNC_MAX_PARAM_NUM);
111         NapiHiSysEventUtil::ThrowParamMandatoryError(env, "watcher");
112         return nullptr;
113     }
114     std::vector<ListenerRule> rules;
115     napi_value jsRulesVal = NapiHiSysEventUtil::GetPropertyByName(env, params[ADD_LISTENER_LISTENER_PARAM_INDEX],
116         RULES_ATTR);
117     if (auto ret = NapiHiSysEventUtil::ParseListenerRules(env, jsRulesVal, rules);
118         ret != SUCCESS) {
119         HiLog::Error(LABEL, "failed to parse watch rules, result code is %{public}d.", ret);
120         return nullptr;
121     }
122     CallbackContext* callbackContext = new CallbackContext();
123     callbackContext->env = env;
124     callbackContext->threadId = syscall(SYS_gettid);
125     napi_create_reference(env, params[ADD_LISTENER_LISTENER_PARAM_INDEX], 1, &callbackContext->ref);
126     std::shared_ptr<NapiHiSysEventListener> listener = std::make_shared<NapiHiSysEventListener>(callbackContext);
127     auto ret = HiSysEventBaseManager::AddListener(listener, rules);
128     if (ret != NAPI_SUCCESS) {
129         HiLog::Error(LABEL, "failed to add event listener, result code is %{public}d.", ret);
130         NapiHiSysEventUtil::ThrowErrorByRet(env, ret);
131         return nullptr;
132     }
133     listeners[callbackContext->ref] = std::make_pair(callbackContext->threadId, listener);
134     return nullptr;
135 }
136 
RemoveWatcher(napi_env env,napi_callback_info info)137 static napi_value RemoveWatcher(napi_env env, napi_callback_info info)
138 {
139     size_t paramNum = REMOVE_LISTENER_FUNC_MAX_PARAM_NUM;
140     napi_value params[REMOVE_LISTENER_FUNC_MAX_PARAM_NUM] = {0};
141     napi_value thisArg = nullptr;
142     void* data = nullptr;
143     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisArg, &data));
144     if (paramNum < REMOVE_LISTENER_FUNC_MAX_PARAM_NUM) {
145         HiLog::Error(LABEL, "count of parameters is less than %{public}zu.", REMOVE_LISTENER_FUNC_MAX_PARAM_NUM);
146         NapiHiSysEventUtil::ThrowParamMandatoryError(env, "watcher");
147         return nullptr;
148     }
149     auto iter = NapiHiSysEventUtil::CompareAndReturnCacheItem<NapiHiSysEventListener>(env,
150         params[REMOVE_LISTENER_LISTENER_PARAM_INDEX], listeners);
151     if (iter == listeners.end()) {
152         HiLog::Error(LABEL, "listener not exist.");
153         NapiHiSysEventUtil::ThrowErrorByRet(env, ERR_NAPI_LISTENER_NOT_FOUND);
154         return nullptr;
155     }
156     listeners.erase(iter->first);
157     if (auto ret = HiSysEventBaseManager::RemoveListener(iter->second.second);
158         ret != NAPI_SUCCESS) {
159         HiLog::Error(LABEL, "failed to remove event listener, result code is %{public}d.", ret);
160         NapiHiSysEventUtil::ThrowErrorByRet(env, ret);
161     }
162     return nullptr;
163 }
164 
Query(napi_env env,napi_callback_info info)165 static napi_value Query(napi_env env, napi_callback_info info)
166 {
167     size_t paramNum = QUERY_FUNC_MAX_PARAM_NUM;
168     napi_value params[QUERY_FUNC_MAX_PARAM_NUM] = {0};
169     napi_value thisArg = nullptr;
170     void* data = nullptr;
171     NAPI_CALL(env, napi_get_cb_info(env, info, &paramNum, params, &thisArg, &data));
172     if (paramNum < QUERY_FUNC_MAX_PARAM_NUM) {
173         std::unordered_map<int32_t, std::string> paramError = {
174             {QUERY_QUERY_ARG_PARAM_INDEX, "queryArg"},
175             {QUERY_RULE_ARRAY_PARAM_INDEX, "rules"},
176             {QUERY_QUERIER_PARAM_INDEX, "querier"},
177         };
178         HiLog::Error(LABEL, "count of parameters is less than %{public}zu.", QUERY_FUNC_MAX_PARAM_NUM);
179         NapiHiSysEventUtil::ThrowParamMandatoryError(env, paramError.at(paramNum));
180         return nullptr;
181     }
182     QueryArg queryArg = { DEFAULT_TIME_STAMP, DEFAULT_TIME_STAMP, DEFAULT_EVENT_COUNT };
183     if (auto ret = NapiHiSysEventUtil::ParseQueryArg(env, params[QUERY_QUERY_ARG_PARAM_INDEX], queryArg);
184         ret != SUCCESS) {
185         HiLog::Error(LABEL, "failed to parse query arg, result code is %{public}d.", ret);
186         return nullptr;
187     }
188     std::vector<QueryRule> rules;
189     if (auto ret = NapiHiSysEventUtil::ParseQueryRules(env, params[QUERY_RULE_ARRAY_PARAM_INDEX], rules);
190         ret != SUCCESS) {
191         HiLog::Error(LABEL, "failed to parse query rules, result code is %{public}d.", ret);
192         return nullptr;
193     }
194     CallbackContext* callbackContext = new CallbackContext();
195     callbackContext->env = env;
196     callbackContext->threadId = syscall(SYS_gettid);
197     napi_create_reference(env, params[QUERY_QUERIER_PARAM_INDEX], 1, &callbackContext->ref);
198     std::shared_ptr<NapiHiSysEventQuerier> querier = std::make_shared<NapiHiSysEventQuerier>(callbackContext,
199         [] (const napi_env env, const napi_ref ref) {
200             napi_value querier = nullptr;
201             napi_get_reference_value(env, ref, &querier);
202             auto iter = NapiHiSysEventUtil::CompareAndReturnCacheItem<NapiHiSysEventQuerier>(env, querier, queriers);
203             if (iter != queriers.end()) {
204                 queriers.erase(iter->first);
205             }
206         });
207     auto ret = HiSysEventBaseManager::Query(queryArg, rules, querier);
208     if (ret != NAPI_SUCCESS) {
209         HiLog::Error(LABEL, "failed to query hisysevent, result code is %{public}d.", ret);
210         NapiHiSysEventUtil::ThrowErrorByRet(env, ret);
211     }
212     queriers[callbackContext->ref] = std::make_pair(callbackContext->threadId, querier);
213     return nullptr;
214 }
215 
216 EXTERN_C_START
Init(napi_env env,napi_value exports)217 static napi_value Init(napi_env env, napi_value exports)
218 {
219     napi_property_descriptor desc[] = {
220         DECLARE_NAPI_FUNCTION("write", Write),
221         DECLARE_NAPI_FUNCTION("addWatcher", AddWatcher),
222         DECLARE_NAPI_FUNCTION("removeWatcher", RemoveWatcher),
223         DECLARE_NAPI_FUNCTION("query", Query),
224     };
225     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
226 
227     // init EventType class, Event class and Param class
228     InitNapiClass(env, exports);
229 
230     return exports;
231 }
232 EXTERN_C_END
233 
234 static napi_module _module = {
235     .nm_version = 1,
236     .nm_flags = 0,
237     .nm_filename = nullptr,
238     .nm_register_func = Init,
239     .nm_modname = "hiSysEvent",
240     .nm_priv = ((void*)0),
241     .reserved = {0}
242 };
243 
RegisterModule(void)244 extern "C" __attribute__((constructor)) void RegisterModule(void)
245 {
246     napi_module_register(&_module);
247 }
248