1 /*
2  * Copyright (c) 2022 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 "datashare_js_utils.h"
17 
18 #include "datashare_log.h"
19 #include "datashare_predicates_proxy.h"
20 #include "datashare_valuebucket_convert.h"
21 #include "napi/native_common.h"
22 #include "napi_datashare_values_bucket.h"
23 #include "securec.h"
24 
25 namespace OHOS {
26 namespace DataShare {
Convert2String(napi_env env,napi_value jsStr,const size_t max)27 std::string DataShareJSUtils::Convert2String(napi_env env, napi_value jsStr, const size_t max)
28 {
29     size_t str_buffer_size = max;
30     napi_get_value_string_utf8(env, jsStr, nullptr, 0, &str_buffer_size);
31     char *buf = new (std::nothrow) char[str_buffer_size + 1];
32     if (buf == nullptr) {
33         return "";
34     }
35     size_t len = 0;
36     napi_get_value_string_utf8(env, jsStr, buf, str_buffer_size + 1, &len);
37     buf[len] = 0;
38     std::string value(buf);
39     delete[] buf;
40     return value;
41 }
42 
Convert2StrVector(napi_env env,napi_value value,const size_t strMax)43 std::vector<std::string> DataShareJSUtils::Convert2StrVector(napi_env env, napi_value value, const size_t strMax)
44 {
45     NAPI_ASSERT_BASE(env, strMax > 0, "failed on strMax > 0",  std::vector<std::string>());
46     uint32_t arrLen = 0;
47     napi_get_array_length(env, value, &arrLen);
48     if (arrLen == 0) {
49         return {};
50     }
51     std::vector<std::string> result;
52     for (size_t i = 0; i < arrLen; ++i) {
53         napi_value element;
54         if (napi_get_element(env, value, i, &element) != napi_ok) {
55             return {};
56         }
57         result.push_back(ConvertAny2String(env, element));
58     }
59     return result;
60 }
61 
Convert2U8Vector(napi_env env,napi_value input_array)62 std::vector<uint8_t> DataShareJSUtils::Convert2U8Vector(napi_env env, napi_value input_array)
63 {
64     bool isTypedArray = false;
65     bool isArrayBuffer = false;
66     napi_is_typedarray(env, input_array, &isTypedArray);
67     if (!isTypedArray) {
68         napi_is_arraybuffer(env, input_array, &isArrayBuffer);
69         if (!isArrayBuffer) {
70             LOG_ERROR("unknow type");
71             return {};
72         }
73     }
74     size_t length = 0;
75     void *data = nullptr;
76     if (isTypedArray) {
77         napi_typedarray_type type;
78         napi_value input_buffer = nullptr;
79         size_t byte_offset = 0;
80         napi_get_typedarray_info(env, input_array, &type, &length, &data, &input_buffer, &byte_offset);
81         if (type != napi_uint8_array || data == nullptr) {
82             LOG_ERROR("napi_get_typedarray_info err");
83             return {};
84         }
85     } else {
86         napi_get_arraybuffer_info(env, input_array, &data, &length);
87         if (data == nullptr || length <= 0) {
88             LOG_ERROR("napi_get_arraybuffer_info err");
89             return {};
90         }
91     }
92     return std::vector<uint8_t>((uint8_t *)data, ((uint8_t *)data) + length);
93 }
94 
ConvertU8Vector(napi_env env,napi_value jsValue)95 std::vector<uint8_t> DataShareJSUtils::ConvertU8Vector(napi_env env, napi_value jsValue)
96 {
97     bool isTypedArray = false;
98     if (napi_is_typedarray(env, jsValue, &isTypedArray) != napi_ok || !isTypedArray) {
99         return {};
100     }
101 
102     napi_typedarray_type type;
103     size_t length = 0;
104     napi_value buffer = nullptr;
105     size_t offset = 0;
106     NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, &length, nullptr, &buffer, &offset), {});
107     if (type != napi_uint8_array) {
108         return {};
109     }
110     uint8_t *data = nullptr;
111     size_t total = 0;
112     NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast<void **>(&data), &total), {});
113     length = std::min<size_t>(length, total - offset);
114     std::vector<uint8_t> result(sizeof(uint8_t) + length);
115     int retCode = memcpy_s(result.data(), result.size(), &data[offset], length);
116     if (retCode != 0) {
117         return {};
118     }
119     return result;
120 }
121 
ConvertAny2String(napi_env env,napi_value jsValue)122 std::string DataShareJSUtils::ConvertAny2String(napi_env env, napi_value jsValue)
123 {
124     napi_valuetype valueType = napi_undefined;
125     NAPI_CALL_BASE(env, napi_typeof(env, jsValue, &valueType), "napi_typeof failed");
126     if (valueType == napi_string) {
127         return DataShareJSUtils::Convert2String(env, jsValue, DataShareJSUtils::DEFAULT_BUF_SIZE);
128     } else if (valueType == napi_number) {
129         double valueNumber;
130         napi_get_value_double(env, jsValue, &valueNumber);
131         return std::to_string(valueNumber);
132     } else if (valueType == napi_boolean) {
133         bool valueBool = false;
134         napi_get_value_bool(env, jsValue, &valueBool);
135         return std::to_string(valueBool);
136     } else if (valueType == napi_null) {
137         return "null";
138     } else if (valueType == napi_object) {
139         std::vector<uint8_t> bytes = DataShareJSUtils::Convert2U8Vector(env, jsValue);
140         std::string ret(bytes.begin(), bytes.end());
141         return ret;
142     }
143 
144     return "invalid type";
145 }
146 
Convert2JSValue(napi_env env,const std::monostate & value)147 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::monostate &value)
148 {
149     return nullptr;
150 }
151 
Convert2JSValue(napi_env env,const std::vector<std::string> & value)152 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector<std::string> &value)
153 {
154     napi_value jsValue;
155     napi_status status = napi_create_array_with_length(env, value.size(), &jsValue);
156     if (status != napi_ok) {
157         return nullptr;
158     }
159 
160     for (size_t i = 0; i < value.size(); ++i) {
161         napi_set_element(env, jsValue, i, Convert2JSValue(env, value[i]));
162     }
163     return jsValue;
164 }
165 
Convert2JSValue(napi_env env,const std::string & value)166 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::string &value)
167 {
168     napi_value jsValue;
169     napi_status status = napi_create_string_utf8(env, value.c_str(), value.size(), &jsValue);
170     if (status != napi_ok) {
171         return nullptr;
172     }
173     return jsValue;
174 }
175 
Convert2JSValue(napi_env env,const std::vector<uint8_t> & value,bool isTypedArray)176 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector<uint8_t> &value, bool isTypedArray)
177 {
178     void *native = nullptr;
179     napi_value buffer = nullptr;
180     if (value.empty()) {
181         LOG_DEBUG("vector is empty");
182         return nullptr;
183     }
184     napi_status status = napi_create_arraybuffer(env, value.size(), &native, &buffer);
185     if (status != napi_ok) {
186         return nullptr;
187     }
188     if (memcpy_s(native, value.size(), value.data(), value.size()) != EOK && value.size() > 0) {
189         return nullptr;
190     }
191     if (!isTypedArray) {
192         return buffer;
193     }
194     napi_value jsValue;
195     status = napi_create_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &jsValue);
196     if (status != napi_ok) {
197         return nullptr;
198     }
199     return jsValue;
200 }
201 
Convert2JSValue(napi_env env,int32_t value)202 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, int32_t value)
203 {
204     napi_value jsValue;
205     napi_status status = napi_create_int32(env, value, &jsValue);
206     if (status != napi_ok) {
207         return nullptr;
208     }
209     return jsValue;
210 }
211 
Convert2JSValue(napi_env env,int64_t value)212 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, int64_t value)
213 {
214     napi_value jsValue;
215     napi_status status = napi_create_int64(env, value, &jsValue);
216     if (status != napi_ok) {
217         return nullptr;
218     }
219     return jsValue;
220 }
221 
Convert2JSValue(napi_env env,uint32_t value)222 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, uint32_t value)
223 {
224     napi_value jsValue;
225     napi_status status = napi_create_uint32(env, value, &jsValue);
226     if (status != napi_ok) {
227         return nullptr;
228     }
229     return jsValue;
230 }
231 
Convert2JSValue(napi_env env,double value)232 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, double value)
233 {
234     napi_value jsValue;
235     napi_status status = napi_create_double(env, value, &jsValue);
236     if (status != napi_ok) {
237         return nullptr;
238     }
239     return jsValue;
240 }
241 
Convert2JSValue(napi_env env,bool value)242 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, bool value)
243 {
244     napi_value jsValue;
245     napi_status status = napi_get_boolean(env, value, &jsValue);
246     if (status != napi_ok) {
247         return nullptr;
248     }
249     return jsValue;
250 }
251 
Convert2JSValue(napi_env env,const std::map<std::string,int> & value)252 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::map<std::string, int> &value)
253 {
254     napi_value jsValue;
255     napi_status status = napi_create_array_with_length(env, value.size(), &jsValue);
256     if (status != napi_ok) {
257         return nullptr;
258     }
259 
260     int index = 0;
261     for (const auto& [device, result] : value) {
262         napi_value jsElement;
263         status = napi_create_array_with_length(env, SYNC_RESULT_ELEMNT_NUM, &jsElement);
264         if (status != napi_ok) {
265             return nullptr;
266         }
267         napi_set_element(env, jsElement, 0, Convert2JSValue(env, device));
268         napi_set_element(env, jsElement, 1, Convert2JSValue(env, result));
269         napi_set_element(env, jsValue, index++, jsElement);
270     }
271 
272     return jsValue;
273 }
UnwrapStringFromJS(napi_env env,napi_value param,const std::string & defaultValue)274 std::string DataShareJSUtils::UnwrapStringFromJS(napi_env env, napi_value param, const std::string &defaultValue)
275 {
276     size_t size = 0;
277     if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) {
278         return defaultValue;
279     }
280 
281     std::string value("");
282     if (size == 0) {
283         return defaultValue;
284     }
285 
286     char *buf = new (std::nothrow) char[size + 1];
287     if (buf == nullptr) {
288         return value;
289     }
290     (void)memset_s(buf, size + 1, 0, size + 1);
291 
292     bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok;
293     if (rev) {
294         value = buf;
295     } else {
296         value = defaultValue;
297     }
298 
299     if (buf != nullptr) {
300         delete[] buf;
301         buf = nullptr;
302     }
303     return value;
304 }
305 
Convert2JSValue(napi_env env,const DataShareValuesBucket & valueBucket)306 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareValuesBucket &valueBucket)
307 {
308     napi_value res = NewInstance(env, valueBucket);
309     if (res == nullptr) {
310         LOG_ERROR("failed to make new instance of DataShareValueBucket.");
311     }
312     return res;
313 }
314 
Convert2ValueObject(napi_env env,napi_value value,bool & status)315 DataShareValueObject DataShareJSUtils::Convert2ValueObject(napi_env env, napi_value value, bool &status)
316 {
317     napi_valuetype valueType = napi_undefined;
318     napi_typeof(env, value, &valueType);
319     status = true;
320     if (valueType == napi_string) {
321         std::string valueString = DataShareJSUtils::UnwrapStringFromJS(env, value);
322         return valueString;
323     } else if (valueType == napi_number) {
324         double valueNumber = 0;
325         napi_get_value_double(env, value, &valueNumber);
326         return valueNumber;
327     } else if (valueType == napi_boolean) {
328         bool valueBool = false;
329         napi_get_value_bool(env, value, &valueBool);
330         return valueBool;
331     } else if (valueType == napi_null) {
332         return {};
333     } else if (valueType == napi_object) {
334         std::vector<uint8_t> valueBlob = DataShareJSUtils::Convert2U8Vector(env, value);
335         return valueBlob;
336     } else {
337         LOG_ERROR("valuesBucket error");
338         status = false;
339         return {};
340     }
341 }
342 
Equals(napi_env env,napi_value value,napi_ref copy)343 bool DataShareJSUtils::Equals(napi_env env, napi_value value, napi_ref copy)
344 {
345     if (copy == nullptr) {
346         return (value == nullptr);
347     }
348 
349     napi_value copyValue = nullptr;
350     napi_get_reference_value(env, copy, &copyValue);
351 
352     bool isEqual = false;
353     napi_strict_equals(env, value, copyValue, &isEqual);
354     return isEqual;
355 }
356 
Convert2JSValue(napi_env env,const TemplateId & templateId)357 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const TemplateId &templateId)
358 {
359     napi_value tplId = nullptr;
360     napi_create_object(env, &tplId);
361     napi_value subscriberId = Convert2JSValue(env, std::to_string(templateId.subscriberId_));
362     if (subscriberId == nullptr) {
363         return nullptr;
364     }
365     napi_value bundleName = nullptr;
366     bundleName = Convert2JSValue(env, templateId.bundleName_);
367     if (bundleName == nullptr) {
368         return nullptr;
369     }
370     napi_set_named_property(env, tplId, "subscriberId", subscriberId);
371     napi_set_named_property(env, tplId, "bundleName", bundleName);
372     return tplId;
373 }
374 
Convert2JSValue(napi_env env,const RdbChangeNode & changeNode)375 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const RdbChangeNode &changeNode)
376 {
377     napi_value jsRdbChangeNode = nullptr;
378     napi_create_object(env, &jsRdbChangeNode);
379 
380     napi_value uri = nullptr;
381     uri = Convert2JSValue(env, changeNode.uri_);
382     if (uri == nullptr) {
383         return nullptr;
384     }
385     napi_value templateId = nullptr;
386     templateId = Convert2JSValue(env, changeNode.templateId_);
387     if (templateId == nullptr) {
388         return nullptr;
389     }
390     napi_value data = Convert2JSValue(env, changeNode.data_);
391     if (data == nullptr) {
392         return nullptr;
393     }
394     napi_set_named_property(env, jsRdbChangeNode, "uri", uri);
395     napi_set_named_property(env, jsRdbChangeNode, "templateId", templateId);
396     napi_set_named_property(env, jsRdbChangeNode, "data", data);
397     return jsRdbChangeNode;
398 }
399 
Convert2JSValue(napi_env env,PublishedDataItem & publishedDataItem)400 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, PublishedDataItem &publishedDataItem)
401 {
402     napi_value jsPublishedDataItem = nullptr;
403     napi_create_object(env, &jsPublishedDataItem);
404 
405     napi_value key = Convert2JSValue(env, publishedDataItem.key_);
406     if (key == nullptr) {
407         return nullptr;
408     }
409 
410     napi_value subscriberId = nullptr;
411     subscriberId = Convert2JSValue(env, std::to_string(publishedDataItem.subscriberId_));
412     if (subscriberId == nullptr) {
413         return nullptr;
414     }
415 
416     napi_value data = nullptr;
417     if (publishedDataItem.IsAshmem()) {
418         data = Convert2JSValue(env, std::get<std::vector<uint8_t>>(publishedDataItem.GetData()), false);
419     } else {
420         data = Convert2JSValue(env, std::get<std::string>(publishedDataItem.GetData()));
421     }
422     if (data == nullptr) {
423         return nullptr;
424     }
425 
426     napi_set_named_property(env, jsPublishedDataItem, "key", key);
427     napi_set_named_property(env, jsPublishedDataItem, "subscriberId", subscriberId);
428     napi_set_named_property(env, jsPublishedDataItem, "data", data);
429     return jsPublishedDataItem;
430 }
431 
Convert2JSValue(napi_env env,std::vector<PublishedDataItem> & publishedDataItems)432 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, std::vector<PublishedDataItem> &publishedDataItems)
433 {
434     napi_value jsValue;
435     napi_status status = napi_create_array_with_length(env, publishedDataItems.size(), &jsValue);
436     if (status != napi_ok) {
437         return nullptr;
438     }
439 
440     for (size_t i = 0; i < publishedDataItems.size(); ++i) {
441         napi_set_element(env, jsValue, i, Convert2JSValue(env, publishedDataItems[i]));
442     }
443     return jsValue;
444 }
445 
Convert2JSValue(napi_env env,PublishedDataChangeNode & changeNode)446 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, PublishedDataChangeNode &changeNode)
447 {
448     napi_value jsPublishedDataChangeNode = nullptr;
449     napi_create_object(env, &jsPublishedDataChangeNode);
450 
451     napi_value bundleName = nullptr;
452     bundleName = Convert2JSValue(env, changeNode.ownerBundleName_);
453     if (bundleName == nullptr) {
454         return nullptr;
455     }
456     napi_value data = nullptr;
457     data = Convert2JSValue(env, changeNode.datas_);
458     if (data == nullptr) {
459         return nullptr;
460     }
461     napi_set_named_property(env, jsPublishedDataChangeNode, "bundleName", bundleName);
462     napi_set_named_property(env, jsPublishedDataChangeNode, "data", data);
463     return jsPublishedDataChangeNode;
464 }
465 
Convert2JSValue(napi_env env,const OperationResult & results)466 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const OperationResult &results)
467 {
468     napi_value jsOperationResult = nullptr;
469     napi_create_object(env, &jsOperationResult);
470 
471     napi_value key = nullptr;
472     key = Convert2JSValue(env, results.key_);
473     if (key == nullptr) {
474         return nullptr;
475     }
476 
477     napi_value result = nullptr;
478     result = Convert2JSValue(env, results.errCode_);
479     if (result == nullptr) {
480         return nullptr;
481     }
482     napi_set_named_property(env, jsOperationResult, "key", key);
483     napi_set_named_property(env, jsOperationResult, "result", result);
484     return jsOperationResult;
485 }
486 
Convert2JSValue(napi_env env,const std::vector<OperationResult> & results)487 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector<OperationResult> &results)
488 {
489     napi_value jsValue;
490     napi_status status = napi_create_array_with_length(env, results.size(), &jsValue);
491     if (status != napi_ok) {
492         return nullptr;
493     }
494 
495     for (size_t i = 0; i < results.size(); ++i) {
496         napi_set_element(env, jsValue, i, Convert2JSValue(env, results[i]));
497     }
498     return jsValue;
499 }
500 
UnwrapTemplatePredicates(napi_env env,napi_value jsPredicates,std::vector<PredicateTemplateNode> & predicates)501 bool DataShareJSUtils::UnwrapTemplatePredicates(napi_env env, napi_value jsPredicates,
502     std::vector<PredicateTemplateNode> &predicates)
503 {
504     napi_value keys = nullptr;
505     napi_get_property_names(env, jsPredicates, &keys);
506     uint32_t arrLen = 0;
507     napi_status status = napi_get_array_length(env, keys, &arrLen);
508     if (status != napi_ok) {
509         LOG_ERROR("UnwrapTemplatePredicates error");
510         return false;
511     }
512     LOG_DEBUG("TemplatePredicates length : %{public}u", arrLen);
513     for (size_t i = 0; i < arrLen; ++i) {
514         napi_value key = nullptr;
515         status = napi_get_element(env, keys, i, &key);
516         if (status != napi_ok) {
517             LOG_ERROR("UnwrapTemplatePredicates err");
518             return false;
519         }
520         napi_value value = nullptr;
521         status = napi_get_property(env, jsPredicates, key, &value);
522         if (status != napi_ok) {
523             LOG_ERROR("UnwrapTemplatePredicates err");
524             return false;
525         }
526         std::string keyStr = UnwrapStringFromJS(env, key);
527         std::string valueStr = UnwrapStringFromJS(env, value);
528         PredicateTemplateNode node(keyStr, valueStr);
529         predicates.emplace_back(node);
530     }
531     return true;
532 }
533 
Convert2Template(napi_env env,napi_value value)534 Template DataShareJSUtils::Convert2Template(napi_env env, napi_value value)
535 {
536     napi_valuetype valueType = napi_undefined;
537     napi_typeof(env, value, &valueType);
538     if (valueType != napi_object) {
539         LOG_ERROR("Convert2Template error, value is not object");
540         return {};
541     }
542     napi_value jsPredicates;
543     auto status =  napi_get_named_property(env, value, "predicates", &jsPredicates);
544     if (status != napi_ok) {
545         LOG_ERROR("Convert predicates failed");
546         return {};
547     }
548     std::vector<PredicateTemplateNode> predicates;
549     if (!UnwrapTemplatePredicates(env, jsPredicates, predicates)) {
550         LOG_ERROR("UnwrapTemplateNodeVector failed");
551         return {};
552     }
553 
554     std::string scheduler;
555     if (!UnwrapStringByPropertyName(env, value, "scheduler", scheduler)) {
556         LOG_ERROR("Convert scheduler failed");
557         return {};
558     }
559     Template tpl(predicates, scheduler);
560     return tpl;
561 }
562 
Convert2TemplateId(napi_env env,napi_value value)563 TemplateId DataShareJSUtils::Convert2TemplateId(napi_env env, napi_value value)
564 {
565     napi_valuetype valueType = napi_undefined;
566     napi_typeof(env, value, &valueType);
567     if (valueType != napi_object) {
568         LOG_ERROR("Convert2TemplateId error, value is not object");
569         return {};
570     }
571 
572     TemplateId templateId;
573     std::string strSubId;
574     if (!UnwrapStringByPropertyName(env, value, "subscriberId", strSubId)) {
575         LOG_ERROR("Convert subscriberId failed");
576         return {};
577     }
578     templateId.subscriberId_ = atoll(strSubId.c_str());
579     if (!UnwrapStringByPropertyName(env, value, "bundleNameOfOwner", templateId.bundleName_)) {
580         LOG_ERROR("Convert bundleNameOfOwner failed");
581         return {};
582     }
583     return templateId;
584 }
585 
UnwrapPublishedDataItem(napi_env env,napi_value jsObject,PublishedDataItem & publishedDataItem)586 bool DataShareJSUtils::UnwrapPublishedDataItem(napi_env env, napi_value jsObject, PublishedDataItem &publishedDataItem)
587 {
588     napi_valuetype valueType = napi_undefined;
589     napi_typeof(env, jsObject, &valueType);
590     if (valueType != napi_object) {
591         LOG_ERROR("UnwrapPublishedDataItem error, value is not object");
592         return false;
593     }
594 
595     if (!UnwrapStringByPropertyName(env, jsObject, "key", publishedDataItem.key_)) {
596         LOG_ERROR("Convert key failed");
597         return false;
598     }
599     std::string keyStr = "data";
600     napi_value jsDataKey = Convert2JSValue(env, keyStr);
601     napi_value jsDataValue = nullptr;
602     napi_get_property(env, jsObject, jsDataKey, &jsDataValue);
603     napi_typeof(env, jsDataValue, &valueType);
604     PublishedDataItem::DataType value;
605     if (valueType == napi_object) {
606         value = Convert2U8Vector(env, jsDataValue);
607         publishedDataItem.Set(value);
608     } else if (valueType == napi_string) {
609         value = Convert2String(env, jsDataValue);
610         publishedDataItem.Set(value);
611     } else {
612         LOG_ERROR("Convert dataValue failed, type is %{public}d", valueType);
613         return false;
614     }
615     std::string strSubId;
616     if (!UnwrapStringByPropertyName(env, jsObject, "subscriberId", strSubId)) {
617         LOG_ERROR("Convert subscriberId failed");
618         return false;
619     }
620     publishedDataItem.subscriberId_ = atoll(strSubId.c_str());
621     return true;
622 }
623 
IsArrayForNapiValue(napi_env env,napi_value param,uint32_t & arraySize)624 bool DataShareJSUtils::IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize)
625 {
626     bool isArray = false;
627     arraySize = 0;
628 
629     if (napi_is_array(env, param, &isArray) != napi_ok || isArray == false) {
630         return false;
631     }
632 
633     if (napi_get_array_length(env, param, &arraySize) != napi_ok) {
634         return false;
635     }
636     return true;
637 }
638 
UnwrapPublishedDataItemVector(napi_env env,napi_value value,std::vector<PublishedDataItem> & publishedDataItems)639 bool DataShareJSUtils::UnwrapPublishedDataItemVector(napi_env env, napi_value value,
640     std::vector<PublishedDataItem> &publishedDataItems)
641 {
642     uint32_t arraySize = 0;
643 
644     if (!IsArrayForNapiValue(env, value, arraySize)) {
645         LOG_ERROR("IsArrayForNapiValue is false");
646         return false;
647     }
648 
649     for (uint32_t i = 0; i < arraySize; i++) {
650         napi_value jsValue = nullptr;
651         if (napi_get_element(env, value, i, &jsValue) != napi_ok) {
652             LOG_ERROR("napi_get_element is false");
653             return false;
654         }
655 
656         PublishedDataItem publishedDataItem;
657         if (!UnwrapPublishedDataItem(env, jsValue, publishedDataItem)) {
658             LOG_ERROR("UnwrapPublishedDataItem failed");
659             return false;
660         }
661         publishedDataItems.emplace_back(std::move(publishedDataItem));
662     }
663     return true;
664 }
665 
Convert2PublishedData(napi_env env,napi_value value)666 Data DataShareJSUtils::Convert2PublishedData(napi_env env, napi_value value)
667 {
668     napi_valuetype valueType = napi_undefined;
669     napi_typeof(env, value, &valueType);
670     if (valueType != napi_object) {
671         LOG_ERROR("Convert2PublishedData error, value is not object");
672         return {};
673     }
674     Data data;
675     if (!UnwrapPublishedDataItemVector(env, value,  data.datas_)) {
676         LOG_ERROR("UnwrapPublishedDataItems failed");
677         return {};
678     }
679     return data;
680 }
681 
UnwrapStringByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::string & value)682 bool DataShareJSUtils::UnwrapStringByPropertyName(
683     napi_env env, napi_value jsObject, const char *propertyName, std::string &value)
684 {
685     napi_value jsResult = nullptr;
686     auto status = napi_get_named_property(env, jsObject, propertyName, &jsResult);
687     if ((status != napi_ok) || (jsResult == nullptr)) {
688         LOG_ERROR("Convert bundleNameOfOwner failed");
689         return false;
690     }
691     napi_valuetype valueType = napi_undefined;
692     napi_typeof(env, jsResult, &valueType);
693     if (valueType != napi_string) {
694         LOG_ERROR("Convert2PublishedData error, value is not object");
695         return false;
696     }
697     value = DataShareJSUtils::Convert2String(env, jsResult);
698     return true;
699 }
700 
Convert2JSValue(napi_env env,const std::vector<BatchUpdateResult> & result)701 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector<BatchUpdateResult> &result)
702 {
703     napi_value jsResult = nullptr;
704     napi_status status = napi_create_object(env, &jsResult);
705     if (status != napi_ok) {
706         LOG_ERROR("Create object failed, ret : %{public}d", status);
707         return nullptr;
708     }
709     for (const auto &valueArray : result) {
710         napi_value values;
711         if (napi_create_array(env, &values) != napi_ok) {
712             LOG_ERROR("Create array failed");
713             return nullptr;
714         }
715         uint32_t index = 0;
716         for (const auto &value : valueArray.codes) {
717             napi_value jsValue = Convert2JSValue(env, value);
718             if (napi_set_element(env, values, index++, jsValue) != napi_ok) {
719                 LOG_ERROR("Set to array failed");
720                 return nullptr;
721             }
722         }
723         if (napi_set_named_property(env, jsResult, valueArray.uri.c_str(), values) != napi_ok) {
724             LOG_ERROR("Set to map failed");
725             return nullptr;
726         }
727     }
728     return jsResult;
729 }
730 
Convert2Value(napi_env env,napi_value input,UpdateOperation & operation)731 int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, UpdateOperation& operation)
732 {
733     napi_valuetype valueType = napi_undefined;
734     napi_typeof(env, input, &valueType);
735     if (valueType != napi_object) {
736         LOG_ERROR("value is not object");
737         return napi_invalid_arg;
738     }
739     if (Convert2Value(env, input, "predicates", operation.predicates) != napi_ok) {
740         return napi_invalid_arg;
741     }
742     if (Convert2Value(env, input, "values", operation.valuesBucket) != napi_ok) {
743         return napi_invalid_arg;
744     }
745     return napi_ok;
746 }
747 
Convert2Value(napi_env env,napi_value input,std::string & str)748 int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, std::string &str)
749 {
750     size_t strBufferSize = DEFAULT_BUF_SIZE;
751     napi_get_value_string_utf8(env, input, nullptr, 0, &strBufferSize);
752     char *buf = new (std::nothrow) char[strBufferSize + 1];
753     if (buf == nullptr) {
754         return napi_invalid_arg;
755     }
756     size_t len = 0;
757     napi_get_value_string_utf8(env, input, buf, strBufferSize + 1, &len);
758     buf[len] = 0;
759     str = std::string(buf);
760     delete[] buf;
761     return napi_ok;
762 }
763 
Convert2Value(napi_env env,napi_value input,OHOS::DataShare::DataShareObserver::ChangeType & changeType)764 int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input,
765     OHOS::DataShare::DataShareObserver::ChangeType &changeType)
766 {
767     uint32_t number = 0;
768     napi_status status = napi_get_value_uint32(env, input, &number);
769     changeType = static_cast<OHOS::DataShare::DataShareObserver::ChangeType>(number);
770     return status;
771 }
772 
Convert2Value(napi_env env,napi_value input,DataShareObserver::ChangeInfo & changeInfo)773 int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataShareObserver::ChangeInfo &changeInfo)
774 {
775     napi_valuetype type = napi_undefined;
776     napi_typeof(env, input, &type);
777     if (type != napi_object) {
778         LOG_ERROR("ChangeInfo is not object");
779         return napi_invalid_arg;
780     }
781     std::string uriStr;
782     std::vector<DataShareValuesBucket> valuebuckets = {};
783     if (Convert2Value(env, input, "type", changeInfo.changeType_) != napi_ok) {
784         return napi_invalid_arg;
785     }
786     if (Convert2Value(env, input, "uri", uriStr) != napi_ok) {
787         return napi_invalid_arg;
788     }
789     if (Convert2Value(env, input, "values", valuebuckets) != napi_ok) {
790         return napi_invalid_arg;
791     }
792 
793     Uri uri(uriStr);
794     changeInfo.uris_.push_back(uri);
795     changeInfo.valueBuckets_ = ValueProxy::Convert(std::move(valuebuckets));
796     return napi_ok;
797 }
798 
Convert2JSValue(napi_env env,const DataShareObserver::ChangeInfo & changeInfo)799 napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareObserver::ChangeInfo &changeInfo)
800 {
801     napi_value napiValue = nullptr;
802     napi_create_object(env, &napiValue);
803     napi_value changeType = Convert2JSValue(env, changeInfo.changeType_);
804     if (changeType == nullptr) {
805         return nullptr;
806     }
807     napi_value uri = Convert2JSValue(env, changeInfo.uris_.front().ToString());
808     if (uri == nullptr) {
809         return nullptr;
810     }
811     auto &valBucket = const_cast<DataShareObserver::ChangeInfo &>(changeInfo);
812     std::vector<DataShareValuesBucket> VBuckets = ValueProxy::Convert(std::move(valBucket.valueBuckets_));
813     napi_value valueBuckets = Convert2JSValue(env, VBuckets);
814     if (valueBuckets == nullptr) {
815         return nullptr;
816     }
817     napi_set_named_property(env, napiValue, "type", changeType);
818     napi_set_named_property(env, napiValue, "uri", uri);
819     napi_set_named_property(env, napiValue, "values", valueBuckets);
820     return napiValue;
821 }
822 
UnwrapDataSharePredicates(napi_env env,napi_value value,DataSharePredicates & dataSharePredicates)823 bool DataShareJSUtils::UnwrapDataSharePredicates(napi_env env, napi_value value,
824     DataSharePredicates &dataSharePredicates)
825 {
826     auto predicates = DataSharePredicatesProxy::GetNativePredicates(env, value);
827     if (predicates == nullptr) {
828         LOG_ERROR("GetNativePredicates is nullptr.");
829         return false;
830     }
831     dataSharePredicates = DataSharePredicates(predicates->GetOperationList());
832     return true;
833 }
834 
Convert2Value(napi_env env,napi_value input,DataSharePredicates & predicates)835 int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataSharePredicates &predicates)
836 {
837     if (!UnwrapDataSharePredicates(env, input, predicates)) {
838         LOG_ERROR("get predicates from js failed");
839         return napi_invalid_arg;
840     }
841     return napi_ok;
842 }
843 
Convert2Value(napi_env env,napi_value input,DataShareValuesBucket & valueBucket)844 int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataShareValuesBucket &valueBucket)
845 {
846     if (!GetValueBucketObject(valueBucket, env, input)) {
847         LOG_ERROR("get valueBucketObject from js failed");
848         return napi_invalid_arg;
849     }
850     return napi_ok;
851 }
852 } // namespace DataShare
853 } // namespace OHOS