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 uData->value_ = std::make_shared<UnifiedData>(propertiesNapi->value_);
80 if (uRecord) {
81 uData->value_->AddRecord(uRecord->value_);
82 }
83 ASSERT_CALL(env, napi_wrap(env, ctxt->self, uData, Destructor, nullptr, nullptr), uData);
84 return ctxt->self;
85 }
86
Destructor(napi_env env,void * data,void * hint)87 void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint)
88 {
89 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize.");
90 auto *uData = static_cast<UnifiedDataNapi *>(data);
91 ASSERT_VOID(uData != nullptr, "finalize null!");
92 if (uData->propertyRef_ != nullptr) {
93 napi_delete_reference(env, uData->propertyRef_);
94 }
95 delete uData;
96 }
97
NewInstance(napi_env env,std::shared_ptr<UnifiedData> in,napi_value & out)98 napi_status UnifiedDataNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedData> in, napi_value &out)
99 {
100 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
101 ASSERT_CALL_STATUS(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out));
102 auto *unifiedData = new (std::nothrow) UnifiedDataNapi();
103 ASSERT_ERR_STATUS(env, unifiedData != nullptr, Status::E_ERROR, "no memory for unified data!");
104 unifiedData->value_ = in;
105 ASSERT_CALL_DELETE_STATUS(env, napi_wrap(env, out, unifiedData, Destructor, nullptr, nullptr), unifiedData);
106 return napi_ok;
107 }
108
GetUnifiedData(napi_env env,napi_callback_info info)109 UnifiedDataNapi *UnifiedDataNapi::GetUnifiedData(napi_env env, napi_callback_info info)
110 {
111 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
112 auto ctxt = std::make_shared<ContextBase>();
113 ctxt->GetCbInfoSync(env, info);
114 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
115 return static_cast<UnifiedDataNapi *>(ctxt->native);
116 }
117
AddRecord(napi_env env,napi_callback_info info)118 napi_value UnifiedDataNapi::AddRecord(napi_env env, napi_callback_info info)
119 {
120 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
121 UnifiedRecordNapi *uRecord = nullptr;
122 auto ctxt = std::make_shared<ContextBase>();
123 auto input = [env, info, ctxt, &uRecord](size_t argc, napi_value *argv) {
124 ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
125 Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
126 ctxt->status = napi_unwrap(env, *argv, reinterpret_cast<void **>(&uRecord));
127 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok && uRecord != nullptr && uRecord->value_ != nullptr),
128 Status::E_INVALID_PARAMETERS, "Parameter error: parameter record type must be UnifiedRecord");
129 ctxt->status = UnifiedDataUtils::IsValidType(uRecord->value_->GetType()) ? napi_ok : napi_invalid_arg;
130 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_ERROR, "invalid type!");
131 };
132 ctxt->GetCbInfoSync(env, info, input);
133 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
134 auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native);
135 ASSERT_ERR(
136 ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
137 uData->value_->AddRecord(uRecord->value_);
138 return nullptr;
139 }
140
GetRecords(napi_env env,napi_callback_info info)141 napi_value UnifiedDataNapi::GetRecords(napi_env env, napi_callback_info info)
142 {
143 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
144 auto ctxt = std::make_shared<ContextBase>();
145 auto uData = GetUnifiedData(env, info);
146 ASSERT_ERR(
147 ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
148 std::vector<std::shared_ptr<UnifiedRecord>> records = uData->value_->GetRecords();
149 napi_status status = napi_create_array_with_length(env, records.size(), &ctxt->output);
150 ASSERT_ERR(ctxt->env, status == napi_ok, Status::E_ERROR, "init array failed!");
151 int index = 0;
152 for (const std::shared_ptr<UnifiedRecord> &recordPtr : records) {
153 napi_value recordNapi = nullptr;
154 GetRecord(env, recordPtr, recordNapi);
155 ctxt->status = napi_set_element(env, ctxt->output, index++, recordNapi);
156 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, "set element failed!");
157 }
158 return ctxt->output;
159 }
160
GetRecord(napi_env env,std::shared_ptr<UnifiedRecord> in,napi_value & out)161 void UnifiedDataNapi::GetRecord(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out)
162 {
163 switch (in->GetType()) {
164 case TEXT: {
165 TextNapi::NewInstance(env, in, out);
166 break;
167 }
168 case PLAIN_TEXT: {
169 PlainTextNapi::NewInstance(env, in, out);
170 break;
171 }
172 case HTML: {
173 HtmlNapi::NewInstance(env, in, out);
174 break;
175 }
176 case HYPERLINK: {
177 LinkNapi::NewInstance(env, in, out);
178 break;
179 }
180 case FILE: {
181 FileNapi::NewInstance(env, in, out);
182 break;
183 }
184 case IMAGE: {
185 ImageNapi::NewInstance(env, in, out);
186 break;
187 }
188 case VIDEO: {
189 VideoNapi::NewInstance(env, in, out);
190 break;
191 }
192 case AUDIO: {
193 AudioNapi::NewInstance(env, in, out);
194 break;
195 }
196 case FOLDER: {
197 FolderNapi::NewInstance(env, in, out);
198 break;
199 }
200 case SYSTEM_DEFINED_RECORD: {
201 SystemDefinedRecordNapi::NewInstance(env, in, out);
202 break;
203 }
204 case SYSTEM_DEFINED_APP_ITEM: {
205 SystemDefinedAppItemNapi::NewInstance(env, in, out);
206 break;
207 }
208 case SYSTEM_DEFINED_FORM: {
209 SystemDefinedFormNapi::NewInstance(env, in, out);
210 break;
211 }
212 case SYSTEM_DEFINED_PIXEL_MAP: {
213 auto value = in->GetValue();
214 if (std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) {
215 UnifiedRecordNapi::NewInstance(env, in, out);
216 } else {
217 SystemDefinedPixelMapNapi::NewInstance(env, in, out);
218 }
219 break;
220 }
221 case APPLICATION_DEFINED_RECORD: {
222 ApplicationDefinedRecordNapi::NewInstance(env, in, out);
223 break;
224 }
225 default:
226 UnifiedRecordNapi::NewInstance(env, in, out);
227 LOG_INFO(UDMF_KITS_NAPI, "GetRecord default");
228 break;
229 }
230 }
231
HasType(napi_env env,napi_callback_info info)232 napi_value UnifiedDataNapi::HasType(napi_env env, napi_callback_info info)
233 {
234 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
235 std::string type;
236 auto ctxt = std::make_shared<ContextBase>();
237 auto input = [env, info, ctxt, &type](size_t argc, napi_value *argv) {
238 ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
239 Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
240 ctxt->status = NapiDataUtils::GetValue(env, argv[0], type);
241 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok,
242 Status::E_INVALID_PARAMETERS, "Parameter error: parameter type type must be string");
243 };
244 ctxt->GetCbInfoSync(env, info, input);
245 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
246 auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native);
247 ASSERT_ERR(
248 ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
249 bool ret = uData->value_->HasType(type);
250 napi_value result = nullptr;
251 napi_get_boolean(env, ret, &result);
252 return result;
253 }
254
GetTypes(napi_env env,napi_callback_info info)255 napi_value UnifiedDataNapi::GetTypes(napi_env env, napi_callback_info info)
256 {
257 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
258 auto uData = GetUnifiedData(env, info);
259 ASSERT_ERR(env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
260
261 std::vector<std::string> Types = uData->value_->GetTypesLabels();
262 napi_value nTypes = nullptr;
263 napi_status status = napi_create_array(env, &nTypes);
264 ASSERT_ERR(env, status == napi_ok, Status::E_ERROR, "create array fail!");
265
266 size_t index = 0;
267 napi_value value = nullptr;
268 for (auto type : Types) {
269 napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &value);
270 napi_set_element(env, nTypes, index, value);
271 index++;
272 }
273 return nTypes;
274 }
275
GetProperties(napi_env env,napi_callback_info info)276 napi_value UnifiedDataNapi::GetProperties(napi_env env, napi_callback_info info)
277 {
278 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
279 napi_value value;
280 auto uData = GetUnifiedData(env, info);
281 ASSERT_ERR(env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
282 NAPI_CALL(env, napi_get_reference_value(env, uData->propertyRef_, &value));
283 return value;
284 }
285
GetPropertiesNapi(napi_env env)286 UnifiedDataPropertiesNapi* UnifiedDataNapi::GetPropertiesNapi(napi_env env)
287 {
288 napi_value value;
289 NAPI_CALL(env, napi_get_reference_value(env, propertyRef_, &value));
290 UnifiedDataPropertiesNapi* out = nullptr;
291 napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&out));
292 ASSERT_ERR(env, status == napi_ok && out != nullptr, Status::E_ERROR, "napi_unwrap failed");
293 return out;
294 }
295
SetProperties(napi_env env,napi_callback_info info)296 napi_value UnifiedDataNapi::SetProperties(napi_env env, napi_callback_info info)
297 {
298 LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
299 auto ctxt = std::make_shared<ContextBase>();
300 auto input = [env, ctxt](size_t argc, napi_value* argv) {
301 ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
302 Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
303 UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
304 ctxt->status = Unwrap(env, argv[0], reinterpret_cast<void**>(&propertiesNapi),
305 UnifiedDataPropertiesNapi::Constructor(env));
306 ASSERT_BUSINESS_ERR(ctxt, propertiesNapi != nullptr,
307 Status::E_INVALID_PARAMETERS, "Parameter error: parameter properties type must be UnifiedDataProperties");
308
309 auto uData = static_cast<UnifiedDataNapi*>(ctxt->native);
310 if (uData->propertyRef_ != nullptr) {
311 napi_delete_reference(env, uData->propertyRef_);
312 }
313 ctxt->status = napi_create_reference(env, argv[0], 1, &uData->propertyRef_);
314 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok,
315 Status::E_ERROR, "napi_create_reference to properties failed!");
316 uData->value_->SetProperties(propertiesNapi->value_);
317 };
318 ctxt->GetCbInfoSync(env, info, input);
319 ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
320 return ctxt->self;
321 }
322
NewWithRef(napi_env env,size_t argc,napi_value * argv,void ** out,napi_value constructor)323 napi_ref UnifiedDataNapi::NewWithRef(napi_env env, size_t argc, napi_value *argv, void **out, napi_value constructor)
324 {
325 napi_value object = nullptr;
326 napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
327 ASSERT_ERR(env, status == napi_ok && object != nullptr, Status::E_ERROR, "napi_new_instance failed");
328
329 status = napi_unwrap(env, object, out);
330 ASSERT_ERR(env, status == napi_ok && out != nullptr, Status::E_ERROR, "napi_unwrap failed");
331
332 napi_ref ref = nullptr;
333 status = napi_create_reference(env, object, 1, &ref);
334 ASSERT_ERR(env, status == napi_ok && ref != nullptr, Status::E_ERROR, "napi_create_reference failed");
335 return ref;
336 }
337
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)338 napi_status UnifiedDataNapi::Unwrap(napi_env env, napi_value in, void **out, napi_value constructor)
339 {
340 if (constructor != nullptr) {
341 bool isInstance = false;
342 napi_instanceof(env, in, constructor, &isInstance);
343 if (!isInstance) {
344 LOG_ERROR(UDMF_KITS_NAPI, "not a instance of *");
345 return napi_invalid_arg;
346 }
347 }
348 return napi_unwrap(env, in, out);
349 }
350 } // namespace UDMF
351 } // namespace OHOS