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 inline constexpr size_t MAX_PKG_NAME_LEN { 128 };
34 inline constexpr std::string_view GET_VALUE_BOOL { "napi_get_value_bool" };
35 } // namespace
36
JsDragContext()37 JsDragContext::JsDragContext()
38 : mgr_(std::make_shared<JsDragManager>()) {}
39
~JsDragContext()40 JsDragContext::~JsDragContext()
41 {
42 std::lock_guard<std::mutex> guard(mutex_);
43 if (mgr_ != nullptr) {
44 mgr_->ResetEnv();
45 mgr_ = nullptr;
46 }
47 }
48
GetJsDragMgr()49 std::shared_ptr<JsDragManager> JsDragContext::GetJsDragMgr()
50 {
51 std::lock_guard<std::mutex> guard(mutex_);
52 return mgr_;
53 }
54
CreateInstance(napi_env env)55 napi_value JsDragContext::CreateInstance(napi_env env)
56 {
57 CALL_INFO_TRACE;
58 napi_value global = nullptr;
59 CHKRP(napi_get_global(env, &global), GET_GLOBAL);
60
61 constexpr char className[] = "JsDragContext";
62 napi_value jsClass = nullptr;
63 napi_property_descriptor desc[] = {};
64 napi_status status = napi_define_class(env, className, sizeof(className),
65 JsDragContext::JsConstructor, nullptr, sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
66 CHKRP(status, DEFINE_CLASS);
67
68 status = napi_set_named_property(env, global, DRAG_CLASS, jsClass);
69 CHKRP(status, SET_NAMED_PROPERTY);
70
71 napi_value jsInstance = nullptr;
72 CHKRP(napi_new_instance(env, jsClass, 0, nullptr, &jsInstance), NEW_INSTANCE);
73 CHKRP(napi_set_named_property(env, global, DRAG, jsInstance),
74 SET_NAMED_PROPERTY);
75
76 JsDragContext *jsContext = nullptr;
77 CHKRP(napi_unwrap(env, jsInstance, reinterpret_cast<void**>(&jsContext)), UNWRAP);
78 CHKPP(jsContext);
79 CHKRP(napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_)), CREATE_REFERENCE);
80
81 uint32_t refCount = 0;
82 status = napi_reference_ref(env, jsContext->contextRef_, &refCount);
83 if (status != napi_ok) {
84 FI_HILOGE("ref is nullptr");
85 napi_delete_reference(env, jsContext->contextRef_);
86 return nullptr;
87 }
88 return jsInstance;
89 }
90
JsConstructor(napi_env env,napi_callback_info info)91 napi_value JsDragContext::JsConstructor(napi_env env, napi_callback_info info)
92 {
93 CALL_INFO_TRACE;
94 napi_value thisVar = nullptr;
95 void *data = nullptr;
96 CHKRP(napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data), GET_CB_INFO);
97
98 JsDragContext *jsContext = new (std::nothrow) JsDragContext();
99 CHKPP(jsContext);
100 napi_status status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void *data, void *hin) {
101 FI_HILOGI("Jsvm ends");
102 JsDragContext *context = static_cast<JsDragContext*>(data);
103 delete context;
104 }, nullptr, nullptr);
105 if (status != napi_ok) {
106 delete jsContext;
107 FI_HILOGE("%{public}s failed", std::string(WRAP).c_str());
108 auto errInfoTemp = std::string(__FUNCTION__) + ": " + std::string(WRAP) + " failed";
109 napi_throw_error(env, nullptr, errInfoTemp.c_str());
110 return nullptr;
111 }
112 return thisVar;
113 }
114
GetInstance(napi_env env)115 JsDragContext *JsDragContext::GetInstance(napi_env env)
116 {
117 CALL_INFO_TRACE;
118 napi_value global = nullptr;
119 CHKRP(napi_get_global(env, &global), GET_GLOBAL);
120
121 bool result = false;
122 CHKRP(napi_has_named_property(env, global, DRAG, &result), HAS_NAMED_PROPERTY);
123 if (!result) {
124 FI_HILOGE("Drag was not found");
125 return nullptr;
126 }
127
128 napi_handle_scope scope = nullptr;
129 napi_open_handle_scope(env, &scope);
130 if (scope == nullptr) {
131 FI_HILOGE("scope is nullptr");
132 return nullptr;
133 }
134 napi_value object = nullptr;
135 CHKRP_SCOPE(env, napi_get_named_property(env, global, DRAG, &object), GET_NAMED_PROPERTY, scope);
136 if (object == nullptr) {
137 napi_close_handle_scope(env, scope);
138 FI_HILOGE("object is nullptr");
139 return nullptr;
140 }
141
142 JsDragContext *instance = nullptr;
143 CHKRP_SCOPE(env, napi_unwrap(env, object, reinterpret_cast<void**>(&instance)), UNWRAP, scope);
144 if (instance == nullptr) {
145 napi_close_handle_scope(env, scope);
146 FI_HILOGE("instance is nullptr");
147 return nullptr;
148 }
149 napi_close_handle_scope(env, scope);
150 return instance;
151 }
152
On(napi_env env,napi_callback_info info)153 napi_value JsDragContext::On(napi_env env, napi_callback_info info)
154 {
155 CALL_INFO_TRACE;
156 size_t argc = 2;
157 napi_value argv[2] = { nullptr };
158 CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
159 if (argc < 2) {
160 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
161 return nullptr;
162 }
163 JsDragContext *jsDev = JsDragContext::GetInstance(env);
164 CHKPP(jsDev);
165 auto jsDragMgr = jsDev->GetJsDragMgr();
166 CHKPP(jsDragMgr);
167 if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
168 THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
169 return nullptr;
170 }
171 char type[MAX_STRING_LEN] = { 0 };
172 size_t strLength = 0;
173 CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &strLength), CREATE_STRING_UTF8);
174 if ((DRAG_TYPE.compare(type)) != 0) {
175 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be drag");
176 return nullptr;
177 }
178 if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
179 THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
180 return nullptr;
181 }
182 jsDragMgr->RegisterListener(env, argv[1]);
183 return nullptr;
184 }
185
Off(napi_env env,napi_callback_info info)186 napi_value JsDragContext::Off(napi_env env, napi_callback_info info)
187 {
188 CALL_INFO_TRACE;
189 size_t argc = 2;
190 napi_value argv[2] = { nullptr };
191 CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
192
193 JsDragContext *jsDev = JsDragContext::GetInstance(env);
194 CHKPP(jsDev);
195 auto jsDragMgr = jsDev->GetJsDragMgr();
196 CHKPP(jsDragMgr);
197 if ((argc == 0) || (!UtilNapi::TypeOf(env, argv[0], napi_string))) {
198 THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
199 return nullptr;
200 }
201 char type[MAX_STRING_LEN] = { 0 };
202 size_t length = 0;
203 CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), CREATE_STRING_UTF8);
204 if ((DRAG_TYPE.compare(type)) != 0) {
205 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be drag");
206 return nullptr;
207 }
208 if (argc == 1) {
209 jsDragMgr->UnregisterListener(env);
210 return nullptr;
211 }
212 if (UtilNapi::TypeOf(env, argv[1], napi_undefined) || UtilNapi::TypeOf(env, argv[1], napi_null)) {
213 jsDragMgr->UnregisterListener(env);
214 return nullptr;
215 }
216 if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
217 THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
218 return nullptr;
219 }
220 jsDragMgr->UnregisterListener(env, argv[1]);
221 return nullptr;
222 }
223
GetDataSummary(napi_env env,napi_callback_info info)224 napi_value JsDragContext::GetDataSummary(napi_env env, napi_callback_info info)
225 {
226 CALL_INFO_TRACE;
227 JsDragContext *jsDev = JsDragContext::GetInstance(env);
228 CHKPP(jsDev);
229 auto jsDragMgr = jsDev->GetJsDragMgr();
230 CHKPP(jsDragMgr);
231 return jsDragMgr->GetDataSummary(env);
232 }
233
SetDragSwitchState(napi_env env,napi_callback_info info)234 napi_value JsDragContext::SetDragSwitchState(napi_env env, napi_callback_info info)
235 {
236 CALL_INFO_TRACE;
237 size_t argc = ONE_PARAM;
238 napi_value argv[ONE_PARAM] = { nullptr };
239 CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
240
241 JsDragContext *jsDev = JsDragContext::GetInstance(env);
242 CHKPP(jsDev);
243 auto jsDragMgr = jsDev->GetJsDragMgr();
244 CHKPP(jsDragMgr);
245 if (argc < ONE_PARAM) {
246 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
247 return nullptr;
248 }
249 if (!UtilNapi::TypeOf(env, argv[ZERO_PARAM], napi_boolean)) {
250 THROWERR(env, COMMON_PARAMETER_ERROR, "enable", "boolean");
251 return nullptr;
252 }
253 bool enable = false;
254 CHKRP(napi_get_value_bool(env, argv[ZERO_PARAM], &enable), GET_VALUE_BOOL);
255 if (jsDragMgr->SetDragSwitchState(env, enable) == COMMON_NOT_SYSTEM_APP) {
256 THROWERR_CUSTOM(env, COMMON_NOT_SYSTEM_APP, "Not system application.");
257 }
258 return nullptr;
259 }
260
SetAppDragSwitchState(napi_env env,napi_callback_info info)261 napi_value JsDragContext::SetAppDragSwitchState(napi_env env, napi_callback_info info)
262 {
263 CALL_INFO_TRACE;
264 size_t argc = TWO_PARAM;
265 napi_value argv[TWO_PARAM] = { nullptr };
266 CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
267
268 JsDragContext *jsDev = JsDragContext::GetInstance(env);
269 CHKPP(jsDev);
270 auto jsDragMgr = jsDev->GetJsDragMgr();
271 CHKPP(jsDragMgr);
272 if (argc < TWO_PARAM) {
273 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
274 return nullptr;
275 }
276 if (!UtilNapi::TypeOf(env, argv[ZERO_PARAM], napi_boolean)) {
277 THROWERR(env, COMMON_PARAMETER_ERROR, "enable", "boolean");
278 return nullptr;
279 }
280 if (!UtilNapi::TypeOf(env, argv[ONE_PARAM], napi_string)) {
281 THROWERR(env, COMMON_PARAMETER_ERROR, "pkgName", "string");
282 return nullptr;
283 }
284 bool enable = false;
285 CHKRP(napi_get_value_bool(env, argv[ZERO_PARAM], &enable), GET_VALUE_BOOL);
286 char param[MAX_STRING_LEN] = { 0 };
287 size_t length = 0;
288 CHKRP(napi_get_value_string_utf8(env, argv[ONE_PARAM], param, sizeof(param), &length), CREATE_STRING_UTF8);
289 if (length <= 0 || length > MAX_PKG_NAME_LEN) {
290 FI_HILOGE("Invalid pkgName length:%{public}zu", length);
291 THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Invalid pkgName length");
292 return nullptr;
293 }
294 std::string pkgName = param;
295 if (jsDragMgr->SetAppDragSwitchState(env, enable, pkgName) == COMMON_NOT_SYSTEM_APP) {
296 THROWERR_CUSTOM(env, COMMON_NOT_SYSTEM_APP, "Not system application.");
297 }
298 return nullptr;
299 }
300
DeclareDragData(napi_env env,napi_value exports)301 void JsDragContext::DeclareDragData(napi_env env, napi_value exports)
302 {
303 napi_value startMsg = nullptr;
304 CHKRV(napi_create_int32(env, static_cast<int32_t>(DragState::START), &startMsg),
305 CREATE_INT32);
306 napi_value stopMsg = nullptr;
307 CHKRV(napi_create_int32(env, static_cast<int32_t>(DragState::STOP), &stopMsg),
308 CREATE_INT32);
309 napi_value cancelMsg = nullptr;
310 CHKRV(napi_create_int32(env, static_cast<int32_t>(DragState::CANCEL), &cancelMsg),
311 CREATE_INT32);
312
313 napi_property_descriptor msg[] = {
314 DECLARE_NAPI_STATIC_PROPERTY("MSG_DRAG_STATE_START", startMsg),
315 DECLARE_NAPI_STATIC_PROPERTY("MSG_DRAG_STATE_STOP", stopMsg),
316 DECLARE_NAPI_STATIC_PROPERTY("MSG_DRAG_STATE_CANCEL", cancelMsg)
317 };
318
319 napi_value eventMsg = nullptr;
320 CHKRV(napi_define_class(env, "DragState", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
321 sizeof(msg) / sizeof(*msg), msg, &eventMsg), DEFINE_CLASS);
322 CHKRV(napi_set_named_property(env, exports, "DragState", eventMsg), SET_NAMED_PROPERTY);
323 }
324
DeclareDragInterface(napi_env env,napi_value exports)325 void JsDragContext::DeclareDragInterface(napi_env env, napi_value exports)
326 {
327 napi_property_descriptor functions[] = {
328 DECLARE_NAPI_STATIC_FUNCTION("on", On),
329 DECLARE_NAPI_STATIC_FUNCTION("off", Off),
330 DECLARE_NAPI_STATIC_FUNCTION("getDataSummary", GetDataSummary),
331 DECLARE_NAPI_STATIC_FUNCTION("setDragSwitchState", SetDragSwitchState),
332 DECLARE_NAPI_STATIC_FUNCTION("setAppDragSwitchState", SetAppDragSwitchState)
333 };
334 CHKRV(napi_define_properties(env, exports,
335 sizeof(functions) / sizeof(*functions), functions), DEFINE_PROPERTIES);
336 }
337
EnumClassConstructor(napi_env env,napi_callback_info info)338 napi_value JsDragContext::EnumClassConstructor(napi_env env, napi_callback_info info)
339 {
340 size_t argc = 0;
341 napi_value args[1] = { nullptr };
342 napi_value result = nullptr;
343 void *data = nullptr;
344 CHKRP(napi_get_cb_info(env, info, &argc, args, &result, &data), GET_CB_INFO);
345 return result;
346 }
347
Export(napi_env env,napi_value exports)348 napi_value JsDragContext::Export(napi_env env, napi_value exports)
349 {
350 CALL_INFO_TRACE;
351 auto instance = CreateInstance(env);
352 CHKPP(instance);
353 DeclareDragData(env, exports);
354 DeclareDragInterface(env, exports);
355 return exports;
356 }
357 } // namespace DeviceStatus
358 } // namespace Msdp
359 } // namespace OHOS
360