1 /*
2 * Copyright (c) 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 "js_drag_context.h"
17
18 #include "devicestatus_define.h"
19 #include "drag_data.h"
20 #include "napi_constants.h"
21 #include "util_napi_error.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "JsDragContext"
25
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
29 namespace {
30 const char* DRAG_CLASS { "drag_class" };
31 const char* DRAG { "drag" };
32 inline constexpr size_t MAX_STRING_LEN { 1024 };
33 } // namespace
34
JsDragContext()35 JsDragContext::JsDragContext()
36 : mgr_(std::make_shared<JsDragManager>()) {}
37
~JsDragContext()38 JsDragContext::~JsDragContext()
39 {
40 std::lock_guard<std::mutex> guard(mutex_);
41 if (mgr_ != nullptr) {
42 mgr_->ResetEnv();
43 mgr_ = nullptr;
44 }
45 }
46
GetJsDragMgr()47 std::shared_ptr<JsDragManager> JsDragContext::GetJsDragMgr()
48 {
49 std::lock_guard<std::mutex> guard(mutex_);
50 return mgr_;
51 }
52
CreateInstance(napi_env env)53 napi_value JsDragContext::CreateInstance(napi_env env)
54 {
55 CALL_INFO_TRACE;
56 napi_value global = nullptr;
57 CHKRP(napi_get_global(env, &global), GET_GLOBAL);
58
59 constexpr char className[] = "JsDragContext";
60 napi_value jsClass = nullptr;
61 napi_property_descriptor desc[] = {};
62 napi_status status = napi_define_class(env, className, sizeof(className),
63 JsDragContext::JsConstructor, nullptr, sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
64 CHKRP(status, DEFINE_CLASS);
65
66 status = napi_set_named_property(env, global, DRAG_CLASS, jsClass);
67 CHKRP(status, SET_NAMED_PROPERTY);
68
69 napi_value jsInstance = nullptr;
70 CHKRP(napi_new_instance(env, jsClass, 0, nullptr, &jsInstance), NEW_INSTANCE);
71 CHKRP(napi_set_named_property(env, global, DRAG, jsInstance),
72 SET_NAMED_PROPERTY);
73
74 JsDragContext *jsContext = nullptr;
75 CHKRP(napi_unwrap(env, jsInstance, reinterpret_cast<void**>(&jsContext)), UNWRAP);
76 CHKPP(jsContext);
77 CHKRP(napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_)), CREATE_REFERENCE);
78
79 uint32_t refCount = 0;
80 status = napi_reference_ref(env, jsContext->contextRef_, &refCount);
81 if (status != napi_ok) {
82 FI_HILOGE("ref is nullptr");
83 napi_delete_reference(env, jsContext->contextRef_);
84 return nullptr;
85 }
86 return jsInstance;
87 }
88
JsConstructor(napi_env env,napi_callback_info info)89 napi_value JsDragContext::JsConstructor(napi_env env, napi_callback_info info)
90 {
91 CALL_INFO_TRACE;
92 napi_value thisVar = nullptr;
93 void *data = nullptr;
94 CHKRP(napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data), GET_CB_INFO);
95
96 JsDragContext *jsContext = new (std::nothrow) JsDragContext();
97 CHKPP(jsContext);
98 napi_status status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void *data, void *hin) {
99 FI_HILOGI("Jsvm ends");
100 JsDragContext *context = static_cast<JsDragContext*>(data);
101 delete context;
102 }, nullptr, nullptr);
103 if (status != napi_ok) {
104 delete jsContext;
105 FI_HILOGE("%{public}s failed", std::string(WRAP).c_str());
106 auto errInfoTemp = std::string(__FUNCTION__) + ": " + std::string(WRAP) + " failed";
107 napi_throw_error(env, nullptr, errInfoTemp.c_str());
108 return nullptr;
109 }
110 return thisVar;
111 }
112
GetInstance(napi_env env)113 JsDragContext *JsDragContext::GetInstance(napi_env env)
114 {
115 CALL_INFO_TRACE;
116 napi_value global = nullptr;
117 CHKRP(napi_get_global(env, &global), GET_GLOBAL);
118
119 bool result = false;
120 CHKRP(napi_has_named_property(env, global, DRAG, &result), HAS_NAMED_PROPERTY);
121 if (!result) {
122 FI_HILOGE("Drag was not found");
123 return nullptr;
124 }
125
126 napi_handle_scope scope = nullptr;
127 napi_open_handle_scope(env, &scope);
128 if (scope == nullptr) {
129 FI_HILOGE("scope is nullptr");
130 return nullptr;
131 }
132 napi_value object = nullptr;
133 CHKRP_SCOPE(env, napi_get_named_property(env, global, DRAG, &object), GET_NAMED_PROPERTY, scope);
134 if (object == nullptr) {
135 napi_close_handle_scope(env, scope);
136 FI_HILOGE("object is nullptr");
137 return nullptr;
138 }
139
140 JsDragContext *instance = nullptr;
141 CHKRP_SCOPE(env, napi_unwrap(env, object, reinterpret_cast<void**>(&instance)), UNWRAP, scope);
142 if (instance == nullptr) {
143 napi_close_handle_scope(env, scope);
144 FI_HILOGE("instance is nullptr");
145 return nullptr;
146 }
147 napi_close_handle_scope(env, scope);
148 return instance;
149 }
150
On(napi_env env,napi_callback_info info)151 napi_value JsDragContext::On(napi_env env, napi_callback_info info)
152 {
153 CALL_INFO_TRACE;
154 size_t argc = 2;
155 napi_value argv[2] = { nullptr };
156 CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
157 if (argc < 2) {
158 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
159 return nullptr;
160 }
161 JsDragContext *jsDev = JsDragContext::GetInstance(env);
162 CHKPP(jsDev);
163 auto jsDragMgr = jsDev->GetJsDragMgr();
164 CHKPP(jsDragMgr);
165 if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
166 THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
167 return nullptr;
168 }
169 char type[MAX_STRING_LEN] = { 0 };
170 size_t strLength = 0;
171 CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &strLength), CREATE_STRING_UTF8);
172 if ((DRAG_TYPE.compare(type)) != 0) {
173 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be drag");
174 return nullptr;
175 }
176 if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
177 THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
178 return nullptr;
179 }
180 jsDragMgr->RegisterListener(env, argv[1]);
181 return nullptr;
182 }
183
Off(napi_env env,napi_callback_info info)184 napi_value JsDragContext::Off(napi_env env, napi_callback_info info)
185 {
186 CALL_INFO_TRACE;
187 size_t argc = 2;
188 napi_value argv[2] = { nullptr };
189 CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
190
191 JsDragContext *jsDev = JsDragContext::GetInstance(env);
192 CHKPP(jsDev);
193 auto jsDragMgr = jsDev->GetJsDragMgr();
194 CHKPP(jsDragMgr);
195 if ((argc == 0) || (!UtilNapi::TypeOf(env, argv[0], napi_string))) {
196 THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
197 return nullptr;
198 }
199 char type[MAX_STRING_LEN] = { 0 };
200 size_t length = 0;
201 CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), CREATE_STRING_UTF8);
202 if ((DRAG_TYPE.compare(type)) != 0) {
203 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be drag");
204 return nullptr;
205 }
206 if (argc == 1) {
207 jsDragMgr->UnregisterListener(env);
208 return nullptr;
209 }
210 if (UtilNapi::TypeOf(env, argv[1], napi_undefined) || UtilNapi::TypeOf(env, argv[1], napi_null)) {
211 jsDragMgr->UnregisterListener(env);
212 return nullptr;
213 }
214 if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
215 THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
216 return nullptr;
217 }
218 jsDragMgr->UnregisterListener(env, argv[1]);
219 return nullptr;
220 }
221
GetDataSummary(napi_env env,napi_callback_info info)222 napi_value JsDragContext::GetDataSummary(napi_env env, napi_callback_info info)
223 {
224 CALL_INFO_TRACE;
225 JsDragContext *jsDev = JsDragContext::GetInstance(env);
226 CHKPP(jsDev);
227 auto jsDragMgr = jsDev->GetJsDragMgr();
228 CHKPP(jsDragMgr);
229 return jsDragMgr->GetDataSummary(env);
230 }
231
DeclareDragData(napi_env env,napi_value exports)232 void JsDragContext::DeclareDragData(napi_env env, napi_value exports)
233 {
234 napi_value startMsg = nullptr;
235 CHKRV(napi_create_int32(env, static_cast<int32_t>(DragState::START), &startMsg),
236 CREATE_INT32);
237 napi_value stopMsg = nullptr;
238 CHKRV(napi_create_int32(env, static_cast<int32_t>(DragState::STOP), &stopMsg),
239 CREATE_INT32);
240 napi_value cancelMsg = nullptr;
241 CHKRV(napi_create_int32(env, static_cast<int32_t>(DragState::CANCEL), &cancelMsg),
242 CREATE_INT32);
243
244 napi_property_descriptor msg[] = {
245 DECLARE_NAPI_STATIC_PROPERTY("MSG_DRAG_STATE_START", startMsg),
246 DECLARE_NAPI_STATIC_PROPERTY("MSG_DRAG_STATE_STOP", stopMsg),
247 DECLARE_NAPI_STATIC_PROPERTY("MSG_DRAG_STATE_CANCEL", cancelMsg)
248 };
249
250 napi_value eventMsg = nullptr;
251 CHKRV(napi_define_class(env, "DragState", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
252 sizeof(msg) / sizeof(*msg), msg, &eventMsg), DEFINE_CLASS);
253 CHKRV(napi_set_named_property(env, exports, "DragState", eventMsg), SET_NAMED_PROPERTY);
254 }
255
DeclareDragInterface(napi_env env,napi_value exports)256 void JsDragContext::DeclareDragInterface(napi_env env, napi_value exports)
257 {
258 napi_property_descriptor functions[] = {
259 DECLARE_NAPI_STATIC_FUNCTION("on", On),
260 DECLARE_NAPI_STATIC_FUNCTION("off", Off),
261 DECLARE_NAPI_STATIC_FUNCTION("getDataSummary", GetDataSummary)
262 };
263 CHKRV(napi_define_properties(env, exports,
264 sizeof(functions) / sizeof(*functions), functions), DEFINE_PROPERTIES);
265 }
266
EnumClassConstructor(napi_env env,napi_callback_info info)267 napi_value JsDragContext::EnumClassConstructor(napi_env env, napi_callback_info info)
268 {
269 size_t argc = 0;
270 napi_value args[1] = { nullptr };
271 napi_value result = nullptr;
272 void *data = nullptr;
273 CHKRP(napi_get_cb_info(env, info, &argc, args, &result, &data), GET_CB_INFO);
274 return result;
275 }
276
Export(napi_env env,napi_value exports)277 napi_value JsDragContext::Export(napi_env env, napi_value exports)
278 {
279 CALL_INFO_TRACE;
280 auto instance = CreateInstance(env);
281 CHKPP(instance);
282 DeclareDragData(env, exports);
283 DeclareDragInterface(env, exports);
284 return exports;
285 }
286 } // namespace DeviceStatus
287 } // namespace Msdp
288 } // namespace OHOS
289