1 /*
2 * Copyright (C) 2024 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_event_subscribe_module.h"
17
18 #include <algorithm>
19 #include "../parser/napi_parser_utils.h"
20 #include "string_ex.h"
21
22 namespace OHOS {
23 namespace Bluetooth {
ToLogString(const std::vector<std::string> & validNameVec)24 static std::string ToLogString(const std::vector<std::string> &validNameVec)
25 {
26 std::string str = "[";
27 for (const auto &s : validNameVec) {
28 str += s;
29 str += ", ";
30 }
31 str += "]";
32 return str;
33 }
34
NapiEventSubscribeModule(const char * validEventName,const char * moduleName)35 NapiEventSubscribeModule::NapiEventSubscribeModule(const char *validEventName, const char *moduleName)
36 : validEventNameVec_(std::vector<std::string>{validEventName}), moduleName_(moduleName)
37 {}
NapiEventSubscribeModule(std::vector<std::string> validEventNameVec,const char * moduleName)38 NapiEventSubscribeModule::NapiEventSubscribeModule(std::vector<std::string> validEventNameVec, const char *moduleName)
39 : validEventNameVec_(validEventNameVec), moduleName_(moduleName)
40 {}
41
Register(napi_env env,napi_callback_info info)42 napi_status NapiEventSubscribeModule::Register(napi_env env, napi_callback_info info)
43 {
44 size_t argc = ARGS_SIZE_TWO;
45 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
46 napi_value thisVar = nullptr;
47 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
48 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments", napi_invalid_arg);
49
50 std::string name {};
51 NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], name));
52 if (!IsValidEventName(name)) {
53 HILOGE("Invalid name %{public}s, valid name is %{public}s",
54 name.c_str(), ToLogString(validEventNameVec_).c_str());
55 return napi_invalid_arg;
56 }
57
58 napi_value callback = argv[PARAM1];
59 NAPI_BT_CALL_RETURN(NapiIsFunction(env, callback));
60
61 eventSubscribeMap_.ChangeValueByLambda(name, [this, &env, &name, &callback](auto &callbackVec) {
62 if (IsNapiCallbackExist(callbackVec, callback)) {
63 HILOGW("The %{public}s callback is registered, no need to re-registered", name.c_str());
64 return;
65 }
66 auto napiCallback = std::make_shared<NapiCallback>(env, callback);
67 if (napiCallback) {
68 callbackVec.push_back(napiCallback);
69 }
70 HILOGI("Register one %{public}s callback in %{public}s module, %{public}zu callback left",
71 name.c_str(), moduleName_.c_str(), callbackVec.size());
72 });
73 return napi_ok;
74 }
75
Deregister(napi_env env,napi_callback_info info)76 napi_status NapiEventSubscribeModule::Deregister(napi_env env, napi_callback_info info)
77 {
78 size_t argc = ARGS_SIZE_TWO;
79 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
80 napi_value thisVar = nullptr;
81 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
82 NAPI_BT_RETURN_IF(
83 argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments", napi_invalid_arg);
84
85 std::string name {};
86 NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], name));
87 if (!IsValidEventName(name)) {
88 HILOGE("Invalid name %{public}s, valid name is %{public}s",
89 name.c_str(), ToLogString(validEventNameVec_).c_str());
90 return napi_invalid_arg;
91 }
92
93 if (argc == ARGS_SIZE_ONE) {
94 HILOGI("Deregister all %{public}s callback in %{public}s module", name.c_str(), moduleName_.c_str());
95 eventSubscribeMap_.Erase(name);
96 return napi_ok;
97 }
98 // The argc is ARGS_SIZE_TWO
99 napi_value callback = argv[PARAM1];
100 NAPI_BT_CALL_RETURN(NapiIsFunction(env, callback));
101 eventSubscribeMap_.ChangeValueByLambda(name, [this, &name, &callback](auto &callbackVec) {
102 auto it = std::find_if(callbackVec.begin(), callbackVec.end(),
103 [&callback](auto &napiCallback) { return napiCallback->Equal(callback); });
104 if (it != callbackVec.end()) {
105 callbackVec.erase(it);
106 }
107 HILOGI("Deregister one %{public}s callback in %{public}s module, %{public}zu callback left",
108 name.c_str(), moduleName_.c_str(), callbackVec.size());
109 });
110 return napi_ok;
111 }
112
IsValidEventName(const std::string & eventName) const113 bool NapiEventSubscribeModule::IsValidEventName(const std::string &eventName) const
114 {
115 auto it = std::find(validEventNameVec_.begin(), validEventNameVec_.end(), eventName);
116 return it != validEventNameVec_.end();
117 }
118
IsNapiCallbackExist(const std::vector<std::shared_ptr<NapiCallback>> & napiCallbackVec,napi_value & callback) const119 bool NapiEventSubscribeModule::IsNapiCallbackExist(
120 const std::vector<std::shared_ptr<NapiCallback>> &napiCallbackVec, napi_value &callback) const
121 {
122 auto it = std::find_if(napiCallbackVec.begin(), napiCallbackVec.end(),
123 [&callback](const std::shared_ptr<NapiCallback> &napiCallback) { return napiCallback->Equal(callback); });
124 return it != napiCallbackVec.end();
125 }
126
CallFunction(std::shared_ptr<NapiNativeObject> nativeObject,std::vector<std::shared_ptr<NapiCallback>> napiCallbackVec)127 void NapiEventSubscribeModule::CallFunction(
128 std::shared_ptr<NapiNativeObject> nativeObject, std::vector<std::shared_ptr<NapiCallback>> napiCallbackVec)
129 {
130 for (const auto &callback : napiCallbackVec) {
131 if (callback == nullptr) {
132 continue;
133 }
134 auto func = [nativeObject, callback]() {
135 callback->CallFunction(nativeObject);
136 };
137 DoInJsMainThread(callback->GetNapiEnv(), std::move(func));
138 }
139 }
140
PublishEvent(std::string eventName,const std::shared_ptr<NapiNativeObject> & nativeObject)141 void NapiEventSubscribeModule::PublishEvent(
142 std::string eventName, const std::shared_ptr<NapiNativeObject> &nativeObject)
143 {
144 eventSubscribeMap_.Iterate([this, &eventName, &nativeObject](
145 const std::string &name, std::vector<std::shared_ptr<NapiCallback>> &napiCallbackVec) {
146 if (name != eventName) {
147 return;
148 }
149 CallFunction(nativeObject, napiCallbackVec);
150 });
151 }
152 } // namespace Bluetooth
153 } // namespace OHOS
154