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 #define LOG_TAG "UnifiedDataNapi"
16 #include "unified_data_napi.h"
17
18 #include "application_defined_record_napi.h"
19 #include "audio_napi.h"
20 #include "file_napi.h"
21 #include "folder_napi.h"
22 #include "html_napi.h"
23 #include "image_napi.h"
24 #include "link_napi.h"
25 #include "plain_text_napi.h"
26 #include "system_defined_appitem_napi.h"
27 #include "system_defined_form_napi.h"
28 #include "system_defined_pixelmap_napi.h"
29 #include "system_defined_record_napi.h"
30 #include "text_napi.h"
31 #include "unified_data.h"
32 #include "unified_record_napi.h"
33 #include "video_napi.h"
34
35 namespace OHOS {
36 namespace UDMF {
Constructor(napi_env env)37 napi_value UnifiedDataNapi::Constructor(napi_env env)
38 {
39 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
40 napi_property_descriptor properties[] = {
41 /* UnifiedData properties */
42 DECLARE_NAPI_FUNCTION("addRecord", AddRecord),
43 DECLARE_NAPI_FUNCTION("getRecords", GetRecords),
44 DECLARE_NAPI_FUNCTION("hasType", HasType),
45 DECLARE_NAPI_FUNCTION("getTypes", GetTypes),
46 DECLARE_NAPI_GETTER_SETTER("properties", GetProperties, SetProperties),
47 };
48 size_t count = sizeof(properties) / sizeof(properties[0]);
49 return NapiDataUtils::DefineClass(env, "UnifiedData", properties, count, UnifiedDataNapi::New);
50 }
51
New(napi_env env,napi_callback_info info)52 napi_value UnifiedDataNapi::New(napi_env env, napi_callback_info info)
53 {
54 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
55 UnifiedRecordNapi *uRecord = nullptr;
56 auto ctxt = std::make_shared<ContextBase>();
57 auto input = [env, info, ctxt, &uRecord](size_t argc, napi_value *argv) {
58 if (argc == 1) {
59 ctxt->status = napi_unwrap(env, *argv, reinterpret_cast<void **>(&uRecord));
60 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok && uRecord != nullptr && uRecord->value_ != nullptr),
61 Status::E_INVALID_PARAMETERS, "Parameter error: parameter record type must be UnifiedRecord");
62 ctxt->status = UnifiedDataUtils::IsValidType(uRecord->value_->GetType()) ? napi_ok : napi_invalid_arg;
63 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_ERROR, "invalid type!");
64 }
65 };
66
67 // Parsing input parameters
68 ctxt->GetCbInfoSync(env, info, input);
69 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
70 auto *uData = new (std::nothrow) UnifiedDataNapi();
71 ASSERT_ERR(ctxt->env, uData != nullptr, Status::E_ERROR, "no memory for unified data!");
72
73 // Create and bind UnifiedDataPropertiesNapi
74 int argc = 0;
75 napi_value argv[0] = {};
76 UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
77 uData->propertyRef_ = NewWithRef(env, argc, argv, reinterpret_cast<void **>(&propertiesNapi),
78 UnifiedDataPropertiesNapi::Constructor(env));
79 if (propertiesNapi == nullptr) {
80 LOG_ERROR(UDMF_KITS_NAPI, "new UnifiedDataPropertiesNapi failed!");
81 if (uData->propertyRef_ != nullptr) {
82 napi_delete_reference(env, uData->propertyRef_);
83 }
84 delete(uData);
85 return nullptr;
86 }
87 uData->value_ = std::make_shared<UnifiedData>(propertiesNapi->value_);
88 if (uRecord) {
89 uData->value_->AddRecord(uRecord->value_);
90 }
91 ASSERT_CALL(env, napi_wrap(env, ctxt->self, uData, Destructor, nullptr, nullptr), uData);
92 return ctxt->self;
93 }
94
Destructor(napi_env env,void * data,void * hint)95 void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint)
96 {
97 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize.");
98 auto *uData = static_cast<UnifiedDataNapi *>(data);
99 ASSERT_VOID(uData != nullptr, "finalize null!");
100 if (uData->propertyRef_ != nullptr) {
101 napi_delete_reference(env, uData->propertyRef_);
102 }
103 delete uData;
104 }
105
NewInstance(napi_env env,std::shared_ptr<UnifiedData> in,napi_value & out)106 napi_status UnifiedDataNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedData> in, napi_value &out)
107 {
108 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
109 ASSERT_CALL_STATUS(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out));
110
111 UnifiedDataNapi* unifiedData = nullptr;
112 napi_status status = napi_unwrap(env, out, reinterpret_cast<void **>(&unifiedData));
113 if (status != napi_ok || unifiedData == nullptr) {
114 LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap unifiedData failed, status=%{public}d", status);
115 return status;
116 }
117 unifiedData->value_ = in;
118
119 napi_value value;
120 status = napi_get_reference_value(env, unifiedData->propertyRef_, &value);
121 if (status != napi_ok) {
122 LOG_ERROR(UDMF_KITS_NAPI, "napi_get_reference_value propertyRef failed, status=%{public}d", status);
123 return status;
124 }
125 UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
126 status = napi_unwrap(env, value, reinterpret_cast<void **>(&propertiesNapi));
127 if (status != napi_ok || propertiesNapi == nullptr) {
128 LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap propertiesNapi failed, status=%{public}d", status);
129 return status;
130 }
131 propertiesNapi->value_ = in->GetProperties();
132 return napi_ok;
133 }
134
GetUnifiedData(napi_env env,napi_callback_info info)135 UnifiedDataNapi *UnifiedDataNapi::GetUnifiedData(napi_env env, napi_callback_info info)
136 {
137 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
138 auto ctxt = std::make_shared<ContextBase>();
139 ctxt->GetCbInfoSync(env, info);
140 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
141 return static_cast<UnifiedDataNapi *>(ctxt->native);
142 }
143
AddRecord(napi_env env,napi_callback_info info)144 napi_value UnifiedDataNapi::AddRecord(napi_env env, napi_callback_info info)
145 {
146 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
147 UnifiedRecordNapi *uRecord = nullptr;
148 auto ctxt = std::make_shared<ContextBase>();
149 auto input = [env, info, ctxt, &uRecord](size_t argc, napi_value *argv) {
150 ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
151 Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
152 ctxt->status = napi_unwrap(env, *argv, reinterpret_cast<void **>(&uRecord));
153 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok && uRecord != nullptr && uRecord->value_ != nullptr),
154 Status::E_INVALID_PARAMETERS, "Parameter error: parameter record type must be UnifiedRecord");
155 ctxt->status = UnifiedDataUtils::IsValidType(uRecord->value_->GetType()) ? napi_ok : napi_invalid_arg;
156 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_ERROR, "invalid type!");
157 };
158 ctxt->GetCbInfoSync(env, info, input);
159 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
160 auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native);
161 ASSERT_ERR(
162 ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
163 uData->value_->AddRecord(uRecord->value_);
164 return nullptr;
165 }
166
GetRecords(napi_env env,napi_callback_info info)167 napi_value UnifiedDataNapi::GetRecords(napi_env env, napi_callback_info info)
168 {
169 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
170 auto ctxt = std::make_shared<ContextBase>();
171 auto uData = GetUnifiedData(env, info);
172 ASSERT_ERR(
173 ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
174 std::vector<std::shared_ptr<UnifiedRecord>> records = uData->value_->GetRecords();
175 napi_status status = napi_create_array_with_length(env, records.size(), &ctxt->output);
176 ASSERT_ERR(ctxt->env, status == napi_ok, Status::E_ERROR, "init array failed!");
177 int index = 0;
178 for (const std::shared_ptr<UnifiedRecord> &recordPtr : records) {
179 napi_value recordNapi = nullptr;
180 GetRecord(env, recordPtr, recordNapi);
181 ctxt->status = napi_set_element(env, ctxt->output, index++, recordNapi);
182 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, "set element failed!");
183 }
184 return ctxt->output;
185 }
186
GetRecord(napi_env env,std::shared_ptr<UnifiedRecord> in,napi_value & out)187 void UnifiedDataNapi::GetRecord(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out)
188 {
189 switch (in->GetType()) {
190 case TEXT: {
191 TextNapi::NewInstance(env, in, out);
192 break;
193 }
194 case PLAIN_TEXT: {
195 PlainTextNapi::NewInstance(env, in, out);
196 break;
197 }
198 case HTML: {
199 HtmlNapi::NewInstance(env, in, out);
200 break;
201 }
202 case HYPERLINK: {
203 LinkNapi::NewInstance(env, in, out);
204 break;
205 }
206 case FILE: {
207 FileNapi::NewInstance(env, in, out);
208 break;
209 }
210 case IMAGE: {
211 ImageNapi::NewInstance(env, in, out);
212 break;
213 }
214 case VIDEO: {
215 VideoNapi::NewInstance(env, in, out);
216 break;
217 }
218 case AUDIO: {
219 AudioNapi::NewInstance(env, in, out);
220 break;
221 }
222 case FOLDER: {
223 FolderNapi::NewInstance(env, in, out);
224 break;
225 }
226 case SYSTEM_DEFINED_RECORD: {
227 SystemDefinedRecordNapi::NewInstance(env, in, out);
228 break;
229 }
230 case SYSTEM_DEFINED_APP_ITEM: {
231 SystemDefinedAppItemNapi::NewInstance(env, in, out);
232 break;
233 }
234 case SYSTEM_DEFINED_FORM: {
235 SystemDefinedFormNapi::NewInstance(env, in, out);
236 break;
237 }
238 case SYSTEM_DEFINED_PIXEL_MAP: {
239 auto value = in->GetValue();
240 if (std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) {
241 UnifiedRecordNapi::NewInstance(env, in, out);
242 } else {
243 SystemDefinedPixelMapNapi::NewInstance(env, in, out);
244 }
245 break;
246 }
247 case APPLICATION_DEFINED_RECORD: {
248 ApplicationDefinedRecordNapi::NewInstance(env, in, out);
249 break;
250 }
251 default:
252 UnifiedRecordNapi::NewInstance(env, in, out);
253 LOG_INFO(UDMF_KITS_NAPI, "GetRecord default");
254 break;
255 }
256 }
257
HasType(napi_env env,napi_callback_info info)258 napi_value UnifiedDataNapi::HasType(napi_env env, napi_callback_info info)
259 {
260 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
261 std::string type;
262 auto ctxt = std::make_shared<ContextBase>();
263 auto input = [env, info, ctxt, &type](size_t argc, napi_value *argv) {
264 ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
265 Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
266 ctxt->status = NapiDataUtils::GetValue(env, argv[0], type);
267 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok,
268 Status::E_INVALID_PARAMETERS, "Parameter error: parameter type type must be string");
269 };
270 ctxt->GetCbInfoSync(env, info, input);
271 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
272 auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native);
273 ASSERT_ERR(
274 ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
275 bool ret = uData->value_->HasHigherFileType(type);
276 napi_value result = nullptr;
277 napi_get_boolean(env, ret, &result);
278 return result;
279 }
280
GetTypes(napi_env env,napi_callback_info info)281 napi_value UnifiedDataNapi::GetTypes(napi_env env, napi_callback_info info)
282 {
283 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
284 auto uData = GetUnifiedData(env, info);
285 ASSERT_ERR(env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
286
287 std::vector<std::string> Types = uData->value_->GetTypesLabels();
288 napi_value nTypes = nullptr;
289 napi_status status = napi_create_array(env, &nTypes);
290 ASSERT_ERR(env, status == napi_ok, Status::E_ERROR, "create array fail!");
291
292 size_t index = 0;
293 napi_value value = nullptr;
294 for (auto type : Types) {
295 napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &value);
296 napi_set_element(env, nTypes, index, value);
297 index++;
298 }
299 return nTypes;
300 }
301
GetProperties(napi_env env,napi_callback_info info)302 napi_value UnifiedDataNapi::GetProperties(napi_env env, napi_callback_info info)
303 {
304 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
305 napi_value value;
306 auto uData = GetUnifiedData(env, info);
307 ASSERT_ERR(env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
308 ASSERT_ERR(env, (uData != nullptr && uData->propertyRef_ != nullptr), Status::E_ERROR, "invalid properties!");
309 NAPI_CALL(env, napi_get_reference_value(env, uData->propertyRef_, &value));
310 return value;
311 }
312
GetPropertiesNapi(napi_env env)313 UnifiedDataPropertiesNapi* UnifiedDataNapi::GetPropertiesNapi(napi_env env)
314 {
315 napi_value value;
316 NAPI_CALL(env, napi_get_reference_value(env, propertyRef_, &value));
317 UnifiedDataPropertiesNapi* out = nullptr;
318 napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&out));
319 ASSERT_ERR(env, status == napi_ok && out != nullptr, Status::E_ERROR, "napi_unwrap failed");
320 return out;
321 }
322
SetProperties(napi_env env,napi_callback_info info)323 napi_value UnifiedDataNapi::SetProperties(napi_env env, napi_callback_info info)
324 {
325 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
326 auto ctxt = std::make_shared<ContextBase>();
327 auto input = [env, ctxt](size_t argc, napi_value* argv) {
328 ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
329 Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
330 UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
331 ctxt->status = Unwrap(env, argv[0], reinterpret_cast<void**>(&propertiesNapi),
332 UnifiedDataPropertiesNapi::Constructor(env));
333 ASSERT_BUSINESS_ERR(ctxt, propertiesNapi != nullptr,
334 Status::E_INVALID_PARAMETERS, "Parameter error: parameter properties type must be UnifiedDataProperties");
335
336 auto uData = static_cast<UnifiedDataNapi*>(ctxt->native);
337 if (uData->propertyRef_ != nullptr) {
338 napi_delete_reference(env, uData->propertyRef_);
339 }
340 ctxt->status = napi_create_reference(env, argv[0], 1, &uData->propertyRef_);
341 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok,
342 Status::E_ERROR, "napi_create_reference to properties failed!");
343 uData->value_->SetProperties(propertiesNapi->value_);
344 };
345 ctxt->GetCbInfoSync(env, info, input);
346 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
347 return ctxt->self;
348 }
349
NewWithRef(napi_env env,size_t argc,napi_value * argv,void ** out,napi_value constructor)350 napi_ref UnifiedDataNapi::NewWithRef(napi_env env, size_t argc, napi_value *argv, void **out, napi_value constructor)
351 {
352 napi_value object = nullptr;
353 napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
354 ASSERT_ERR(env, status == napi_ok && object != nullptr, Status::E_ERROR, "napi_new_instance failed");
355
356 status = napi_unwrap(env, object, out);
357 ASSERT_ERR(env, status == napi_ok && out != nullptr, Status::E_ERROR, "napi_unwrap failed");
358
359 napi_ref ref = nullptr;
360 status = napi_create_reference(env, object, 1, &ref);
361 ASSERT_ERR(env, status == napi_ok && ref != nullptr, Status::E_ERROR, "napi_create_reference failed");
362 return ref;
363 }
364
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)365 napi_status UnifiedDataNapi::Unwrap(napi_env env, napi_value in, void **out, napi_value constructor)
366 {
367 if (constructor != nullptr) {
368 bool isInstance = false;
369 napi_instanceof(env, in, constructor, &isInstance);
370 if (!isInstance) {
371 LOG_ERROR(UDMF_KITS_NAPI, "not a instance of *");
372 return napi_invalid_arg;
373 }
374 }
375 return napi_unwrap(env, in, out);
376 }
377 } // namespace UDMF
378 } // namespace OHOS