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