• 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 #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     auto status = napi_coerce_to_native_binding_object(
92         env, ctxt->self, DetachUnifiedData, AttachUnifiedData, uData, nullptr);
93     if (status != napi_ok) {
94         LOG_ERROR(UDMF_KITS_NAPI, "napi_coerce_to_native_binding_object failed!");
95     }
96     ASSERT_CALL(env, napi_wrap(env, ctxt->self, uData, Destructor, nullptr, nullptr), uData);
97     return ctxt->self;
98 }
99 
AttachUnifiedData(napi_env env,void * value,void *)100 napi_value UnifiedDataNapi::AttachUnifiedData(napi_env env, void *value, void *)
101 {
102     if (value == nullptr) {
103         LOG_ERROR(UDMF_KITS_NAPI, "Invalid value.");
104         return nullptr;
105     }
106     auto *data = static_cast<UnifiedDataNapi *>(value);
107     napi_value jsData = nullptr;
108     auto status = napi_create_object(env, &jsData);
109     if (status != napi_ok) {
110         LOG_ERROR(UDMF_KITS_NAPI, "napi_create_object failed!");
111         delete data;
112         return nullptr;
113     }
114     napi_property_descriptor properties[] = {
115         DECLARE_NAPI_FUNCTION("addRecord", AddRecord),
116         DECLARE_NAPI_FUNCTION("getRecords", GetRecords),
117         DECLARE_NAPI_FUNCTION("hasType", HasType),
118         DECLARE_NAPI_FUNCTION("getTypes", GetTypes),
119         DECLARE_NAPI_GETTER_SETTER("properties", GetProperties, SetProperties),
120     };
121     status = napi_define_properties(env, jsData, sizeof(properties) / sizeof(properties[0]), properties);
122     if (status != napi_ok) {
123         LOG_ERROR(UDMF_KITS_NAPI, "napi_define_properties failed!");
124         delete data;
125         return nullptr;
126     }
127     status = napi_coerce_to_native_binding_object(
128         env, jsData, DetachUnifiedData, AttachUnifiedData, value, nullptr);
129     if (status != napi_ok) {
130         LOG_ERROR(UDMF_KITS_NAPI, "napi_coerce_to_native_binding_object failed!");
131         delete data;
132         return nullptr;
133     }
134     status = napi_wrap(env, jsData, value, Destructor, nullptr, nullptr);
135     if (status != napi_ok) {
136         LOG_ERROR(UDMF_KITS_NAPI, "napi_wrap failed!");
137         delete data;
138         return nullptr;
139     }
140     return jsData;
141 }
142 
DetachUnifiedData(napi_env env,void * value,void *)143 void* UnifiedDataNapi::DetachUnifiedData(napi_env env, void *value, void *)
144 {
145     if (value == nullptr) {
146         LOG_ERROR(UDMF_KITS_NAPI, "Invalid value.");
147         return nullptr;
148     }
149     auto *origin = static_cast<UnifiedDataNapi *>(value);
150     auto result = new (std::nothrow) UnifiedDataNapi();
151     if (result == nullptr) {
152         LOG_ERROR(UDMF_KITS_NAPI, "Memory allocation failed.");
153         return nullptr;
154     }
155     result->value_ = origin->value_;
156 
157     int argc = 0;
158     napi_value argv[0] = {};
159     UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
160     result->propertyRef_ = NewWithRef(env, argc, argv, reinterpret_cast<void **>(&propertiesNapi),
161         UnifiedDataPropertiesNapi::Constructor(env));
162     if (propertiesNapi == nullptr) {
163         LOG_ERROR(UDMF_KITS_NAPI, "new UnifiedDataPropertiesNapi failed!");
164         if (result->propertyRef_ != nullptr) {
165             napi_delete_reference(env, result->propertyRef_);
166         }
167         delete result;
168         return nullptr;
169     }
170     propertiesNapi->value_ = origin->value_->GetProperties();
171     return result;
172 }
173 
Destructor(napi_env env,void * data,void * hint)174 void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint)
175 {
176     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize.");
177     auto *uData = static_cast<UnifiedDataNapi *>(data);
178     ASSERT_VOID(uData != nullptr, "finalize null!");
179     if (uData->propertyRef_ != nullptr) {
180         napi_delete_reference(env, uData->propertyRef_);
181     }
182     delete uData;
183 }
184 
NewInstance(napi_env env,std::shared_ptr<UnifiedData> in,napi_value & out)185 napi_status UnifiedDataNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedData> in, napi_value &out)
186 {
187     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
188     ASSERT_CALL_STATUS(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out));
189 
190     UnifiedDataNapi* unifiedData = nullptr;
191     napi_status status = napi_unwrap(env, out, reinterpret_cast<void **>(&unifiedData));
192     if (status != napi_ok || unifiedData == nullptr) {
193         LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap unifiedData failed, status=%{public}d", status);
194         return status;
195     }
196     unifiedData->value_ = in;
197 
198     napi_value value;
199     status = napi_get_reference_value(env, unifiedData->propertyRef_, &value);
200     if (status != napi_ok) {
201         LOG_ERROR(UDMF_KITS_NAPI, "napi_get_reference_value propertyRef failed, status=%{public}d", status);
202         return status;
203     }
204     UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
205     status = napi_unwrap(env, value, reinterpret_cast<void **>(&propertiesNapi));
206     if (status != napi_ok || propertiesNapi == nullptr) {
207         LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap propertiesNapi failed, status=%{public}d", status);
208         return status;
209     }
210     propertiesNapi->value_ = in->GetProperties();
211     return napi_ok;
212 }
213 
GetUnifiedData(napi_env env,napi_callback_info info)214 UnifiedDataNapi *UnifiedDataNapi::GetUnifiedData(napi_env env, napi_callback_info info)
215 {
216     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
217     auto ctxt = std::make_shared<ContextBase>();
218     ctxt->GetCbInfoSync(env, info);
219     ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
220     return static_cast<UnifiedDataNapi *>(ctxt->native);
221 }
222 
AddRecord(napi_env env,napi_callback_info info)223 napi_value UnifiedDataNapi::AddRecord(napi_env env, napi_callback_info info)
224 {
225     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
226     UnifiedRecordNapi *uRecord = nullptr;
227     auto ctxt = std::make_shared<ContextBase>();
228     auto input = [env, info, ctxt, &uRecord](size_t argc, napi_value *argv) {
229         ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
230             Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
231         ctxt->status = napi_unwrap(env, *argv, reinterpret_cast<void **>(&uRecord));
232         ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok && uRecord != nullptr && uRecord->value_ != nullptr),
233             Status::E_INVALID_PARAMETERS, "Parameter error: parameter record type must be UnifiedRecord");
234         ctxt->status = UnifiedDataUtils::IsValidType(uRecord->value_->GetType()) ? napi_ok : napi_invalid_arg;
235         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::E_ERROR, "invalid type!");
236     };
237     ctxt->GetCbInfoSync(env, info, input);
238     ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
239     auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native);
240     ASSERT_ERR(
241         ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
242     uData->value_->AddRecord(uRecord->value_);
243     return nullptr;
244 }
245 
GetRecords(napi_env env,napi_callback_info info)246 napi_value UnifiedDataNapi::GetRecords(napi_env env, napi_callback_info info)
247 {
248     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
249     auto ctxt = std::make_shared<ContextBase>();
250     auto uData = GetUnifiedData(env, info);
251     ASSERT_ERR(
252         ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
253     std::vector<std::shared_ptr<UnifiedRecord>> records = uData->value_->GetRecords();
254     napi_status status = napi_create_array_with_length(env, records.size(), &ctxt->output);
255     ASSERT_ERR(ctxt->env, status == napi_ok, Status::E_ERROR, "init array failed!");
256     int index = 0;
257     for (const std::shared_ptr<UnifiedRecord> &recordPtr : records) {
258         napi_value recordNapi = nullptr;
259         GetRecord(env, recordPtr, recordNapi);
260         ctxt->status = napi_set_element(env, ctxt->output, index++, recordNapi);
261         ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, "set element failed!");
262     }
263     return ctxt->output;
264 }
265 
GetRecord(napi_env env,std::shared_ptr<UnifiedRecord> in,napi_value & out)266 void UnifiedDataNapi::GetRecord(napi_env env, std::shared_ptr<UnifiedRecord> in, napi_value &out)
267 {
268     switch (in->GetType()) {
269         case TEXT: {
270             TextNapi::NewInstance(env, in, out);
271             break;
272         }
273         case PLAIN_TEXT: {
274             PlainTextNapi::NewInstance(env, in, out);
275             break;
276         }
277         case HTML: {
278             HtmlNapi::NewInstance(env, in, out);
279             break;
280         }
281         case HYPERLINK: {
282             LinkNapi::NewInstance(env, in, out);
283             break;
284         }
285         case FILE: {
286             FileNapi::NewInstance(env, in, out);
287             break;
288         }
289         case IMAGE: {
290             ImageNapi::NewInstance(env, in, out);
291             break;
292         }
293         case VIDEO: {
294             VideoNapi::NewInstance(env, in, out);
295             break;
296         }
297         case AUDIO: {
298             AudioNapi::NewInstance(env, in, out);
299             break;
300         }
301         case FOLDER: {
302             FolderNapi::NewInstance(env, in, out);
303             break;
304         }
305         case SYSTEM_DEFINED_RECORD: {
306             SystemDefinedRecordNapi::NewInstance(env, in, out);
307             break;
308         }
309         case SYSTEM_DEFINED_APP_ITEM: {
310             SystemDefinedAppItemNapi::NewInstance(env, in, out);
311             break;
312         }
313         case SYSTEM_DEFINED_FORM: {
314             SystemDefinedFormNapi::NewInstance(env, in, out);
315             break;
316         }
317         case SYSTEM_DEFINED_PIXEL_MAP: {
318             auto value = in->GetValue();
319             if (std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) {
320                 UnifiedRecordNapi::NewInstance(env, in, out);
321             } else {
322                 SystemDefinedPixelMapNapi::NewInstance(env, in, out);
323             }
324             break;
325         }
326         case APPLICATION_DEFINED_RECORD: {
327             ApplicationDefinedRecordNapi::NewInstance(env, in, out);
328             break;
329         }
330         default:
331             UnifiedRecordNapi::NewInstance(env, in, out);
332             LOG_INFO(UDMF_KITS_NAPI, "GetRecord default");
333             break;
334     }
335 }
336 
HasType(napi_env env,napi_callback_info info)337 napi_value UnifiedDataNapi::HasType(napi_env env, napi_callback_info info)
338 {
339     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
340     std::string type;
341     auto ctxt = std::make_shared<ContextBase>();
342     auto input = [env, info, ctxt, &type](size_t argc, napi_value *argv) {
343         ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
344             Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
345         ctxt->status = NapiDataUtils::GetValue(env, argv[0], type);
346         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok,
347             Status::E_INVALID_PARAMETERS, "Parameter error: parameter type type must be string");
348     };
349     ctxt->GetCbInfoSync(env, info, input);
350     ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
351     auto *uData = static_cast<UnifiedDataNapi *>(ctxt->native);
352     ASSERT_ERR(
353         ctxt->env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
354     bool ret = uData->value_->HasHigherFileType(type);
355     napi_value result = nullptr;
356     napi_get_boolean(env, ret, &result);
357     return result;
358 }
359 
GetTypes(napi_env env,napi_callback_info info)360 napi_value UnifiedDataNapi::GetTypes(napi_env env, napi_callback_info info)
361 {
362     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
363     auto uData = GetUnifiedData(env, info);
364     ASSERT_ERR(env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
365 
366     std::vector<std::string> Types = uData->value_->GetTypesLabels();
367     napi_value nTypes = nullptr;
368     napi_status status = napi_create_array(env, &nTypes);
369     ASSERT_ERR(env, status == napi_ok, Status::E_ERROR, "create array fail!");
370 
371     size_t index = 0;
372     napi_value value = nullptr;
373     for (auto type : Types) {
374         napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &value);
375         napi_set_element(env, nTypes, index, value);
376         index++;
377     }
378     return nTypes;
379 }
380 
GetProperties(napi_env env,napi_callback_info info)381 napi_value UnifiedDataNapi::GetProperties(napi_env env, napi_callback_info info)
382 {
383     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
384     napi_value value;
385     auto uData = GetUnifiedData(env, info);
386     ASSERT_ERR(env, (uData != nullptr && uData->value_ != nullptr), Status::E_ERROR, "invalid object!");
387     ASSERT_ERR(env, (uData != nullptr && uData->propertyRef_ != nullptr), Status::E_ERROR, "invalid properties!");
388     NAPI_CALL(env, napi_get_reference_value(env, uData->propertyRef_, &value));
389     return value;
390 }
391 
GetPropertiesNapi(napi_env env)392 UnifiedDataPropertiesNapi* UnifiedDataNapi::GetPropertiesNapi(napi_env env)
393 {
394     napi_value value;
395     NAPI_CALL(env, napi_get_reference_value(env, propertyRef_, &value));
396     UnifiedDataPropertiesNapi* out = nullptr;
397     napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&out));
398     ASSERT_ERR(env, status == napi_ok && out != nullptr, Status::E_ERROR, "napi_unwrap failed");
399     return out;
400 }
401 
SetProperties(napi_env env,napi_callback_info info)402 napi_value UnifiedDataNapi::SetProperties(napi_env env, napi_callback_info info)
403 {
404     LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi");
405     auto ctxt = std::make_shared<ContextBase>();
406     auto input = [env, ctxt](size_t argc, napi_value* argv) {
407         ASSERT_BUSINESS_ERR(ctxt, argc >= 1,
408             Status::E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified");
409         UnifiedDataPropertiesNapi* propertiesNapi = nullptr;
410         ctxt->status = Unwrap(env, argv[0], reinterpret_cast<void**>(&propertiesNapi),
411             UnifiedDataPropertiesNapi::Constructor(env));
412         ASSERT_BUSINESS_ERR(ctxt, propertiesNapi != nullptr,
413             Status::E_INVALID_PARAMETERS, "Parameter error: parameter properties type must be UnifiedDataProperties");
414 
415         auto uData = static_cast<UnifiedDataNapi*>(ctxt->native);
416         if (uData->propertyRef_ != nullptr) {
417             napi_delete_reference(env, uData->propertyRef_);
418         }
419         ctxt->status = napi_create_reference(env, argv[0], 1, &uData->propertyRef_);
420         ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok,
421             Status::E_ERROR, "napi_create_reference to properties failed!");
422         uData->value_->SetProperties(propertiesNapi->value_);
423     };
424     ctxt->GetCbInfoSync(env, info, input);
425     ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, ctxt->error);
426     return ctxt->self;
427 }
428 
NewWithRef(napi_env env,size_t argc,napi_value * argv,void ** out,napi_value constructor)429 napi_ref UnifiedDataNapi::NewWithRef(napi_env env, size_t argc, napi_value *argv, void **out, napi_value constructor)
430 {
431     napi_value object = nullptr;
432     napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
433     ASSERT_ERR(env, status == napi_ok && object != nullptr, Status::E_ERROR, "napi_new_instance failed");
434 
435     status = napi_unwrap(env, object, out);
436     ASSERT_ERR(env, status == napi_ok && out != nullptr, Status::E_ERROR, "napi_unwrap failed");
437 
438     napi_ref ref = nullptr;
439     status = napi_create_reference(env, object, 1, &ref);
440     ASSERT_ERR(env, status == napi_ok && ref != nullptr, Status::E_ERROR, "napi_create_reference failed");
441     return ref;
442 }
443 
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)444 napi_status UnifiedDataNapi::Unwrap(napi_env env, napi_value in, void **out, napi_value constructor)
445 {
446     if (constructor != nullptr) {
447         bool isInstance = false;
448         napi_instanceof(env, in, constructor, &isInstance);
449         if (!isInstance) {
450             LOG_ERROR(UDMF_KITS_NAPI, "not a instance of *");
451             return napi_invalid_arg;
452         }
453     }
454     return napi_unwrap(env, in, out);
455 }
456 } // namespace UDMF
457 } // namespace OHOS