• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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